diff --git a/.gitignore b/.gitignore index ff9a120d59b75f4cbd071c65386b8d3b2e0aa4c3..ee2ae170cef66d49bd229bcd3cf590116044b43f 100644 --- a/.gitignore +++ b/.gitignore @@ -29,7 +29,4 @@ atlassian* /pub/media/customer/* /pub/media/downloadable/* /var/* -dev/api-tests/config.php -dev/api-tests/integration/tmp/* -dev/api-tests/integration/framework/local-mysql.xml diff --git a/CHANGELOG.markdown b/CHANGELOG.markdown index 3e8af1f31ff6d32884f74c82d80f942462973a19..571d65fc847878f40390ee20a6d82e366fb3e0b3 100644 --- a/CHANGELOG.markdown +++ b/CHANGELOG.markdown @@ -1,3 +1,44 @@ +2.0.0.0-dev35 +============= +* Enhancements of System Configuration: + * Introduced new items that can be configured in the similar to Magento 1.x way, using xml files: nested groups in System Configuration form, group dependencies, intersected dependencies + * Enhanced handling of field dependencies, required fields functionality + * Changed Configuration structure to be represented as an object model + * Improved performance of configuration rendering +* Implemented new API in `Mage_Webapi` module + * Removed `Mage_Api` and `Mage_Api2` modules as obsolete API implementation + * Added support of REST and SOAP 1.2 [WS-I 2.0](http://ws-i.org/Profiles/BasicProfile-2.0-2010-11-09.html) APIs + * Introduced versioning per API resource. The application will support old version(s) of API after upgrading to not make old API requests fail + * Unified implementation for all API types + * Significantly simplified coverage of new API resources + * Added two-legged `OAuth` 1.0 for REST authentication + * Added WS-Security for SOAP authentication + * Added automatic generation of REST routes and SOAP WSDL on the basis of API class interface and annotations + * Introduced generation of API reference from annotated WSDL (for SOAP API) +* Introduced service layer. Business logic should be implemented once on service layer and could be utilized from different types of controller (e.g., general or API) + * Business logic is implemented on service layer to be utilized from different types of controller (e.g., general or API) + * Implemented abstract service layer class - `Mage_Core_Service_ServiceAbstract` + * Implemented concrete service layers for customers, orders and quotes. Appropriate duplicate logic has been eliminated from controllers and API +* Improved validation approach: + * Added support of describing validation rules in a module's configuration file - `validation.xml` in the module's `etc` directory + * Added `Mage_Core_Model_Validator_Factory` + * Added new validators to Magento Validator library + * Added `Magento_Translate_Adapter` as a translator for the validators + * New approach is utilized in `Mage_Customer`, `Mage_Eav` and `Mage_Webapi` modules +* Added profiling of DB and cache requests +* Minor Improvements: + * Added an ability to choose the image for logo and upload it from backend web-interface + * Added notification in backend in case of product SKU change +* Bug fixes: + * Fixed bug in `Mage_Adminhtml_Sales_Order_CreditmemoController` that changed item’s stock status after each comment + * Removed `Debug` section in `System -> Configuration -> Advanced -> Developer` for default configuration scope + * Fixed bug in `Mage_Tax_Model_Resource_Calculation` that prevented placing order with two tax rules having the same rate + * Removed `Url Options` section in `System -> Configuration -> General -> Web` for website and store configuration scope + * Changed backend template for UPS shipping provider to fix translation issue +* Fixed security issue - set `CURLOPT_SSL_VERIFYPEER` to `true` by default in cUrl calls +* Added `Zend/Escaper`, `Zend/I18`, `Zend/Validator` ZF2 libraries +* Updated `Zend/Server` and `Zend/Soap` libraries to ZF2 versions + 2.0.0.0-dev34 ============= * Test Framework: diff --git a/LICENSE.txt b/LICENSE.txt index 1c0ad61e66c15faeb1255120f35ae7ebfd24230b..63f5337c5f9cdcc88741ceb5632734d4de55dd7f 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,48 +1,48 @@ - -Open Software License ("OSL") v. 3.0 - -This Open Software License (the "License") applies to any original work of authorship (the "Original Work") whose owner (the "Licensor") has placed the following licensing notice adjacent to the copyright notice for the Original Work: - -Licensed under the Open Software License version 3.0 - - 1. Grant of Copyright License. Licensor grants You a worldwide, royalty-free, non-exclusive, sublicensable license, for the duration of the copyright, to do the following: - - 1. to reproduce the Original Work in copies, either alone or as part of a collective work; - - 2. to translate, adapt, alter, transform, modify, or arrange the Original Work, thereby creating derivative works ("Derivative Works") based upon the Original Work; - - 3. to distribute or communicate copies of the Original Work and Derivative Works to the public, with the proviso that copies of Original Work or Derivative Works that You distribute or communicate shall be licensed under this Open Software License; - - 4. to perform the Original Work publicly; and - - 5. to display the Original Work publicly. - - 2. Grant of Patent License. Licensor grants You a worldwide, royalty-free, non-exclusive, sublicensable license, under patent claims owned or controlled by the Licensor that are embodied in the Original Work as furnished by the Licensor, for the duration of the patents, to make, use, sell, offer for sale, have made, and import the Original Work and Derivative Works. - - 3. Grant of Source Code License. The term "Source Code" means the preferred form of the Original Work for making modifications to it and all available documentation describing how to modify the Original Work. Licensor agrees to provide a machine-readable copy of the Source Code of the Original Work along with each copy of the Original Work that Licensor distributes. Licensor reserves the right to satisfy this obligation by placing a machine-readable copy of the Source Code in an information repository reasonably calculated to permit inexpensive and convenient access by You for as long as Licensor continues to distribute the Original Work. - - 4. Exclusions From License Grant. Neither the names of Licensor, nor the names of any contributors to the Original Work, nor any of their trademarks or service marks, may be used to endorse or promote products derived from this Original Work without express prior permission of the Licensor. Except as expressly stated herein, nothing in this License grants any license to Licensor's trademarks, copyrights, patents, trade secrets or any other intellectual property. No patent license is granted to make, use, sell, offer for sale, have made, or import embodiments of any patent claims other than the licensed claims defined in Section 2. No license is granted to the trademarks of Licensor even if such marks are included in the Original Work. Nothing in this License shall be interpreted to prohibit Licensor from licensing under terms different from this License any Original Work that Licensor otherwise would have a right to license. - - 5. External Deployment. The term "External Deployment" means the use, distribution, or communication of the Original Work or Derivative Works in any way such that the Original Work or Derivative Works may be used by anyone other than You, whether those works are distributed or communicated to those persons or made available as an application intended for use over a network. As an express condition for the grants of license hereunder, You must treat any External Deployment by You of the Original Work or a Derivative Work as a distribution under section 1(c). - - 6. Attribution Rights. You must retain, in the Source Code of any Derivative Works that You create, all copyright, patent, or trademark notices from the Source Code of the Original Work, as well as any notices of licensing and any descriptive text identified therein as an "Attribution Notice." You must cause the Source Code for any Derivative Works that You create to carry a prominent Attribution Notice reasonably calculated to inform recipients that You have modified the Original Work. - - 7. Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that the copyright in and to the Original Work and the patent rights granted herein by Licensor are owned by the Licensor or are sublicensed to You under the terms of this License with the permission of the contributor(s) of those copyrights and patent rights. Except as expressly stated in the immediately preceding sentence, the Original Work is provided under this License on an "AS IS" BASIS and WITHOUT WARRANTY, either express or implied, including, without limitation, the warranties of non-infringement, merchantability or fitness for a particular purpose. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK IS WITH YOU. This DISCLAIMER OF WARRANTY constitutes an essential part of this License. No license to the Original Work is granted by this License except under this disclaimer. - - 8. Limitation of Liability. Under no circumstances and under no legal theory, whether in tort (including negligence), contract, or otherwise, shall the Licensor be liable to anyone for any indirect, special, incidental, or consequential damages of any character arising as a result of this License or the use of the Original Work including, without limitation, damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses. This limitation of liability shall not apply to the extent applicable law prohibits such limitation. - - 9. Acceptance and Termination. If, at any time, You expressly assented to this License, that assent indicates your clear and irrevocable acceptance of this License and all of its terms and conditions. If You distribute or communicate copies of the Original Work or a Derivative Work, You must make a reasonable effort under the circumstances to obtain the express assent of recipients to the terms of this License. This License conditions your rights to undertake the activities listed in Section 1, including your right to create Derivative Works based upon the Original Work, and doing so without honoring these terms and conditions is prohibited by copyright law and international treaty. Nothing in this License is intended to affect copyright exceptions and limitations (including 'fair use' or 'fair dealing'). This License shall terminate immediately and You may no longer exercise any of the rights granted to You by this License upon your failure to honor the conditions in Section 1(c). - - 10. Termination for Patent Action. This License shall terminate automatically and You may no longer exercise any of the rights granted to You by this License as of the date You commence an action, including a cross-claim or counterclaim, against Licensor or any licensee alleging that the Original Work infringes a patent. This termination provision shall not apply for an action alleging patent infringement by combinations of the Original Work with other software or hardware. - - 11. Jurisdiction, Venue and Governing Law. Any action or suit relating to this License may be brought only in the courts of a jurisdiction wherein the Licensor resides or in which Licensor conducts its primary business, and under the laws of that jurisdiction excluding its conflict-of-law provisions. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any use of the Original Work outside the scope of this License or after its termination shall be subject to the requirements and penalties of copyright or patent law in the appropriate jurisdiction. This section shall survive the termination of this License. - - 12. Attorneys' Fees. In any action to enforce the terms of this License or seeking damages relating thereto, the prevailing party shall be entitled to recover its costs and expenses, including, without limitation, reasonable attorneys' fees and costs incurred in connection with such action, including any appeal of such action. This section shall survive the termination of this License. - - 13. Miscellaneous. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. - - 14. Definition of "You" in This License. "You" throughout this License, whether in upper or lower case, means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License. For legal entities, "You" includes any entity that controls, is controlled by, or is under common control with you. For purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. - - 15. Right to Use. You may use the Original Work in all ways not otherwise restricted or conditioned by this License or by law, and Licensor promises not to interfere with or be responsible for such uses by You. - + +Open Software License ("OSL") v. 3.0 + +This Open Software License (the "License") applies to any original work of authorship (the "Original Work") whose owner (the "Licensor") has placed the following licensing notice adjacent to the copyright notice for the Original Work: + +Licensed under the Open Software License version 3.0 + + 1. Grant of Copyright License. Licensor grants You a worldwide, royalty-free, non-exclusive, sublicensable license, for the duration of the copyright, to do the following: + + 1. to reproduce the Original Work in copies, either alone or as part of a collective work; + + 2. to translate, adapt, alter, transform, modify, or arrange the Original Work, thereby creating derivative works ("Derivative Works") based upon the Original Work; + + 3. to distribute or communicate copies of the Original Work and Derivative Works to the public, with the proviso that copies of Original Work or Derivative Works that You distribute or communicate shall be licensed under this Open Software License; + + 4. to perform the Original Work publicly; and + + 5. to display the Original Work publicly. + + 2. Grant of Patent License. Licensor grants You a worldwide, royalty-free, non-exclusive, sublicensable license, under patent claims owned or controlled by the Licensor that are embodied in the Original Work as furnished by the Licensor, for the duration of the patents, to make, use, sell, offer for sale, have made, and import the Original Work and Derivative Works. + + 3. Grant of Source Code License. The term "Source Code" means the preferred form of the Original Work for making modifications to it and all available documentation describing how to modify the Original Work. Licensor agrees to provide a machine-readable copy of the Source Code of the Original Work along with each copy of the Original Work that Licensor distributes. Licensor reserves the right to satisfy this obligation by placing a machine-readable copy of the Source Code in an information repository reasonably calculated to permit inexpensive and convenient access by You for as long as Licensor continues to distribute the Original Work. + + 4. Exclusions From License Grant. Neither the names of Licensor, nor the names of any contributors to the Original Work, nor any of their trademarks or service marks, may be used to endorse or promote products derived from this Original Work without express prior permission of the Licensor. Except as expressly stated herein, nothing in this License grants any license to Licensor's trademarks, copyrights, patents, trade secrets or any other intellectual property. No patent license is granted to make, use, sell, offer for sale, have made, or import embodiments of any patent claims other than the licensed claims defined in Section 2. No license is granted to the trademarks of Licensor even if such marks are included in the Original Work. Nothing in this License shall be interpreted to prohibit Licensor from licensing under terms different from this License any Original Work that Licensor otherwise would have a right to license. + + 5. External Deployment. The term "External Deployment" means the use, distribution, or communication of the Original Work or Derivative Works in any way such that the Original Work or Derivative Works may be used by anyone other than You, whether those works are distributed or communicated to those persons or made available as an application intended for use over a network. As an express condition for the grants of license hereunder, You must treat any External Deployment by You of the Original Work or a Derivative Work as a distribution under section 1(c). + + 6. Attribution Rights. You must retain, in the Source Code of any Derivative Works that You create, all copyright, patent, or trademark notices from the Source Code of the Original Work, as well as any notices of licensing and any descriptive text identified therein as an "Attribution Notice." You must cause the Source Code for any Derivative Works that You create to carry a prominent Attribution Notice reasonably calculated to inform recipients that You have modified the Original Work. + + 7. Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that the copyright in and to the Original Work and the patent rights granted herein by Licensor are owned by the Licensor or are sublicensed to You under the terms of this License with the permission of the contributor(s) of those copyrights and patent rights. Except as expressly stated in the immediately preceding sentence, the Original Work is provided under this License on an "AS IS" BASIS and WITHOUT WARRANTY, either express or implied, including, without limitation, the warranties of non-infringement, merchantability or fitness for a particular purpose. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK IS WITH YOU. This DISCLAIMER OF WARRANTY constitutes an essential part of this License. No license to the Original Work is granted by this License except under this disclaimer. + + 8. Limitation of Liability. Under no circumstances and under no legal theory, whether in tort (including negligence), contract, or otherwise, shall the Licensor be liable to anyone for any indirect, special, incidental, or consequential damages of any character arising as a result of this License or the use of the Original Work including, without limitation, damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses. This limitation of liability shall not apply to the extent applicable law prohibits such limitation. + + 9. Acceptance and Termination. If, at any time, You expressly assented to this License, that assent indicates your clear and irrevocable acceptance of this License and all of its terms and conditions. If You distribute or communicate copies of the Original Work or a Derivative Work, You must make a reasonable effort under the circumstances to obtain the express assent of recipients to the terms of this License. This License conditions your rights to undertake the activities listed in Section 1, including your right to create Derivative Works based upon the Original Work, and doing so without honoring these terms and conditions is prohibited by copyright law and international treaty. Nothing in this License is intended to affect copyright exceptions and limitations (including 'fair use' or 'fair dealing'). This License shall terminate immediately and You may no longer exercise any of the rights granted to You by this License upon your failure to honor the conditions in Section 1(c). + + 10. Termination for Patent Action. This License shall terminate automatically and You may no longer exercise any of the rights granted to You by this License as of the date You commence an action, including a cross-claim or counterclaim, against Licensor or any licensee alleging that the Original Work infringes a patent. This termination provision shall not apply for an action alleging patent infringement by combinations of the Original Work with other software or hardware. + + 11. Jurisdiction, Venue and Governing Law. Any action or suit relating to this License may be brought only in the courts of a jurisdiction wherein the Licensor resides or in which Licensor conducts its primary business, and under the laws of that jurisdiction excluding its conflict-of-law provisions. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any use of the Original Work outside the scope of this License or after its termination shall be subject to the requirements and penalties of copyright or patent law in the appropriate jurisdiction. This section shall survive the termination of this License. + + 12. Attorneys' Fees. In any action to enforce the terms of this License or seeking damages relating thereto, the prevailing party shall be entitled to recover its costs and expenses, including, without limitation, reasonable attorneys' fees and costs incurred in connection with such action, including any appeal of such action. This section shall survive the termination of this License. + + 13. Miscellaneous. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. + + 14. Definition of "You" in This License. "You" throughout this License, whether in upper or lower case, means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License. For legal entities, "You" includes any entity that controls, is controlled by, or is under common control with you. For purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + 15. Right to Use. You may use the Original Work in all ways not otherwise restricted or conditioned by this License or by law, and Licensor promises not to interfere with or be responsible for such uses by You. + 16. Modification of This License. This License is Copyright © 2005 Lawrence Rosen. Permission is granted to copy, distribute, or communicate this License without modification. Nothing in this License permits You to modify this License as applied to the Original Work or to Derivative Works. However, You may modify the text of this License and copy, distribute or communicate your modified version (the "Modified License") and apply it to other original works of authorship subject to the following conditions: (i) You may not indicate in any way that your Modified License is the "Open Software License" or "OSL" and you may not use those names in the name of your Modified License; (ii) You must replace the notice specified in the first paragraph above with the notice "Licensed under <insert your license name here>" or with a notice of your own that is not confusingly similar to the notice in this License; and (iii) You may not claim that your original works are open source software unless your Modified License has been approved by Open Source Initiative (OSI) and You comply with its license review and certification process. \ No newline at end of file diff --git a/LICENSE_AFL.txt b/LICENSE_AFL.txt index f3144bd43d1fb967a53d0ad601cf026cfc1dbee0..87943b95d43a5bb8736093275afe3cb8e1d93d26 100644 --- a/LICENSE_AFL.txt +++ b/LICENSE_AFL.txt @@ -1,48 +1,48 @@ - -Academic Free License ("AFL") v. 3.0 - -This Academic Free License (the "License") applies to any original work of authorship (the "Original Work") whose owner (the "Licensor") has placed the following licensing notice adjacent to the copyright notice for the Original Work: - -Licensed under the Academic Free License version 3.0 - - 1. Grant of Copyright License. Licensor grants You a worldwide, royalty-free, non-exclusive, sublicensable license, for the duration of the copyright, to do the following: - - 1. to reproduce the Original Work in copies, either alone or as part of a collective work; - - 2. to translate, adapt, alter, transform, modify, or arrange the Original Work, thereby creating derivative works ("Derivative Works") based upon the Original Work; - - 3. to distribute or communicate copies of the Original Work and Derivative Works to the public, under any license of your choice that does not contradict the terms and conditions, including Licensor's reserved rights and remedies, in this Academic Free License; - - 4. to perform the Original Work publicly; and - - 5. to display the Original Work publicly. - - 2. Grant of Patent License. Licensor grants You a worldwide, royalty-free, non-exclusive, sublicensable license, under patent claims owned or controlled by the Licensor that are embodied in the Original Work as furnished by the Licensor, for the duration of the patents, to make, use, sell, offer for sale, have made, and import the Original Work and Derivative Works. - - 3. Grant of Source Code License. The term "Source Code" means the preferred form of the Original Work for making modifications to it and all available documentation describing how to modify the Original Work. Licensor agrees to provide a machine-readable copy of the Source Code of the Original Work along with each copy of the Original Work that Licensor distributes. Licensor reserves the right to satisfy this obligation by placing a machine-readable copy of the Source Code in an information repository reasonably calculated to permit inexpensive and convenient access by You for as long as Licensor continues to distribute the Original Work. - - 4. Exclusions From License Grant. Neither the names of Licensor, nor the names of any contributors to the Original Work, nor any of their trademarks or service marks, may be used to endorse or promote products derived from this Original Work without express prior permission of the Licensor. Except as expressly stated herein, nothing in this License grants any license to Licensor's trademarks, copyrights, patents, trade secrets or any other intellectual property. No patent license is granted to make, use, sell, offer for sale, have made, or import embodiments of any patent claims other than the licensed claims defined in Section 2. No license is granted to the trademarks of Licensor even if such marks are included in the Original Work. Nothing in this License shall be interpreted to prohibit Licensor from licensing under terms different from this License any Original Work that Licensor otherwise would have a right to license. - - 5. External Deployment. The term "External Deployment" means the use, distribution, or communication of the Original Work or Derivative Works in any way such that the Original Work or Derivative Works may be used by anyone other than You, whether those works are distributed or communicated to those persons or made available as an application intended for use over a network. As an express condition for the grants of license hereunder, You must treat any External Deployment by You of the Original Work or a Derivative Work as a distribution under section 1(c). - - 6. Attribution Rights. You must retain, in the Source Code of any Derivative Works that You create, all copyright, patent, or trademark notices from the Source Code of the Original Work, as well as any notices of licensing and any descriptive text identified therein as an "Attribution Notice." You must cause the Source Code for any Derivative Works that You create to carry a prominent Attribution Notice reasonably calculated to inform recipients that You have modified the Original Work. - - 7. Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that the copyright in and to the Original Work and the patent rights granted herein by Licensor are owned by the Licensor or are sublicensed to You under the terms of this License with the permission of the contributor(s) of those copyrights and patent rights. Except as expressly stated in the immediately preceding sentence, the Original Work is provided under this License on an "AS IS" BASIS and WITHOUT WARRANTY, either express or implied, including, without limitation, the warranties of non-infringement, merchantability or fitness for a particular purpose. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK IS WITH YOU. This DISCLAIMER OF WARRANTY constitutes an essential part of this License. No license to the Original Work is granted by this License except under this disclaimer. - - 8. Limitation of Liability. Under no circumstances and under no legal theory, whether in tort (including negligence), contract, or otherwise, shall the Licensor be liable to anyone for any indirect, special, incidental, or consequential damages of any character arising as a result of this License or the use of the Original Work including, without limitation, damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses. This limitation of liability shall not apply to the extent applicable law prohibits such limitation. - - 9. Acceptance and Termination. If, at any time, You expressly assented to this License, that assent indicates your clear and irrevocable acceptance of this License and all of its terms and conditions. If You distribute or communicate copies of the Original Work or a Derivative Work, You must make a reasonable effort under the circumstances to obtain the express assent of recipients to the terms of this License. This License conditions your rights to undertake the activities listed in Section 1, including your right to create Derivative Works based upon the Original Work, and doing so without honoring these terms and conditions is prohibited by copyright law and international treaty. Nothing in this License is intended to affect copyright exceptions and limitations (including "fair use" or "fair dealing"). This License shall terminate immediately and You may no longer exercise any of the rights granted to You by this License upon your failure to honor the conditions in Section 1(c). - - 10. Termination for Patent Action. This License shall terminate automatically and You may no longer exercise any of the rights granted to You by this License as of the date You commence an action, including a cross-claim or counterclaim, against Licensor or any licensee alleging that the Original Work infringes a patent. This termination provision shall not apply for an action alleging patent infringement by combinations of the Original Work with other software or hardware. - - 11. Jurisdiction, Venue and Governing Law. Any action or suit relating to this License may be brought only in the courts of a jurisdiction wherein the Licensor resides or in which Licensor conducts its primary business, and under the laws of that jurisdiction excluding its conflict-of-law provisions. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any use of the Original Work outside the scope of this License or after its termination shall be subject to the requirements and penalties of copyright or patent law in the appropriate jurisdiction. This section shall survive the termination of this License. - - 12. Attorneys' Fees. In any action to enforce the terms of this License or seeking damages relating thereto, the prevailing party shall be entitled to recover its costs and expenses, including, without limitation, reasonable attorneys' fees and costs incurred in connection with such action, including any appeal of such action. This section shall survive the termination of this License. - - 13. Miscellaneous. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. - - 14. Definition of "You" in This License. "You" throughout this License, whether in upper or lower case, means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License. For legal entities, "You" includes any entity that controls, is controlled by, or is under common control with you. For purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. - - 15. Right to Use. You may use the Original Work in all ways not otherwise restricted or conditioned by this License or by law, and Licensor promises not to interfere with or be responsible for such uses by You. - + +Academic Free License ("AFL") v. 3.0 + +This Academic Free License (the "License") applies to any original work of authorship (the "Original Work") whose owner (the "Licensor") has placed the following licensing notice adjacent to the copyright notice for the Original Work: + +Licensed under the Academic Free License version 3.0 + + 1. Grant of Copyright License. Licensor grants You a worldwide, royalty-free, non-exclusive, sublicensable license, for the duration of the copyright, to do the following: + + 1. to reproduce the Original Work in copies, either alone or as part of a collective work; + + 2. to translate, adapt, alter, transform, modify, or arrange the Original Work, thereby creating derivative works ("Derivative Works") based upon the Original Work; + + 3. to distribute or communicate copies of the Original Work and Derivative Works to the public, under any license of your choice that does not contradict the terms and conditions, including Licensor's reserved rights and remedies, in this Academic Free License; + + 4. to perform the Original Work publicly; and + + 5. to display the Original Work publicly. + + 2. Grant of Patent License. Licensor grants You a worldwide, royalty-free, non-exclusive, sublicensable license, under patent claims owned or controlled by the Licensor that are embodied in the Original Work as furnished by the Licensor, for the duration of the patents, to make, use, sell, offer for sale, have made, and import the Original Work and Derivative Works. + + 3. Grant of Source Code License. The term "Source Code" means the preferred form of the Original Work for making modifications to it and all available documentation describing how to modify the Original Work. Licensor agrees to provide a machine-readable copy of the Source Code of the Original Work along with each copy of the Original Work that Licensor distributes. Licensor reserves the right to satisfy this obligation by placing a machine-readable copy of the Source Code in an information repository reasonably calculated to permit inexpensive and convenient access by You for as long as Licensor continues to distribute the Original Work. + + 4. Exclusions From License Grant. Neither the names of Licensor, nor the names of any contributors to the Original Work, nor any of their trademarks or service marks, may be used to endorse or promote products derived from this Original Work without express prior permission of the Licensor. Except as expressly stated herein, nothing in this License grants any license to Licensor's trademarks, copyrights, patents, trade secrets or any other intellectual property. No patent license is granted to make, use, sell, offer for sale, have made, or import embodiments of any patent claims other than the licensed claims defined in Section 2. No license is granted to the trademarks of Licensor even if such marks are included in the Original Work. Nothing in this License shall be interpreted to prohibit Licensor from licensing under terms different from this License any Original Work that Licensor otherwise would have a right to license. + + 5. External Deployment. The term "External Deployment" means the use, distribution, or communication of the Original Work or Derivative Works in any way such that the Original Work or Derivative Works may be used by anyone other than You, whether those works are distributed or communicated to those persons or made available as an application intended for use over a network. As an express condition for the grants of license hereunder, You must treat any External Deployment by You of the Original Work or a Derivative Work as a distribution under section 1(c). + + 6. Attribution Rights. You must retain, in the Source Code of any Derivative Works that You create, all copyright, patent, or trademark notices from the Source Code of the Original Work, as well as any notices of licensing and any descriptive text identified therein as an "Attribution Notice." You must cause the Source Code for any Derivative Works that You create to carry a prominent Attribution Notice reasonably calculated to inform recipients that You have modified the Original Work. + + 7. Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that the copyright in and to the Original Work and the patent rights granted herein by Licensor are owned by the Licensor or are sublicensed to You under the terms of this License with the permission of the contributor(s) of those copyrights and patent rights. Except as expressly stated in the immediately preceding sentence, the Original Work is provided under this License on an "AS IS" BASIS and WITHOUT WARRANTY, either express or implied, including, without limitation, the warranties of non-infringement, merchantability or fitness for a particular purpose. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK IS WITH YOU. This DISCLAIMER OF WARRANTY constitutes an essential part of this License. No license to the Original Work is granted by this License except under this disclaimer. + + 8. Limitation of Liability. Under no circumstances and under no legal theory, whether in tort (including negligence), contract, or otherwise, shall the Licensor be liable to anyone for any indirect, special, incidental, or consequential damages of any character arising as a result of this License or the use of the Original Work including, without limitation, damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses. This limitation of liability shall not apply to the extent applicable law prohibits such limitation. + + 9. Acceptance and Termination. If, at any time, You expressly assented to this License, that assent indicates your clear and irrevocable acceptance of this License and all of its terms and conditions. If You distribute or communicate copies of the Original Work or a Derivative Work, You must make a reasonable effort under the circumstances to obtain the express assent of recipients to the terms of this License. This License conditions your rights to undertake the activities listed in Section 1, including your right to create Derivative Works based upon the Original Work, and doing so without honoring these terms and conditions is prohibited by copyright law and international treaty. Nothing in this License is intended to affect copyright exceptions and limitations (including "fair use" or "fair dealing"). This License shall terminate immediately and You may no longer exercise any of the rights granted to You by this License upon your failure to honor the conditions in Section 1(c). + + 10. Termination for Patent Action. This License shall terminate automatically and You may no longer exercise any of the rights granted to You by this License as of the date You commence an action, including a cross-claim or counterclaim, against Licensor or any licensee alleging that the Original Work infringes a patent. This termination provision shall not apply for an action alleging patent infringement by combinations of the Original Work with other software or hardware. + + 11. Jurisdiction, Venue and Governing Law. Any action or suit relating to this License may be brought only in the courts of a jurisdiction wherein the Licensor resides or in which Licensor conducts its primary business, and under the laws of that jurisdiction excluding its conflict-of-law provisions. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any use of the Original Work outside the scope of this License or after its termination shall be subject to the requirements and penalties of copyright or patent law in the appropriate jurisdiction. This section shall survive the termination of this License. + + 12. Attorneys' Fees. In any action to enforce the terms of this License or seeking damages relating thereto, the prevailing party shall be entitled to recover its costs and expenses, including, without limitation, reasonable attorneys' fees and costs incurred in connection with such action, including any appeal of such action. This section shall survive the termination of this License. + + 13. Miscellaneous. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. + + 14. Definition of "You" in This License. "You" throughout this License, whether in upper or lower case, means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License. For legal entities, "You" includes any entity that controls, is controlled by, or is under common control with you. For purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + 15. Right to Use. You may use the Original Work in all ways not otherwise restricted or conditioned by this License or by law, and Licensor promises not to interfere with or be responsible for such uses by You. + 16. Modification of This License. This License is Copyright © 2005 Lawrence Rosen. Permission is granted to copy, distribute, or communicate this License without modification. Nothing in this License permits You to modify this License as applied to the Original Work or to Derivative Works. However, You may modify the text of this License and copy, distribute or communicate your modified version (the "Modified License") and apply it to other original works of authorship subject to the following conditions: (i) You may not indicate in any way that your Modified License is the "Academic Free License" or "AFL" and you may not use those names in the name of your Modified License; (ii) You must replace the notice specified in the first paragraph above with the notice "Licensed under <insert your license name here>" or with a notice of your own that is not confusingly similar to the notice in this License; and (iii) You may not claim that your original works are open source software unless your Modified License has been approved by Open Source Initiative (OSI) and You comply with its license review and certification process. \ No newline at end of file diff --git a/app/Mage.php b/app/Mage.php index 8dc32ae5cd05a835b0d7d941fc4e2ab92f85e50e..d5c8e4988e61df908957a92721bad32ed1d5bb63 100644 --- a/app/Mage.php +++ b/app/Mage.php @@ -170,7 +170,7 @@ final class Mage 'revision' => '0', 'patch' => '0', 'stability' => 'dev', - 'number' => '34', + 'number' => '35', ); } diff --git a/app/bootstrap.php b/app/bootstrap.php index 315f3cba0db6bb981c34af4589511cab39b62d19..2283f095dae3e3fe363f5ad4f9fff3bcba99c010 100644 --- a/app/bootstrap.php +++ b/app/bootstrap.php @@ -18,9 +18,8 @@ * versions in the future. If you wish to customize Magento for your * needs please refer to http://www.magentocommerce.com for more information. * - * @category Magento - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ /* PHP version validation */ @@ -97,15 +96,22 @@ if (file_exists($definitionsFile)) { Mage::initializeObjectManager($definitionsFile); } +$output = null; if (isset($_SERVER['MAGE_PROFILER'])) { switch ($_SERVER['MAGE_PROFILER']) { case 'firebug': - Magento_Profiler::registerOutput(new Magento_Profiler_Output_Firebug()); + $output = new Magento_Profiler_Driver_Standard_Output_Firebug(); break; case 'csv': - Magento_Profiler::registerOutput(new Magento_Profiler_Output_Csvfile(__DIR__ . '/../var/log/profiler.csv')); + $output = new Magento_Profiler_Driver_Standard_Output_Csvfile(__DIR__ . '/../var/log/profiler.csv'); break; default: - Magento_Profiler::registerOutput(new Magento_Profiler_Output_Html()); + $output = new Magento_Profiler_Driver_Standard_Output_Html(); } } + +if ($output) { + $driver = new Magento_Profiler_Driver_Standard(); + $driver->registerOutput($output); + Magento_Profiler::add($driver); +} diff --git a/app/code/core/Mage/Adminhtml/Block/Api/Buttons.php b/app/code/core/Mage/Adminhtml/Block/Api/Buttons.php deleted file mode 100644 index d938be45056bd5f8d4370956b1b1bf3a4b4b3c2a..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Adminhtml/Block/Api/Buttons.php +++ /dev/null @@ -1,88 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Adminhtml - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -class Mage_Adminhtml_Block_Api_Buttons extends Mage_Adminhtml_Block_Template -{ - - protected $_template = 'api/userinfo.phtml'; - - protected function _prepareLayout() - { - $this->addChild('backButton', 'Mage_Adminhtml_Block_Widget_Button', array( - 'label' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('Back'), - 'onclick' => 'window.location.href=\''.$this->getUrl('*/*/').'\'', - 'class' => 'back' - )); - - $this->addChild('resetButton', 'Mage_Adminhtml_Block_Widget_Button', array( - 'label' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('Reset'), - 'onclick' => 'window.location.reload()' - )); - - $this->addChild('saveButton', 'Mage_Adminhtml_Block_Widget_Button', array( - 'label' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('Save Role'), - 'class' => 'save', - 'data_attr' => array( - 'widget-button' => array('event' => 'save', 'related' => '#role-edit-form') - ) - )); - - $this->addChild('deleteButton', 'Mage_Adminhtml_Block_Widget_Button', array( - 'label' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('Delete Role'), - 'onclick' => 'deleteConfirm(\'' . Mage::helper('Mage_Adminhtml_Helper_Data')->__('Are you sure you want to do this?') . '\', \'' . $this->getUrl('*/*/delete', array('rid' => $this->getRequest()->getParam('rid'))) . '\')', - 'class' => 'delete' - )); - return parent::_prepareLayout(); - } - - public function getBackButtonHtml() - { - return $this->getChildHtml('backButton'); - } - - public function getResetButtonHtml() - { - return $this->getChildHtml('resetButton'); - } - - public function getSaveButtonHtml() - { - return $this->getChildHtml('saveButton'); - } - - public function getDeleteButtonHtml() - { - if( intval($this->getRequest()->getParam('rid')) == 0 ) { - return; - } - return $this->getChildHtml('deleteButton'); - } - - public function getUser() - { - return Mage::registry('user_data'); - } -} diff --git a/app/code/core/Mage/Adminhtml/Block/Api/Editroles.php b/app/code/core/Mage/Adminhtml/Block/Api/Editroles.php deleted file mode 100644 index 95ad290140847279679a7c68834a806651048279..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Adminhtml/Block/Api/Editroles.php +++ /dev/null @@ -1,69 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Adminhtml - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -class Mage_Adminhtml_Block_Api_Editroles extends Mage_Adminhtml_Block_Widget_Tabs { - protected function _construct() - { - parent::_construct(); - $this->setId('role_info_tabs'); - $this->setDestElementId('role-edit-form'); - $this->setTitle(Mage::helper('Mage_Adminhtml_Helper_Data')->__('Role Information')); - } - - protected function _beforeToHtml() - { - $roleId = $this->getRequest()->getParam('rid', false); - $role = Mage::getModel('Mage_Api_Model_Roles') - ->load($roleId); - - $this->addTab('info', array( - 'label' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('Role Info'), - 'title' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('Role Info'), - 'content' => $this->getLayout()->createBlock( - 'Mage_Adminhtml_Block_Api_Tab_Roleinfo' - )->setRole($role)->toHtml(), - 'active' => true - )); - - $this->addTab('account', array( - 'label' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('Role Resources'), - 'title' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('Role Resources'), - 'content' => $this->getLayout()->createBlock('Mage_Adminhtml_Block_Api_Tab_Rolesedit')->toHtml(), - )); - - if( intval($roleId) > 0 ) { - $this->addTab('roles', array( - 'label' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('Role Users'), - 'title' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('Role Users'), - 'content' => $this->getLayout()->createBlock( - 'Mage_Adminhtml_Block_Api_Tab_Rolesusers', - 'role.users.grid' - )->toHtml(), - )); - } - return parent::_beforeToHtml(); - } -} diff --git a/app/code/core/Mage/Adminhtml/Block/Api/Grid/Role.php b/app/code/core/Mage/Adminhtml/Block/Api/Grid/Role.php deleted file mode 100644 index 9b5e38a2c14dfe1c8b4c85fb01165d0148177e43..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Adminhtml/Block/Api/Grid/Role.php +++ /dev/null @@ -1,81 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Adminhtml - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * roles grid - * - * @category Mage - * @package Mage_Adminhtml - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Adminhtml_Block_Api_Grid_Role extends Mage_Adminhtml_Block_Widget_Grid -{ - protected function _construct() - { - parent::_construct(); - $this->setId('roleGrid'); - $this->setSaveParametersInSession(true); - $this->setDefaultSort('role_id'); - $this->setDefaultDir('asc'); - $this->setUseAjax(true); - } - - protected function _prepareCollection() - { - $collection = Mage::getModel('Mage_Api_Model_Roles')->getCollection(); - $this->setCollection($collection); - - return parent::_prepareCollection(); - } - - protected function _prepareColumns() - { - - $this->addColumn('role_id', array( - 'header' =>Mage::helper('Mage_Adminhtml_Helper_Data')->__('ID'), - 'index' =>'role_id', - 'align' => 'right', - 'width' => '50px' - )); - - $this->addColumn('role_name', array( - 'header' =>Mage::helper('Mage_Adminhtml_Helper_Data')->__('Role Name'), - 'index' =>'role_name' - )); - - return parent::_prepareColumns(); - } - - public function getGridUrl() - { - return $this->getUrl('*/*/roleGrid', array('_current'=>true)); - } - - public function getRowUrl($row) - { - return $this->getUrl('*/*/editrole', array('rid' => $row->getRoleId())); - } -} diff --git a/app/code/core/Mage/Adminhtml/Block/Api/Role/Grid/User.php b/app/code/core/Mage/Adminhtml/Block/Api/Role/Grid/User.php deleted file mode 100644 index 478bd8b4fe76617ebb04c7ac55429164384c7c44..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Adminhtml/Block/Api/Role/Grid/User.php +++ /dev/null @@ -1,182 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Adminhtml - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Acl role user grid - * - * @category Mage - * @package Mage_Adminhtml - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Adminhtml_Block_Api_Role_Grid_User extends Mage_Adminhtml_Block_Widget_Grid -{ - - protected function _construct() - { - parent::_construct(); - $this->setDefaultSort('role_user_id'); - $this->setDefaultDir('asc'); - $this->setId('roleUserGrid'); - $this->setDefaultFilter(array('in_role_users'=>1)); - $this->setUseAjax(true); - } - - protected function _addColumnFilterToCollection($column) - { - if ($column->getId() == 'in_role_users') { - $inRoleIds = $this->_getUsers(); - if (empty($inRoleIds)) { - $inRoleIds = 0; - } - if ($column->getFilter()->getValue()) { - $this->getCollection()->addFieldToFilter('user_id', array('in'=>$inRoleIds)); - } - else { - if($inRoleIds) { - $this->getCollection()->addFieldToFilter('user_id', array('nin'=>$inRoleIds)); - } - } - } - else { - parent::_addColumnFilterToCollection($column); - } - return $this; - } - - protected function _prepareCollection() - { - $roleId = $this->getRequest()->getParam('rid'); - Mage::register('RID', $roleId); - $collection = Mage::getModel('Mage_Api_Model_Roles')->getUsersCollection(); - $this->setCollection($collection); - return parent::_prepareCollection(); - } - - protected function _prepareColumns() - { - $this->addColumn('in_role_users', array( - 'header_css_class' => 'a-center', - 'type' => 'checkbox', - 'name' => 'in_role_users', - 'values' => $this->_getUsers(), - 'align' => 'center', - 'index' => 'user_id' - )); - - $this->addColumn('role_user_id', array( - 'header' =>Mage::helper('Mage_Adminhtml_Helper_Data')->__('User ID'), - 'width' =>5, - 'align' =>'left', - 'sortable' =>true, - 'index' =>'user_id' - )); - - $this->addColumn('role_user_username', array( - 'header' =>Mage::helper('Mage_Adminhtml_Helper_Data')->__('User Name'), - 'align' =>'left', - 'index' =>'username' - )); - - $this->addColumn('role_user_firstname', array( - 'header' =>Mage::helper('Mage_Adminhtml_Helper_Data')->__('First Name'), - 'align' =>'left', - 'index' =>'firstname' - )); - - $this->addColumn('role_user_lastname', array( - 'header' =>Mage::helper('Mage_Adminhtml_Helper_Data')->__('Last Name'), - 'align' =>'left', - 'index' =>'lastname' - )); - - $this->addColumn('role_user_email', array( - 'header' =>Mage::helper('Mage_Adminhtml_Helper_Data')->__('Email'), - 'width' =>40, - 'align' =>'left', - 'index' =>'email' - )); - - $this->addColumn('role_user_is_active', array( - 'header' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('Status'), - 'index' => 'is_active', - 'align' =>'left', - 'type' => 'options', - 'options' => array('1' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('Active'), '0' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('Inactive')), - )); - - /* - $this->addColumn('grid_actions', - array( - 'header'=>Mage::helper('Mage_Adminhtml_Helper_Data')->__('Actions'), - 'width'=>5, - 'sortable'=>false, - 'filter' =>false, - 'type' => 'action', - 'actions' => array( - array( - 'caption' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('Remove'), - 'onClick' => 'role.deleteFromRole($role_id);' - ) - ) - ) - ); - */ - - return parent::_prepareColumns(); - } - - public function getGridUrl() - { - $roleId = $this->getRequest()->getParam('rid'); - return $this->getUrl('*/*/editrolegrid', array('rid' => $roleId)); - } - - protected function _getUsers($json=false) - { - if ( $this->getRequest()->getParam('in_role_user') != "" ) { - return $this->getRequest()->getParam('in_role_user'); - } - $roleId = ( $this->getRequest()->getParam('rid') > 0 ) ? $this->getRequest()->getParam('rid') : Mage::registry('RID'); - $users = Mage::getModel('Mage_Api_Model_Roles')->setId($roleId)->getRoleUsers(); - if (sizeof($users) > 0) { - if ( $json ) { - $jsonUsers = Array(); - foreach($users as $usrid) $jsonUsers[$usrid] = 0; - return Mage::helper('Mage_Core_Helper_Data')->jsonEncode((object)$jsonUsers); - } else { - return array_values($users); - } - } else { - if ( $json ) { - return '{}'; - } else { - return array(); - } - } - } - -} - diff --git a/app/code/core/Mage/Adminhtml/Block/Api/Tab/Roleinfo.php b/app/code/core/Mage/Adminhtml/Block/Api/Tab/Roleinfo.php deleted file mode 100644 index 167539f5629e761949a2156d69ecdac3255b9389..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Adminhtml/Block/Api/Tab/Roleinfo.php +++ /dev/null @@ -1,76 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Adminhtml - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * implementing now - * - */ -class Mage_Adminhtml_Block_Api_Tab_Roleinfo extends Mage_Adminhtml_Block_Widget_Form -{ - public function _beforeToHtml() { - $this->_initForm(); - - return parent::_beforeToHtml(); - } - - protected function _initForm() - { - $roleId = $this->getRequest()->getParam('rid'); - - $form = new Varien_Data_Form(); - - $fieldset = $form->addFieldset('base_fieldset', array('legend'=>Mage::helper('Mage_Adminhtml_Helper_Data')->__('Role Information'))); - - $fieldset->addField('role_name', 'text', - array( - 'name' => 'rolename', - 'label' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('Role Name'), - 'id' => 'role_name', - 'class' => 'required-entry', - 'required' => true, - ) - ); - - $fieldset->addField('role_id', 'hidden', - array( - 'name' => 'role_id', - 'id' => 'role_id', - ) - ); - - $fieldset->addField('in_role_user', 'hidden', - array( - 'name' => 'in_role_user', - 'id' => 'in_role_userz', - ) - ); - - $fieldset->addField('in_role_user_old', 'hidden', array('name' => 'in_role_user_old')); - - $form->setValues($this->getRole()->getData()); - $this->setForm($form); - } -} diff --git a/app/code/core/Mage/Adminhtml/Block/Api/Tab/Rolesedit.php b/app/code/core/Mage/Adminhtml/Block/Api/Tab/Rolesedit.php deleted file mode 100644 index 75725f4b2b868ef19ec0f6d104a7931da1c37ad3..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Adminhtml/Block/Api/Tab/Rolesedit.php +++ /dev/null @@ -1,122 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Adminhtml - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -class Mage_Adminhtml_Block_Api_Tab_Rolesedit extends Mage_Adminhtml_Block_Widget_Form { - - protected $_template = 'api/rolesedit.phtml'; - - - protected function _construct() { - parent::_construct(); - - $rid = Mage::app()->getRequest()->getParam('rid', false); - - $resources = Mage::getModel('Mage_Api_Model_Roles')->getResourcesList(); - - $rules_set = Mage::getResourceModel('Mage_Api_Model_Resource_Rules_Collection')->getByRoles($rid)->load(); - - $selrids = array(); - - foreach ($rules_set->getItems() as $item) { - if (array_key_exists(strtolower($item->getResource_id()), $resources) - && $item->getApiPermission() == 'allow') - { - $resources[$item->getResource_id()]['checked'] = true; - array_push($selrids, $item->getResource_id()); - } - } - - $this->setSelectedResources($selrids); - - - //->assign('resources', $resources); - //->assign('checkedResources', join(',', $selrids)); - } - - public function getEverythingAllowed() - { - return in_array('all', $this->getSelectedResources()); - } - - public function getResTreeJson() - { - $rid = Mage::app()->getRequest()->getParam('rid', false); - $resources = Mage::getModel('Mage_Api_Model_Roles')->getResourcesTree(); - - $rootArray = $this->_getNodeJson($resources,1); - - $json = Mage::helper('Mage_Core_Helper_Data')->jsonEncode(isset($rootArray['children']) ? $rootArray['children'] : array()); - - return $json; - } - - protected function _sortTree($a, $b) - { - return $a['sort_order']<$b['sort_order'] ? -1 : ($a['sort_order']>$b['sort_order'] ? 1 : 0); - } - - - protected function _getNodeJson($node, $level=0) - { - $item = array(); - $selres = $this->getSelectedResources(); - - if ($level != 0) { - $item['text']= (string)$node->title; - $item['sort_order']= isset($node->sort_order) ? (string)$node->sort_order : 0; - $item['id'] = (string)$node->attributes()->aclpath; - - if (in_array($item['id'], $selres)) - $item['checked'] = true; - } - if (isset($node->children)) { - $children = $node->children->children(); - } else { - $children = $node->children(); - } - if (empty($children)) { - return $item; - } - - if ($children) { - $item['children'] = array(); - //$item['cls'] = 'fiche-node'; - foreach ($children as $child) { - if ($child->getName()!='title' && $child->getName()!='sort_order' && $child->attributes()->module) { - if ($level != 0) { - $item['children'][] = $this->_getNodeJson($child, $level+1); - } else { - $item = $this->_getNodeJson($child, $level+1); - } - } - } - if (!empty($item['children'])) { - usort($item['children'], array($this, '_sortTree')); - } - } - return $item; - } -} diff --git a/app/code/core/Mage/Adminhtml/Block/Api/Tab/Rolesusers.php b/app/code/core/Mage/Adminhtml/Block/Api/Tab/Rolesusers.php deleted file mode 100644 index 2d06670ab68e88b52772ffbc2a3fa06864102d2d..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Adminhtml/Block/Api/Tab/Rolesusers.php +++ /dev/null @@ -1,54 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Adminhtml - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -class Mage_Adminhtml_Block_Api_Tab_Rolesusers extends Mage_Adminhtml_Block_Widget_Tabs { - - protected function _construct() - { - parent::_construct(); - - $roleId = $this->getRequest()->getParam('rid', false); - - $users = Mage::getModel('Mage_Api_Model_User')->getCollection()->load(); - $this->setTemplate('api/rolesusers.phtml') - ->assign('users', $users->getItems()) - ->assign('roleId', $roleId); - } - - protected function _prepareLayout() - { - $this->setChild( - 'userGrid', - $this->getLayout()->createBlock('Mage_Adminhtml_Block_Api_Role_Grid_User', 'roleUsersGrid') - ); - return parent::_prepareLayout(); - } - - protected function _getGridHtml() - { - return $this->getChildHtml('userGrid'); - } -} diff --git a/app/code/core/Mage/Adminhtml/Block/Api/User/Edit.php b/app/code/core/Mage/Adminhtml/Block/Api/User/Edit.php deleted file mode 100644 index 823ebd020f2392e74fe53277e2d696c4af33210d..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Adminhtml/Block/Api/User/Edit.php +++ /dev/null @@ -1,58 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Adminhtml - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Adminhtml permissions user edit page - * - * @category Mage - * @package Mage_Adminhtml - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Adminhtml_Block_Api_User_Edit extends Mage_Adminhtml_Block_Widget_Form_Container -{ - - protected function _construct() - { - $this->_objectId = 'user_id'; - $this->_controller = 'api_user'; - - parent::_construct(); - - $this->_updateButton('save', 'label', Mage::helper('Mage_Adminhtml_Helper_Data')->__('Save User')); - $this->_updateButton('delete', 'label', Mage::helper('Mage_Adminhtml_Helper_Data')->__('Delete User')); - } - - public function getHeaderText() - { - if (Mage::registry('api_user')->getId()) { - return Mage::helper('Mage_Adminhtml_Helper_Data')->__("Edit User '%s'", $this->escapeHtml(Mage::registry('api_user')->getUsername())); - } - else { - return Mage::helper('Mage_Adminhtml_Helper_Data')->__('New User'); - } - } - -} diff --git a/app/code/core/Mage/Adminhtml/Block/Api/User/Edit/Tab/Main.php b/app/code/core/Mage/Adminhtml/Block/Api/User/Edit/Tab/Main.php deleted file mode 100644 index 7a14ba863a978a1c062d8733f9270a4facb84d5d..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Adminhtml/Block/Api/User/Edit/Tab/Main.php +++ /dev/null @@ -1,153 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Adminhtml - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Cms page edit form main tab - * - * @category Mage - * @package Mage_Adminhtml - * @author Magento Core Team <core@magentocommerce.com> - */ - -class Mage_Adminhtml_Block_Api_User_Edit_Tab_Main extends Mage_Adminhtml_Block_Widget_Form -{ - - protected function _prepareForm() - { - $model = Mage::registry('api_user'); - - $form = new Varien_Data_Form(); - - $form->setHtmlIdPrefix('user_'); - - $fieldset = $form->addFieldset('base_fieldset', array('legend'=>Mage::helper('Mage_Adminhtml_Helper_Data')->__('Account Information'))); - - if ($model->getUserId()) { - $fieldset->addField('user_id', 'hidden', array( - 'name' => 'user_id', - )); - } else { - if (! $model->hasData('is_active')) { - $model->setIsActive(1); - } - } - - $fieldset->addField('username', 'text', array( - 'name' => 'username', - 'label' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('User Name'), - 'id' => 'username', - 'title' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('User Name'), - 'required' => true, - )); - - $fieldset->addField('firstname', 'text', array( - 'name' => 'firstname', - 'label' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('First Name'), - 'id' => 'firstname', - 'title' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('First Name'), - 'required' => true, - )); - - $fieldset->addField('lastname', 'text', array( - 'name' => 'lastname', - 'label' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('Last Name'), - 'id' => 'lastname', - 'title' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('Last Name'), - 'required' => true, - )); - - $fieldset->addField('email', 'text', array( - 'name' => 'email', - 'label' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('Email'), - 'id' => 'customer_email', - 'title' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('User Email'), - 'class' => 'required-entry validate-email', - 'required' => true, - )); - - if ($model->getUserId()) { - $fieldset->addField('password', 'password', array( - 'name' => 'new_api_key', - 'label' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('New API Key'), - 'id' => 'new_pass', - 'title' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('New API Key'), - 'class' => 'input-text validate-password', - )); - - $fieldset->addField('confirmation', 'password', array( - 'name' => 'api_key_confirmation', - 'label' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('API Key Confirmation'), - 'id' => 'confirmation', - 'class' => 'input-text validate-cpassword', - )); - } - else { - $fieldset->addField('password', 'password', array( - 'name' => 'api_key', - 'label' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('API Key'), - 'id' => 'customer_pass', - 'title' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('API Key'), - 'class' => 'input-text required-entry validate-password', - 'required' => true, - )); - $fieldset->addField('confirmation', 'password', array( - 'name' => 'api_key_confirmation', - 'label' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('API Key Confirmation'), - 'id' => 'confirmation', - 'title' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('API Key Confirmation'), - 'class' => 'input-text required-entry validate-cpassword', - 'required' => true, - )); - } - - if (Mage::getSingleton('Mage_Backend_Model_Auth_Session')->getUser()->getId() != $model->getUserId()) { - $fieldset->addField('is_active', 'select', array( - 'name' => 'is_active', - 'label' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('This account is'), - 'id' => 'is_active', - 'title' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('Account status'), - 'class' => 'input-select', - 'style' => 'width: 80px', - 'options' => array('1' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('Active'), '0' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('Inactive')), - )); - } - - $fieldset->addField('user_roles', 'hidden', array( - 'name' => 'user_roles', - 'id' => '_user_roles', - )); - - $data = $model->getData(); - - unset($data['password']); - - $form->setValues($data); - - $this->setForm($form); - - return parent::_prepareForm(); - } -} diff --git a/app/code/core/Mage/Adminhtml/Block/Api/User/Edit/Tab/Roles.php b/app/code/core/Mage/Adminhtml/Block/Api/User/Edit/Tab/Roles.php deleted file mode 100644 index d0e34dd791751a887781d9a5df4f0c47dad6e5c1..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Adminhtml/Block/Api/User/Edit/Tab/Roles.php +++ /dev/null @@ -1,119 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Adminhtml - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -class Mage_Adminhtml_Block_Api_User_Edit_Tab_Roles extends Mage_Adminhtml_Block_Widget_Grid -{ - - protected function _construct() - { - parent::_construct(); - $this->setId('permissionsUserRolesGrid'); - $this->setDefaultSort('sort_order'); - $this->setDefaultDir('asc'); - //$this->setDefaultFilter(array('assigned_user_role'=>1)); - $this->setTitle(Mage::helper('Mage_Adminhtml_Helper_Data')->__('User Roles Information')); - $this->setUseAjax(true); - } - - protected function _addColumnFilterToCollection($column) - { - if ($column->getId() == 'assigned_user_role') { - $userRoles = $this->_getSelectedRoles(); - if (empty($userRoles)) { - $userRoles = 0; - } - if ($column->getFilter()->getValue()) { - $this->getCollection()->addFieldToFilter('role_id', array('in'=>$userRoles)); - } - else { - if($userRoles) { - $this->getCollection()->addFieldToFilter('role_id', array('nin'=>$userRoles)); - } - } - } - else { - parent::_addColumnFilterToCollection($column); - } - return $this; - } - - protected function _prepareCollection() - { - $collection = Mage::getResourceModel('Mage_Api_Model_Resource_Role_Collection'); - $collection->setRolesFilter(); - $this->setCollection($collection); - return parent::_prepareCollection(); - } - - protected function _prepareColumns() - { - - $this->addColumn('assigned_user_role', array( - 'header_css_class' => 'a-center', - 'header' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('Assigned'), - 'type' => 'radio', - 'html_name' => 'roles[]', - 'values' => $this->_getSelectedRoles(), - 'align' => 'center', - 'index' => 'role_id' - )); - - /*$this->addColumn('role_id', array( - 'header' =>Mage::helper('Mage_Adminhtml_Helper_Data')->__('Role ID'), - 'index' =>'role_id', - 'align' => 'right', - 'width' => '50px' - ));*/ - - $this->addColumn('role_name', array( - 'header' =>Mage::helper('Mage_Adminhtml_Helper_Data')->__('Role Name'), - 'index' =>'role_name' - )); - - return parent::_prepareColumns(); - } - - public function getGridUrl() - { - return $this->getUrl('*/*/rolesGrid', array('user_id' => Mage::registry('api_user')->getUserId())); - } - - protected function _getSelectedRoles($json=false) - { - if ( $this->getRequest()->getParam('user_roles') != "" ) { - return $this->getRequest()->getParam('user_roles'); - } - $uRoles = Mage::registry('api_user')->getRoles(); - if ($json) { - $jsonRoles = Array(); - foreach($uRoles as $urid) $jsonRoles[$urid] = 0; - return Mage::helper('Mage_Core_Helper_Data')->jsonEncode((object)$jsonRoles); - } else { - return $uRoles; - } - } - -} diff --git a/app/code/core/Mage/Adminhtml/Block/Api/User/Grid.php b/app/code/core/Mage/Adminhtml/Block/Api/User/Grid.php deleted file mode 100644 index 1d25368fcdab4f5397892cbda393ccca1e6c302c..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Adminhtml/Block/Api/User/Grid.php +++ /dev/null @@ -1,106 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Adminhtml - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Adminhtml permissions user grid - * - * @category Mage - * @package Mage_Adminhtml - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Adminhtml_Block_Api_User_Grid extends Mage_Adminhtml_Block_Widget_Grid -{ - - protected function _construct() - { - parent::_construct(); - $this->setId('permissionsUserGrid'); - $this->setDefaultSort('username'); - $this->setDefaultDir('asc'); - $this->setUseAjax(true); - } - - protected function _prepareCollection() - { - $collection = Mage::getResourceModel('Mage_Api_Model_Resource_User_Collection'); - $this->setCollection($collection); - return parent::_prepareCollection(); - } - - protected function _prepareColumns() - { - $this->addColumn('user_id', array( - 'header' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('ID'), - 'width' => 5, - 'align' => 'right', - 'sortable' => true, - 'index' => 'user_id' - )); - - $this->addColumn('username', array( - 'header' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('User Name'), - 'index' => 'username' - )); - - $this->addColumn('firstname', array( - 'header' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('First Name'), - 'index' => 'firstname' - )); - - $this->addColumn('lastname', array( - 'header' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('Last Name'), - 'index' => 'lastname' - )); - - $this->addColumn('email', array( - 'header' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('Email'), - 'width' => 40, - 'align' => 'left', - 'index' => 'email' - )); - - $this->addColumn('is_active', array( - 'header' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('Status'), - 'index' => 'is_active', - 'type' => 'options', - 'options' => array('1' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('Active'), '0' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('Inactive')), - )); - - return parent::_prepareColumns(); - } - - public function getRowUrl($row) - { - return $this->getUrl('*/*/edit', array('user_id' => $row->getId())); - } - - public function getGridUrl() - { - //$uid = $this->getRequest()->getParam('user_id'); - return $this->getUrl('*/*/roleGrid', array()); - } - -} diff --git a/app/code/core/Mage/Adminhtml/Block/System/Email/Template/Edit.php b/app/code/core/Mage/Adminhtml/Block/System/Email/Template/Edit.php index 816328de477e57fb2b52438d0caac6e47b660c48..f29aa2d2f486138d259fc80afc876ff400cef021 100644 --- a/app/code/core/Mage/Adminhtml/Block/System/Email/Template/Edit.php +++ b/app/code/core/Mage/Adminhtml/Block/System/Email/Template/Edit.php @@ -34,6 +34,66 @@ */ class Mage_Adminhtml_Block_System_Email_Template_Edit extends Mage_Adminhtml_Block_Widget { + /** + * @var Mage_Core_Model_Registry + */ + protected $_registryManager; + + /** + * @var Mage_Backend_Model_Menu_Config + */ + protected $_menuConfig; + + /** + * @var Mage_Backend_Model_Config_Structure + */ + protected $_configStructure; + + /** + * @param Mage_Core_Controller_Request_Http $request + * @param Mage_Core_Model_Layout $layout + * @param Mage_Core_Model_Event_Manager $eventManager + * @param Mage_Backend_Model_Url $urlBuilder + * @param Mage_Core_Model_Translate $translator + * @param Mage_Core_Model_Cache $cache + * @param Mage_Core_Model_Design_Package $designPackage + * @param Mage_Core_Model_Session $session + * @param Mage_Core_Model_Store_Config $storeConfig + * @param Mage_Core_Controller_Varien_Front $frontController + * @param Mage_Core_Model_Factory_Helper $helperFactory + * @param Mage_Core_Model_Registry $registry + * @param Mage_Backend_Model_Menu_Config $menuConfig + * @param Mage_Backend_Model_Config_Structure $configStructure + * @param array $data + * + * @SuppressWarnings(PHPMD.ExcessiveParameterList) + */ + public function __construct( + Mage_Core_Controller_Request_Http $request, + Mage_Core_Model_Layout $layout, + Mage_Core_Model_Event_Manager $eventManager, + Mage_Backend_Model_Url $urlBuilder, + Mage_Core_Model_Translate $translator, + Mage_Core_Model_Cache $cache, + Mage_Core_Model_Design_Package $designPackage, + Mage_Core_Model_Session $session, + Mage_Core_Model_Store_Config $storeConfig, + Mage_Core_Controller_Varien_Front $frontController, + Mage_Core_Model_Factory_Helper $helperFactory, + Mage_Core_Model_Registry $registry, + Mage_Backend_Model_Menu_Config $menuConfig, + Mage_Backend_Model_Config_Structure $configStructure, + array $data = array() + ) + { + parent::__construct($request, $layout, $eventManager, $urlBuilder, $translator, $cache, + $designPackage, $session, $storeConfig, $frontController, $helperFactory, $data + ); + $this->_registryManager = $registry; + $this->_menuConfig = $menuConfig; + $this->_configStructure = $configStructure; + } + protected $_template = 'system/email/template/edit.phtml'; @@ -287,7 +347,7 @@ class Mage_Adminhtml_Block_System_Email_Template_Edit extends Mage_Adminhtml_Blo */ public function getEmailTemplate() { - return Mage::registry('current_email_template'); + return $this->_registryManager->registry('current_email_template'); } /** @@ -308,10 +368,12 @@ class Mage_Adminhtml_Block_System_Email_Template_Edit extends Mage_Adminhtml_Blo */ public function getUsedDefaultForPaths($asJSON = true) { - $paths = $this->getEmailTemplate()->getSystemConfigPathsWhereUsedAsDefault(); + /** @var $template Mage_Adminhtml_Model_Email_Template */ + $template = $this->getEmailTemplate(); + $paths = $template->getSystemConfigPathsWhereUsedAsDefault(); $pathsParts = $this->_getSystemConfigPathsParts($paths); if($asJSON){ - return Mage::helper('Mage_Core_Helper_Data')->jsonEncode($pathsParts); + return $this->helper('Mage_Core_Helper_Data')->jsonEncode($pathsParts); } return $pathsParts; } @@ -324,7 +386,9 @@ class Mage_Adminhtml_Block_System_Email_Template_Edit extends Mage_Adminhtml_Blo */ public function getUsedCurrentlyForPaths($asJSON = true) { - $paths = $this->getEmailTemplate()->getSystemConfigPathsWhereUsedCurrently(); + /** @var $template Mage_Adminhtml_Model_Email_Template */ + $template = $this->getEmailTemplate(); + $paths = $template->getSystemConfigPathsWhereUsedCurrently(); $pathsParts = $this->_getSystemConfigPathsParts($paths); if($asJSON){ return Mage::helper('Mage_Core_Helper_Data')->jsonEncode($pathsParts); @@ -341,10 +405,10 @@ class Mage_Adminhtml_Block_System_Email_Template_Edit extends Mage_Adminhtml_Blo protected function _getSystemConfigPathsParts($paths) { $result = $urlParams = $prefixParts = array(); - $scopeLabel = Mage::helper('Mage_Adminhtml_Helper_Data')->__('GLOBAL'); + $scopeLabel = $this->helper('Mage_Backend_Helper_Data')->__('GLOBAL'); if ($paths) { /** @var $menu Mage_Backend_Model_Menu */ - $menu = Mage::getSingleton('Mage_Backend_Model_Menu_Config')->getMenu(); + $menu = $this->_menuConfig->getMenu(); $item = $menu->get('Mage_Adminhtml::system'); // create prefix path parts $prefixParts[] = array( @@ -357,8 +421,10 @@ class Mage_Adminhtml_Block_System_Email_Template_Edit extends Mage_Adminhtml_Blo ); $pathParts = $prefixParts; - foreach ($paths as $id => $pathData) { - list($sectionName, $groupName, $fieldName) = explode('/', $pathData['path']); + foreach ($paths as $pathData) { + $pathDataParts = explode('/', $pathData['path']); + $sectionName = array_shift($pathDataParts); + $urlParams = array('section' => $sectionName); if (isset($pathData['scope']) && isset($pathData['scope_id'])) { switch ($pathData['scope']) { @@ -382,20 +448,23 @@ class Mage_Adminhtml_Block_System_Email_Template_Edit extends Mage_Adminhtml_Blo } } $pathParts[] = array( - 'title' => Mage::getSingleton('Mage_Backend_Model_Config_Structure_Reader') - ->getConfiguration() - ->getSystemConfigNodeLabel($sectionName), + 'title' => $this->_configStructure->getElement($sectionName)->getLabel(), 'url' => $this->getUrl('adminhtml/system_config/edit', $urlParams), ); + $elementPathParts = array($sectionName); + while (count($pathDataParts) != 1) { + $elementPathParts[] = array_shift($pathDataParts); + $pathParts[] = array( + 'title' => $this->_configStructure + ->getElementByPathParts($elementPathParts) + ->getLabel() + ); + } + $elementPathParts[] = array_shift($pathDataParts); $pathParts[] = array( - 'title' => Mage::getSingleton('Mage_Backend_Model_Config_Structure_Reader') - ->getConfiguration() - ->getSystemConfigNodeLabel($sectionName, $groupName) - ); - $pathParts[] = array( - 'title' => Mage::getSingleton('Mage_Backend_Model_Config_Structure_Reader') - ->getConfiguration() - ->getSystemConfigNodeLabel($sectionName, $groupName, $fieldName), + 'title' => $this->_configStructure + ->getElementByPathParts($elementPathParts) + ->getLabel(), 'scope' => $scopeLabel ); $result[] = $pathParts; diff --git a/app/code/core/Mage/Adminhtml/Model/Email/Template.php b/app/code/core/Mage/Adminhtml/Model/Email/Template.php index 1ff14aa5d8dbe5d1a594c7f4e641641001c2b27c..b6d173e97d8028b7cdff307e5016a354c948c662 100644 --- a/app/code/core/Mage/Adminhtml/Model/Email/Template.php +++ b/app/code/core/Mage/Adminhtml/Model/Email/Template.php @@ -47,10 +47,6 @@ class Mage_Adminhtml_Model_Email_Template extends Mage_Core_Model_Email_Template } $paths = array(); - $configSections = Mage::getSingleton('Mage_Backend_Model_Config_Structure_Reader') - ->getConfiguration() - ->getSections(); - // find nodes which are using $templateCode value $defaultCfgNodes = Mage::getConfig()->getXpath('default/*/*[*="' . $templateCode . '"]'); if (!is_array($defaultCfgNodes)) { @@ -79,9 +75,10 @@ class Mage_Adminhtml_Model_Email_Template extends Mage_Core_Model_Email_Template return array(); } - $templatePaths = Mage::getSingleton('Mage_Backend_Model_Config_Structure_Reader') - ->getConfiguration() - ->getFieldsByAttribute('source_model', 'Mage_Backend_Model_Config_Source_Email_Template'); + /** @var Mage_Backend_Model_Config_Structure $configStructure */ + $configStructure = Mage::getSingleton('Mage_Backend_Model_Config_Structure'); + $templatePaths = $configStructure + ->getFieldPathsByAttribute('source_model', 'Mage_Backend_Model_Config_Source_Email_Template'); if (!count($templatePaths)) { return array(); diff --git a/app/code/core/Mage/Adminhtml/controllers/Api/RoleController.php b/app/code/core/Mage/Adminhtml/controllers/Api/RoleController.php deleted file mode 100644 index 4d839e491166ad5c88cf3027ff6749f66203552f..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Adminhtml/controllers/Api/RoleController.php +++ /dev/null @@ -1,217 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Adminhtml - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Adminhtml roles controller - * - * @category Mage - * @package Mage_Adminhtml - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Adminhtml_Api_RoleController extends Mage_Adminhtml_Controller_Action -{ - - protected function _initAction() - { - $this->loadLayout(); - $this->_setActiveMenu('Mage_Api::system_api_roles'); - $this->_addBreadcrumb($this->__('Web services'), $this->__('Web services')); - $this->_addBreadcrumb($this->__('Permissions'), $this->__('Permissions')); - $this->_addBreadcrumb($this->__('Roles'), $this->__('Roles')); - return $this; - } - - public function indexAction() - { - $this->_title($this->__('System')) - ->_title($this->__('Web Services')) - ->_title($this->__('Roles')); - - $this->_initAction(); - - $this->_addContent($this->getLayout()->createBlock('Mage_Adminhtml_Block_Api_Roles')); - - $this->renderLayout(); - } - - public function roleGridAction() - { - $this->getResponse() - ->setBody($this->getLayout() - ->createBlock('Mage_Adminhtml_Block_Api_Grid_Role') - ->toHtml() - ); - } - - public function editRoleAction() - { - $this->_title($this->__('System')) - ->_title($this->__('Web Services')) - ->_title($this->__('Roles')); - - $this->_initAction(); - - $roleId = $this->getRequest()->getParam('rid'); - if( intval($roleId) > 0 ) { - $breadCrumb = $this->__('Edit Role'); - $breadCrumbTitle = $this->__('Edit Role'); - $this->_title($this->__('Edit Role')); - } else { - $breadCrumb = $this->__('Add New Role'); - $breadCrumbTitle = $this->__('Add New Role'); - $this->_title($this->__('New Role')); - } - $this->_addBreadcrumb($breadCrumb, $breadCrumbTitle); - - $this->getLayout()->getBlock('head')->setCanLoadExtJs(true); - - $this->_addLeft( - $this->getLayout()->createBlock('Mage_Adminhtml_Block_Api_Editroles') - ); - $resources = Mage::getModel('Mage_Api_Model_Roles')->getResourcesList(); - $this->_addContent( - $this->getLayout()->createBlock('Mage_Adminhtml_Block_Api_Buttons') - ->setRoleId($roleId) - ->setRoleInfo(Mage::getModel('Mage_Api_Model_Roles')->load($roleId)) - ->setTemplate('api/roleinfo.phtml') - ); - $this->_addJs( - $this->getLayout() - ->createBlock('Mage_Adminhtml_Block_Template') - ->setTemplate('api/role_users_grid_js.phtml') - ); - $this->renderLayout(); - } - - public function deleteAction() - { - $rid = $this->getRequest()->getParam('rid', false); - - try { - Mage::getModel('Mage_Api_Model_Roles')->load($rid)->delete(); - Mage::getSingleton('Mage_Adminhtml_Model_Session')->addSuccess($this->__('The role has been deleted.')); - } catch (Exception $e) { - Mage::getSingleton('Mage_Adminhtml_Model_Session')->addError($this->__('An error occurred while deleting this role.')); - } - - $this->_redirect("*/*/"); - } - - public function saveRoleAction() - { - - $rid = $this->getRequest()->getParam('role_id', false); - $role = Mage::getModel('Mage_Api_Model_Roles')->load($rid); - if (!$role->getId() && $rid) { - Mage::getSingleton('Mage_Adminhtml_Model_Session')->addError($this->__('This Role no longer exists')); - $this->_redirect('*/*/'); - return; - } - - $resource = explode(',', $this->getRequest()->getParam('resource', false)); - $roleUsers = $this->getRequest()->getParam('in_role_user', null); - parse_str($roleUsers, $roleUsers); - $roleUsers = array_keys($roleUsers); - - $oldRoleUsers = $this->getRequest()->getParam('in_role_user_old'); - parse_str($oldRoleUsers, $oldRoleUsers); - $oldRoleUsers = array_keys($oldRoleUsers); - - $isAll = $this->getRequest()->getParam('all'); - if ($isAll) { - $resource = array("all"); - } - - try { - $role = $role - ->setName($this->getRequest()->getParam('rolename', false)) - ->setPid($this->getRequest()->getParam('parent_id', false)) - ->setRoleType('G') - ->save(); - - Mage::getModel('Mage_Api_Model_Rules') - ->setRoleId($role->getId()) - ->setResources($resource) - ->saveRel(); - - foreach($oldRoleUsers as $oUid) { - $this->_deleteUserFromRole($oUid, $role->getId()); - } - - foreach ($roleUsers as $nRuid) { - $this->_addUserToRole($nRuid, $role->getId()); - } - - $rid = $role->getId(); - Mage::getSingleton('Mage_Adminhtml_Model_Session')->addSuccess($this->__('The role has been saved.')); - } catch (Exception $e) { - Mage::getSingleton('Mage_Adminhtml_Model_Session')->addError($this->__('An error occurred while saving this role.')); - } - - //$this->getResponse()->setRedirect($this->getUrl("*/*/editrole/rid/$rid")); - $this->_redirect('*/*/editrole', array('rid' => $rid)); - return; - } - - public function editrolegridAction() - { - $this->getResponse()->setBody( - $this->getLayout()->createBlock('Mage_Adminhtml_Block_Api_Role_Grid_User')->toHtml() - ); - } - - protected function _deleteUserFromRole($userId, $roleId) - { - try { - Mage::getModel('Mage_Api_Model_User') - ->setRoleId($roleId) - ->setUserId($userId) - ->deleteFromRole(); - } catch (Exception $e) { - throw $e; - return false; - } - return true; - } - - protected function _addUserToRole($userId, $roleId) - { - $user = Mage::getModel('Mage_Api_Model_User')->load($userId); - $user->setRoleId($roleId)->setUserId($userId); - - if( $user->roleUserExists() === true ) { - return false; - } else { - $user->add(); - return true; - } - } - - protected function _isAllowed() - { - return Mage::getSingleton('Mage_Core_Model_Authorization')->isAllowed('Mage_Api::roles'); - } -} diff --git a/app/code/core/Mage/Adminhtml/controllers/Api/UserController.php b/app/code/core/Mage/Adminhtml/controllers/Api/UserController.php deleted file mode 100644 index d817ad82807b3155c4065163ccf5edf27b66577c..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Adminhtml/controllers/Api/UserController.php +++ /dev/null @@ -1,190 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Adminhtml - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ -class Mage_Adminhtml_Api_UserController extends Mage_Adminhtml_Controller_Action -{ - - protected function _initAction() - { - $this->loadLayout() - ->_setActiveMenu('Mage_Api::system_api_users') - ->_addBreadcrumb($this->__('Web Services'), $this->__('Web Services')) - ->_addBreadcrumb($this->__('Permissions'), $this->__('Permissions')) - ->_addBreadcrumb($this->__('Users'), $this->__('Users')) - ; - return $this; - } - - public function indexAction() - { - $this->_title($this->__('System')) - ->_title($this->__('Web Services')) - ->_title($this->__('Users')); - - $this->_initAction() - ->_addContent($this->getLayout()->createBlock('Mage_Adminhtml_Block_Api_User')) - ->renderLayout(); - } - - public function newAction() - { - $this->_forward('edit'); - } - - public function editAction() - { - $this->_title($this->__('System')) - ->_title($this->__('Web Services')) - ->_title($this->__('Users')); - - $id = $this->getRequest()->getParam('user_id'); - $model = Mage::getModel('Mage_Api_Model_User'); - - if ($id) { - $model->load($id); - if (! $model->getId()) { - Mage::getSingleton('Mage_Adminhtml_Model_Session')->addError($this->__('This user no longer exists.')); - $this->_redirect('*/*/'); - return; - } - } - - $this->_title($model->getId() ? $model->getName() : $this->__('New User')); - - // Restore previously entered form data from session - $data = Mage::getSingleton('Mage_Adminhtml_Model_Session')->getUserData(true); - if (!empty($data)) { - $model->setData($data); - } - - Mage::register('api_user', $model); - - $this->_initAction() - ->_addBreadcrumb($id ? $this->__('Edit User') : $this->__('New User'), $id ? $this->__('Edit User') : $this->__('New User')) - ->_addContent($this->getLayout() - ->createBlock('Mage_Adminhtml_Block_Api_User_Edit') - ->setData('action', $this->getUrl('*/api_user/save'))) - ->_addLeft($this->getLayout()->createBlock('Mage_Adminhtml_Block_Api_User_Edit_Tabs')); - - $this->_addJs($this->getLayout() - ->createBlock('Mage_Adminhtml_Block_Template') - ->setTemplate('api/user_roles_grid_js.phtml') - ); - $this->renderLayout(); - } - - public function saveAction() - { - if ($data = $this->getRequest()->getPost()) { - $id = $this->getRequest()->getPost('user_id', false); - $model = Mage::getModel('Mage_Api_Model_User')->load($id); - if (!$model->getId() && $id) { - Mage::getSingleton('Mage_Adminhtml_Model_Session')->addError($this->__('This user no longer exists.')); - $this->_redirect('*/*/'); - return; - } - $model->setData($data); - try { - $model->save(); - if ( $uRoles = $this->getRequest()->getParam('roles', false) ) { - /*parse_str($uRoles, $uRoles); - $uRoles = array_keys($uRoles);*/ - if ( 1 == sizeof($uRoles) ) { - $model->setRoleIds($uRoles) - ->setRoleUserId($model->getUserId()) - ->saveRelations(); - } else if ( sizeof($uRoles) > 1 ) { - //@FIXME: stupid fix of previous multi-roles logic. - //@TODO: make proper DB upgrade in the future revisions. - $rs = array(); - $rs[0] = $uRoles[0]; - $model->setRoleIds( $rs )->setRoleUserId( $model->getUserId() )->saveRelations(); - } - } - Mage::getSingleton('Mage_Adminhtml_Model_Session')->addSuccess($this->__('The user has been saved.')); - Mage::getSingleton('Mage_Adminhtml_Model_Session')->setUserData(false); - $this->_redirect('*/*/edit', array('user_id' => $model->getUserId())); - return; - } catch (Exception $e) { - Mage::getSingleton('Mage_Adminhtml_Model_Session')->addError($e->getMessage()); - Mage::getSingleton('Mage_Adminhtml_Model_Session')->setUserData($data); - $this->_redirect('*/*/edit', array('user_id' => $model->getUserId())); - return; - } - } - $this->_redirect('*/*/'); - } - - public function deleteAction() - { - if ($id = $this->getRequest()->getParam('user_id')) { - - try { - $model = Mage::getModel('Mage_Api_Model_User')->load($id); - $model->delete(); - Mage::getSingleton('Mage_Adminhtml_Model_Session')->addSuccess($this->__('The user has been deleted.')); - $this->_redirect('*/*/'); - return; - } - catch (Exception $e) { - Mage::getSingleton('Mage_Adminhtml_Model_Session')->addError($e->getMessage()); - $this->_redirect('*/*/edit', array('user_id' => $this->getRequest()->getParam('user_id'))); - return; - } - } - Mage::getSingleton('Mage_Adminhtml_Model_Session')->addError($this->__('Unable to find a user to delete.')); - $this->_redirect('*/*/'); - } - - public function rolesGridAction() - { - $id = $this->getRequest()->getParam('user_id'); - $model = Mage::getModel('Mage_Api_Model_User'); - - if ($id) { - $model->load($id); - } - - Mage::register('api_user', $model); - $this->getResponse()->setBody( - $this->getLayout()->createBlock('Mage_Adminhtml_Block_Api_User_Edit_Tab_Roles')->toHtml() - ); - } - - public function roleGridAction() - { - $this->getResponse() - ->setBody($this->getLayout() - ->createBlock('Mage_Adminhtml_Block_Api_User_Grid') - ->toHtml() - ); - } - - protected function _isAllowed() - { - return Mage::getSingleton('Mage_Core_Model_Authorization')->isAllowed('Mage_Api::users'); - } - -} diff --git a/app/code/core/Mage/Adminhtml/controllers/CustomerController.php b/app/code/core/Mage/Adminhtml/controllers/CustomerController.php index 16da2fbc8e2a0330525b9afa4bf94eed2daf0475..efee4a08e9022fffa70521bd23fc3ac8ae73ffad 100644 --- a/app/code/core/Mage/Adminhtml/controllers/CustomerController.php +++ b/app/code/core/Mage/Adminhtml/controllers/CustomerController.php @@ -1,5 +1,7 @@ <?php /** + * Customer admin controller + * * Magento * * NOTICE OF LICENSE @@ -18,29 +20,29 @@ * versions in the future. If you wish to customize Magento for your * needs please refer to http://www.magentocommerce.com for more information. * - * @category Mage - * @package Mage_Adminhtml * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ - -/** - * Customer admin controller - * - * @category Mage - * @package Mage_Adminhtml - * @author Magento Core Team <core@magentocommerce.com> - */ class Mage_Adminhtml_CustomerController extends Mage_Adminhtml_Controller_Action { + /** + * @var Magento_Validator + */ + protected $_validator; + /** + * Customer initialization + * + * @param string $idFieldName + * @return Mage_Adminhtml_CustomerController + */ protected function _initCustomer($idFieldName = 'id') { + // Default title $this->_title($this->__('Customers'))->_title($this->__('Manage Customers')); - $customerId = (int) $this->getRequest()->getParam($idFieldName); + $customerId = (int)$this->getRequest()->getParam($idFieldName); $customer = Mage::getModel('Mage_Customer_Model_Customer'); - if ($customerId) { $customer->load($customerId); } @@ -77,12 +79,17 @@ class Mage_Adminhtml_CustomerController extends Mage_Adminhtml_Controller_Action /** * Add breadcrumb item */ - $this->_addBreadcrumb(Mage::helper('Mage_Adminhtml_Helper_Data')->__('Customers'), Mage::helper('Mage_Adminhtml_Helper_Data')->__('Customers')); - $this->_addBreadcrumb(Mage::helper('Mage_Adminhtml_Helper_Data')->__('Manage Customers'), Mage::helper('Mage_Adminhtml_Helper_Data')->__('Manage Customers')); + $this->_addBreadcrumb(Mage::helper('Mage_Adminhtml_Helper_Data')->__('Customers'), + Mage::helper('Mage_Adminhtml_Helper_Data')->__('Customers')); + $this->_addBreadcrumb(Mage::helper('Mage_Adminhtml_Helper_Data')->__('Manage Customers'), + Mage::helper('Mage_Adminhtml_Helper_Data')->__('Manage Customers')); $this->renderLayout(); } + /** + * Customer grid action + */ public function gridAction() { $this->loadLayout(); @@ -168,12 +175,12 @@ class Mage_Adminhtml_CustomerController extends Mage_Adminhtml_Controller_Action $customer = Mage::registry('current_customer'); if ($customer->getId()) { try { - $customer->load($customer->getId()); $customer->delete(); - Mage::getSingleton('Mage_Adminhtml_Model_Session')->addSuccess(Mage::helper('Mage_Adminhtml_Helper_Data')->__('The customer has been deleted.')); + $this->_getSession()->addSuccess( + Mage::helper('Mage_Adminhtml_Helper_Data')->__('The customer has been deleted.')); } - catch (Exception $e){ - Mage::getSingleton('Mage_Adminhtml_Model_Session')->addError($e->getMessage()); + catch (Exception $exception){ + $this->_getSession()->addError($exception->getMessage()); } } $this->_redirect('*/customer'); @@ -184,191 +191,198 @@ class Mage_Adminhtml_CustomerController extends Mage_Adminhtml_Controller_Action */ public function saveAction() { - $data = $this->getRequest()->getPost(); - if ($data) { - $redirectBack = $this->getRequest()->getParam('back', false); - $this->_initCustomer('customer_id'); - - /** @var $customer Mage_Customer_Model_Customer */ - $customer = Mage::registry('current_customer'); - - /** @var $customerForm Mage_Customer_Model_Form */ - $customerForm = Mage::getModel('Mage_Customer_Model_Form'); - $customerForm->setEntity($customer) - ->setFormCode('adminhtml_customer') - ->ignoreInvisible(false) - ; - - $formData = $customerForm->extractData($this->getRequest(), 'account'); - - // Handle 'disable auto_group_change' attribute - if (isset($formData['disable_auto_group_change'])) { - $formData['disable_auto_group_change'] = empty($formData['disable_auto_group_change']) ? '0' : '1'; - } + /** @var Mage_Customer_Model_Customer $customer */ + $customer = null; + $returnToEdit = false; + $customerId = (int)$this->getRequest()->getPost('customer_id'); + $originalRequestData = $this->getRequest()->getPost(); + if ($originalRequestData) { + try { + // optional fields might be set in request for future processing by observers in other modules + $accountData = $this->_extractCustomerData(); + $addressesData = $this->_extractCustomerAddressData(); + + $request = $this->getRequest(); + /** @var Mage_Core_Model_Event_Manager $eventManager */ + $eventManager = $this->_objectManager->get('Mage_Core_Model_Event_Manager'); + $beforeSaveCallback = function ($customer) use ($request, $eventManager) { + $eventManager->dispatch('adminhtml_customer_prepare_save', array( + 'customer' => $customer, + 'request' => $request + )); + }; + $afterSaveCallback = function ($customer) use ($request, $eventManager) { + $eventManager->dispatch('adminhtml_customer_save_after', array( + 'customer' => $customer, + 'request' => $request + )); + }; + + /** @var Mage_Customer_Service_Customer $customerService */ + $customerService = $this->_objectManager->get('Mage_Customer_Service_Customer'); + $customerService->setIsAdminStore(true); + $customerService->setBeforeSaveCallback($beforeSaveCallback); + $customerService->setAfterSaveCallback($afterSaveCallback); + if ($customerId) { + $customer = $customerService->update($customerId, $accountData, $addressesData); + } else { + $customer = $customerService->create($accountData, $addressesData); + } - $errors = $customerForm->validateData($formData); - if ($errors !== true) { - foreach ($errors as $error) { - $this->_getSession()->addError($error); + $this->_objectManager->get('Mage_Core_Model_Registry')->register('current_customer', $customer); + $this->_getSession()->addSuccess($this->_getHelper()->__('The customer has been saved.')); + + $returnToEdit = (bool)$this->getRequest()->getParam('back', false); + $customerId = $customer->getId(); + } catch (Magento_Validator_Exception $exception) { + $this->_addSessionErrorMessages($exception->getMessages()); + $this->_getSession()->setCustomerData($originalRequestData); + $returnToEdit = true; + } catch (Mage_Core_Exception $exception) { + $messages = $exception->getMessages(Mage_Core_Model_Message::ERROR); + if (!count($messages)) { + $messages = $exception->getMessage(); } - $this->_getSession()->setCustomerData($data); - $this->getResponse()->setRedirect($this->getUrl('*/customer/edit', array('id' => $customer->getId()))); - return; + $this->_addSessionErrorMessages($messages); + $this->_getSession()->setCustomerData($originalRequestData); + $returnToEdit = true; + } catch (Exception $exception) { + $this->_getSession()->addException($exception, + $this->_getHelper()->__('An error occurred while saving the customer.')); + $this->_getSession()->setCustomerData($originalRequestData); + $returnToEdit = true; } + } - $customerForm->compactData($formData); - - // Unset template data - if (isset($data['address']['_template_'])) { - unset($data['address']['_template_']); + if ($returnToEdit) { + if ($customerId) { + $this->_redirect('*/*/edit', array('id' => $customerId, '_current' => true)); + } else { + $this->_redirect('*/*/new', array('_current' => true)); } + } else { + $this->_redirect('*/customer'); + } + } - $modifiedAddresses = array(); - if (!empty($data['address'])) { - /** @var $addressForm Mage_Customer_Model_Form */ - $addressForm = Mage::getModel('Mage_Customer_Model_Form'); - $addressForm->setFormCode('adminhtml_customer_address')->ignoreInvisible(false); + /** + * Add errors messages to session. + * + * @param array|string $messages + */ + protected function _addSessionErrorMessages($messages) + { + $messages = (array)$messages; + $session = $this->_getSession(); - foreach (array_keys($data['address']) as $index) { - $address = $customer->getAddressItemById($index); - if (!$address) { - $address = Mage::getModel('Mage_Customer_Model_Address'); - } + $callback = function ($error) use ($session) { + if (!($error instanceof Mage_Core_Model_Message_Error)) { + $error = new Mage_Core_Model_Message_Error($error); + } + $session->addMessage($error); + }; + array_walk_recursive($messages, $callback); + } - $requestScope = sprintf('address/%s', $index); - $formData = $addressForm->setEntity($address) - ->extractData($this->getRequest(), $requestScope); - - // Set default billing and shipping flags to address - $isDefaultBilling = isset($data['account']['default_billing']) - && $data['account']['default_billing'] == $index; - $address->setIsDefaultBilling($isDefaultBilling); - $isDefaultShipping = isset($data['account']['default_shipping']) - && $data['account']['default_shipping'] == $index; - $address->setIsDefaultShipping($isDefaultShipping); - - $errors = $addressForm->validateData($formData); - if ($errors !== true) { - foreach ($errors as $error) { - $this->_getSession()->addError($error); - } - $this->_getSession()->setCustomerData($data); - $this->getResponse()->setRedirect($this->getUrl('*/customer/edit', array( - 'id' => $customer->getId()) - )); - return; - } + /** + * Reformat customer account data to be compatible with customer service interface + * + * @return array + */ + protected function _extractCustomerData() + { + $customerData = array(); + if ($this->getRequest()->getPost('account')) { + $serviceAttributes = array( + 'password', 'new_password', 'default_billing', 'default_shipping', 'confirmation'); + + /** @var Mage_Customer_Model_Customer $customerEntity */ + $customerEntity = $this->_objectManager + ->get('Mage_Customer_Model_Customer_Factory') + ->create(); + /** @var Mage_Customer_Helper_Data $customerHelper */ + $customerHelper = $this->_objectManager->get('Mage_Customer_Helper_Data'); + $customerData = $customerHelper->extractCustomerData( + $this->getRequest(), 'adminhtml_customer', $customerEntity, $serviceAttributes, 'account'); + } - $addressForm->compactData($formData); + $this->_processCustomerPassword($customerData); + /** @var Mage_Core_Model_Authorization $acl */ + $acl = $this->_objectManager->get('Mage_Core_Model_Authorization'); + if ($acl->isAllowed(Mage_Backend_Model_Acl_Config::ACL_RESOURCE_ALL)) { + $customerData['is_subscribed'] = (bool)$this->getRequest()->getPost('subscription', false); + } - // Set post_index for detect default billing and shipping addresses - $address->setPostIndex($index); + if (isset($customerData['disable_auto_group_change'])) { + $customerData['disable_auto_group_change'] = empty($customerData['disable_auto_group_change']) ? '0' : '1'; + } - if ($address->getId()) { - $modifiedAddresses[] = $address->getId(); - } else { - $customer->addAddress($address); - } - } - } + return $customerData; + } - // Default billing and shipping - if (isset($data['account']['default_billing'])) { - $customer->setData('default_billing', $data['account']['default_billing']); - } - if (isset($data['account']['default_shipping'])) { - $customer->setData('default_shipping', $data['account']['default_shipping']); - } - if (isset($data['account']['confirmation'])) { - $customer->setData('confirmation', $data['account']['confirmation']); + /** + * Reformat customer addresses data to be compatible with customer service interface + * + * @return array + */ + protected function _extractCustomerAddressData() + { + $addresses = $this->getRequest()->getPost('address'); + $customerData = $this->getRequest()->getPost('account'); + $result = array(); + if ($addresses) { + if (isset($addresses['_template_'])) { + unset($addresses['_template_']); } - // Mark not modified customer addresses for delete - foreach ($customer->getAddressesCollection() as $customerAddress) { - if ($customerAddress->getId() && !in_array($customerAddress->getId(), $modifiedAddresses)) { - $customerAddress->setData('_deleted', true); + /** @var Mage_Customer_Model_Address_Form $eavForm */ + $eavForm = $this->_objectManager->create('Mage_Customer_Model_Address_Form'); + /** @var Mage_Customer_Model_Address $addressEntity */ + $addressEntity = $this->_objectManager + ->get('Mage_Customer_Model_Address_Factory') + ->create(); + + $addressIdList = array_keys($addresses); + /** @var Mage_Customer_Helper_Data $customerHelper */ + $customerHelper = $this->_objectManager->get('Mage_Customer_Helper_Data'); + foreach ($addressIdList as $addressId) { + $scope = sprintf('address/%s', $addressId); + $addressData = $customerHelper->extractCustomerData( + $this->getRequest(), 'adminhtml_customer_address', $addressEntity, array(), $scope, $eavForm); + if (is_numeric($addressId)) { + $addressData['entity_id'] = $addressId; } + // Set default billing and shipping flags to address + $addressData['is_default_billing'] = isset($customerData['default_billing']) + && $customerData['default_billing'] + && $customerData['default_billing'] == $addressId; + $addressData['is_default_shipping'] = isset($customerData['default_shipping']) + && $customerData['default_shipping'] + && $customerData['default_shipping'] == $addressId; + + $result[] = $addressData; } + } - if (Mage::getSingleton('Mage_Core_Model_Authorization') - ->isAllowed(Mage_Backend_Model_Acl_Config::ACL_RESOURCE_ALL) - && !$customer->getConfirmation() - ) { - $customer->setIsSubscribed(isset($data['subscription'])); - } - - if (isset($data['account']['sendemail_store_id'])) { - $customer->setSendemailStoreId($data['account']['sendemail_store_id']); - } - - $isNewCustomer = $customer->isObjectNew(); - try { - $sendPassToEmail = false; - // Force new customer confirmation - if ($isNewCustomer) { - $customer->setPassword($data['account']['password']); - $customer->setForceConfirmed(true); - if ($customer->getPassword() == 'auto') { - $sendPassToEmail = true; - $customer->setPassword($customer->generatePassword()); - } - } - - Mage::dispatchEvent('adminhtml_customer_prepare_save', array( - 'customer' => $customer, - 'request' => $this->getRequest() - )); - - $customer->save(); - - // Send welcome email - if ($customer->getWebsiteId() && (isset($data['account']['sendemail']) || $sendPassToEmail)) { - $storeId = $customer->getSendemailStoreId(); - if ($isNewCustomer) { - $customer->sendNewAccountEmail('registered', '', $storeId); - } elseif ((!$customer->getConfirmation())) { - // Confirm not confirmed customer - $customer->sendNewAccountEmail('confirmed', '', $storeId); - } - } - - if (!empty($data['account']['new_password'])) { - $newPassword = $data['account']['new_password']; - if ($newPassword == 'auto') { - $newPassword = $customer->generatePassword(); - } - $customer->changePassword($newPassword); - $customer->sendPasswordReminderEmail(); - } + return $result; + } - Mage::getSingleton('Mage_Adminhtml_Model_Session')->addSuccess( - Mage::helper('Mage_Adminhtml_Helper_Data')->__('The customer has been saved.') - ); - Mage::dispatchEvent('adminhtml_customer_save_after', array( - 'customer' => $customer, - 'request' => $this->getRequest() - )); - - if ($redirectBack) { - $this->_redirect('*/*/edit', array( - 'id' => $customer->getId(), - '_current' => true - )); - return; - } - } catch (Mage_Core_Exception $e) { - $this->_getSession()->addError($e->getMessage()); - $this->_getSession()->setCustomerData($data); - $this->getResponse()->setRedirect($this->getUrl('*/customer/edit', array('id' => $customer->getId()))); - } catch (Exception $e) { - $this->_getSession()->addException($e, - Mage::helper('Mage_Adminhtml_Helper_Data')->__('An error occurred while saving the customer.')); - $this->_getSession()->setCustomerData($data); - $this->getResponse()->setRedirect($this->getUrl('*/customer/edit', array('id'=>$customer->getId()))); - return; - } + /** + * Generate password if auto generated password was requested + * + * @param array $customerData + * @throws Mage_Core_Exception + */ + protected function _processCustomerPassword(&$customerData) + { + if (isset($customerData['new_password']) && $customerData['new_password'] !== false) { + $customerData['password'] = $customerData['new_password']; + unset($customerData['new_password']); + } + if (isset($customerData['password']) && ($customerData['password'] == 'auto')) { + unset($customerData['password']); + $customerData['autogenerate_password'] = true; } - $this->getResponse()->setRedirect($this->getUrl('*/customer')); } /** @@ -376,9 +390,8 @@ class Mage_Adminhtml_CustomerController extends Mage_Adminhtml_Controller_Action */ public function exportCsvAction() { - $fileName = 'customers.csv'; - $content = $this->getLayout()->createBlock('Mage_Adminhtml_Block_Customer_Grid') - ->getCsvFile(); + $fileName = 'customers.csv'; + $content = $this->getLayout()->createBlock('Mage_Adminhtml_Block_Customer_Grid')->getCsvFile(); $this->_prepareDownloadResponse($fileName, $content); } @@ -440,8 +453,8 @@ class Mage_Adminhtml_CustomerController extends Mage_Adminhtml_Controller_Action Mage::getModel('Mage_Wishlist_Model_Item')->load($itemId) ->delete(); } - catch (Exception $e) { - Mage::logException($e); + catch (Exception $exception) { + Mage::logException($exception); } } } @@ -499,7 +512,7 @@ class Mage_Adminhtml_CustomerController extends Mage_Adminhtml_Controller_Action public function viewCartAction() { $this->_initCustomer(); - $layout = $this->loadLayout() + $this->loadLayout() ->getLayout() ->getBlock('admin.customer.view.cart') ->setWebsiteId((int)$this->getRequest()->getParam('website_id')); @@ -532,54 +545,93 @@ class Mage_Adminhtml_CustomerController extends Mage_Adminhtml_Controller_Action $this->renderLayout(); } + /** + * AJAX customer validation action + */ public function validateAction() { - $response = new Varien_Object(); + $response = new Varien_Object(); $response->setError(0); - $websiteId = Mage::app()->getStore()->getWebsiteId(); - $accountData = $this->getRequest()->getPost('account'); - $customer = Mage::getModel('Mage_Customer_Model_Customer'); - $customerId = $this->getRequest()->getParam('id'); - if ($customerId) { - $customer->load($customerId); - $websiteId = $customer->getWebsiteId(); - } else if (isset($accountData['website_id'])) { - $websiteId = $accountData['website_id']; + $customer = $this->_validateCustomer($response); + if ($customer) { + $this->_validateCustomerAddress($response, $customer); } - /* @var $customerForm Mage_Customer_Model_Form */ - $customerForm = Mage::getModel('Mage_Customer_Model_Form'); - $customerForm->setEntity($customer) - ->setFormCode('adminhtml_customer') - ->setIsAjaxRequest(true) - ->ignoreInvisible(false) - ; - - $data = $customerForm->extractData($this->getRequest(), 'account'); - $errors = $customerForm->validateData($data); - if ($errors !== true) { + if ($response->getError()) { + $this->_initLayoutMessages('Mage_Adminhtml_Model_Session'); + $response->setMessage($this->getLayout()->getMessagesBlock()->getGroupedHtml()); + } + + $this->getResponse()->setBody($response->toJson()); + } + + /** + * Customer validation + * + * @param Varien_Object $response + * @return Mage_Customer_Model_Customer|null + */ + protected function _validateCustomer($response) + { + $customer = null; + $errors = null; + + try { + /** @var Mage_Customer_Model_Customer $customer */ + $customer = $this->_objectManager->create('Mage_Customer_Model_Customer'); + $customerId = $this->getRequest()->getParam('id'); + if ($customerId) { + $customer->load($customerId); + } + + /* @var $customerForm Mage_Customer_Model_Form */ + $customerForm = $this->_objectManager->get('Mage_Customer_Model_Form'); + $customerForm->setEntity($customer) + ->setFormCode('adminhtml_customer') + ->setIsAjaxRequest(true) + ->ignoreInvisible(false); + $data = $customerForm->extractData($this->getRequest(), 'account'); + $accountData = $this->getRequest()->getPost('account'); + $this->_processCustomerPassword($accountData); + if (isset($accountData['autogenerate_password'])) { + $data['password'] = $customer->generatePassword(); + } else { + $data['password'] = $accountData['password']; + } + $data['confirmation'] = $data['password']; + + if ($customer->getWebsiteId()) { + unset($data['website_id']); + } + + $customer->addData($data); + $errors = $customer->validate(); + } catch (Mage_Core_Exception $exception) { + /* @var $error Mage_Core_Model_Message_Error */ + foreach ($exception->getMessages(Mage_Core_Model_Message::ERROR) as $error) { + $errors[] = $error->getCode(); + } + } + + if ($errors !== true && !empty($errors)) { foreach ($errors as $error) { $this->_getSession()->addError($error); } $response->setError(1); } - # additional validate email - if (!$response->getError()) { - # Trying to load customer with the same email and return error message - # if customer with the same email address exisits - $checkCustomer = Mage::getModel('Mage_Customer_Model_Customer') - ->setWebsiteId($websiteId); - $checkCustomer->loadByEmail($accountData['email']); - if ($checkCustomer->getId() && ($checkCustomer->getId() != $customer->getId())) { - $response->setError(1); - $this->_getSession()->addError( - Mage::helper('Mage_Adminhtml_Helper_Data')->__('Customer with the same email already exists.') - ); - } - } + return $customer; + } + /** + * Customer address validation. + * + * @param Varien_Object $response + * @param Mage_Customer_Model_Customer $customer + */ + protected function _validateCustomerAddress($response, $customer) + { $addressesData = $this->getRequest()->getParam('address'); if (is_array($addressesData)) { /* @var $addressForm Mage_Customer_Model_Form */ @@ -607,21 +659,16 @@ class Mage_Adminhtml_CustomerController extends Mage_Adminhtml_Controller_Action } } } - - if ($response->getError()) { - $this->_initLayoutMessages('Mage_Adminhtml_Model_Session'); - $response->setMessage($this->getLayout()->getMessagesBlock()->getGroupedHtml()); - } - - $this->getResponse()->setBody($response->toJson()); } + /** + * Customer mass subscribe action + */ public function massSubscribeAction() { $customersIds = $this->getRequest()->getParam('customer'); if(!is_array($customersIds)) { Mage::getSingleton('Mage_Adminhtml_Model_Session')->addError(Mage::helper('Mage_Adminhtml_Helper_Data')->__('Please select customer(s).')); - } else { try { foreach ($customersIds as $customerId) { @@ -632,13 +679,16 @@ class Mage_Adminhtml_CustomerController extends Mage_Adminhtml_Controller_Action Mage::getSingleton('Mage_Adminhtml_Model_Session')->addSuccess( Mage::helper('Mage_Adminhtml_Helper_Data')->__('Total of %d record(s) were updated.', count($customersIds)) ); - } catch (Exception $e) { - Mage::getSingleton('Mage_Adminhtml_Model_Session')->addError($e->getMessage()); + } catch (Exception $exception) { + Mage::getSingleton('Mage_Adminhtml_Model_Session')->addError($exception->getMessage()); } } $this->_redirect('*/*/index'); } + /** + * Customer mass unsubscribe action + */ public function massUnsubscribeAction() { $customersIds = $this->getRequest()->getParam('customer'); @@ -654,14 +704,17 @@ class Mage_Adminhtml_CustomerController extends Mage_Adminhtml_Controller_Action Mage::getSingleton('Mage_Adminhtml_Model_Session')->addSuccess( Mage::helper('Mage_Adminhtml_Helper_Data')->__('Total of %d record(s) were updated.', count($customersIds)) ); - } catch (Exception $e) { - Mage::getSingleton('Mage_Adminhtml_Model_Session')->addError($e->getMessage()); + } catch (Exception $exception) { + Mage::getSingleton('Mage_Adminhtml_Model_Session')->addError($exception->getMessage()); } } $this->_redirect('*/*/index'); } + /** + * Customer mass delete action + */ public function massDeleteAction() { $customersIds = $this->getRequest()->getParam('customer'); @@ -678,14 +731,17 @@ class Mage_Adminhtml_CustomerController extends Mage_Adminhtml_Controller_Action Mage::getSingleton('Mage_Adminhtml_Model_Session')->addSuccess( Mage::helper('Mage_Adminhtml_Helper_Data')->__('Total of %d record(s) were deleted.', count($customersIds)) ); - } catch (Exception $e) { - Mage::getSingleton('Mage_Adminhtml_Model_Session')->addError($e->getMessage()); + } catch (Exception $exception) { + Mage::getSingleton('Mage_Adminhtml_Model_Session')->addError($exception->getMessage()); } } $this->_redirect('*/*/index'); } + /** + * Customer mass assign group action + */ public function massAssignGroupAction() { $customersIds = $this->getRequest()->getParam('customer'); @@ -701,14 +757,17 @@ class Mage_Adminhtml_CustomerController extends Mage_Adminhtml_Controller_Action Mage::getSingleton('Mage_Adminhtml_Model_Session')->addSuccess( Mage::helper('Mage_Adminhtml_Helper_Data')->__('Total of %d record(s) were updated.', count($customersIds)) ); - } catch (Exception $e) { - Mage::getSingleton('Mage_Adminhtml_Model_Session')->addError($e->getMessage()); + } catch (Exception $exception) { + Mage::getSingleton('Mage_Adminhtml_Model_Session')->addError($exception->getMessage()); } } $this->_redirect('*/*/index'); } + /** + * Customer view file action + */ public function viewfileAction() { $file = null; @@ -781,6 +840,10 @@ class Mage_Adminhtml_CustomerController extends Mage_Adminhtml_Controller_Action exit(); } + /** + * Customer access rights checking + * @return bool + */ protected function _isAllowed() { return Mage::getSingleton('Mage_Core_Model_Authorization')->isAllowed('Mage_Customer::manage'); diff --git a/app/code/core/Mage/Adminhtml/controllers/Sales/Order/CreditmemoController.php b/app/code/core/Mage/Adminhtml/controllers/Sales/Order/CreditmemoController.php index 3bbee3200131785d53bf3edf13aaf159fe753bfb..127ff0f4c11205479b1cfed701d081df61dc1891 100644 --- a/app/code/core/Mage/Adminhtml/controllers/Sales/Order/CreditmemoController.php +++ b/app/code/core/Mage/Adminhtml/controllers/Sales/Order/CreditmemoController.php @@ -149,7 +149,9 @@ class Mage_Adminhtml_Sales_Order_CreditmemoController extends Mage_Adminhtml_Con } elseif ($orderItem->getParentItem() && isset($backToStock[$parentId]) && $backToStock[$parentId]) { $creditmemoItem->setBackToStock(true); } elseif (empty($savedData)) { - $creditmemoItem->setBackToStock(Mage::helper('Mage_CatalogInventory_Helper_Data')->isAutoReturnEnabled()); + $creditmemoItem->setBackToStock( + Mage::helper('Mage_CatalogInventory_Helper_Data')->isAutoReturnEnabled() + ); } else { $creditmemoItem->setBackToStock(false); } @@ -387,12 +389,12 @@ class Mage_Adminhtml_Sales_Order_CreditmemoController extends Mage_Adminhtml_Con Mage::throwException($this->__('The Comment Text field cannot be empty.')); } $creditmemo = $this->_initCreditmemo(); - $creditmemo->addComment( + $comment = $creditmemo->addComment( $data['comment'], isset($data['is_customer_notified']), isset($data['is_visible_on_front']) ); - $creditmemo->save(); + $comment->save(); $creditmemo->sendUpdateEmail(!empty($data['is_customer_notified']), $data['comment']); $this->loadLayout(); diff --git a/app/code/core/Mage/Adminhtml/view/adminhtml/api/roleinfo.phtml b/app/code/core/Mage/Adminhtml/view/adminhtml/api/roleinfo.phtml deleted file mode 100644 index 1316df7665bf147b0a4f8ebece5dc0c902a96246..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Adminhtml/view/adminhtml/api/roleinfo.phtml +++ /dev/null @@ -1,47 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Academic Free License (AFL 3.0) - * that is bundled with this package in the file LICENSE_AFL.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/afl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category design - * @package default_default - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) - */ -/** @var $this Mage_Adminhtml_Block_Api_Tab_Roleinfo */ - -?> -<div class="content-header"> - <table cellspacing="0"> - <tr> - <td style="width:50%;"><h3 class="icon-head head-permissions-role"><?php echo ($this->getRoleId() > 0 ) ? ($this->__('Edit Role') . " '{$this->escapeHtml($this->getRoleInfo()->getRoleName())}'") : $this->__('Add New Role') ?></h3></td> - <td class="form-buttons"> - <?php echo $this->getBackButtonHtml() ?> - <?php echo $this->getResetButtonHtml() ?> - <?php echo $this->getDeleteButtonHtml() ?> - <?php echo $this->getSaveButtonHtml() ?> - </td> - </tr> - </table> -</div> -<form action="<?php echo $this->getUrl('*/*/saverole') ?>" method="post" id="role-edit-form"> - <?php echo $this->getBlockHtml('formkey')?> -</form> -<script type="text/javascript"> - jQuery('#role-edit-form').form().validation(); -</script> diff --git a/app/code/core/Mage/Adminhtml/view/adminhtml/api/roles.phtml b/app/code/core/Mage/Adminhtml/view/adminhtml/api/roles.phtml deleted file mode 100644 index 5e1ba95a03cbd2407088f66590e9493dc0510628..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Adminhtml/view/adminhtml/api/roles.phtml +++ /dev/null @@ -1,37 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Academic Free License (AFL 3.0) - * that is bundled with this package in the file LICENSE_AFL.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/afl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category design - * @package default_default - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) - */ -?> -<div class="content-header"> - <table cellspacing="0"> - <tr> - <td style="width:50%;"><h3 class="icon-head head-permissions-role"><?php echo $this->__('Roles') ?></h3></td> - <td class="form-buttons"> - <button class="scalable add" onclick="window.location='<?php echo $this->getAddNewUrl() ?>'"><span><span><span><?php echo $this->__('Add New Role') ?></span></span></span></button> - </td> - </tr> - </table> -</div> -<?php echo $this->getGridHtml() ?> diff --git a/app/code/core/Mage/Adminhtml/view/adminhtml/api/user_roles_grid_js.phtml b/app/code/core/Mage/Adminhtml/view/adminhtml/api/user_roles_grid_js.phtml deleted file mode 100644 index 312a049b25142ff97199370eaf9f2971db9836d8..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Adminhtml/view/adminhtml/api/user_roles_grid_js.phtml +++ /dev/null @@ -1,85 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Academic Free License (AFL 3.0) - * that is bundled with this package in the file LICENSE_AFL.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/afl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category design - * @package default_default - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) - */ -?> -<script type="text/javascript"> -<!-- -<?php $myBlock = $this->getLayout()->getBlock('user.roles.grid'); ?> -<?php if( is_object($myBlock) && $myBlock->getJsObjectName()): ?> - var radioBoxes = $H({}); - var warning = false; - var userRoles = $H(<?php echo $myBlock->_getSelectedRoles(true) ?>); - if (userRoles.size() > 0) warning = true; - $('user_user_roles').value = userRoles.toQueryString(); - - function registerUserRole(grid, element, checked){ - if(checked){ - userRoles.each(function(o){userRoles.remove(o[0]);}); - userRoles[element.value] = 0; - } else { - userRoles.remove(element.value); - } - $('user_user_roles').value = userRoles.toQueryString(); - grid.reloadParams = {'user_roles[]':userRoles.keys()}; - } - - function roleRowClick(grid, event){ - var trElement = Event.findElement(event, 'tr'); - var isInput = Event.element(event).tagName == 'INPUT'; - if(trElement){ - var checkbox = Element.getElementsBySelector(trElement, 'input'); - if(checkbox[0] && !checkbox[0].checked){ - var checked = isInput ? checkbox[0].checked : !checkbox[0].checked; - if (checked && warning && radioBoxes.size() > 0) { - if ( !confirm("<?php echo $this->__('Warning!\r\nThis action will remove this user from already assigned role\r\nAre you sure?') ?>") ) { - checkbox[0].checked = false; - for(i in radioBoxes) { - if( radioBoxes[i].status == 1) { - radioBoxes[i].object.checked = true; - } - } - return false; - } - warning = false; - } - <?php echo $myBlock->getJsObjectName() ?>.setCheckboxChecked(checkbox[0], checked); - } - } - } - - function rolesRowInit(grid, row){ - var checkbox = $(row).getElementsByClassName('radio')[0]; - if (checkbox) { - radioBoxes[checkbox.value] = {'status' : ((checkbox.checked) ? 1 : 0), 'object' : checkbox}; - } - } - -<?php echo $myBlock->getJsObjectName() ?>.rowClickCallback = roleRowClick; -<?php echo $myBlock->getJsObjectName() ?>.initRowCallback = rolesRowInit; -<?php echo $myBlock->getJsObjectName() ?>.checkboxCheckCallback = registerUserRole; -<?php echo $myBlock->getJsObjectName() ?>.rows.each(function(row){rolesRowInit(<?php echo $myBlock->getJsObjectName() ?>, row)}); -<?php endif; ?> -//--> -</script> diff --git a/app/code/core/Mage/Adminhtml/view/adminhtml/api/userinfo.phtml b/app/code/core/Mage/Adminhtml/view/adminhtml/api/userinfo.phtml deleted file mode 100644 index a4a595a208316a7b8f8e59ebe0144320ac4f0ce1..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Adminhtml/view/adminhtml/api/userinfo.phtml +++ /dev/null @@ -1,52 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Academic Free License (AFL 3.0) - * that is bundled with this package in the file LICENSE_AFL.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/afl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category design - * @package default_default - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) - */ -?> -<div class="content-header"> - <table cellspacing="0"> - <tr> - <td style="width:50%;"> - <h3> - <?php if($this->getUser()->getUserId()): ?> - <?php $_userName = $this->getUser()->getFirstname() . ' ' . $this->getUser()->getLastname() ?> - <?php echo $this->__("Edit User '%s'", $_userName) ?> - <?php else: ?> - <?php echo $this->__('Add New User') ?> - <?php endif; ?> - </h3> - </td> - <td class="form-buttons"> - <?php echo $this->getBackButtonHtml() ?> - <?php echo $this->getResetButtonHtml() ?> - <?php echo $this->getDeleteButtonHtml() ?> - <?php echo $this->getSaveButtonHtml() ?> - </table> -</div> -<form action="<?php echo $this->getUrl('*/*/saveuser') ?>" method="post" id="user-edit-form"> - <?php echo $this->getBlockHtml('formkey')?> -</form> -<script type="text/javascript"> - jQuery('#user-edit-form').form().validation(); -</script> diff --git a/app/code/core/Mage/Adminhtml/view/adminhtml/api/usernroles.phtml b/app/code/core/Mage/Adminhtml/view/adminhtml/api/usernroles.phtml deleted file mode 100644 index 3180c5a26ff14a5d2214c7def62779677e6925f5..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Adminhtml/view/adminhtml/api/usernroles.phtml +++ /dev/null @@ -1,31 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Academic Free License (AFL 3.0) - * that is bundled with this package in the file LICENSE_AFL.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/afl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category design - * @package default_default - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) - */ -?> -<div id="roles"> - <li class="add"><a href="<?php echo $this->getUrl('*/*/edituser') ?>"><?php echo $this->__('Add New User') ?></a></li> - <li class="add"><a href="<?php echo $this->getUrl('*/*/editroles') ?>"><?php echo $this->__('Add New Role') ?></a></li> -</div> -<div class="clear"></div> diff --git a/app/code/core/Mage/Adminhtml/view/adminhtml/system/shipping/ups.phtml b/app/code/core/Mage/Adminhtml/view/adminhtml/system/shipping/ups.phtml index edbef89483f23e4d077e75eaef4c3805f5700f76..32ecdf1fb98fa4b459940a33de361400984067d6 100644 --- a/app/code/core/Mage/Adminhtml/view/adminhtml/system/shipping/ups.phtml +++ b/app/code/core/Mage/Adminhtml/view/adminhtml/system/shipping/ups.phtml @@ -124,8 +124,7 @@ if (!$storeCode && $websiteCode) { while (freeMethod.length > 0) { freeMethod.remove(0); } - - freeMethod.insert(new Element('option', {value:''}).update('None')); + freeMethod.insert(new Element('option', {value:''}).update('<?php echo $_coreHelper->escapeHtml(Mage::helper('Mage_Shipping_Helper_Data')->__('None')); ?>')); var code, option; for (code in originShipment) { diff --git a/app/code/core/Mage/Api/Helper/Data.php b/app/code/core/Mage/Api/Helper/Data.php deleted file mode 100644 index 8d1bd3d3842678719e6daa0de92d1c55c37034b0..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api/Helper/Data.php +++ /dev/null @@ -1,338 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Web service api main helper - * - * @category Mage - * @package Mage_Api - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api_Helper_Data extends Mage_Core_Helper_Abstract -{ - const XML_PATH_API_WSI = 'api/config/compliance_wsi'; - - /** - * Method to find adapter code depending on WS-I compatibility setting - * - * @return string - */ - public function getV2AdapterCode() - { - return $this->isComplianceWSI() ? 'soap_wsi' : 'soap_v2'; - } - - /** - * @return boolean - */ - public function isComplianceWSI() - { - return Mage::getStoreConfig(self::XML_PATH_API_WSI); - } - - /** - * Go thru a WSI args array and turns it to correct state. - * - * @param Object $obj - Link to Object - * @return Object - */ - public function wsiArrayUnpacker(&$obj) - { - if (is_object($obj)) { - - $modifiedKeys = $this->clearWsiFootprints($obj); - - foreach ($obj as $key => $value) { - if (is_object($value)) { - $this->wsiArrayUnpacker($value); - } - if (is_array($value)) { - foreach ($value as &$val) { - if (is_object($val)) { - $this->wsiArrayUnpacker($val); - } - } - } - } - - foreach ($modifiedKeys as $arrKey) { - $this->associativeArrayUnpack($obj->$arrKey); - } - } - } - - /** - * Go thru an object parameters and unpak associative object to array. - * - * @param Object $obj - Link to Object - * @return Object - */ - public function v2AssociativeArrayUnpacker(&$obj) - { - if (is_object($obj) - && property_exists($obj, 'key') - && property_exists($obj, 'value') - ) { - if (count(array_keys(get_object_vars($obj))) == 2) { - $obj = array($obj->key => $obj->value); - return true; - } - } elseif (is_array($obj)) { - $arr = array(); - $needReplacement = true; - foreach ($obj as $key => &$value) { - $isAssoc = $this->v2AssociativeArrayUnpacker($value); - if ($isAssoc) { - foreach ($value as $aKey => $aVal) { - $arr[$aKey] = $aVal; - } - } else { - $needReplacement = false; - } - } - if ($needReplacement) { - $obj = $arr; - } - } elseif (is_object($obj)) { - $objectKeys = array_keys(get_object_vars($obj)); - - foreach ($objectKeys as $key) { - $this->v2AssociativeArrayUnpacker($obj->$key); - } - } - return false; - } - - /** - * Go thru mixed and turns it to a correct look. - * - * @param Mixed $mixed A link to variable that may contain associative array. - */ - public function associativeArrayUnpack(&$mixed) - { - if (is_array($mixed)) { - $tmpArr = array(); - foreach ($mixed as $key => $value) { - if (is_object($value)) { - $value = get_object_vars($value); - if (count($value) == 2 && isset($value['key']) && isset($value['value'])) { - $tmpArr[$value['key']] = $value['value']; - } - } - } - if (count($tmpArr)) { - $mixed = $tmpArr; - } - } - - if (is_object($mixed)) { - $numOfVals = count(get_object_vars($mixed)); - if ($numOfVals == 2 && isset($mixed->key) && isset($mixed->value)) { - $mixed = get_object_vars($mixed); - /* - * Processing an associative arrays. - * $mixed->key = '2'; $mixed->value = '3'; turns to array(2 => '3'); - */ - $mixed = array($mixed['key'] => $mixed['value']); - } - } - } - - /** - * Corrects data representation. - * - * @param Object $obj - Link to Object - * @return Object - */ - public function clearWsiFootprints(&$obj) - { - $modifiedKeys = array(); - - $objectKeys = array_keys(get_object_vars($obj)); - - foreach ($objectKeys as $key) { - if (is_object($obj->$key) && isset($obj->$key->complexObjectArray)) { - if (is_array($obj->$key->complexObjectArray)) { - $obj->$key = $obj->$key->complexObjectArray; - } else { // for one element array - $obj->$key = array($obj->$key->complexObjectArray); - } - $modifiedKeys[] = $key; - } - } - return $modifiedKeys; - } - - /** - * For the WSI, generates an response object. - * - * @param mixed $mixed - Link to Object - * @return mixed - */ - public function wsiArrayPacker($mixed) - { - if (is_array($mixed)) { - $arrKeys = array_keys($mixed); - $isDigit = false; - $isString = false; - foreach ($arrKeys as $key) { - if (is_int($key)) { - $isDigit = true; - break; - } - } - if ($isDigit) { - $mixed = $this->packArrayToObjec($mixed); - } else { - $mixed = (object) $mixed; - } - } - if (is_object($mixed) && isset($mixed->complexObjectArray)) { - foreach ($mixed->complexObjectArray as $k => $v) { - $mixed->complexObjectArray[$k] = $this->wsiArrayPacker($v); - } - } - return $mixed; - } - - /** - * For response to the WSI, generates an object from array. - * - * @param Array $arr - Link to Object - * @return Object - */ - public function packArrayToObjec(Array $arr) - { - $obj = new stdClass(); - $obj->complexObjectArray = $arr; - return $obj; - } - - /** - * Convert objects and arrays to array recursively - * - * @param array|object $data - * @return void - */ - public function toArray(&$data) - { - if (is_object($data)) { - $data = get_object_vars($data); - } - if (is_array($data)) { - foreach ($data as &$value) { - if (is_array($value) or is_object($value)) { - $this->toArray($value); - } - } - } - } - - /** - * Parse filters and format them to be applicable for collection filtration - * - * @param null|object|array $filters - * @param array $fieldsMap Map of field names in format: array('field_name_in_filter' => 'field_name_in_db') - * @return array - */ - public function parseFilters($filters, $fieldsMap = null) - { - // if filters are used in SOAP they must be represented in array format to be used for collection filtration - if (is_object($filters)) { - $parsedFilters = array(); - // parse simple filter - if (isset($filters->filter) && is_array($filters->filter)) { - foreach ($filters->filter as $field => $value) { - if (is_object($value) && isset($value->key) && isset($value->value)) { - $parsedFilters[$value->key] = $value->value; - } else { - $parsedFilters[$field] = $value; - } - } - } - // parse complex filter - if (isset($filters->complex_filter) && is_array($filters->complex_filter)) { - if ($this->isComplianceWSI()) { - // WS-I compliance mode - foreach ($filters->complex_filter as $fieldName => $condition) { - if (is_object($condition) && isset($condition->key) && isset($condition->value)) { - $conditionName = $condition->key; - $conditionValue = $condition->value; - $this->formatFilterConditionValue($conditionName, $conditionValue); - $parsedFilters[$fieldName] = array($conditionName => $conditionValue); - } - } - } else { - // non WS-I compliance mode - foreach ($filters->complex_filter as $value) { - if (is_object($value) && isset($value->key) && isset($value->value)) { - $fieldName = $value->key; - $condition = $value->value; - if (is_object($condition) && isset($condition->key) && isset($condition->value)) { - $this->formatFilterConditionValue($condition->key, $condition->value); - $parsedFilters[$fieldName] = array($condition->key => $condition->value); - } - } - } - } - } - $filters = $parsedFilters; - } - // make sure that method result is always array - if (!is_array($filters)) { - $filters = array(); - } - // apply fields mapping - if (isset($fieldsMap) && is_array($fieldsMap)) { - foreach ($filters as $field => $value) { - if (isset($fieldsMap[$field])) { - unset($filters[$field]); - $field = $fieldsMap[$field]; - $filters[$field] = $value; - } - } - } - return $filters; - } - - /** - * Convert condition value from the string into the array - * for the condition operators that require value to be an array. - * Condition value is changed by reference - * - * @param string $conditionOperator - * @param string $conditionValue - */ - public function formatFilterConditionValue($conditionOperator, &$conditionValue) - { - if (is_string($conditionOperator) && in_array($conditionOperator, array('in', 'nin', 'finset')) - && is_string($conditionValue) - ) { - $delimiter = ','; - $conditionValue = explode($delimiter, $conditionValue); - } - } -} diff --git a/app/code/core/Mage/Api/Model/Acl.php b/app/code/core/Mage/Api/Model/Acl.php deleted file mode 100644 index 1c9ded5d42b8f1dc6b011217b1805789d02a0846..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api/Model/Acl.php +++ /dev/null @@ -1,103 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - - -/** - * Acl model - * - * @category Mage - * @package Mage_Api - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api_Model_Acl extends Zend_Acl -{ - /** - * All the group roles are prepended by G - * - */ - const ROLE_TYPE_GROUP = 'G'; - - /** - * All the user roles are prepended by U - * - */ - const ROLE_TYPE_USER = 'U'; - - /** - * User types for store access - * G - Guest customer (anonymous) - * C - Authenticated customer - * A - Authenticated admin user - * - */ - const USER_TYPE_GUEST = 'G'; - const USER_TYPE_CUSTOMER = 'C'; - const USER_TYPE_ADMIN = 'A'; - - /** - * Permission level to deny access - * - */ - const RULE_PERM_DENY = 0; - - /** - * Permission level to inheric access from parent role - * - */ - const RULE_PERM_INHERIT = 1; - - /** - * Permission level to allow access - * - */ - const RULE_PERM_ALLOW = 2; - - /** - * Get role registry object or create one - * - * @return Mage_Api_Model_Acl_Role_Registry - */ - protected function _getRoleRegistry() - { - if (null === $this->_roleRegistry) { - $this->_roleRegistry = Mage::getModel('Mage_Api_Model_Acl_Role_Registry'); - } - return $this->_roleRegistry; - } - - /** - * Add parent to role object - * - * @param Zend_Acl_Role $role - * @param Zend_Acl_Role $parent - * @return Mage_Api_Model_Acl - */ - public function addRoleParent($role, $parent) - { - $this->_getRoleRegistry()->addParent($role, $parent); - return $this; - } -} diff --git a/app/code/core/Mage/Api/Model/Acl/Role.php b/app/code/core/Mage/Api/Model/Acl/Role.php deleted file mode 100644 index 72d1525d6e9fc9f169515e27ba658814e9f197d6..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api/Model/Acl/Role.php +++ /dev/null @@ -1,56 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - - -/** - * User acl role - * - * @method Mage_Api_Model_Resource_Role _getResource() - * @method Mage_Api_Model_Resource_Role getResource() - * @method int getParentId() - * @method Mage_Api_Model_Acl_Role setParentId(int $value) - * @method int getTreeLevel() - * @method Mage_Api_Model_Acl_Role setTreeLevel(int $value) - * @method int getSortOrder() - * @method Mage_Api_Model_Acl_Role setSortOrder(int $value) - * @method string getRoleType() - * @method Mage_Api_Model_Acl_Role setRoleType(string $value) - * @method int getUserId() - * @method Mage_Api_Model_Acl_Role setUserId(int $value) - * @method string getRoleName() - * @method Mage_Api_Model_Acl_Role setRoleName(string $value) - * - * @category Mage - * @package Mage_Api - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api_Model_Acl_Role extends Mage_Core_Model_Abstract -{ - protected function _construct() - { - $this->_init('Mage_Api_Model_Resource_Role'); - } -} diff --git a/app/code/core/Mage/Api/Model/Acl/Role/Registry.php b/app/code/core/Mage/Api/Model/Acl/Role/Registry.php deleted file mode 100644 index 4bb9d78f998651f242a79a86dff492806fa00014..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api/Model/Acl/Role/Registry.php +++ /dev/null @@ -1,76 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - - -/** - * Acl role registry - * - * @category Mage - * @package Mage_Api - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api_Model_Acl_Role_Registry extends Zend_Acl_Role_Registry -{ - /** - * Add parent to the $role node - * - * @param Zend_Acl_Role_Interface|string $role - * @param array|Zend_Acl_Role_Interface|string $parents - * @return Mage_Auth_Model_Acl_Role_Registry - */ - function addParent($role, $parents) - { - try { - if ($role instanceof Zend_Acl_Role_Interface) { - $roleId = $role->getRoleId(); - } else { - $roleId = $role; - $role = $this->get($role); - } - } catch (Zend_Acl_Role_Registry_Exception $e) { - throw new Zend_Acl_Role_Registry_Exception("Child Role id '$roleId' does not exist"); - } - - if (!is_array($parents)) { - $parents = array($parents); - } - foreach ($parents as $parent) { - try { - if ($parent instanceof Zend_Acl_Role_Interface) { - $roleParentId = $parent->getRoleId(); - } else { - $roleParentId = $parent; - } - $roleParent = $this->get($roleParentId); - } catch (Zend_Acl_Role_Registry_Exception $e) { - throw new Zend_Acl_Role_Registry_Exception("Parent Role id '$roleParentId' does not exist"); - } - $this->_roles[$roleId]['parents'][$roleParentId] = $roleParent; - $this->_roles[$roleParentId]['children'][$roleId] = $role; - } - return $this; - } -} diff --git a/app/code/core/Mage/Api/Model/Config.php b/app/code/core/Mage/Api/Model/Config.php deleted file mode 100644 index d24a42e84898e4a440be2d92277ea1c9e66768b2..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api/Model/Config.php +++ /dev/null @@ -1,291 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Webservice api config model - * - * @category Mage - * @package Mage_Api - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api_Model_Config extends Varien_Simplexml_Config -{ - const CACHE_TAG = 'config_api'; - - /** - * Constructor - * - * @see Varien_Simplexml_Config - */ - public function __construct($sourceData=null) - { - $this->setCacheId('config_api'); - $this->setCacheTags(array(self::CACHE_TAG)); - - parent::__construct($sourceData); - $this->_construct(); - } - - /** - * Init configuration for webservices api - * - * @return Mage_Api_Model_Config - */ - protected function _construct() - { - if (Mage::app()->useCache('config_api')) { - if ($this->loadCache()) { - return $this; - } - } - - $config = Mage::getConfig()->loadModulesConfiguration('api.xml'); - $this->setXml($config->getNode('api')); - - if (Mage::app()->useCache('config_api')) { - $this->saveCache(); - } - return $this; - } - - /** - * Retrieve adapter aliases from config. - * - * @return array - */ - public function getAdapterAliases() - { - $aliases = array(); - - foreach ($this->getNode('adapter_aliases')->children() as $alias => $adapter) { - $aliases[$alias] = array( - (string) $adapter->suggest_class, // model class name - (string) $adapter->suggest_method // model method name - ); - } - return $aliases; - } - - /** - * Retrieve all adapters - * - * @return array - */ - public function getAdapters() - { - $adapters = array(); - foreach ($this->getNode('adapters')->children() as $adapterName => $adapter) { - /* @var $adapter Varien_SimpleXml_Element */ - if (isset($adapter->use)) { - $adapter = $this->getNode('adapters/' . (string) $adapter->use); - } - $adapters[$adapterName] = $adapter; - } - return $adapters; - } - - /** - * Retrieve active adapters - * - * @return array - */ - public function getActiveAdapters() - { - $adapters = array(); - foreach ($this->getAdapters() as $adapterName => $adapter) { - if (!isset($adapter->active) || $adapter->active == '0') { - continue; - } - - if (isset($adapter->required) && isset($adapter->required->extensions)) { - foreach ($adapter->required->extensions->children() as $extension=>$data) { - if (!extension_loaded($extension)) { - continue; - } - } - } - - $adapters[$adapterName] = $adapter; - } - - return $adapters; - } - - /** - * Retrieve handlers - * - * @return Varien_Simplexml_Element - */ - public function getHandlers() - { - return $this->getNode('handlers')->children(); - } - - /** - * Retrieve resources - * - * @return Varien_Simplexml_Element - */ - public function getResources() - { - return $this->getNode('resources')->children(); - } - - /** - * Retrieve resources alias - * - * @return Varien_Simplexml_Element - */ - public function getResourcesAlias() - { - return $this->getNode('resources_alias')->children(); - } - - - /** - * Load Acl resources from config - * - * @param Mage_Api_Model_Acl $acl - * @param Mage_Core_Model_Config_Element $resource - * @param string $parentName - * @return Mage_Api_Model_Config - */ - public function loadAclResources(Mage_Api_Model_Acl $acl, $resource=null, $parentName=null) - { - $resourceName = null; - if (is_null($resource)) { - $resource = $this->getNode('acl/resources'); - } else { - $resourceName = (is_null($parentName) ? '' : $parentName.'/').$resource->getName(); - $acl->add(Mage::getModel('Mage_Api_Model_Acl_Resource', array('resourceId' => $resourceName)), $parentName); - } - - $children = $resource->children(); - - if (empty($children)) { - return $this; - } - - foreach ($children as $res) { - if ($res->getName() != 'title' && $res->getName() != 'sort_order') { - $this->loadAclResources($acl, $res, $resourceName); - } - } - return $this; - } - - /** - * Get acl assert config - * - * @param string $name - * @return Mage_Core_Model_Config_Element|boolean - */ - public function getAclAssert($name='') - { - $asserts = $this->getNode('acl/asserts'); - if (''===$name) { - return $asserts; - } - - if (isset($asserts->$name)) { - return $asserts->$name; - } - - return false; - } - - /** - * Retrieve privilege set by name - * - * @param string $name - * @return Mage_Core_Model_Config_Element|boolean - */ - public function getAclPrivilegeSet($name='') - { - $sets = $this->getNode('acl/privilegeSets'); - if (''===$name) { - return $sets; - } - - if (isset($sets->$name)) { - return $sets->$name; - } - - return false; - } - - public function getFaults($resourceName=null) - { - if (is_null($resourceName) - || !isset($this->getResources()->$resourceName) - || !isset($this->getResources()->$resourceName->faults)) { - $faultsNode = $this->getNode('faults'); - } else { - $faultsNode = $this->getResources()->$resourceName->faults; - } - /* @var $faultsNode Varien_Simplexml_Element */ - - $translateModule = 'Mage_Api'; - if (isset($faultsNode['module'])) { - $translateModule = (string) $faultsNode['module']; - } - - $faults = array(); - foreach ($faultsNode->children() as $faultName => $fault) { - $faults[$faultName] = array( - 'code' => (string) $fault->code, - 'message' => Mage::helper($translateModule)->__((string)$fault->message) - ); - } - - return $faults; - } - - /** - * Retrieve cache object - * - * @return Zend_Cache_Frontend_File - */ - public function getCache() - { - return Mage::app()->getCache(); - } - - protected function _loadCache($id) - { - return Mage::app()->loadCache($id); - } - - protected function _saveCache($data, $id, $tags=array(), $lifetime=false) - { - return Mage::app()->saveCache($data, $id, $tags, $lifetime); - } - - protected function _removeCache($id) - { - return Mage::app()->removeCache($id); - } -} // Class Mage_Api_Model_Config End diff --git a/app/code/core/Mage/Api/Model/Resource/Abstract.php b/app/code/core/Mage/Api/Model/Resource/Abstract.php deleted file mode 100644 index 10f740368f608bab8c8d09ac93bc93eaca4caec7..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api/Model/Resource/Abstract.php +++ /dev/null @@ -1,105 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Api resource abstract - * - * @category Mage - * @package Mage_Api - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api_Model_Resource_Abstract -{ - - /** - * Resource configuration - * - * @var Varien_Simplexml_Element - */ - protected $_resourceConfig = null; - - /** - * Retrieve webservice session - * - * @return Mage_Api_Model_Session - */ - protected function _getSession() - { - return Mage::getSingleton('Mage_Api_Model_Session'); - } - - /** - * Retrieve webservice configuration - * - * @return Mage_Api_Model_Config - */ - protected function _getConfig() - { - return Mage::getSingleton('Mage_Api_Model_Config'); - } - - /** - * Set configuration for api resource - * - * @param Varien_Simplexml_Element $xml - * @return Mage_Api_Model_Resource_Abstract - */ - public function setResourceConfig(Varien_Simplexml_Element $xml) - { - $this->_resourceConfig = $xml; - return $this; - } - - /** - * Retrieve configuration for api resource - * - * @return Varien_Simplexml_Element - */ - public function getResourceConfig() - { - return $this->_resourceConfig; - } - - /** - * Retrieve webservice server - * - * @return Mage_Api_Model_Server - */ - protected function _getServer() - { - return Mage::getSingleton('Mage_Api_Model_Server'); - } - - /** - * Dispatches fault - * - * @param string $code - */ - protected function _fault($code, $customMessage=null) - { - throw new Mage_Api_Exception($code, $customMessage); - } -} // Class Mage_Api_Model_Resource_Abstract End diff --git a/app/code/core/Mage/Api/Model/Resource/Acl.php b/app/code/core/Mage/Api/Model/Resource/Acl.php deleted file mode 100755 index 5b2035d4d2aa334746b061648cec64e40b65bd97..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api/Model/Resource/Acl.php +++ /dev/null @@ -1,159 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - - -/** - * Resource model for admin ACL - * - * @category Mage - * @package Mage_Api - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api_Model_Resource_Acl extends Mage_Core_Model_Resource_Db_Abstract -{ - /** - * Initialize resource connections - * - */ - protected function _construct() - { - $this->_init('api_role', 'role_id'); - } - - /** - * Load ACL for the user - * - * @return Mage_Api_Model_Acl - */ - public function loadAcl() - { - $acl = Mage::getModel('Mage_Api_Model_Acl'); - $adapter = $this->_getReadAdapter(); - - Mage::getSingleton('Mage_Api_Model_Config')->loadAclResources($acl); - - $rolesArr = $adapter->fetchAll( - $adapter->select() - ->from($this->getTable('api_role')) - ->order(array('tree_level', 'role_type')) - ); - $this->loadRoles($acl, $rolesArr); - - $rulesArr = $adapter->fetchAll( - $adapter->select() - ->from(array('r'=>$this->getTable('api_rule'))) - ->joinLeft( - array('a'=>$this->getTable('api_assert')), - 'a.assert_id=r.assert_id', - array('assert_type', 'assert_data') - )); - $this->loadRules($acl, $rulesArr); - return $acl; - } - - /** - * Load roles - * - * @param Mage_Api_Model_Acl $acl - * @param array $rolesArr - * @return Mage_Api_Model_Resource_Acl - */ - public function loadRoles(Mage_Api_Model_Acl $acl, array $rolesArr) - { - foreach ($rolesArr as $role) { - $parent = $role['parent_id']>0 ? Mage_Api_Model_Acl::ROLE_TYPE_GROUP.$role['parent_id'] : null; - switch ($role['role_type']) { - case Mage_Api_Model_Acl::ROLE_TYPE_GROUP: - $roleId = $role['role_type'].$role['role_id']; - $acl->addRole(Mage::getModel('Mage_Api_Model_Acl_Role_Group', array('roleId' => $roleId)), - $parent); - break; - - case Mage_Api_Model_Acl::ROLE_TYPE_USER: - $roleId = $role['role_type'].$role['user_id']; - if (!$acl->hasRole($roleId)) { - $acl->addRole(Mage::getModel('Mage_Api_Model_Acl_Role_User', array('roleId' => $roleId)), - $parent); - } else { - $acl->addRoleParent($roleId, $parent); - } - break; - } - } - - return $this; - } - - /** - * Load rules - * - * @param Mage_Api_Model_Acl $acl - * @param array $rulesArr - * @return Mage_Api_Model_Resource_Acl - */ - public function loadRules(Mage_Api_Model_Acl $acl, array $rulesArr) - { - foreach ($rulesArr as $rule) { - $role = $rule['role_type'].$rule['role_id']; - $resource = $rule['resource_id']; - $privileges = !empty($rule['api_privileges']) ? explode(',', $rule['api_privileges']) : null; - - $assert = null; - if (0!=$rule['assert_id']) { - $assertClass = Mage::getSingleton('Mage_Api_Model_Config')->getAclAssert($rule['assert_type'])->getClassName(); - $assert = new $assertClass(unserialize($rule['assert_data'])); - } - try { - if ($rule['api_permission'] == 'allow') { - $acl->allow($role, $resource, $privileges, $assert); - } else if ($rule['api_permission'] == 'deny') { - $acl->deny($role, $resource, $privileges, $assert); - } - } catch (Exception $e) { - //$m = $e->getMessage(); - //if ( eregi("^Resource '(.*)' not found", $m) ) { - // Deleting non existent resource rule from rules table - //$cond = $this->_write->quoteInto('resource_id = ?', $resource); - //$this->_write->delete(Mage::getSingleton('Mage_Core_Model_Resource')->getTableName('admin_rule'), $cond); - //} else { - //TODO: We need to log such exceptions to somewhere like a system/errors.log - //} - } - /* - switch ($rule['api_permission']) { - case Mage_Api_Model_Acl::RULE_PERM_ALLOW: - $acl->allow($role, $resource, $privileges, $assert); - break; - - case Mage_Api_Model_Acl::RULE_PERM_DENY: - $acl->deny($role, $resource, $privileges, $assert); - break; - } - */ - } - return $this; - } -} diff --git a/app/code/core/Mage/Api/Model/Resource/Role.php b/app/code/core/Mage/Api/Model/Resource/Role.php deleted file mode 100755 index c2334c10e1085e62d69c651095dd8726eb34fe5c..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api/Model/Resource/Role.php +++ /dev/null @@ -1,76 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - - -/** - * ACL role resource - * - * @category Mage - * @package Mage_Api - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api_Model_Resource_Role extends Mage_Core_Model_Resource_Db_Abstract -{ - /** - * Resource initialization - * - */ - protected function _construct() - { - $this->_init('api_role', 'role_id'); - } - - /** - * Action before save - * - * @param Mage_Core_Model_Abstract $object - * @return Mage_Api_Model_Resource_Role - */ - protected function _beforeSave(Mage_Core_Model_Abstract $object) - { - if (!$object->getId()) { - $object->setCreated(now()); - } - $object->setModified(now()); - return $this; - } - - /** - * Load an object - * - * @param Mage_Core_Model_Abstract $object - * @param mixed $value - * @param string $field field to load by (defaults to model id) - * @return Mage_Core_Model_Resource_Db_Abstract - */ - public function load(Mage_Core_Model_Abstract $object, $value, $field = null) - { - if (!intval($value) && is_string($value)) { - $field = 'role_id'; - } - return parent::load($object, $value, $field); - } -} diff --git a/app/code/core/Mage/Api/Model/Resource/Roles.php b/app/code/core/Mage/Api/Model/Resource/Roles.php deleted file mode 100755 index b40d0808ad520953de436667005a89c5c8ebfbe9..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api/Model/Resource/Roles.php +++ /dev/null @@ -1,151 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - - -/** - * ACL roles resource - * - * @category Mage - * @package Mage_Api - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api_Model_Resource_Roles extends Mage_Core_Model_Resource_Db_Abstract -{ - /** - * User table name - * - * @var unknown - */ - protected $_usersTable; - - /** - * Rule table name - * - * @var unknown - */ - protected $_ruleTable; - - /** - * Resource initialization - * - */ - protected function _construct() - { - $this->_init('api_role', 'role_id'); - - $this->_usersTable = $this->getTable('api_user'); - $this->_ruleTable = $this->getTable('api_rule'); - } - - /** - * Action before save - * - * @param Mage_Core_Model_Abstract $role - * @return Mage_Api_Model_Resource_Roles - */ - protected function _beforeSave(Mage_Core_Model_Abstract $role) - { - if ($role->getId() == '') { - if ($role->getIdFieldName()) { - $role->unsetData($role->getIdFieldName()); - } else { - $role->unsetData('id'); - } - } - - if ($role->getPid() > 0) { - $row = $this->load($role->getPid()); - } else { - $row = array('tree_level' => 0); - } - $role->setTreeLevel($row['tree_level'] + 1); - $role->setRoleName($role->getName()); - return $this; - } - - /** - * Action after save - * - * @param Mage_Core_Model_Abstract $role - * @return Mage_Api_Model_Resource_Roles - */ - protected function _afterSave(Mage_Core_Model_Abstract $role) - { - $this->_updateRoleUsersAcl($role); - Mage::app()->getCache()->clean(Zend_Cache::CLEANING_MODE_MATCHING_TAG); - return $this; - } - - /** - * Action after delete - * - * @param Mage_Core_Model_Abstract $role - * @return Mage_Api_Model_Resource_Roles - */ - protected function _afterDelete(Mage_Core_Model_Abstract $role) - { - $adapter = $this->_getWriteAdapter(); - $adapter->delete($this->getMainTable(), array('parent_id=?'=>$role->getId())); - $adapter->delete($this->_ruleTable, array('role_id=?'=>$role->getId())); - return $this; - } - - /** - * Get role users - * - * @param Mage_Api_Model_Roles $role - * @return unknown - */ - public function getRoleUsers(Mage_Api_Model_Roles $role) - { - $adapter = $this->_getReadAdapter(); - $select = $adapter->select() - ->from($this->getMainTable(), array('user_id')) - ->where('parent_id = ?', $role->getId()) - ->where('role_type = ?', Mage_Api_Model_Acl::ROLE_TYPE_USER) - ->where('user_id > 0'); - return $adapter->fetchCol($select); - } - - /** - * Update role users - * - * @param Mage_Api_Model_Roles $role - * @return boolean - */ - private function _updateRoleUsersAcl(Mage_Api_Model_Roles $role) - { - $users = $this->getRoleUsers($role); - $rowsCount = 0; - if (sizeof($users) > 0) { - $rowsCount = $this->_getWriteAdapter()->update( - $this->_usersTable, - array('reload_acl_flag' => 1), - array('user_id IN(?)' => $users)); - } - return ($rowsCount > 0) ? true : false; - } -} diff --git a/app/code/core/Mage/Api/Model/Resource/Rules.php b/app/code/core/Mage/Api/Model/Resource/Rules.php deleted file mode 100755 index c83cb6f71719fff8960df81c8a8e4289b06e661b..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api/Model/Resource/Rules.php +++ /dev/null @@ -1,87 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - - -/** - * Rules resource model - * - * @category Mage - * @package Mage_Api - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api_Model_Resource_Rules extends Mage_Core_Model_Resource_Db_Abstract -{ - /** - * Resource initialization - * - */ - protected function _construct() - { - $this->_init('api_rule', 'rule_id'); - } - - /** - * Save rule - * - * @param Mage_Api_Model_Rules $rule - */ - public function saveRel(Mage_Api_Model_Rules $rule) - { - $adapter = $this->_getWriteAdapter(); - $adapter->beginTransaction(); - - try { - $roleId = $rule->getRoleId(); - $adapter->delete($this->getMainTable(), array('role_id = ?' => $roleId)); - $masterResources = Mage::getModel('Mage_Api_Model_Roles')->getResourcesList2D(); - $masterAdmin = false; - if ($postedResources = $rule->getResources()) { - foreach ($masterResources as $index => $resName) { - if (!$masterAdmin) { - $permission = (in_array($resName, $postedResources))? 'allow' : 'deny'; - $adapter->insert($this->getMainTable(), array( - 'role_type' => 'G', - 'resource_id' => trim($resName, '/'), - 'api_privileges' => null, - 'assert_id' => 0, - 'role_id' => $roleId, - 'api_permission' => $permission - )); - } - if ($resName == 'all' && $permission == 'allow') { - $masterAdmin = true; - } - } - } - - $adapter->commit(); - } catch (Mage_Core_Exception $e) { - throw $e; - } catch (Exception $e) { - $adapter->rollBack(); - } - } -} diff --git a/app/code/core/Mage/Api/Model/Resource/User.php b/app/code/core/Mage/Api/Model/Resource/User.php deleted file mode 100755 index d7cc9ed775a05a90d0612444ff4798efa5f23e07..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api/Model/Resource/User.php +++ /dev/null @@ -1,435 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - - -/** - * ACL user resource - * - * @category Mage - * @package Mage_Api - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api_Model_Resource_User extends Mage_Core_Model_Resource_Db_Abstract -{ - /** - * Resource initialization - * - */ - protected function _construct() - { - $this->_init('api_user', 'user_id'); - } - - /** - * Initialize unique fields - * - * @return Mage_Api_Model_Resource_User - */ - protected function _initUniqueFields() - { - $this->_uniqueFields = array( - array( - 'field' => 'email', - 'title' => Mage::helper('Mage_Api_Helper_Data')->__('Email') - ), - array( - 'field' => 'username', - 'title' => Mage::helper('Mage_Api_Helper_Data')->__('User Name') - ), - ); - return $this; - } - - /** - * Authenticate user by $username and $password - * - * @param Mage_Api_Model_User $user - * @return Mage_Api_Model_Resource_User - */ - public function recordLogin(Mage_Api_Model_User $user) - { - $data = array( - 'lognum' => $user->getLognum()+1, - ); - $condition = $this->_getReadAdapter()->quoteInto('user_id=?', $user->getUserId()); - $this->_getWriteAdapter()->update($this->getTable('api_user'), $data, $condition); - return $this; - } - - /** - * Record api user session - * - * @param Mage_Api_Model_User $user - * @return Mage_Api_Model_Resource_User - */ - public function recordSession(Mage_Api_Model_User $user) - { - $readAdapter = $this->_getReadAdapter(); - $writeAdapter = $this->_getWriteAdapter(); - $select = $readAdapter->select() - ->from($this->getTable('api_session'), 'user_id') - ->where('user_id = ?', $user->getId()) - ->where('sessid = ?', $user->getSessid()); - $loginDate = now(); - if ($readAdapter->fetchRow($select)) { - $writeAdapter->update( - $this->getTable('api_session'), - array ('logdate' => $loginDate), - $readAdapter->quoteInto('user_id = ?', $user->getId()) . ' AND ' - . $readAdapter->quoteInto('sessid = ?', $user->getSessid()) - ); - } else { - $writeAdapter->insert( - $this->getTable('api_session'), - array( - 'user_id' => $user->getId(), - 'logdate' => $loginDate, - 'sessid' => $user->getSessid() - ) - ); - } - $user->setLogdate($loginDate); - return $this; - } - - /** - * Clean old session - * - * @param Mage_Api_Model_User $user - * @return Mage_Api_Model_Resource_User - */ - public function cleanOldSessions(Mage_Api_Model_User $user) - { - $readAdapter = $this->_getReadAdapter(); - $writeAdapter = $this->_getWriteAdapter(); - $timeout = Mage::getStoreConfig('api/config/session_timeout'); - $timeSubtract = $readAdapter->getDateAddSql( - 'logdate', - $timeout, - Varien_Db_Adapter_Interface::INTERVAL_SECOND); - $writeAdapter->delete( - $this->getTable('api_session'), - array('user_id = ?' => $user->getId(), $readAdapter->quote(now()) . ' > '.$timeSubtract) - ); - return $this; - } - - /** - * Load data by username - * - * @param string $username - * @return array - */ - public function loadByUsername($username) - { - $adapter = $this->_getReadAdapter(); - $select = $adapter->select()->from($this->getTable('api_user')) - ->where('username=:username'); - return $adapter->fetchRow($select, array('username'=>$username)); - } - - /** - * load by session id - * - * @param string $sessId - * @return array - */ - public function loadBySessId($sessId) - { - $result = array(); - $adapter = $this->_getReadAdapter(); - $select = $adapter->select() - ->from($this->getTable('api_session')) - ->where('sessid = ?', $sessId); - if ($apiSession = $adapter->fetchRow($select)) { - $selectUser = $adapter->select() - ->from($this->getTable('api_user')) - ->where('user_id = ?', $apiSession['user_id']); - if ($user = $adapter->fetchRow($selectUser)) { - $result = array_merge($user, $apiSession); - } - } - return $result; - } - - /** - * Clear by session - * - * @param string $sessid - * @return Mage_Api_Model_Resource_User - */ - public function clearBySessId($sessid) - { - $this->_getWriteAdapter()->delete( - $this->getTable('api_session'), - array('sessid = ?' => $sessid) - ); - return $this; - } - - /** - * Retrieve api user role data if it was assigned to role - * - * @param int | Mage_Api_Model_User $user - * @return null | array - */ - public function hasAssigned2Role($user) - { - $userId = null; - $result = null; - if (is_numeric($user)) { - $userId = $user; - } else if ($user instanceof Mage_Core_Model_Abstract) { - $userId = $user->getUserId(); - } - - if ($userId) { - $adapter = $this->_getReadAdapter(); - $select = $adapter->select(); - $select->from($this->getTable('api_role')) - ->where('parent_id > 0 AND user_id = ?', $userId); - $result = $adapter->fetchAll($select); - } - return $result; - } - - /** - * Action before save - * - * @param Mage_Core_Model_Abstract $user - * @return Mage_Api_Model_Resource_User - */ - protected function _beforeSave(Mage_Core_Model_Abstract $user) - { - if (!$user->getId()) { - $user->setCreated(now()); - } - $user->setModified(now()); - return $this; - } - - /** - * Delete the object - * - * @param Mage_Core_Model_Abstract $user - * @return boolean - */ - public function delete(Mage_Core_Model_Abstract $user) - { - $dbh = $this->_getWriteAdapter(); - $uid = (int) $user->getId(); - $dbh->beginTransaction(); - try { - $dbh->delete($this->getTable('api_user'), array('user_id = ?' => $uid)); - $dbh->delete($this->getTable('api_role'), array('user_id = ?' => $uid)); - } catch (Mage_Core_Exception $e) { - throw $e; - return false; - } catch (Exception $e) { - $dbh->rollBack(); - return false; - } - $dbh->commit(); - return true; - } - - /** - * Save user roles - * - * @param Mage_Core_Model_Abstract $user - * @return unknown - */ - public function _saveRelations(Mage_Core_Model_Abstract $user) - { - $rolesIds = $user->getRoleIds(); - if (!is_array($rolesIds) || count($rolesIds) == 0) { - return $user; - } - - $adapter = $this->_getWriteAdapter(); - - $adapter->beginTransaction(); - - try { - $adapter->delete( - $this->getTable('api_role'), - array('user_id = ?' => (int) $user->getId())); - foreach ($rolesIds as $rid) { - $rid = intval($rid); - if ($rid > 0) { - //$row = $this->load($user, $rid); - } else { - $row = array('tree_level' => 0); - } - $row = array('tree_level' => 0); - - $data = array( - 'parent_id' => $rid, - 'tree_level' => $row['tree_level'] + 1, - 'sort_order' => 0, - 'role_type' => Mage_Api_Model_Acl::ROLE_TYPE_USER, - 'user_id' => $user->getId(), - 'role_name' => $user->getFirstname() - ); - $adapter->insert($this->getTable('api_role'), $data); - } - $adapter->commit(); - } catch (Mage_Core_Exception $e) { - throw $e; - } catch (Exception $e) { - $adapter->rollBack(); - } - return $this; - } - - /** - * Retrieve roles data - * - * @param Mage_Core_Model_Abstract $user - * @return array - */ - public function _getRoles(Mage_Core_Model_Abstract $user) - { - if (!$user->getId()) { - return array(); - } - $table = $this->getTable('api_role'); - $adapter = $this->_getReadAdapter(); - $select = $adapter->select() - ->from($table, array()) - ->joinLeft( - array('ar' => $table), - $adapter->quoteInto( - "ar.role_id = {$table}.parent_id AND ar.role_type = ?", - Mage_Api_Model_Acl::ROLE_TYPE_GROUP), - array('role_id')) - ->where("{$table}.user_id = ?", $user->getId()); - - return (($roles = $adapter->fetchCol($select)) ? $roles : array()); - } - - /** - * Add Role - * - * @param Mage_Core_Model_Abstract $user - * @return Mage_Api_Model_Resource_User - */ - public function add(Mage_Core_Model_Abstract $user) - { - $adapter = $this->_getWriteAdapter(); - $aRoles = $this->hasAssigned2Role($user); - if (sizeof($aRoles) > 0) { - foreach ($aRoles as $idx => $data) { - $adapter->delete( - $this->getTable('api_role'), - array('role_id = ?' => $data['role_id']) - ); - } - } - - if ($user->getId() > 0) { - $role = Mage::getModel('Mage_Api_Model_Role')->load($user->getRoleId()); - } else { - $role = new Varien_Object(array('tree_level' => 0)); - } - $adapter->insert($this->getTable('api_role'), array( - 'parent_id' => $user->getRoleId(), - 'tree_level'=> ($role->getTreeLevel() + 1), - 'sort_order'=> 0, - 'role_type' => Mage_Api_Model_Acl::ROLE_TYPE_USER, - 'user_id' => $user->getUserId(), - 'role_name' => $user->getFirstname() - )); - - return $this; - } - - /** - * Delete from role - * - * @param Mage_Core_Model_Abstract $user - * @return Mage_Api_Model_Resource_User - */ - public function deleteFromRole(Mage_Core_Model_Abstract $user) - { - if ($user->getUserId() <= 0) { - return $this; - } - if ($user->getRoleId() <= 0) { - return $this; - }; - - $adapter = $this->_getWriteAdapter(); - $table = $this->getTable('api_role'); - - $condition = array( - "{$table}.user_id = ?" => $user->getUserId(), - "{$table}.parent_id = ?"=> $user->getRoleId() - ); - $adapter->delete($table, $condition); - return $this; - } - - /** - * Retrieve roles which exists for user - * - * @param Mage_Core_Model_Abstract $user - * @return array - */ - public function roleUserExists(Mage_Core_Model_Abstract $user) - { - $result = array(); - if ($user->getUserId() > 0) { - $adapter = $this->_getReadAdapter(); - $select = $adapter->select()->from($this->getTable('api_role')) - ->where('parent_id = ?', $user->getRoleId()) - ->where('user_id = ?', $user->getUserId()); - $result = $adapter->fetchCol($select); - } - return $result; - } - - /** - * Check if user not unique - * - * @param Mage_Core_Model_Abstract $user - * @return array - */ - public function userExists(Mage_Core_Model_Abstract $user) - { - $usersTable = $this->getTable('api_user'); - $adapter = $this->_getReadAdapter(); - $condition = array( - $adapter->quoteInto("{$usersTable}.username = ?", $user->getUsername()), - $adapter->quoteInto("{$usersTable}.email = ?", $user->getEmail()), - ); - $select = $adapter->select() - ->from($usersTable) - ->where(implode(' OR ', $condition)) - ->where($usersTable.'.user_id != ?', (int) $user->getId()); - return $adapter->fetchRow($select); - } -} diff --git a/app/code/core/Mage/Api/Model/Role.php b/app/code/core/Mage/Api/Model/Role.php deleted file mode 100644 index 356a2b5732f9515233d4478424dfc9d1203b133f..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api/Model/Role.php +++ /dev/null @@ -1,58 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Role item model - * - * @method Mage_Api_Model_Resource_Role _getResource() - * @method Mage_Api_Model_Resource_Role getResource() - * @method int getParentId() - * @method Mage_Api_Model_Role setParentId(int $value) - * @method int getTreeLevel() - * @method Mage_Api_Model_Role setTreeLevel(int $value) - * @method int getSortOrder() - * @method Mage_Api_Model_Role setSortOrder(int $value) - * @method string getRoleType() - * @method Mage_Api_Model_Role setRoleType(string $value) - * @method int getUserId() - * @method Mage_Api_Model_Role setUserId(int $value) - * @method string getRoleName() - * @method Mage_Api_Model_Role setRoleName(string $value) - * - * @category Mage - * @package Mage_Api - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api_Model_Role extends Mage_Core_Model_Abstract -{ - /** - * Initialize resource - */ - protected function _construct() - { - $this->_init('Mage_Api_Model_Resource_Role'); - } -} diff --git a/app/code/core/Mage/Api/Model/Roles.php b/app/code/core/Mage/Api/Model/Roles.php deleted file mode 100644 index c9d153be4e312c0d88ddb07f48bd8fa53192880b..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api/Model/Roles.php +++ /dev/null @@ -1,181 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Enter description here ... - * - * @method Mage_Api_Model_Resource_Roles _getResource() - * @method Mage_Api_Model_Resource_Roles getResource() - * @method int getParentId() - * @method Mage_Api_Model_Roles setParentId(int $value) - * @method int getTreeLevel() - * @method Mage_Api_Model_Roles setTreeLevel(int $value) - * @method int getSortOrder() - * @method Mage_Api_Model_Roles setSortOrder(int $value) - * @method string getRoleType() - * @method Mage_Api_Model_Roles setRoleType(string $value) - * @method int getUserId() - * @method Mage_Api_Model_Roles setUserId(int $value) - * @method string getRoleName() - * @method Mage_Api_Model_Roles setRoleName(string $value) - * @method string getName() - * @method Mage_Api_Model_Role setName() setName(string $name) - * - * @category Mage - * @package Mage_Api - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api_Model_Roles extends Mage_Core_Model_Abstract -{ - /** - * Filters - * - * @var array - */ - protected $_filters; - - - protected function _construct() - { - $this->_init('Mage_Api_Model_Resource_Roles'); - } - - public function update() - { - $this->getResource()->update($this); - return $this; - } - - public function getUsersCollection() - { - return Mage::getResourceModel('Mage_Api_Model_Resource_Roles_User_Collection'); - } - - public function getResourcesTree() - { - return $this->_buildResourcesArray(null, null, null, null, true); - } - - public function getResourcesList() - { - return $this->_buildResourcesArray(); - } - - public function getResourcesList2D() - { - return $this->_buildResourcesArray(null, null, null, true); - } - - public function getRoleUsers() - { - return $this->getResource()->getRoleUsers($this); - } - - protected function _buildResourcesArray( - Varien_Simplexml_Element $resource = null, $parentName = null, $level = 0, $represent2Darray = null, - $rawNodes = false, $module = 'Mage_Adminhtml' - ) { - static $result; - - if (is_null($resource)) { - $resource = Mage::getSingleton('Mage_Api_Model_Config')->getNode('acl/resources'); - $resourceName = null; - $level = -1; - } else { - $resourceName = $parentName; - if ($resource->getName()!='title' && $resource->getName()!='sort_order' - && $resource->getName() != 'children' - ) { - $resourceName = (is_null($parentName) ? '' : $parentName.'/').$resource->getName(); - - //assigning module for its' children nodes - if ($resource->getAttribute('module')) { - $module = (string)$resource->getAttribute('module'); - } - - if ($rawNodes) { - $resource->addAttribute("aclpath", $resourceName); - } - - $resource->title = Mage::helper($module)->__((string)$resource->title); - - if ( is_null($represent2Darray) ) { - $result[$resourceName]['name'] = (string)$resource->title; - $result[$resourceName]['level'] = $level; - } else { - $result[] = $resourceName; - } - } - } - - $children = $resource->children(); - if (empty($children)) { - if ($rawNodes) { - return $resource; - } else { - return $result; - } - } - foreach ($children as $child) { - $this->_buildResourcesArray($child, $resourceName, $level+1, $represent2Darray, $rawNodes, $module); - } - if ($rawNodes) { - return $resource; - } else { - return $result; - } - } - - /** - * Filter data before save - * - * @return Mage_Api_Model_Roles - */ - protected function _beforeSave() - { - $this->filter(); - parent::_beforeSave(); - return $this; - } - - /** - * Filter set data - * - * @return Mage_Api_Model_Roles - */ - public function filter() - { - $data = $this->getData(); - if (!$this->_filters || !$data) { - return $this; - } - /** @var $filter Mage_Core_Model_Input_Filter */ - $filter = Mage::getModel('Mage_Core_Model_Input_Filter'); - $filter->setFilters($this->_filters); - $this->setData($filter->filter($data)); - return $this; - } -} diff --git a/app/code/core/Mage/Api/Model/Rules.php b/app/code/core/Mage/Api/Model/Rules.php deleted file mode 100644 index 28cc1c9ac24a1d8f3d2f6b3f0258fb7243250ba5..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api/Model/Rules.php +++ /dev/null @@ -1,69 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Enter description here ... - * - * @method Mage_Api_Model_Resource_Rules _getResource() - * @method Mage_Api_Model_Resource_Rules getResource() - * @method int getRoleId() - * @method Mage_Api_Model_Rules setRoleId(int $value) - * @method string getResourceId() - * @method Mage_Api_Model_Rules setResourceId(string $value) - * @method string getPrivileges() - * @method Mage_Api_Model_Rules setPrivileges(string $value) - * @method int getAssertId() - * @method Mage_Api_Model_Rules setAssertId(int $value) - * @method string getRoleType() - * @method Mage_Api_Model_Rules setRoleType(string $value) - * @method string getPermission() - * @method Mage_Api_Model_Rules setPermission(string $value) - * - * @category Mage - * @package Mage_Api - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api_Model_Rules extends Mage_Core_Model_Abstract -{ - protected function _construct() - { - $this->_init('Mage_Api_Model_Resource_Rules'); - } - - public function update() { - $this->getResource()->update($this); - return $this; - } - - public function getCollection() { - return Mage::getResourceModel('Mage_Api_Model_Resource_Permissions_Collection'); - } - - public function saveRel() { - $this->getResource()->saveRel($this); - return $this; - } -} diff --git a/app/code/core/Mage/Api/Model/Server.php b/app/code/core/Mage/Api/Model/Server.php deleted file mode 100644 index d5aabeeb63ae1a27cef8521d0c93f401131ed418..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api/Model/Server.php +++ /dev/null @@ -1,161 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Webservice api abstract - * - * @category Mage - * @package Mage_Api - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api_Model_Server -{ - - /** - * Api Name by Adapter - * @var string - */ - protected $_api = ""; - - /** - * Web service adapter - * - * @var Mage_Api_Model_Server_Adapter_Interface - */ - protected $_adapter; - - /** - * Complex retrieve adapter code by calling auxiliary model method - * - * @param string $alias Alias name - * @return string|null Returns NULL if no alias found - */ - public function getAdapterCodeByAlias($alias) - { - /** @var $config Mage_Api_Model_Config */ - $config = Mage::getSingleton('Mage_Api_Model_Config'); - $aliases = $config->getAdapterAliases(); - - if (!isset($aliases[$alias])) { - return null; - } - $object = Mage::getModel($aliases[$alias][0]); - $method = $aliases[$alias][1]; - - if (!method_exists($object, $method)) { - Mage::throwException(Mage::helper('Mage_Api_Helper_Data')->__('Can not find webservice adapter.')); - } - return $object->$method(); - } - - /** - * Initialize server components - * - * @param Mage_Api_Controller_Action $controller - * @param string $adapter Adapter name - * @param string $handler Handler name - * @return Mage_Api_Model_Server - */ - public function init(Mage_Api_Controller_Action $controller, $adapter = 'default', $handler = 'default') - { - $this->initialize($adapter, $handler); - - $this->_adapter->setController($controller); - - return $this; - } - - /** - * Initialize server components. Lightweight implementation of init() method - * - * @param string $adapterCode Adapter code - * @param string $handler OPTIONAL Handler name (if not specified, it will be found from config) - * @return Mage_Api_Model_Server - */ - public function initialize($adapterCode, $handler = null) - { - /** @var $helper Mage_Api_Model_Config */ - $helper = Mage::getSingleton('Mage_Api_Model_Config'); - $adapters = $helper->getActiveAdapters(); - - if (isset($adapters[$adapterCode])) { - /** @var $adapterModel Mage_Api_Model_Server_Adapter_Interface */ - $adapterModel = Mage::getModel((string) $adapters[$adapterCode]->model); - - if (!($adapterModel instanceof Mage_Api_Model_Server_Adapter_Interface)) { - Mage::throwException(Mage::helper('Mage_Api_Helper_Data')->__('Invalid webservice adapter specified.')); - } - $this->_adapter = $adapterModel; - $this->_api = $adapterCode; - - // get handler code from config if no handler passed as argument - if (null === $handler && !empty($adapters[$adapterCode]->handler)) { - $handler = (string) $adapters[$adapterCode]->handler; - } - $handlers = $helper->getHandlers(); - - if (!isset($handlers->$handler)) { - Mage::throwException(Mage::helper('Mage_Api_Helper_Data')->__('Invalid webservice handler specified.')); - } - $handlerClassName = Mage::getConfig()->getModelClassName((string) $handlers->$handler->model); - - $this->_adapter->setHandler($handlerClassName); - } else { - Mage::throwException(Mage::helper('Mage_Api_Helper_Data')->__('Invalid webservice adapter specified.')); - } - return $this; - } - - /** - * Run server - * - */ - public function run() - { - $this->getAdapter()->run(); - } - - /** - * Get Api name by Adapter - * @return string - */ - public function getApiName() - { - return $this->_api; - } - - /** - * Retrieve web service adapter - * - * @return Mage_Api_Model_Server_Adapter_Interface - */ - public function getAdapter() - { - return $this->_adapter; - } - - -} // Class Mage_Api_Model_Server_Abstract End diff --git a/app/code/core/Mage/Api/Model/Server/Adapter/Soap.php b/app/code/core/Mage/Api/Model/Server/Adapter/Soap.php deleted file mode 100644 index 5390e37ca6a6b373ce8d8a337385aa6f9ad94e84..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api/Model/Server/Adapter/Soap.php +++ /dev/null @@ -1,263 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Webservice soap adapter - * - * @category Mage - * @package Mage_Api - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api_Model_Server_Adapter_Soap - extends Varien_Object - implements Mage_Api_Model_Server_Adapter_Interface -{ - /** - * Soap server - * - * @var SoapServer - */ - protected $_soap = null; - - /** - * Set handler class name for webservice - * - * @param string $handler - * @return Mage_Api_Model_Server_Adapter_Soap - */ - public function setHandler($handler) - { - $this->setData('handler', $handler); - return $this; - } - - /** - * Retrive handler class name for webservice - * - * @return string - */ - public function getHandler() - { - return $this->getData('handler'); - } - - /** - * Set webservice api controller - * - * @param Mage_Api_Controller_Action $controller - * @return Mage_Api_Model_Server_Adapter_Soap - */ - public function setController(Mage_Api_Controller_Action $controller) - { - $this->setData('controller', $controller); - return $this; - } - - /** - * Retrive webservice api controller. If no controller have been set - emulate it by the use of Varien_Object - * - * @return Mage_Api_Controller_Action|Varien_Object - */ - public function getController() - { - $controller = $this->getData('controller'); - - if (null === $controller) { - $controller = new Varien_Object( - array('request' => Mage::app()->getRequest(), 'response' => Mage::app()->getResponse()) - ); - - $this->setData('controller', $controller); - } - return $controller; - } - - /** - * Run webservice - * - * @param Mage_Api_Controller_Action $controller - * @return Mage_Api_Model_Server_Adapter_Soap - */ - public function run() - { - $apiConfigCharset = Mage::getStoreConfig("api/config/charset"); - - if ($this->getController()->getRequest()->getParam('wsdl') !== null) { - // Generating wsdl content from template - $io = new Varien_Io_File(); - $io->open(array('path'=>Mage::getModuleDir('etc', 'Mage_Api'))); - - $wsdlContent = $io->read('wsdl.xml'); - - $template = Mage::getModel('Mage_Core_Model_Email_Template_Filter'); - - $wsdlConfig = new Varien_Object(); - $queryParams = $this->getController()->getRequest()->getQuery(); - if (isset($queryParams['wsdl'])) { - unset($queryParams['wsdl']); - } - - $wsdlConfig->setUrl(htmlspecialchars(Mage::getUrl('*/*/*', array('_query'=>$queryParams)))); - $wsdlConfig->setName('Magento'); - $wsdlConfig->setHandler($this->getHandler()); - - $template->setVariables(array('wsdl' => $wsdlConfig)); - - $this->getController()->getResponse() - ->clearHeaders() - ->setHeader('Content-Type','text/xml; charset='.$apiConfigCharset) - ->setBody( - preg_replace( - '/<\?xml version="([^\"]+)"([^\>]+)>/i', - '<?xml version="$1" encoding="'.$apiConfigCharset.'"?>', - $template->filter($wsdlContent) - ) - ); - } else { - try { - $this->_instantiateServer(); - - $this->getController()->getResponse() - ->clearHeaders() - ->setHeader('Content-Type','text/xml; charset='.$apiConfigCharset) - ->setBody( - preg_replace( - '/<\?xml version="([^\"]+)"([^\>]+)>/i', - '<?xml version="$1" encoding="'.$apiConfigCharset.'"?>', - $this->_soap->handle() - ) - ); - } catch( Zend_Soap_Server_Exception $e ) { - $this->fault( $e->getCode(), $e->getMessage() ); - } catch( Exception $e ) { - $this->fault( $e->getCode(), $e->getMessage() ); - } - } - - return $this; - } - - /** - * Dispatch webservice fault - * - * @param int $code - * @param string $message - */ - public function fault($code, $message) - { - if ($this->_extensionLoaded()) { - throw new SoapFault($code, $message); - } else { - die('<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> - <SOAP-ENV:Body> - <SOAP-ENV:Fault> - <faultcode>' . $code . '</faultcode> - <faultstring>' . $message . '</faultstring> - </SOAP-ENV:Fault> - </SOAP-ENV:Body> - </SOAP-ENV:Envelope>'); - } - - } - - /** - * Check whether Soap extension is loaded - * - * @return boolean - */ - protected function _extensionLoaded() - { - return class_exists('SoapServer', false); - } - - /** - * Transform wsdl url if $_SERVER["PHP_AUTH_USER"] is set - * - * @param array - * @return String - */ - protected function getWsdlUrl($params = null, $withAuth = true) - { - $urlModel = Mage::getModel('Mage_Core_Model_Url') - ->setUseSession(false); - - $wsdlUrl = $params !== null - ? $urlModel->getUrl('*/*/*', array('_current' => true, '_query' => $params)) - : $urlModel->getUrl('*/*/*'); - - if( $withAuth ) { - $phpAuthUser = $this->getController()->getRequest()->getServer('PHP_AUTH_USER', false); - $phpAuthPw = $this->getController()->getRequest()->getServer('PHP_AUTH_PW', false); - - if ($phpAuthUser && $phpAuthPw) { - $wsdlUrl = sprintf("http://%s:%s@%s", $phpAuthUser, $phpAuthPw, str_replace('http://', '', $wsdlUrl )); - } - } - - return $wsdlUrl; - } - - /** - * Try to instantiate Zend_Soap_Server - * If schema import error is caught, it will retry in 1 second. - * - * @throws Zend_Soap_Server_Exception - */ - protected function _instantiateServer() - { - $apiConfigCharset = Mage::getStoreConfig('api/config/charset'); - $wsdlCacheEnabled = (bool) Mage::getStoreConfig('api/config/wsdl_cache_enabled'); - - if ($wsdlCacheEnabled) { - ini_set('soap.wsdl_cache_enabled', '1'); - } else { - ini_set('soap.wsdl_cache_enabled', '0'); - } - - $tries = 0; - do { - $retry = false; - try { - $this->_soap = new Zend_Soap_Server($this->getWsdlUrl(array("wsdl" => 1)), - array('encoding' => $apiConfigCharset)); - } catch (SoapFault $e) { - if (false !== strpos($e->getMessage(), - "can't import schema from 'http://schemas.xmlsoap.org/soap/encoding/'") - ) { - $retry = true; - sleep(1); - } else { - throw $e; - } - $tries++; - } - } while ($retry && $tries < 5); - use_soap_error_handler(false); - $this->_soap - ->setReturnResponse(true) - ->setClass($this->getHandler()); - } -} diff --git a/app/code/core/Mage/Api/Model/Server/Adapter/Xmlrpc.php b/app/code/core/Mage/Api/Model/Server/Adapter/Xmlrpc.php deleted file mode 100644 index c9bcfed0f9ee5ade9177e273e24e558192970492..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api/Model/Server/Adapter/Xmlrpc.php +++ /dev/null @@ -1,127 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Webservice XmlRpc adapter - * - * @category Mage - * @package Mage_Api - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api_Model_Server_Adapter_Xmlrpc - extends Varien_Object - implements Mage_Api_Model_Server_Adapter_Interface -{ - /** - * XmlRpc Server - * - * @var Zend_XmlRpc_Server - */ - protected $_xmlRpc = null; - - /** - * Set handler class name for webservice - * - * @param string $handler - * @return Mage_Api_Model_Server_Adapter_Xmlrpc - */ - public function setHandler($handler) - { - $this->setData('handler', $handler); - return $this; - } - - /** - * Retrive handler class name for webservice - * - * @return string - */ - public function getHandler() - { - return $this->getData('handler'); - } - - /** - * Set webservice api controller - * - * @param Mage_Api_Controller_Action $controller - * @return Mage_Api_Model_Server_Adapter_Xmlrpc - */ - public function setController(Mage_Api_Controller_Action $controller) - { - $this->setData('controller', $controller); - return $this; - } - - /** - * Retrive webservice api controller. If no controller have been set - emulate it by the use of Varien_Object - * - * @return Mage_Api_Controller_Action|Varien_Object - */ - public function getController() - { - $controller = $this->getData('controller'); - - if (null === $controller) { - $controller = new Varien_Object( - array('request' => Mage::app()->getRequest(), 'response' => Mage::app()->getResponse()) - ); - - $this->setData('controller', $controller); - } - return $controller; - } - - /** - * Run webservice - * - * @return Mage_Api_Model_Server_Adapter_Xmlrpc - */ - public function run() - { - $apiConfigCharset = Mage::getStoreConfig("api/config/charset"); - - $this->_xmlRpc = new Zend_XmlRpc_Server(); - $this->_xmlRpc->setEncoding($apiConfigCharset) - ->setClass($this->getHandler()); - $this->getController()->getResponse() - ->clearHeaders() - ->setHeader('Content-Type','text/xml; charset='.$apiConfigCharset) - ->setBody($this->_xmlRpc->handle()); - return $this; - } - - /** - * Dispatch webservice fault - * - * @param int $code - * @param string $message - */ - public function fault($code, $message) - { - throw new Zend_XmlRpc_Server_Exception($message, $code); - } -} // Class Mage_Api_Model_Server_Adapter_Xmlrpc End diff --git a/app/code/core/Mage/Api/Model/Server/Handler.php b/app/code/core/Mage/Api/Model/Server/Handler.php deleted file mode 100644 index 8b1044ae6b6ba3f2a0d3bc9a86a74458c5c6719e..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api/Model/Server/Handler.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Webservices default server handler - * - * @category Mage - * @package Mage_Api - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api_Model_Server_Handler extends Mage_Api_Model_Server_Handler_Abstract -{ - -} // Class Mage_Api_Model_Server_Handler End diff --git a/app/code/core/Mage/Api/Model/Server/Handler/Abstract.php b/app/code/core/Mage/Api/Model/Server/Handler/Abstract.php deleted file mode 100644 index a398fed0f21f186e30d5e703ccc64c74671bc4e2..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api/Model/Server/Handler/Abstract.php +++ /dev/null @@ -1,546 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Webservice default handler - * - * @category Mage - * @package Mage_Api - * @author Magento Core Team <core@magentocommerce.com> - */ -abstract class Mage_Api_Model_Server_Handler_Abstract -{ - protected $_resourceSuffix = null; - - public function __construct() - { - set_error_handler(array($this, 'handlePhpError'), E_ALL); - Mage::app()->loadAreaPart(Mage_Core_Model_App_Area::AREA_ADMIN, Mage_Core_Model_App_Area::PART_EVENTS); - } - - public function handlePhpError($errorCode, $errorMessage, $errorFile) - { - Mage::log($errorMessage . $errorFile); - if (in_array($errorCode, array(E_ERROR, E_USER_ERROR, E_RECOVERABLE_ERROR))) { - $this->_fault('internal'); - } - return true; - } - - - /** - * Retrive webservice session - * - * @return Mage_Api_Model_Session - */ - protected function _getSession() - { - return Mage::getSingleton('Mage_Api_Model_Session'); - } - - /** - * Retrive webservice configuration - * - * @return Mage_Api_Model_Config - */ - protected function _getConfig() - { - return Mage::getSingleton('Mage_Api_Model_Config'); - } - - /** - * Retrive webservice server - * - * @return Mage_Api_Model_Server - */ - protected function _getServer() - { - return Mage::getSingleton('Mage_Api_Model_Server'); - } - - /** - * Start webservice session - * - * @param string $sessionId - * @return Mage_Api_Model_Server_Handler_Abstract - */ - protected function _startSession($sessionId=null) - { - $this->_getSession()->setSessionId($sessionId); - $this->_getSession()->init('api', 'api'); - return $this; - } - - /** - * Check current user permission on resource and privilege - * - * - * @param string $resource - * @param string $privilege - * @return bool - */ - protected function _isAllowed($resource, $privilege=null) - { - return $this->_getSession()->isAllowed($resource, $privilege); - } - - /** - * Check session expiration - * - * @return boolean - */ - protected function _isSessionExpired () - { - return $this->_getSession()->isSessionExpired(); - } - - /** - * Dispatch webservice fault - * - * @param string $faultName - * @param string $resourceName - * @param string $customMessage - */ - protected function _fault($faultName, $resourceName=null, $customMessage=null) - { - $faults = $this->_getConfig()->getFaults($resourceName); - if (!isset($faults[$faultName]) && !is_null($resourceName)) { - $this->_fault($faultName); - return; - } elseif (!isset($faults[$faultName])) { - $this->_fault('unknown'); - return; - } - $this->_getServer()->getAdapter()->fault( - $faults[$faultName]['code'], - (is_null($customMessage) ? $faults[$faultName]['message'] : $customMessage) - ); - } - - /** - * Retrive webservice fault as array - * - * @param string $faultName - * @param string $resourceName - * @param string $customMessage - * @return array - */ - protected function _faultAsArray($faultName, $resourceName=null, $customMessage=null) - { - $faults = $this->_getConfig()->getFaults($resourceName); - if (!isset($faults[$faultName]) && !is_null($resourceName)) { - return $this->_faultAsArray($faultName); - } elseif (!isset($faults[$faultName])) { - return $this->_faultAsArray('unknown'); - } - - return array( - 'isFault' => true, - 'faultCode' => $faults[$faultName]['code'], - 'faultMessage' => (is_null($customMessage) ? $faults[$faultName]['message'] : $customMessage) - ); - } - - /** - * Start web service session - * - * @return string - */ - public function startSession() - { - $this->_startSession(); - return $this->_getSession()->getSessionId(); - } - - - /** - * End web service session - * - * @param string $sessionId - * @return boolean - */ - public function endSession($sessionId) - { - $this->_startSession($sessionId); - $this->_getSession()->clear(); - return true; - } - - /** - * Enter description here... - * - * @param string $resource - * @return string - */ - protected function _prepareResourceModelName($resource) - { - if (null !== $this->_resourceSuffix) { - return $resource . $this->_resourceSuffix; - } - return $resource; - } - - /** - * Login user and Retrieve session id - * - * @param string $username - * @param string $apiKey - * @return string - */ - public function login($username, $apiKey = null) - { - if (empty($username) || empty($apiKey)) { - return $this->_fault('invalid_request_param'); - } - - try { - $this->_startSession(); - $this->_getSession()->login($username, $apiKey); - } catch (Exception $e) { - return $this->_fault('access_denied'); - } - return $this->_getSession()->getSessionId(); - } - - /** - * Call resource functionality - * - * @param string $sessionId - * @param string $apiPath - * @param array $args - * @return mixed - */ - public function call($sessionId, $apiPath, $args = array()) - { - $this->_startSession($sessionId); - - if (!$this->_getSession()->isLoggedIn($sessionId)) { - return $this->_fault('session_expired'); - } - - list($resourceName, $methodName) = explode('.', $apiPath); - - if (empty($resourceName) || empty($methodName)) { - return $this->_fault('resource_path_invalid'); - } - - $resourcesAlias = $this->_getConfig()->getResourcesAlias(); - $resources = $this->_getConfig()->getResources(); - if (isset($resourcesAlias->$resourceName)) { - $resourceName = (string) $resourcesAlias->$resourceName; - } - - if (!isset($resources->$resourceName) - || !isset($resources->$resourceName->methods->$methodName)) { - return $this->_fault('resource_path_invalid'); - } - - if (!isset($resources->$resourceName->public) - && isset($resources->$resourceName->acl) - && !$this->_isAllowed((string)$resources->$resourceName->acl)) { - return $this->_fault('access_denied'); - - } - - - if (!isset($resources->$resourceName->methods->$methodName->public) - && isset($resources->$resourceName->methods->$methodName->acl) - && !$this->_isAllowed((string)$resources->$resourceName->methods->$methodName->acl)) { - return $this->_fault('access_denied'); - } - - $methodInfo = $resources->$resourceName->methods->$methodName; - - try { - $method = (isset($methodInfo->method) ? (string) $methodInfo->method : $methodName); - - $modelName = $this->_prepareResourceModelName((string) $resources->$resourceName->model); - try { - $model = Mage::getModel($modelName); - if ($model instanceof Mage_Api_Model_Resource_Abstract) { - $model->setResourceConfig($resources->$resourceName); - } - } catch (Exception $e) { - throw new Mage_Api_Exception('resource_path_not_callable'); - } - - if (method_exists($model, $method)) { - if (isset($methodInfo->arguments) && ((string)$methodInfo->arguments) == 'array') { - return $model->$method((is_array($args) ? $args : array($args))); - } elseif (!is_array($args)) { - return $model->$method($args); - } else { - return call_user_func_array(array(&$model, $method), $args); - } - } else { - throw new Mage_Api_Exception('resource_path_not_callable'); - } - } catch (Mage_Api_Exception $e) { - return $this->_fault($e->getMessage(), $resourceName, $e->getCustomMessage()); - } catch (Exception $e) { - Mage::logException($e); - return $this->_fault('internal', null, $e->getMessage()); - } - } - - /** - * Multiple calls of resource functionality - * - * @param string $sessionId - * @param array $calls - * @param array $options - * @return array - */ - public function multiCall($sessionId, array $calls = array(), $options = array()) - { - $this->_startSession($sessionId); - - if (!$this->_getSession()->isLoggedIn($sessionId)) { - return $this->_fault('session_expired'); - } - - $result = array(); - - $resourcesAlias = $this->_getConfig()->getResourcesAlias(); - $resources = $this->_getConfig()->getResources(); - - foreach ($calls as $call) { - if (!isset($call[0])) { - $result[] = $this->_faultAsArray('resource_path_invalid'); - if (isset($options['break']) && $options['break']==1) { - break; - } else { - continue; - } - } - - $apiPath = $call[0]; - $args = (isset($call[1]) ? $call[1] : array()); - - list($resourceName, $methodName) = explode('.', $apiPath); - - if (empty($resourceName) || empty($methodName)) { - $result[] = $this->_faultAsArray('resource_path_invalid'); - if (isset($options['break']) && $options['break']==1) { - break; - } else { - continue; - } - } - - if (isset($resourcesAlias->$resourceName)) { - $resourceName = (string) $resourcesAlias->$resourceName; - } - - if (!isset($resources->$resourceName) - || !isset($resources->$resourceName->methods->$methodName)) { - $result[] = $this->_faultAsArray('resource_path_invalid'); - if (isset($options['break']) && $options['break']==1) { - break; - } else { - continue; - } - } - - if (!isset($resources->$resourceName->public) - && isset($resources->$resourceName->acl) - && !$this->_isAllowed((string)$resources->$resourceName->acl)) { - $result[] = $this->_faultAsArray('access_denied'); - if (isset($options['break']) && $options['break']==1) { - break; - } else { - continue; - } - } - - - if (!isset($resources->$resourceName->methods->$methodName->public) - && isset($resources->$resourceName->methods->$methodName->acl) - && !$this->_isAllowed((string)$resources->$resourceName->methods->$methodName->acl)) { - $result[] = $this->_faultAsArray('access_denied'); - if (isset($options['break']) && $options['break']==1) { - break; - } else { - continue; - } - } - - $methodInfo = $resources->$resourceName->methods->$methodName; - - try { - $method = (isset($methodInfo->method) ? (string) $methodInfo->method : $methodName); - - $modelName = $this->_prepareResourceModelName((string) $resources->$resourceName->model); - try { - $model = Mage::getModel($modelName); - } catch (Exception $e) { - throw new Mage_Api_Exception('resource_path_not_callable'); - } - - if (method_exists($model, $method)) { - if (isset($methodInfo->arguments) && ((string)$methodInfo->arguments) == 'array') { - $result[] = $model->$method((is_array($args) ? $args : array($args))); - } elseif (!is_array($args)) { - $result[] = $model->$method($args); - } else { - $result[] = call_user_func_array(array(&$model, $method), $args); - } - } else { - throw new Mage_Api_Exception('resource_path_not_callable'); - } - } catch (Mage_Api_Exception $e) { - $result[] = $this->_faultAsArray($e->getMessage(), $resourceName, $e->getCustomMessage()); - if (isset($options['break']) && $options['break']==1) { - break; - } else { - continue; - } - } catch (Exception $e) { - Mage::logException($e); - $result[] = $this->_faultAsArray('internal'); - if (isset($options['break']) && $options['break']==1) { - break; - } else { - continue; - } - } - } - - return $result; - } - - /** - * List of available resources - * - * @param string $sessionId - * @return array - */ - public function resources($sessionId) - { - $this->_startSession($sessionId); - - if (!$this->_getSession()->isLoggedIn($sessionId)) { - return $this->_fault('session_expired'); - } - - $resources = array(); - - $resourcesAlias = array(); - foreach ($this->_getConfig()->getResourcesAlias() as $alias => $resourceName) { - $resourcesAlias[(string) $resourceName][] = $alias; - } - - - foreach ($this->_getConfig()->getResources() as $resourceName => $resource) { - if (isset($resource->acl) && !$this->_isAllowed((string) $resource->acl)) { - continue; - } - - $methods = array(); - foreach ($resource->methods->children() as $methodName => $method) { - if (isset($method->acl) && !$this->_isAllowed((string) $method->acl)) { - continue; - } - $methodAliases = array(); - if (isset($resourcesAlias[$resourceName])) { - foreach ($resourcesAlias[$resourceName] as $alias) { - $methodAliases[] = $alias . '.' . $methodName; - } - } - - $methods[] = array( - 'title' => (string) $method->title, - 'description' => (isset($method->description) ? (string)$method->description : null), - 'path' => $resourceName . '.' . $methodName, - 'name' => $methodName, - 'aliases' => $methodAliases - ); - } - - if (count($methods) == 0) { - continue; - } - - $resources[] = array( - 'title' => (string) $resource->title, - 'description' => (isset($resource->description) ? (string)$resource->description : null), - 'name' => $resourceName, - 'aliases' => (isset($resourcesAlias[$resourceName]) ? $resourcesAlias[$resourceName] : array()), - 'methods' => $methods - ); - } - - return $resources; - } - - /** - * List of resource faults - * - * @param string $sessionId - * @param string $resourceName - * @return array - */ - public function resourceFaults($sessionId, $resourceName) - { - $this->_startSession($sessionId); - - if (!$this->_getSession()->isLoggedIn($sessionId)) { - return $this->_fault('session_expired'); - } - - $resourcesAlias = $this->_getConfig()->getResourcesAlias(); - $resources = $this->_getConfig()->getResources(); - - if (isset($resourcesAlias->$resourceName)) { - $resourceName = (string) $resourcesAlias->$resourceName; - } - - - if (empty($resourceName) - || !isset($resources->$resourceName)) { - return $this->_fault('resource_path_invalid'); - } - - if (isset($resources->$resourceName->acl) - && !$this->_isAllowed((string)$resources->$resourceName->acl)) { - return $this->_fault('access_denied'); - } - - return array_values($this->_getConfig()->getFaults($resourceName)); - } - - /** - * List of global faults - * - * @param string $sessionId - * @return array - */ - public function globalFaults($sessionId) - { - $this->_startSession($sessionId); - return array_values($this->_getConfig()->getFaults()); - } -} // Class Mage_Api_Model_Server_Handler_Abstract End diff --git a/app/code/core/Mage/Api/Model/Server/V2/Adapter/Soap.php b/app/code/core/Mage/Api/Model/Server/V2/Adapter/Soap.php deleted file mode 100644 index c4176cc4708fbfee5ecd006f7c78257a0b49e49b..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api/Model/Server/V2/Adapter/Soap.php +++ /dev/null @@ -1,83 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Webservice soap adapter - * - * @category Mage - * @package Mage_Api - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api_Model_Server_V2_Adapter_Soap extends Mage_Api_Model_Server_Adapter_Soap -{ - /** - * Run webservice - * - * @param Mage_Api_Controller_Action $controller - * @return Mage_Api_Model_Server_Adapter_Soap - */ - public function run() - { - $apiConfigCharset = Mage::getStoreConfig("api/config/charset"); - - if ($this->getController()->getRequest()->getParam('wsdl') !== null) { - $wsdlConfig = Mage::getModel('Mage_Api_Model_Wsdl_Config'); - $wsdlConfig->setHandler($this->getHandler()) - ->init(); - $this->getController()->getResponse() - ->clearHeaders() - ->setHeader('Content-Type','text/xml; charset='.$apiConfigCharset) - ->setBody( - preg_replace( - '/<\?xml version="([^\"]+)"([^\>]+)>/i', - '<?xml version="$1" encoding="'.$apiConfigCharset.'"?>', - $wsdlConfig->getWsdlContent() - ) - ); - } else { - try { - $this->_instantiateServer(); - - $this->getController()->getResponse() - ->clearHeaders() - ->setHeader('Content-Type','text/xml; charset='.$apiConfigCharset) - ->setBody( - preg_replace( - '/<\?xml version="([^\"]+)"([^\>]+)>/i', - '<?xml version="$1" encoding="'.$apiConfigCharset.'"?>', - $this->_soap->handle() - ) - ); - } catch( Zend_Soap_Server_Exception $e ) { - $this->fault( $e->getCode(), $e->getMessage() ); - } catch( Exception $e ) { - $this->fault( $e->getCode(), $e->getMessage() ); - } - } - - return $this; - } -} diff --git a/app/code/core/Mage/Api/Model/Server/Wsi/Adapter/Soap.php b/app/code/core/Mage/Api/Model/Server/Wsi/Adapter/Soap.php deleted file mode 100644 index 9102900f3ecdb43950c95459f721b4cf7a7957da..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api/Model/Server/Wsi/Adapter/Soap.php +++ /dev/null @@ -1,103 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Webservice soap adapter - * - * @category Mage - * @package Mage_Api - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api_Model_Server_Wsi_Adapter_Soap extends Mage_Api_Model_Server_Adapter_Soap -{ - /** - * Run webservice - * - * @param Mage_Api_Controller_Action $controller - * @return Mage_Api_Model_Server_Adapter_Soap - */ - public function run() - { - $apiConfigCharset = Mage::getStoreConfig("api/config/charset"); - - if ($this->getController()->getRequest()->getParam('wsdl') !== null) { - $wsdlConfig = Mage::getModel('Mage_Api_Model_Wsdl_Config'); - $wsdlConfig->setHandler($this->getHandler()) - ->init(); - $this->getController()->getResponse() - ->clearHeaders() - ->setHeader('Content-Type','text/xml; charset='.$apiConfigCharset) - ->setBody( - preg_replace( - '/(\>\<)/i', - ">\n<", - str_replace( - '<soap:operation soapAction=""></soap:operation>', - "<soap:operation soapAction=\"\" />\n", - str_replace( - '<soap:body use="literal"></soap:body>', - "<soap:body use=\"literal\" />\n", - preg_replace( - '/<\?xml version="([^\"]+)"([^\>]+)>/i', - '<?xml version="$1" encoding="'.$apiConfigCharset.'"?>', - $wsdlConfig->getWsdlContent() - ) - ) - ) - ) - ); - } else { - try { - $this->_instantiateServer(); - - $this->getController()->getResponse() - ->clearHeaders() - ->setHeader('Content-Type','text/xml; charset='.$apiConfigCharset) - ->setBody( - str_replace( - '<soap:operation soapAction=""></soap:operation>', - "<soap:operation soapAction=\"\" />\n", - str_replace( - '<soap:body use="literal"></soap:body>', - "<soap:body use=\"literal\" />\n", - preg_replace( - '/<\?xml version="([^\"]+)"([^\>]+)>/i', - '<?xml version="$1" encoding="'.$apiConfigCharset.'"?>', - $this->_soap->handle() - ) - ) - ) - ); - } catch( Zend_Soap_Server_Exception $e ) { - $this->fault( $e->getCode(), $e->getMessage() ); - } catch( Exception $e ) { - $this->fault( $e->getCode(), $e->getMessage() ); - } - } - - return $this; - } -} diff --git a/app/code/core/Mage/Api/Model/Server/Wsi/Handler.php b/app/code/core/Mage/Api/Model/Server/Wsi/Handler.php deleted file mode 100644 index e7deb22020857237eb5ed3b27c2db5625cd5b1f2..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api/Model/Server/Wsi/Handler.php +++ /dev/null @@ -1,179 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Webservices server handler WSI - * - * @category Mage - * @package Mage_Api - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api_Model_Server_Wsi_Handler extends Mage_Api_Model_Server_Handler_Abstract -{ - protected $_resourceSuffix = '_v2'; - - /** - * Interceptor for all interfaces - * - * @param string $function - * @param array $args - */ - - public function __call ($function, $args) - { - $args = $args[0]; - - /** @var Mage_Api_Helper_Data */ - $helper = Mage::helper('Mage_Api_Helper_Data'); - - $helper->wsiArrayUnpacker($args); - $args = get_object_vars($args); - - if(isset($args['sessionId'])){ - $sessionId = $args['sessionId']; - unset($args['sessionId']); - } else { - // Was left for backward compatibility. - $sessionId = array_shift( $args ); - } - - $apiKey = ''; - $nodes = Mage::getSingleton('Mage_Api_Model_Config')->getNode('v2/resources_function_prefix')->children(); - foreach ($nodes as $resource => $prefix) { - $prefix = $prefix->asArray(); - if (false !== strpos($function, $prefix)) { - $method = substr($function, strlen($prefix)); - $apiKey = $resource . '.' . strtolower($method[0]).substr($method, 1); - } - } - - list($modelName, $methodName) = $this->_getResourceName($apiKey); - $methodParams = $this->getMethodParams($modelName, $methodName); - - $args = $this->prepareArgs($methodParams, $args); - - $res = $this->call($sessionId, $apiKey, $args); - - $obj = $helper->wsiArrayPacker($res); - $stdObj = new stdClass(); - $stdObj->result = $obj; - - return $stdObj; - } - - /** - * Login user and Retrieve session id - * - * @param string $username - * @param string $apiKey - * @return string - */ - public function login($username, $apiKey = null) - { - if (is_object($username)) { - $apiKey = $username->apiKey; - $username = $username->username; - } - - $stdObject = new stdClass(); - $stdObject->result = parent::login($username, $apiKey); - return $stdObject; - } - - /** - * Return called class and method names - * - * @param String $apiPath - * @return Array - */ - protected function _getResourceName($apiPath){ - - list($resourceName, $methodName) = explode('.', $apiPath); - - if (empty($resourceName) || empty($methodName)) { - return $this->_fault('resource_path_invalid'); - } - - $resourcesAlias = $this->_getConfig()->getResourcesAlias(); - $resources = $this->_getConfig()->getResources(); - if (isset($resourcesAlias->$resourceName)) { - $resourceName = (string) $resourcesAlias->$resourceName; - } - - $methodInfo = $resources->$resourceName->methods->$methodName; - - $modelName = $this->_prepareResourceModelName((string) $resources->$resourceName->model); - - $modelClass = Mage::getConfig()->getModelClassName($modelName); - - $method = (isset($methodInfo->method) ? (string) $methodInfo->method : $methodName); - - return array($modelClass, $method); - } - - /** - * Return an array of parameters for the callable method. - * - * @param String $modelName - * @param String $methodName - * @return Array of ReflectionParameter - */ - public function getMethodParams($modelName, $methodName) { - - $method = new ReflectionMethod($modelName, $methodName); - - return $method->getParameters(); - } - - /** - * Prepares arguments for the method calling. Sort in correct order, set default values for omitted parameters. - * - * @param Array $params - * @param Array $args - * @return Array - */ - public function prepareArgs($params, $args) { - - $callArgs = array(); - - /** @var $parameter ReflectionParameter */ - foreach($params AS $parameter){ - $pName = $parameter->getName(); - if( isset( $args[$pName] ) ){ - $callArgs[$pName] = $args[$pName]; - } else { - if($parameter->isOptional()){ - $callArgs[$pName] = $parameter->getDefaultValue(); - } else { - Mage::logException(new Exception("Required parameter \"$pName\" is missing.", 0)); - $this->_fault('invalid_request_param'); - } - } - } - return $callArgs; - } - -} diff --git a/app/code/core/Mage/Api/Model/Session.php b/app/code/core/Mage/Api/Model/Session.php deleted file mode 100644 index 4e779886d21abcfcc7bdf9c0b509749da4b3a77d..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api/Model/Session.php +++ /dev/null @@ -1,207 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Webservice api session - * - * @category Mage - * @package Mage_Api - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api_Model_Session extends Mage_Core_Model_Session_Abstract -{ - public $sessionIds = array(); - protected $_currentSessId = null; - - public function start($sessionName=null) - { -// parent::start($sessionName=null); - $this->_currentSessId = md5(time() . uniqid('', true) . $sessionName); - $this->sessionIds[] = $this->getSessionId(); - return $this; - } - - public function init($namespace, $sessionName=null) - { - if (is_null($this->_currentSessId)) { - $this->start(); - } - return $this; - } - - public function getSessionId() - { - return $this->_currentSessId; - } - - public function setSessionId($sessId = null) - { - if (!is_null($sessId)) { - $this->_currentSessId = $sessId; - } - return $this; - } - - public function revalidateCookie() - { - // In api we don't use cookies - } - - public function clear() { - if ($sessId = $this->getSessionId()) { - try { - Mage::getModel('Mage_Api_Model_User')->logoutBySessId($sessId); - } catch (Exception $e) { - return false; - } - } - return true; - } - - public function login($username, $apiKey) - { - $user = Mage::getModel('Mage_Api_Model_User') - ->setSessid($this->getSessionId()) - ->login($username, $apiKey); - - if ( $user->getId() && $user->getIsActive() != '1' ) { - Mage::throwException(Mage::helper('Mage_Api_Helper_Data')->__('Your account has been deactivated.')); - } elseif (!Mage::getModel('Mage_Api_Model_User')->hasAssigned2Role($user->getId())) { - Mage::throwException(Mage::helper('Mage_Api_Helper_Data')->__('Access denied.')); - } else { - if ($user->getId()) { - $this->setUser($user); - $this->setAcl(Mage::getResourceModel('Mage_Api_Model_Resource_Acl')->loadAcl()); - } else { - Mage::throwException(Mage::helper('Mage_Api_Helper_Data')->__('Unable to login.')); - } - } - - return $user; - } - - public function refreshAcl($user=null) - { - if (is_null($user)) { - $user = $this->getUser(); - } - if (!$user) { - return $this; - } - if (!$this->getAcl() || $user->getReloadAclFlag()) { - $this->setAcl(Mage::getResourceModel('Mage_Api_Model_Resource_Acl')->loadAcl()); - } - if ($user->getReloadAclFlag()) { - $user->unsetData('api_key'); - $user->setReloadAclFlag('0')->save(); - } - return $this; - } - - /** - * Check current user permission on resource and privilege - * - * - * @param string $resource - * @param string $privilege - * @return bool - */ - public function isAllowed($resource, $privilege=null) - { - $user = $this->getUser(); - $acl = $this->getAcl(); - - if ($user && $acl) { - try { - if ($acl->isAllowed($user->getAclRole(), 'all', null)){ - return true; - } - } catch (Exception $e) {} - - try { - return $acl->isAllowed($user->getAclRole(), $resource, $privilege); - } catch (Exception $e) { - return false; - } - } - return false; - } - - /** - * Check session expiration - * - * @return boolean - */ - public function isSessionExpired ($user) - { - if (!$user->getId()) { - return true; - } - $timeout = strtotime( now() ) - strtotime( $user->getLogdate() ); - return $timeout > Mage::getStoreConfig('api/config/session_timeout'); - } - - - public function isLoggedIn($sessId = false) - { - $userExists = $this->getUser() && $this->getUser()->getId(); - - if (!$userExists && $sessId !== false) { - return $this->_renewBySessId($sessId); - } - - if ($userExists) { - Mage::register('isSecureArea', true, true); - } - return $userExists; - } - - /** - * Renew user by session ID if session not expired - * - * @param string $sessId - * @return boolean - */ - protected function _renewBySessId ($sessId) - { - $user = Mage::getModel('Mage_Api_Model_User')->loadBySessId($sessId); - if (!$user->getId() || !$user->getSessid()) { - return false; - } - - if ($user->getSessid() == $sessId && !$this->isSessionExpired($user)) { - $this->setUser($user); - $this->setAcl(Mage::getResourceModel('Mage_Api_Model_Resource_Acl')->loadAcl()); - - $user->getResource()->recordLogin($user) - ->recordSession($user); - - return true; - } - return false; - } - -} // Class Mage_Api_Model_Session End diff --git a/app/code/core/Mage/Api/Model/User.php b/app/code/core/Mage/Api/Model/User.php deleted file mode 100644 index cd119b8ef6e50bd94b2b4bb492d3859401e72d91..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api/Model/User.php +++ /dev/null @@ -1,254 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Enter description here ... - * - * @method Mage_Api_Model_Resource_User _getResource() - * @method Mage_Api_Model_Resource_User getResource() - * @method string getFirstname() - * @method Mage_Api_Model_User setFirstname(string $value) - * @method string getLastname() - * @method Mage_Api_Model_User setLastname(string $value) - * @method string getEmail() - * @method Mage_Api_Model_User setEmail(string $value) - * @method string getUsername() - * @method Mage_Api_Model_User setUsername(string $value) - * @method string getApiKey() - * @method Mage_Api_Model_User setApiKey(string $value) - * @method string getCreated() - * @method Mage_Api_Model_User setCreated(string $value) - * @method string getModified() - * @method Mage_Api_Model_User setModified(string $value) - * @method int getLognum() - * @method Mage_Api_Model_User setLognum(int $value) - * @method int getReloadAclFlag() - * @method Mage_Api_Model_User setReloadAclFlag(int $value) - * @method int getIsActive() - * @method Mage_Api_Model_User setIsActive(int $value) - * - * @category Mage - * @package Mage_Api - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api_Model_User extends Mage_Core_Model_Abstract -{ - /** - * Prefix of model events names - * - * @var string - */ - protected $_eventPrefix = 'api_user'; - - protected function _construct() - { - $this->_init('Mage_Api_Model_Resource_User'); - } - - public function save() - { - $this->_beforeSave(); - $data = array( - 'firstname' => $this->getFirstname(), - 'lastname' => $this->getLastname(), - 'email' => $this->getEmail(), - 'modified' => Mage::getSingleton('Mage_Core_Model_Date')->gmtDate() - ); - - if($this->getId() > 0) { - $data['user_id'] = $this->getId(); - } - - if( $this->getUsername() ) { - $data['username'] = $this->getUsername(); - } - - if ($this->getApiKey()) { - $data['api_key'] = $this->_getEncodedApiKey($this->getApiKey()); - } - - if ($this->getNewApiKey()) { - $data['api_key'] = $this->_getEncodedApiKey($this->getNewApiKey()); - } - - if ( !is_null($this->getIsActive()) ) { - $data['is_active'] = intval($this->getIsActive()); - } - - $this->setData($data); - $this->_getResource()->save($this); - $this->_afterSave(); - return $this; - } - - public function delete() - { - $this->_beforeDelete(); - $this->_getResource()->delete($this); - $this->_afterDelete(); - return $this; - } - - public function saveRelations() - { - $this->_getResource()->_saveRelations($this); - return $this; - } - - public function getRoles() - { - return $this->_getResource()->_getRoles($this); - } - - public function deleteFromRole() - { - $this->_getResource()->deleteFromRole($this); - return $this; - } - - public function roleUserExists() - { - $result = $this->_getResource()->roleUserExists($this); - return ( is_array($result) && count($result) > 0 ) ? true : false; - } - - public function add() - { - $this->_getResource()->add($this); - return $this; - } - - public function userExists() - { - $result = $this->_getResource()->userExists($this); - return ( is_array($result) && count($result) > 0 ) ? true : false; - } - - public function getCollection() { - return Mage::getResourceModel('Mage_Api_Model_Resource_User_Collection'); - } - - public function getName($separator=' ') - { - return $this->getFirstname().$separator.$this->getLastname(); - } - - public function getId() - { - return $this->getUserId(); - } - - /** - * Get user ACL role - * - * @return string - */ - public function getAclRole() - { - return 'U'.$this->getUserId(); - } - - /** - * Authenticate user name and api key and save loaded record - * - * @param string $username - * @param string $apiKey - * @return boolean - */ - public function authenticate($username, $apiKey) - { - $this->loadByUsername($username); - if (!$this->getId()) { - return false; - } - $auth = Mage::helper('Mage_Core_Helper_Data')->validateHash($apiKey, $this->getApiKey()); - if ($auth) { - return true; - } else { - $this->unsetData(); - return false; - } - } - - /** - * Login user - * - * @param string $login - * @param string $apiKey - * @return Mage_Api_Model_User - */ - public function login($username, $apiKey) - { - $sessId = $this->getSessid(); - if ($this->authenticate($username, $apiKey)) { - $this->setSessid($sessId); - $this->getResource()->cleanOldSessions($this) - ->recordLogin($this) - ->recordSession($this); - Mage::dispatchEvent('api_user_authenticated', array( - 'model' => $this, - 'api_key' => $apiKey, - )); - } - - return $this; - } - - public function reload() - { - $this->load($this->getId()); - return $this; - } - - public function loadByUsername($username) - { - $this->setData($this->getResource()->loadByUsername($username)); - return $this; - } - - public function loadBySessId ($sessId) - { - $this->setData($this->getResource()->loadBySessId($sessId)); - return $this; - } - - public function logoutBySessId($sessid) - { - $this->getResource()->clearBySessId($sessid); - return $this; - } - - public function hasAssigned2Role($user) - { - return $this->getResource()->hasAssigned2Role($user); - } - - protected function _getEncodedApiKey($apiKey) - { - return Mage::helper('Mage_Core_Helper_Data')->getHash($apiKey, 2); - } - -} diff --git a/app/code/core/Mage/Api/Model/Wsdl/Config.php b/app/code/core/Mage/Api/Model/Wsdl/Config.php deleted file mode 100644 index 45df22c9d1eb3111bd6a868d02b363ba49fd03d6..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api/Model/Wsdl/Config.php +++ /dev/null @@ -1,144 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Wsdl config model - * - * @category Mage - * @package Mage_Api - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api_Model_Wsdl_Config extends Mage_Api_Model_Wsdl_Config_Base -{ - protected static $_namespacesPrefix = null; - - public function __construct($sourceData=null) - { - $this->setCacheId('wsdl_config_global'); - parent::__construct($sourceData); - } - - /** - * Return wsdl content - * - * @return string - */ - public function getWsdlContent() - { - return $this->_xml->asXML(); - } - - /** - * Return namespaces with their prefix - * - * @return array - */ - public static function getNamespacesPrefix() - { - if (is_null(self::$_namespacesPrefix)) { - self::$_namespacesPrefix = array(); - $config = Mage::getSingleton('Mage_Api_Model_Config')->getNode('v2/wsdl/prefix')->children(); - foreach ($config as $prefix => $namespace) { - self::$_namespacesPrefix[$namespace->asArray()] = $prefix; - } - } - return self::$_namespacesPrefix; - } - - public function getCache() - { - return Mage::app()->getCache(); - } - - protected function _loadCache($id) - { - return Mage::app()->loadCache($id); - } - - protected function _saveCache($data, $id, $tags=array(), $lifetime=false) - { - return Mage::app()->saveCache($data, $id, $tags, $lifetime); - } - - protected function _removeCache($id) - { - return Mage::app()->removeCache($id); - } - - public function init() - { - $this->setCacheChecksum(null); - $saveCache = true; - - if (Mage::app()->useCache('config')) { - $loaded = $this->loadCache(); - if ($loaded) { - return $this; - } - } - - $mergeWsdl = new Mage_Api_Model_Wsdl_Config_Base(); - $mergeWsdl->setHandler($this->getHandler()); - - if(Mage::helper('Mage_Api_Helper_Data')->isComplianceWSI()){ - /** - * Exclude Mage_Api wsdl xml file because it used for previous version - * of API wsdl declaration - */ - $mergeWsdl->addLoadedFile(Mage::getConfig()->getModuleDir('etc', "Mage_Api").DS.'wsi.xml'); - - $baseWsdlFile = Mage::getConfig()->getModuleDir('etc', "Mage_Api").DS.'wsi.xml'; - $this->loadFile($baseWsdlFile); - Mage::getConfig()->loadModulesConfiguration('wsi.xml', $this, $mergeWsdl); - } else { - /** - * Exclude Mage_Api wsdl xml file because it used for previous version - * of API wsdl declaration - */ - $mergeWsdl->addLoadedFile(Mage::getConfig()->getModuleDir('etc', "Mage_Api").DS.'wsdl.xml'); - - $baseWsdlFile = Mage::getConfig()->getModuleDir('etc', "Mage_Api").DS.'wsdl2.xml'; - $this->loadFile($baseWsdlFile); - Mage::getConfig()->loadModulesConfiguration('wsdl.xml', $this, $mergeWsdl); - } - - if (Mage::app()->useCache('config')) { - $this->saveCache(array('config')); - } - - return $this; - } - - /** - * Return Xml of node as string - * - * @return string - */ - public function getXmlString() - { - return $this->getNode()->asXML(); - } -} diff --git a/app/code/core/Mage/Api/Model/Wsdl/Config/Base.php b/app/code/core/Mage/Api/Model/Wsdl/Config/Base.php deleted file mode 100644 index cce9b124fe15a50e6f3bbbde103a740d93877350..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api/Model/Wsdl/Config/Base.php +++ /dev/null @@ -1,136 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Wsdl base config - * - * @category Mage - * @package Mage_Api - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api_Model_Wsdl_Config_Base extends Varien_Simplexml_Config -{ - protected $_handler = ''; - - /** - * @var Varien_Object - */ - protected $_wsdlVariables = null; - - protected $_loadedFiles = array(); - - public function __construct($sourceData=null) - { - $this->_elementClass = 'Mage_Api_Model_Wsdl_Config_Element'; - - // remove wsdl parameter from query - $queryParams = Mage::app()->getRequest()->getQuery(); - unset($queryParams['wsdl']); - - // set up default WSDL template variables - $this->_wsdlVariables = new Varien_Object( - array( - 'name' => 'Magento', - 'url' => htmlspecialchars(Mage::getUrl('*/*/*', array('_query' => $queryParams))) - ) - ); - parent::__construct($sourceData); - } - - /** - * Set handler - * - * @param string $handler - * @return Mage_Api_Model_Wsdl_Config_Base - */ - public function setHandler($handler) - { - $this->_handler = $handler; - return $this; - } - - /** - * Get handler - * - * @return string - */ - public function getHandler() - { - return $this->_handler; - } - - /** - * Processing file data - * - * @param string $text - * @return string - */ - public function processFileData($text) - { - /** @var $template Mage_Core_Model_Email_Template_Filter */ - $template = Mage::getModel('Mage_Core_Model_Email_Template_Filter'); - - $this->_wsdlVariables->setHandler($this->getHandler()); - - $template->setVariables(array('wsdl'=>$this->_wsdlVariables)); - - return $template->filter($text); - } - - public function addLoadedFile($file) - { - if (!in_array($file, $this->_loadedFiles)) { - $this->_loadedFiles[] = $file; - } - return $this; - } - - public function loadFile($file) - { - if (in_array($file, $this->_loadedFiles)) { - return false; - } - $res = parent::loadFile($file); - if ($res) { - $this->addLoadedFile($file); - } - return $this; - } - - /** - * Set variable to be used in WSDL template processing - * - * @param string $key Varible key - * @param string $value Variable value - * @return Mage_Api_Model_Wsdl_Config_Base - */ - public function setWsdlVariable($key, $value) - { - $this->_wsdlVariables->setData($key, $value); - - return $this; - } -} diff --git a/app/code/core/Mage/Api/Model/Wsdl/Config/Element.php b/app/code/core/Mage/Api/Model/Wsdl/Config/Element.php deleted file mode 100644 index 861adc09bfd8f6abce74ca72589cee3add8afd47..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api/Model/Wsdl/Config/Element.php +++ /dev/null @@ -1,265 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - - -/** - * Wsdl element model - * - * @category Mage - * @package Mage_Core - */ -class Mage_Api_Model_Wsdl_Config_Element extends Varien_Simplexml_Element -{ - public function extend($source, $overwrite=false) - { - if (!$source instanceof Varien_Simplexml_Element) { - return $this; - } - - foreach ($this->getChildren($source) as $namespace => $children) { - foreach ($children as $child) { - $this->extendChild($child, $overwrite, $namespace); - } - } - - return $this; - } - - /** - * Extends one node - * - * @param Varien_Simplexml_Element $source - * @param boolean $overwrite - * @return Varien_Simplexml_Element - */ - public function extendChild($source, $overwrite=false, $elmNamespace = '') - { - // this will be our new target node - $targetChild = null; - - // name of the source node - $sourceName = $source->getName(); - - // here we have children of our source node - $sourceChildren = $this->getChildren($source); - - if ($elmNamespace == '') { - $elmNamespace = null; - } - - if (!$source->hasChildren()) { - // handle string node - $elm = $this->getElementByName($source, $elmNamespace); - if (!is_null($elm)) { - - // if target already has children return without regard - if ($this->getChildren($elm)) { - return $this; - } - if ($overwrite) { -// unset($this->$sourceName); - unset($elm); - } else { - return $this; - } - } - $targetChild = $this->addChild($sourceName, $source->xmlentities(), $elmNamespace); - $targetChild->setParent($this); - foreach ($this->getAttributes($source) as $namespace => $attributes) { - foreach ($attributes as $key => $value) { - $_namespacesPrefix = Mage_Api_Model_Wsdl_Config::getNamespacesPrefix(); - if ($namespace == '') { - $namespace = null; - } elseif (array_key_exists($namespace, $_namespacesPrefix)) { - $key = $_namespacesPrefix[$namespace] . ':' . $key; - } - - $targetChild->addAttribute($key, $this->xmlentities($value), $namespace); - } - } - return $this; - } - - $elm = $this->getElementByName($source, $elmNamespace); - if (!is_null($elm)) { - $targetChild = $elm; - } - if (is_null($targetChild)) { - // if child target is not found create new and descend - $targetChild = $this->addChild($sourceName, null, $elmNamespace); - $targetChild->setParent($this); - foreach ($this->getAttributes($source) as $namespace => $attributes) { - foreach ($attributes as $key => $value) { - $_namespacesPrefix = Mage_Api_Model_Wsdl_Config::getNamespacesPrefix(); - if ($namespace == '') { - $namespace = null; - } elseif (array_key_exists($namespace, $_namespacesPrefix)) { - $key = $_namespacesPrefix[$namespace] . ':' . $key; - } - $targetChild->addAttribute($key, $this->xmlentities($value), $namespace); - } - } - } - - foreach ($sourceChildren as $elmNamespace => $children) { - foreach ($children as $childKey => $childNode) { - $targetChild->extendChild($childNode, $overwrite, $elmNamespace); - } - } - - return $this; - } - - /** - * Return attributes of all namespaces - * - * array( - * namespace => array( - * attribute_key => attribute_value, - * ... - * ) - * ) - * - * @param Varien_Simplexml_Element $source - * @return array - */ - public function getAttributes($source, $namespace = null) - { - $attributes = array(); - if (!is_null($namespace)) { - $attributes[$namespace] = $source->attributes($namespace); - return $attributes; - } - $namespaces = $source->getNamespaces(true); - $attributes[''] = $source->attributes(''); - foreach ($namespaces as $key => $value) { - if ($key == '' || $key == 'soap') { - continue; - } - $attributes[$value] = $source->attributes($value); - } - return $attributes; - } - - /** - * Return children of all namespaces - * - * @param Varien_Simplexml_Element $source - */ - public function getChildren($source) - { - $children = array(); - $namespaces = $source->getNamespaces(true); - - $isWsi = Mage::helper('Mage_Api_Helper_Data')->isComplianceWSI(); - - foreach ($namespaces as $key => $value) { - if ($key == '' || (!$isWsi && $key == 'wsdl')) { - continue; - } - $children[$value] = $source->children($value); - } - $children[''] = $source->children(''); - return $children; - } - - /** - * Return if has children - * - * @return boolean - */ - public function hasChildren() - { - if (!$this->getChildren($this)) { - return false; - } - - // simplexml bug: @attributes is in children() but invisible in foreach - foreach ($this->getChildren($this) as $namespace => $children) { - foreach ($children as $k => $child) { - return true; - } - } - return false; - } - - /** - * Return element by tag name, and checking attributes with namespaces - * - * @param Varien_Simplexml_Element $source - * @param string $namespace - * @return null|Varien_Simplexml_Element - */ - public function getElementByName($source, $elmNamespace = '') - { - $sourceName = $source->getName(); - $extendElmAttributes = $this->getAttributes($source); - foreach ($this->children($elmNamespace) as $k => $child) { - if ($child->getName() == $sourceName) { - $elm = true; - foreach ($extendElmAttributes as $namespace => $attributes) { - /** - * if count of attributes of extend element is 0 in $namespace, - * and current element has attributes in $namespace - different elements - */ -// if (!count($attributes) && count($this->getAttributes($child, $namespace))) { -// foreach ($this->getAttributes($child, $namespace) as $attribute) { -// $elm = false; -// break; -// } -// } - foreach ($attributes as $key => $value) { - if (is_null($child->getAttribute($key, $namespace)) || $child->getAttribute($key, $namespace) != $value) { - $elm = false; - } - } - } - /** - * if count of namespaces attributes of element to extend is 0, - * but current element has namespaces attributes - different elements - */ - if (!count($extendElmAttributes) && count($this->getAttributes($child))) { - $elm = false; - } - if ($elm) { - return $child; - } - } - } - return null; - } - - /** - * Returns attribute value by attribute name - * - * @return string - */ - public function getAttribute($name, $namespace = ''){ - $attrs = $this->attributes($namespace); - return isset($attrs[$name]) ? (string)$attrs[$name] : null; - } - -} diff --git a/app/code/core/Mage/Api/controllers/SoapController.php b/app/code/core/Mage/Api/controllers/SoapController.php deleted file mode 100644 index 0ee01d163534552179ee1acc70dcc494a86ec73f..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api/controllers/SoapController.php +++ /dev/null @@ -1,42 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Webservice main controller - * - * @category Mage - * @package Mage_Api - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api_SoapController extends Mage_Api_Controller_Action -{ - public function indexAction() - { - /* @var $server Mage_Api_Model_Server */ - $this->_getServer()->init($this, 'soap') - ->run(); - } -} // Class Mage_Api_IndexController End diff --git a/app/code/core/Mage/Api/controllers/V2/SoapController.php b/app/code/core/Mage/Api/controllers/V2/SoapController.php deleted file mode 100644 index 8b894736c31a0174d7af31e6671c31262c8c4ac4..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api/controllers/V2/SoapController.php +++ /dev/null @@ -1,48 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Webservice main controller - * - * @category Mage - * @package Mage_Api - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api_V2_SoapController extends Mage_Api_Controller_Action -{ - public function indexAction() - { - if(Mage::helper('Mage_Api_Helper_Data')->isComplianceWSI()){ - $handler_name = 'soap_wsi'; - } else { - $handler_name = 'soap_v2'; - } - - /* @var $server Mage_Api_Model_Server */ - $this->_getServer()->init($this, $handler_name, $handler_name) - ->run(); - } -} // Class Mage_Api_IndexController End diff --git a/app/code/core/Mage/Api/etc/api.xml b/app/code/core/Mage/Api/etc/api.xml deleted file mode 100644 index 59ab04d101ef39b87f0687a34fcb2bc1083f469c..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api/etc/api.xml +++ /dev/null @@ -1,287 +0,0 @@ -<?xml version="1.0"?> -<!-- -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Academic Free License (AFL 3.0) - * that is bundled with this package in the file LICENSE_AFL.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/afl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) - */ ---> -<config> - <api> - <adapter_aliases> - <v2_soap> - <suggest_class>Mage_Api_Helper_Data</suggest_class> - <suggest_method>getV2AdapterCode</suggest_method> - </v2_soap> - </adapter_aliases> - <adapters> - <soap> - <model>Mage_Api_Model_Server_Adapter_Soap</model> - <handler>default</handler> - <active>1</active> - <required> - <extensions> - <soap /> - </extensions> - </required> - </soap> - <soap_v2> - <model>Mage_Api_Model_Server_V2_Adapter_Soap</model> - <handler>soap_v2</handler> - <active>1</active> - <required> - <extensions> - <soap /> - </extensions> - </required> - </soap_v2> - <soap_wsi> - <model>Mage_Api_Model_Server_Wsi_Adapter_Soap</model> - <handler>soap_wsi</handler> - <active>1</active> - <required> - <extensions> - <soap /> - </extensions> - </required> - </soap_wsi> - <xmlrpc> - <model>Mage_Api_Model_Server_Adapter_Xmlrpc</model> - <handler>default</handler> - <active>1</active> - </xmlrpc> - <default> - <use>soap</use> - </default> - </adapters> - <handlers> - <default> - <model>Mage_Api_Model_Server_Handler</model> - </default> - <soap_v2> - <model>Mage_Api_Model_Server_V2_Handler</model> - </soap_v2> - <soap_wsi> - <model>Mage_Api_Model_Server_Wsi_Handler</model> - </soap_wsi> - </handlers> - <resources> - </resources> - <resources_alias> - </resources_alias> - <v2> - <wsdl> - <prefix> - <wsdl>http://schemas.xmlsoap.org/wsdl/</wsdl> - </prefix> - </wsdl> - </v2> - <faults> - <unknown> - <code>0</code> - <message>Unknown Error</message> - </unknown> - <internal> - <code>1</code> - <message>Internal Error. Please see log for details.</message> - </internal> - <access_denied> - <code>2</code> - <message>Access denied.</message> - </access_denied> - <resource_path_invalid> - <code>3</code> - <message>Invalid api path.</message> - </resource_path_invalid> - <resource_path_not_callable> - <code>4</code> - <message>Resource path is not callable.</message> - </resource_path_not_callable> - <session_expired> - <code>5</code> - <message>Session expired. Try to relogin.</message> - </session_expired> - <invalid_request_param> - <code>6</code> - <message>Required parameter is missing, for more details see "exception.log".</message> - </invalid_request_param> - </faults> - <acl> - <resources> - <all> - </all> - </resources> - - <privilegeSets> - <default> - <view descr="View entity"/> - <edit descr="Edit entity"/> - <delete descr="Delete entity"/> - <create descr="Create entity"/> - </default> - </privilegeSets> - </acl> - - <domain_messages> - <!-- module name --> - <core> - <!-- 200 --> - <success> - <ok>Request is executed.</ok> - </success> - <!-- 201 --> - <created> - <created>Request is executed. Created new resource.</created> - </created> - <!-- 202 --> - <processing> - <processing>Request is carried out.</processing> - </processing> - <!-- 400 --> - <validation> - <invalid_param>Parameter "%s" is not valid.</invalid_param> - </validation> - <!-- 400 --> - <request_error> - <!-- Client sent wrong API version --> - <invalid_api_version>API version "%s" not found.</invalid_api_version> - </request_error> - <!-- 401 --> - <authentication> - <protect_resource>You must provide an authenticated user for this method.</protect_resource> - <invalid_token>Token in request is not valid.</invalid_token> - </authentication> - <!-- 403 --> - <forbidden> - <api_key_invalid>Invalid API key</api_key_invalid> - </forbidden> - <!-- 404 --> - <not_found> - <item_not_found>Requested item %s not found.</item_not_found> - <resource_not_found>Requested resource %s not found.</resource_not_found> - </not_found> - <!-- 405 --> - <not_allowed> - <method_not_allowed>Method "%s" is not allowed.</method_not_allowed> - </not_allowed> - <!-- 406 --> - <not_acceptable> - <api_version_required>Api version is required.</api_version_required> - </not_acceptable> - <!-- 410 --> - <gone> - <!-- Message when client trying sent the API version which no longer maintained --> - <api_deprecated>API version "%s" is deprecated.</api_deprecated> - <!-- Message when client trying request the resource which no longer maintained --> - <deprecated>Resource "%s" is deprecated.</deprecated> - </gone> - - <!-- 500 --> - <internal_error> - <!-- Code error message not found or not exist --> - <unknown_error>There was unknown error while processing your request.</unknown_error> - <!-- Internal error when server catch some exception or language error --> - <internal_error>There was internal error while processing your request.</internal_error> - <!-- Developer mode message about error --> - <code_error>Server has internal error. %s: %s</code_error> - </internal_error> - <!-- 501 --> - <not_implemented> - <resource_not_implemented>This resource is not implemented so far.</resource_not_implemented> - <method_not_implemented>This method is not implemented so far.</method_not_implemented> - </not_implemented> - </core> - </domain_messages> - - <!-- Message Domains with relation to HTTP codes --> - <!-- The priority for domains is the HTTP code --> - <domain_codes> - <!-- All success messages except "entry_created", "processing" --> - <success> - <http_code>200</http_code> - <type>notification</type> - </success> - <!-- Messages when created new entry --> - <created> - <http_code>201</http_code> - <type>notification</type> - </created> - <!-- Processing messages --> - <processing> - <http_code>202</http_code> - <type>notification</type> - </processing> - - <!-- Validation messages --> - <validation> - <http_code>400</http_code> - <type>error</type> - </validation> - <!-- Messages when the request from a client has an error --> - <request_error> - <http_code>400</http_code> - <type>error</type> - </request_error> - <!-- Authentication error messages --> - <authentication> - <http_code>401</http_code> - <type>error</type> - </authentication> - <!-- Messages when post request is accepted but cannot performed --> - <forbidden> - <http_code>403</http_code> - <type>error</type> - </forbidden> - <!-- Messages when some data not found --> - <not_found> - <http_code>404</http_code> - <type>error</type> - </not_found> - <!-- Messages when some method is not allowed --> - <not_allowed> - <http_code>405</http_code> - <type>error</type> - </not_allowed> - <!-- Messages when some is not acceptable --> - <not_acceptable> - <http_code>406</http_code> - <type>error</type> - </not_acceptable> - <!-- Messages when some resource are gone --> - <gone> - <http_code>410</http_code> - <type>error</type> - </gone> - <!-- All messages related with internal errors --> - <internal_error> - <http_code>500</http_code> - <type>error</type> - </internal_error> - <!-- Messages when something not implemented --> - <not_implemented> - <http_code>501</http_code> - <type>error</type> - </not_implemented> - </domain_codes> - - </api> -</config> diff --git a/app/code/core/Mage/Api/etc/config.xml b/app/code/core/Mage/Api/etc/config.xml deleted file mode 100644 index 3ece14a6079d189957dfee95a0b81071d55255cf..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api/etc/config.xml +++ /dev/null @@ -1,108 +0,0 @@ -<?xml version="1.0"?> -<!-- -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Academic Free License (AFL 3.0) - * that is bundled with this package in the file LICENSE_AFL.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/afl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) - */ ---> -<config> - <modules> - <Mage_Api> - <version>1.6.0.0</version> - <active>true</active> - <codePool>core</codePool> - <depends> - <Mage_Core /> - </depends> - </Mage_Api> - </modules> - <global> - <ignoredModules> - <entities> - <api/> - </entities> - </ignoredModules> - <cache> - <types> - <config_api translate="label,description" module="Mage_Api"> - <label>Web Services Configuration</label> - <description>Web Services definition files (api.xml).</description> - <tags>CONFIG_API</tags> - </config_api> - </types> - </cache> - <resources> - <api_setup> - <setup> - <module>Mage_Api</module> - </setup> - </api_setup> - </resources> - <request> - <direct_front_name> - <api/> - </direct_front_name> - </request> - </global> - <frontend> - <routers> - <api> - <use>standard</use> - <args> - <module>Mage_Api</module> - <frontName>api</frontName> - </args> - </api> - </routers> - <translate> - <modules> - <Mage_Api> - <files> - <default>Mage_Api.csv</default> - </files> - </Mage_Api> - </modules> - </translate> - </frontend> - <adminhtml> - <translate> - <modules> - <Mage_Api> - <files> - <default>Mage_Api.csv</default> - </files> - </Mage_Api> - </modules> - </translate> - </adminhtml> - <default> - <api> - <config> - <charset>UTF-8</charset> - <session_timeout>3600</session_timeout> - <compliance_wsi>0</compliance_wsi> - <wsdl_cache_enabled>0</wsdl_cache_enabled> - </config> - </api> - </default> -</config> diff --git a/app/code/core/Mage/Api/etc/wsdl.xml b/app/code/core/Mage/Api/etc/wsdl.xml deleted file mode 100644 index 6b24d0d9a39ff3239225249beb9fa98fd336a1a9..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api/etc/wsdl.xml +++ /dev/null @@ -1,191 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<definitions xmlns:typens="urn:{{var wsdl.name}}" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" - xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns="http://schemas.xmlsoap.org/wsdl/" - name="{{var wsdl.name}}" targetNamespace="urn:{{var wsdl.name}}"> - <types> - <schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:Magento"> -<!-- <import namespace="http://schemas.xmlsoap.org/soap/encoding/" schemaLocation="http://schemas.xmlsoap.org/soap/encoding/" />--> - <complexType name="FixedArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="xsd:anyType[]" /> - </restriction> - </complexContent> - </complexType> - </schema> - </types> - <message name="call"> - <part name="sessionId" type="xsd:string" /> - <part name="resourcePath" type="xsd:string" /> - <part name="args" type="xsd:anyType" /> - </message> - <message name="callResponse"> - <part name="callReturn" type="xsd:anyType" /> - </message> - <message name="multiCall"> - <part name="sessionId" type="xsd:string" /> - <part name="calls" type="typens:FixedArray" /> - <part name="options" type="xsd:anyType" /> - </message> - <message name="multiCallResponse"> - <part name="multiCallReturn" type="typens:FixedArray" /> - </message> - <message name="endSession"> - <part name="sessionId" type="xsd:string" /> - </message> - <message name="endSessionResponse"> - <part name="endSessionReturn" type="xsd:boolean" /> - </message> - <message name="login"> - <part name="username" type="xsd:string" /> - <part name="apiKey" type="xsd:string" /> - </message> - <message name="loginResponse"> - <part name="loginReturn" type="xsd:string" /> - </message> - <message name="resources"> - <part name="sessionId" type="xsd:string" /> - </message> - <message name="resourcesResponse"> - <part name="resourcesReturn" type="typens:FixedArray" /> - </message> - <message name="globalFaults"> - <part name="sessionId" type="xsd:string" /> - </message> - <message name="globalFaultsResponse"> - <part name="globalFaultsReturn" type="typens:FixedArray" /> - </message> - <message name="resourceFaults"> - <part name="resourceName" type="xsd:string" /> - <part name="sessionId" type="xsd:string" /> - </message> - <message name="resourceFaultsResponse"> - <part name="resourceFaultsReturn" type="typens:FixedArray" /> - </message> - <message name="startSession" /> - <message name="startSessionResponse"> - <part name="startSessionReturn" type="xsd:string" /> - </message> - <portType name="{{var wsdl.handler}}PortType"> - <operation name="call"> - <documentation>Call api functionality</documentation> - <input message="typens:call" /> - <output message="typens:callResponse" /> - </operation> - <operation name="multiCall"> - <documentation>Multiple calls of resource functionality</documentation> - <input message="typens:multiCall" /> - <output message="typens:multiCallResponse" /> - </operation> - <operation name="endSession"> - <documentation>End web service session</documentation> - <input message="typens:endSession" /> - <output message="typens:endSessionResponse" /> - </operation> - <operation name="login"> - <documentation>Login user and retrive session id</documentation> - <input message="typens:login" /> - <output message="typens:loginResponse" /> - </operation> - <operation name="startSession"> - <documentation>Start web service session</documentation> - <input message="typens:startSession" /> - <output message="typens:startSessionResponse" /> - </operation> - <operation name="resources"> - <documentation>List of available resources</documentation> - <input message="typens:resources" /> - <output message="typens:resourcesResponse" /> - </operation> - <operation name="globalFaults"> - <documentation>List of resource faults</documentation> - <input message="typens:globalFaults" /> - <output message="typens:globalFaultsResponse" /> - </operation> - <operation name="resourceFaults"> - <documentation>List of global faults</documentation> - <input message="typens:resourceFaults" /> - <output message="typens:resourceFaultsResponse" /> - </operation> - </portType> - <binding name="{{var wsdl.handler}}Binding" type="typens:{{var wsdl.handler}}PortType"> - <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" /> - <operation name="call"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="multiCall"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="endSession"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="login"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="startSession"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="resources"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="globalFaults"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="resourceFaults"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - </binding> - <service name="{{var wsdl.name}}Service"> - <port name="{{var wsdl.handler}}Port" binding="typens:{{var wsdl.handler}}Binding"> - <soap:address location="{{var wsdl.url}}" /> - </port> - </service> -</definitions> diff --git a/app/code/core/Mage/Api/etc/wsdl2.xml b/app/code/core/Mage/Api/etc/wsdl2.xml deleted file mode 100644 index fd9fe0d5dd39f94c9a1528a3be89c9d1bb202da0..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api/etc/wsdl2.xml +++ /dev/null @@ -1,242 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<definitions xmlns:typens="urn:{{var wsdl.name}}" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" - xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns="http://schemas.xmlsoap.org/wsdl/" - name="{{var wsdl.name}}" targetNamespace="urn:{{var wsdl.name}}"> - <types> - <schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:Magento"> - <import namespace="http://schemas.xmlsoap.org/soap/encoding/" schemaLocation="http://schemas.xmlsoap.org/soap/encoding/" /> - <complexType name="associativeEntity"> - <all> - <element name="key" type="xsd:string" /> - <element name="value" type="xsd:string" /> - </all> - </complexType> - <complexType name="associativeArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:associativeEntity[]" /> - </restriction> - </complexContent> - </complexType> - <complexType name="associativeMultiEntity"> - <all> - <element name="key" type="xsd:string" /> - <element name="value" type="typens:ArrayOfString" /> - </all> - </complexType> - <complexType name="associativeMultiArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:associativeMultiEntity[]" /> - </restriction> - </complexContent> - </complexType> - <complexType name="filters"> - <all> - <element name="filter" type="typens:associativeArray" minOccurs="0" /> - <element name="complex_filter" type="typens:complexFilterArray" minOccurs="0" /> - </all> - </complexType> - <complexType name="complexFilterArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:complexFilter[]" /> - </restriction> - </complexContent> - </complexType> - <complexType name="complexFilter"> - <all> - <element name="key" type="xsd:string" /> - <element name="value" type="typens:associativeEntity" /> - </all> - </complexType> - <complexType name="ArrayOfString"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="xsd:string[]" /> - </restriction> - </complexContent> - </complexType> - <complexType name="ArrayOfInt"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="xsd:int[]" /> - </restriction> - </complexContent> - </complexType> - <complexType name="apiMethodEntity"> - <all> - <element name="title" type="xsd:string" /> - <element name="path" type="xsd:string" /> - <element name="name" type="xsd:string" /> - <element name="aliases" type="typens:ArrayOfString" /> - </all> - </complexType> - <complexType name="ArrayOfApiMethods"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:apiMethodEntity[]" /> - </restriction> - </complexContent> - </complexType> - <complexType name="apiEntity"> - <all> - <element name="title" type="xsd:string" /> - <element name="name" type="xsd:string" /> - <element name="aliases" type="typens:ArrayOfString" /> - <element name="methods" type="typens:ArrayOfApiMethods" /> - </all> - </complexType> - <complexType name="ArrayOfApis"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:apiEntity[]" /> - </restriction> - </complexContent> - </complexType> - <complexType name="existsFaltureEntity"> - <all> - <element name="code" type="xsd:string" /> - <element name="message" type="xsd:string" /> - </all> - </complexType> - <complexType name="ArrayOfExistsFaltures"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:existsFaltureEntity[]" /> - </restriction> - </complexContent> - </complexType> - </schema> - </types> - <message name="endSession"> - <part name="sessionId" type="xsd:string" /> - </message> - <message name="endSessionResponse"> - <part name="endSessionReturn" type="xsd:boolean" /> - </message> - <message name="login"> - <part name="username" type="xsd:string" /> - <part name="apiKey" type="xsd:string" /> - </message> - <message name="loginResponse"> - <part name="loginReturn" type="xsd:string" /> - </message> - <message name="resourcesRequest"> - <part name="sessionId" type="xsd:string" /> - </message> - <message name="resourcesResponse"> - <part name="resourcesReturn" type="typens:ArrayOfApis" /> - </message> - <message name="globalFaults"> - <part name="sessionId" type="xsd:string" /> - </message> - <message name="globalFaultsResponse"> - <part name="globalFaultsReturn" type="typens:ArrayOfExistsFaltures" /> - </message> - <message name="resourceFaults"> - <part name="resourceName" type="xsd:string" /> - <part name="sessionId" type="xsd:string" /> - </message> - <message name="resourceFaultsResponse"> - <part name="resourceFaultsReturn" type="typens:ArrayOfExistsFaltures" /> - </message> - <message name="startSession" /> - <message name="startSessionResponse"> - <part name="startSessionReturn" type="xsd:string" /> - </message> - <portType name="{{var wsdl.handler}}PortType"> - <operation name="endSession"> - <documentation>End web service session</documentation> - <input message="typens:endSession" /> - <output message="typens:endSessionResponse" /> - </operation> - <operation name="login"> - <documentation>Login user and retrive session id</documentation> - <input message="typens:login" /> - <output message="typens:loginResponse" /> - </operation> - <operation name="startSession"> - <documentation>Start web service session</documentation> - <input message="typens:startSession" /> - <output message="typens:startSessionResponse" /> - </operation> - <operation name="resources"> - <documentation>List of available resources</documentation> - <input message="typens:resourcesRequest" /> - <output message="typens:resourcesResponse" /> - </operation> - <operation name="globalFaults"> - <documentation>List of global faults</documentation> - <input message="typens:globalFaults" /> - <output message="typens:globalFaultsResponse" /> - </operation> - <operation name="resourceFaults"> - <documentation>List of resource faults</documentation> - <input message="typens:resourceFaults" /> - <output message="typens:resourceFaultsResponse" /> - </operation> - </portType> - <binding name="{{var wsdl.handler}}Binding" type="typens:{{var wsdl.handler}}PortType"> - <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" /> - <operation name="endSession"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="login"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="startSession"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="resources"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="globalFaults"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="resourceFaults"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - </binding> - <service name="{{var wsdl.name}}Service"> - <port name="{{var wsdl.handler}}Port" binding="typens:{{var wsdl.handler}}Binding"> - <soap:address location="{{var wsdl.url}}" /> - </port> - </service> -</definitions> diff --git a/app/code/core/Mage/Api/etc/wsi.xml b/app/code/core/Mage/Api/etc/wsi.xml deleted file mode 100644 index 0db28ab286910254a2758db7cc5a3667ae41c0dd..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api/etc/wsi.xml +++ /dev/null @@ -1,381 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<wsdl:definitions xmlns:typens="urn:{{var wsdl.name}}" - xmlns:xsd="http://www.w3.org/2001/XMLSchema" - xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" - xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" - xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" - name="{{var wsdl.name}}" - targetNamespace="urn:{{var wsdl.name}}"> - <wsdl:types> - <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:{{var wsdl.name}}"> - <xsd:complexType name="associativeEntity"> - <xsd:sequence> - <xsd:element name="key" type="xsd:string" /> - <xsd:element name="value" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="associativeArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:associativeEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="associativeMultiEntity"> - <xsd:sequence> - <xsd:element name="key" type="xsd:string" /> - <xsd:element name="value" type="typens:ArrayOfString" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="associativeMultiArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:associativeMultiEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="complexFilter"> - <xsd:sequence> - <xsd:element name="key" type="xsd:string" /> - <xsd:element name="value" type="typens:associativeEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="complexFilterArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:complexFilter" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="filters"> - <xsd:sequence> - <xsd:element name="filter" type="typens:associativeArray" minOccurs="0" /> - <xsd:element name="complex_filter" type="typens:complexFilterArray" minOccurs="0" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="ArrayOfString"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="ArrayOfInt"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="apiMethodEntity"> - <xsd:sequence> - <xsd:element name="title" type="xsd:string" /> - <xsd:element name="path" type="xsd:string" /> - <xsd:element name="name" type="xsd:string" /> - <xsd:element name="aliases" type="typens:ArrayOfString" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="ArrayOfApiMethods"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:apiMethodEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="apiEntity"> - <xsd:sequence> - <xsd:element name="title" type="xsd:string" /> - <xsd:element name="name" type="xsd:string" /> - <xsd:element name="aliases" type="typens:ArrayOfString" /> - <xsd:element name="methods" type="typens:ArrayOfApiMethods" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="ArrayOfApis"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:apiEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="existsFaltureEntity"> - <xsd:sequence> - <xsd:element name="code" type="xsd:string" /> - <xsd:element name="message" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="ArrayOfExistsFaltures"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:existsFaltureEntity" /> - </xsd:sequence> - </xsd:complexType> - - - - <xsd:element name="callParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="apiPath" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="args" type="xsd:anyType" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="callResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:anyType" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="multiCallParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="calls" type="xsd:anyType" /> - <xsd:element minOccurs="1" maxOccurs="1" name="options" type="xsd:anyType" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="multiCallResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:anyType" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="endSessionParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="endSessionResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:boolean" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="loginParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="username" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="apiKey" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="loginResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="resourcesRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="resourcesResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:ArrayOfApis" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="globalFaultsParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="globalFaultsResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:ArrayOfExistsFaltures" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="resourceFaultsParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="resourceName" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="resourceFaultsResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:ArrayOfExistsFaltures" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="startSessionResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - </xsd:schema> - </wsdl:types> - <wsdl:message name="call"> - <wsdl:part name="parameters" element="typens:callParam" /> - </wsdl:message> - <wsdl:message name="callResponse"> - <wsdl:part name="parameters" element="typens:callResponseParam" /> - </wsdl:message> - <wsdl:message name="multiCall"> - <wsdl:part name="parameters" element="typens:multiCallParam" /> - </wsdl:message> - <wsdl:message name="multiCallResponse"> - <wsdl:part name="parameters" element="typens:multiCallResponseParam" /> - </wsdl:message> - <wsdl:message name="endSession"> - <wsdl:part name="parameters" element="typens:endSessionParam" /> - </wsdl:message> - <wsdl:message name="endSessionResponse"> - <wsdl:part name="parameters" element="typens:endSessionResponseParam" /> - </wsdl:message> - <wsdl:message name="login"> - <wsdl:part name="parameters" element="typens:loginParam" /> - </wsdl:message> - <wsdl:message name="loginResponse"> - <wsdl:part name="parameters" element="typens:loginResponseParam" /> - </wsdl:message> - <wsdl:message name="resourcesRequest"> - <wsdl:part name="parameters" element="typens:resourcesRequestParam" /> - </wsdl:message> - <wsdl:message name="resourcesResponse"> - <wsdl:part name="parameters" element="typens:resourcesResponseParam" /> - </wsdl:message> - <wsdl:message name="globalFaults"> - <wsdl:part name="parameters" element="typens:globalFaultsParam" /> - </wsdl:message> - <wsdl:message name="globalFaultsResponse"> - <wsdl:part name="parameters" element="typens:globalFaultsResponseParam" /> - </wsdl:message> - <wsdl:message name="resourceFaults"> - <wsdl:part name="parameters" element="typens:resourceFaultsParam" /> - </wsdl:message> - <wsdl:message name="resourceFaultsResponse"> - <wsdl:part name="parameters" element="typens:resourceFaultsResponseParam" /> - </wsdl:message> - <wsdl:message name="startSession" /> - <wsdl:message name="startSessionResponse"> - <wsdl:part name="parameters" element="typens:startSessionResponseParam" /> - </wsdl:message> - <wsdl:portType name="{{var wsdl.handler}}PortType"> - <wsdl:operation name="call"> - <wsdl:documentation>Call api functionality</wsdl:documentation> - <wsdl:input message="typens:call" /> - <wsdl:output message="typens:callResponse" /> - </wsdl:operation> - <wsdl:operation name="multiCall"> - <wsdl:documentation>Multiple calls of resource functionality</wsdl:documentation> - <wsdl:input message="typens:multiCall" /> - <wsdl:output message="typens:multiCallResponse" /> - </wsdl:operation> - <wsdl:operation name="endSession"> - <wsdl:documentation>End web service session</wsdl:documentation> - <wsdl:input message="typens:endSession" /> - <wsdl:output message="typens:endSessionResponse" /> - </wsdl:operation> - <wsdl:operation name="login"> - <wsdl:documentation>Login user and retrive session id</wsdl:documentation> - <wsdl:input message="typens:login" /> - <wsdl:output message="typens:loginResponse" /> - </wsdl:operation> - <wsdl:operation name="startSession"> - <wsdl:documentation>Start web service session</wsdl:documentation> - <wsdl:input message="typens:startSession" /> - <wsdl:output message="typens:startSessionResponse" /> - </wsdl:operation> - <wsdl:operation name="resources"> - <wsdl:documentation>List of available resources</wsdl:documentation> - <wsdl:input message="typens:resourcesRequest" /> - <wsdl:output message="typens:resourcesResponse" /> - </wsdl:operation> - <wsdl:operation name="globalFaults"> - <wsdl:documentation>List of global faults</wsdl:documentation> - <wsdl:input message="typens:globalFaults" /> - <wsdl:output message="typens:globalFaultsResponse" /> - </wsdl:operation> - <wsdl:operation name="resourceFaults"> - <wsdl:documentation>List of resource faults</wsdl:documentation> - <wsdl:input message="typens:resourceFaults" /> - <wsdl:output message="typens:resourceFaultsResponse" /> - </wsdl:operation> - </wsdl:portType> - <wsdl:binding name="{{var wsdl.handler}}Binding" type="typens:{{var wsdl.handler}}PortType"> - <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" /> - <wsdl:operation name="call"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="multiCall"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="endSession"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="login"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="startSession"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="resources"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="globalFaults"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="resourceFaults"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - </wsdl:binding> - <wsdl:service name="{{var wsdl.name}}Service"> - <wsdl:port name="{{var wsdl.handler}}Port" binding="typens:{{var wsdl.handler}}Binding"> - <soap:address location="{{var wsdl.url}}" /> - </wsdl:port> - </wsdl:service> -</wsdl:definitions> diff --git a/app/code/core/Mage/Api/locale/de_DE/Mage_Api.csv b/app/code/core/Mage/Api/locale/de_DE/Mage_Api.csv deleted file mode 100644 index 4d060c6fd98dc54a245946723ed463b5dd8d9baa..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api/locale/de_DE/Mage_Api.csv +++ /dev/null @@ -1,16 +0,0 @@ -"Access denied.","Zugang verweigert." -"Client Session Timeout (sec.)","Kunde Session-Timeout (in Sekunden)" -"Default Response Charset","Standard-Schriftsatz für Antwort" -"Email","E-Mail" -"General Settings","Allgemeine Einstellungen" -"Invalid webservice adapter specified.","Ungültiger Webservice Adapter angegeben." -"Invalid webservice handler specified.","Ungültiger Webservice Handler angegeben." -"Magento Core API","Magento Core API" -"Magento Core API Section","Magento Core API Sektion" -"Roles","Rollen" -"Unable to login.","Einloggen nicht möglich." -"User Name","Benutzername" -"Users","Benutzer" -"WS-I Compliance","WS-I Übereinstimmung" -"Web Services","Webdienste" -"Your account has been deactivated.","Ihr Benutzerkonto wurde deaktiviert." diff --git a/app/code/core/Mage/Api/locale/en_US/Mage_Api.csv b/app/code/core/Mage/Api/locale/en_US/Mage_Api.csv deleted file mode 100644 index 5c6674a0d99c62b49c97d66c3609accc1f53483b..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api/locale/en_US/Mage_Api.csv +++ /dev/null @@ -1,16 +0,0 @@ -"Access denied.","Access denied." -"Client Session Timeout (sec.)","Client Session Timeout (sec.)" -"Default Response Charset","Default Response Charset" -"Email","Email" -"General Settings","General Settings" -"Invalid webservice adapter specified.","Invalid webservice adapter specified." -"Invalid webservice handler specified.","Invalid webservice handler specified." -"Magento Core API","Magento Core API" -"Magento Core API Section","Magento Core API Section" -"Roles","Roles" -"Unable to login.","Unable to login." -"User Name","User Name" -"Users","Users" -"WS-I Compliance","WS-I Compliance" -"Web Services","Web Services" -"Your account has been deactivated.","Your account has been deactivated." diff --git a/app/code/core/Mage/Api/locale/es_ES/Mage_Api.csv b/app/code/core/Mage/Api/locale/es_ES/Mage_Api.csv deleted file mode 100644 index 972a0ac704b2a9192ac1bbbb688d8f0340fa126a..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api/locale/es_ES/Mage_Api.csv +++ /dev/null @@ -1,16 +0,0 @@ -"Access denied.","Acceso denegado" -"Client Session Timeout (sec.)","Plazo lÃmite de la sesión cliente (seg.)" -"Default Response Charset","Conjunto de caracteres de respuesta por omisión" -"Email","Correo electrónico" -"General Settings","Opciones generales" -"Invalid webservice adapter specified.","Adaptador de servicio web especificado inválido" -"Invalid webservice handler specified.","Controlador de servicio web especificado inválido" -"Magento Core API","API del núcleo de Magento" -"Magento Core API Section","Apartado de la API (interfaz de programación de aplicaciones) del núcleo de Magento" -"Roles","Roles" -"Unable to login.","No es posible entrar al sistema." -"User Name","Nombre de usuario" -"Users","Usuarios" -"WS-I Compliance","Conformidad con WS-I" -"Web Services","Servicios web" -"Your account has been deactivated.","Se ha desactivado su cuenta." diff --git a/app/code/core/Mage/Api/locale/fr_FR/Mage_Api.csv b/app/code/core/Mage/Api/locale/fr_FR/Mage_Api.csv deleted file mode 100644 index 9389383ef216978971b273187086083dd7e4262a..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api/locale/fr_FR/Mage_Api.csv +++ /dev/null @@ -1,16 +0,0 @@ -"Access denied.","Accès refusé." -"Client Session Timeout (sec.)","Expiration de la session client (secondes)" -"Default Response Charset","Table de caractères de la réponse par défaut" -"Email","Email" -"General Settings","Réglages généraux" -"Invalid webservice adapter specified.","Adaptateur de service web invalide." -"Invalid webservice handler specified.","Gérant de service web invalide." -"Magento Core API","Magento Core API" -"Magento Core API Section","Magento Core API Section" -"Roles","Rôles" -"Unable to login.","Connexion impossible." -"User Name","Nom d'utilisateur" -"Users","Utilisateurs" -"WS-I Compliance","Conforme à WS-I" -"Web Services","Services Web" -"Your account has been deactivated.","Votre compte a été désactivé." diff --git a/app/code/core/Mage/Api/locale/nl_NL/Mage_Api.csv b/app/code/core/Mage/Api/locale/nl_NL/Mage_Api.csv deleted file mode 100644 index 62570ad76ad788be83453e0ac0d8f3ad0957ff29..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api/locale/nl_NL/Mage_Api.csv +++ /dev/null @@ -1,16 +0,0 @@ -"Access denied.","Toegang geweigerd." -"Client Session Timeout (sec.)","Klant Sessie Time out (sec.)" -"Default Response Charset","Karakterset standaard antwoord" -"Email","Email" -"General Settings","Algemene instellingen" -"Invalid webservice adapter specified.","Ongeldige webdienst adapter gespecificeerd." -"Invalid webservice handler specified.","Ongeldige webservice handler gespecificeerd." -"Magento Core API","Magento Core API" -"Magento Core API Section","Magento Core API Sectie" -"Roles","Rollen" -"Unable to login.","Kan niet inloggen." -"User Name","Gebruikersnaam" -"Users","Gebruikers" -"WS-I Compliance","WS-I naleving" -"Web Services","Web Diensten" -"Your account has been deactivated.","Uw account is gedeactiveerd." diff --git a/app/code/core/Mage/Api/locale/pt_BR/Mage_Api.csv b/app/code/core/Mage/Api/locale/pt_BR/Mage_Api.csv deleted file mode 100644 index bebef0b86a0e41fb8a678aac9fec6f25fbf0afd0..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api/locale/pt_BR/Mage_Api.csv +++ /dev/null @@ -1,16 +0,0 @@ -"Access denied.","Acesso negado." -"Client Session Timeout (sec.)","Tempo Limite da Sessão de Cliente (seg.)" -"Default Response Charset","Conjunto de Caracteres Predefinido de Resposta" -"Email","E-mail" -"General Settings","Definições Gerais" -"Invalid webservice adapter specified.","Adaptador de serviço de rede especificado inválido." -"Invalid webservice handler specified.","Processador de serviço de rede especificado inválido." -"Magento Core API","Núcleo Magento API" -"Magento Core API Section","Seção Núcleo Magento API" -"Roles","Funções" -"Unable to login.","Incapaz de entrar." -"User Name","Nome do Usuário" -"Users","Usuários" -"WS-I Compliance","Conformidade WS-I" -"Web Services","Serviços Web" -"Your account has been deactivated.","Sua conta foi desativada." diff --git a/app/code/core/Mage/Api/locale/zh_CN/Mage_Api.csv b/app/code/core/Mage/Api/locale/zh_CN/Mage_Api.csv deleted file mode 100644 index 9130432dcadc7662e30673ac84c18ed3e0e38d0a..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api/locale/zh_CN/Mage_Api.csv +++ /dev/null @@ -1,16 +0,0 @@ -"Access denied.","访问被拒ç»" -"Client Session Timeout (sec.)","客户端会è¯è¶…时(秒。)" -"Default Response Charset","默认å“应å—符集" -"Email","电å邮件" -"General Settings","常规设置" -"Invalid webservice adapter specified.","指定的WebæœåС适é…å™¨æ— æ•ˆã€‚" -"Invalid webservice handler specified.","指定的WebæœåС处ç†ç¨‹åºæ— 效。" -"Magento Core API","Magento Core API" -"Magento Core API Section","Magento Core API 部分" -"Roles","角色" -"Unable to login.","æ— æ³•ç™»å½•ã€‚" -"User Name","用户å" -"Users","用户" -"WS-I Compliance","WS-I 兼容" -"Web Services","WebæœåŠ¡" -"Your account has been deactivated.","æ‚¨çš„å¸æˆ·å·²è¢«æ’¤é”€ã€‚" diff --git a/app/code/core/Mage/Api/sql/api_setup/install-1.6.0.0.php b/app/code/core/Mage/Api/sql/api_setup/install-1.6.0.0.php deleted file mode 100644 index 479c250ca2bae6425d842bfa232cec0da09ee478..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api/sql/api_setup/install-1.6.0.0.php +++ /dev/null @@ -1,208 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Api install - * - * @category Mage - * @package Mage_Api - * @author Magento Core Team <core@magentocommerce.com> - */ -$installer = $this; -/* @var $installer Mage_Core_Model_Resource_Setup */ - -$installer->startSetup(); - -/** - * Create table 'api_assert' - */ -$table = $installer->getConnection() - ->newTable($installer->getTable('api_assert')) - ->addColumn('assert_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array( - 'identity' => true, - 'unsigned' => true, - 'nullable' => false, - 'primary' => true, - ), 'Assert id') - ->addColumn('assert_type', Varien_Db_Ddl_Table::TYPE_TEXT, 20, array( - ), 'Assert type') - ->addColumn('assert_data', Varien_Db_Ddl_Table::TYPE_TEXT, '64k', array( - ), 'Assert additional data') - ->setComment('Api ACL Asserts'); -$installer->getConnection()->createTable($table); - -/** - * Create table 'api_role' - */ -$table = $installer->getConnection() - ->newTable($installer->getTable('api_role')) - ->addColumn('role_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array( - 'identity' => true, - 'unsigned' => true, - 'nullable' => false, - 'primary' => true, - ), 'Role id') - ->addColumn('parent_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array( - 'unsigned' => true, - 'nullable' => false, - 'default' => '0', - ), 'Parent role id') - ->addColumn('tree_level', Varien_Db_Ddl_Table::TYPE_SMALLINT, null, array( - 'unsigned' => true, - 'nullable' => false, - 'default' => '0', - ), 'Role level in tree') - ->addColumn('sort_order', Varien_Db_Ddl_Table::TYPE_SMALLINT, null, array( - 'unsigned' => true, - 'nullable' => false, - 'default' => '0', - ), 'Sort order to display on admin area') - ->addColumn('role_type', Varien_Db_Ddl_Table::TYPE_TEXT, 1, array( - 'nullable' => false, - 'default' => '0', - ), 'Role type') - ->addColumn('user_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array( - 'unsigned' => true, - 'nullable' => false, - 'default' => '0', - ), 'User id') - ->addColumn('role_name', Varien_Db_Ddl_Table::TYPE_TEXT, 50, array( - ), 'Role name') - ->addIndex($installer->getIdxName('api_role', array('parent_id', 'sort_order')), - array('parent_id', 'sort_order')) - ->addIndex($installer->getIdxName('api_role', array('tree_level')), - array('tree_level')) - ->setComment('Api ACL Roles'); -$installer->getConnection()->createTable($table); - -/** - * Create table 'api_rule' - */ -$table = $installer->getConnection() - ->newTable($installer->getTable('api_rule')) - ->addColumn('rule_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array( - 'identity' => true, - 'unsigned' => true, - 'nullable' => false, - 'primary' => true, - ), 'Api rule Id') - ->addColumn('role_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array( - 'unsigned' => true, - 'nullable' => false, - 'default' => '0', - ), 'Api role Id') - ->addColumn('resource_id', Varien_Db_Ddl_Table::TYPE_TEXT, 255, array( - ), 'Module code') - ->addColumn('api_privileges', Varien_Db_Ddl_Table::TYPE_TEXT, 20, array( - ), 'Privileges') - ->addColumn('assert_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array( - 'unsigned' => true, - 'nullable' => false, - 'default' => '0', - ), 'Assert id') - ->addColumn('role_type', Varien_Db_Ddl_Table::TYPE_TEXT, 1, array( - ), 'Role type') - ->addColumn('api_permission', Varien_Db_Ddl_Table::TYPE_TEXT, 10, array( - ), 'Permission') - ->addIndex($installer->getIdxName('api_rule', array('resource_id', 'role_id')), - array('resource_id', 'role_id')) - ->addIndex($installer->getIdxName('api_rule', array('role_id', 'resource_id')), - array('role_id', 'resource_id')) - ->addForeignKey($installer->getFkName('api_rule', 'role_id', 'api_role', 'role_id'), - 'role_id', $installer->getTable('api_role'), 'role_id', - Varien_Db_Ddl_Table::ACTION_CASCADE, Varien_Db_Ddl_Table::ACTION_CASCADE) - ->setComment('Api ACL Rules'); -$installer->getConnection()->createTable($table); - -/** - * Create table 'api_user' - */ -$table = $installer->getConnection() - ->newTable($installer->getTable('api_user')) - ->addColumn('user_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array( - 'identity' => true, - 'unsigned' => true, - 'nullable' => false, - 'primary' => true, - ), 'User id') - ->addColumn('firstname', Varien_Db_Ddl_Table::TYPE_TEXT, 32, array( - ), 'First name') - ->addColumn('lastname', Varien_Db_Ddl_Table::TYPE_TEXT, 32, array( - ), 'Last name') - ->addColumn('email', Varien_Db_Ddl_Table::TYPE_TEXT, 128, array( - ), 'Email') - ->addColumn('username', Varien_Db_Ddl_Table::TYPE_TEXT, 40, array( - ), 'Nickname') - ->addColumn('api_key', Varien_Db_Ddl_Table::TYPE_TEXT, 40, array( - ), 'Api key') - ->addColumn('created', Varien_Db_Ddl_Table::TYPE_TIMESTAMP, null, array( - 'nullable' => false, - ), 'User record create date') - ->addColumn('modified', Varien_Db_Ddl_Table::TYPE_TIMESTAMP, null, array( - ), 'User record modify date') - ->addColumn('lognum', Varien_Db_Ddl_Table::TYPE_SMALLINT, null, array( - 'unsigned' => true, - 'nullable' => false, - 'default' => '0', - ), 'Quantity of log ins') - ->addColumn('reload_acl_flag', Varien_Db_Ddl_Table::TYPE_SMALLINT, null, array( - 'nullable' => false, - 'default' => '0', - ), 'Refresh ACL flag') - ->addColumn('is_active', Varien_Db_Ddl_Table::TYPE_SMALLINT, null, array( - 'nullable' => false, - 'default' => '1', - ), 'Account status') - ->setComment('Api Users'); -$installer->getConnection()->createTable($table); - -/** - * Create table 'api_session' - */ -$table = $installer->getConnection() - ->newTable($installer->getTable('api_session')) - ->addColumn('user_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array( - 'unsigned' => true, - 'nullable' => false, - ), 'User id') - ->addColumn('logdate', Varien_Db_Ddl_Table::TYPE_TIMESTAMP, null, array( - 'nullable' => false, - ), 'Login date') - ->addColumn('sessid', Varien_Db_Ddl_Table::TYPE_TEXT, 40, array( - ), 'Sessioin id') - ->addIndex($installer->getIdxName('api_session', array('user_id')), - array('user_id')) - ->addIndex($installer->getIdxName('api_session', array('sessid')), - array('sessid')) - ->addForeignKey($installer->getFkName('api_session', 'user_id', 'api_user', 'user_id'), - 'user_id', $installer->getTable('api_user'), 'user_id', - Varien_Db_Ddl_Table::ACTION_CASCADE, Varien_Db_Ddl_Table::ACTION_CASCADE) - ->setComment('Api Sessions'); -$installer->getConnection()->createTable($table); - - - -$installer->endSetup(); diff --git a/app/code/core/Mage/Api2/Block/Adminhtml/Attribute.php b/app/code/core/Mage/Api2/Block/Adminhtml/Attribute.php deleted file mode 100644 index 8c751333365b7d7cccd8c45c04a1db8371118829..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Block/Adminhtml/Attribute.php +++ /dev/null @@ -1,48 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 attributes grid container block - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Block_Adminhtml_Attribute extends Mage_Adminhtml_Block_Widget_Grid_Container -{ - /** - * Construct grid container - */ - public function _construct() - { - parent::_construct(); - - $this->_blockGroup = 'Mage_Api2'; - $this->_controller = 'adminhtml_attribute'; - $this->_headerText = $this->__('REST Attributes'); - $this->_removeButton('add'); - } -} diff --git a/app/code/core/Mage/Api2/Block/Adminhtml/Attribute/Buttons.php b/app/code/core/Mage/Api2/Block/Adminhtml/Attribute/Buttons.php deleted file mode 100644 index 33786f0864f624a037ff040dce2c60f4f25b67c4..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Block/Adminhtml/Attribute/Buttons.php +++ /dev/null @@ -1,112 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Block for rendering buttons - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Block_Adminhtml_Attribute_Buttons extends Mage_Adminhtml_Block_Template -{ - /** - * Construct - */ - public function __construct() - { - parent::__construct(); - $this->setTemplate('api2/attribute/buttons.phtml'); - } - - /** - * Prepare global layout - * - * @return Mage_Core_Block_Abstract - */ - protected function _prepareLayout() - { - $buttons = array( - 'backButton' => array( - 'label' => $this->__('Back'), - 'onclick' => sprintf("window.location.href='%s';", $this->getUrl('*/*/')), - 'class' => 'back' - ), - 'saveButton' => array( - 'label' => $this->__('Save'), - 'onclick' => 'form.submit(); return false;', - 'class' => 'save' - ), - ); - - foreach ($buttons as $name => $data) { - $button = $this->getLayout()->createBlock('Mage_Adminhtml_Block_Widget_Button')->setData($data); - $this->setChild($name, $button); - } - - return parent::_prepareLayout(); - } - - /** - * Get back button HTML - * - * @return string - */ - public function getBackButtonHtml() - { - return $this->getChildHtml('backButton'); - } - - /** - * Get reset button HTML - * - * @return string - */ - public function getResetButtonHtml() - { - return $this->getChildHtml('resetButton'); - } - - /** - * Get save button HTML - * - * @return string - */ - public function getSaveButtonHtml() - { - return $this->getChildHtml('saveButton'); - } - - /** - * Get block caption - * - * @return string - */ - public function getCaption() - { - return $this->__('Edit'); - } -} diff --git a/app/code/core/Mage/Api2/Block/Adminhtml/Attribute/Edit.php b/app/code/core/Mage/Api2/Block/Adminhtml/Attribute/Edit.php deleted file mode 100644 index 9d55b892ec33a724ab4bc8a211134317cd144e1c..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Block/Adminhtml/Attribute/Edit.php +++ /dev/null @@ -1,61 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Attribute Edit block - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Block_Adminhtml_Attribute_Edit extends Mage_Adminhtml_Block_Widget_Form_Container -{ - /** - * Initialize edit form container - */ - public function _construct() - { - $this->_objectId = 'id'; - $this->_blockGroup = 'Mage_Api2'; - $this->_controller = 'adminhtml_attribute'; - - parent::_construct(); - - $this->_updateButton('save', 'label', $this->__('Save')) - ->_removeButton('delete'); - } - - /** - * Retrieve text for header element depending on loaded page - * - * @return string - */ - public function getHeaderText() - { - $userTypes = Mage_Api2_Model_Auth_User::getUserTypes(); - return $this->__('Edit attribute rules for %s Role', $userTypes[$this->getRequest()->getParam('type')]); - } -} diff --git a/app/code/core/Mage/Api2/Block/Adminhtml/Attribute/Edit/Form.php b/app/code/core/Mage/Api2/Block/Adminhtml/Attribute/Edit/Form.php deleted file mode 100644 index 4b961a6edc95be13f72f6113ce0c7d253610a30a..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Block/Adminhtml/Attribute/Edit/Form.php +++ /dev/null @@ -1,58 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Adminhtml - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - - -/** - * Attribute edit form block - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Block_Adminhtml_Attribute_Edit_Form extends Mage_Adminhtml_Block_Widget_Form -{ - /** - * Prepare form before rendering HTML - * - * @return Mage_Api2_Block_Adminhtml_Attribute_Edit_Form - */ - protected function _prepareForm() - { - $form = new Varien_Data_Form(array( - 'id' => 'edit_form', - 'action' => $this->getData('action'), - 'method' => 'post' - )); - - - $form->setAction($this->getUrl('*/*/save', array('type' => $this->getRequest()->getParam('type')))) - ->setUseContainer(true); - - $this->setForm($form); - - return parent::_prepareForm(); - } -} diff --git a/app/code/core/Mage/Api2/Block/Adminhtml/Attribute/Grid.php b/app/code/core/Mage/Api2/Block/Adminhtml/Attribute/Grid.php deleted file mode 100644 index 0816e4dc5dae267dd2c8369de1c3390595598999..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Block/Adminhtml/Attribute/Grid.php +++ /dev/null @@ -1,105 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 attributes grid block - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Block_Adminhtml_Attribute_Grid extends Mage_Adminhtml_Block_Widget_Grid -{ - /** - * Set grid ID - * - * @param array $attributes - */ - public function _construct() - { - parent::_construct(); - $this->setId('api2_attributes'); - } - - /** - * Collection object set up - */ - protected function _prepareCollection() - { - $collection = new Varien_Data_Collection(); - - foreach (Mage_Api2_Model_Auth_User::getUserTypes() as $type => $label) { - $collection->addItem( - new Varien_Object(array('user_type_name' => $label, 'user_type_code' => $type)) - ); - } - - $this->setCollection($collection); - } - - /** - * Prepare grid columns - * - * @return Mage_Api2_Block_Adminhtml_Attribute_Grid - */ - protected function _prepareColumns() - { - $this->addColumn('user_type_name', array( - 'header' => $this->__('User Type'), - 'index' => 'user_type_name' - )); - - return parent::_prepareColumns(); - } - - /** - * Disable unnecessary functionality - * - * @return Mage_Api2_Block_Adminhtml_Attribute_Grid - */ - public function _prepareLayout() - { - $this->setFilterVisibility(false); - $this->setPagerVisibility(false); - - return $this; - } - - /** - * Get row URL - * - * @param Varien_Object $row - * @return string|null - */ - public function getRowUrl($row) - { - if (Mage::getSingleton('Mage_Core_Model_Authorization')->isAllowed('Mage_Api2::rest_attributes_edit')) { - return $this->getUrl('*/*/edit', array('type' => $row->getUserTypeCode())); - } - - return null; - } -} diff --git a/app/code/core/Mage/Api2/Block/Adminhtml/Attribute/Tab/Resource.php b/app/code/core/Mage/Api2/Block/Adminhtml/Attribute/Tab/Resource.php deleted file mode 100644 index 6fb02a480f476b9e7e5f66dbfac03dfd3eff9655..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Block/Adminhtml/Attribute/Tab/Resource.php +++ /dev/null @@ -1,143 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Block for rendering attributes tree list tab - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - * @method Mage_Api2_Model_Acl_Global_Role getRole() - * @method Mage_Api2_Block_Adminhtml_Attribute_Tab_Resource setRole(Mage_Api2_Model_Acl_Global_Role $role) - */ -class Mage_Api2_Block_Adminhtml_Attribute_Tab_Resource extends Mage_Adminhtml_Block_Widget_Form - implements Mage_Adminhtml_Block_Widget_Tab_Interface -{ - /** - * Tree model - * - * @var Mage_Api2_Model_Acl_Global_Rule_Tree - */ - protected $_treeModel = false; - - /** - * Constructor - */ - public function _construct() - { - parent::_construct(); - - $this->setId('api2_attribute_section_resources') - ->setData('default_dir', Varien_Db_Select::SQL_ASC) - ->setData('default_sort', 'sort_order') - ->setData('title', $this->__('Attribute Rules Information')) - ->setData('use_ajax', true); - - $options = array('type' => Mage_Api2_Model_Acl_Global_Rule_Tree::TYPE_ATTRIBUTE); - $this->_treeModel = Mage::getModel( - 'Mage_Api2_Model_Acl_Global_Rule_Tree', - array('options' => $options) - ); - - /** @var $permissions Mage_Api2_Model_Acl_Filter_Attribute_ResourcePermission */ - $permissions = Mage::getModel('Mage_Api2_Model_Acl_Filter_Attribute_ResourcePermission'); - $permissions->setFilterValue($this->getRequest()->getParam('type')); - $this->_treeModel->setResourcesPermissions($permissions->getResourcesPermissions()) - ->setHasEntityOnlyAttributes($permissions->getHasEntityOnlyAttributes()); - } - - /** - * Get Json Representation of Resource Tree - * - * @return string - */ - public function getResTreeJson() - { - /** @var $helper Mage_Core_Helper_Data */ - $helper = Mage::helper('Mage_Core_Helper_Data'); - return $helper->jsonEncode($this->_treeModel->getTreeResources()); - } - - /** - * Check if everything is allowed - * - * @return boolean - */ - public function getEverythingAllowed() - { - return $this->_treeModel->getEverythingAllowed(); - } - - /** - * Check if tree has entity only attributes - * - * @return bool - */ - public function hasEntityOnlyAttributes() - { - return $this->_treeModel->getHasEntityOnlyAttributes(); - } - - /** - * Get tab label - * - * @return string - */ - public function getTabLabel() - { - return $this->__('ACL Attribute Rules'); - } - - /** - * Get tab title - * - * @return string - */ - public function getTabTitle() - { - return $this->getTabLabel(); - } - - /** - * Whether tab is available - * - * @return bool - */ - public function canShowTab() - { - return true; - } - - /** - * Whether tab is hidden - * - * @return bool - */ - public function isHidden() - { - return false; - } -} diff --git a/app/code/core/Mage/Api2/Block/Adminhtml/Attribute/Tabs.php b/app/code/core/Mage/Api2/Block/Adminhtml/Attribute/Tabs.php deleted file mode 100644 index bde404bb03634782ce86fbdf6a730b37ee164eba..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Block/Adminhtml/Attribute/Tabs.php +++ /dev/null @@ -1,47 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Block tabs for attributes edit page - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Block_Adminhtml_Attribute_Tabs extends Mage_Adminhtml_Block_Widget_Tabs -{ - /** - * Constructor - */ - public function _construct() - { - parent::_construct(); - - $this->setId('api2_attribute_section_main') - ->setDestElementId('edit_form') - ->setData('title', $this->__('ACL Attributes Information')); - } -} diff --git a/app/code/core/Mage/Api2/Block/Adminhtml/Permissions/User/Edit/Tab/Roles.php b/app/code/core/Mage/Api2/Block/Adminhtml/Permissions/User/Edit/Tab/Roles.php deleted file mode 100644 index ef85a970b704d66f78bcec671a743b55af211952..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Block/Adminhtml/Permissions/User/Edit/Tab/Roles.php +++ /dev/null @@ -1,203 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 role list for admin user permissions - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Block_Adminhtml_Permissions_User_Edit_Tab_Roles - extends Mage_Adminhtml_Block_Widget_Grid - implements Mage_Adminhtml_Block_Widget_Tab_Interface -{ - /** - * Selected API2 roles for grid - * - * @var array - */ - protected $_selectedRoles; - - /** - * Constructor - * Prepare grid parameters - */ - public function _construct() - { - parent::_construct(); - - $this->setId('api2_roles_section') - ->setDefaultSort('sort_order') - ->setDefaultDir(Varien_Db_Select::SQL_ASC) - ->setTitle($this->__('REST Roles Information')) - ->setUseAjax(true); - } - - /** - * Prepare grid collection object - * - * @return Mage_Api2_Block_Adminhtml_Permissions_User_Edit_Tab_Roles - */ - protected function _prepareCollection() - { - /** @var $collection Mage_Api2_Model_Resource_Acl_Global_Role_Collection */ - $collection = Mage::getResourceModel('Mage_Api2_Model_Resource_Acl_Global_Role_Collection'); - $collection->addFieldToFilter('entity_id', array('nin' => Mage_Api2_Model_Acl_Global_Role::getSystemRoles())); - - $this->setCollection($collection); - - return parent::_prepareCollection(); - } - - /** - * Prepare grid columns - * - * @return Mage_Api2_Block_Adminhtml_Permissions_User_Edit_Tab_Roles - */ - protected function _prepareColumns() - { - $this->addColumn('assigned_user_role', array( - 'header_css_class' => 'a-center', - 'header' => $this->__('Assigned'), - 'type' => 'radio', - 'html_name' => 'api2_roles[]', - 'values' => $this->_getSelectedRoles(), - 'align' => 'center', - 'index' => 'entity_id' - )); - - $this->addColumn('role_name', array( - 'header' => $this->__('Role Name'), - 'index' => 'role_name' - )); - - return parent::_prepareColumns(); - } - - /** - * Add custom column filter to collection - * - * @param Mage_Adminhtml_Block_Widget_Grid_Column $column - * @return Mage_Api2_Block_Adminhtml_Permissions_User_Edit_Tab_Roles - */ - protected function _addColumnFilterToCollection($column) - { - if ($column->getId() == 'assigned_user_role') { - $userRoles = $this->_getSelectedRoles(); - if ($column->getFilter()->getValue()) { - $this->getCollection()->addFieldToFilter('entity_id', array('in' => $userRoles)); - } elseif (!empty($userRoles)) { - $this->getCollection()->addFieldToFilter('entity_id', array('nin' => $userRoles)); - } else { - $this->getCollection(); - } - } else { - parent::_addColumnFilterToCollection($column); - } - - return $this; - } - - /** - * Get selected API2 roles for grid - * - * @return array - */ - protected function _getSelectedRoles() - { - if (null === $this->_selectedRoles) { - $userRoles = array(); - - /* @var $user Mage_User_Model_User */ - $user = Mage::registry('permissions_user'); - if ($user->getId()) { - /** @var $collection Mage_Api2_Model_Resource_Acl_Global_Role_Collection */ - $collection = Mage::getResourceModel('Mage_Api2_Model_Resource_Acl_Global_Role_Collection'); - $collection->addFilterByAdminId($user->getId()); - - $userRoles = $collection->getAllIds(); - } - - $this->_selectedRoles = $userRoles; - } - - return $this->_selectedRoles; - } - - /** - * Prepare label for tab - * - * @return string - */ - public function getTabLabel() - { - return $this->__('REST Role'); - } - - /** - * Prepare title for tab - * - * @return string - */ - public function getTabTitle() - { - return $this->__('REST Role'); - } - - /** - * Returns status flag about this tab can be shown or not - * - * @return true - */ - public function canShowTab() - { - return true; - } - - /** - * Returns status flag about this tab hidden or not - * - * @return true - */ - public function isHidden() - { - return false; - } - - /** - * Get controller action url for grid ajax actions - * - * @return string - */ - public function getGridUrl() - { - return $this->getUrl( - '*/api2_role/rolesGrid', - array('user_id' => Mage::registry('permissions_user')->getUserId()) - ); - } -} diff --git a/app/code/core/Mage/Api2/Block/Adminhtml/Roles.php b/app/code/core/Mage/Api2/Block/Adminhtml/Roles.php deleted file mode 100644 index 689857758f970c0f558b5fdf81e290ed9bfeb77d..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Block/Adminhtml/Roles.php +++ /dev/null @@ -1,54 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Adminhtml - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Roles grid container block - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Block_Adminhtml_Roles extends Mage_Adminhtml_Block_Widget_Grid_Container -{ - /** - * Construct grid container - */ - public function _construct() - { - parent::_construct(); - - $this->_blockGroup = 'Mage_Api2'; - $this->_controller = 'adminhtml_roles'; - $this->_headerText = Mage::helper('Mage_Adminhtml_Helper_Data')->__('REST Roles'); - - //check allow edit - if (Mage::getSingleton('Mage_Core_Model_Authorization')->isAllowed('Mage_Api2::rest_roles_add')) { - $this->_updateButton('add', 'label', $this->__('Add Admin Role')); - } else { - $this->_removeButton('add'); - } - } -} diff --git a/app/code/core/Mage/Api2/Block/Adminhtml/Roles/Buttons.php b/app/code/core/Mage/Api2/Block/Adminhtml/Roles/Buttons.php deleted file mode 100644 index 925c9ce0150310b7f63f702d2144e77f2771caa0..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Block/Adminhtml/Roles/Buttons.php +++ /dev/null @@ -1,148 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Adminhtml - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Block for rendering buttons - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - * @method Mage_Api2_Block_Adminhtml_Roles_Buttons setRole(Mage_Api2_Model_Acl_Global_Role $role) - * @method Mage_Api2_Model_Acl_Global_Role getRole() - */ -class Mage_Api2_Block_Adminhtml_Roles_Buttons extends Mage_Adminhtml_Block_Template -{ - /** - * Construct - */ - public function _construct() - { - parent::_construct(); - $this->setTemplate('role/buttons.phtml'); - } - - /** - * Preparing global layout - * - * @return Mage_Api2_Block_Adminhtml_Roles_Buttons - */ - protected function _prepareLayout() - { - $buttons = array( - 'backButton' => array( - 'label' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('Back'), - 'onclick' => sprintf("window.location.href='%s';", $this->getUrl('*/*/')), - 'class' => 'back' - ), - 'resetButton' => array( - 'label' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('Reset'), - 'onclick' => 'window.location.reload()' - ), - 'saveButton' => array( - 'label' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('Save Role'), - 'class' => 'save', - 'data_attr' => array( - 'widget-button' => array('event' => 'save', 'related' => '#role-edit-form') - ) - ), - 'deleteButton' => array( - 'label' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('Delete Role'), - 'onclick' => '', //roleId is not set at this moment, so we set script later - 'class' => 'delete' - ), - ); - - foreach ($buttons as $name=>$data) { - $button = $this->getLayout()->createBlock('Mage_Adminhtml_Block_Widget_Button')->setData($data); - $this->setChild($name, $button); - } - - return parent::_prepareLayout(); - } - - /** - * Get back button HTML - * - * @return string - */ - public function getBackButtonHtml() - { - return $this->getChildHtml('backButton'); - } - - /** - * Get reset button HTML - * - * @return string - */ - public function getResetButtonHtml() - { - return $this->getChildHtml('resetButton'); - } - - /** - * Get save button HTML - * - * @return string - */ - public function getSaveButtonHtml() - { - return $this->getChildHtml('saveButton'); - } - - /** - * Get delete button HTML - * - * @return string - */ - public function getDeleteButtonHtml() - { - if(!$this->getRole() || !$this->getRole()->getId() - || Mage_Api2_Model_Acl_Global_Role::isSystemRole($this->getRole())) { - - return ''; - } - - $this->getChildBlock('deleteButton')->setData('onclick', sprintf("deleteConfirm('%s', '%s')", - Mage::helper('Mage_Adminhtml_Helper_Data')->__('Are you sure you want to do this?'), - $this->getUrl('*/*/delete', array('id' => $this->getRole()->getId())) - )); - - return $this->getChildHtml('deleteButton'); - } - - /** - * Get block caption - * - * @return string - */ - public function getCaption() - { - return $this->getRole() && $this->getRole()->getId() - ? ($this->__('Edit Role') . " '{$this->escapeHtml($this->getRole()->getRoleName())}'") - : $this->__('Add New Role'); - } -} diff --git a/app/code/core/Mage/Api2/Block/Adminhtml/Roles/Grid.php b/app/code/core/Mage/Api2/Block/Adminhtml/Roles/Grid.php deleted file mode 100644 index a1048edfdeeab86a43f5d2659eb159835dc389ae..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Block/Adminhtml/Roles/Grid.php +++ /dev/null @@ -1,146 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Adminhtml - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Roles grid block - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Block_Adminhtml_Roles_Grid extends Mage_Adminhtml_Block_Widget_Grid -{ - /** - * Construct grid block - */ - public function _construct() - { - parent::_construct(); - $this->setId('rolesGrid'); - $this->setUseAjax(true); - $this->setSaveParametersInSession(true); - $this->setDefaultSort('entity_id') - ->setDefaultDir(Varien_Db_Select::SQL_DESC); - } - - /** - * Prepare collection - * - * @return Mage_Api2_Block_Adminhtml_Roles_Grid - */ - protected function _prepareCollection() - { - /** @var $collection Mage_Api2_Model_Resource_Acl_Global_Role_Collection */ - $collection = Mage::getModel('Mage_Api2_Model_Acl_Global_Role')->getCollection(); - $this->setCollection($collection); - parent::_prepareCollection(); - return $this; - } - - /** - * Prepare columns - * - * @return Mage_Api2_Block_Adminhtml_Roles_Grid - */ - protected function _prepareColumns() - { - $this->addColumn('entity_id', array( - 'header' => Mage::helper('Mage_Oauth_Helper_Data')->__('ID'), - 'index' => 'entity_id', - 'align' => 'right', - 'width' => '50px', - )); - - $this->addColumn('role_name', array( - 'header' => Mage::helper('Mage_Oauth_Helper_Data')->__('Role Name'), - 'index' => 'role_name', - 'escape' => true, - )); - - $this->addColumn('tole_user_type', array( - 'header' => Mage::helper('Mage_Oauth_Helper_Data')->__('User Type'), - 'sortable' => false, - 'frame_callback' => array($this, 'decorateUserType') - )); - - $this->addColumn('created_at', array( - 'header' => Mage::helper('Mage_Oauth_Helper_Data')->__('Created At'), - 'index' => 'created_at' - )); - - parent::_prepareColumns(); - return $this; - } - - /** - * Get grid URL - * - * @return string - */ - public function getGridUrl() - { - return $this->getUrl('*/*/grid', array('_current' => true)); - } - - /** - * Get row URL - * - * @param Mage_Api2_Model_Acl_Global_Role $row - * @return string|null - */ - public function getRowUrl($row) - { - if (Mage::getSingleton('Mage_Core_Model_Authorization')->isAllowed('Mage_Api2::rest_roles_edit')) { - return $this->getUrl('*/*/edit', array('id' => $row->getId())); - } - return null; - } - - /** - * Decorate 'User Type' column - * - * @param string $renderedValue Rendered value - * @param Mage_Api2_Model_Acl_Global_Role $row - * @param Mage_Adminhtml_Block_Widget_Grid_Column $column - * @param bool $isExport - * @return string - */ - public function decorateUserType($renderedValue, $row, $column, $isExport) - { - switch ($row->getEntityId()) { - case Mage_Api2_Model_Acl_Global_Role::ROLE_GUEST_ID: - $userType = Mage::helper('Mage_Api2_Helper_Data')->__('Guest'); - break; - case Mage_Api2_Model_Acl_Global_Role::ROLE_CUSTOMER_ID: - $userType = Mage::helper('Mage_Api2_Helper_Data')->__('Customer'); - break; - default: - $userType = Mage::helper('Mage_Api2_Helper_Data')->__('Admin'); - break; - } - return $userType; - } -} diff --git a/app/code/core/Mage/Api2/Block/Adminhtml/Roles/Tab/Info.php b/app/code/core/Mage/Api2/Block/Adminhtml/Roles/Tab/Info.php deleted file mode 100644 index a42158bf35a39ca0e92874c3f9dd78189846c11d..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Block/Adminhtml/Roles/Tab/Info.php +++ /dev/null @@ -1,131 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Adminhtml - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - - -/** - * Block for rendering role info tab - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - * @method Mage_Api2_Model_Acl_Global_Role getRole() - * @method Mage_Api2_Block_Adminhtml_Roles_Tab_Info setRole(Mage_Api2_Model_Acl_Global_Role $role) - */ -class Mage_Api2_Block_Adminhtml_Roles_Tab_Info extends Mage_Adminhtml_Block_Widget_Form - implements Mage_Adminhtml_Block_Widget_Tab_Interface -{ - /** - * Prepare form object - */ - protected function _prepareForm() - { - $form = new Varien_Data_Form(); - - $fieldset = $form->addFieldset('base_fieldset', array( - 'legend' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('Role Information') - )); - - $data = array( - 'name' => 'role_name', - 'label' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('Role Name'), - 'id' => 'role_name', - 'class' => 'required-entry', - 'required' => true, - ); - - if ($this->isHidden()) { - /** @var $helper Mage_Core_Helper_Data */ - $helper = Mage::helper('Mage_Core_Helper_Data'); - - $data['note'] = Mage::helper('Mage_Api2_Helper_Data')->__( - '%s role is protected.', - $helper->escapeHtml($this->getRole()->getRoleName()) - ); - $data['readonly'] = 'readonly'; - } - $fieldset->addField('role_name', 'text', $data); - - $fieldset->addField('entity_id', 'hidden', - array( - 'name' => 'id', - ) - ); - - $fieldset->addField('in_role_users', 'hidden', - array( - 'name' => 'in_role_users', - 'id' => 'in_role_userz', - ) - ); - - $fieldset->addField('in_role_users_old', 'hidden', array('name' => 'in_role_users_old')); - - if ($this->getRole()) { - $form->setValues($this->getRole()->getData()); - } - $this->setForm($form); - } - - /** - * Get tab label - * - * @return string - */ - public function getTabLabel() - { - return Mage::helper('Mage_Api2_Helper_Data')->__('Role Info'); - } - - /** - * Get tab title - * - * @return string - */ - public function getTabTitle() - { - return $this->getTabLabel(); - } - - /** - * Whether tab is available - * - * @return bool - */ - public function canShowTab() - { - return true; - } - - /** - * Whether tab is hidden - * - * @return bool - */ - public function isHidden() - { - return $this->getRole() && Mage_Api2_Model_Acl_Global_Role::isSystemRole($this->getRole()); - } -} diff --git a/app/code/core/Mage/Api2/Block/Adminhtml/Roles/Tab/Resources.php b/app/code/core/Mage/Api2/Block/Adminhtml/Roles/Tab/Resources.php deleted file mode 100644 index 0988b22b30ad5ec6ad816b3373c5f51bbd640966..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Block/Adminhtml/Roles/Tab/Resources.php +++ /dev/null @@ -1,154 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Block for rendering resources list tab - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - * @method Mage_Api2_Model_Acl_Global_Role getRole() - * @method Mage_Api2_Block_Adminhtml_Roles_Tab_Resources setRole(Mage_Api2_Model_Acl_Global_Role $role) - */ -class Mage_Api2_Block_Adminhtml_Roles_Tab_Resources extends Mage_Adminhtml_Block_Widget_Form - implements Mage_Adminhtml_Block_Widget_Tab_Interface -{ - /** - * Role model - * - * @var Mage_Api2_Model_Acl_Global_Role - */ - protected $_role; - - /** - * Tree model - * - * @var Mage_Api2_Model_Acl_Global_Rule_Tree - */ - protected $_treeModel = false; - - /** - * Constructor - */ - public function _construct() - { - parent::_construct(); - - $this->setId('api2_role_section_resources') - ->setData('default_dir', Varien_Db_Select::SQL_ASC) - ->setData('default_sort', 'sort_order') - ->setData('title', Mage::helper('Mage_Api2_Helper_Data')->__('Api Rules Information')) - ->setData('use_ajax', true); - - $options = array('type' => Mage_Api2_Model_Acl_Global_Rule_Tree::TYPE_PRIVILEGE); - $this->_treeModel = Mage::getModel( - 'Mage_Api2_Model_Acl_Global_Rule_Tree', array('options' => $options) - ); - } - - /** - * Get Json Representation of Resource Tree - * - * @return string - */ - public function getResTreeJson() - { - $this->_prepareTreeModel(); - /** @var $helper Mage_Core_Helper_Data */ - $helper = Mage::helper('Mage_Core_Helper_Data'); - return $helper->jsonEncode($this->_treeModel->getTreeResources()); - } - - /** - * Prepare tree model - * - * @return Mage_Api2_Block_Adminhtml_Roles_Tab_Resources - */ - public function _prepareTreeModel() - { - $role = $this->getRole(); - if ($role) { - $permissionModel = $role->getPermissionModel(); - $permissionModel->setFilterValue($role); - $this->_treeModel->setResourcesPermissions($permissionModel->getResourcesPermissions()); - } else { - $role = Mage::getModel('Mage_Api2_Model_Acl_Global_Role'); - } - $this->_treeModel->setRole($role); - return $this; - } - - /** - * Check if everything is allowed - * - * @return boolean - */ - public function getEverythingAllowed() - { - $this->_prepareTreeModel(); - return $this->_treeModel->getEverythingAllowed(); - } - - /** - * Get tab label - * - * @return string - */ - public function getTabLabel() - { - return Mage::helper('Mage_Api2_Helper_Data')->__('Role API Resources'); - } - - /** - * Get tab title - * - * @return string - */ - public function getTabTitle() - { - return $this->getTabLabel(); - } - - /** - * Whether tab is available - * - * @return bool - */ - public function canShowTab() - { - return true; - } - - /** - * Whether tab is hidden - * - * @return bool - */ - public function isHidden() - { - return false; - } -} diff --git a/app/code/core/Mage/Api2/Block/Adminhtml/Roles/Tab/Users.php b/app/code/core/Mage/Api2/Block/Adminhtml/Roles/Tab/Users.php deleted file mode 100644 index 28e3975ee742e9c595a3e2ebb89d37c3e8d1a991..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Block/Adminhtml/Roles/Tab/Users.php +++ /dev/null @@ -1,239 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Adminhtml - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Block for rendering users list tab - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - * @method Mage_Api2_Model_Acl_Global_Role getRole() - * @method Mage_Api2_Block_Adminhtml_Roles_Tab_Users setRole(Mage_Api2_Model_Acl_Global_Role $role) - * @method Mage_Api2_Block_Adminhtml_Roles_Tab_Users setUsers(array $users) - * @method Mage_User_Model_Resource_User_Collection getCollection() - */ -class Mage_Api2_Block_Adminhtml_Roles_Tab_Users extends Mage_Adminhtml_Block_Widget_Grid - implements Mage_Adminhtml_Block_Widget_Tab_Interface -{ - /** - * Construct grid block - */ - public function _construct() - { - parent::_construct(); - $this->setId('roleUsersGrid'); - $this->setData('use_ajax', true); - $this->setSaveParametersInSession(true); - $this->setDefaultSort('user_id') - ->setDefaultDir(Varien_Db_Select::SQL_DESC); - $this->setDefaultFilter(array('filter_in_role_users'=>1)); - } - - /** - * Prepare collection - * - * @return Mage_Api2_Block_Adminhtml_Roles_Tab_Users - */ - protected function _prepareCollection() - { - /** @var $collection Mage_User_Model_Resource_User_Collection */ - $collection = Mage::getModel('Mage_User_Model_User')->getCollection(); - $collection->getSelect()->joinLeft( - array('acl' => $collection->getTable('api2_acl_user')), - 'acl.admin_id = main_table.user_id', - 'role_id' - ); - if ($this->getRole() && $this->getRole()->getId()) { - $collection->addFilter('acl.role_id', $this->getRole()->getId()); - } - - $this->setCollection($collection); - parent::_prepareCollection(); - return $this; - } - - /** - * Prepare columns - * - * @return Mage_Api2_Block_Adminhtml_Roles_Tab_Users - */ - protected function _prepareColumns() - { - $this->addColumn('filter_in_role_users', array( - 'header_css_class' => 'a-center', - 'type' => 'checkbox', - 'name' => 'filter_in_role_users', - 'values' => $this->getUsers(), - 'align' => 'center', - 'index' => 'user_id' - )); - - $this->addColumn('user_id', array( - 'header' => Mage::helper('Mage_Api2_Helper_Data')->__('ID'), 'index' => 'user_id', 'align' => 'right', 'width' => '50px', - )); - - $this->addColumn('username', array( - 'header' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('User Name'), 'align' => 'left', 'index' => 'username' - )); - - $this->addColumn('firstname', array( - 'header' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('First Name'), 'align' => 'left', 'index' => 'firstname' - )); - - $this->addColumn('lastname', array( - 'header' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('Last Name'), 'align' => 'left', 'index' => 'lastname' - )); - - return parent::_prepareColumns(); - } - - /** - * Get grid URL - * - * @return string - */ - public function getGridUrl() - { - return $this->getUrl('*/*/usersGrid', array('_current' => true)); - } - - /** - * Get row URL - * - * @param Mage_Api2_Model_Acl_Global_Role $row - * @return string|null - */ - public function getRowUrl($row) - { - return null; - } - - /** - * Get tab label - * - * @return string - */ - public function getTabLabel() - { - return Mage::helper('Mage_Api2_Helper_Data')->__('Role Users'); - } - - /** - * Get tab title - * - * @return string - */ - public function getTabTitle() - { - return $this->getTabLabel(); - } - - /** - * Whether tab is available - * - * @return bool - */ - public function canShowTab() - { - return !$this->isHidden(); - } - - /** - * Whether tab is hidden - * - * @return bool - */ - public function isHidden() - { - return $this->getRole() && Mage_Api2_Model_Acl_Global_Role::isSystemRole($this->getRole()); - } - - /** - * Render block only when not hidden - * - * @return string - */ - public function _toHtml() - { - if (!$this->isHidden()) { - return parent::_toHtml(); - } - return ''; - } - - /** - * @param Mage_Adminhtml_Block_Widget_Grid_Column $column - * @return Mage_Api2_Block_Adminhtml_Roles_Tab_Users - */ - protected function _addColumnFilterToCollection($column) - { - if ($column->getId() == 'filter_in_role_users') { - $inRoleIds = $this->getUsers(); - if (empty($inRoleIds)) { - $inRoleIds = 0; - } - - if ($column->getFilter()->getValue()) { - $this->getCollection()->addFieldToFilter('user_id', array('in' => $inRoleIds)); - } else { - if($inRoleIds) { - $this->getCollection()->addFieldToFilter('user_id', array('nin' => $inRoleIds)); - } - } - } else { - parent::_addColumnFilterToCollection($column); - } - return $this; - } - - /** - * Get users - * - * @param bool $json - * @return array|string - */ - public function getUsers($json = false) - { - $users = $this->getData('users'); - - if ($json) { - if ($users === array()) { - return '{}'; - } - $jsonUsers = array(); - foreach($users as $usrId) { - $jsonUsers[$usrId] = 0; - } - /** @var $helper Mage_Core_Helper_Data */ - $helper = Mage::helper('Mage_Core_Helper_Data'); - $result = $helper->jsonEncode((object) $jsonUsers); - } else { - $result = array_values($users); - } - - return $result; - } -} diff --git a/app/code/core/Mage/Api2/Block/Adminhtml/Roles/Tabs.php b/app/code/core/Mage/Api2/Block/Adminhtml/Roles/Tabs.php deleted file mode 100644 index be27d916b082597eff5cf59e6a003805485d41b9..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Block/Adminhtml/Roles/Tabs.php +++ /dev/null @@ -1,65 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Adminhtml - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Block tabs for role edit page - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - * @method Mage_Api2_Block_Adminhtml_Roles_Tabs setRole(Mage_Api2_Model_Acl_Global_Role $role) - * @method Mage_Api2_Model_Acl_Global_Role getRole() - */ -class Mage_Api2_Block_Adminhtml_Roles_Tabs extends Mage_Adminhtml_Block_Widget_Tabs -{ - - /** - * Constructor - */ - public function _construct() - { - parent::_construct(); - $this->setId('role_info_tabs'); - $this->setDestElementId('role-edit-form'); - $this->setData('title', Mage::helper('Mage_Api2_Helper_Data')->__('Role Information')); - } - - /** - * Hook before html rendering - * - * @return Mage_Api2_Block_Adminhtml_Roles_Tabs - */ - protected function _beforeToHtml() - { - $role = $this->getRole(); - if ($role && Mage_Api2_Model_Acl_Global_Role::isSystemRole($role)) { - $this->setActiveTab('api2_role_section_resources'); - } else { - $this->setActiveTab('api2_role_section_info'); - } - return parent::_beforeToHtml(); - } -} diff --git a/app/code/core/Mage/Api2/Exception.php b/app/code/core/Mage/Api2/Exception.php deleted file mode 100644 index 9de45b26836657dae626dd261ea7f26ae6f056ba..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Exception.php +++ /dev/null @@ -1,50 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API exception - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Exception extends Exception -{ - /** - * Exception constructor - * - * @param string $message - * @param int $code - */ - public function __construct($message, $code) - { - if ($code <= 100 || $code >= 599) { - throw new Exception(sprintf('Invalid Exception code "%d"', $code)); - } - - parent::__construct($message, $code); - } -} diff --git a/app/code/core/Mage/Api2/Helper/Data.php b/app/code/core/Mage/Api2/Helper/Data.php deleted file mode 100644 index 40a623e77cc38276317f33b21abb460b1d6bd8c2..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Helper/Data.php +++ /dev/null @@ -1,198 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Webservice API2 data helper - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Helper_Data extends Mage_Core_Helper_Abstract -{ - /** - * Request interpret adapters - */ - const XML_PATH_API2_REQUEST_INTERPRETERS = 'global/api2/request/interpreters'; - - /** - * Response render adapters - */ - const XML_PATH_API2_RESPONSE_RENDERS = 'global/api2/response/renders'; - - /**#@+ - * Config paths - */ - const XML_PATH_AUTH_ADAPTERS = 'global/api2/auth_adapters'; - const XML_PATH_USER_TYPES = 'global/api2/user_types'; - /**#@- */ - - /** - * Compare order to be used in adapters list sort - * - * @param int $a - * @param int $b - * @return int - */ - protected static function _compareOrder($a, $b) - { - if ($a['order'] == $b['order']) { - return 0; - } - return ($a['order'] < $b['order']) ? -1 : 1; - } - - /** - * Retrieve Auth adapters info from configuration file as array - * - * @param bool $enabledOnly - * @return array - */ - public function getAuthAdapters($enabledOnly = false) - { - $adapters = Mage::getConfig()->getNode(self::XML_PATH_AUTH_ADAPTERS); - - if (!$adapters) { - return array(); - } - $adapters = $adapters->asArray(); - - if ($enabledOnly) { - foreach ($adapters as $adapter) { - if (empty($adapter['enabled'])) { - unset($adapters); - } - } - $adapters = (array) $adapters; - } - uasort($adapters, array('Mage_Api2_Helper_Data', '_compareOrder')); - - return $adapters; - } - - /** - * Retrieve enabled user types in form of user type => user model pairs - * - * @return array - */ - public function getUserTypes() - { - $userModels = array(); - $types = Mage::getConfig()->getNode(self::XML_PATH_USER_TYPES); - - if ($types) { - foreach ($types->asArray() as $type => $params) { - if (!empty($params['allowed'])) { - $userModels[$type] = $params['model']; - } - } - } - return $userModels; - } - - /** - * Get interpreter type for Request body according to Content-type HTTP header - * - * @return array - */ - public function getRequestInterpreterAdapters() - { - return (array) Mage::app()->getConfig()->getNode(self::XML_PATH_API2_REQUEST_INTERPRETERS); - } - - /** - * Get interpreter type for Request body according to Content-type HTTP header - * - * @return array - */ - public function getResponseRenderAdapters() - { - return (array) Mage::app()->getConfig()->getNode(self::XML_PATH_API2_RESPONSE_RENDERS); - } - - /** - * Check API type support - * - * @param string $type - * @return bool - */ - public function isApiTypeSupported($type) - { - return in_array($type, Mage_Api2_Model_Server::getApiTypes()); - } - - /** - * Get allowed attributes of a rule - * - * @param string $userType - * @param string $resourceId - * @param string $operation One of Mage_Api2_Model_Resource::OPERATION_ATTRIBUTE_... constant - * @return array - */ - public function getAllowedAttributes($userType, $resourceId, $operation) - { - /** @var $resource Mage_Api2_Model_Resource_Acl_Filter_Attribute */ - $resource = Mage::getResourceModel('Mage_Api2_Model_Resource_Acl_Filter_Attribute'); - - $attributes = $resource->getAllowedAttributes($userType, $resourceId, $operation); - - return ($attributes === false || $attributes === null ? array() : explode(',', $attributes)); - } - - /** - * Check if ALL attributes are allowed - * - * @param string $userType - * @return bool - */ - public function isAllAttributesAllowed($userType) - { - /** @var $resource Mage_Api2_Model_Resource_Acl_Filter_Attribute */ - $resource = Mage::getResourceModel('Mage_Api2_Model_Resource_Acl_Filter_Attribute'); - - return $resource->isAllAttributesAllowed($userType); - } - - /** - * Get operation type for specified operation - * - * @param string $operation One of Mage_Api2_Model_Resource::OPERATION_... constant - * @return string One of Mage_Api2_Model_Resource::OPERATION_ATTRIBUTE_... constant - * @throws Exception - */ - public function getTypeOfOperation($operation) - { - if (Mage_Api2_Model_Resource::OPERATION_RETRIEVE === $operation) { - return Mage_Api2_Model_Resource::OPERATION_ATTRIBUTE_READ; - } elseif (Mage_Api2_Model_Resource::OPERATION_CREATE === $operation) { - return Mage_Api2_Model_Resource::OPERATION_ATTRIBUTE_WRITE; - } elseif (Mage_Api2_Model_Resource::OPERATION_UPDATE === $operation) { - return Mage_Api2_Model_Resource::OPERATION_ATTRIBUTE_WRITE; - } else { - throw new Exception('Can not determine operation type'); - } - } -} diff --git a/app/code/core/Mage/Api2/Model/Acl.php b/app/code/core/Mage/Api2/Model/Acl.php deleted file mode 100644 index eb3f1a38af5e334c1606dfaedabb62e2b3353161..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Acl.php +++ /dev/null @@ -1,187 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API User ACL model - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Model_Acl extends Zend_Acl -{ - /** - * REST ACL roles collection - * - * @var Mage_Api2_Model_Resource_Acl_Global_Role_Collection - */ - protected $_rolesCollection; - - /** - * API2 config model instance - * - * @var Mage_Api2_Model_Config - */ - protected $_config; - - /** - * Resource type of request - * - * @var string - */ - protected $_resourceType; - - /** - * Operation of request - * - * @var string - */ - protected $_operation; - - /** - * Constructor - * - * @param array $options - */ - public function __construct($options) - { - if (!isset($options['resource_type']) || empty($options['resource_type'])) { - throw new Exception("Passed parameter 'resource_type' is wrong."); - } - if (!isset($options['operation']) || empty($options['operation'])) { - throw new Exception("Passed parameter 'operation' is wrong."); - } - $this->_resourceType = $options['resource_type']; - $this->_operation = $options['operation']; - - $this->_setResources(); - $this->_setRoles(); - $this->_setRules(); - } - - /** - * Retrieve REST ACL roles collection - * - * @return Mage_Api2_Model_Resource_Acl_Global_Role_Collection - */ - protected function _getRolesCollection() - { - if (null === $this->_rolesCollection) { - $this->_rolesCollection = Mage::getResourceModel('Mage_Api2_Model_Resource_Acl_Global_Role_Collection'); - } - return $this->_rolesCollection; - } - - /** - * Retrieve API2 config model instance - * - * @return Mage_Api2_Model_Config - */ - protected function _getConfig() - { - if (null === $this->_config) { - $this->_config = Mage::getModel('Mage_Api2_Model_Config'); - } - return $this->_config; - } - - /** - * Retrieve resources types and set into ACL - * - * @return Mage_Api2_Model_Acl - */ - protected function _setResources() - { - foreach ($this->_getConfig()->getResourcesTypes() as $type) { - $this->addResource($type); - } - return $this; - } - - /** - * Retrieve roles from DB and set into ACL - * - * @return Mage_Api2_Model_Acl - */ - protected function _setRoles() - { - /** @var $role Mage_Api2_Model_Acl_Global_Role */ - foreach ($this->_getRolesCollection() as $role) { - $this->addRole($role->getId()); - } - return $this; - } - - /** - * Retrieve rules data from DB and inject it into ACL - * - * @return Mage_Api2_Model_Acl - */ - protected function _setRules() - { - /** @var $rulesCollection Mage_Api2_Model_Resource_Acl_Global_Rule_Collection */ - $rulesCollection = Mage::getResourceModel('Mage_Api2_Model_Resource_Acl_Global_Rule_Collection'); - - /** @var $rule Mage_Api2_Model_Acl_Global_Rule */ - foreach ($rulesCollection as $rule) { - if (Mage_Api2_Model_Acl_Global_Rule::RESOURCE_ALL === $rule->getResourceId()) { - if (in_array($rule->getRoleId(), Mage_Api2_Model_Acl_Global_Role::getSystemRoles())) { - /** @var $role Mage_Api2_Model_Acl_Global_Role */ - $role = $this->_getRolesCollection()->getItemById($rule->getRoleId()); - $privileges = $this->_getConfig()->getResourceUserPrivileges( - $this->_resourceType, - $role->getConfigNodeName() - ); - - if (!array_key_exists($this->_operation, $privileges)) { - continue; - } - } - - $this->allow($rule->getRoleId()); - } else { - $this->allow($rule->getRoleId(), $rule->getResourceId(), $rule->getPrivilege()); - } - } - return $this; - } - - /** - * Adds a Role having an identifier unique to the registry - * OVERRIDE to allow numeric roles identifiers - * - * @param int $roleId Role identifier - * @param Zend_Acl_Role_Interface|string|array $parents - * @return Zend_Acl Provides a fluent interface - */ - public function addRole($roleId, $parents = null) - { - if (!is_numeric($roleId)) { - throw new Exception('Invalid role identifier'); - } - return parent::addRole((string) $roleId); - } -} diff --git a/app/code/core/Mage/Api2/Model/Acl/Filter.php b/app/code/core/Mage/Api2/Model/Acl/Filter.php deleted file mode 100644 index 50d5f0473f9d9639166c9d0a2b241629e6996333..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Acl/Filter.php +++ /dev/null @@ -1,193 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API ACL filter - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Model_Acl_Filter -{ - /** - * Attributes allowed for use - * - * @var array - */ - protected $_allowedAttributes; - - /** - * A list of attributes to be included into output - * - * @var array - */ - protected $_attributesToInclude; - - /** - * Associated resource model - * - * @var Mage_Api2_Model_Resource - */ - protected $_resource; - - /** - * Object constructor - * - * @param Mage_Api2_Model_Resource $resource - */ - public function __construct(Mage_Api2_Model_Resource $resource) - { - $this->_resource = $resource; - } - - /** - * Return only the data which keys are allowed - * - * @param array $allowedAttributes List of attributes available to use - * @param array $data Associative array attribute to value - * @return array - */ - protected function _filter(array $allowedAttributes, array $data) - { - foreach ($data as $attribute => $value) { - if (!in_array($attribute, $allowedAttributes)) { - unset($data[$attribute]); - } - } - return $data; - } - - /** - * Strip attributes in of collection items - * - * @param array $items - * @return array - */ - public function collectionIn($items) - { - foreach ($items as &$data) { - $data = is_array($data) ? $this->in($data) : array(); - } - return $items; - } - - /** - * Strip attributes out of collection items - * - * @param array $items - * @return array - */ - public function collectionOut($items) - { - foreach ($items as &$data) { - $data = $this->out($data); - } - return $items; - } - - /** - * Fetch array of allowed attributes for given resource type, operation and user type. - * - * @param string $operationType OPTIONAL One of Mage_Api2_Model_Resource::OPERATION_ATTRIBUTE_... constant - * @return array - */ - public function getAllowedAttributes($operationType = null) - { - if (null === $this->_allowedAttributes) { - /** @var $helper Mage_Api2_Helper_Data */ - $helper = Mage::helper('Mage_Api2_Helper_Data'); - - if (null === $operationType) { - $operationType = $helper->getTypeOfOperation($this->_resource->getOperation()); - } - if ($helper->isAllAttributesAllowed($this->_resource->getUserType())) { - $this->_allowedAttributes = array_keys($this->_resource->getAvailableAttributes( - $this->_resource->getUserType(), $operationType - )); - } else { - $this->_allowedAttributes = $helper->getAllowedAttributes( - $this->_resource->getUserType(), $this->_resource->getResourceType(), $operationType - ); - } - // force attributes to be no filtered - foreach ($this->_resource->getForcedAttributes() as $forcedAttr) { - if (!in_array($forcedAttr, $this->_allowedAttributes)) { - $this->_allowedAttributes[] = $forcedAttr; - } - } - } - return $this->_allowedAttributes; - } - - /** - * Retrieve a list of attributes to be included in output based on available and requested attributes - * - * @return array - */ - public function getAttributesToInclude() - { - if (null === $this->_attributesToInclude) { - $allowedAttrs = $this->getAllowedAttributes(Mage_Api2_Model_Resource::OPERATION_ATTRIBUTE_READ); - $requestedAttrs = $this->_resource->getRequest()->getRequestedAttributes(); - - if ($requestedAttrs) { - foreach ($allowedAttrs as $allowedAttr) { - if (in_array($allowedAttr, $requestedAttrs)) { - $this->_attributesToInclude[] = $allowedAttr; - } - } - } else { - $this->_attributesToInclude = $allowedAttrs; - } - } - return $this->_attributesToInclude; - } - - /** - * Filter data for write operations - * - * @param array $requestData - * @return array - */ - public function in(array $requestData) - { - $allowedAttributes = $this->getAllowedAttributes(Mage_Api2_Model_Resource::OPERATION_ATTRIBUTE_WRITE); - - return $this->_filter($allowedAttributes, $requestData); - } - - /** - * Filter data before output - * - * @param array $retrievedData - * @return array - */ - public function out(array $retrievedData) - { - return $this->_filter($this->getAttributesToInclude(), $retrievedData); - } -} diff --git a/app/code/core/Mage/Api2/Model/Acl/Filter/Attribute.php b/app/code/core/Mage/Api2/Model/Acl/Filter/Attribute.php deleted file mode 100644 index 9d63fb7c0e8e1b4cf7caf62f181c63141b237f32..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Acl/Filter/Attribute.php +++ /dev/null @@ -1,77 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 filter ACL attribute model - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - * @method Mage_Api2_Model_Resource_Acl_Filter_Attribute_Collection getCollection() - * @method Mage_Api2_Model_Resource_Acl_Filter_Attribute_Collection getResourceCollection() - * @method Mage_Api2_Model_Resource_Acl_Filter_Attribute getResource() - * @method Mage_Api2_Model_Resource_Acl_Filter_Attribute _getResource() - * @method string getUserType() - * @method Mage_Api2_Model_Acl_Filter_Attribute setUserType() setUserType(string $type) - * @method string getResourceId() - * @method Mage_Api2_Model_Acl_Filter_Attribute setResourceId() setResourceId(string $resource) - * @method string getOperation() - * @method Mage_Api2_Model_Acl_Filter_Attribute setOperation() setOperation(string $operation) - * @method string getAllowedAttributes() - * @method Mage_Api2_Model_Acl_Filter_Attribute setAllowedAttributes() setAllowedAttributes(string $attributes) - */ -class Mage_Api2_Model_Acl_Filter_Attribute extends Mage_Core_Model_Abstract -{ - /** - * Permissions model - * - * @var Mage_Api2_Model_Acl_Filter_Attribute_ResourcePermission - */ - protected $_permissionModel; - - /** - * Initialize resource model - * - * @return void - */ - protected function _construct() - { - $this->_init('Mage_Api2_Model_Resource_Acl_Filter_Attribute'); - } - - /** - * Get pairs resources-permissions for current attribute - * - * @return Mage_Api2_Model_Acl_Filter_Attribute_ResourcePermission - */ - public function getPermissionModel() - { - if (null == $this->_permissionModel) { - $this->_permissionModel = Mage::getModel('Mage_Api2_Model_Acl_Filter_Attribute_ResourcePermission'); - } - return $this->_permissionModel; - } -} diff --git a/app/code/core/Mage/Api2/Model/Acl/Filter/Attribute/Operation.php b/app/code/core/Mage/Api2/Model/Acl/Filter/Attribute/Operation.php deleted file mode 100644 index ab524ceec4cac509c0a5dadbee3862a3ba736d5f..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Acl/Filter/Attribute/Operation.php +++ /dev/null @@ -1,67 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Operation source model - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Model_Acl_Filter_Attribute_Operation -{ - /** - * Get options paramets - * - * @return array - */ - static public function toOptionArray() - { - return array( - array( - 'value' => Mage_Api2_Model_Resource::OPERATION_ATTRIBUTE_READ, - 'label' => Mage::helper('Mage_Api2_Helper_Data')->__('Read') - ), - array( - 'value' => Mage_Api2_Model_Resource::OPERATION_ATTRIBUTE_WRITE, - 'label' => Mage::helper('Mage_Api2_Helper_Data')->__('Write') - ) - ); - } - - /** - * Get options in "key-value" format - * - * @return array - */ - static public function toArray() - { - return array( - Mage_Api2_Model_Resource::OPERATION_ATTRIBUTE_READ => Mage::helper('Mage_Api2_Helper_Data')->__('Read'), - Mage_Api2_Model_Resource::OPERATION_ATTRIBUTE_WRITE => Mage::helper('Mage_Api2_Helper_Data')->__('Write') - ); - } -} diff --git a/app/code/core/Mage/Api2/Model/Acl/Filter/Attribute/ResourcePermission.php b/app/code/core/Mage/Api2/Model/Acl/Filter/Attribute/ResourcePermission.php deleted file mode 100644 index 3ca5db61f6d0a7466a26e6fd7fa9cdf7850ac8f6..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Acl/Filter/Attribute/ResourcePermission.php +++ /dev/null @@ -1,181 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 filter ACL attribute resources permissions model - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Model_Acl_Filter_Attribute_ResourcePermission - implements Mage_Api2_Model_Acl_PermissionInterface -{ - /** - * Resources permissions - * - * @var array - */ - protected $_resourcesPermissions; - - /** - * Filter item value - * - * @var string - */ - protected $_userType; - - /** - * Flag if resource has entity only attributes - * - * @var bool - */ - protected $_hasEntityOnlyAttributes = false; - - /** - * Get resources permissions for selected role - * - * @return array - */ - public function getResourcesPermissions() - { - if (null === $this->_resourcesPermissions) { - $rulesPairs = array(); - - if ($this->_userType) { - $allowedAttributes = array(); - - /** @var $rules Mage_Api2_Model_Resource_Acl_Filter_Attribute_Collection */ - $rules = Mage::getResourceModel('Mage_Api2_Model_Resource_Acl_Filter_Attribute_Collection'); - $rules->addFilterByUserType($this->_userType); - - foreach ($rules as $rule) { - if (Mage_Api2_Model_Acl_Global_Rule::RESOURCE_ALL === $rule->getResourceId()) { - $rulesPairs[$rule->getResourceId()] = Mage_Api2_Model_Acl_Global_Rule_Permission::TYPE_ALLOW; - } - - /** @var $rule Mage_Api2_Model_Acl_Filter_Attribute */ - if (null !== $rule->getAllowedAttributes()) { - $allowedAttributes[$rule->getResourceId()][$rule->getOperation()] = explode( - ',', $rule->getAllowedAttributes() - ); - } - } - - /** @var $config Mage_Api2_Model_Config */ - $config = Mage::getModel('Mage_Api2_Model_Config'); - - /** @var $operationSource Mage_Api2_Model_Acl_Filter_Attribute_Operation */ - $operationSource = Mage::getModel('Mage_Api2_Model_Acl_Filter_Attribute_Operation'); - - foreach ($config->getResourcesTypes() as $resource) { - $resourceUserPrivileges = $config->getResourceUserPrivileges($resource, $this->_userType); - - if (!$resourceUserPrivileges) { // skip user without any privileges for resource - continue; - } - $operations = $operationSource->toArray(); - - if (empty($resourceUserPrivileges[Mage_Api2_Model_Resource::OPERATION_CREATE]) - && empty($resourceUserPrivileges[Mage_Api2_Model_Resource::OPERATION_UPDATE]) - ) { - unset($operations[Mage_Api2_Model_Resource::OPERATION_ATTRIBUTE_WRITE]); - } - if (empty($resourceUserPrivileges[Mage_Api2_Model_Resource::OPERATION_RETRIEVE])) { - unset($operations[Mage_Api2_Model_Resource::OPERATION_ATTRIBUTE_READ]); - } - if (!$operations) { // skip resource without any operations allowed - continue; - } - try { - /** @var $resourceModel Mage_Api2_Model_Resource */ - $resourceModel = Mage::getModel($config->getResourceModel($resource)); - if ($resourceModel) { - $resourceModel->setResourceType($resource) - ->setUserType($this->_userType); - - foreach ($operations as $operation => $operationLabel) { - if (!$this->_hasEntityOnlyAttributes - && $config->getResourceEntityOnlyAttributes($resource, $this->_userType, $operation) - ) { - $this->_hasEntityOnlyAttributes = true; - } - $availableAttributes = $resourceModel->getAvailableAttributes( - $this->_userType, - $operation - ); - asort($availableAttributes); - foreach ($availableAttributes as $attribute => $attributeLabel) { - $status = isset($allowedAttributes[$resource][$operation]) - && in_array($attribute, $allowedAttributes[$resource][$operation]) - ? Mage_Api2_Model_Acl_Global_Rule_Permission::TYPE_ALLOW - : Mage_Api2_Model_Acl_Global_Rule_Permission::TYPE_DENY; - - $rulesPairs[$resource]['operations'][$operation]['attributes'][$attribute] = array( - 'status' => $status, - 'title' => $attributeLabel - ); - } - } - } - } catch (Exception $e) { - // getModel() throws exception when application is in development mode - Mage::logException($e); - } - } - } - $this->_resourcesPermissions = $rulesPairs; - } - return $this->_resourcesPermissions; - } - - /** - * Set filter value - * - * Set user type - * - * @param string $userType - * @return Mage_Api2_Model_Acl_Filter_Attribute_ResourcePermission - */ - public function setFilterValue($userType) - { - if (!array_key_exists($userType, Mage_Api2_Model_Auth_User::getUserTypes())) { - throw new Exception('Unknown user type.'); - } - $this->_userType = $userType; - return $this; - } - - /** - * Get flag value - * - * @return bool - */ - public function getHasEntityOnlyAttributes() - { - return $this->_hasEntityOnlyAttributes; - } -} diff --git a/app/code/core/Mage/Api2/Model/Acl/Global.php b/app/code/core/Mage/Api2/Model/Acl/Global.php deleted file mode 100644 index df0707f69459ea0ce3af44279ca1d50f84514df6..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Acl/Global.php +++ /dev/null @@ -1,65 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API Global ACL model - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Model_Acl_Global -{ - /** - * Check if the operation is allowed on resources of given type type for given user type/role - * - * @param Mage_Api2_Model_Auth_User_Abstract $apiUser - * @param string $resourceType - * @param string $operation - * @return boolean - * @throws Mage_Api2_Exception - */ - public function isAllowed(Mage_Api2_Model_Auth_User_Abstract $apiUser, $resourceType, $operation) - { - // skip user without role, e.g. Customer - if (null === $apiUser->getRole()) { - return true; - } - /** @var $aclInstance Mage_Api2_Model_Acl */ - $aclInstance = Mage::getSingleton( - 'Mage_Api2_Model_Acl', - array('options' => array('resource_type' => $resourceType, 'operation' => $operation)) - ); - - if (!$aclInstance->hasRole($apiUser->getRole())) { - throw new Mage_Api2_Exception('Role not found', Mage_Api2_Model_Server::HTTP_UNAUTHORIZED); - } - if (!$aclInstance->has($resourceType)) { - throw new Mage_Api2_Exception('Resource not found', Mage_Api2_Model_Server::HTTP_NOT_FOUND); - } - return $aclInstance->isAllowed($apiUser->getRole(), $resourceType, $operation); - } -} diff --git a/app/code/core/Mage/Api2/Model/Acl/Global/Role.php b/app/code/core/Mage/Api2/Model/Acl/Global/Role.php deleted file mode 100644 index ec946683034ba1b8240d55c1f3f5976b50cc1a76..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Acl/Global/Role.php +++ /dev/null @@ -1,185 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 Global ACL Role model - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - * @method Mage_Api2_Model_Resource_Acl_Global_Role_Collection getCollection() - * @method Mage_Api2_Model_Resource_Acl_Global_Role_Collection getResourceCollection() - * @method Mage_Api2_Model_Resource_Acl_Global_Role getResource() - * @method Mage_Api2_Model_Resource_Acl_Global_Role _getResource() - * @method string getCreatedAt() - * @method Mage_Api2_Model_Acl_Global_Role setCreatedAt() setCreatedAt(string $createdAt) - * @method string getUpdatedAt() - * @method Mage_Api2_Model_Acl_Global_Role setUpdatedAt() setUpdatedAt(string $updatedAt) - * @method string getRoleName() - * @method Mage_Api2_Model_Acl_Global_Role setRoleName() setRoleName(string $roleName) - */ -class Mage_Api2_Model_Acl_Global_Role extends Mage_Core_Model_Abstract -{ - /**#@+ - * System roles identifiers - */ - const ROLE_GUEST_ID = 1; - const ROLE_CUSTOMER_ID = 2; - /**#@-*/ - - /**#@+ - * Config node identifiers - */ - const ROLE_CONFIG_NODE_NAME_GUEST = 'guest'; - const ROLE_CONFIG_NODE_NAME_CUSTOMER = 'customer'; - const ROLE_CONFIG_NODE_NAME_ADMIN = 'admin'; - /**#@-*/ - - /** - * Permissions model - * - * @var Mage_Api2_Model_Acl_Global_Rule_ResourcePermission - */ - protected $_permissionModel; - - /** - * Initialize resource model - * - * @return void - */ - protected function _construct() - { - $this->_init('Mage_Api2_Model_Resource_Acl_Global_Role'); - } - - /** - * Before save actions - * - * @return Mage_Api2_Model_Acl_Global_Role - */ - protected function _beforeSave() - { - if ($this->isObjectNew() && null === $this->getCreatedAt()) { - $this->setCreatedAt(Varien_Date::now()); - } else { - $this->setUpdatedAt(Varien_Date::now()); - } - - //check and protect guest role - if (Mage_Api2_Model_Acl_Global_Role::isSystemRole($this) - && $this->getRoleName() != $this->getOrigData('role_name')) { - - /** @var $helper Mage_Core_Helper_Data */ - $helper = Mage::helper('Mage_Core_Helper_Data'); - - Mage::throwException( - Mage::helper('Mage_Api2_Helper_Data')->__('%s role is a special one and can\'t be changed.', - $helper->escapeHtml($this->getRoleName())) - ); - } - - parent::_beforeSave(); - return $this; - } - - /** - * Perform checks before role delete - * - * @return Mage_Api2_Model_Acl_Global_Role - */ - protected function _beforeDelete() - { - if (Mage_Api2_Model_Acl_Global_Role::isSystemRole($this)) { - /** @var $helper Mage_Core_Helper_Data */ - $helper = Mage::helper('Mage_Core_Helper_Data'); - - Mage::throwException( - Mage::helper('Mage_Api2_Helper_Data')->__('%s role is a special one and can\'t be deleted.', - $helper->escapeHtml($this->getRoleName())) - ); - } - - parent::_beforeDelete(); - return $this; - } - - /** - * Get pairs resources-permissions for current role - * - * @return Mage_Api2_Model_Acl_Global_Rule_ResourcePermission - */ - public function getPermissionModel() - { - if (null == $this->_permissionModel) { - $this->_permissionModel = Mage::getModel('Mage_Api2_Model_Acl_Global_Rule_ResourcePermission'); - } - return $this->_permissionModel; - } - - /** - * Retrieve system roles - * - * @return array - */ - static public function getSystemRoles() - { - return array( - self::ROLE_GUEST_ID, - self::ROLE_CUSTOMER_ID - ); - } - - /** - * Get role system belonging - * - * @param Mage_Api2_Model_Acl_Global_Role $role - * @return bool - */ - public static function isSystemRole($role) - { - return in_array($role->getId(), self::getSystemRoles()); - } - - /** - * Get config node identifiers - * - * @return string - */ - public function getConfigNodeName() - { - switch ($this->getId()) { - case self::ROLE_GUEST_ID: - $roleNodeName = self::ROLE_CONFIG_NODE_NAME_GUEST; - break; - case self::ROLE_CUSTOMER_ID: - $roleNodeName = self::ROLE_CONFIG_NODE_NAME_CUSTOMER; - break; - default: - $roleNodeName = self::ROLE_CONFIG_NODE_NAME_ADMIN; - } - return $roleNodeName; - } -} diff --git a/app/code/core/Mage/Api2/Model/Acl/Global/Rule.php b/app/code/core/Mage/Api2/Model/Acl/Global/Rule.php deleted file mode 100644 index 0ac61f0011dcbb59b9c701430f14b6dd9bdea2c4..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Acl/Global/Rule.php +++ /dev/null @@ -1,65 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 Global ACL Rule model - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - * @method Mage_Api2_Model_Resource_Acl_Global_Rule_Collection getCollection() - * @method Mage_Api2_Model_Resource_Acl_Global_Rule_Collection getResourceCollection() - * @method Mage_Api2_Model_Resource_Acl_Global_Rule getResource() - * @method Mage_Api2_Model_Resource_Acl_Global_Rule _getResource() - * @method int getRoleId() - * @method Mage_Api2_Model_Acl_Global_Rule setRoleId() setRoleId(int $roleId) - * @method string getResourceId() - * @method Mage_Api2_Model_Acl_Global_Rule setResourceId() setResourceId(string $resource) - * @method string getPrivilege() - * @method int getPermission() - * @method Mage_Api2_Model_Acl_Global_Rule setPermission() setPermission(int $permission) - * @method string getPrivilege() - * @method Mage_Api2_Model_Acl_Global_Rule setPrivilege() setPrivilege(string $privilege) - * @method string getAllowedAttributes() - * @method Mage_Api2_Model_Acl_Global_Rule setAllowedAttributes() setAllowedAttributes(string $allowedAttributes) - */ -class Mage_Api2_Model_Acl_Global_Rule extends Mage_Core_Model_Abstract -{ - /** - * Root resource ID "all" - */ - const RESOURCE_ALL = 'all'; - - /** - * Initialize resource model - * - * @return void - */ - protected function _construct() - { - $this->_init('Mage_Api2_Model_Resource_Acl_Global_Rule'); - } -} diff --git a/app/code/core/Mage/Api2/Model/Acl/Global/Rule/Permission.php b/app/code/core/Mage/Api2/Model/Acl/Global/Rule/Permission.php deleted file mode 100644 index 9db9b595bed9f74aedc34d37225bbcc900f675f0..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Acl/Global/Rule/Permission.php +++ /dev/null @@ -1,74 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Permission source model - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Model_Acl_Global_Rule_Permission -{ - /**#@+ - * Source keys - */ - const TYPE_ALLOW = 1; - const TYPE_DENY = 0; - /**#@-*/ - - /** - * Get options parameters - * - * @return array - */ - static public function toOptionArray() - { - return array( - array( - 'value' => self::TYPE_DENY, - 'label' => Mage::helper('Mage_Api2_Helper_Data')->__('Deny') - ), - array( - 'value' => self::TYPE_ALLOW, - 'label' => Mage::helper('Mage_Api2_Helper_Data')->__('Allow') - ), - ); - } - - /** - * Get options in "key-value" format - * - * @return array - */ - static public function toArray() - { - return array( - self::TYPE_DENY => Mage::helper('Mage_Api2_Helper_Data')->__('Deny'), - self::TYPE_ALLOW => Mage::helper('Mage_Api2_Helper_Data')->__('Allow'), - ); - } -} diff --git a/app/code/core/Mage/Api2/Model/Acl/Global/Rule/Privilege.php b/app/code/core/Mage/Api2/Model/Acl/Global/Rule/Privilege.php deleted file mode 100644 index 4f5285a03c115b387c2ae374b3fd6c6ba934c3f4..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Acl/Global/Rule/Privilege.php +++ /dev/null @@ -1,77 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Privilege of rule source model - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Model_Acl_Global_Rule_Privilege -{ - /** - * Get options parameters - * - * @return array - */ - static public function toOptionArray() - { - return array( - array( - 'value' => Mage_Api2_Model_Resource::OPERATION_CREATE, - 'label' => Mage::helper('Mage_Api2_Helper_Data')->__('Create') - ), - array( - 'value' => Mage_Api2_Model_Resource::OPERATION_RETRIEVE, - 'label' => Mage::helper('Mage_Api2_Helper_Data')->__('Retrieve') - ), - array( - 'value' => Mage_Api2_Model_Resource::OPERATION_UPDATE, - 'label' => Mage::helper('Mage_Api2_Helper_Data')->__('Update') - ), - array( - 'value' => Mage_Api2_Model_Resource::OPERATION_DELETE, - 'label' => Mage::helper('Mage_Api2_Helper_Data')->__('Delete') - ) - ); - } - - /** - * Get options in "key-value" format - * - * @return array - */ - static public function toArray() - { - return array( - Mage_Api2_Model_Resource::OPERATION_CREATE => Mage::helper('Mage_Api2_Helper_Data')->__('Create'), - Mage_Api2_Model_Resource::OPERATION_RETRIEVE => Mage::helper('Mage_Api2_Helper_Data')->__('Retrieve'), - Mage_Api2_Model_Resource::OPERATION_UPDATE => Mage::helper('Mage_Api2_Helper_Data')->__('Update'), - Mage_Api2_Model_Resource::OPERATION_DELETE => Mage::helper('Mage_Api2_Helper_Data')->__('Delete') - ); - } -} diff --git a/app/code/core/Mage/Api2/Model/Acl/Global/Rule/ResourcePermission.php b/app/code/core/Mage/Api2/Model/Acl/Global/Rule/ResourcePermission.php deleted file mode 100644 index 2f9d865525ef5c9a925292de3cac67a0ef075495..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Acl/Global/Rule/ResourcePermission.php +++ /dev/null @@ -1,122 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 Global ACL role resources permissions model - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Model_Acl_Global_Rule_ResourcePermission - implements Mage_Api2_Model_Acl_PermissionInterface -{ - /** - * Resources permissions - * - * @var array - */ - protected $_resourcesPermissions; - - /** - * Role - * - * @var Mage_Api2_Model_Acl_Global_Role - */ - protected $_role; - - /** - * Get resources permissions for selected role - * - * @return array - */ - public function getResourcesPermissions() - { - if (null === $this->_resourcesPermissions) { - $roleConfigNodeName = $this->_role->getConfigNodeName(); - $rulesPairs = array(); - $allowedType = Mage_Api2_Model_Acl_Global_Rule_Permission::TYPE_ALLOW; - - if ($this->_role) { - /** @var $rules Mage_Api2_Model_Resource_Acl_Global_Rule_Collection */ - $rules = Mage::getResourceModel('Mage_Api2_Model_Resource_Acl_Global_Rule_Collection'); - $rules->addFilterByRoleId($this->_role->getId()); - - /** @var $rule Mage_Api2_Model_Acl_Global_Rule */ - foreach ($rules as $rule) { - $resourceId = $rule->getResourceId(); - $rulesPairs[$resourceId]['privileges'][$roleConfigNodeName][$rule->getPrivilege()] = $allowedType; - } - } else { - //make resource "all" as default for new item - $rulesPairs = array(Mage_Api2_Model_Acl_Global_Rule::RESOURCE_ALL => $allowedType); - } - - //set permissions to resources - /** @var $config Mage_Api2_Model_Config */ - $config = Mage::getModel('Mage_Api2_Model_Config'); - /** @var $privilegeSource Mage_Api2_Model_Acl_Global_Rule_Privilege */ - $privilegeSource = Mage::getModel('Mage_Api2_Model_Acl_Global_Rule_Privilege'); - $privileges = array_keys($privilegeSource->toArray()); - - /** @var $node Varien_Simplexml_Element */ - foreach ($config->getResources() as $resourceType => $node) { - $resourceId = (string)$resourceType; - $allowedRoles = (array)$node->privileges; - $allowedPrivileges = array(); - if (isset($allowedRoles[$roleConfigNodeName])) { - $allowedPrivileges = $allowedRoles[$roleConfigNodeName]; - } - foreach ($privileges as $privilege) { - if (empty($allowedPrivileges[$privilege]) - && isset($rulesPairs[$resourceId][$roleConfigNodeName]['privileges'][$privilege]) - ) { - unset($rulesPairs[$resourceId][$roleConfigNodeName]['privileges'][$privilege]); - } elseif (!empty($allowedPrivileges[$privilege]) - && !isset($rulesPairs[$resourceId][$roleConfigNodeName]['privileges'][$privilege]) - ) { - $deniedType = Mage_Api2_Model_Acl_Global_Rule_Permission::TYPE_DENY; - $rulesPairs[$resourceId]['privileges'][$roleConfigNodeName][$privilege] = $deniedType; - } - } - } - $this->_resourcesPermissions = $rulesPairs; - } - return $this->_resourcesPermissions; - } - - /** - * Set filter value - * - * @param Mage_Api2_Model_Acl_Global_Role $role - */ - public function setFilterValue($role) - { - if ($role && $role->getId()) { - $this->_role = $role; - } - } -} diff --git a/app/code/core/Mage/Api2/Model/Acl/Global/Rule/Tree.php b/app/code/core/Mage/Api2/Model/Acl/Global/Rule/Tree.php deleted file mode 100644 index 1104fe46690625c541a71d06ea0bd14f3a4f5d42..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Acl/Global/Rule/Tree.php +++ /dev/null @@ -1,547 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 acl global rule tree - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Model_Acl_Global_Rule_Tree extends Mage_Core_Helper_Abstract -{ - /**#@+ - * Tree types - */ - const TYPE_ATTRIBUTE = 'attribute'; - const TYPE_PRIVILEGE = 'privilege'; - /**#@-*/ - - /**#@+ - * Names - */ - const NAME_CHILDREN = 'children'; - const NAME_PRIVILEGE = 'privilege'; - const NAME_OPERATION = 'operation'; - const NAME_ATTRIBUTE = 'attribute'; - const NAME_RESOURCE = 'resource'; - const NAME_RESOURCE_GROUPS = 'resource_groups'; - const NAME_GROUP = 'group'; - /**#@-*/ - - /** - * Separator for tree ID - */ - const ID_SEPARATOR = '-'; - - /** - * Role - * - * @var Mage_Api2_Model_Acl_Global_Role - */ - protected $_role; - - /** - * Resources permissions - * - * @var array - */ - protected $_resourcesPermissions; - - /** - * Resources from config model - * - * @var Varien_Simplexml_Element - */ - protected $_resourcesConfig; - - /** - * Exist privileges - * - * @var array - */ - protected $_existPrivileges; - - /** - * Exist operations - * - * @var array - */ - protected $_existOperations; - - /** - * Tree type - * - * @var string - */ - protected $_type; - - /** - * Initialized - * - * @var bool - */ - protected $_initialized = false; - - /** - * Flag if resource has entity only attributes - * - * @var bool - */ - protected $_hasEntityOnlyAttributes = false; - - /** - * Constructor - * - * In the constructor should be set tree type: attributes or privileges. - * Attributes for tree with resources, operations and attributes. - * Privileges for tree with resources and privileges. - * - * @param array $options - * @throws Exception - */ - public function __construct($options = array()) - { - $this->_type = $options['type']; - - switch ($this->_type) { - case self::TYPE_ATTRIBUTE: - /** @var $operationSource Mage_Api2_Model_Acl_Filter_Attribute_Operation */ - $operationSource = Mage::getModel('Mage_Api2_Model_Acl_Filter_Attribute_Operation'); - $this->_existOperations = $operationSource->toArray(); - break; - - case self::TYPE_PRIVILEGE: - /** @var $privilegeSource Mage_Api2_Model_Acl_Global_Rule_Privilege */ - $privilegeSource = Mage::getModel('Mage_Api2_Model_Acl_Global_Rule_Privilege'); - $this->_existPrivileges = $privilegeSource->toArray(); - break; - - default: - throw new Exception(sprintf('Unknown tree type "%s".', $this->_type)); - break; - } - } - - /** - * Initialize block - * - * @return Mage_Api2_Model_Acl_Global_Rule_Tree - * @throws Exception - */ - protected function _init() - { - if ($this->_initialized) { - return $this; - } - - /** @var $config Mage_Api2_Model_Config */ - $config = Mage::getModel('Mage_Api2_Model_Config'); - $this->_resourcesConfig = $config->getResourceGroups(); - - if ($this->_type == self::TYPE_ATTRIBUTE && !$this->_existOperations) { - throw new Exception('Operations is not set'); - } - - if ($this->_type == self::TYPE_PRIVILEGE && !$this->_existPrivileges) { - throw new Exception('Privileges is not set.'); - } - - return $this; - } - - /** - * Convert to array serialized post data from tree grid - * - * @return array - */ - public function getPostResources() - { - $isAll = Mage::app()->getRequest()->getParam(Mage_Api2_Model_Acl_Global_Rule::RESOURCE_ALL); - $allow = Mage_Api2_Model_Acl_Global_Rule_Permission::TYPE_ALLOW; - if ($isAll) { - $resources = array( - Mage_Api2_Model_Acl_Global_Rule::RESOURCE_ALL => array( - null => $allow - ) - ); - } else { - $resources = array(); - $checkedResources = explode(',', Mage::app()->getRequest()->getParam('resource')); - $prefixResource = self::NAME_RESOURCE . self::ID_SEPARATOR; - switch ($this->_type) { - case self::TYPE_PRIVILEGE: - $prefixPrivilege = self::NAME_PRIVILEGE . self::ID_SEPARATOR; - $nameResource = null; - foreach ($checkedResources as $i => $item) { - if (0 === strpos($item, $prefixResource)) { - $nameResource = substr($item, mb_strlen($prefixResource, 'UTF-8')); - $resources[$nameResource] = array(); - } elseif (0 === strpos($item, $prefixPrivilege)) { - $name = substr($item, mb_strlen($prefixPrivilege, 'UTF-8')); - $namePrivilege = str_replace($nameResource . self::ID_SEPARATOR, '', $name); - $resources[$nameResource][$namePrivilege] = $allow; - } else { - unset($checkedResources[$i]); - } - } - break; - - case self::TYPE_ATTRIBUTE: - $prefixOperation = self::NAME_OPERATION . self::ID_SEPARATOR; - $prefixAttribute = self::NAME_ATTRIBUTE . self::ID_SEPARATOR; - $nameResource = null; - foreach ($checkedResources as $i => $item) { - if (0 === strpos($item, $prefixResource)) { - $nameResource = substr($item, mb_strlen($prefixResource, 'UTF-8')); - $resources[$nameResource] = array(); - } elseif (0 === strpos($item, $prefixOperation)) { - $name = substr($item, mb_strlen($prefixOperation, 'UTF-8')); - $operationName = str_replace($nameResource . self::ID_SEPARATOR, '', $name); - $resources[$nameResource][$operationName] = array(); - } elseif (0 === strpos($item, $prefixAttribute)) { - $name = substr($item, mb_strlen($prefixOperation, 'UTF-8')); - $attributeName = str_replace( - $nameResource . self::ID_SEPARATOR . $operationName . self::ID_SEPARATOR, - '', - $name - ); - $resources[$nameResource][$operationName][$attributeName] = $allow; - } else { - unset($checkedResources[$i]); - } - } - break; - - //no default - } - } - return $resources; - } - - /** - * Check if everything is allowed - * - * @return boolean - */ - public function getEverythingAllowed() - { - $this->_init(); - - $all = Mage_Api2_Model_Acl_Global_Rule::RESOURCE_ALL; - return !empty($this->_resourcesPermissions[$all]); - } - - /** - * Get tree resources - * - * @return array - */ - public function getTreeResources() - { - $this->_init(); - $root = $this->_getTreeNode($this->_resourcesConfig, 1); - return isset($root[self::NAME_CHILDREN]) ? $root[self::NAME_CHILDREN] : array(); - } - - /** - * Get tree node - * - * @param Varien_Simplexml_Element|array $node - * @param int $level - * @return array - */ - protected function _getTreeNode($node, $level = 0) - { - $item = array(); - - $isResource = false; - $isGroup = false; - $name = null; - - if ($level != 0) { - $name = $node->getName(); - if (!(int) $node->resource) { - if (self::NAME_RESOURCE_GROUPS != $name) { - $isGroup = true; - $item['id'] = self::NAME_GROUP . self::ID_SEPARATOR . $name; - } - $item['text'] = (string) $node->title; - } else { - $isResource = true; - $item['id'] = self::NAME_RESOURCE . self::ID_SEPARATOR . $name; - $item['text'] = $this->__('%s', (string) $node->title); - } - $item['checked'] = false; - $item['sort_order'] = isset($node->sort_order) ? (string) $node->sort_order : 0; - } - if (isset($node->children)) { - $children = $node->children->children(); - } else { - $children = $node->children(); - } - - if (empty($children)) { - /** - * Node doesn't have any child nodes - * and it should be skipped - */ - return $item; - } - - $item[self::NAME_CHILDREN] = array(); - - if ($isResource) { - if (self::TYPE_ATTRIBUTE == $this->_type) { - if (!$this->_addOperations($item, $node, $name)) { - return null; - } - } elseif (self::TYPE_PRIVILEGE == $this->_type) { - if (!$this->_addPrivileges($item, $node, $name)) { - return null; - } - } - } - - /** @var $child Varien_Simplexml_Element */ - foreach ($children as $child) { - if ($child->getName() != 'title' && $child->getName() != 'sort_order') { - if (!(string) $child->title) { - continue; - } - - if ($level != 0) { - $subNode = $this->_getTreeNode($child, $level + 1); - if (!$subNode) { - continue; - } - //if sub-node check then check current node - if (!empty($subNode['checked'])) { - $item['checked'] = true; - } - $item[self::NAME_CHILDREN][] = $subNode; - } else { - $item = $this->_getTreeNode($child, $level + 1); - } - } - } - if (!empty($item[self::NAME_CHILDREN])) { - usort($item[self::NAME_CHILDREN], array($this, '_sortTree')); - } elseif ($isGroup) { - //skip empty group - return null; - } - return $item; - } - - /** - * Add privileges - * - * @param array $item Tree node - * @param Varien_Simplexml_Element $node XML node - * @param string $name Resource name - * @return bool - */ - protected function _addPrivileges(&$item, Varien_Simplexml_Element $node, $name) - { - $roleConfigNodeName = $this->getRole()->getConfigNodeName(); - $possibleList = array(); - if (isset($node->privileges)) { - $possibleRoles = $node->privileges->asArray(); - if (isset($possibleRoles[$roleConfigNodeName])) { - $possibleList = $possibleRoles[$roleConfigNodeName]; - } - } - - if (!$possibleList) { - return false; - } - - $cnt = 0; - foreach ($this->_existPrivileges as $key => $title) { - if (empty($possibleList[$key])) { - continue; - } - $checked = !empty($this->_resourcesPermissions[$name]['privileges'][$roleConfigNodeName][$key]); - $item['checked'] = $checked ? $checked : $item['checked']; - $subItem = array( - 'id' => self::NAME_PRIVILEGE . self::ID_SEPARATOR . $name . self::ID_SEPARATOR . $key, - 'text' => $title, - 'checked' => $checked, - 'sort_order' => ++$cnt, - ); - $item[self::NAME_CHILDREN][] = $subItem; - } - return true; - } - - /** - * Add operation - * - * @param array $item Tree node - * @param Varien_Simplexml_Element $node XML node - * @param string $name Resource name - * @return bool - */ - protected function _addOperations(&$item, Varien_Simplexml_Element $node, $name) - { - $cnt = 0; - foreach ($this->_existOperations as $key => $title) { - $subItem = array( - 'id' => self::NAME_OPERATION . self::ID_SEPARATOR . $name . self::ID_SEPARATOR . $key, - 'text' => $title, - 'checked' => false, - 'sort_order' => ++$cnt, - ); - - if (!empty($this->_resourcesPermissions[$name]['operations'][$key]['attributes'])) { - if (!$this->_addAttribute($subItem, $node, $name, $key)) { - $cnt--; - continue; - } - } else { - $cnt--; - continue; - } - if (!empty($subItem['checked'])) { - $item['checked'] = true; - } - $item[self::NAME_CHILDREN][] = $subItem; - } - if (!$cnt) { - return false; - } - return true; - } - - /** - * Add privileges - * - * @param array $item Tree node - * @param Varien_Simplexml_Element $node XML node - * @param string $name Node name - * @param string $privilege Privilege name - * @return bool - */ - protected function _addAttribute(&$item, Varien_Simplexml_Element $node, $name, $privilege) - { - $cnt = 0; - foreach ($this->_resourcesPermissions[$name]['operations'][$privilege]['attributes'] as $key => $attribute) { - $title = $attribute['title']; - $status = $attribute['status']; - - $checked = $status == Mage_Api2_Model_Acl_Global_Rule_Permission::TYPE_ALLOW; - $item['checked'] = $checked ? $checked : $item['checked']; - $item[self::NAME_CHILDREN][] = array( - 'id' => self::NAME_ATTRIBUTE . self::ID_SEPARATOR . $name . self::ID_SEPARATOR . $privilege - . self::ID_SEPARATOR . $key, - 'text' => $title, - 'checked' => $checked, - 'sort_order' => ++$cnt, - ); - } - - return true; - } - - /** - * Compare two nodes of the Resource Tree - * - * @param array $a - * @param array $b - * @return int - */ - protected function _sortTree($a, $b) - { - return $a['sort_order'] < $b['sort_order'] ? -1 : ($a['sort_order'] > $b['sort_order'] ? 1 : 0); - } - - /** - * Set role - * - * @param Mage_Api2_Model_Acl_Global_Role $role - * @return Mage_Api2_Model_Acl_Global_Rule_Tree - */ - public function setRole($role) - { - $this->_role = $role; - return $this; - } - - /** - * Get role - * - * @return Mage_Api2_Model_Acl_Global_Role - */ - public function getRole() - { - return $this->_role; - } - - /** - * Set resources permissions - * - * @param array $resourcesPermissions - * @return Mage_Api2_Model_Acl_Global_Rule_Tree - */ - public function setResourcesPermissions($resourcesPermissions) - { - $this->_resourcesPermissions = $resourcesPermissions; - return $this; - } - - /** - * Get resources permissions - * - * @return array - */ - public function getResourcesPermissions() - { - return $this->_resourcesPermissions; - } - - /** - * Set has entity only attributes flag - * - * @param bool $hasEntityOnlyAttributes - * @return Mage_Api2_Model_Acl_Global_Rule_Tree - */ - public function setHasEntityOnlyAttributes($hasEntityOnlyAttributes) - { - $this->_hasEntityOnlyAttributes = $hasEntityOnlyAttributes; - return $this; - } - - /** - * Get has entity only attributes flag - * - * @return bool - */ - public function getHasEntityOnlyAttributes() - { - return $this->_hasEntityOnlyAttributes; - } -} diff --git a/app/code/core/Mage/Api2/Model/Acl/PermissionInterface.php b/app/code/core/Mage/Api2/Model/Acl/PermissionInterface.php deleted file mode 100644 index 09bf0292eaa2dc27e2b48757dd49fd89d5fe7fca..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Acl/PermissionInterface.php +++ /dev/null @@ -1,52 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 ACL resource permission interface - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -interface Mage_Api2_Model_Acl_PermissionInterface -{ - /** - * Get ACL resources permissions - * - * Get permissions list with set permissions - * - * @return array - */ - public function getResourcesPermissions(); - - /** - * Set filter value - * - * @param mixed $filterValue - * @return Mage_Api2_Model_Acl_PermissionInterface - */ - public function setFilterValue($filterValue); -} diff --git a/app/code/core/Mage/Api2/Model/Auth.php b/app/code/core/Mage/Api2/Model/Auth.php deleted file mode 100644 index a7e30175d12ecd0f72415a477f5f226c9630c072..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Auth.php +++ /dev/null @@ -1,80 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API User authentication model - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Model_Auth -{ - /** - * Use this type if no authentication adapter is applied - */ - const DEFAULT_USER_TYPE = 'guest'; - - /** - * Figure out API user type and create user model instance - * - * @param Mage_Api2_Model_Request $request - * @throws Exception - * @return Mage_Api2_Model_Auth_User_Abstract - */ - public function authenticate(Mage_Api2_Model_Request $request) - { - /** @var $helper Mage_Api2_Helper_Data */ - $helper = Mage::helper('Mage_Api2_Helper_Data'); - $userTypes = $helper->getUserTypes(); - - if (!$userTypes) { - throw new Exception('No allowed user types found'); - } - /** @var $authAdapter Mage_Api2_Model_Auth_Adapter */ - $authAdapter = Mage::getModel('Mage_Api2_Model_Auth_Adapter'); - $userParamsObj = $authAdapter->getUserParams($request); - - if (!isset($userTypes[$userParamsObj->type])) { - throw new Mage_Api2_Exception( - 'Invalid user type or type is not allowed', Mage_Api2_Model_Server::HTTP_UNAUTHORIZED - ); - } - /** @var $userModel Mage_Api2_Model_Auth_User_Abstract */ - $userModel = Mage::getModel($userTypes[$userParamsObj->type]); - - if (!$userModel instanceof Mage_Api2_Model_Auth_User_Abstract) { - throw new Exception('User model must to extend Mage_Api2_Model_Auth_User_Abstract'); - } - // check user type consistency - if ($userModel->getType() != $userParamsObj->type) { - throw new Exception('User model type does not match appropriate type in config'); - } - $userModel->setUserId($userParamsObj->id); - - return $userModel; - } -} diff --git a/app/code/core/Mage/Api2/Model/Auth/Adapter.php b/app/code/core/Mage/Api2/Model/Auth/Adapter.php deleted file mode 100644 index 749536a423936efe8b30db3506b66146623c8022..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Auth/Adapter.php +++ /dev/null @@ -1,93 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API Auth Adapter class - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Model_Auth_Adapter -{ - /** - * Adapter models - * - * @var array - */ - protected $_adapters = array(); - - /** - * Load adapters configuration and create adapters models - * - * @return Mage_Api2_Model_Auth_Adapter - * @throws Exception - */ - protected function _initAdapters() - { - /** @var $helper Mage_Api2_Helper_Data */ - $helper = Mage::helper('Mage_Api2_Helper_Data'); - - foreach ($helper->getAuthAdapters(true) as $adapterKey => $adapterParams) { - $adapterModel = Mage::getModel($adapterParams['model']); - - if (!$adapterModel instanceof Mage_Api2_Model_Auth_Adapter_Abstract) { - throw new Exception('Authentication adapter must to extend Mage_Api2_Model_Auth_Adapter_Abstract'); - } - $this->_adapters[$adapterKey] = $adapterModel; - } - if (!$this->_adapters) { - throw new Exception('No active authentication adapters found'); - } - return $this; - } - - /** - * Process request and figure out an API user type and its identifier - * - * Returns stdClass object with two properties: type and id - * - * @param Mage_Api2_Model_Request $request - * @return stdClass - */ - public function getUserParams(Mage_Api2_Model_Request $request) - { - $this->_initAdapters(); - - foreach ($this->_adapters as $adapterModel) { - /** @var $adapterModel Mage_Api2_Model_Auth_Adapter_Abstract */ - if ($adapterModel->isApplicableToRequest($request)) { - $userParams = $adapterModel->getUserParams($request); - - if (null !== $userParams->type) { - return $userParams; - } - throw new Mage_Api2_Exception('Can not determine user type', Mage_Api2_Model_Server::HTTP_UNAUTHORIZED); - } - } - return (object) array('type' => Mage_Api2_Model_Auth::DEFAULT_USER_TYPE, 'id' => null); - } -} diff --git a/app/code/core/Mage/Api2/Model/Auth/Adapter/Abstract.php b/app/code/core/Mage/Api2/Model/Auth/Adapter/Abstract.php deleted file mode 100644 index 236fd36c01f16e525172567b57fd57af474db1bf..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Auth/Adapter/Abstract.php +++ /dev/null @@ -1,53 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Abstract class of authentication adapter - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -abstract class Mage_Api2_Model_Auth_Adapter_Abstract -{ - /** - * Process request and figure out an API user type and its identifier - * - * Returns stdClass object with two properties: type and id - * - * @param Mage_Api2_Model_Request $request - * @return stdClass - */ - abstract public function getUserParams(Mage_Api2_Model_Request $request); - - /** - * Check if request contains authentication info for adapter - * - * @param Mage_Api2_Model_Request $request - * @return boolean - */ - abstract public function isApplicableToRequest(Mage_Api2_Model_Request $request); -} diff --git a/app/code/core/Mage/Api2/Model/Auth/Adapter/Oauth.php b/app/code/core/Mage/Api2/Model/Auth/Adapter/Oauth.php deleted file mode 100644 index 8ae8e9c1bd741526be6a2374438227cf4085fb87..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Auth/Adapter/Oauth.php +++ /dev/null @@ -1,78 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * oAuth Authentication adapter - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Model_Auth_Adapter_Oauth extends Mage_Api2_Model_Auth_Adapter_Abstract -{ - /** - * Process request and figure out an API user type and its identifier - * - * Returns stdClass object with two properties: type and id - * - * @param Mage_Api2_Model_Request $request - * @return stdClass - */ - public function getUserParams(Mage_Api2_Model_Request $request) - { - /** @var $oauthServer Mage_Oauth_Model_Server */ - $oauthServer = Mage::getModel('Mage_Oauth_Model_Server', array('request' => $request)); - $userParamsObj = (object) array('type' => null, 'id' => null); - - try { - $token = $oauthServer->checkAccessRequest(); - $userType = $token->getUserType(); - - if (Mage_Oauth_Model_Token::USER_TYPE_ADMIN == $userType) { - $userParamsObj->id = $token->getAdminId(); - } else { - $userParamsObj->id = $token->getCustomerId(); - } - $userParamsObj->type = $userType; - } catch (Exception $e) { - throw new Mage_Api2_Exception($oauthServer->reportProblem($e), Mage_Api2_Model_Server::HTTP_UNAUTHORIZED); - } - return $userParamsObj; - } - - /** - * Check if request contains authentication info for adapter - * - * @param Mage_Api2_Model_Request $request - * @return boolean - */ - public function isApplicableToRequest(Mage_Api2_Model_Request $request) - { - $headerValue = $request->getHeader('Authorization'); - - return $headerValue && 'oauth' === strtolower(substr($headerValue, 0, 5)); - } -} diff --git a/app/code/core/Mage/Api2/Model/Auth/User.php b/app/code/core/Mage/Api2/Model/Auth/User.php deleted file mode 100644 index 03d9047d3132b89bbf7e10370ea40e17cb13e84b..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Auth/User.php +++ /dev/null @@ -1,61 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API auth user - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Model_Auth_User -{ - /** - * Get options in "key-value" format - * - * @param boolean $asOptionArray OPTIONAL If TRUE - return an options array, plain array - otherwise - * @return array - */ - static public function getUserTypes($asOptionArray = false) - { - $userTypes = array(); - - /** @var $helper Mage_Api2_Helper_Data */ - $helper = Mage::helper('Mage_Api2_Helper_Data'); - - foreach ($helper->getUserTypes() as $modelPath) { - /** @var $userModel Mage_Api2_Model_Auth_User_Abstract */ - $userModel = Mage::getModel($modelPath); - - if ($asOptionArray) { - $userTypes[] = array('value' => $userModel->getType(), 'label' => $userModel->getLabel()); - } else { - $userTypes[$userModel->getType()] = $userModel->getLabel(); - } - } - return $userTypes; - } -} diff --git a/app/code/core/Mage/Api2/Model/Auth/User/Abstract.php b/app/code/core/Mage/Api2/Model/Auth/User/Abstract.php deleted file mode 100644 index 5354cd3a9faa142223f040ab990c5ec8e4dd78b6..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Auth/User/Abstract.php +++ /dev/null @@ -1,96 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 User Abstract Class - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -abstract class Mage_Api2_Model_Auth_User_Abstract -{ - /** - * Customer/Admin identifier - * - * @var int - */ - protected $_userId; - - /** - * User Role - * - * @var int - */ - protected $_role; - - /** - * Retrieve user human-readable label - * - * @return string - */ - public function getLabel() - { - return $this->getType(); - } - - /** - * Retrieve user role - * - * @return int - */ - abstract public function getRole(); - - /** - * Retrieve user type - * - * @return string - */ - abstract public function getType(); - - /** - * Retrieve user identifier - * - * @return int - */ - public function getUserId() - { - return $this->_userId; - } - - /** - * Set user identifier - * - * @param int $userId User identifier - * @return Mage_Api2_Model_Auth_User_Abstract - */ - public function setUserId($userId) - { - $this->_userId = $userId; - - return $this; - } -} diff --git a/app/code/core/Mage/Api2/Model/Auth/User/Admin.php b/app/code/core/Mage/Api2/Model/Auth/User/Admin.php deleted file mode 100644 index 9d586f89c48db163eefd1f39da2e49d4bcc2372b..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Auth/User/Admin.php +++ /dev/null @@ -1,106 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 User Admin Class - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Model_Auth_User_Admin extends Mage_Api2_Model_Auth_User_Abstract -{ - /** - * User type - */ - const USER_TYPE = 'admin'; - - /** - * Retrieve user human-readable label - * - * @return string - */ - public function getLabel() - { - return Mage::helper('Mage_Api2_Helper_Data')->__('Admin'); - } - - /** - * Retrieve user role - * - * @return int - * @throws Exception - */ - public function getRole() - { - if (!$this->_role) { - if (!$this->getUserId()) { - throw new Exception('Admin identifier is not set'); - } - - /** @var $collection Mage_Api2_Model_Resource_Acl_Global_Role_Collection */ - $collection = Mage::getModel('Mage_Api2_Model_Acl_Global_Role')->getCollection(); - $collection->addFilterByAdminId($this->getUserId()); - - /** @var $role Mage_Api2_Model_Acl_Global_Role */ - $role = $collection->getFirstItem(); - if (!$role->getId()) { - throw new Exception('Admin role not found'); - } - - $this->setRole($role->getId()); - } - - return $this->_role; - } - - /** - * Retrieve user type - * - * @return string - */ - public function getType() - { - return self::USER_TYPE; - } - - /** - * Set user role - * - * @param int $role - * @return Mage_Api2_Model_Auth_User_Admin - * @throws Exception - */ - public function setRole($role) - { - if ($this->_role) { - throw new Exception('Admin role has been already set'); - } - $this->_role = $role; - - return $this; - } -} diff --git a/app/code/core/Mage/Api2/Model/Auth/User/Customer.php b/app/code/core/Mage/Api2/Model/Auth/User/Customer.php deleted file mode 100644 index 9966bf83110c1d0c785e685a81989265e348eb90..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Auth/User/Customer.php +++ /dev/null @@ -1,80 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 User Customer Class - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Model_Auth_User_Customer extends Mage_Api2_Model_Auth_User_Abstract -{ - /** - * User type - */ - const USER_TYPE = 'customer'; - - /** - * Retrieve user human-readable label - * - * @return string - */ - public function getLabel() - { - return Mage::helper('Mage_Api2_Helper_Data')->__('Customer'); - } - - /** - * Retrieve user type - * - * @return string - */ - public function getType() - { - return self::USER_TYPE; - } - - /** - * Retrieve user role - * - * @return int - */ - public function getRole() - { - if (!$this->_role) { - /** @var $role Mage_Api2_Model_Acl_Global_Role */ - $role = Mage::getModel('Mage_Api2_Model_Acl_Global_Role')->load(Mage_Api2_Model_Acl_Global_Role::ROLE_CUSTOMER_ID); - if (!$role->getId()) { - throw new Exception('Customer role not found'); - } - - $this->_role = Mage_Api2_Model_Acl_Global_Role::ROLE_CUSTOMER_ID; - } - - return $this->_role; - } -} diff --git a/app/code/core/Mage/Api2/Model/Auth/User/Guest.php b/app/code/core/Mage/Api2/Model/Auth/User/Guest.php deleted file mode 100644 index 91a3ff1e7b6cc1f84c7a0cb0e25727c81a800c8f..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Auth/User/Guest.php +++ /dev/null @@ -1,80 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 User Guest Class - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Model_Auth_User_Guest extends Mage_Api2_Model_Auth_User_Abstract -{ - /** - * User type - */ - const USER_TYPE = 'guest'; - - /** - * Retrieve user human-readable label - * - * @return string - */ - public function getLabel() - { - return Mage::helper('Mage_Api2_Helper_Data')->__('Guest'); - } - - /** - * Retrieve user type - * - * @return string - */ - public function getType() - { - return self::USER_TYPE; - } - - /** - * Retrieve user role - * - * @return int - */ - public function getRole() - { - if (!$this->_role) { - /** @var $role Mage_Api2_Model_Acl_Global_Role */ - $role = Mage::getModel('Mage_Api2_Model_Acl_Global_Role')->load(Mage_Api2_Model_Acl_Global_Role::ROLE_GUEST_ID); - if (!$role->getId()) { - throw new Exception('Guest role not found'); - } - - $this->_role = Mage_Api2_Model_Acl_Global_Role::ROLE_GUEST_ID; - } - - return $this->_role; - } -} diff --git a/app/code/core/Mage/Api2/Model/Config.php b/app/code/core/Mage/Api2/Model/Config.php deleted file mode 100644 index b70150395b7e150a196892e0a06c381255971655..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Config.php +++ /dev/null @@ -1,449 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Webservice api2 config model - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Model_Config extends Varien_Simplexml_Config -{ - /** - * Node name of resource groups - */ - const NODE_RESOURCE_GROUPS = 'resource_groups'; - - /** - * Id for config cache - */ - const CACHE_ID = 'config_api2'; - - /** - * Tag name for config cache - */ - const CACHE_TAG = 'CONFIG_API2'; - - /** - * Is resources added to group - * - * @var boolean - */ - protected $_resourcesGrouped = false; - - /** - * Constructor - * Initializes XML for this configuration - * Local cache configuration - * - * @param string|Varien_Simplexml_Element|null $sourceData - */ - public function __construct($sourceData = null) - { - parent::__construct($sourceData); - - $canUserCache = Mage::app()->useCache('config'); - if ($canUserCache) { - $this->setCacheId(self::CACHE_ID) - ->setCacheTags(array(self::CACHE_TAG)) - ->setCacheChecksum(null) - ->setCache(Mage::app()->getCache()); - - if ($this->loadCache()) { - return; - } - } - - // Load data of config files api2.xml - $config = Mage::getConfig()->loadModulesConfiguration('api2.xml'); - $this->setXml($config->getNode('api2')); - - if ($canUserCache) { - $this->saveCache(); - } - } - - /** - * Fetch all routes of the given api type from config files api2.xml - * - * @param string $apiType - * @throws Mage_Api2_Exception - * @return array - */ - public function getRoutes($apiType) - { - /** @var $helper Mage_Api2_Helper_Data */ - $helper = Mage::helper('Mage_Api2_Helper_Data'); - if (!$helper->isApiTypeSupported($apiType)) { - throw new Mage_Api2_Exception(sprintf('API type "%s" is not supported', $apiType), - Mage_Api2_Model_Server::HTTP_BAD_REQUEST); - } - - $routes = array(); - foreach ($this->getResources() as $resourceKey => $resource) { - if (!$resource->routes) { - continue; - } - - /** @var $routes Varien_Simplexml_Element */ - foreach ($resource->routes->children() as $route) { - $arguments = array( - Mage_Api2_Model_Route_Abstract::PARAM_ROUTE => (string)$route->route, - Mage_Api2_Model_Route_Abstract::PARAM_DEFAULTS => array( - 'model' => (string)$resource->model, - 'type' => (string)$resourceKey, - 'action_type' => (string)$route->action_type - ) - ); - - $routes[] = Mage::getModel('Mage_Api2_Model_Route_' . ucfirst($apiType), $arguments); - } - } - return $routes; - } - - /** - * Retrieve all resources from config files api2.xml - * - * @return Varien_Simplexml_Element - */ - public function getResources() - { - return $this->getNode('resources')->children(); - } - - /** - * Retrieve all resources types - * - * @return array - */ - public function getResourcesTypes() - { - $list = array(); - - foreach ($this->getResources() as $resourceType => $resourceCfg) { - $list[] = (string) $resourceType; - } - return $list; - } - - /** - * Retrieve all resource groups from config files api2.xml - * - * @return Varien_Simplexml_Element|boolean - */ - public function getResourceGroups() - { - $groups = $this->getXpath('//' . self::NODE_RESOURCE_GROUPS); - if (!$groups) { - return false; - } - - /** @var $groups Varien_Simplexml_Element */ - $groups = $groups[0]; - - if (!$this->_resourcesGrouped) { - /** @var $node Varien_Simplexml_Element */ - foreach ($this->getResources() as $node) { - $result = $node->xpath('group'); - if (!$result) { - continue; - } - $groupName = (string) $result[0]; - if ($groupName) { - $result = $groups->xpath('.//' . $groupName); - if (!$result) { - continue; - } - - /** @var $group Varien_Simplexml_Element */ - $group = $result[0]; - - if (!isset($group->children)) { - $children = new Varien_Simplexml_Element('<children />'); - } else { - $children = $group->children; - } - $node->resource = 1; - $children->appendChild($node); - $group->appendChild($children); - } - } - } - return $groups; - } - - /** - * Retrieve resource group from config files api2.xml - * - * @param string $name - * @return Mage_Core_Model_Config_Element|boolean - */ - public function getResourceGroup($name) - { - $group = $this->getResourceGroups()->xpath('.//' . $name); - if (!$group) { - return false; - } - return $group[0]; - } - - /** - * Retrieve resource by type (node) - * - * @param string $node - * @return Varien_Simplexml_Element|boolean - */ - public function getResource($node) - { - return $this->getNode('resources/' . $node); - } - - /** - * Retrieve resource attributes - * - * @param string $node - * @return array - */ - public function getResourceAttributes($node) - { - $attributes = $this->getNode('resources/' . $node . '/attributes'); - return $attributes ? $attributes->asCanonicalArray() : array(); - } - - /** - * Get excluded attributes of API resource - * - * @param string $resource - * @param string $userType - * @param string $operation - * @return array - */ - public function getResourceExcludedAttributes($resource, $userType, $operation) - { - $node = $this->getNode('resources/' . $resource . '/exclude_attributes/' . $userType . '/' . $operation); - $exclAttributes = array(); - - if ($node) { - foreach ($node->children() as $attribute => $status) { - if ((string) $status) { - $exclAttributes[] = $attribute; - } - } - } - return $exclAttributes; - } - - /** - * Get forced attributes of API resource - * - * @param string $resource - * @param string $userType - * @return array - */ - public function getResourceForcedAttributes($resource, $userType) - { - $node = $this->getNode('resources/' . $resource . '/force_attributes/' . $userType); - $forcedAttributes = array(); - - if ($node) { - foreach ($node->children() as $attribute => $status) { - if ((string) $status) { - $forcedAttributes[] = $attribute; - } - } - } - return $forcedAttributes; - } - - /** - * Get included attributes - * - * @param string $resource API resource ID - * @param string $userType API user type - * @param string $operationType Type of operation: one of Mage_Api2_Model_Resource::OPERATION_ATTRIBUTE_... constant - * @return array - */ - public function getResourceIncludedAttributes($resource, $userType, $operationType) - { - $node = $this->getNode('resources/' . $resource . '/include_attributes/' . $userType . '/' . $operationType); - $inclAttributes = array(); - - if ($node) { - foreach ($node->children() as $attribute => $status) { - if ((string) $status) { - $inclAttributes[] = $attribute; - } - } - } - return $inclAttributes; - } - - /** - * Get entity only attributes - * - * @param string $resource API resource ID - * @param string $userType API user type - * @param string $operationType Type of operation: one of Mage_Api2_Model_Resource::OPERATION_ATTRIBUTE_... constant - * @return array - */ - public function getResourceEntityOnlyAttributes($resource, $userType, $operationType) - { - $node = $this->getNode('resources/' . $resource . '/entity_only_attributes/' . $userType . '/' . - $operationType); - $entityOnlyAttributes = array(); - - if ($node) { - foreach ($node->children() as $attribute => $status) { - if ((string) $status) { - $entityOnlyAttributes[] = $attribute; - } - } - } - return $entityOnlyAttributes; - } - - /** - * Retrieve resource working model - * - * @param string $node - * @return string - */ - public function getResourceWorkingModel($node) - { - return (string)$this->getNode('resources/' . $node . '/working_model'); - } - - /** - * Get resource allowed versions sorted in reverse order - * - * @param string $node - * @return array - * @throws Exception - */ - public function getVersions($node) - { - $element = $this->getNode('resources/' . $node . '/versions'); - if (!$element) { - throw new Exception( - sprintf('Resource "%s" does not have node <versions> in config.', htmlspecialchars($node)) - ); - } - - $versions = explode(',', (string)$element); - if (count(array_filter($versions, 'is_numeric')) != count($versions)) { - throw new Exception(sprintf('Invalid resource "%s" versions in config.', htmlspecialchars($node))); - } - - rsort($versions, SORT_NUMERIC); - - return $versions; - } - - /** - * Retrieve resource model - * - * @param string $node - * @return string - */ - public function getResourceModel($node) - { - return (string)$this->getNode('resources/' . $node . '/model'); - } - - /** - * Retrieve API user privileges for specified resource - * - * @param string $resource - * @param string $userType - * @return array - */ - public function getResourceUserPrivileges($resource, $userType) - { - $attributes = $this->getNode('resources/' . $resource . '/privileges/' . $userType); - return $attributes ? $attributes->asCanonicalArray() : array(); - } - - /** - * Retrieve resource subresources - * - * @param string $node - * @return array - */ - public function getResourceSubresources($node) - { - $subresources = $this->getNode('resources/' . $node . '/subresources'); - return $subresources ? $subresources->asCanonicalArray() : array(); - } - - /** - * Get validation config by validator type - * - * @param string $resourceType - * @param string $validatorType - * @return array - */ - public function getValidationConfig($resourceType, $validatorType) - { - $config = $this->getNode('resources/' . $resourceType . '/validators/' . $validatorType); - return $config ? $config->asCanonicalArray() : array(); - } - - /** - * Get latest version of resource model. If second arg is specified - use it as a limiter - * - * @param string $resourceType Resource type - * @param int $lowerOrEqualsTo OPTIONAL If specified - return version equal or lower to - * @return int - */ - public function getResourceLastVersion($resourceType, $lowerOrEqualsTo = null) - { - $availVersions = $this->getVersions($resourceType); // already ordered in reverse order - $useVersion = reset($availVersions); - - if (null !== $lowerOrEqualsTo) { - foreach ($availVersions as $availVersion) { - if ($availVersion <= $lowerOrEqualsTo) { - $useVersion = $availVersion; - break; - } - } - } - return (int)$useVersion; - } - - /** - * Get route with Mage_Api2_Model_Resource::ACTION_TYPE_ENTITY type - * - * @param string $node - * @return string - */ - public function getRouteWithEntityTypeAction($node) - { - return (string)$this->getNode('resources/' . $node . '/routes/route_entity/route'); - } -} diff --git a/app/code/core/Mage/Api2/Model/Dispatcher.php b/app/code/core/Mage/Api2/Model/Dispatcher.php deleted file mode 100644 index 52934ae22c0a9c0a3aebcac51dabdd1ee50adde6..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Dispatcher.php +++ /dev/null @@ -1,162 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Webservice api2 dispatcher model - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Model_Dispatcher -{ - /** - * Template for retrieve resource class name - */ - const RESOURCE_CLASS_TEMPLATE = ':resource_:api_:user_v:version'; - - /** - * API User object - * - * @var Mage_Api2_Model_Auth_User_Abstract - */ - protected $_apiUser; - - /** - * Instantiate resource class, set parameters to the instance, run resource internal dispatch method - * - * @param Mage_Api2_Model_Request $request - * @param Mage_Api2_Model_Response $response - * @return Mage_Api2_Model_Dispatcher - * @throws Mage_Api2_Exception - */ - public function dispatch(Mage_Api2_Model_Request $request, Mage_Api2_Model_Response $response) - { - if (!$request->getModel() || !$request->getApiType()) { - throw new Mage_Api2_Exception( - 'Request does not contains all necessary data', Mage_Api2_Model_Server::HTTP_BAD_REQUEST - ); - } - $model = self::loadResourceModel( - $request->getModel(), - $request->getApiType(), - $this->getApiUser()->getType(), - $this->getVersion($request->getResourceType(), $request->getVersion()) - ); - - $model->setRequest($request); - $model->setResponse($response); - $model->setApiUser($this->getApiUser()); - - $model->dispatch(); - - return $this; - } - - /** - * Pack resource model class path from components and try to load it - * - * @param string $apiType API type - * @param string $userType API User type (e.g. admin, customer, guest) - * @param int $version Requested version - * @return Mage_Api2_Model_Resource - * @throws Mage_Api2_Exception - */ - public static function loadResourceModel($model, $apiType, $userType, $version) - { - $class = strtr( - self::RESOURCE_CLASS_TEMPLATE, - array(':resource' => $model, ':api' => $apiType, ':user' => $userType, ':version' => $version) - ); - - try { - /** @var $modelObj Mage_Api2_Model_Resource */ - $modelObj = Mage::getModel($class); - } catch (Exception $e) { - // getModel() throws exception when in application is in development mode - skip it to next check - } - if (empty($modelObj) || !$modelObj instanceof Mage_Api2_Model_Resource) { - throw new Mage_Api2_Exception('Resource not found', Mage_Api2_Model_Server::HTTP_NOT_FOUND); - } - return $modelObj; - } - - /** - * Set API user object - * - * @param Mage_Api2_Model_Auth_User_Abstract $apiUser - * @return Mage_Api2_Model_Dispatcher - */ - public function setApiUser(Mage_Api2_Model_Auth_User_Abstract $apiUser) - { - $this->_apiUser = $apiUser; - - return $this; - } - - /** - * Get API user object - * - * @return Mage_Api2_Model_Auth_User_Abstract - */ - public function getApiUser() - { - if (!$this->_apiUser) { - throw new Exception('API user is not set.'); - } - - return $this->_apiUser; - } - - /** - * Get correct version of the resource model - * - * @param string $resourceType - * @param string|bool $requestedVersion - * @return int - * @throws Mage_Api2_Exception - */ - public function getVersion($resourceType, $requestedVersion) - { - if (false !== $requestedVersion && !preg_match('/^[1-9]\d*$/', $requestedVersion)) { - throw new Mage_Api2_Exception( - sprintf('Invalid version "%s" requested.', htmlspecialchars($requestedVersion)), - Mage_Api2_Model_Server::HTTP_BAD_REQUEST - ); - } - return $this->getConfig()->getResourceLastVersion($resourceType, $requestedVersion); - } - - /** - * Get config - * - * @return Mage_Api2_Model_Config - */ - public function getConfig() - { - return Mage::getModel('Mage_Api2_Model_Config'); - } -} diff --git a/app/code/core/Mage/Api2/Model/Multicall.php b/app/code/core/Mage/Api2/Model/Multicall.php deleted file mode 100644 index 8a3d96f543d02acb0bd92e501ae789107a1f72ca..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Multicall.php +++ /dev/null @@ -1,278 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 model for multiple internal calls to subresources of specified resource - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Model_Multicall -{ - - /** - * @var Mage_Api2_Model_Request - */ - protected $_parentCallRequest; - - /** - * @var string - */ - protected $_parentResourceId; - - /** - * Multicall to subresources of specified resource - * - * @param string $parentResourceId - * @param string $parentResourceName - * @param Mage_Api2_Model_Request $parentCallRequest - * @return Mage_Api2_Model_Response - */ - public function call($parentResourceId, $parentResourceName, Mage_Api2_Model_Request $parentCallRequest) - { - $this->_parentResourceId = $parentResourceId; - $this->_parentCallRequest = $parentCallRequest; - $subresources = $this->_getDeclaredSubresources($parentResourceName); - foreach ($subresources as $subresource) { - $this->_callSubresource($subresource); - } - - return $this->_getResponse(); - } - - /** - * Make call to specified subresource with data from request - * - * @param Mage_Core_Model_Config_Element $subresource - * @return Mage_Api2_Model_Multicall - */ - protected function _callSubresource($subresource) - { - $bodyParams = $this->_getRequest()->getBodyParams(); - // check if subresource data exists in request - $requestParamName = (string)$subresource->request_param_name; - if (!(is_array($bodyParams) && array_key_exists($requestParamName, $bodyParams) - && is_array($bodyParams[$requestParamName])) - ) { - return $this; - } - // make internal call - $subresourceType = (string)$subresource->type; - $requestData = $bodyParams[$requestParamName]; - switch ($subresourceType) { - case 'collection': - foreach ($requestData as $subresourceData) { - $this->_internalCall($subresource, $subresourceData); - } - break; - case 'instance': - default: - $this->_internalCall($subresource, $requestData); - break; - } - return $this; - } - - /** - * Make internal call to specified subresource on with specified data via API2 server - * - * @param Mage_Core_Model_Config_Element $subresource - * @param array $requestData - * @throws Mage_Api2_Exception - * @return Mage_Api2_Model_Multicall - */ - protected function _internalCall($subresource, $requestData) - { - try { - if (!is_array($requestData)) { - throw new Mage_Api2_Exception('Invalid data format', Mage_Api2_Model_Server::HTTP_BAD_REQUEST); - } - $subresourceIdKey = (string)$subresource->id_param_name; - /** @var $server Mage_Api2_Model_Server */ - $server = Mage::getSingleton('Mage_Api2_Model_Server'); - - // create subresource item before linking it to main resource - if (!array_key_exists($subresourceIdKey, $requestData)) { - $subresourceCreateResourceName = (string)$subresource->create_resource_name; - $internalRequest = $this->_prepareRequest($subresourceCreateResourceName, $requestData); - /** @var $internalCreateResponse Mage_Api2_Model_Response */ - $internalCreateResponse = Mage::getModel('Mage_Api2_Model_Response'); - $server->internalCall($internalRequest, $internalCreateResponse); - $createdSubresourceInstanceId = $this->_getCreatedResourceId($internalCreateResponse); - if (empty($createdSubresourceInstanceId)) { - throw new Mage_Api2_Exception('Error during subresource creation', - Mage_Api2_Model_Server::HTTP_INTERNAL_ERROR); - } - $requestData[$subresourceIdKey] = $createdSubresourceInstanceId; - } - - // link subresource to main resource - $subresourceName = (string)$subresource->name; - $parentResourceIdFieldName = (string)$subresource->parent_resource_id_field_name; - $internalRequest = $this->_prepareRequest($subresourceName, $requestData, $parentResourceIdFieldName); - - /** @var $internalResponse Mage_Api2_Model_Response */ - $internalResponse = Mage::getModel('Mage_Api2_Model_Response'); - $server->internalCall($internalRequest, $internalResponse); - } catch (Exception $e) { - // TODO: implement strict mode - Mage::logException($e); - $this->_getResponse()->setException($e); - // TODO: Refactor partial success idintification process - $this->_getResponse()->setHttpResponseCode(Mage_Api2_Model_Server::HTTP_CREATED); - } - - if (isset($internalCreateResponse)) { - $this->_aggregateResponse($internalCreateResponse); - } - if (isset($internalResponse)) { - $this->_aggregateResponse($internalResponse); - } - - return $this; - } - - /** - * Prepare internal request - * - * @param string $subresourceName - * @param array $data - * @param string|null $parentResourceIdFieldName - * @return Mage_Api2_Model_Request_Internal - */ - protected function _prepareRequest($subresourceName, $data, $parentResourceIdFieldName = null) - { - $subresourceUri = $this->_createSubresourceUri($subresourceName, $parentResourceIdFieldName); - /** @var $internalRequest Mage_Api2_Model_Request_Internal */ - $internalRequest = Mage::getModel('Mage_Api2_Model_Request_Internal'); - $internalRequest->setRequestUri($subresourceUri); - $internalRequest->setBodyParams($data); - $internalRequest->setMethod('POST'); - return $internalRequest; - } - - /** - * Generate subresource uri - * - * @param string $subresourceName - * @param string $parentResourceIdFieldName - * @return string - */ - protected function _createSubresourceUri($subresourceName, $parentResourceIdFieldName = null) - { - /** @var $apiTypeRoute Mage_Api2_Model_Route_ApiType */ - $apiTypeRoute = Mage::getModel('Mage_Api2_Model_Route_ApiType'); - - $chain = $apiTypeRoute->chain( - new Zend_Controller_Router_Route($this->_getConfig()->getMainRoute($subresourceName)) - ); - $params = array(); - $params['api_type'] = 'rest'; - if (null !== $parentResourceIdFieldName) { - $params[$parentResourceIdFieldName] = $this->_parentResourceId; - } - $uri = $chain->assemble($params); - - return '/' . $uri; - } - - /** - * Retrieve list of subresources declared in configuration - * - * @param string $parentResourceName - * @return array - */ - protected function _getDeclaredSubresources($parentResourceName) - { - return $this->_getConfig()->getResourceSubresources($parentResourceName); - } - - /** - * Retrieve API2 config - * - * @return Mage_Api2_Model_Config - */ - protected function _getConfig() - { - return Mage::getSingleton('Mage_Api2_Model_Config'); - } - - /** - * Retrieve global response - * - * @return Mage_Api2_Model_Response - */ - protected function _getResponse() - { - return Mage::getSingleton('Mage_Api2_Model_Response'); - } - - /** - * Retrieve parent request - * - * @return Mage_Api2_Model_Request - */ - protected function _getRequest() - { - return $this->_parentCallRequest; - } - - /** - * Add internal call response to global response - * - * @param Mage_Api2_Model_Response $response - */ - protected function _aggregateResponse(Mage_Api2_Model_Response $response) - { - if ($response->isException()) { - $errors = $response->getException(); - // @TODO: add subresource prefix to error messages - foreach ($errors as $error) { - $this->_getResponse()->setException($error); - } - } - } - - /** - * Retrieve created resource id from response - * - * @param Mage_Api2_Model_Response $response - * @return string|int - */ - protected function _getCreatedResourceId($response) - { - $resourceId = 0; - $headers = $response->getHeaders(); - foreach ($headers as $header) { - if ($header['name'] == 'Location') { - list($resourceId) = array_reverse(explode('/', $header['value'])); - break; - } - } - return $resourceId; - } -} diff --git a/app/code/core/Mage/Api2/Model/Observer.php b/app/code/core/Mage/Api2/Model/Observer.php deleted file mode 100644 index 865d4dccaf5ea317f4f02b71d69f7574197c7894..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Observer.php +++ /dev/null @@ -1,86 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 observer - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Model_Observer -{ - /** - * Save relation of admin user to API2 role - * - * @param Varien_Event_Observer $observer - * @return void - */ - public function saveAdminToRoleRelation(Varien_Event_Observer $observer) - { - /** @var $user Mage_User_Model_User Object */ - $user = $observer->getObject(); - - if ($user->hasData('api2_roles')) { - $roles = $user->getData('api2_roles'); - - if (!is_array($roles) || !isset($roles[0])) { - throw new Exception('API2 roles property has wrong data format.'); - } - - /** @var $resourceModel Mage_Api2_Model_Resource_Acl_Global_Role */ - $resourceModel = Mage::getResourceModel('Mage_Api2_Model_Resource_Acl_Global_Role'); - $resourceModel->saveAdminToRoleRelation($user->getId(), $roles[0]); - } - } - - /** - * After save attribute if it is not visible on front remove it from Attribute ACL - * - * @param Varien_Event_Observer $observer - * @return Mage_Api2_Model_Observer - */ - public function catalogAttributeSaveAfter(Varien_Event_Observer $observer) - { - /** @var $attribute Mage_Catalog_Model_Resource_Eav_Attribute */ - $attribute = $observer->getEvent()->getAttribute(); - if ($attribute->getIsUserDefined() && $attribute->dataHasChangedFor('is_visible_on_front') - && !$attribute->getIsVisibleOnFront()) { - /** @var $collection Mage_Api2_Model_Resource_Acl_Filter_Attribute_Collection */ - $collection = Mage::getResourceModel('Mage_Api2_Model_Resource_Acl_Filter_Attribute_Collection'); - /** @var $aclFilter Mage_Api2_Model_Acl_Filter_Attribute */ - foreach ($collection as $aclFilter) { - if ($aclFilter->getResourceId() != Mage_Api2_Model_Acl_Global_Rule::RESOURCE_ALL) { - $allowedAttributes = explode(',', $aclFilter->getAllowedAttributes()); - $allowedAttributes = array_diff($allowedAttributes, array($attribute->getAttributeCode())); - $aclFilter->setAllowedAttributes(implode(',', $allowedAttributes))->save(); - } - } - } - - return $this; - } -} diff --git a/app/code/core/Mage/Api2/Model/Renderer.php b/app/code/core/Mage/Api2/Model/Renderer.php deleted file mode 100644 index 8892f2e1e03d983471f6a977ce6e6b9f09f6b5cd..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Renderer.php +++ /dev/null @@ -1,83 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Webservice API2 renderer factory model - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -abstract class Mage_Api2_Model_Renderer -{ - /** - * Get Renderer of given type - * - * @param array|string $acceptTypes - * @throws Mage_Api2_Exception - * @throws Exception - * @return Mage_Api2_Model_Renderer_Interface - */ - public static function factory($acceptTypes) - { - /** @var $helper Mage_Api2_Helper_Data */ - $helper = Mage::helper('Mage_Api2_Helper_Data'); - $adapters = $helper->getResponseRenderAdapters(); - - if (!is_array($acceptTypes)) { - $acceptTypes = array($acceptTypes); - } - - $type = null; - $adapterPath = null; - foreach ($acceptTypes as $type) { - foreach ($adapters as $item) { - $itemType = $item->type; - if ($type == $itemType - || $type == current(explode('/', $itemType)) . '/*' || $type == '*/*' - ) { - $adapterPath = $item->model; - break 2; - } - } - } - - //if server can't respond in any of accepted types it SHOULD send 406(not acceptable) - if (null === $adapterPath) { - throw new Mage_Api2_Exception( - 'Server can not understand Accept HTTP header media type.', - Mage_Api2_Model_Server::HTTP_NOT_ACCEPTABLE - ); - } - - $adapter = Mage::getModel($adapterPath); - if (!$adapter) { - throw new Exception(sprintf('Response renderer adapter for content type "%s" not found.', $type)); - } - - return $adapter; - } -} diff --git a/app/code/core/Mage/Api2/Model/Renderer/Interface.php b/app/code/core/Mage/Api2/Model/Renderer/Interface.php deleted file mode 100644 index 444e086f1e258ef04ce7becabd15dd10e5e688e4..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Renderer/Interface.php +++ /dev/null @@ -1,50 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Webservice API2 renderer adapter interface - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -interface Mage_Api2_Model_Renderer_Interface -{ - /** - * Render content in a certain format - * - * @param array|object $data - * @return string - */ - public function render($data); - - /** - * Get MIME type generated by renderer - * - * @return string - */ - public function getMimeType(); -} diff --git a/app/code/core/Mage/Api2/Model/Renderer/Query.php b/app/code/core/Mage/Api2/Model/Renderer/Query.php deleted file mode 100644 index 278820c93b85b0c5935a79dc9724319e43fa9e04..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Renderer/Query.php +++ /dev/null @@ -1,62 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Webservice API2 renderer of query format model - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Model_Renderer_Query implements Mage_Api2_Model_Renderer_Interface -{ - /** - * Adapter mime type - */ - const MIME_TYPE = 'text/plain'; - - /** - * Convert Array to URL-encoded query string - * - * @param array|object $data - * @return string - */ - public function render($data) - { - $query = http_build_query($data); - return $query; - } - - /** - * Get MIME type generated by renderer - * - * @return string - */ - public function getMimeType() - { - return self::MIME_TYPE; - } -} diff --git a/app/code/core/Mage/Api2/Model/Renderer/Xml.php b/app/code/core/Mage/Api2/Model/Renderer/Xml.php deleted file mode 100644 index 5cd665a23785e2c008274735607791b67eecbed9..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Renderer/Xml.php +++ /dev/null @@ -1,162 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Webservice API2 renderer of XML type model - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Model_Renderer_Xml implements Mage_Api2_Model_Renderer_Interface -{ - /** - * Adapter mime type - */ - const MIME_TYPE = 'application/xml'; - - /** - * Default name for item of non-associative array - */ - const ARRAY_NON_ASSOC_ITEM_NAME = 'data_item'; - - /** - * Chars for replacement in the tag name - * - * @var array - */ - protected $_replacementInTagName = array( - '!' => '', '"' => '', '#' => '', '$' => '', '%' => '', '&' => '', '\'' => '', - '(' => '', ')' => '', '*' => '', '+' => '', ',' => '', '/' => '', ';' => '', - '<' => '', '=' => '', '>' => '', '?' => '', '@' => '', '[' => '', '\\' => '', - ']' => '', '^' => '', '`' => '', '{' => '', '|' => '', '}' => '', '~' => '', - ' ' => '_', ':' => '_' - ); - - /** - * Chars for replacement in the tag value - * - * @var array - */ - protected $_replacementInTagValue = array( - '&' => '&' // replace "&" with HTML entity, because by default not replaced - ); - - /** - * Protected pattern for check chars in the begin of tag name - * - * @var string - */ - protected $_protectedTagNamePattern = '/^[0-9,.-]/'; - - /** - * Convert Array to XML - * - * @param mixed $data - * @return string - */ - public function render($data) - { - /* @var $writer Mage_Api2_Model_Renderer_Xml_Writer */ - $writer = Mage::getModel('Mage_Api2_Model_Renderer_Xml_Writer', array('options' => array( - 'config' => new Zend_Config($this->_prepareData($data, true)) - ))); - return $writer->render(); - } - - /** - * Prepare convert data - * - * @param array|Varien_Object $data - * @param bool $root - * @return array - * @throws Exception - */ - protected function _prepareData($data, $root = false) - { - if (!is_array($data) && !is_object($data)) { - if ($root) { - $data = array($data); - } else { - throw new Exception('Prepare data must be an object or an array.'); - } - } - $data = $data instanceof Varien_Object ? $data->toArray() : (array)$data; - $isAssoc = !preg_match('/^\d+$/', implode(array_keys($data), '')); - - $preparedData = array(); - foreach ($data as $key => $value) { - $value = is_array($value) || is_object($value) ? $this->_prepareData($value) : $this->_prepareValue($value); - if ($isAssoc) { - $preparedData[$this->_prepareKey($key)] = $value; - } else { - $preparedData[self::ARRAY_NON_ASSOC_ITEM_NAME][] = $value; - } - } - return $preparedData; - } - - /** - * Prepare value - * - * @param string $value - * @return string - */ - protected function _prepareValue($value) - { - return str_replace( - array_keys($this->_replacementInTagValue), - array_values($this->_replacementInTagValue), - $value - ); - } - - /** - * Prepare key and replace unavailable chars - * - * @param string $key - * @return string - */ - protected function _prepareKey($key) - { - $key = str_replace(array_keys($this->_replacementInTagName), array_values($this->_replacementInTagName), $key); - $key = trim($key, '_'); - if (preg_match($this->_protectedTagNamePattern, $key)) { - $key = self::ARRAY_NON_ASSOC_ITEM_NAME . '_' . $key; - } - return $key; - } - - /** - * Get MIME type generated by renderer - * - * @return string - */ - public function getMimeType() - { - return self::MIME_TYPE; - } -} diff --git a/app/code/core/Mage/Api2/Model/Renderer/Xml/Writer.php b/app/code/core/Mage/Api2/Model/Renderer/Xml/Writer.php deleted file mode 100644 index 1bb13266b1534da12d8dc0f0bf22da15d1d01539..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Renderer/Xml/Writer.php +++ /dev/null @@ -1,80 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API XML Renderer Writer - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Model_Renderer_Xml_Writer extends Zend_Config_Writer_Xml -{ - /** - * Root node in XML output - */ - const XML_ROOT_NODE = 'magento_api'; - - /** - * Render a Zend_Config into a XML config string. - * OVERRIDE to avoid using zend-config string in XML - * - * @return string - */ - public function render() - { - $xml = new SimpleXMLElement('<' . self::XML_ROOT_NODE . '/>'); - $extends = $this->_config->getExtends(); - $sectionName = $this->_config->getSectionName(); - - if (is_string($sectionName)) { - $child = $xml->addChild($sectionName); - - $this->_addBranch($this->_config, $child, $xml); - } else { - foreach ($this->_config as $sectionName => $data) { - if (!($data instanceof Zend_Config)) { - $xml->addChild($sectionName, (string) $data); - } else { - $child = $xml->addChild($sectionName); - - if (isset($extends[$sectionName])) { - $child->addAttribute('zf:extends', $extends[$sectionName], Zend_Config_Xml::XML_NAMESPACE); - } - - $this->_addBranch($data, $child, $xml); - } - } - } - - $dom = dom_import_simplexml($xml)->ownerDocument; - $dom->formatOutput = true; - - $xmlString = $dom->saveXML(); - - return $xmlString; - } -} diff --git a/app/code/core/Mage/Api2/Model/Request.php b/app/code/core/Mage/Api2/Model/Request.php deleted file mode 100644 index e3a8bc41086b5fec1da3ae1cb278d522387c27b3..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Request.php +++ /dev/null @@ -1,325 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API Request model - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Model_Request extends Zend_Controller_Request_Http -{ - /** - * Character set which must be used in request - */ - const REQUEST_CHARSET = 'utf-8'; - - /**#@+ - * Name of query ($_GET) parameters to use in navigation and so on - */ - const QUERY_PARAM_REQ_ATTRS = 'attrs'; - const QUERY_PARAM_PAGE_NUM = 'page'; - const QUERY_PARAM_PAGE_SIZE = 'limit'; - const QUERY_PARAM_ORDER_FIELD = 'order'; - const QUERY_PARAM_ORDER_DIR = 'dir'; - const QUERY_PARAM_FILTER = 'filter'; - /**#@- */ - - /** - * Interpreter adapter - * - * @var Mage_Api2_Model_Request_Interpreter_Interface - */ - protected $_interpreter; - - /** - * Body params - * - * @var array - */ - protected $_bodyParams; - - /** - * Constructor - * - * If a $uri is passed, the object will attempt to populate itself using - * that information. - * Override parent class to allow object instance get via Mage::getSingleton() - * - * @param string|Zend_Uri $uri - */ - public function __construct($uri = null) - { - parent::__construct($uri ? $uri : null); - } - - /** - * Get request interpreter - * - * @return Mage_Api2_Model_Request_Interpreter_Interface - */ - protected function _getInterpreter() - { - if (null === $this->_interpreter) { - $this->_interpreter = Mage_Api2_Model_Request_Interpreter::factory($this->getContentType()); - } - return $this->_interpreter; - } - - /** - * Retrieve accept types understandable by requester in a form of array sorted by quality descending - * - * @return array - */ - public function getAcceptTypes() - { - $qualityToTypes = array(); - $orderedTypes = array(); - - foreach (preg_split('/,\s*/', $this->getHeader('Accept')) as $definition) { - $typeWithQ = explode(';', $definition); - $mimeType = trim(array_shift($typeWithQ)); - - // check MIME type validity - if (!preg_match('~^([0-9a-z*+\-]+)(?:/([0-9a-z*+\-\.]+))?$~i', $mimeType)) { - continue; - } - $quality = '1.0'; // default value for quality - - if ($typeWithQ) { - $qAndValue = explode('=', $typeWithQ[0]); - - if (2 == count($qAndValue)) { - $quality = $qAndValue[1]; - } - } - $qualityToTypes[$quality][$mimeType] = true; - } - krsort($qualityToTypes); - - foreach ($qualityToTypes as $typeList) { - $orderedTypes += $typeList; - } - return array_keys($orderedTypes); - } - - /** - * Get api type from Request - * - * @return string - */ - public function getApiType() - { - // getParam() is not used to avoid parameter fetch from $_GET or $_POST - return isset($this->_params['api_type']) ? $this->_params['api_type'] : null; - } - - /** - * Fetch data from HTTP Request body - * - * @return array - */ - public function getBodyParams() - { - if (null == $this->_bodyParams) { - $this->_bodyParams = $this->_getInterpreter()->interpret((string)$this->getRawBody()); - } - return $this->_bodyParams; - } - - /** - * Get Content-Type of request - * - * @return string - * @throws Mage_Api2_Exception - */ - public function getContentType() - { - $headerValue = $this->getHeader('Content-Type'); - - if (!$headerValue) { - throw new Mage_Api2_Exception('Content-Type header is empty', Mage_Api2_Model_Server::HTTP_BAD_REQUEST); - } - if (!preg_match('~^([a-z\d/\-+.]+)(?:; *charset=(.+))?$~Ui', $headerValue, $matches)) { - throw new Mage_Api2_Exception('Invalid Content-Type header', Mage_Api2_Model_Server::HTTP_BAD_REQUEST); - } - // request encoding check if it is specified in header - if (isset($matches[2]) && self::REQUEST_CHARSET != strtolower($matches[2])) { - throw new Mage_Api2_Exception( - 'UTF-8 is the only supported charset', Mage_Api2_Model_Server::HTTP_BAD_REQUEST - ); - } - return $matches[1]; - } - - /** - * Get filter settings passed by API user - * - * @return mixed - */ - public function getFilter() - { - return $this->getQuery(self::QUERY_PARAM_FILTER); - } - - /** - * Get resource model class name - * - * @return string|null - */ - public function getModel() - { - // getParam() is not used to avoid parameter fetch from $_GET or $_POST - return isset($this->_params['model']) ? $this->_params['model'] : null; - } - - /** - * Retrieve one of CRUD operation dependent on HTTP method - * - * @return string - * @throws Mage_Api2_Exception - */ - public function getOperation() - { - if (!$this->isGet() && !$this->isPost() && !$this->isPut() && !$this->isDelete()) { - throw new Mage_Api2_Exception('Invalid request method', Mage_Api2_Model_Server::HTTP_BAD_REQUEST); - } - // Map HTTP methods to classic CRUD verbs - $operationByMethod = array( - 'GET' => Mage_Api2_Model_Resource::OPERATION_RETRIEVE, - 'POST' => Mage_Api2_Model_Resource::OPERATION_CREATE, - 'PUT' => Mage_Api2_Model_Resource::OPERATION_UPDATE, - 'DELETE' => Mage_Api2_Model_Resource::OPERATION_DELETE - ); - - return $operationByMethod[$this->getMethod()]; - } - - /** - * Get sort order direction requested by API user - * - * @return mixed - */ - public function getOrderDirection() - { - return $this->getQuery(self::QUERY_PARAM_ORDER_DIR); - } - - /** - * Get sort order field requested by API user - * - * @return mixed - */ - public function getOrderField() - { - return $this->getQuery(self::QUERY_PARAM_ORDER_FIELD); - } - - /** - * Retrieve page number requested by API user - * - * @return mixed - */ - public function getPageNumber() - { - return $this->getQuery(self::QUERY_PARAM_PAGE_NUM); - } - - /** - * Retrieve page size requested by API user - * - * @return mixed - */ - public function getPageSize() - { - return $this->getQuery(self::QUERY_PARAM_PAGE_SIZE); - } - - /** - * Get an array of attribute codes requested by API user - * - * @return array - */ - public function getRequestedAttributes() - { - $include = $this->getQuery(self::QUERY_PARAM_REQ_ATTRS, array()); - - //transform comma-separated list - if (!is_array($include)) { - $include = explode(',', $include); - } - return array_map('trim', $include); - } - - /** - * Retrieve resource type - * - * @return string - */ - public function getResourceType() - { - // getParam() is not used to avoid parameter fetch from $_GET or $_POST - return isset($this->_params['type']) ? $this->_params['type'] : null; - } - - /** - * Get Version header from headers - * - * @return string - */ - public function getVersion() - { - return $this->getHeader('Version'); - } - - /** - * Retrieve action type - * - * @return string|null - */ - public function getActionType() - { - // getParam() is not used to avoid parameter fetch from $_GET or $_POST - return isset($this->_params['action_type']) ? $this->_params['action_type'] : null; - } - - /** - * It checks if the array in the request body is an associative one. - * It is required for definition of the dynamic aaction type (multi or single) - * - * @return bool - */ - public function isAssocArrayInRequestBody() - { - $params = $this->getBodyParams(); - if (count($params)) { - $keys = array_keys($params); - return !is_numeric($keys[0]); - } - return false; - } -} diff --git a/app/code/core/Mage/Api2/Model/Request/Internal.php b/app/code/core/Mage/Api2/Model/Request/Internal.php deleted file mode 100644 index 50689572f4cbcc7f57028d8431187827cfcb0d55..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Request/Internal.php +++ /dev/null @@ -1,105 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API internal request model - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Model_Request_Internal extends Mage_Api2_Model_Request -{ - /** - * Request body data - * - * @var array - */ - protected $_bodyParams; - - /** - * Request method - * - * @var string - */ - protected $_method; - - /** - * Fetch data from HTTP Request body - * - * @return array - */ - public function getBodyParams() - { - if ($this->_bodyParams === null) { - $this->_bodyParams = $this->_getInterpreter()->interpret((string) $this->getRawBody()); - } - return $this->_bodyParams; - } - - /** - * Set request body data - * - * @param array $data - * @return Mage_Api2_Model_Request - */ - public function setBodyParams($data) - { - $this->_bodyParams = $data; - return $this; - } - - /** - * Set HTTP request method for request emulation during internal call - * - * @param string $method - * @return Mage_Api2_Model_Request_Internal - */ - public function setMethod($method) - { - $availableMethod = array('GET', 'POST', 'PUT', 'DELETE'); - if (in_array($method, $availableMethod)) { - $this->_method = $method; - } else { - throw new Mage_Api2_Exception('Invalid method provided', Mage_Api2_Model_Server::HTTP_INTERNAL_ERROR); - } - return $this; - } - - /** - * Override parent method for request emulation during internal call - * - * @return string - */ - public function getMethod() - { - $method = $this->_method; - if (!$method) { - $method = parent::getMethod(); - } - return $method; - } -} diff --git a/app/code/core/Mage/Api2/Model/Request/Interpreter.php b/app/code/core/Mage/Api2/Model/Request/Interpreter.php deleted file mode 100644 index b672480764cd6a6dbdb2375f19228e9cd8d08561..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Request/Interpreter.php +++ /dev/null @@ -1,76 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Request content interpreter factory - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -abstract class Mage_Api2_Model_Request_Interpreter -{ - /** - * Request body interpreters factory - * - * @param string $type - * @return Mage_Api2_Model_Request_Interpreter_Interface - * @throws Exception|Mage_Api2_Exception - */ - public static function factory($type) - { - /** @var $helper Mage_Api2_Helper_Data */ - $helper = Mage::helper('Mage_Api2_Helper_Data'); - $adapters = $helper->getRequestInterpreterAdapters(); - - if (empty($adapters) || !is_array($adapters)) { - throw new Exception('Request interpreter adapters is not set.'); - } - - $adapterModel = null; - foreach ($adapters as $item) { - $itemType = $item->type; - if ($itemType == $type) { - $adapterModel = $item->model; - break; - } - } - - if ($adapterModel === null) { - throw new Mage_Api2_Exception( - sprintf('Server can not understand Content-Type HTTP header media type "%s"', $type), - Mage_Api2_Model_Server::HTTP_BAD_REQUEST - ); - } - - $adapter = Mage::getModel($adapterModel); - if (!$adapter) { - throw new Exception(sprintf('Request interpreter adapter "%s" not found.', $type)); - } - - return $adapter; - } -} diff --git a/app/code/core/Mage/Api2/Model/Request/Interpreter/Interface.php b/app/code/core/Mage/Api2/Model/Request/Interpreter/Interface.php deleted file mode 100644 index ba40a3b6e75316d7781f1c845ad05547179cebbe..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Request/Interpreter/Interface.php +++ /dev/null @@ -1,43 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Request content interpreter adapter interface - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -interface Mage_Api2_Model_Request_Interpreter_Interface -{ - /** - * Parse request body into array of params - * - * @param string $body Posted content from request - * @return array|null Return NULL if content is invalid - */ - public function interpret($body); -} diff --git a/app/code/core/Mage/Api2/Model/Request/Interpreter/Json.php b/app/code/core/Mage/Api2/Model/Request/Interpreter/Json.php deleted file mode 100644 index c75afa6861e36774a4d2ee38d504acf812d20587..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Request/Interpreter/Json.php +++ /dev/null @@ -1,57 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Request content interpreter JSON adapter - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Model_Request_Interpreter_Json implements Mage_Api2_Model_Request_Interpreter_Interface -{ - /** - * Parse Request body into array of params - * - * @param string $body Posted content from request - * @return array|null Return NULL if content is invalid - * @throws Exception|Mage_Api2_Exception - */ - public function interpret($body) - { - if (!is_string($body)) { - throw new Exception(sprintf('Invalid data type "%s". String expected.', gettype($body))); - } - - $decoded = Zend_Json::decode($body); - - if ($body != 'null' && $decoded === null) { - throw new Mage_Api2_Exception('Decoding error.', Mage_Api2_Model_Server::HTTP_BAD_REQUEST); - } - - return $decoded; - } -} diff --git a/app/code/core/Mage/Api2/Model/Request/Interpreter/Query.php b/app/code/core/Mage/Api2/Model/Request/Interpreter/Query.php deleted file mode 100644 index 8b010cb9ff056ffb1e5d9218fa0963a64f30b90e..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Request/Interpreter/Query.php +++ /dev/null @@ -1,77 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Request content interpreter query adapter - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Model_Request_Interpreter_Query implements Mage_Api2_Model_Request_Interpreter_Interface -{ - /** - * URI validate pattern - */ - const URI_VALIDATE_PATTERN = "/^(?:%[[:xdigit:]]{2}|[A-Za-z0-9-_.!~*'()\[\];\/?:@&=+$,])*$/"; - - /** - * Parse request body into array of params - * - * @param string $body Posted content from request - * @return array Return always array - * @throws Exception|Mage_Api2_Exception - */ - public function interpret($body) - { - if (!is_string($body)) { - throw new Exception(sprintf('Invalid data type "%s". String expected.', gettype($body))); - } - - if (!$this->_validateQuery($body)) { - throw new Mage_Api2_Exception( - 'Invalid data type. Check Content-Type.', - Mage_Api2_Model_Server::HTTP_BAD_REQUEST - ); - } - - $data = array(); - parse_str($body, $data); - return $data; - } - - /** - * Returns true if and only if the query string passes validation. - * - * @param string $query The query to validate - * @return boolean - * @link http://www.faqs.org/rfcs/rfc2396.html - */ - protected function _validateQuery($query) - { - return preg_match(self::URI_VALIDATE_PATTERN, $query); - } -} diff --git a/app/code/core/Mage/Api2/Model/Request/Interpreter/Xml.php b/app/code/core/Mage/Api2/Model/Request/Interpreter/Xml.php deleted file mode 100644 index b9375b39713ffcdac84c2a12a92e369064cb08a4..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Request/Interpreter/Xml.php +++ /dev/null @@ -1,154 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Request content interpreter XML adapter - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Model_Request_Interpreter_Xml implements Mage_Api2_Model_Request_Interpreter_Interface -{ - /** - * Default name for item of non-associative array - */ - const ARRAY_NON_ASSOC_ITEM_NAME = 'data_item'; - - /** - * Load error string. - * - * Is null if there was no error while loading - * - * @var string - */ - protected $_loadErrorStr = null; - - /** - * Parse Request body into array of params - * - * @param string $body Posted content from request - * @return array - * @throws Exception|Mage_Api2_Exception - */ - public function interpret($body) - { - if (!is_string($body)) { - throw new Exception(sprintf('Invalid data type "%s". String expected.', gettype($body))); - } - $body = false !== strpos($body, '<?xml') ? $body : '<?xml version="1.0"?>' . PHP_EOL . $body; - - // disable external entity loading to prevent possible vulnerability - libxml_disable_entity_loader(true); - set_error_handler(array($this, '_loadErrorHandler')); // Warnings and errors are suppressed - $config = simplexml_load_string($body); - restore_error_handler(); - // restore default behavior to make possible to load external entities - libxml_disable_entity_loader(false); - - // Check if there was a error while loading file - if ($this->_loadErrorStr !== null) { - throw new Mage_Api2_Exception('Decoding error.', Mage_Api2_Model_Server::HTTP_BAD_REQUEST); - } - - $xml = $this->_toArray($config); - return $xml; - } - - /** - * Returns an associativearray from a SimpleXMLElement. - * - * @param SimpleXMLElement $xmlObject Convert a SimpleXMLElement into an array - * @return array - */ - protected function _toArray(SimpleXMLElement $xmlObject) - { - $config = array(); - // Search for parent node values - if (count($xmlObject->attributes()) > 0) { - foreach ($xmlObject->attributes() as $key => $value) { - $value = (string)$value; - if (array_key_exists($key, $config)) { - if (!is_array($config[$key])) { - $config[$key] = array($config[$key]); - } - $config[$key][] = $value; - } else { - $config[$key] = $value; - } - } - } - - // Search for children - if (count($xmlObject->children()) > 0) { - foreach ($xmlObject->children() as $key => $value) { - if (count($value->children()) > 0) { - $value = $this->_toArray($value); - } else if (count($value->attributes()) > 0) { - $attributes = $value->attributes(); - if (isset($attributes['value'])) { - $value = (string)$attributes['value']; - } else { - $value = $this->_toArray($value); - } - } else { - $value = (string) $value; - } - if (array_key_exists($key, $config)) { - if (!is_array($config[$key]) || !array_key_exists(0, $config[$key])) { - $config[$key] = array($config[$key]); - } - $config[$key][] = $value; - } else { - if (self::ARRAY_NON_ASSOC_ITEM_NAME != $key) { - $config[$key] = $value; - } else { - $config[] = $value; - } - } - } - } - - return $config; - } - - /** - * Handle any errors from load xml - * - * @param integer $errno - * @param string $errstr - * @param string $errfile - * @param integer $errline - */ - protected function _loadErrorHandler($errno, $errstr, $errfile, $errline) - { - if ($this->_loadErrorStr === null) { - $this->_loadErrorStr = $errstr; - } else { - $this->_loadErrorStr .= (PHP_EOL . $errstr); - } - } -} diff --git a/app/code/core/Mage/Api2/Model/Resource.php b/app/code/core/Mage/Api2/Model/Resource.php deleted file mode 100644 index 8db23b7ca61a363ebc39cd520da46415c56fd6e4..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Resource.php +++ /dev/null @@ -1,1082 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 Abstract Resource - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - * @method string _create() _create(array $filteredData) creation of an entity - * @method void _multiCreate() _multiCreate(array $filteredData) processing and creation of a collection - * @method array _retrieve() retrieving an entity - * @method array _retrieveCollection() retrieving a collection - * @method void _update() _update(array $filteredData) update of an entity - * @method void _multiUpdate() _multiUpdate(array $filteredData) update of a collection - * @method void _delete() deletion of an entity - * @method void _multidelete() _multidelete(array $requestData) deletion of a collection - */ -abstract class Mage_Api2_Model_Resource -{ - /**#@+ - * Action types - */ - const ACTION_TYPE_ENTITY = 'entity'; - const ACTION_TYPE_COLLECTION = 'collection'; - /**#@-*/ - - /**#@+ - * Operations. Resource method names - */ - const OPERATION_CREATE = 'create'; - const OPERATION_RETRIEVE = 'retrieve'; - const OPERATION_UPDATE = 'update'; - const OPERATION_DELETE = 'delete'; - /**#@-*/ - - /**#@+ - * Common operations for attributes - */ - const OPERATION_ATTRIBUTE_READ = 'read'; - const OPERATION_ATTRIBUTE_WRITE = 'write'; - /**#@-*/ - - /**#@+ - * Default error messages - */ - const RESOURCE_NOT_FOUND = 'Resource not found.'; - const RESOURCE_METHOD_NOT_ALLOWED = 'Resource does not support method.'; - const RESOURCE_METHOD_NOT_IMPLEMENTED = 'Resource method not implemented yet.'; - const RESOURCE_INTERNAL_ERROR = 'Resource internal error.'; - const RESOURCE_DATA_PRE_VALIDATION_ERROR = 'Resource data pre-validation error.'; - const RESOURCE_DATA_INVALID = 'Resource data invalid.'; //error while checking data inside method - const RESOURCE_UNKNOWN_ERROR = 'Resource unknown error.'; - const RESOURCE_REQUEST_DATA_INVALID = 'The request data is invalid.'; - /**#@-*/ - - /**#@+ - * Default collection resources error messages - */ - const RESOURCE_COLLECTION_PAGING_ERROR = 'Resource collection paging error.'; - const RESOURCE_COLLECTION_PAGING_LIMIT_ERROR = 'The paging limit exceeds the allowed number.'; - const RESOURCE_COLLECTION_ORDERING_ERROR = 'Resource collection ordering error.'; - const RESOURCE_COLLECTION_FILTERING_ERROR = 'Resource collection filtering error.'; - const RESOURCE_COLLECTION_ATTRIBUTES_ERROR = 'Resource collection including additional attributes error.'; - /**#@-*/ - - /**#@+ - * Default success messages - */ - const RESOURCE_UPDATED_SUCCESSFUL = 'Resource updated successful.'; - /**#@-*/ - - /**#@+ - * Collection page sizes - */ - const PAGE_SIZE_DEFAULT = 10; - const PAGE_SIZE_MAX = 100; - /**#@-*/ - - /** - * Request - * - * @var Mage_Api2_Model_Request - */ - protected $_request; - - /** - * Resource type - * - * @var string - */ - protected $_resourceType; - - /** - * Api type - * - * @var string - */ - protected $_apiType; - - /** - * API Version - * - * @var int - */ - protected $_version = null; - - /** - * Response - * - * @var Zend_Controller_Response_Http - */ - protected $_response; - - /** - * Attribute Filter - * - * @var Mage_Api2_Model_Acl_Filter - */ - protected $_filter; - - /** - * Renderer - * - * @var Mage_Api2_Model_Renderer_Interface - */ - protected $_renderer; - - /** - * Api user - * - * @var Mage_Api2_Model_Auth_User_Abstract - */ - protected $_apiUser; - - /** - * User type - * - * @var string - */ - protected $_userType; - - /** - * One of Mage_Api2_Model_Resource::ACTION_TYPE_... constant - * - * @var string - */ - protected $_actionType; - - /** - * One of Mage_Api2_Model_Resource::OPERATION_... constant - * - * @var string - */ - protected $_operation; - - /** - * If TRUE - no rendering will be done and dispatch will return data. Otherwise, by default - * - * @var bool - */ - protected $_returnData = false; - - /** - * @var Mage_Api2_Model_Multicall - */ - protected $_multicall; - - /** - * Dispatch - * To implement the functionality, you must create a method in the parent one. - * - * Action type is defined in api2.xml in the routes section and depends on entity (single object) - * or collection (several objects). - * - * HTTP_MULTI_STATUS is used for several status codes in the response - */ - public function dispatch() - { - switch ($this->getActionType() . $this->getOperation()) { - /* Create */ - case self::ACTION_TYPE_ENTITY . self::OPERATION_CREATE: - // Creation of objects is possible only when working with collection - $this->_critical(self::RESOURCE_METHOD_NOT_IMPLEMENTED); - break; - case self::ACTION_TYPE_COLLECTION . self::OPERATION_CREATE: - // If no of the methods(multi or single) is implemented, request body is not checked - if (!$this->_checkMethodExist('_create') && !$this->_checkMethodExist('_multiCreate')) { - $this->_critical(self::RESOURCE_METHOD_NOT_IMPLEMENTED); - } - // If one of the methods(multi or single) is implemented, request body must not be empty - $requestData = $this->getRequest()->getBodyParams(); - if (empty($requestData)) { - $this->_critical(self::RESOURCE_REQUEST_DATA_INVALID); - } - // The create action has the dynamic type which depends on data in the request body - if ($this->getRequest()->isAssocArrayInRequestBody()) { - $this->_errorIfMethodNotExist('_create'); - $filteredData = $this->getFilter()->in($requestData); - if (empty($filteredData)) { - $this->_critical(self::RESOURCE_REQUEST_DATA_INVALID); - } - $newItemLocation = $this->_create($filteredData); - $this->getResponse()->setHeader('Location', $newItemLocation); - } else { - $this->_errorIfMethodNotExist('_multiCreate'); - $filteredData = $this->getFilter()->collectionIn($requestData); - $this->_multiCreate($filteredData); - $this->_render($this->getResponse()->getMessages()); - $this->getResponse()->setHttpResponseCode(Mage_Api2_Model_Server::HTTP_MULTI_STATUS); - } - break; - /* Retrieve */ - case self::ACTION_TYPE_ENTITY . self::OPERATION_RETRIEVE: - $this->_errorIfMethodNotExist('_retrieve'); - $retrievedData = $this->_retrieve(); - $filteredData = $this->getFilter()->out($retrievedData); - $this->_render($filteredData); - break; - case self::ACTION_TYPE_COLLECTION . self::OPERATION_RETRIEVE: - $this->_errorIfMethodNotExist('_retrieveCollection'); - $retrievedData = $this->_retrieveCollection(); - $filteredData = $this->getFilter()->collectionOut($retrievedData); - $this->_render($filteredData); - break; - /* Update */ - case self::ACTION_TYPE_ENTITY . self::OPERATION_UPDATE: - $this->_errorIfMethodNotExist('_update'); - $requestData = $this->getRequest()->getBodyParams(); - if (empty($requestData)) { - $this->_critical(self::RESOURCE_REQUEST_DATA_INVALID); - } - $filteredData = $this->getFilter()->in($requestData); - if (empty($filteredData)) { - $this->_critical(self::RESOURCE_REQUEST_DATA_INVALID); - } - $this->_update($filteredData); - break; - case self::ACTION_TYPE_COLLECTION . self::OPERATION_UPDATE: - $this->_errorIfMethodNotExist('_multiUpdate'); - $requestData = $this->getRequest()->getBodyParams(); - if (empty($requestData)) { - $this->_critical(self::RESOURCE_REQUEST_DATA_INVALID); - } - $filteredData = $this->getFilter()->collectionIn($requestData); - $this->_multiUpdate($filteredData); - $this->_render($this->getResponse()->getMessages()); - $this->getResponse()->setHttpResponseCode(Mage_Api2_Model_Server::HTTP_MULTI_STATUS); - break; - /* Delete */ - case self::ACTION_TYPE_ENTITY . self::OPERATION_DELETE: - $this->_errorIfMethodNotExist('_delete'); - $this->_delete(); - break; - case self::ACTION_TYPE_COLLECTION . self::OPERATION_DELETE: - $this->_errorIfMethodNotExist('_multiDelete'); - $requestData = $this->getRequest()->getBodyParams(); - if (empty($requestData)) { - $this->_critical(self::RESOURCE_REQUEST_DATA_INVALID); - } - $this->_multiDelete($requestData); - $this->getResponse()->setHttpResponseCode(Mage_Api2_Model_Server::HTTP_MULTI_STATUS); - break; - default: - $this->_critical(self::RESOURCE_METHOD_NOT_IMPLEMENTED); - break; - } - } - - /** - * Trigger error for not-implemented operations - * - * @param $methodName - */ - protected function _errorIfMethodNotExist($methodName) - { - if (!$this->_checkMethodExist($methodName)) { - $this->_critical(self::RESOURCE_METHOD_NOT_IMPLEMENTED); - } - } - - /** - * Check method exist - * - * @param $methodName - * @return bool - */ - protected function _checkMethodExist($methodName) - { - return method_exists($this, $methodName); - } - - /** - * Get request - * - * @throws Exception - * @return Mage_Api2_Model_Request - */ - public function getRequest() - { - if (!$this->_request) { - throw new Exception('Request is not set.'); - } - return $this->_request; - } - - /** - * Set request - * - * @param Mage_Api2_Model_Request $request - * @return Mage_Api2_Model_Resource - */ - public function setRequest(Mage_Api2_Model_Request $request) - { - $this->setResourceType($request->getResourceType()); - $this->setApiType($request->getApiType()); - $this->_request = $request; - return $this; - } - - /** - * Get resource type - * If not exists get from Request - * - * @return string - */ - public function getResourceType() - { - if (!$this->_resourceType) { - $this->setResourceType($this->getRequest()->getResourceType()); - } - return $this->_resourceType; - } - - /** - * Set resource type - * - * @param string $resourceType - * @return Mage_Api2_Model_Resource - */ - public function setResourceType($resourceType) - { - $this->_resourceType = $resourceType; - return $this; - } - - /** - * Get API type - * If not exists get from Request. - * - * @return string - */ - public function getApiType() - { - if (!$this->_apiType) { - $this->setApiType($this->getRequest()->getApiType()); - } - return $this->_apiType; - } - - /** - * Set API type - * - * @param string $apiType - * @return Mage_Api2_Model_Resource - */ - public function setApiType($apiType) - { - $this->_apiType = $apiType; - return $this; - } - - /** - * Determine version from class name - * - * @return int - */ - public function getVersion() - { - if (null === $this->_version) { - if (preg_match('/^.+([1-9]\d*)$/', get_class($this), $matches) ) { - $this->setVersion($matches[1]); - } else { - throw new Exception('Can not determine version from class name'); - } - } - return $this->_version; - } - - /** - * Set API version - * - * @param int $version - */ - public function setVersion($version) - { - $this->_version = (int)$version; - } - - /** - * Get response - * - * @return Mage_Api2_Model_Response - */ - public function getResponse() - { - if (!$this->_response) { - throw new Exception('Response is not set.'); - } - return $this->_response; - } - - /** - * Set response - * - * @param Mage_Api2_Model_Response $response - */ - public function setResponse(Mage_Api2_Model_Response $response) - { - $this->_response = $response; - } - - /** - * Get filter if not exists create - * - * @return Mage_Api2_Model_Acl_Filter - */ - public function getFilter() - { - if (!$this->_filter) { - /** @var $filter Mage_Api2_Model_Acl_Filter */ - $filter = Mage::getModel('Mage_Api2_Model_Acl_Filter', array('resource' => $this)); - $this->setFilter($filter); - } - return $this->_filter; - } - - /** - * Set filter - * - * @param Mage_Api2_Model_Acl_Filter $filter - */ - public function setFilter(Mage_Api2_Model_Acl_Filter $filter) - { - $this->_filter = $filter; - } - - /** - * Get renderer if not exists create - * - * @return Mage_Api2_Model_Renderer_Interface - */ - public function getRenderer() - { - if (!$this->_renderer) { - $renderer = Mage_Api2_Model_Renderer::factory($this->getRequest()->getAcceptTypes()); - $this->setRenderer($renderer); - } - - return $this->_renderer; - } - - /** - * Set renderer - * - * @param Mage_Api2_Model_Renderer_Interface $renderer - */ - public function setRenderer(Mage_Api2_Model_Renderer_Interface $renderer) - { - $this->_renderer = $renderer; - } - - /** - * Get user type - * If not exists get from apiUser - * - * @return string - */ - public function getUserType() - { - if (!$this->_userType) { - $this->setUserType($this->getApiUser()->getType()); - } - return $this->_userType; - } - - /** - * Set user type - * - * @param string $userType - * @return Mage_Api2_Model_Resource - */ - public function setUserType($userType) - { - $this->_userType = $userType; - return $this; - } - - /** - * Get API user - * - * @throws Exception - * @return Mage_Api2_Model_Auth_User_Abstract - */ - public function getApiUser() - { - if (!$this->_apiUser) { - throw new Exception('API user is not set.'); - } - return $this->_apiUser; - } - - /** - * Set API user - * - * @param Mage_Api2_Model_Auth_User_Abstract $apiUser - * @return Mage_Api2_Model_Resource - */ - public function setApiUser(Mage_Api2_Model_Auth_User_Abstract $apiUser) - { - $this->_apiUser = $apiUser; - return $this; - } - - /** - * Get action type - * If not exists get from Request - * - * @return string One of Mage_Api2_Model_Resource::ACTION_TYPE_... constant - */ - public function getActionType() - { - if (!$this->_actionType) { - $this->setActionType($this->getRequest()->getActionType()); - } - return $this->_actionType; - } - - /** - * Set route type - * - * @param string $actionType One of Mage_Api2_Model_Resource::ACTION_TYPE_... constant - * @return Mage_Api2_Model_Resource - */ - public function setActionType($actionType) - { - $this->_actionType = $actionType; - return $this; - } - - /** - * Get operation - * If not exists get from Request - * - * @return string One of Mage_Api2_Model_Resource::OPERATION_... constant - */ - public function getOperation() - { - if (!$this->_operation) { - $this->setOperation($this->getRequest()->getOperation()); - } - return $this->_operation; - } - - /** - * Set operation - * - * @param string $operation One of Mage_Api2_Model_Resource::OPERATION_... constant - * @return Mage_Api2_Model_Resource - */ - public function setOperation($operation) - { - $this->_operation = $operation; - return $this; - } - - /** - * Get API2 config - * - * @return Mage_Api2_Model_Config - */ - public function getConfig() - { - return Mage::getSingleton('Mage_Api2_Model_Config'); - } - - /** - * Get working model - * - * @return Mage_Core_Model_Abstract - */ - public function getWorkingModel() - { - return Mage::getModel($this->getConfig()->getResourceWorkingModel($this->getResourceType())); - } - - /** - * Render data using registered Renderer - * - * @param mixed $data - */ - protected function _render($data) - { - $this->getResponse()->setMimeType($this->getRenderer()->getMimeType()) - ->setBody($this->getRenderer()->render($data)); - } - - /** - * Throw exception, critical error - stop execution - * - * @param string $message - * @param int $code - * @throws Mage_Api2_Exception - */ - protected function _critical($message, $code = null) - { - if ($code === null) { - $errors = $this->_getCriticalErrors(); - if (!isset($errors[$message])) { - throw new Exception( - sprintf('Invalid error "%s" or error code missed.', $message), - Mage_Api2_Model_Server::HTTP_INTERNAL_ERROR - ); - } - $code = $errors[$message]; - } - throw new Mage_Api2_Exception($message, $code); - } - - /** - * Retrieve array with critical errors mapped to HTTP codes - * - * @return array - */ - protected function _getCriticalErrors() - { - return array( - '' => Mage_Api2_Model_Server::HTTP_BAD_REQUEST, - self::RESOURCE_NOT_FOUND => Mage_Api2_Model_Server::HTTP_NOT_FOUND, - self::RESOURCE_METHOD_NOT_ALLOWED => Mage_Api2_Model_Server::HTTP_METHOD_NOT_ALLOWED, - self::RESOURCE_METHOD_NOT_IMPLEMENTED => Mage_Api2_Model_Server::HTTP_METHOD_NOT_ALLOWED, - self::RESOURCE_DATA_PRE_VALIDATION_ERROR => Mage_Api2_Model_Server::HTTP_BAD_REQUEST, - self::RESOURCE_INTERNAL_ERROR => Mage_Api2_Model_Server::HTTP_INTERNAL_ERROR, - self::RESOURCE_UNKNOWN_ERROR => Mage_Api2_Model_Server::HTTP_BAD_REQUEST, - self::RESOURCE_REQUEST_DATA_INVALID => Mage_Api2_Model_Server::HTTP_BAD_REQUEST, - self::RESOURCE_COLLECTION_PAGING_ERROR => Mage_Api2_Model_Server::HTTP_BAD_REQUEST, - self::RESOURCE_COLLECTION_PAGING_LIMIT_ERROR => Mage_Api2_Model_Server::HTTP_BAD_REQUEST, - self::RESOURCE_COLLECTION_ORDERING_ERROR => Mage_Api2_Model_Server::HTTP_BAD_REQUEST, - self::RESOURCE_COLLECTION_FILTERING_ERROR => Mage_Api2_Model_Server::HTTP_BAD_REQUEST, - self::RESOURCE_COLLECTION_ATTRIBUTES_ERROR => Mage_Api2_Model_Server::HTTP_BAD_REQUEST, - ); - } - - /** - * Add non-critical error - * - * @param string $message - * @param int $code - * @return Mage_Api2_Model_Resource - */ - protected function _error($message, $code) - { - $this->getResponse()->setException(new Mage_Api2_Exception($message, $code)); - return $this; - } - - /** - * Add success message - * - * @param string $message - * @param int $code - * @param array $params - * @return Mage_Api2_Model_Resource - */ - protected function _successMessage($message, $code, $params = array()) - { - $this->getResponse()->addMessage($message, $code, $params, Mage_Api2_Model_Response::MESSAGE_TYPE_SUCCESS); - return $this; - } - - /** - * Add error message - * - * @param string $message - * @param int $code - * @param array $params - * @return Mage_Api2_Model_Resource - */ - protected function _errorMessage($message, $code, $params = array()) - { - $this->getResponse()->addMessage($message, $code, $params, Mage_Api2_Model_Response::MESSAGE_TYPE_ERROR); - return $this; - } - - /** - * Set navigation parameters and apply filters from URL params - * - * @param Varien_Data_Collection_Db $collection - * @return Mage_Api2_Model_Resource - */ - final protected function _applyCollectionModifiers(Varien_Data_Collection_Db $collection) - { - $pageNumber = $this->getRequest()->getPageNumber(); - if ($pageNumber != abs($pageNumber)) { - $this->_critical(self::RESOURCE_COLLECTION_PAGING_ERROR); - } - - $pageSize = $this->getRequest()->getPageSize(); - if (null == $pageSize) { - $pageSize = self::PAGE_SIZE_DEFAULT; - } else { - if ($pageSize != abs($pageSize) || $pageSize > self::PAGE_SIZE_MAX) { - $this->_critical(self::RESOURCE_COLLECTION_PAGING_LIMIT_ERROR); - } - } - - $orderField = $this->getRequest()->getOrderField(); - - if (null !== $orderField) { - $operation = Mage_Api2_Model_Resource::OPERATION_ATTRIBUTE_READ; - if (!is_string($orderField) - || !array_key_exists($orderField, $this->getAvailableAttributes($this->getUserType(), $operation)) - ) { - $this->_critical(self::RESOURCE_COLLECTION_ORDERING_ERROR); - } - $collection->setOrder($orderField, $this->getRequest()->getOrderDirection()); - } - $collection->setCurPage($pageNumber)->setPageSize($pageSize); - - return $this->_applyFilter($collection); - } - - /** - * Validate filter data and apply it to collection if possible - * - * @param Varien_Data_Collection_Db $collection - * @return Mage_Api2_Model_Resource - */ - protected function _applyFilter(Varien_Data_Collection_Db $collection) - { - $filter = $this->getRequest()->getFilter(); - - if (!$filter) { - return $this; - } - if (!is_array($filter)) { - $this->_critical(self::RESOURCE_COLLECTION_FILTERING_ERROR); - } - if (method_exists($collection, 'addAttributeToFilter')) { - $methodName = 'addAttributeToFilter'; - } elseif (method_exists($collection, 'addFieldToFilter')) { - $methodName = 'addFieldToFilter'; - } else { - return $this; - } - $allowedAttributes = $this->getFilter()->getAllowedAttributes(self::OPERATION_ATTRIBUTE_READ); - - foreach ($filter as $filterEntry) { - if (!is_array($filterEntry) - || !array_key_exists('attribute', $filterEntry) - || !in_array($filterEntry['attribute'], $allowedAttributes) - ) { - $this->_critical(self::RESOURCE_COLLECTION_FILTERING_ERROR); - } - $attributeCode = $filterEntry['attribute']; - - unset($filterEntry['attribute']); - - try { - $collection->$methodName($attributeCode, $filterEntry); - } catch(Exception $e) { - $this->_critical(self::RESOURCE_COLLECTION_FILTERING_ERROR); - } - } - return $this; - } - - /** - * Perform multiple calls to subresources of specified resource - * - * @param string $resourceInstanceId - * @return Mage_Api2_Model_Response - */ - protected function _multicall($resourceInstanceId) - { - if (!$this->_multicall) { - $this->_multicall = Mage::getModel('Mage_Api2_Model_Multicall'); - } - $resourceName = $this->getResourceType(); - return $this->_multicall->call($resourceInstanceId, $resourceName, $this->getRequest()); - } - - /** - * Create model of specified resource and configure it with current object attributes - * - * @param string $resourceId Resource identifier - * @param array $requestParams Parameters to be set to request - * @return Mage_Api2_Model_Resource - */ - protected function _getSubModel($resourceId, array $requestParams) - { - $resourceModel = Mage_Api2_Model_Dispatcher::loadResourceModel( - $this->getConfig()->getResourceModel($resourceId), - $this->getApiType(), - $this->getUserType(), - $this->getVersion() - ); - - /** @var $request Mage_Api2_Model_Request */ - $request = Mage::getModel('Mage_Api2_Model_Request'); - - $request->setParams($requestParams); - - $resourceModel - ->setRequest($request) // request MUST be set first - ->setApiUser($this->getApiUser()) - ->setApiType($this->getApiType()) - ->setResourceType($resourceId) - ->setOperation($this->getOperation()) - ->setReturnData(true); - - return $resourceModel; - } - - /** - * Check ACL permission for specified resource with current other conditions - * - * @param string $resourceId Resource identifier - * @return bool - * @throws Exception - */ - protected function _isSubCallAllowed($resourceId) - { - /** @var $globalAcl Mage_Api2_Model_Acl_Global */ - $globalAcl = Mage::getSingleton('Mage_Api2_Model_Acl_Global'); - - try { - return $globalAcl->isAllowed($this->getApiUser(), $resourceId, $this->getOperation()); - } catch (Mage_Api2_Exception $e) { - throw new Exception('Invalid arguments for isAllowed() call'); - } - } - - /** - * Set 'returnData' flag - * - * @param boolean $flag - * @return Mage_Api2_Model_Resource - */ - public function setReturnData($flag) - { - $this->_returnData = $flag; - return $this; - } - - /** - * Get resource location - * - * @param Mage_Core_Model_Abstract $resource - * @return string URL - */ - protected function _getLocation($resource) - { - /* @var $apiTypeRoute Mage_Api2_Model_Route_ApiType */ - $apiTypeRoute = Mage::getModel('Mage_Api2_Model_Route_ApiType'); - - $chain = $apiTypeRoute->chain( - new Zend_Controller_Router_Route($this->getConfig()->getRouteWithEntityTypeAction($this->getResourceType())) - ); - $params = array( - 'api_type' => $this->getRequest()->getApiType(), - 'id' => $resource->getId() - ); - $uri = $chain->assemble($params); - - return '/' . $uri; - } - - /** - * Resource specific method to retrieve attributes' codes. May be overriden in child. - * - * @return array - */ - protected function _getResourceAttributes() - { - return array(); - } - - /** - * Get available attributes of API resource - * - * @param string $userType - * @param string $operation - * @return array - */ - public function getAvailableAttributes($userType, $operation) - { - $available = $this->getAvailableAttributesFromConfig(); - $excludedAttrs = $this->getExcludedAttributes($userType, $operation); - $includedAttrs = $this->getIncludedAttributes($userType, $operation); - $entityOnlyAttrs = $this->getEntityOnlyAttributes($userType, $operation); - $resourceAttrs = $this->_getResourceAttributes(); - - // if resource returns not-associative array - attributes' codes only - if (0 === key($resourceAttrs)) { - $resourceAttrs = array_combine($resourceAttrs, $resourceAttrs); - } - foreach ($resourceAttrs as $attrCode => $attrLabel) { - if (!isset($available[$attrCode])) { - $available[$attrCode] = empty($attrLabel) ? $attrCode : $attrLabel; - } - } - foreach (array_keys($available) as $code) { - if (in_array($code, $excludedAttrs) || ($includedAttrs && !in_array($code, $includedAttrs))) { - unset($available[$code]); - } - if (in_array($code, $entityOnlyAttrs)) { - $available[$code] .= ' *'; - } - } - return $available; - } - - /** - * Get excluded attributes for user type - * - * @param string $userType - * @param string $operation - * @return array - */ - public function getExcludedAttributes($userType, $operation) - { - return $this->getConfig()->getResourceExcludedAttributes($this->getResourceType(), $userType, $operation); - } - - /** - * Get forced attributes - * - * @return array - */ - public function getForcedAttributes() - { - return $this->getConfig()->getResourceForcedAttributes($this->getResourceType(), $this->getUserType()); - } - - /** - * Retrieve list of included attributes - * - * @param string $userType API user type - * @param string $operationType Type of operation: one of Mage_Api2_Model_Resource::OPERATION_ATTRIBUTE_... constant - * @return array - */ - public function getIncludedAttributes($userType, $operationType) - { - return $this->getConfig()->getResourceIncludedAttributes($this->getResourceType(), $userType, $operationType); - } - - /** - * Retrieve list of entity only attributes - * - * @param string $userType API user type - * @param string $operationType Type of operation: one of Mage_Api2_Model_Resource::OPERATION_ATTRIBUTE_... constant - * @return array - */ - public function getEntityOnlyAttributes($userType, $operationType) - { - return $this->getConfig()->getResourceEntityOnlyAttributes($this->getResourceType(), $userType, $operationType); - } - - /** - * Get available attributes of API resource from configuration file - * - * @return array - */ - public function getAvailableAttributesFromConfig() - { - return $this->getConfig()->getResourceAttributes($this->getResourceType()); - } - - /** - * Get available attributes of API resource from data base - * - * @return array - */ - public function getDbAttributes() - { - $available = array(); - $workModel = $this->getConfig()->getResourceWorkingModel($this->getResourceType()); - - if ($workModel) { - /* @var $resource Mage_Core_Model_Resource_Db_Abstract */ - $resource = Mage::getResourceModel($workModel); - - if (method_exists($resource, 'getMainTable')) { - $available = array_keys($resource->getReadConnection()->describeTable($resource->getMainTable())); - } - } - return $available; - } - - /** - * Get EAV attributes of working model - * - * @param bool $onlyVisible OPTIONAL Show only the attributes which are visible on frontend - * @param bool $excludeSystem OPTIONAL Exclude attributes marked as system - * @return array - */ - public function getEavAttributes($onlyVisible = false, $excludeSystem = false) - { - $attributes = array(); - $model = $this->getConfig()->getResourceWorkingModel($this->getResourceType()); - - /** @var $entityType Mage_Eav_Model_Entity_Type */ - $entityType = Mage::getModel('Mage_Eav_Model_Entity_Type')->load($model, 'entity_model'); - - /** @var $attribute Mage_Eav_Model_Entity_Attribute */ - foreach ($entityType->getAttributeCollection() as $attribute) { - if ($onlyVisible && !$attribute->getIsVisible()) { - continue; - } - if ($excludeSystem && $attribute->getIsSystem()) { - continue; - } - $attributes[$attribute->getAttributeCode()] = $attribute->getFrontendLabel(); - } - - return $attributes; - } - - /** - * Retrieve current store according to request and API user type - * - * @return Mage_Core_Model_Store - */ - protected function _getStore() - { - $store = $this->getRequest()->getParam('store'); - try { - if ($this->getUserType() != Mage_Api2_Model_Auth_User_Admin::USER_TYPE) { - // customer or guest role - if (!$store) { - $store = Mage::app()->getDefaultStoreView(); - } else { - $store = Mage::app()->getStore($store); - } - } else { - // admin role - if (is_null($store)) { - $store = Mage_Catalog_Model_Abstract::DEFAULT_STORE_ID; - } - $store = Mage::app()->getStore($store); - } - } catch (Mage_Core_Model_Store_Exception $e) { - // store does not exist - $this->_critical('Requested store is invalid', Mage_Api2_Model_Server::HTTP_BAD_REQUEST); - } - return $store; - } -} diff --git a/app/code/core/Mage/Api2/Model/Resource/Acl/Filter/Attribute.php b/app/code/core/Mage/Api2/Model/Resource/Acl/Filter/Attribute.php deleted file mode 100644 index ec9faf8d7d600f852feba44914199008760d1012..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Resource/Acl/Filter/Attribute.php +++ /dev/null @@ -1,87 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 filter ACL attribute resource model - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Model_Resource_Acl_Filter_Attribute extends Mage_Core_Model_Resource_Db_Abstract -{ - /** - * Attribute Filter resource ID "all" - */ - const FILTER_RESOURCE_ALL = 'all'; - - /** - * Initialize resource model - * - * @return void - */ - protected function _construct() - { - $this->_init('api2_acl_attribute', 'entity_id'); - } - - /** - * Get allowed attributes - * - * @param string $userType - * @param string $resourceId - * @param string $operation One of Mage_Api2_Model_Resource::OPERATION_ATTRIBUTE_... constant - * @return string|bool|null - */ - public function getAllowedAttributes($userType, $resourceId, $operation) - { - $select = $this->_getReadAdapter()->select() - ->from($this->getMainTable(), 'allowed_attributes') - ->where('user_type = ?', $userType) - ->where('resource_id = ?', $resourceId) - ->where('operation = ?', $operation); - - return $this->getReadConnection()->fetchOne($select); - } - - /** - * Check if ALL attributes allowed - * - * @param string $userType - * @return bool - */ - public function isAllAttributesAllowed($userType) - { - $resourceId = self::FILTER_RESOURCE_ALL; - - $select = $this->getReadConnection()->select() - ->from($this->getMainTable(), new Zend_Db_Expr('COUNT(*)')) - ->where('user_type = ?', $userType) - ->where('resource_id = ?', $resourceId); - - return ($this->getReadConnection()->fetchOne($select) == 1); - } -} diff --git a/app/code/core/Mage/Api2/Model/Resource/Acl/Filter/Attribute/Collection.php b/app/code/core/Mage/Api2/Model/Resource/Acl/Filter/Attribute/Collection.php deleted file mode 100644 index 46c6f5a1311d2c25b84e3e1c17426bf0aef0842c..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Resource/Acl/Filter/Attribute/Collection.php +++ /dev/null @@ -1,57 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 filter ACL attribute resource collection model - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Model_Resource_Acl_Filter_Attribute_Collection extends Mage_Core_Model_Resource_Db_Collection_Abstract -{ - /** - * Initialize collection model - * - * @return void - */ - protected function _construct() - { - $this->_init('Mage_Api2_Model_Acl_Filter_Attribute', 'Mage_Api2_Model_Resource_Acl_Filter_Attribute'); - } - - /** - * Add filtering by user type - * - * @param string $userType - * @return Mage_Api2_Model_Resource_Acl_Filter_Attribute_Collection - */ - public function addFilterByUserType($userType) - { - $this->addFilter('user_type', $userType, 'public'); - return $this; - } -} diff --git a/app/code/core/Mage/Api2/Model/Resource/Acl/Global/Role.php b/app/code/core/Mage/Api2/Model/Resource/Acl/Global/Role.php deleted file mode 100644 index 3c5ff17396861e6c796a81d54e4d27dc66a6a4ad..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Resource/Acl/Global/Role.php +++ /dev/null @@ -1,121 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 global ACL role resource model - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - * @method int getId - * @method string getRoleName - */ -class Mage_Api2_Model_Resource_Acl_Global_Role extends Mage_Core_Model_Resource_Db_Abstract -{ - /** - * Initialize resource model - * - * @return void - */ - protected function _construct() - { - $this->_init('api2_acl_role', 'entity_id'); - } - - /** - * Create/update relation row of admin user to API2 role - * - * @param int $adminId Admin user id - * @param int $roleId API2 role id - * @return Mage_Api2_Model_Resource_Acl_Global_Role - */ - public function saveAdminToRoleRelation($adminId, $roleId) - { - if (Mage_Api2_Model_Acl_Global_Role::ROLE_GUEST_ID == $roleId - || Mage_Api2_Model_Acl_Global_Role::ROLE_CUSTOMER_ID == $roleId - ) { - Mage::throwException( - Mage::helper('Mage_Api2_Helper_Data')->__('The role is a special one and not for assigning it to admin users.') - ); - } - - $read = $this->_getReadAdapter(); - $select = $read->select() - ->from($this->getTable('api2_acl_user'), 'admin_id') - ->where('admin_id = ?', $adminId, Zend_Db::INT_TYPE); - - $write = $this->_getWriteAdapter(); - $table = $this->getTable('api2_acl_user'); - - if (false === $read->fetchOne($select)) { - $write->insert($table, array('admin_id' => $adminId, 'role_id' => $roleId)); - } else { - $write->update($table, array('role_id' => $roleId), array('admin_id = ?' => $adminId)); - } - - return $this; - } - - /** - * delete relation row of admin user to API2 role - * - * @param int $adminId Admin user id - * @param int $roleId API2 role id - * @return Mage_Api2_Model_Resource_Acl_Global_Role - */ - public function deleteAdminToRoleRelation($adminId, $roleId) - { - $write = $this->_getWriteAdapter(); - $table = $this->getTable('api2_acl_user'); - - $where = array( - 'role_id = ?' => $roleId, - 'admin_id = ?' => $adminId - ); - - $write->delete($table, $where); - - return $this; - } - - /** - * Get users - * - * @param Mage_Api2_Model_Acl_Global_Role $role - * @return array - */ - public function getRoleUsers(Mage_Api2_Model_Acl_Global_Role $role) - { - $adapter = $this->_getReadAdapter(); - $select = $adapter->select() - ->from($this->getTable('api2_acl_user')) - ->where('role_id=?', $role->getId()); - - $users = $adapter->fetchCol($select); - - return $users; - } -} diff --git a/app/code/core/Mage/Api2/Model/Resource/Acl/Global/Role/Collection.php b/app/code/core/Mage/Api2/Model/Resource/Acl/Global/Role/Collection.php deleted file mode 100644 index b9dbd0ea98727f0f6bbb869bd14b848791908113..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Resource/Acl/Global/Role/Collection.php +++ /dev/null @@ -1,63 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 global ACL role resource collection model - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Model_Resource_Acl_Global_Role_Collection extends Mage_Core_Model_Resource_Db_Collection_Abstract -{ - /** - * Initialize collection model - * - * @return void - */ - protected function _construct() - { - $this->_init('Mage_Api2_Model_Acl_Global_Role', 'Mage_Api2_Model_Resource_Acl_Global_Role'); - } - - /** - * Add filter by admin user id and join table with appropriate information - * - * @param int $id Admin user id - * @return Mage_Api2_Model_Resource_Acl_Global_Role_Collection - */ - public function addFilterByAdminId($id) - { - $this->getSelect() - ->joinInner( - array('acl_global_role_user' => $this->getTable('api2_acl_user')), - 'main_table.entity_id = acl_global_role_user.role_id', - array('admin_id' => 'acl_global_role_user.admin_id')) - ->where('acl_global_role_user.admin_id = ?', $id, Zend_Db::INT_TYPE); - - return $this; - } -} diff --git a/app/code/core/Mage/Api2/Model/Resource/Acl/Global/Rule.php b/app/code/core/Mage/Api2/Model/Resource/Acl/Global/Rule.php deleted file mode 100644 index 781ba99654075e426df22f76570829bbdb4668d5..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Resource/Acl/Global/Rule.php +++ /dev/null @@ -1,45 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 global ACL rule resource model - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Model_Resource_Acl_Global_Rule extends Mage_Core_Model_Resource_Db_Abstract -{ - /** - * Initialize resource model - * - * @return void - */ - protected function _construct() - { - $this->_init('api2_acl_rule', 'entity_id'); - } -} diff --git a/app/code/core/Mage/Api2/Model/Resource/Acl/Global/Rule/Collection.php b/app/code/core/Mage/Api2/Model/Resource/Acl/Global/Rule/Collection.php deleted file mode 100644 index 4a9ef92068775e1b02f5087cdf2d0d45e4d731f3..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Resource/Acl/Global/Rule/Collection.php +++ /dev/null @@ -1,57 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Api2 global ACL rule resource collection model - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Model_Resource_Acl_Global_Rule_Collection extends Mage_Core_Model_Resource_Db_Collection_Abstract -{ - /** - * Initialize collection model - * - * @return void - */ - protected function _construct() - { - $this->_init('Mage_Api2_Model_Acl_Global_Rule', 'Mage_Api2_Model_Resource_Acl_Global_Rule'); - } - - /** - * Add filtering by role ID - * - * @param int $roleId - * @return Mage_Api2_Model_Resource_Acl_Global_Rule_Collection - */ - public function addFilterByRoleId($roleId) - { - $this->addFilter('role_id', $roleId, 'public'); - return $this; - } -} diff --git a/app/code/core/Mage/Api2/Model/Resource/Setup.php b/app/code/core/Mage/Api2/Model/Resource/Setup.php deleted file mode 100644 index 06292b4281b877ec643c6446ebf84f39062b3f4d..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Resource/Setup.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 setup model - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Model_Resource_Setup extends Mage_Core_Model_Resource_Setup -{ -} diff --git a/app/code/core/Mage/Api2/Model/Resource/Validator.php b/app/code/core/Mage/Api2/Model/Resource/Validator.php deleted file mode 100644 index b81e20cd15a2e10a1f238d5349a412d55463f6a7..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Resource/Validator.php +++ /dev/null @@ -1,102 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 Abstarct Validator - * - * This is an object to which we encapsulate all business logic of validation and different invariants. - * But instead of different validators, we group all logic in one class but in different methods. - * - * If fails validation, then validation method returns false, and - * getErrors() will return an array of errors that explain why the - * validation failed. - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -abstract class Mage_Api2_Model_Resource_Validator -{ - /** - * Array of validation failure errors. - * - * @var array - */ - protected $_errors = array(); - - /** - * Set an array of errors - * - * @param array $data - * @return Mage_Api2_Model_Resource_Validator - */ - protected function _setErrors(array $data) - { - $this->_errors = array_values($data); - return $this; - } - - /** - * Add errors - * - * @param array $errors - * @return Mage_Api2_Model_Resource_Validator - */ - protected function _addErrors($errors) - { - foreach ($errors as $error) { - $this->_addError($error); - } - return $this; - } - - /** - * Add error - * - * @param string $error - * @return Mage_Api2_Model_Resource_Validator - */ - protected function _addError($error) - { - $this->_errors[] = $error; - return $this; - } - - /** - * Returns an array of errors that explain why the most recent isValidData() - * call returned false. The array keys are validation failure error identifiers, - * and the array values are the corresponding human-readable error strings. - * - * If isValidData() was never called or if the most recent isValidData() call - * returned true, then this method returns an empty array. - * - * @return array - */ - public function getErrors() - { - return $this->_errors; - } -} diff --git a/app/code/core/Mage/Api2/Model/Resource/Validator/Eav.php b/app/code/core/Mage/Api2/Model/Resource/Validator/Eav.php deleted file mode 100644 index e750d8b5ac23fb018f88fc80633205a2d0b6f63d..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Resource/Validator/Eav.php +++ /dev/null @@ -1,249 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 EAV Validator - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Model_Resource_Validator_Eav extends Mage_Api2_Model_Resource_Validator -{ - /** - * Config node key of current validator - */ - const CONFIG_NODE_KEY = 'eav'; - - /** - * Form path - * - * @var string - */ - protected $_formPath; - - /** - * Entity model - * - * @var Mage_Core_Model_Abstract - */ - protected $_entity; - - /** - * Form code - * - * @var string - */ - protected $_formCode; - - /** - * Eav form model - * - * @var Mage_Eav_Model_Form - */ - protected $_eavForm; - - /** - * Construct. Set all depends. - * - * Required parameteres for options: - * - resource - * - * @param array $options - * @throws Exception If passed parameter 'resource' is wrong - * @throws Exception If config parameter 'formPath' is empty - * @throws Exception If config parameter 'formCode' is empty - * @throws Exception If config parameter 'entity' is wrong - * @throws Exception If entity is not model - * @throws Exception If eav form is not found - */ - public function __construct($options) - { - if (!isset($options['resource']) || !$options['resource'] instanceof Mage_Api2_Model_Resource) { - throw new Exception("Passed parameter 'resource' is wrong."); - } - $resource = $options['resource']; - $userType = $resource->getUserType(); - - $validationConfig = $resource->getConfig()->getValidationConfig( - $resource->getResourceType(), self::CONFIG_NODE_KEY); - - if (empty($validationConfig[$userType]['form_model'])) { - throw new Exception("Config parameter 'formPath' is empty."); - } - $this->_formPath = $validationConfig[$userType]['form_model']; - - if (empty($validationConfig[$userType]['form_code'])) { - throw new Exception("Config parameter 'formCode' is empty."); - } - $this->_formCode = $validationConfig[$userType]['form_code']; - - if (empty($validationConfig[$userType]['entity_model'])) { - throw new Exception("Config parameter 'entity' is wrong."); - } - $this->_entity = Mage::getModel($validationConfig[$userType]['entity_model']); - if (empty($this->_entity) || !$this->_entity instanceof Mage_Core_Model_Abstract) { - throw new Exception("Entity is not model."); - } - - $this->_eavForm = Mage::getModel($this->_formPath); - if (empty($this->_eavForm) || !$this->_eavForm instanceof Mage_Eav_Model_Form) { - throw new Exception("Eav form '{$this->_formPath}' is not found."); - } - $this->_eavForm->setEntity($this->_entity) - ->setFormCode($this->_formCode) - ->ignoreInvisible(false); - } - - /** - * Validate attribute value for attributes with source models - * - * @param Mage_Eav_Model_Entity_Attribute_Abstract $attribute - * @param mixed $attrValue - * @return array|bool - */ - protected function _validateAttributeWithSource(Mage_Eav_Model_Entity_Attribute_Abstract $attribute, $attrValue) - { - $errors = array(); - - // validate attributes with source models - if (null !== $attrValue && $attribute->getSourceModel()) { - if ('multiselect' !== $attribute->getFrontendInput() && is_array($attrValue)) { - return array('Invalid value type for ' . $attribute->getAttributeCode()); - } - $possibleValues = $attribute->getSource()->getAllOptions(false); - - foreach ((array) $attrValue as $value) { - if (is_scalar($value)) { - $value = (string) $value; - $isValid = false; - foreach ($possibleValues as $optionData) { - // comparison without types check is performed only when both values are numeric - $useStrictMode = !(is_numeric($value) && is_numeric($optionData['value'])); - $isValid = $useStrictMode ? $value === $optionData['value'] : $value == $optionData['value']; - if ($isValid) { - break; - } - } - if (!$isValid) { - $errors[] = 'Invalid value "' . $value . '" for '. $attribute->getAttributeCode(); - } - } else { - $errors[] = 'Invalid value type for ' . $attribute->getAttributeCode(); - } - } - } - return $errors ? $errors : true; - } - - /** - * Filter request data. - * - * @param array $data - * @return array Filtered data - */ - public function filter(array $data) - { - return array_intersect_key($this->_eavForm->extractData($this->_eavForm->prepareRequest($data)), $data); - } - - /** - * Validate entity. - * If the $partial parameter is TRUE, then we validate only those parameters that were passed. - * - * If fails validation, then this method returns false, and - * getErrors() will return an array of errors that explain why the - * validation failed. - * - * @param array $data - * @param bool $partial - * @return bool - */ - public function isValidData(array $data, $partial = false) - { - $errors = array(); - foreach ($this->_eavForm->getAttributes() as $attribute) { - if ($partial && !array_key_exists($attribute->getAttributeCode(), $data)) { - continue; - } - if ($this->_eavForm->ignoreInvisible() && !$attribute->getIsVisible()) { - continue; - } - $attrValue = isset($data[$attribute->getAttributeCode()]) ? $data[$attribute->getAttributeCode()] : null; - - $result = Mage_Eav_Model_Attribute_Data::factory($attribute, $this->_eavForm->getEntity()) - ->setExtractedData($data) - ->validateValue($attrValue); - - if ($result !== true) { - $errors = array_merge($errors, $result); - } else { - $result = $this->_validateAttributeWithSource($attribute, $attrValue); - - if (true !== $result) { - $errors = array_merge($errors, $result); - } - } - } - $this->_setErrors($errors); - - return $errors ? false : true; - } - - /** - * Returns an array of errors - * - * @return array - */ - public function getErrors() - { - // business asked to avoid additional validation message, so we filter it here - $errors = array(); - $helper = Mage::helper('Mage_Eav_Helper_Data'); - $requiredAttrs = array(); - $isRequiredRE = '/^' . str_replace('%s', '(.+)', preg_quote(Mage::helper('Mage_Eav_Helper_Data')->__('"%s" is a required value.'))) . '$/'; - $greaterThanRE = '/^' . str_replace( - '%s', '(.+)', preg_quote(Mage::helper('Mage_Eav_Helper_Data')->__('"%s" length must be equal or greater than %s characters.')) - ) . '$/'; - - // find all required attributes labels - foreach ($this->_errors as $error) { - if (preg_match($isRequiredRE, $error, $matches)) { - $requiredAttrs[$matches[1]] = true; - } - } - // exclude additional messages for required attributes been failed - foreach ($this->_errors as $error) { - if (preg_match($isRequiredRE, $error) - || !preg_match($greaterThanRE, $error, $matches) - || !isset($requiredAttrs[$matches[1]]) - ) { - $errors[] = $error; - } - } - return $errors; - } -} diff --git a/app/code/core/Mage/Api2/Model/Resource/Validator/Fields.php b/app/code/core/Mage/Api2/Model/Resource/Validator/Fields.php deleted file mode 100644 index 7220cc44ba4cd988fbc32abe5d71e5beddcafba1..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Resource/Validator/Fields.php +++ /dev/null @@ -1,186 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 Fields Validator - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Model_Resource_Validator_Fields extends Mage_Api2_Model_Resource_Validator -{ - /** - * Config node key of current validator - */ - const CONFIG_NODE_KEY = 'fields'; - - /** - * Resource - * - * @var Mage_Api2_Model_Resource - */ - protected $_resource; - - /** - * List of Validators (Zend_Validate_Interface) - * The key is a field name, a value is validator for this field - * - * @var array - */ - protected $_validators; - - /** - * List of required fields - * - * @var array - */ - protected $_requiredFields; - - /** - * Construct. Set all depends. - * - * Required parameteres for options: - * - resource - * - * @param array $options - * @throws Exception If passed parameter 'resource' is wrong - */ - public function __construct($options) - { - if (!isset($options['resource']) || !$options['resource'] instanceof Mage_Api2_Model_Resource) { - throw new Exception("Passed parameter 'resource' is wrong."); - } - $this->_resource = $options['resource']; - - $validationConfig = $this->_resource->getConfig()->getValidationConfig( - $this->_resource->getResourceType(), self::CONFIG_NODE_KEY); - if (!is_array($validationConfig)) { - $validationConfig = array(); - } - $this->_buildValidatorsChain($validationConfig); - } - - /** - * Build validator chain with config data - * - * @param array $validationConfig - * @throws Exception If validator type is not set - * @throws Exception If validator is not exist - */ - protected function _buildValidatorsChain(array $validationConfig) - { - foreach ($validationConfig as $field => $validatorsConfig) { - if (count($validatorsConfig)) { - $chainForOneField = new Zend_Validate(); - foreach ($validatorsConfig as $validatorName => $validatorConfig) { - // it is required field - if ('required' == $validatorName && 1 == $validatorConfig) { - $this->_requiredFields[] = $field; - continue; - } - // instantiation of the validator class - if (!isset($validatorConfig['type'])) { - throw new Exception("Validator type is not set for {$validatorName}"); - } - $validator = $this->_getValidatorInstance( - $validatorConfig['type'], - !empty($validatorConfig['options']) ? $validatorConfig['options'] : array() - ); - // set custom message - if (isset($validatorConfig['message'])) { - $validator->setMessage($validatorConfig['message']); - } - // add to list of validators - $chainForOneField->addValidator($validator); - } - $this->_validators[$field] = $chainForOneField; - } - } - } - - /** - * Get validator object instance - * Override the method if we need to use not only Zend validators! - * - * @param string $type - * @param array $options - * @return Zend_Validate_Interface - * @throws Exception If validator is not exist - */ - protected function _getValidatorInstance($type, $options) - { - $validatorClass = 'Zend_Validate_' . $type; - if (!class_exists($validatorClass)) { - throw new Exception("Validator {$type} is not exist"); - } - return new $validatorClass($options); - } - - /** - * Validate data. - * If fails validation, then this method returns false, and - * getErrors() will return an array of errors that explain why the - * validation failed. - * - * @param array $data - * @param bool $isPartial - * @return bool - */ - public function isValidData(array $data, $isPartial = false) - { - $isValid = true; - - // required fields - if (!$isPartial && count($this->_requiredFields) > 0) { - $notEmptyValidator = new Zend_Validate_NotEmpty(); - foreach ($this->_requiredFields as $requiredField) { - if (!$notEmptyValidator->isValid(isset($data[$requiredField]) ? $data[$requiredField] : null)) { - $isValid = false; - foreach ($notEmptyValidator->getMessages() as $message) { - $this->_addError(sprintf('%s: %s', $requiredField, $message)); - } - } - } - } - - // fields rules - foreach ($data as $field => $value) { - if (isset($this->_validators[$field])) { - /* @var $validator Zend_Validate_Interface */ - $validator = $this->_validators[$field]; - if (!$validator->isValid($value)) { - $isValid = false; - foreach ($validator->getMessages() as $message) { - $this->_addError(sprintf('%s: %s', $field, $message)); - } - } - } - } - - return $isValid; - } -} diff --git a/app/code/core/Mage/Api2/Model/Route/Abstract.php b/app/code/core/Mage/Api2/Model/Route/Abstract.php deleted file mode 100644 index d6bfca85a8b27a876df5246293fa640d243e3da7..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Route/Abstract.php +++ /dev/null @@ -1,99 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Webservice apia2 route abstract - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -abstract class Mage_Api2_Model_Route_Abstract extends Zend_Controller_Router_Route -{ - /**#@+ - * Names for Zend_Controller_Router_Route::__construct params - */ - const PARAM_ROUTE = 'route'; - const PARAM_DEFAULTS = 'defaults'; - const PARAM_REQS = 'reqs'; - const PARAM_TRANSLATOR = 'translator'; - const PARAM_LOCALE = 'locale'; - /**#@- */ - - /* - * Default values of parent::__construct() params - * - * @var array - */ - protected $_paramsDefaultValues = array( - self::PARAM_ROUTE => null, - self::PARAM_DEFAULTS => array(), - self::PARAM_REQS => array(), - self::PARAM_TRANSLATOR => null, - self::PARAM_LOCALE => null - ); - - /** - * Process construct param and call parent::__construct() with params - * - * @param array $arguments - */ - public function __construct(array $arguments) - { - parent::__construct( - $this->_getArgumentValue(self::PARAM_ROUTE, $arguments), - $this->_getArgumentValue(self::PARAM_DEFAULTS, $arguments), - $this->_getArgumentValue(self::PARAM_REQS, $arguments), - $this->_getArgumentValue(self::PARAM_TRANSLATOR, $arguments), - $this->_getArgumentValue(self::PARAM_LOCALE, $arguments) - ); - } - - /** - * Retrieve argument value - * - * @param string $name argument name - * @param array $arguments - * @return mixed - */ - protected function _getArgumentValue($name, array $arguments) - { - return isset($arguments[$name]) ? $arguments[$name] : $this->_paramsDefaultValues[$name]; - } - - /** - * Matches a Request with parts defined by a map. Assigns and - * returns an array of variables on a successful match. - * - * @param Mage_Api2_Model_Request $request - * @param boolean $partial Partial path matching - * @return array|bool An array of assigned values or a boolean false on a mismatch - */ - public function match($request, $partial = false) - { - return parent::match(ltrim($request->getPathInfo(), $this->_urlDelimiter), $partial); - } -} diff --git a/app/code/core/Mage/Api2/Model/Route/ApiType.php b/app/code/core/Mage/Api2/Model/Route/ApiType.php deleted file mode 100644 index 52059d68a3a4a7935d5c357ecffc2e68bc350d9c..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Route/ApiType.php +++ /dev/null @@ -1,57 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Webservice Api2 Route to find out API type from request - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Model_Route_ApiType extends Mage_Api2_Model_Route_Abstract implements Mage_Api2_Model_Route_Interface -{ - /** - * API url template with API type variable - */ - const API_ROUTE = 'api/:api_type'; - - /** - * Prepares the route for mapping by splitting (exploding) it - * to a corresponding atomic parts. These parts are assigned - * a position which is later used for matching and preparing values. - * - * @param string $route Map used to match with later submitted URL path - * @param array $defaults Defaults for map variables with keys as variable names - * @param array $reqs Regular expression requirements for variables (keys as variable names) - * @param Zend_Translate $translator Translator to use for this instance - * @param mixed $locale - */ - public function __construct($route, $defaults = array(), $reqs = array(), Zend_Translate $translator = null, - $locale = null - ) { - parent::__construct(array(Mage_Api2_Model_Route_Abstract::PARAM_ROUTE => self::API_ROUTE)); - } -} diff --git a/app/code/core/Mage/Api2/Model/Route/Interface.php b/app/code/core/Mage/Api2/Model/Route/Interface.php deleted file mode 100644 index 4ac433eb956f7ef1734f1abb7831290c44979ca7..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Route/Interface.php +++ /dev/null @@ -1,45 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Webservice apia2 route interface - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -interface Mage_Api2_Model_Route_Interface -{ - /** - * Matches a Request with parts defined by a map. Assigns and - * returns an array of variables on a successful match. - * - * @param Mage_Api2_Model_Request $request - * @param boolean $partial Partial path matching - * @return array|false An array of assigned values or a false on a mismatch - */ - public function match($request, $partial = false); -} diff --git a/app/code/core/Mage/Api2/Model/Route/Rest.php b/app/code/core/Mage/Api2/Model/Route/Rest.php deleted file mode 100644 index 6e5de99896d79cf32002b3f2da5851c61a5e3419..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Route/Rest.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Webservice apia2 REST route - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Model_Route_Rest extends Mage_Api2_Model_Route_Abstract implements Mage_Api2_Model_Route_Interface -{ -} diff --git a/app/code/core/Mage/Api2/Model/Router.php b/app/code/core/Mage/Api2/Model/Router.php deleted file mode 100644 index f56b490da6778acf315a00c77bf8c1b036cac591..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Router.php +++ /dev/null @@ -1,122 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Webservice api2 router model - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Model_Router -{ - /** - * Routes which are stored in module config files api2.xml - * - * @var array - */ - protected $_routes = array(); - - /** - * Set routes - * - * @param array $routes - * @return Mage_Api2_Model_Router - */ - public function setRoutes(array $routes) - { - $this->_routes = $routes; - - return $this; - } - - /** - * Get routes - * - * @return array - */ - public function getRoutes() - { - return $this->_routes; - } - - /** - * Route the Request, the only responsibility of the class - * Find route that match current URL, set parameters of the route to Request object - * - * @param Mage_Api2_Model_Request $request - * @return Mage_Api2_Model_Request - * @throws Mage_Api2_Exception - */ - public function route(Mage_Api2_Model_Request $request) - { - $isMatched = false; - - /** @var $route Mage_Api2_Model_Route_Interface */ - foreach ($this->getRoutes() as $route) { - if ($params = $route->match($request)) { - $request->setParams($params); - $isMatched = true; - break; - } - } - if (!$isMatched) { - throw new Mage_Api2_Exception('Request does not match any route.', Mage_Api2_Model_Server::HTTP_NOT_FOUND); - } - if (!$request->getResourceType() || !$request->getModel()) { - throw new Mage_Api2_Exception('Matched resource is not properly set.', - Mage_Api2_Model_Server::HTTP_INTERNAL_ERROR); - } - return $request; - } - - /** - * Set API type to request as a result of one pass route - * - * @param Mage_Api2_Model_Request $request - * @param boolean $trimApiTypePath OPTIONAL If TRUE - /api/:api_type part of request path info will be trimmed - * @return Mage_Api2_Model_Router - * @throws Mage_Api2_Exception - */ - public function routeApiType(Mage_Api2_Model_Request $request, $trimApiTypePath = true) - { - /** @var $apiTypeRoute Mage_Api2_Model_Route_ApiType */ - $apiTypeRoute = Mage::getModel('Mage_Api2_Model_Route_ApiType'); - - if (!($apiTypeMatch = $apiTypeRoute->match($request, true))) { - throw new Mage_Api2_Exception('Request does not match type route.', Mage_Api2_Model_Server::HTTP_NOT_FOUND); - } - // Trim matched URI path for next routes - if ($trimApiTypePath) { - $matchedPathLength = strlen('/' . ltrim($apiTypeRoute->getMatchedPath(), '/')); - - $request->setPathInfo(substr($request->getPathInfo(), $matchedPathLength)); - } - $request->setParam('api_type', $apiTypeMatch['api_type']); - - return $this; - } -} diff --git a/app/code/core/Mage/Api2/Model/Server.php b/app/code/core/Mage/Api2/Model/Server.php deleted file mode 100644 index 5feb31ba084aaba268d1069487332dfa0340a523..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/Model/Server.php +++ /dev/null @@ -1,315 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 Server - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Model_Server -{ - /** - * Api2 REST type - */ - const API_TYPE_REST = 'rest'; - - /**#@+ - * HTTP Response Codes - */ - const HTTP_OK = 200; - const HTTP_CREATED = 201; - const HTTP_MULTI_STATUS = 207; - const HTTP_BAD_REQUEST = 400; - const HTTP_UNAUTHORIZED = 401; - const HTTP_FORBIDDEN = 403; - const HTTP_NOT_FOUND = 404; - const HTTP_METHOD_NOT_ALLOWED = 405; - const HTTP_NOT_ACCEPTABLE = 406; - const HTTP_INTERNAL_ERROR = 500; - /**#@- */ - - /** - * List of api types - * - * @var array - */ - protected static $_apiTypes = array(self::API_TYPE_REST); - - /** - * @var Mage_Api2_Model_Auth_User_Abstract - */ - protected $_authUser; - - /** - * Run server - */ - public function run() - { - // can not use response object case - try { - /** @var $response Mage_Api2_Model_Response */ - $response = Mage::getSingleton('Mage_Api2_Model_Response'); - } catch (Exception $e) { - Mage::logException($e); - - if (!headers_sent()) { - header('HTTP/1.1 ' . self::HTTP_INTERNAL_ERROR); - } - echo 'Service temporary unavailable'; - return; - } - // can not render errors case - try { - /** @var $request Mage_Api2_Model_Request */ - $request = Mage::getSingleton('Mage_Api2_Model_Request'); - /** @var $renderer Mage_Api2_Model_Renderer_Interface */ - $renderer = Mage_Api2_Model_Renderer::factory($request->getAcceptTypes()); - } catch (Exception $e) { - Mage::logException($e); - - $response->setHttpResponseCode(self::HTTP_INTERNAL_ERROR) - ->setBody('Service temporary unavailable') - ->sendResponse(); - return; - } - // default case - try { - /** @var $apiUser Mage_Api2_Model_Auth_User_Abstract */ - $apiUser = $this->_authenticate($request); - - $this->_route($request) - ->_allow($request, $apiUser) - ->_dispatch($request, $response, $apiUser); - - if ($response->getHttpResponseCode() == self::HTTP_CREATED) { - // TODO: Re-factor this after _renderException refactoring - throw new Mage_Api2_Exception('Resource was partially created', self::HTTP_CREATED); - } - //NOTE: At this moment Renderer already could have some content rendered, so we should replace it - if ($response->isException()) { - throw new Mage_Api2_Exception('Unhandled simple errors.', self::HTTP_INTERNAL_ERROR); - } - } catch (Exception $e) { - Mage::logException($e); - $this->_renderException($e, $renderer, $response); - } - - $response->sendResponse(); - } - - /** - * Make internal call to api - * - * @param Mage_Api2_Model_Request $request - * @param Mage_Api2_Model_Response $response - * @return Mage_Api2_Model_Response - */ - public function internalCall(Mage_Api2_Model_Request $request, Mage_Api2_Model_Response $response) - { - $apiUser = $this->_getAuthUser(); - $this->_route($request) - ->_allow($request, $apiUser) - ->_dispatch($request, $response, $apiUser); - } - - /** - * Authenticate user - * - * @throws Exception - * @param Mage_Api2_Model_Request $request - * @return Mage_Api2_Model_Auth_User_Abstract - */ - protected function _authenticate(Mage_Api2_Model_Request $request) - { - /** @var $authManager Mage_Api2_Model_Auth */ - $authManager = Mage::getModel('Mage_Api2_Model_Auth'); - - $this->_setAuthUser($authManager->authenticate($request)); - return $this->_getAuthUser(); - } - - /** - * Set auth user - * - * @throws Exception - * @param Mage_Api2_Model_Auth_User_Abstract $authUser - * @return Mage_Api2_Model_Server - */ - protected function _setAuthUser(Mage_Api2_Model_Auth_User_Abstract $authUser) - { - $this->_authUser = $authUser; - return $this; - } - - /** - * Retrieve existing auth user - * - * @throws Exception - * @return Mage_Api2_Model_Auth_User_Abstract - */ - protected function _getAuthUser() - { - if (!$this->_authUser) { - throw new Exception("Mage_Api2_Model_Server::internalCall() seems to be executed " - . "before Mage_Api2_Model_Server::run()"); - } - return $this->_authUser; - } - - /** - * Set all routes of the given api type to Route object - * Find route that match current URL, set parameters of the route to Request object - * - * @param Mage_Api2_Model_Request $request - * @return Mage_Api2_Model_Server - */ - protected function _route(Mage_Api2_Model_Request $request) - { - /** @var $router Mage_Api2_Model_Router */ - $router = Mage::getModel('Mage_Api2_Model_Router'); - - $router->routeApiType($request, true) - ->setRoutes($this->_getConfig()->getRoutes($request->getApiType())) - ->route($request); - - return $this; - } - - /** - * Global ACL processing - * - * @param Mage_Api2_Model_Request $request - * @param Mage_Api2_Model_Auth_User_Abstract $apiUser - * @return Mage_Api2_Model_Server - * @throws Mage_Api2_Exception - */ - protected function _allow(Mage_Api2_Model_Request $request, Mage_Api2_Model_Auth_User_Abstract $apiUser) - { - /** @var $globalAcl Mage_Api2_Model_Acl_Global */ - $globalAcl = Mage::getModel('Mage_Api2_Model_Acl_Global'); - - if (!$globalAcl->isAllowed($apiUser, $request->getResourceType(), $request->getOperation())) { - throw new Mage_Api2_Exception('Access denied', self::HTTP_FORBIDDEN); - } - return $this; - } - - /** - * Load class file, instantiate resource class, set parameters to the instance, run resource internal dispatch - * method - * - * @param Mage_Api2_Model_Request $request - * @param Mage_Api2_Model_Response $response - * @param Mage_Api2_Model_Auth_User_Abstract $apiUser - * @return Mage_Api2_Model_Server - */ - protected function _dispatch( - Mage_Api2_Model_Request $request, - Mage_Api2_Model_Response $response, - Mage_Api2_Model_Auth_User_Abstract $apiUser - ) - { - /** @var $dispatcher Mage_Api2_Model_Dispatcher */ - $dispatcher = Mage::getModel('Mage_Api2_Model_Dispatcher'); - $dispatcher->setApiUser($apiUser)->dispatch($request, $response); - - return $this; - } - - /** - * Get api2 config instance - * - * @return Mage_Api2_Model_Config - */ - protected function _getConfig() - { - return Mage::getModel('Mage_Api2_Model_Config'); - } - - /** - * Process thrown exception - * Generate and set HTTP response code, error message to Response object - * - * @param Exception $exception - * @param Mage_Api2_Model_Renderer_Interface $renderer - * @param Mage_Api2_Model_Response $response - * @return Mage_Api2_Model_Server - */ - protected function _renderException(Exception $exception, Mage_Api2_Model_Renderer_Interface $renderer, - Mage_Api2_Model_Response $response - ) { - if ($exception instanceof Mage_Api2_Exception && $exception->getCode()) { - $httpCode = $exception->getCode(); - } else { - $httpCode = self::HTTP_INTERNAL_ERROR; - } - try { - //add last error to stack - $response->setException($exception); - - $messages = array(); - - /** @var Exception $exception */ - foreach ($response->getException() as $exception) { - $message = array('code' => $exception->getCode(), 'message' => $exception->getMessage()); - - if (Mage::getIsDeveloperMode()) { - $message['trace'] = $exception->getTraceAsString(); - } - $messages['messages']['error'][] = $message; - } - //set HTTP Code of last error, Content-Type and Body - $response->setBody($renderer->render($messages)); - $response->setHeader('Content-Type', sprintf( - '%s; charset=%s', $renderer->getMimeType(), Mage_Api2_Model_Response::RESPONSE_CHARSET - )); - } catch (Exception $e) { - //tunnelling of 406(Not acceptable) error - $httpCode = $e->getCode() == self::HTTP_NOT_ACCEPTABLE //$e->getCode() can result in one more loop - ? self::HTTP_NOT_ACCEPTABLE // of try..catch - : self::HTTP_INTERNAL_ERROR; - - //if error appeared in "error rendering" process then show it in plain text - $response->setBody($e->getMessage()); - $response->setHeader('Content-Type', 'text/plain; charset=' . Mage_Api2_Model_Response::RESPONSE_CHARSET); - } - $response->setHttpResponseCode($httpCode); - - return $this; - } - - /** - * Retrieve api types - * - * @return array - */ - public static function getApiTypes() - { - return self::$_apiTypes; - } -} diff --git a/app/code/core/Mage/Api2/controllers/Adminhtml/Api2/AttributeController.php b/app/code/core/Mage/Api2/controllers/Adminhtml/Api2/AttributeController.php deleted file mode 100644 index 58128346931a6200f8b2b2b127f3a6e320c21c0b..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/controllers/Adminhtml/Api2/AttributeController.php +++ /dev/null @@ -1,148 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 attribute controller - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Adminhtml_Api2_AttributeController extends Mage_Adminhtml_Controller_Action -{ - /** - * Show user types grid - */ - public function indexAction() - { - $this->_title($this->__('System')) - ->_title($this->__('Web Services')) - ->_title($this->__('REST Attributes')); - - $this->loadLayout()->_setActiveMenu('Mage_Api2::system_api_rest_attributes'); - - $this->_addBreadcrumb($this->__('Web services'), $this->__('Web services')) - ->_addBreadcrumb($this->__('REST Attributes'), $this->__('REST Attributes')) - ->_addBreadcrumb($this->__('Attributes'), $this->__('Attributes')); - - $this->renderLayout(); - } - - /** - * Edit role - */ - public function editAction() - { - $this->loadLayout() - ->_setActiveMenu('Mage_Api2::system_api_rest_attributes'); - - $type = $this->getRequest()->getParam('type'); - - $userTypes = Mage_Api2_Model_Auth_User::getUserTypes(); - if (!isset($userTypes[$type])) { - $this->_getSession()->addError($this->__('User type "%s" not found.', $type)); - $this->_redirect('*/*/'); - return; - } - - $this->_title($this->__('System')) - ->_title($this->__('Web Services')) - ->_title($this->__('REST ACL Attributes')); - - $title = $this->__('Edit %s ACL attribute rules', $userTypes[$type]); - $this->_title($title); - $this->_addBreadcrumb($title, $title); - - $this->renderLayout(); - } - - /** - * Save role - */ - public function saveAction() - { - $request = $this->getRequest(); - - $type = $request->getParam('type'); - - if (!$type) { - $this->_getSession()->addError( - $this->__('User type "%s" no longer exists', $type)); - $this->_redirect('*/*/'); - return; - } - - /** @var $session Mage_Adminhtml_Model_Session */ - $session = $this->_getSession(); - - try { - /** @var $ruleTree Mage_Api2_Model_Acl_Global_Rule_Tree */ - $ruleTree = Mage::getSingleton( - 'Mage_Api2_Model_Acl_Global_Rule_Tree', - array('options' => array('type' => Mage_Api2_Model_Acl_Global_Rule_Tree::TYPE_ATTRIBUTE)) - ); - - /** @var $attribute Mage_Api2_Model_Acl_Filter_Attribute */ - $attribute = Mage::getModel('Mage_Api2_Model_Acl_Filter_Attribute'); - - /** @var $collection Mage_Api2_Model_Resource_Acl_Filter_Attribute_Collection */ - $collection = $attribute->getCollection(); - $collection->addFilterByUserType($type); - - /** @var $model Mage_Api2_Model_Acl_Filter_Attribute */ - foreach ($collection as $model) { - $model->delete(); - } - - foreach ($ruleTree->getPostResources() as $resourceId => $operations) { - if (Mage_Api2_Model_Acl_Global_Rule::RESOURCE_ALL === $resourceId) { - $attribute->setUserType($type) - ->setResourceId($resourceId) - ->save(); - } else { - foreach ($operations as $operation => $attributes) { - $attribute->setId(null) - ->isObjectNew(true); - - $attribute->setUserType($type) - ->setResourceId($resourceId) - ->setOperation($operation) - ->setAllowedAttributes(implode(',', array_keys($attributes))) - ->save(); - } - } - } - - $session->addSuccess($this->__('The attribute rules were saved.')); - } catch (Mage_Core_Exception $e) { - $session->addError($e->getMessage()); - } catch (Exception $e) { - $session->addException($e, $this->__('An error occurred while saving attribute rules.')); - } - - $this->_redirect('*/*/edit', array('type' => $type)); - } -} diff --git a/app/code/core/Mage/Api2/controllers/Adminhtml/Api2/RoleController.php b/app/code/core/Mage/Api2/controllers/Adminhtml/Api2/RoleController.php deleted file mode 100644 index 1bb3db8518ca3944704870aac606f164642708dc..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/controllers/Adminhtml/Api2/RoleController.php +++ /dev/null @@ -1,341 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 roles controller - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api2_Adminhtml_Api2_RoleController extends Mage_Adminhtml_Controller_Action -{ - /** - * Show grid - */ - public function indexAction() - { - $this->_title($this->__('System')) - ->_title($this->__('Web Services')) - ->_title($this->__('REST Roles')); - - $this->loadLayout()->_setActiveMenu('Mage_Api2::system_api_rest_roles'); - $this->_addBreadcrumb($this->__('Web services'), $this->__('Web services')); - $this->_addBreadcrumb($this->__('REST Roles'), $this->__('REST Roles')); - $this->_addBreadcrumb($this->__('Roles'), $this->__('Roles')); - - $this->renderLayout(); - } - - /** - * Updating grid by ajax - */ - public function gridAction() - { - $this->loadLayout(); - $this->renderLayout(); - } - - /** - * Updating users grid by ajax - */ - public function usersGridAction() - { - $id = $this->getRequest()->getParam('id', false); - - $this->loadLayout(); - /** @var $grid Mage_Api2_Block_Adminhtml_Roles_Tab_Users */ - $grid = $this->getLayout()->getBlock('adminhtml.role.edit.tab.users'); - $grid->setUsers($this->_getUsers($id)); - - $this->renderLayout(); - } - - /** - * Create new role - */ - public function newAction() - { - $this->_title($this->__('System')) - ->_title($this->__('Web Services')) - ->_title($this->__('Rest Roles')); - - $this->loadLayout()->_setActiveMenu('Mage_Api2::system_api_rest_roles'); - $this->_addBreadcrumb($this->__('Web services'), $this->__('Web services')); - $this->_addBreadcrumb($this->__('REST Roles'), $this->__('REST Roles')); - $this->_addBreadcrumb($this->__('Roles'), $this->__('Roles')); - - $breadCrumb = $this->__('Add New Role'); - $breadCrumbTitle = $this->__('Add New Role'); - $this->_title($this->__('New Role')); - - $this->_addBreadcrumb($breadCrumb, $breadCrumbTitle); - - $this->renderLayout(); - } - - /** - * Edit role - */ - public function editAction() - { - $id = (int) $this->getRequest()->getParam('id'); - /** @var $role Mage_Api2_Model_Acl_Global_Role */ - $role = Mage::getModel('Mage_Api2_Model_Acl_Global_Role')->load($id); - - if (!$role->getId()) { - $this->_getSession()->addError($this->__('Role "%s" not found.', $id)); - $this->_redirect('*/*/'); - return; - } - - $this->loadLayout()->_setActiveMenu('Mage_Api2::system_api_rest_roles'); - - $this->_title($this->__('System')) - ->_title($this->__('Web Services')) - ->_title($this->__('Rest Roles')); - - $breadCrumb = $this->__('Edit Role'); - $breadCrumbTitle = $this->__('Edit Role'); - $this->_title($this->__('Edit Role')); - $this->_addBreadcrumb($breadCrumb, $breadCrumbTitle); - - /** @var $tabs Mage_Api2_Block_Adminhtml_Roles_Tabs */ - $tabs = $this->getLayout()->getBlock('adminhtml.role.edit.tabs'); - $tabs->setRole($role); - /** @var $child Mage_Adminhtml_Block_Template */ - foreach ($tabs->getChildNames() as $childName) { - $child = $this->getLayout()->getBlock($childName); - if ($child) { - $child->setData('role', $role); - } - } - - /** @var $buttons Mage_Api2_Block_Adminhtml_Roles_Buttons */ - $buttons = $this->getLayout()->getBlock('adminhtml.roles.buttons'); - $buttons->setRole($role); - - /** @var $users Mage_Api2_Block_Adminhtml_Roles_Tab_Users */ - $users = $this->getLayout()->getBlock('adminhtml.role.edit.tab.users'); - $users->setUsers($this->_getUsers($id)); - - //$this->getLayout()->getBlock('adminhtml.role.edit.tab.resources')->getResTreeJson(); - //exit; - - $this->renderLayout(); - } - - /** - * Save role - */ - public function saveAction() - { - $request = $this->getRequest(); - - $id = $request->getParam('id', false); - /** @var $role Mage_Api2_Model_Acl_Global_Role */ - $role = Mage::getModel('Mage_Api2_Model_Acl_Global_Role')->load($id); - - if (!$role->getId() && $id) { - $this->_getSession()->addError( - $this->__('Role "%s" no longer exists', $role->getData('role_name'))); - $this->_redirect('*/*/'); - return; - } - - $roleUsers = $request->getParam('in_role_users', null); - parse_str($roleUsers, $roleUsers); - $roleUsers = array_keys($roleUsers); - - $oldRoleUsers = $this->getRequest()->getParam('in_role_users_old'); - parse_str($oldRoleUsers, $oldRoleUsers); - $oldRoleUsers = array_keys($oldRoleUsers); - - /** @var $session Mage_Adminhtml_Model_Session */ - $session = $this->_getSession(); - - try { - $role->setRoleName($this->getRequest()->getParam('role_name', false)) - ->save(); - - foreach($oldRoleUsers as $oUid) { - $this->_deleteUserFromRole($oUid, $role->getId()); - } - - foreach ($roleUsers as $nRuid) { - $this->_addUserToRole($nRuid, $role->getId()); - } - - /** - * Save rules with resources - */ - /** @var $rule Mage_Api2_Model_Acl_Global_Rule */ - $rule = Mage::getModel('Mage_Api2_Model_Acl_Global_Rule'); - if ($id) { - $collection = $rule->getCollection(); - $collection->addFilterByRoleId($role->getId()); - - /** @var $model Mage_Api2_Model_Acl_Global_Rule */ - foreach ($collection as $model) { - $model->delete(); - } - } - - /** @var $ruleTree Mage_Api2_Model_Acl_Global_Rule_Tree */ - $ruleTree = Mage::getSingleton( - 'Mage_Api2_Model_Acl_Global_Rule_Tree', - array('options' => array('type' => Mage_Api2_Model_Acl_Global_Rule_Tree::TYPE_PRIVILEGE)) - ); - $resources = $ruleTree->getPostResources(); - $id = $role->getId(); - foreach ($resources as $resourceId => $privileges) { - foreach ($privileges as $privilege => $allow) { - if (!$allow) { - continue; - } - - $rule->setId(null) - ->isObjectNew(true); - - $rule->setRoleId($id) - ->setResourceId($resourceId) - ->setPrivilege($privilege) - ->save(); - } - } - - $session->addSuccess($this->__('The role has been saved.')); - } catch (Mage_Core_Exception $e) { - $session->addError($e->getMessage()); - } catch (Exception $e) { - $session->addException($e, $this->__('An error occurred while saving role.')); - } - - $this->_redirect('*/*/edit', array('id'=>$id)); - } - - /** - * Delete role - */ - public function deleteAction() - { - $id = $this->getRequest()->getParam('id', false); - - try { - /** @var $model Mage_Api2_Model_Acl_Global_Role */ - $model = Mage::getModel('Mage_Api2_Model_Acl_Global_Role'); - $model->load($id)->delete(); - $this->_getSession()->addSuccess($this->__('Role has been deleted.')); - } catch (Mage_Core_Exception $e) { - $this->_getSession()->addError($e->getMessage()); - } catch (Exception $e) { - $this->_getSession()->addException($e, $this->__('An error occurred while deleting the role.')); - } - - $this->_redirect("*/*/"); - } - - /** - * Check against ACL - * - * @return bool - */ - protected function _isAllowed() - { - return Mage::getSingleton('Mage_Core_Model_Authorization')->isAllowed('Mage_Api2::rest_roles'); - } - - /** - * Get API2 roles ajax grid action - */ - public function rolesGridAction() - { - /** @var $model Mage_User_Model_User */ - $model = Mage::getModel('Mage_User_Model_User'); - $model->load($this->getRequest()->getParam('user_id')); - - Mage::register('permissions_user', $model); - $this->getResponse() - ->setBody($this->getLayout()->createBlock('Mage_Api2_Block_Adminhtml_Permissions_User_Edit_Tab_Roles')->toHtml()); - } - - /** - * Get users possessing the role - * - * @param int $id - * @return array|mixed - */ - protected function _getUsers($id) - { - if ( $this->getRequest()->getParam('in_role_users') != "" ) { - return $this->getRequest()->getParam('in_role_users'); - } - - /** @var $role Mage_Api2_Model_Acl_Global_Role */ - $role = Mage::getModel('Mage_Api2_Model_Acl_Global_Role'); - $role->setId($id); - - /** @var $resource Mage_Api2_Model_Resource_Acl_Global_Role */ - $resource = $role->getResource(); - $users = $resource->getRoleUsers($role); - - if (sizeof($users) == 0) { - $users = array(); - } - - return $users; - } - - /** - * Take away user role - * - * @param int $adminId - * @param int $roleId - * @return Mage_Api2_Adminhtml_Api2_RoleController - */ - protected function _deleteUserFromRole($adminId, $roleId) - { - /** @var $resourceModel Mage_Api2_Model_Resource_Acl_Global_Role */ - $resourceModel = Mage::getResourceModel('Mage_Api2_Model_Resource_Acl_Global_Role'); - $resourceModel->deleteAdminToRoleRelation($adminId, $roleId); - return $this; - } - - /** - * Give user a role - * - * @param int $adminId - * @param int $roleId - * @return Mage_Api2_Adminhtml_Api2_RoleController - */ - protected function _addUserToRole($adminId, $roleId) - { - /** @var $resourceModel Mage_Api2_Model_Resource_Acl_Global_Role */ - $resourceModel = Mage::getResourceModel('Mage_Api2_Model_Resource_Acl_Global_Role'); - $resourceModel->saveAdminToRoleRelation($adminId, $roleId); - return $this; - } -} diff --git a/app/code/core/Mage/Api2/etc/adminhtml/acl.xml b/app/code/core/Mage/Api2/etc/adminhtml/acl.xml deleted file mode 100644 index fe611c69aecdd7da8f11e30f0c4f95521d52cb21..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/etc/adminhtml/acl.xml +++ /dev/null @@ -1,47 +0,0 @@ -<?xml version="1.0"?> -<!-- -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Academic Free License (AFL 3.0) - * that is bundled with this package in the file LICENSE_AFL.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/afl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) - */ ---> -<config> - <acl> - <resources> - <resource id="Mage_Adminhtml::admin"> - <resource id="Mage_Adminhtml::system"> - <resource id="Mage_Api::api"> - <resource id="Mage_Api2::rest_roles" module="Mage_Api2" title="REST - Roles" sortOrder="30"> - <resource id="Mage_Api2::rest_roles_add" title="Add" sortOrder="10" /> - <resource id="Mage_Api2::rest_roles_edit" title="Edit" sortOrder="20" /> - <resource id="Mage_Api2::delete" title="Delete" sortOrder="30" /> - </resource> - <resource id="Mage_Api2::rest_attributes" module="Mage_Api2" title="REST - Attributes" sortOrder="40"> - <resource id="Mage_Api2::rest_attributes_edit" title="Edit" sortOrder="10" /> - </resource> - </resource> - </resource> - </resource> - </resources> - </acl> -</config> diff --git a/app/code/core/Mage/Api2/etc/config.xml b/app/code/core/Mage/Api2/etc/config.xml deleted file mode 100644 index 13c0b3bf0304112094aa0acaaac53f3c1582527a..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/etc/config.xml +++ /dev/null @@ -1,185 +0,0 @@ -<?xml version="1.0"?> -<!-- -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Academic Free License (AFL 3.0) - * that is bundled with this package in the file LICENSE_AFL.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/afl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) - */ ---> -<config> - <modules> - <Mage_Api2> - <version>1.0.0.0</version> - <active>true</active> - <codePool>core</codePool> - <depends> - <Mage_Core /> - <Mage_Oauth /> - </depends> - </Mage_Api2> - </modules> - <global> - <cache> - <types> - <config_api2 translate="label,description" module="Mage_Api2"> - <label>Web Services Configuration</label> - <description>Web Services definition files (api2.xml).</description> - <tags>CONFIG_API2</tags> - </config_api2> - </types> - </cache> - <resources> - <api2_setup> - <setup> - <module>Mage_Api2</module> - <class>Mage_Api2_Model_Resource_Setup</class> - </setup> - </api2_setup> - </resources> - <events> - <admin_user_save_after> - <observers> - <api2> - <class>Mage_Api2_Model_Observer</class> - <method>saveAdminToRoleRelation</method> - </api2> - </observers> - </admin_user_save_after> - </events> - <api2> - <auth_adapters> - <oauth module="Mage_Api2" translate="label"> - <model>Mage_Api2_Model_Auth_Adapter_Oauth</model> - <label>OAuth</label> - <enabled>1</enabled> - <order>10</order> - </oauth> - </auth_adapters> - <user_types> - <admin> - <model>Mage_Api2_Model_Auth_User_Admin</model> - <allowed>1</allowed> - </admin> - <customer> - <model>Mage_Api2_Model_Auth_User_Customer</model> - <allowed>1</allowed> - </customer> - <guest> - <model>Mage_Api2_Model_Auth_User_Guest</model> - <allowed>1</allowed> - </guest> - </user_types> - <request> - <interpreters> - <!-- JSON --> - <application_json> - <type>application/json</type> - <model>Mage_Api2_Model_Request_Interpreter_Json</model> - </application_json> - - <!-- QUERY --> - <text_plain> - <type>text/plain</type> - <model>Mage_Api2_Model_Request_Interpreter_Query</model> - </text_plain> - - <!-- XML --> - <application_xml> - <type>application/xml</type> - <model>Mage_Api2_Model_Request_Interpreter_Xml</model> - </application_xml> - <application_xhtml_xml> - <type>application/xhtml+xml</type> - <model>Mage_Api2_Model_Request_Interpreter_Xml</model> - </application_xhtml_xml> - <text_xml> - <type>text/xml</type> - <model>Mage_Api2_Model_Request_Interpreter_Xml</model> - </text_xml> - </interpreters> - </request> - <response> - <renders> - <!-- JSON --> - <default> - <type>*/*</type> - <model>Mage_Api2_Model_Renderer_Json</model> - </default> - <application_json> - <type>application/json</type> - <model>Mage_Api2_Model_Renderer_Json</model> - </application_json> - - <!-- QUERY --> - <text_plain> - <type>text/plain</type> - <model>Mage_Api2_Model_Renderer_Query</model> - </text_plain> - - <!-- XML --> - <text_xml> - <type>text/xml</type> - <model>Mage_Api2_Model_Renderer_Xml</model> - </text_xml> - <application_xml> - <type>application/xml</type> - <model>Mage_Api2_Model_Renderer_Xml</model> - </application_xml> - <application_xhtml_xml> - <type>application/xhtml+xml</type> - <model>Mage_Api2_Model_Renderer_Xml</model> - </application_xhtml_xml> - </renders> - </response> - </api2> - </global> - <admin> - <routers> - <adminhtml> - <args> - <modules> - <api2 before="Mage_Adminhtml">Mage_Api2_Adminhtml</api2> - </modules> - </args> - </adminhtml> - </routers> - </admin> - <adminhtml> - <layout> - <updates> - <api2 module="Mage_Api2"> - <file>layout.xml</file> - </api2> - </updates> - </layout> - <events> - <catalog_entity_attribute_save_after> - <observers> - <api2> - <class>Mage_Api2_Model_Observer</class> - <method>catalogAttributeSaveAfter</method> - </api2> - </observers> - </catalog_entity_attribute_save_after> - </events> - </adminhtml> -</config> diff --git a/app/code/core/Mage/Api2/sql/api2_setup/install-1.0.0.0.php b/app/code/core/Mage/Api2/sql/api2_setup/install-1.0.0.0.php deleted file mode 100644 index b14869ce08e37a78fbbdd743ef3608fcb03b08c1..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/sql/api2_setup/install-1.0.0.0.php +++ /dev/null @@ -1,183 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ -/** - * Installation of Api2 module tables - */ -/** @var $installer Mage_Api2_Model_Resource_Setup */ -$installer = $this; - -$installer->startSetup(); - -/** @var $adapter Varien_Db_Adapter_Pdo_Mysql */ -$adapter = $installer->getConnection(); - -/** - * Create table 'api2_acl_role' - */ -$table = $adapter->newTable($installer->getTable('api2_acl_role')) - ->addColumn('entity_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array( - 'identity' => true, - 'unsigned' => true, - 'nullable' => false, - 'primary' => true, - ), 'Entity ID') - ->addColumn('created_at', Varien_Db_Ddl_Table::TYPE_TIMESTAMP, null, - array( - 'nullable' => false, - 'default' => Varien_Db_Ddl_Table::TIMESTAMP_INIT - ), 'Created At') - ->addColumn('updated_at', Varien_Db_Ddl_Table::TYPE_TIMESTAMP, null, - array( - 'nullable' => true - ), 'Updated At') - ->addColumn('role_name', Varien_Db_Ddl_Table::TYPE_TEXT, - 255, array('nullable' => false), 'Name of role') - ->addIndex($installer->getIdxName('api2_acl_role', array('created_at')), array('created_at')) - ->addIndex($installer->getIdxName('api2_acl_role', array('updated_at')), array('updated_at')) - ->setComment('Api2 Global ACL Roles'); -$adapter->createTable($table); - -// Create Guest and Customer User Roles -$adapter->insertMultiple( - $installer->getTable('api2_acl_role'), - array( - array('role_name' => 'Guest'), - array('role_name' => 'Customer') - ) -); - -/** - * Create table 'api2_acl_user' - */ -$table = $adapter->newTable($installer->getTable('api2_acl_user')) - ->addColumn('admin_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array( - 'unsigned' => true, - 'nullable' => false, - ), 'Admin ID') - ->addColumn('role_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array( - 'unsigned' => true, - 'nullable' => false, - ), 'Role ID') - ->addIndex( - $installer->getIdxName( - $installer->getTable('api2_acl_user'), - array('admin_id'), - Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE - ), - array('admin_id'), - array('type' => Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE)) - ->addForeignKey( - $installer->getFkName('api2_acl_user', 'admin_id', 'admin_user', 'user_id'), - 'admin_id', - $installer->getTable('admin_user'), - 'user_id', - Varien_Db_Ddl_Table::ACTION_CASCADE, - Varien_Db_Ddl_Table::ACTION_CASCADE) - ->addForeignKey( - $installer->getFkName('api2_acl_user', 'role_id', 'api2_acl_role', 'entity_id'), - 'role_id', - $installer->getTable('api2_acl_role'), - 'entity_id', - Varien_Db_Ddl_Table::ACTION_CASCADE, - Varien_Db_Ddl_Table::ACTION_CASCADE) - ->setComment('Api2 Global ACL Users'); -$adapter->createTable($table); - -/** - * Create table 'api2_acl_rule' - */ -$table = $adapter->newTable($installer->getTable('api2_acl_rule')) - ->addColumn('entity_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array( - 'primary' => true, - 'identity' => true, - 'unsigned' => true, - 'nullable' => false, - ), 'Entity ID') - ->addColumn('role_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array( - 'unsigned' => true, - 'nullable' => false, - ), 'Role ID') - ->addColumn('resource_id', Varien_Db_Ddl_Table::TYPE_TEXT, 255, array( - 'nullable' => false - ), 'Resource ID') - ->addColumn('privilege', Varien_Db_Ddl_Table::TYPE_TEXT, 20, array( - 'nullable' => true - ), 'ACL Privilege') - ->addIndex( - $installer->getIdxName( - $installer->getTable('api2_acl_rule'), - array('role_id', 'resource_id', 'privilege'), - Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE - ), - array('role_id', 'resource_id', 'privilege'), - array('type' => Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE)) - ->addForeignKey( - $installer->getFkName('api2_acl_rule', 'role_id', 'api2_acl_role', 'entity_id'), - 'role_id', - $installer->getTable('api2_acl_role'), - 'entity_id', - Varien_Db_Ddl_Table::ACTION_CASCADE, - Varien_Db_Ddl_Table::ACTION_CASCADE) - ->setComment('Api2 Global ACL Rules'); -$adapter->createTable($table); - -/** -* Create table 'api2_acl_attribute' -*/ -$table = $adapter->newTable($installer->getTable('api2_acl_attribute')) - ->addColumn('entity_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array( - 'identity' => true, - 'unsigned' => true, - 'nullable' => false, - 'primary' => true, - ), 'Entity ID') - ->addColumn('user_type', Varien_Db_Ddl_Table::TYPE_TEXT, 20, array( - 'nullable' => false - ), 'Type of user') - ->addColumn('resource_id', Varien_Db_Ddl_Table::TYPE_TEXT, 255, array( - 'nullable' => false - ), 'Resource ID') - ->addColumn('operation', Varien_Db_Ddl_Table::TYPE_TEXT, 20, array( - 'nullable' => false - ), 'Operation') - ->addColumn('allowed_attributes', Varien_Db_Ddl_Table::TYPE_TEXT, null, array( - 'nullable' => true - ), 'Allowed attributes') - ->addIndex( - $installer->getIdxName('api2_acl_attribute', array('user_type')), - array('user_type')) - ->addIndex( - $installer->getIdxName( - $installer->getTable('api2_acl_attribute'), - array('user_type', 'resource_id', 'operation'), - Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE - ), - array('user_type', 'resource_id', 'operation'), - array('type' => Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE)) - ->setComment('Api2 Filter ACL Attributes'); -$adapter->createTable($table); - -$installer->endSetup(); diff --git a/app/code/core/Mage/Api2/view/adminhtml/attribute/buttons.phtml b/app/code/core/Mage/Api2/view/adminhtml/attribute/buttons.phtml deleted file mode 100644 index ec2a35637ee8bc3da4701bf802ae63b20426592c..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/view/adminhtml/attribute/buttons.phtml +++ /dev/null @@ -1,51 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Academic Free License (AFL 3.0) - * that is bundled with this package in the file LICENSE_AFL.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/afl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category design - * @package default_default - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) - */ -/** @var $this Mage_Api2_Block_Adminhtml_Attribute_Buttons */ - -?> -<div class="content-header"> - <table cellspacing="0"> - <tr> - <td style="width:50%;"> - <h3 class="icon-head head-permissions-role"> - <?php echo $this->getCaption() ?> - </h3> - </td> - <td class="form-buttons"> - <?php echo $this->getBackButtonHtml() ?> - <?php echo $this->getResetButtonHtml() ?> - <?php echo $this->getDeleteButtonHtml() ?> - <?php echo $this->getSaveButtonHtml() ?> - </td> - </tr> - </table> -</div> -<form action="<?php echo $this->getUrl('*/*/save') ?>" method="post" id="role-edit-form"> - <?php echo $this->getBlockHtml('formkey')?> -</form> -<script type="text/javascript"> - jQuery('#role-edit-form').form().validation(); -</script> diff --git a/app/code/core/Mage/Api2/view/adminhtml/attribute/resource.phtml b/app/code/core/Mage/Api2/view/adminhtml/attribute/resource.phtml deleted file mode 100644 index c8f304d52952e4cafab4db441f8ce73dda2ee66f..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/view/adminhtml/attribute/resource.phtml +++ /dev/null @@ -1,158 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Academic Free License (AFL 3.0) - * that is bundled with this package in the file LICENSE_AFL.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/afl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category design - * @package default_default - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) - */ -?> - -<?php -/** - * @see Mage_Api2_Block_Adminhtml_Attribute_Tab_Resource - */ -?> - -<?php echo $this->getChildHtml(); ?> - -<div class="entry-edit"> - <div class="entry-edit-head"> - <h4 class="icon-head head-edit-form fieldset-legend"><?php echo $this->__('User Type Resources') ?></h4> - </div> - <input type="hidden" name="resource" id="role_resources" value="" /> - <fieldset id="role_resources"> - - <span class="field-row"> - <label for="all"><?php echo $this->__('Resource Access') ?></label> - <select id="all" name="all" onchange="$('resources_container').toggle()" class="select"> - <option value="0" <?php echo ($this->getEverythingAllowed()?'':'selected'); ?>><?php echo $this->__('Custom') ?></option> - <option value="1" <?php echo ($this->getEverythingAllowed()?'selected':''); ?>><?php echo $this->__('All') ?></option> - </select> - </span> - - <span class="field-row" id="resources_container"> - <label><?php echo $this->__('Resources') ?></label> - <div class="f-left"> - <div class="tree x-tree" id="resource-tree"></div> - </div> - <?php if ($this->hasEntityOnlyAttributes()): ?> - <div class="clear"></div> - <span>* This attribute data will be returned for a single resource only.</span> - <?php endif; ?> - </span> - - </fieldset> -</div> -<!-- Draw Resources Tree --> -<script type="text/javascript"> -//<![CDATA[ -<?php if($this->getEverythingAllowed()): ?> - $('resources_container').hide(); -<?php endif; ?> -Ext.EventManager.onDocumentReady(function() { - var tree = new Ext.tree.TreePanel('resource-tree', { - animate:false, - loader: false, - enableDD:false, - containerScroll: true, - rootUIProvider: Ext.tree.CheckboxNodeUI, - selModel: new Ext.tree.CheckNodeMultiSelectionModel(), - rootVisible: false - }); - - tree.on('check', checkHandler, tree); - - // set the root node - var root = new Ext.tree.TreeNode({ - text: 'root', - draggable:false, - checked:'false', - id:'__root__', - uiProvider: Ext.tree.CheckboxNodeUI - }); - - tree.setRootNode(root); - bildResourcesTree(root, <?php echo $this->getResTreeJson() ?>); - tree.addListener('click', resourceClick.createDelegate(this)); - - // render the tree - tree.render(); - // root.expand(); - tree.expandAll(); - - $('role_resources').value = tree.getChecked().join(','); -}); - -function resourceClick(node, e){ - node.getUI().check(!node.getUI().checked()); - varienElementMethods.setHasChanges(Event.element(e), e); -}; - -function bildResourcesTree(parent, config){ - if (!config) return null; - - if (parent && config && config.length){ - for (var i = 0; i < config.length; i++){ - config[i].uiProvider = Ext.tree.CheckboxNodeUI; - var node = new Ext.tree.TreeNode(config[i]); - parent.appendChild(node); - if(config[i].children){ - bildResourcesTree(node, config[i].children); - } - } - } -} - -function checkHandler(node) -{ - if ( node.attributes.checked && node.parentNode ) { - var n = node.parentNode; - this.removeListener('check', checkHandler); - do { - if (!n || n.attributes.id == 'admin' || n.attributes.id == '__root__') { - break; - } else { - n.ui.check(true); - } - } while (n = n.parentNode ); - this.on('check', checkHandler); - } - if ( !node.isLeaf() && node.hasChildNodes() ) { - this.removeListener('check', checkHandler); - processChildren(node, node.attributes.checked); - this.on('check', checkHandler); - } - $('role_resources').value = this.getChecked().join(','); -} - -function processChildren(node, state) -{ - if ( !node.hasChildNodes() ) return false; - for(var i = 0; i < node.childNodes.length; i++ ) { - node.childNodes[i].ui.check(state); - if ( node.childNodes[i].hasChildNodes() ) { - processChildren(node.childNodes[i], state); - } - } - return true; -} -//]]> -</script> diff --git a/app/code/core/Mage/Api2/view/adminhtml/layout.xml b/app/code/core/Mage/Api2/view/adminhtml/layout.xml deleted file mode 100644 index 6c126652037603e746ca8cb67c0068340e2ef355..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/view/adminhtml/layout.xml +++ /dev/null @@ -1,147 +0,0 @@ -<?xml version="1.0"?> -<!-- -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Academic Free License (AFL 3.0) - * that is bundled with this package in the file LICENSE_AFL.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/afl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category design - * @package default_default - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) - */ ---> -<layout> - <adminhtml_api2_role_index> - <reference name="content"> - <block type="Mage_Api2_Block_Adminhtml_Roles" name="api2_roles"/> - </reference> - </adminhtml_api2_role_index> - - <adminhtml_api2_role_new> - <reference name="left"> - <block type="Mage_Api2_Block_Adminhtml_Roles_Tabs" name="adminhtml.role.edit.tabs"> - <block type="Mage_Api2_Block_Adminhtml_Roles_Tab_Info" name="adminhtml.role.edit.tab.info"/> - <block type="Mage_Api2_Block_Adminhtml_Roles_Tab_Resources" name="adminhtml.role.edit.tab.resources" template="Mage_User::role/edit.phtml"/> - <action method="addTab"> - <id>api2_role_section_info</id> - <block>adminhtml.role.edit.tab.info</block> - </action> - <action method="addTab"> - <id>api2_role_section_resources</id> - <block>adminhtml.role.edit.tab.resources</block> - </action> - </block> - </reference> - <reference name="content"> - <block type="Mage_Api2_Block_Adminhtml_Roles_Buttons" name="adminhtml.roles.buttons"/> - </reference> - <reference name="head"> - <action method="setCanLoadExtJs"> - <flag>1</flag> - </action> - </reference> - </adminhtml_api2_role_new> - - <adminhtml_api2_role_edit> - <reference name="left"> - <block type="Mage_Api2_Block_Adminhtml_Roles_Tabs" name="adminhtml.role.edit.tabs"> - <block type="Mage_Api2_Block_Adminhtml_Roles_Tab_Info" name="adminhtml.role.edit.tab.info"/> - <block type="Mage_Api2_Block_Adminhtml_Roles_Tab_Resources" name="adminhtml.role.edit.tab.resources" template="Mage_User::role/edit.phtml"/> - <block type="Mage_Api2_Block_Adminhtml_Roles_Tab_Users" name="adminhtml.role.edit.tab.users"/> - <action method="addTab"> - <id>api2_role_section_info</id> - <block>adminhtml.role.edit.tab.info</block> - </action> - <action method="addTab"> - <id>api2_role_section_resources</id> - <block>adminhtml.role.edit.tab.resources</block> - </action> - <action method="addTab"> - <id>roleUsersGrid</id> - <block>adminhtml.role.edit.tab.users</block> - </action> - </block> - </reference> - <reference name="content"> - <block type="Mage_Api2_Block_Adminhtml_Roles_Buttons" name="adminhtml.roles.buttons"/> - </reference> - <reference name="head"> - <action method="setCanLoadExtJs"> - <flag>1</flag> - </action> - </reference> - <reference name="js"> - <block type="Mage_Adminhtml_Block_Template" name="adminhtml.role.js.users.grid" template="Mage_Api2::role/users_grid_js.phtml"/> - </reference> - </adminhtml_api2_role_edit> - - <adminhtml_api2_role_grid> - <remove name="root"/> - <block type="Mage_Api2_Block_Adminhtml_Roles_Grid" name="api2_roles.grid" output="1"/> - </adminhtml_api2_role_grid> - - <adminhtml_api2_role_usersgrid> - <remove name="root"/> - <block type="Mage_Api2_Block_Adminhtml_Roles_Tab_Users" name="adminhtml.role.edit.tab.users" output="1"/> - </adminhtml_api2_role_usersgrid> - - <!-- admin acl users edit page --> - <adminhtml_user_edit> - <reference name="adminhtml.user.edit.tabs"> - <block type="Mage_Api2_Block_Adminhtml_Permissions_User_Edit_Tab_Roles" name="adminhtml.user.edit.tab.roles"/> - <action method="addTabAfter"> - <id>api2_roles_section</id> - <block>adminhtml.user.edit.tab.roles</block> - <after>roles_section</after> - </action> - </reference> - <reference name="js"> - <block type="Mage_Adminhtml_Block_Template" name="adminhtml.user.edit.tab.roles.js" template="Mage_Api2::permissions/user/edit/tab/roles/js.phtml"/> - </reference> - </adminhtml_user_edit> - - <!-- ACL attributes --> - <adminhtml_api2_attribute_index> - <reference name="content"> - <block type="Mage_Api2_Block_Adminhtml_Attribute" name="api2.attribute"/> - </reference> - </adminhtml_api2_attribute_index> - - <adminhtml_api2_attribute_edit> - <reference name="left"> - <block type="Mage_Api2_Block_Adminhtml_Attribute_Tabs" name="api2.attribute.edit.tabs"> - <block type="Mage_Api2_Block_Adminhtml_Attribute_Tab_Resource" name="api2.attribute.tab.resource" template="attribute/resource.phtml"/> - <action method="addTab"> - <name>api2_attribute_section_resources</name> - <block>api2.attribute.tab.resource</block> - </action> - </block> - </reference> - <reference name="content"> - <block type="Mage_Api2_Block_Adminhtml_Attribute_Edit" name="edit_form"> - <block type="Mage_Api2_Block_Adminhtml_Attribute_Edit_Form" name="form"/> - </block> - </reference> - <reference name="head"> - <action method="setCanLoadExtJs"> - <flag>1</flag> - </action> - </reference> - </adminhtml_api2_attribute_edit> - <!-- EOF ACL attributes --> -</layout> diff --git a/app/code/core/Mage/Api2/view/adminhtml/permissions/user/edit/tab/roles/js.phtml b/app/code/core/Mage/Api2/view/adminhtml/permissions/user/edit/tab/roles/js.phtml deleted file mode 100644 index 5306e9f730acceebae24f3afaf81bb09de390af4..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/view/adminhtml/permissions/user/edit/tab/roles/js.phtml +++ /dev/null @@ -1,59 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Academic Free License (AFL 3.0) - * that is bundled with this package in the file LICENSE_AFL.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/afl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category design - * @package default_default - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) - */ -?> - -<script type="text/javascript"> -//<![CDATA[ -var activeRestRole = getActiveRestRole(); - -/* Retrieve current active rest role */ -function getActiveRestRole() { - var role; - api2_roles_sectionJsObject.rows.each(function(row) { - var radiobox = $(row).getElementsByClassName('radio')[0]; - if ('undefined' != typeof radiobox && radiobox.checked) { - role = radiobox; - } - }); - return role; -} - -/* Callback function for rest role row click */ -function restRolesRowClick(grid, event) { - var newRestRole = getActiveRestRole(); - if (newRestRole.value !== activeRestRole.value) { - if (!confirm("Warning!\r\nThis action will remove this user from already assigned role\r\nAre you sure?") ) { - newRestRole.checked = !newRestRole.checked; - activeRestRole.checked = true; - } else { - activeRestRole = newRestRole; - } - } -} - -api2_roles_sectionJsObject.rowClickCallback = restRolesRowClick; -//]]> -</script> diff --git a/app/code/core/Mage/Api2/view/adminhtml/role/buttons.phtml b/app/code/core/Mage/Api2/view/adminhtml/role/buttons.phtml deleted file mode 100644 index fd87ee38d29a5ff4633d0b7b817c60191ebe68ef..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/view/adminhtml/role/buttons.phtml +++ /dev/null @@ -1,50 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Academic Free License (AFL 3.0) - * that is bundled with this package in the file LICENSE_AFL.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/afl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category design - * @package default_default - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) - */ -?> -<?php /** @var $this Mage_Adminhtml_Block_Api_Tab_Roleinfo */ ?> -<div class="content-header"> - <table cellspacing="0"> - <tr> - <td style="width:50%;"> - <h3 class="icon-head head-permissions-role"> - <?php echo $this->getCaption() ?> - </h3> - </td> - <td class="form-buttons"> - <?php echo $this->getBackButtonHtml() ?> - <?php echo $this->getResetButtonHtml() ?> - <?php echo $this->getDeleteButtonHtml() ?> - <?php echo $this->getSaveButtonHtml() ?> - </td> - </tr> - </table> -</div> -<form action="<?php echo $this->getUrl('*/*/save') ?>" method="post" id="role-edit-form"> - <?php echo $this->getBlockHtml('formkey')?> -</form> -<script type="text/javascript"> - jQuery('#role-edit-form').form().validation(); -</script> diff --git a/app/code/core/Mage/Api2/view/adminhtml/role/users_grid_js.phtml b/app/code/core/Mage/Api2/view/adminhtml/role/users_grid_js.phtml deleted file mode 100644 index 12355f8e7bc0898466a5cae8a7aa5d010a7c2390..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Api2/view/adminhtml/role/users_grid_js.phtml +++ /dev/null @@ -1,122 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Academic Free License (AFL 3.0) - * that is bundled with this package in the file LICENSE_AFL.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/afl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category design - * @package default_default - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) - */ - -?> -<script type="text/javascript"> -//<![CDATA[ -<?php - /** @var $myBlock Mage_Api2_Block_Adminhtml_Roles_Tab_Users */ - $myBlock = $this->getLayout()->getBlock('adminhtml.role.edit.tab.users'); - $name = $myBlock->getJsObjectName(); -?> - <?php if (is_object($myBlock) && $name && !$myBlock->isHidden()): ?> - var checkBoxes = $H(<?php echo $myBlock->getUsers(true) ?>); - var warning = false; - if (checkBoxes.size() > 0) { - warning = true; - } - $('in_role_users').value = checkBoxes.toQueryString(); - - function registerUserRole(grid, element, checked) - { - if (checked) { - checkBoxes.set(element.value, 0); - } else { - checkBoxes.unset(element.value); - } - $('in_role_users').value = checkBoxes.toQueryString(); - grid.reloadParams = {'in_role_users[]':checkBoxes.keys()}; - } - - function roleUsersRowClick(grid, event) - { - var trElement = Event.findElement(event, 'tr'); - var isInput = Event.element(event).tagName == 'INPUT'; - if (trElement) { - var checkbox = Element.getElementsBySelector(trElement, 'input'); - if(checkbox[0]){ - var checked = isInput ? checkbox[0].checked : !checkbox[0].checked; - if (checked) { - checkbox[0].checked = true; - if ( confirm("<?php echo $this->__('Warning!\r\nThis action will remove this user from already assigned role\r\nAre you sure?') ?>") ) { - checkBoxes.set(checkbox[0].value, checked); - varienElementMethods.setHasChanges(checkbox[0]); - } else { - checkbox[0].checked = false; - } - warning = false; - } else { - checkBoxes.unset(checkbox[0].value); - } - - $('in_role_users').value = checkBoxes.toQueryString(); - grid.reloadParams = {'in_role_user[]':checkBoxes.keys()}; - } - } - } - - function roleUsersRowInit(grid, row) - { - var checkbox = $(row).getElementsByClassName('checkbox')[0]; - if (checkbox) { - if (checkbox.checked) { - checkBoxes.set(checkbox.value, checkbox.checked); - } else { - checkBoxes.unset(checkbox.value); - } - - $('in_role_users').value = checkBoxes.toQueryString(); - grid.reloadParams = {'in_role_user[]':checkBoxes.keys()}; - } - } - - function myhandler(o) - { - if (checkBoxes.size() > 0) { - if (!confirm("<?php echo $this->__('Warning!\r\nThis action will remove those users from already assigned roles\r\nAre you sure?') ?>") ) { - o.checked = !o.checked; - } else { - checkBoxes.each(function(el){ - el.checked = o.checked; - }); - return false; - } - warning = false; - } - - $('in_role_users').value = checkBoxes.toQueryString(); - //grid.reloadParams = {'in_role_user[]':checkBoxes.keys()}; - } - - <?php echo $name ?>.rowClickCallback = roleUsersRowClick; - <?php echo $name ?>.initRowCallback = roleUsersRowInit; - <?php echo $name ?>.checkboxCheckCallback = registerUserRole; - <?php echo $name ?>.checkCheckboxes = myhandler; - <?php echo $name ?>.rows.each(function(row){roleUsersRowInit(<?php echo $name ?>, row)}); - $('in_role_users_old').value = $('in_role_users').value; - <?php endif; ?> -//]]> -</script> diff --git a/app/code/core/Mage/Backend/Block/Store/Switcher.php b/app/code/core/Mage/Backend/Block/Store/Switcher.php index e41b4dfe3dbbb9c2ba8794259e157d02e46df753..ae60107b6e083a2008e9535d1ab9b5e5197bca64 100644 --- a/app/code/core/Mage/Backend/Block/Store/Switcher.php +++ b/app/code/core/Mage/Backend/Block/Store/Switcher.php @@ -30,6 +30,7 @@ * @category Mage * @package Mage_Backend * @author Magento Core Team <core@magentocommerce.com> + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class Mage_Backend_Block_Store_Switcher extends Mage_Backend_Block_Template { @@ -90,6 +91,25 @@ class Mage_Backend_Block_Store_Switcher extends Mage_Backend_Block_Template */ protected $_storeGroupFactory; + /** + * @param Mage_Core_Controller_Request_Http $request + * @param Mage_Core_Model_Layout $layout + * @param Mage_Core_Model_Event_Manager $eventManager + * @param Mage_Backend_Model_Url $urlBuilder + * @param Mage_Core_Model_Translate $translator + * @param Mage_Core_Model_Cache $cache + * @param Mage_Core_Model_Design_Package $designPackage + * @param Mage_Core_Model_Session $session + * @param Mage_Core_Model_Store_Config $storeConfig + * @param Mage_Core_Controller_Varien_Front $frontController + * @param Mage_Core_Model_Factory_Helper $helperFactory + * @param Mage_Core_Model_App $application + * @param Mage_Core_Model_Website_Factory $websiteFactory + * @param Mage_Core_Model_Store_Group_Factory $storeGroupFactory + * @param array $data + * + * @SuppressWarnings(PHPMD.ExcessiveParameterList) + */ public function __construct( Mage_Core_Controller_Request_Http $request, Mage_Core_Model_Layout $layout, @@ -148,7 +168,7 @@ class Mage_Backend_Block_Store_Switcher extends Mage_Backend_Block_Template { $websites = $this->_application->getWebsites(); if ($websiteIds = $this->getWebsiteIds()) { - foreach ($websites as $websiteId => $website) { + foreach (array_keys($websites) as $websiteId) { if (!in_array($websiteId, $websiteIds)) { unset($websites[$websiteId]); } @@ -213,7 +233,7 @@ class Mage_Backend_Block_Store_Switcher extends Mage_Backend_Block_Template } $stores = $group->getStores(); if ($storeIds = $this->getStoreIds()) { - foreach ($stores as $storeId => $store) { + foreach (array_keys($stores) as $storeId) { if (!in_array($storeId, $storeIds)) { unset($stores[$storeId]); } diff --git a/app/code/core/Mage/Backend/Block/System/Config/Dwstree.php b/app/code/core/Mage/Backend/Block/System/Config/Dwstree.php index 59bcc5ec8c1298b4e8662611388d83c9426086fe..c784fb553bd535ef75934620e2d9c8c1aeead15a 100644 --- a/app/code/core/Mage/Backend/Block/System/Config/Dwstree.php +++ b/app/code/core/Mage/Backend/Block/System/Config/Dwstree.php @@ -74,7 +74,7 @@ class Mage_Backend_Block_System_Config_Dwstree extends Mage_Backend_Block_Widget $this->_addBreadcrumb($wName); } } - foreach ($wConfig->descend('system/stores')->children() as $sCode => $sId) { + foreach (array_keys($wConfig->descend('system/stores')->children()) as $sCode) { $sName = (string)$storesConfig->descend($sCode . '/system/store/name'); $this->addTab('store_' . $sCode, array( 'label' => $sName, diff --git a/app/code/core/Mage/Backend/Block/System/Config/Edit.php b/app/code/core/Mage/Backend/Block/System/Config/Edit.php index 87cd713cebd033913be7651a13b5c9b05fbf8a19..09d3ff3523bab6099f5cb80039d5e0fa1f811a03 100644 --- a/app/code/core/Mage/Backend/Block/System/Config/Edit.php +++ b/app/code/core/Mage/Backend/Block/System/Config/Edit.php @@ -30,22 +30,18 @@ * @category Mage * @package Mage_Backend * @author Magento Core Team <core@magentocommerce.com> + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class Mage_Backend_Block_System_Config_Edit extends Mage_Backend_Block_Widget { const DEFAULT_SECTION_BLOCK = 'Mage_Backend_Block_System_Config_Form'; /** - * Sections configuration + * Form block class name * - * @var array - */ - protected $_section; - - /** - * @var Mage_Backend_Model_Config_StructureInterface + * @var string */ - protected $_systemConfig; + protected $_formBlockName; /** * Block template File @@ -54,27 +50,67 @@ class Mage_Backend_Block_System_Config_Edit extends Mage_Backend_Block_Widget */ protected $_template = 'Mage_Backend::system/config/edit.phtml'; - protected function _construct() - { - $this->_systemConfig = $this->hasData('systemConfig') ? - $this->getData('systemConfig') : - Mage::getSingleton('Mage_Backend_Model_Config_Structure_Reader')->getConfiguration(); - - parent::_construct(); - - $sectionCode = $this->getRequest()->getParam('section'); - - $this->_section = $this->_systemConfig->getSection($sectionCode); + /** + * Configuration structure + * + * @var Mage_Backend_Model_Config_Structure + */ + protected $_configStructure; - $this->setTitle($this->_section['label']); - $this->setHeaderCss(isset($this->_section['header_css']) ? $this->_section['header_css'] : ''); + /** + * @param Mage_Core_Controller_Request_Http $request + * @param Mage_Core_Model_Layout $layout + * @param Mage_Core_Model_Event_Manager $eventManager + * @param Mage_Backend_Model_Url $urlBuilder + * @param Mage_Core_Model_Translate $translator + * @param Mage_Core_Model_Cache $cache + * @param Mage_Core_Model_Design_Package $designPackage + * @param Mage_Core_Model_Session $session + * @param Mage_Core_Model_Store_Config $storeConfig + * @param Mage_Core_Controller_Varien_Front $frontController + * @param Mage_Core_Model_Factory_Helper $helperFactory + * @param Mage_Backend_Model_Config_Structure $configStructure + * @param array $data + * + * @SuppressWarnings(PHPMD.ExcessiveParameterList) + */ + public function __construct( + Mage_Core_Controller_Request_Http $request, + Mage_Core_Model_Layout $layout, + Mage_Core_Model_Event_Manager $eventManager, + Mage_Backend_Model_Url $urlBuilder, + Mage_Core_Model_Translate $translator, + Mage_Core_Model_Cache $cache, + Mage_Core_Model_Design_Package $designPackage, + Mage_Core_Model_Session $session, + Mage_Core_Model_Store_Config $storeConfig, + Mage_Core_Controller_Varien_Front $frontController, + Mage_Core_Model_Factory_Helper $helperFactory, + Mage_Backend_Model_Config_Structure $configStructure, + array $data = array() + ) { + parent::__construct($request, $layout, $eventManager, $urlBuilder, $translator, $cache, $designPackage, + $session, $storeConfig, $frontController, $helperFactory, $data + ); + $this->_configStructure = $configStructure; } /** + * Prepare layout object + * * @return Mage_Core_Block_Abstract */ protected function _prepareLayout() { + /** @var $section Mage_Backend_Model_Config_Structure_Element_Section */ + $section = $this->_configStructure->getElement($this->getRequest()->getParam('section')); + $this->_formBlockName = $section->getFrontendModel(); + if (empty($this->_formBlockName)) { + $this->_formBlockName = self::DEFAULT_SECTION_BLOCK; + } + $this->setTitle($section->getLabel()); + $this->setHeaderCss($section->getHeaderCss()); + $this->addChild('save_button', 'Mage_Backend_Block_Widget_Button', array( 'label' => Mage::helper('Mage_Backend_Helper_Data')->__('Save Config'), 'class' => 'save', @@ -82,10 +118,14 @@ class Mage_Backend_Block_System_Config_Edit extends Mage_Backend_Block_Widget 'widget-button' => array('event' => 'save', 'related' => '#config-edit-form') ), )); + $block = $this->getLayout()->createBlock($this->_formBlockName); + $this->setChild('form', $block); return parent::_prepareLayout(); } /** + * Retrieve rendered save buttons + * * @return string */ public function getSaveButtonHtml() @@ -94,26 +134,12 @@ class Mage_Backend_Block_System_Config_Edit extends Mage_Backend_Block_Widget } /** + * Retrieve config save url + * * @return string */ public function getSaveUrl() { - return $this->getUrl('*/*/save', array('_current' => true)); - } - - /** - * @return Mage_Backend_Block_System_Config_Edit - */ - public function initForm() - { - $blockName = isset($this->_section['frontend_model']) ? $this->_section['frontend_model'] : ''; - if (empty($blockName)) { - $blockName = self::DEFAULT_SECTION_BLOCK; - } - - $block = $this->getLayout()->createBlock($blockName); - $block->initForm(); - $this->setChild('form', $block); - return $this; + return $this->getUrl('*/system_config_save/index', array('_current' => true)); } } diff --git a/app/code/core/Mage/Backend/Block/System/Config/Form.php b/app/code/core/Mage/Backend/Block/System/Config/Form.php index 4c0e5b36ec72a2c8faf5770654aca14ba1fdb21e..47901f262036ce875689b612c431ca9c79a2cf11 100644 --- a/app/code/core/Mage/Backend/Block/System/Config/Form.php +++ b/app/code/core/Mage/Backend/Block/System/Config/Form.php @@ -31,6 +31,8 @@ * @category Mage * @package Mage_Backend * @author Magento Core Team <core@magentocommerce.com> + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class Mage_Backend_Block_System_Config_Form extends Mage_Backend_Block_Widget_Form { @@ -54,32 +56,25 @@ class Mage_Backend_Block_System_Config_Form extends Mage_Backend_Block_Widget_Fo protected $_configDataObject; /** - * Enter description here... + * System configuration root node * * @var Varien_Simplexml_Element */ protected $_configRoot; /** - * System configuration - * - * @var Mage_Backend_Model_Config_StructureInterface - */ - protected $_systemConfig; - - /** - * Enter description here... + * Default fieldset rendering block * * @var Mage_Backend_Block_System_Config_Form_Fieldset */ - protected $_defaultFieldsetRenderer; + protected $_fieldsetRenderer; /** - * Enter description here... + * Default field rendering block * * @var Mage_Backend_Block_System_Config_Form_Field */ - protected $_defaultFieldRenderer; + protected $_fieldRenderer; /** * List of fieldset @@ -109,6 +104,34 @@ class Mage_Backend_Block_System_Config_Form extends Mage_Backend_Block_Widget_Fo */ protected $_formFactory; + /** + * System config structure + * + * @var Mage_Backend_Model_Config_Structure + */ + protected $_configStructure; + + /** + *Form fieldset factory + * + * @var Mage_Backend_Block_System_Config_Form_Fieldset_Factory + */ + protected $_fieldsetFactory; + + /** + * Form field factory + * + * @var Mage_Backend_Block_System_Config_Form_Field_Factory + */ + protected $_fieldFactory; + + /** + * Form field factory + * + * @var Mage_Core_Model_Config + */ + protected $_coreConfig; + /** * @param Mage_Core_Controller_Request_Http $request * @param Mage_Core_Model_Layout $layout @@ -124,6 +147,10 @@ class Mage_Backend_Block_System_Config_Form extends Mage_Backend_Block_Widget_Fo * @param Mage_Backend_Model_Config_Factory $configFactory * @param Varien_Data_Form_Factory $formFactory * @param Mage_Backend_Model_Config_Clone_Factory $cloneModelFactory + * @param Mage_Backend_Model_Config_Structure $configStructure + * @param Mage_Backend_Block_System_Config_Form_Fieldset_Factory $fieldsetFactory + * @param Mage_Backend_Block_System_Config_Form_Field_Factory $fieldFactory + * @param Mage_Core_Model_Config $coreConfig * @param array $data * * @SuppressWarnings(PHPMD.ExcessiveParameterList) @@ -143,6 +170,10 @@ class Mage_Backend_Block_System_Config_Form extends Mage_Backend_Block_Widget_Fo Mage_Backend_Model_Config_Factory $configFactory, Varien_Data_Form_Factory $formFactory, Mage_Backend_Model_Config_Clone_Factory $cloneModelFactory, + Mage_Backend_Model_Config_Structure $configStructure, + Mage_Backend_Block_System_Config_Form_Fieldset_Factory $fieldsetFactory, + Mage_Backend_Block_System_Config_Form_Field_Factory $fieldFactory, + Mage_Core_Model_Config $coreConfig, array $data = array() ) { parent::__construct($request, $layout, $eventManager, $urlBuilder, $translator, $cache, $designPackage, @@ -151,15 +182,10 @@ class Mage_Backend_Block_System_Config_Form extends Mage_Backend_Block_Widget_Fo $this->_configFactory = $configFactory; $this->_formFactory = $formFactory; $this->_cloneModelFactory = $cloneModelFactory; - } - - - protected function _construct() - { - parent::_construct(); - $this->_systemConfig = $this->hasData('systemConfig') ? - $this->getData('systemConfig') : - Mage::getSingleton('Mage_Backend_Model_Config_Structure_Reader')->getConfiguration(); + $this->_configStructure = $configStructure; + $this->_fieldsetFactory = $fieldsetFactory; + $this->_fieldFactory = $fieldFactory; + $this->_coreConfig = $coreConfig; $this->_scopeLabels = array( self::SCOPE_DEFAULT => $this->helper('Mage_Backend_Helper_Data')->__('[GLOBAL]'), @@ -169,23 +195,25 @@ class Mage_Backend_Block_System_Config_Form extends Mage_Backend_Block_Widget_Fo } /** - * Enter description here... + * Initialize objects required to render config form * * @return Mage_Backend_Block_System_Config_Form */ protected function _initObjects() { - $this->_configRoot = Mage::getConfig()->getNode(null, $this->getScope(), $this->getScopeCode()); - - $this->_configDataObject = $this->_configFactory->create() - ->setSection($this->getSectionCode()) - ->setWebsite($this->getWebsiteCode()) - ->setStore($this->getStoreCode()); + $this->_configRoot = $this->_coreConfig->getNode(null, $this->getScope(), $this->getScopeCode()); + + $this->_configDataObject = $this->_configFactory->create( + array( + 'section' => $this->getSectionCode(), + 'website' => $this->getWebsiteCode(), + 'store' => $this->getStoreCode() + ) + ); $this->_configData = $this->_configDataObject->load(); - - $this->_defaultFieldsetRenderer = Mage::getBlockSingleton('Mage_Backend_Block_System_Config_Form_Fieldset'); - $this->_defaultFieldRenderer = Mage::getBlockSingleton('Mage_Backend_Block_System_Config_Form_Field'); + $this->_fieldsetRenderer = $this->_fieldsetFactory->create(); + $this->_fieldRenderer = $this->_fieldFactory->create(); return $this; } @@ -200,21 +228,10 @@ class Mage_Backend_Block_System_Config_Form extends Mage_Backend_Block_Widget_Fo /** @var Varien_Data_Form $form */ $form = $this->_formFactory->create(); - - $section = $this->_systemConfig->getSection( - $this->getSectionCode(), - $this->getWebsiteCode(), - $this->getStoreCode() - ); - if (!empty($section) && false !== $this->_canShowField($section)) { - $groups = $section['groups']; - usort($groups, array($this, '_sortForm')); - - foreach ($groups as $group){ - /* @var $group array */ - if (false == $this->_canShowField($group)) { - continue; - } + /** @var $section Mage_Backend_Model_Config_Structure_Element_Section */ + $section = $this->_configStructure->getElement($this->getSectionCode()); + if ($section && $section->isVisible($this->getWebsiteCode(), $this->getStoreCode())) { + foreach ($section->getChildren() as $group) { $this->_initGroup($group, $section, $form); } } @@ -224,61 +241,52 @@ class Mage_Backend_Block_System_Config_Form extends Mage_Backend_Block_Widget_Fo } /** - * Initialize element group + * Initialize config field group * - * @param array $group - * @param array $section + * @param Mage_Backend_Model_Config_Structure_Element_Group $group + * @param Mage_Backend_Model_Config_Structure_Element_Section $section * @param Varien_Data_Form $form */ - protected function _initGroup($group, $section, $form) - { - if (isset($group['frontend_model'])) { - $fieldsetRenderer = Mage::getBlockSingleton((string)$group['frontend_model']); - } else { - $fieldsetRenderer = $this->_defaultFieldsetRenderer; - } + protected function _initGroup(Mage_Backend_Model_Config_Structure_Element_Group $group, + Mage_Backend_Model_Config_Structure_Element_Section $section, + Varien_Data_Form_Abstract $form + ) { + $frontendModelClass = $group->getFrontendModel(); + $fieldsetRenderer = $frontendModelClass ? + Mage::getBlockSingleton($frontendModelClass) : + $this->_fieldsetRenderer; $fieldsetRenderer->setForm($this); $fieldsetRenderer->setConfigData($this->_configData); $fieldsetRenderer->setGroup($group); - if ($this->_systemConfig->hasChildren($group, $this->getWebsiteCode(), $this->getStoreCode())) { + $fieldsetConfig = array( + 'legend' => $group->getLabel(), + 'comment' => $group->getComment(), + 'expanded' => $group->isExpanded() + ); - $helperName = $this->_systemConfig->getAttributeModule($section, $group); + $fieldset = $form->addFieldset($this->_generateElementId($group->getPath()), $fieldsetConfig); + $fieldset->setRenderer($fieldsetRenderer); + $group->populateFieldset($fieldset); + $this->_addElementTypes($fieldset); - $fieldsetConfig = array( - 'legend' => $this->helper($helperName) - ->__(array_key_exists('label', $group) ? $group['label'] : '') - ); - if (isset($group['comment'])) { - $fieldsetConfig['comment'] = $this->helper($helperName)->__($group['comment']); - } - if (isset($group['expanded'])) { - $fieldsetConfig['expanded'] = (bool)$group['expanded']; - } + $dependencies = $group->getDependencies($this->getStoreCode()); + $elementName = $this->_generateElementName($group->getPath()); + $elementId = $this->_generateElementId($group->getPath()); - $fieldset = $form->addFieldset($section['id'] . '_' . $group['id'], $fieldsetConfig) - ->setRenderer($fieldsetRenderer); - $this->_prepareFieldOriginalData($fieldset, $group); - $this->_addElementTypes($fieldset); - - if (isset($group['clone_fields'])) { - if (isset($group['clone_model'])) { - $cloneModel = $this->_cloneModelFactory->create($group['clone_model']); - } else { - Mage::throwException( - 'Config form fieldset clone model required to be able to clone fields' - ); - } - foreach ($cloneModel->getPrefixes() as $prefix) { - $this->initFields($fieldset, $group, $section, $prefix['field'], $prefix['label']); - } - } else { - $this->initFields($fieldset, $group, $section); - } + $this->_populateDependenciesBlock($dependencies, $elementId, $elementName); - $this->_fieldsets[$group['id']] = $fieldset; + if ($group->shouldCloneFields()) { + $cloneModel = $group->getCloneModel(); + foreach ($cloneModel->getPrefixes() as $prefix) { + $this->initFields($fieldset, $group, $section, $prefix['field'], $prefix['label']); + } + } else { + $this->initFields($fieldset, $group, $section); } + + $this->_fieldsets[$group->getId()] = $fieldset; } /** @@ -288,98 +296,72 @@ class Mage_Backend_Block_System_Config_Form extends Mage_Backend_Block_Widget_Fo */ protected function _getDependence() { - if (!$this->getChildBlock('element_dependence')){ + if (!$this->getChildBlock('element_dependence')) { $this->addChild('element_dependence', 'Mage_Backend_Block_Widget_Form_Element_Dependence'); } return $this->getChildBlock('element_dependence'); } /** - * Init fieldset fields + * Initialize config group fields * * @param Varien_Data_Form_Element_Fieldset $fieldset - * @param array $group - * @param array $section + * @param Mage_Backend_Model_Config_Structure_Element_Group $group + * @param Mage_Backend_Model_Config_Structure_Element_Section $section * @param string $fieldPrefix * @param string $labelPrefix * @return Mage_Backend_Block_System_Config_Form */ - public function initFields($fieldset, $group, $section, $fieldPrefix='', $labelPrefix='') - { + public function initFields( + Varien_Data_Form_Element_Fieldset $fieldset, + Mage_Backend_Model_Config_Structure_Element_Group $group, + Mage_Backend_Model_Config_Structure_Element_Section $section, + $fieldPrefix = '', + $labelPrefix = '' + ) { if (!$this->_configDataObject) { $this->_initObjects(); } // Extends for config data - $configDataAdditionalGroups = array(); + $extraConfigGroups = array(); - $fields = isset($group['fields']) ? $group['fields'] : array(); - /** @var array $elements */ - // sort either by sortOrder or by child node values by passing the sortOrder - $elements = $this->_sortElements($group, $fieldset, $fields); - - foreach ($elements as $element) { - if (false == $this->_canShowField($element)) { - continue; - } - - /** - * Look for custom defined field path - */ - $path = (isset($element['config_path'])) ? $element['config_path'] : ''; - - if (empty($path)) { - $path = $section['id'] . '/' . $group['id'] . '/' . $fieldPrefix . $element['id']; - } elseif (strrpos($path, '/') > 0) { - // Extend config data with new section group - $groupPath = substr($path, 0, strrpos($path, '/')); - if (false == isset($configDataAdditionalGroups[$groupPath])) { - $this->_configData = $this->_configDataObject->extendConfig( - $groupPath, - false, - $this->_configData - ); - $configDataAdditionalGroups[$groupPath] = true; + /** @var $element Mage_Backend_Model_Config_Structure_Element_Field */ + foreach ($group->getChildren() as $element) { + if ($element instanceof Mage_Backend_Model_Config_Structure_Element_Group) { + $this->_initGroup($element, $section, $fieldset); + } else { + $path = $element->getPath($fieldPrefix); + if ($element->getSectionId() != $section->getId()) { + $groupPath = $element->getGroupPath(); + if (!isset($extraConfigGroups[$groupPath])) { + $this->_configData = $this->_configDataObject + ->extendConfig($groupPath, false, $this->_configData); + $extraConfigGroups[$groupPath] = true; + } } + $this->_initElement($element, $fieldset, $path, $fieldPrefix, $labelPrefix); } - - $this->_initElement($element, $fieldset, $group, $section, $path, $fieldPrefix, $labelPrefix); } return $this; } - /** - * @param array $group - * @param Varien_Data_Form_Element_Fieldset $fieldset - * @param array $elements - * @return mixed - */ - protected function _sortElements($group, $fieldset, $elements) - { - if (isset($group['sort_fields']) && isset($group['sort_fields']['by'])) { - $fieldset->setSortElementsByAttribute($group['sort_fields']['by'], - isset($group['sort_fields']['direction_desc']) ? SORT_DESC : SORT_ASC - ); - } else { - usort($elements, array($this, '_sortForm')); - } - return $elements; - } - /** * Initialize form element * - * @param array $element + * @param Mage_Backend_Model_Config_Structure_Element_Field $field * @param Varien_Data_Form_Element_Fieldset $fieldset - * @param array $group - * @param array $section - * @param string $path + * @param $path * @param string $fieldPrefix * @param string $labelPrefix */ - protected function _initElement($element, $fieldset, $group, $section, $path, $fieldPrefix = '', $labelPrefix = '') - { - $elementId = $section['id'] . '_' . $group['id'] . '_' . $fieldPrefix . $element['id']; + protected function _initElement( + Mage_Backend_Model_Config_Structure_Element_Field $field, + Varien_Data_Form_Element_Fieldset $fieldset, + $path, + $fieldPrefix = '', + $labelPrefix = '' + ) { if (array_key_exists($path, $this->_configData)) { $data = $this->_configData[$path]; @@ -388,200 +370,108 @@ class Mage_Backend_Block_System_Config_Form extends Mage_Backend_Block_Widget_Fo $data = $this->_configRoot->descend($path); $inherit = true; } - $fieldRenderer = $this->_getFieldRenderer($element); + $fieldRendererClass = $field->getFrontendModel(); + if ($fieldRendererClass) { + $fieldRenderer = Mage::getBlockSingleton($fieldRendererClass); + } else { + $fieldRenderer = $this->_fieldRenderer; + } $fieldRenderer->setForm($this); $fieldRenderer->setConfigData($this->_configData); - $helperName = $this->_systemConfig->getAttributeModule($section, $group, $element); - $fieldType = isset($element['type']) ? $element['type'] : 'text'; - $name = 'groups[' . $group['id'] . '][fields][' . $fieldPrefix . $element['id'] . '][value]'; - $label = $this->helper($helperName)->__($labelPrefix) - . ' ' - . $this->helper($helperName)->__(array_key_exists('label', $element) ? (string)$element['label'] : ''); - $hint = isset($element['hint']) ? $this->helper($helperName)->__($element['hint']) : ''; + $elementName = $this->_generateElementName($field->getPath(), $fieldPrefix); + $elementId = $this->_generateElementId($field->getPath($fieldPrefix)); - if (isset($element['backend_model'])) { - $data = $this->_fetchBackendModelData($element, $path, $data); + if ($field->hasBackendModel()) { + $backendModel = $field->getBackendModel(); + $backendModel->setPath($path) + ->setValue($data) + ->setWebsite($this->getWebsiteCode()) + ->setStore($this->getStoreCode()) + ->afterLoad(); + $data = $backendModel->getValue(); } - $comment = $this->_prepareFieldComment($element, $helperName, $data); - $tooltip = $this->_prepareFieldTooltip($element, $helperName); + $dependencies = $field->getDependencies($fieldPrefix, $this->getStoreCode()); + $this->_populateDependenciesBlock($dependencies, $elementId, $elementName); - if (isset($element['depends'])) { - $this->_processElementDependencies($element, $section, $group, $elementId, $fieldPrefix); - } - $field = $fieldset->addField($elementId, $fieldType, array( - 'name' => $name, - 'label' => $label, - 'comment' => $comment, - 'tooltip' => $tooltip, - 'hint' => $hint, + $formField = $fieldset->addField($elementId, $field->getType(), array( + 'name' => $elementName, + 'label' => $field->getLabel($labelPrefix), + 'comment' => $field->getComment($data), + 'tooltip' => $field->getTooltip(), + 'hint' => $field->getHint(), 'value' => $data, 'inherit' => $inherit, - 'class' => isset($element['frontend_class']) ? $element['frontend_class'] : '', - 'field_config' => $element, + 'class' => $field->getFrontendClass(), + 'field_config' => $field->getData(), 'scope' => $this->getScope(), 'scope_id' => $this->getScopeId(), - 'scope_label' => $this->getScopeLabel($element), - 'can_use_default_value' => $this->canUseDefaultValue( - isset($element['showInDefault']) ? (int)$element['showInDefault'] : 0 - ), - 'can_use_website_value' => $this->canUseWebsiteValue( - isset($element['showInWebsite']) ? (int)$element['showInWebsite'] : 0 - ), + 'scope_label' => $this->getScopeLabel($field), + 'can_use_default_value' => $this->canUseDefaultValue($field->showInDefault()), + 'can_use_website_value' => $this->canUseWebsiteValue($field->showInWebsite()), )); - $this->_applyFieldConfiguration($field, $element); + $field->populateInput($formField); - $field->setRenderer($fieldRenderer); - - if (isset($element['source_model'])) { - $field->setValues($this->_extractDataFromSourceModel($element, $path, $fieldType)); + if ($field->hasValidation()) { + $formField->addClass($field->getValidation()); } - } - - /** - * Retrieve field renderer block - * - * @param array $element - * @return Mage_Backend_Block_System_Config_Form_Field - */ - protected function _getFieldRenderer($element) - { - if (isset($element['frontend_model'])) { - $fieldRenderer = Mage::getBlockSingleton($element['frontend_model']); - return $fieldRenderer; - } else { - $fieldRenderer = $this->_defaultFieldRenderer; - return $fieldRenderer; + if ($field->getType() == 'multiselect') { + $formField->setCanBeEmpty($field->canBeEmpty()); } - } - - /** - * Retrieve data from backend model - * - * @param array $element - * @param string $path - * @param mixed $data - * @return mixed - */ - protected function _fetchBackendModelData($element, $path, $data) - { - $model = Mage::getModel($element['backend_model']); - if (!$model instanceof Mage_Core_Model_Config_Data) { - Mage::throwException('Invalid config field backend model: ' . $element['backend_model']); + if ($field->hasSourceModel()) { + $formField->setValues($field->getOptions()); } - $model->setPath($path) - ->setValue($data) - ->setWebsite($this->getWebsiteCode()) - ->setStore($this->getStoreCode()) - ->afterLoad(); - $data = $model->getValue(); - return $data; + $formField->setRenderer($fieldRenderer); } /** - * Apply element dependencies from configuration + * Populate dependencies block * - * @param array $element - * @param array $section - * @param array $group + * @param array $dependencies * @param string $elementId - * @param string $fieldPrefix + * @param string $elementName */ - protected function _processElementDependencies($element, $section, $group, $elementId, $fieldPrefix = '') + protected function _populateDependenciesBlock(array $dependencies, $elementId, $elementName) { - foreach ($element['depends']['fields'] as $depend) { - /* @var array $depend */ - $dependentId = $section['id'] . '_' . $group['id'] . '_' . $fieldPrefix . $depend['id']; - $shouldBeAddedDependence = true; - $dependentValue = $depend['value']; - if (isset($depend['separator'])) { - $dependentValue = explode($depend['separator'], $dependentValue); - } - $dependentFieldName = $fieldPrefix . $depend['id']; - $dependentField = $group['fields'][$dependentFieldName]; - /* - * If dependent field can't be shown in current scope and real dependent config value - * is not equal to preferred one, then hide dependence fields by adding dependence - * based on not shown field (not rendered field) - */ - if (!$this->_canShowField($dependentField)) { - $dependentFullPath = $section['id'] . '/' . $group['id'] . '/' . $fieldPrefix . $depend['id']; - $dependentValueInStore = Mage::getStoreConfig($dependentFullPath, $this->getStoreCode()); - if (is_array($dependentValue)) { - $shouldBeAddedDependence = !in_array($dependentValueInStore, $dependentValue); - } else { - $shouldBeAddedDependence = $dependentValue != $dependentValueInStore; - } - } - if ($shouldBeAddedDependence) { - $this->_getDependence() - ->addFieldMap($elementId, $elementId) - ->addFieldMap($dependentId, $dependentId) - ->addFieldDependence($elementId, $dependentId, $dependentValue); - } + foreach ($dependencies as $dependentId => $dependentValue) { + $fieldNameFrom = $this->_generateElementName($dependentId, null, '_'); + $this->_getDependence() + ->addFieldMap($elementId, $elementName) + ->addFieldMap($this->_generateElementId($dependentId), $fieldNameFrom) + ->addFieldDependence($elementName, $fieldNameFrom, $dependentValue); } } /** - * Apply custom element configuration + * Generate element name * - * @param Varien_Data_Form_Element_Abstract $field - * @param array $element + * @param string $elementPath + * @param string $fieldPrefix + * @param string $separator + * @return string */ - protected function _applyFieldConfiguration($field, $element) + protected function _generateElementName($elementPath, $fieldPrefix = '', $separator = '/') { - $this->_prepareFieldOriginalData($field, $element); - - if (isset($element['validate'])) { - $field->addClass($element['validate']); - } - - if (isset($element['type']) && 'multiselect' === $element['type'] && isset($element['can_be_empty'])) { - $field->setCanBeEmpty(true); - } + $part = explode($separator, $elementPath); + array_shift($part); //shift section name + $fieldId = array_pop($part); //shift filed id + $groupName = implode('][groups][', $part); + $name = 'groups[' . $groupName . '][fields][' . $fieldPrefix . $fieldId . '][value]'; + return $name; } /** - * Retrieve source model option list + * Generate element id * - * @param array $element * @param string $path - * @param string $fieldType - * @return array + * @return string */ - protected function _extractDataFromSourceModel($element, $path, $fieldType) + protected function _generateElementId($path) { - $factoryName = $element['source_model']; - $method = false; - if (preg_match('/^([^:]+?)::([^:]+?)$/', $factoryName, $matches)) { - array_shift($matches); - list($factoryName, $method) = array_values($matches); - } - - $sourceModel = Mage::getSingleton($factoryName); - if ($sourceModel instanceof Varien_Object) { - $sourceModel->setPath($path); - } - if ($method) { - if ($fieldType == 'multiselect') { - $optionArray = $sourceModel->$method(); - } else { - $optionArray = array(); - foreach ($sourceModel->$method() as $key => $value) { - if (is_array($value)) { - $optionArray[] = $value; - } else { - $optionArray[] = array('label' => $value, 'value' => $key); - } - } - } - } else { - $optionArray = $sourceModel->toOptionArray($fieldType == 'multiselect'); - } - return $optionArray; + return str_replace('/', '_', $path); } /** @@ -598,63 +488,14 @@ class Mage_Backend_Block_System_Config_Form extends Mage_Backend_Block_Widget_Fo } /** - * Set "original_data" array to the element, composed from array elements with scalar values * - * @param Varien_Data_Form_Element_Abstract $field - * @param array $data - */ - protected function _prepareFieldOriginalData($field, $data) - { - $originalData = array(); - foreach ($data as $key => $value) { - if (!is_array($value)) { - $originalData[$key] = $value; - } - } - $field->setOriginalData($originalData); - } - - /** - * Support models "getCommentText" method for field note generation * - * @param array $element - * @param string $helper - * @param string $currentValue - * @return string + * @return Mage_Backend_Block_Widget_Form|Mage_Core_Block_Abstract|void */ - protected function _prepareFieldComment($element, $helper, $currentValue) + protected function _beforeToHtml() { - $comment = ''; - if (isset($element['comment'])) { - if (is_array($element['comment'])) { - if (isset($element['comment']['model'])) { - $model = Mage::getModel($element['comment']['model']); - if (method_exists($model, 'getCommentText')) { - $comment = $model->getCommentText($element, $currentValue); - } - } - } else { - $comment = $this->helper($helper)->__($element['comment']); - } - } - return $comment; - } - - /** - * Prepare additional comment for field like tooltip - * - * @param array $element - * @param string $helper - * @return string - */ - protected function _prepareFieldTooltip($element, $helper) - { - if (isset($element['tooltip'])) { - return $this->helper($helper)->__($element['tooltip']); - } elseif (isset($element['tooltip_block'])) { - return $this->getLayout()->createBlock($element['tooltip_block'])->toHtml(); - } - return ''; + $this->initForm(); + return parent::_beforeToHtml(); } /** @@ -672,20 +513,6 @@ class Mage_Backend_Block_System_Config_Form extends Mage_Backend_Block_Widget_Fo return $html; } - /** - * Sort elements - * - * @param array $a - * @param array $b - * @return boolean - */ - protected function _sortForm($a, $b) - { - $aSortOrder = isset($a['sortOrder']) ? (int)$a['sortOrder'] : 0; - $bSortOrder = isset($b['sortOrder']) ? (int)$b['sortOrder'] : 0; - return $aSortOrder < $bSortOrder ? -1 : ($aSortOrder > $bSortOrder ? 1 : 0); - } - /** * Check if can use default value * @@ -717,46 +544,6 @@ class Mage_Backend_Block_System_Config_Form extends Mage_Backend_Block_Widget_Fo return false; } - /** - * Checking field visibility - * - * @param array $field - * @return bool - */ - protected function _canShowField($field) - { - $ifModuleEnabled = isset($field['if_module_enabled']) ? trim($field['if_module_enabled']) : false; - - if ($ifModuleEnabled && - false == $this->helper('Mage_Core_Helper_Data')->isModuleEnabled($ifModuleEnabled)) { - return false; - } - $showInDefault = isset($field['showInDefault']) ? (bool)$field['showInDefault'] : false; - $showInWebsite = isset($field['showInWebsite']) ? (bool)$field['showInWebsite'] : false; - $showInStore = isset($field['showInStore']) ? (bool)$field['showInStore'] : false; - $hideIfSingleStore = isset($field['hide_in_single_store_mode']) ? (int)$field['hide_in_single_store_mode'] : 0; - - $fieldIsDisplayable = $showInDefault || $showInWebsite || $showInStore; - - if (Mage::app()->isSingleStoreMode() && $fieldIsDisplayable) { - return !$hideIfSingleStore; - } - - $result = true; - switch ($this->getScope()) { - case self::SCOPE_DEFAULT: - $result = (int)$showInDefault; - break; - case self::SCOPE_WEBSITES: - $result = (int)$showInWebsite; - break; - case self::SCOPE_STORES: - $result = (int)$showInStore; - break; - } - return $result; - } - /** * Retrieve current scope * @@ -782,13 +569,13 @@ class Mage_Backend_Block_System_Config_Form extends Mage_Backend_Block_Widget_Fo /** * Retrieve label for scope * - * @param array $element + * @param Mage_Backend_Model_Config_Structure_Element_Field $field * @return string */ - public function getScopeLabel($element) + public function getScopeLabel(Mage_Backend_Model_Config_Structure_Element_Field $field) { - $showInStore = isset($element['showInStore']) ? (int)$element['showInStore'] : 0; - $showInWebsite = isset($element['showInWebsite']) ? (int)$element['showInWebsite'] : 0; + $showInStore = $field->showInStore(); + $showInWebsite = $field->showInWebsite(); if ($showInStore == 1) { return $this->_scopeLabels[self::SCOPE_STORES]; diff --git a/app/code/core/Mage/Backend/Block/System/Config/Form/Field/Array/Abstract.php b/app/code/core/Mage/Backend/Block/System/Config/Form/Field/Array/Abstract.php index 6c463919b5c043df6b2d029e5ffcaaa2c6a1d17c..fbd7e6d91aa965d593ef6f4b97efd196793c44f8 100644 --- a/app/code/core/Mage/Backend/Block/System/Config/Form/Field/Array/Abstract.php +++ b/app/code/core/Mage/Backend/Block/System/Config/Form/Field/Array/Abstract.php @@ -93,10 +93,10 @@ abstract class Mage_Backend_Block_System_Config_Form_Field_Array_Abstract public function addColumn($name, $params) { $this->_columns[$name] = array( - 'label' => empty($params['label']) ? 'Column' : $params['label'], - 'size' => empty($params['size']) ? false : $params['size'], - 'style' => empty($params['style']) ? null : $params['style'], - 'class' => empty($params['class']) ? null : $params['class'], + 'label' => $this->_getParam($params, 'label', 'Column'), + 'size' => $this->_getParam($params, 'size', false), + 'style' => $this->_getParam($params, 'style'), + 'class' => $this->_getParam($params, 'class'), 'renderer' => false, ); if ((!empty($params['renderer'])) && ($params['renderer'] instanceof Mage_Core_Block_Abstract)) { @@ -104,6 +104,19 @@ abstract class Mage_Backend_Block_System_Config_Form_Field_Array_Abstract } } + /** + * Retrieve param + * + * @param array $params + * @param string $paramName + * @param mixed $defaultValue + * @return mixed + */ + protected function _getParam($params, $paramName, $defaultValue = null) + { + return empty($params[$paramName]) ? $defaultValue : $params[$paramName]; + } + /** * Get the grid and scripts contents * @@ -122,6 +135,7 @@ abstract class Mage_Backend_Block_System_Config_Form_Field_Array_Abstract * Prepare existing row data object * * @param Varien_Object + * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ protected function _prepareArrayRow(Varien_Object $row) { diff --git a/app/code/core/Mage/Api/Controller/Action.php b/app/code/core/Mage/Backend/Block/System/Config/Form/Field/Factory.php similarity index 59% rename from app/code/core/Mage/Api/Controller/Action.php rename to app/code/core/Mage/Backend/Block/System/Config/Form/Field/Factory.php index da4a74c7591fe824ad645f3c29b1c40b06481bb2..b666824c165aed837f00c88234b5ad7ff02abf8f 100644 --- a/app/code/core/Mage/Api/Controller/Action.php +++ b/app/code/core/Mage/Backend/Block/System/Config/Form/Field/Factory.php @@ -19,43 +19,37 @@ * needs please refer to http://www.magentocommerce.com for more information. * * @category Mage - * @package Mage_Api + * @package Mage_Backend * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ /** - * Generic API controller + * Mage_Backend_Block_System_Config_Form_Field object factory */ -class Mage_Api_Controller_Action extends Mage_Core_Controller_Front_Action +class Mage_Backend_Block_System_Config_Form_Field_Factory { /** - * Currently used area - * - * @var string + * @var Magento_ObjectManager */ - protected $_currentArea = 'adminhtml'; + protected $_objectManager; /** - * Use 'admin' store and prevent the session from starting - * - * @return Mage_Api_Controller_Action + * @param Magento_ObjectManager $objectManager */ - public function preDispatch() + public function __construct(Magento_ObjectManager $objectManager) { - Mage::app()->setCurrentStore('admin'); - $this->setFlag('', self::FLAG_NO_START_SESSION, 1); - parent::preDispatch(); - return $this; + $this->_objectManager = $objectManager; } /** - * Retrieve webservice server + * Create new config object * - * @return Mage_Api_Model_Server + * @param array $data + * @return Mage_Backend_Block_System_Config_Form_Field */ - protected function _getServer() + public function create(array $data = array()) { - return Mage::getSingleton('Mage_Api_Model_Server'); + return $this->_objectManager->get('Mage_Backend_Block_System_Config_Form_Field', $data); } } diff --git a/app/code/core/Mage/Backend/Block/System/Config/Form/Field/Heading.php b/app/code/core/Mage/Backend/Block/System/Config/Form/Field/Heading.php index 9f1880b2c972fa68b7bacd9584ffce3bf1cc6f26..67fa8b76e36de97095001528730622d15a584626 100644 --- a/app/code/core/Mage/Backend/Block/System/Config/Form/Field/Heading.php +++ b/app/code/core/Mage/Backend/Block/System/Config/Form/Field/Heading.php @@ -41,7 +41,6 @@ class Mage_Backend_Block_System_Config_Form_Field_Heading */ public function render(Varien_Data_Form_Element_Abstract $element) { - $useContainerId = $element->getData('use_container_id'); return sprintf('<tr class="system-fieldset-sub-head" id="row_%s"><td colspan="5"><h4 id="%s">%s</h4></td></tr>', $element->getHtmlId(), $element->getHtmlId(), $element->getLabel() ); diff --git a/app/code/core/Mage/Backend/Block/System/Config/Form/Field/Image.php b/app/code/core/Mage/Backend/Block/System/Config/Form/Field/Image.php index aed6537db751cf93bd49f14c2403fc94e2c39ee6..bd002b3e874a664a70884a58525cf29026930a67 100644 --- a/app/code/core/Mage/Backend/Block/System/Config/Form/Field/Image.php +++ b/app/code/core/Mage/Backend/Block/System/Config/Form/Field/Image.php @@ -47,9 +47,9 @@ class Mage_Backend_Block_System_Config_Form_Field_Image extends Varien_Data_Form $config = $this->getFieldConfig(); /* @var $config array */ if (array_key_exists('base_url', $config)) { - $el = $config['base_url']; - $urlType = empty($el['type']) ? 'link' : (string)$el['type']; - $url = Mage::getBaseUrl($urlType) . $el['value'] . '/' . $url; + $element = $config['base_url']; + $urlType = empty($element['type']) ? 'link' : (string)$element['type']; + $url = Mage::getBaseUrl($urlType) . $element['value'] . '/' . $url; } return $url; diff --git a/app/code/core/Mage/Backend/Block/System/Config/Form/Field/Select/Allowspecific.php b/app/code/core/Mage/Backend/Block/System/Config/Form/Field/Select/Allowspecific.php index 71fca226020b73c1d96bdb210e2ca6810ddd9c6a..b72f87e730a80758f457ad57b469974b74d99115 100644 --- a/app/code/core/Mage/Backend/Block/System/Config/Form/Field/Select/Allowspecific.php +++ b/app/code/core/Mage/Backend/Block/System/Config/Form/Field/Select/Allowspecific.php @@ -57,7 +57,7 @@ class Mage_Backend_Block_System_Config_Form_Field_Select_Allowspecific extends V */ public function getHtml() { - if(!$this->getValue() || 1 != $this->getValue()) { + if (!$this->getValue() || 1 != $this->getValue()) { $element = $this->getForm()->getElement($this->_getSpecificCountryElementId()); $element->setDisabled('disabled'); } diff --git a/app/code/core/Mage/Backend/Block/System/Config/Form/Fieldset.php b/app/code/core/Mage/Backend/Block/System/Config/Form/Fieldset.php index 20d00706fd51bfa212ddcf07eafbeff6c1fb286a..6927de08a00f4ea81bf336139da525911354a525 100644 --- a/app/code/core/Mage/Backend/Block/System/Config/Form/Fieldset.php +++ b/app/code/core/Mage/Backend/Block/System/Config/Form/Fieldset.php @@ -48,7 +48,11 @@ class Mage_Backend_Block_System_Config_Form_Fieldset $html = $this->_getHeaderHtml($element); foreach ($element->getSortedElements() as $field) { - $html .= $field->toHtml(); + if ($field instanceof Varien_Data_Form_Element_Fieldset) { + $html .= '<tr><td colspan="4">' . $field->toHtml() . '</td></tr>'; + } else { + $html .= $field->toHtml(); + } } $html .= $this->_getFooterHtml($element); @@ -66,11 +70,12 @@ class Mage_Backend_Block_System_Config_Form_Fieldset { $default = !$this->getRequest()->getParam('website') && !$this->getRequest()->getParam('store'); - $html = '<div class="entry-edit-head collapseable" ><a id="' . $element->getHtmlId() + $html = '<div><div>'; + $html .= '<div class="entry-edit-head collapseable" ><a id="' . $element->getHtmlId() . '-head" href="#" onclick="Fieldset.toggleCollapse(\'' . $element->getHtmlId() . '\', \'' . $this->getUrl('*/*/state') . '\'); return false;">' . $element->getLegend() . '</a></div>'; $html .= '<input id="'.$element->getHtmlId() . '-state" name="config_state[' . $element->getId() - . ']" type="hidden" value="' . (int)$this->_getCollapseState($element) . '" />'; + . ']" type="hidden" value="' . (int)$this->_isCollapseState($element) . '" />'; $html .= '<fieldset class="' . $this->_getFieldsetCss() . '" id="' . $element->getHtmlId() . '">'; $html .= '<legend>' . $element->getLegend() . '</legend>'; @@ -94,9 +99,10 @@ class Mage_Backend_Block_System_Config_Form_Fieldset */ protected function _getFieldsetCss() { + /** @var Mage_Backend_Model_Config_Structure_Element_Group $group */ $group = $this->getGroup(); - $configCss = isset($group['fieldset_css']) ? $group['fieldset_css'] : null; - return 'config collapseable' . ($configCss ? ' ' . $configCss : ''); + $configCss = $group->getFieldsetCss(); + return 'config collapseable' . ($configCss ? ' ' . $configCss: ''); } /** @@ -119,6 +125,7 @@ class Mage_Backend_Block_System_Config_Form_Fieldset } } $html .= '</fieldset>' . $this->_getExtraJs($element, $tooltipsExist); + $html .= '</div></div>'; return $html; } @@ -133,27 +140,27 @@ class Mage_Backend_Block_System_Config_Form_Fieldset */ protected function _getExtraJs($element, $tooltipsExist = false) { - $id = $element->getHtmlId(); - $js = "Fieldset.applyCollapse('{$id}');"; + $htmlId = $element->getHtmlId(); + $output = "Fieldset.applyCollapse('{$htmlId}');"; if ($tooltipsExist) { - $js.= "$$('#{$id} table')[0].addClassName('system-tooltip-wrap'); - $$('#{$id} table tbody tr').each(function(tr) { + $output.= "$$('#{$htmlId} table')[0].addClassName('system-tooltip-wrap'); + $$('#{$htmlId} table tbody tr').each(function(tr) { Event.observe(tr, 'mouseover', function (event) { var relatedTarget = $(event.relatedTarget || event.fromElement); - if(relatedTarget && (relatedTarget == this || relatedTarget.descendantOf(this))) { + if (relatedTarget && (relatedTarget == this || relatedTarget.descendantOf(this))) { return; } showTooltip(event); }); Event.observe(tr, 'mouseout', function (event) { var relatedTarget = $(event.relatedTarget || event.toElement); - if(relatedTarget && (relatedTarget == this || relatedTarget.childOf(this))) { + if (relatedTarget && (relatedTarget == this || relatedTarget.childOf(this))) { return; } hideTooltip(event); }); }); - $$('#{$id} table')[0].select('input','select').each(function(field) { + $$('#{$htmlId} table')[0].select('input','select').each(function(field) { Event.observe(field, 'focus', function (event) { showTooltip(event); }); @@ -168,7 +175,7 @@ class Mage_Backend_Block_System_Config_Form_Fieldset $$('div.system-tooltip-box').invoke('hide'); if ($(id)) { $(id).show().setStyle({height : tableHeight}); - if(document.viewport.getWidth() < 1200) { + if (document.viewport.getWidth() < 1200) { $(id).addClassName('system-tooltip-small').setStyle({height : 'auto'}); } else { $(id).removeClassName('system-tooltip-small'); @@ -183,7 +190,7 @@ class Mage_Backend_Block_System_Config_Form_Fieldset } };"; } - return $this->helper('Mage_Core_Helper_Js')->getScript($js); + return $this->helper('Mage_Core_Helper_Js')->getScript($output); } /** @@ -192,10 +199,10 @@ class Mage_Backend_Block_System_Config_Form_Fieldset * @param Varien_Data_Form_Element_Abstract $element * @return bool */ - protected function _getCollapseState($element) + protected function _isCollapseState($element) { - if ($element->getExpanded() !== null) { - return 1; + if ($element->getExpanded()) { + return true; } $extra = Mage::getSingleton('Mage_Backend_Model_Auth_Session')->getUser()->getExtra(); if (isset($extra['configState'][$element->getId()])) { diff --git a/app/code/core/Mage/Api/Model/Resource/Acl/Role.php b/app/code/core/Mage/Backend/Block/System/Config/Form/Fieldset/Factory.php old mode 100755 new mode 100644 similarity index 59% rename from app/code/core/Mage/Api/Model/Resource/Acl/Role.php rename to app/code/core/Mage/Backend/Block/System/Config/Form/Fieldset/Factory.php index ed780ccda0f3d5777e7d63140833adfcdfbf89ee..93d5b49f72156f2ed14e6ddd1a6f9ee9c0e1c675 --- a/app/code/core/Mage/Api/Model/Resource/Acl/Role.php +++ b/app/code/core/Mage/Backend/Block/System/Config/Form/Fieldset/Factory.php @@ -19,41 +19,37 @@ * needs please refer to http://www.magentocommerce.com for more information. * * @category Mage - * @package Mage_Api + * @package Mage_Backend * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ - /** - * ACL role resource - * - * @category Mage - * @package Mage_Api - * @author Magento Core Team <core@magentocommerce.com> + * Mage_Backend_Block_System_Config_Form_Fieldset object factory */ -class Mage_Api_Model_Resource_Acl_Role extends Mage_Core_Model_Resource_Db_Abstract +class Mage_Backend_Block_System_Config_Form_Fieldset_Factory { /** - * Resource initialization - * + * @var Magento_ObjectManager + */ + protected $_objectManager; + + /** + * @param Magento_ObjectManager $objectManager */ - protected function _construct() + public function __construct(Magento_ObjectManager $objectManager) { - $this->_init('api_role', 'role_id'); + $this->_objectManager = $objectManager; } /** - * Action before save + * Create new config object * - * @param Mage_Core_Model_Abstract $object - * @return Mage_Api_Model_Resource_Acl_Role + * @param array $data + * @return Mage_Backend_Block_System_Config_Form_Fieldset */ - protected function _beforeSave(Mage_Core_Model_Abstract $object) + public function create(array $data = array()) { - if (!$object->getId()) { - $this->setCreated(Mage::getSingleton('Mage_Core_Model_Date')->gmtDate()); - } - return $this; + return $this->_objectManager->get('Mage_Backend_Block_System_Config_Form_Fieldset', $data); } } diff --git a/app/code/core/Mage/Backend/Block/System/Config/Form/Fieldset/Modules/DisableOutput.php b/app/code/core/Mage/Backend/Block/System/Config/Form/Fieldset/Modules/DisableOutput.php index 4cd0f2fe1c027a2105c4a62f6680b0e1b86d2bd6..e2afeeabb25fe5ee9d5c5e05091f6ad1ba3f009d 100644 --- a/app/code/core/Mage/Backend/Block/System/Config/Form/Fieldset/Modules/DisableOutput.php +++ b/app/code/core/Mage/Backend/Block/System/Config/Form/Fieldset/Modules/DisableOutput.php @@ -126,7 +126,7 @@ class Mage_Backend_Block_System_Config_Form_Fieldset_Modules_DisableOutput $inherit = true; } - $e = $this->_getDummyElement(); + $element = $this->_getDummyElement(); $field = $fieldset->addField($moduleName, 'select', array( @@ -135,8 +135,8 @@ class Mage_Backend_Block_System_Config_Form_Fieldset_Modules_DisableOutput 'value' => $data, 'values' => $this->_getValues(), 'inherit' => $inherit, - 'can_use_default_value' => $this->getForm()->canUseDefaultValue($e), - 'can_use_website_value' => $this->getForm()->canUseWebsiteValue($e), + 'can_use_default_value' => $this->getForm()->canUseDefaultValue($element), + 'can_use_website_value' => $this->getForm()->canUseWebsiteValue($element), ))->setRenderer($this->_getFieldRenderer()); return $field->toHtml(); diff --git a/app/code/core/Mage/Backend/Block/System/Config/Switcher.php b/app/code/core/Mage/Backend/Block/System/Config/Switcher.php index e159d2455b0addfb4d644af82beb8072d55036fc..b9f8ff70b0fbdf3b1468bf6fdb1df90206bef03e 100644 --- a/app/code/core/Mage/Backend/Block/System/Config/Switcher.php +++ b/app/code/core/Mage/Backend/Block/System/Config/Switcher.php @@ -36,7 +36,7 @@ class Mage_Backend_Block_System_Config_Switcher extends Mage_Backend_Block_Templ } /** - * Enter description here... + * Retrieve list of available stores * * @return array */ @@ -58,54 +58,77 @@ class Mage_Backend_Block_System_Config_Switcher extends Mage_Backend_Block_Templ ); foreach ($storeModel->getWebsiteCollection() as $website) { - $websiteShow = false; - foreach ($storeModel->getGroupCollection() as $group) { - if ($group->getWebsiteId() != $website->getId()) { + $options = $this->_processWebsite($storeModel, $website, $section, $curStore, $curWebsite, $options); + } + + return $options; + } + + /** + * Process website info + * + * @param Mage_Core_Model_System_Store $storeModel + * @param Mage_Core_Model_Website $website + * @param string $section + * @param string $curStore + * @param string $curWebsite + * @param array $options + * @return array + */ + protected function _processWebsite( + Mage_Core_Model_System_Store $storeModel, + Mage_Core_Model_Website $website, + $section, + $curStore, + $curWebsite, + array $options + ) { + $websiteShow = false; + foreach ($storeModel->getGroupCollection() as $group) { + if ($group->getWebsiteId() != $website->getId()) { + continue; + } + $groupShow = false; + foreach ($storeModel->getStoreCollection() as $store) { + if ($store->getGroupId() != $group->getId()) { continue; } - $groupShow = false; - foreach ($storeModel->getStoreCollection() as $store) { - if ($store->getGroupId() != $group->getId()) { - continue; - } - if (!$websiteShow) { - $websiteShow = true; - $options['website_' . $website->getCode()] = array( - 'label' => $website->getName(), - 'url' => $this->getUrl('*/*/*', - array('section' => $section, 'website' => $website->getCode()) - ), - 'selected' => !$curStore && $curWebsite == $website->getCode(), - 'style' => 'padding-left:16px; background:#DDD; font-weight:bold;', - ); - } - if (!$groupShow) { - $groupShow = true; - $options['group_' . $group->getId() . '_open'] = array( - 'is_group' => true, - 'is_close' => false, - 'label' => $group->getName(), - 'style' => 'padding-left:32px;' - ); - } - $options['store_' . $store->getCode()] = array( - 'label' => $store->getName(), - 'url' => $this->getUrl('*/*/*', - array('section' => $section, 'website' => $website->getCode(), 'store' => $store->getCode()) + if (!$websiteShow) { + $websiteShow = true; + $options['website_' . $website->getCode()] = array( + 'label' => $website->getName(), + 'url' => $this->getUrl('*/*/*', + array('section' => $section, 'website' => $website->getCode()) ), - 'selected' => $curStore == $store->getCode(), - 'style' => '', + 'selected' => !$curStore && $curWebsite == $website->getCode(), + 'style' => 'padding-left:16px; background:#DDD; font-weight:bold;', ); } - if ($groupShow) { - $options['group_' . $group->getId() . '_close'] = array( - 'is_group' => true, - 'is_close' => true, + if (!$groupShow) { + $groupShow = true; + $options['group_' . $group->getId() . '_open'] = array( + 'is_group' => true, + 'is_close' => false, + 'label' => $group->getName(), + 'style' => 'padding-left:32px;' ); } + $options['store_' . $store->getCode()] = array( + 'label' => $store->getName(), + 'url' => $this->getUrl('*/*/*', + array('section' => $section, 'website' => $website->getCode(), 'store' => $store->getCode()) + ), + 'selected' => $curStore == $store->getCode(), + 'style' => '', + ); + } + if ($groupShow) { + $options['group_' . $group->getId() . '_close'] = array( + 'is_group' => true, + 'is_close' => true, + ); } } - return $options; } diff --git a/app/code/core/Mage/Backend/Block/System/Config/Tabs.php b/app/code/core/Mage/Backend/Block/System/Config/Tabs.php index 2a6195a276b3398432389fe072400d2bdf66d82c..b5657f31802dc92da63e19b2e1ad3d87b66d6f08 100644 --- a/app/code/core/Mage/Backend/Block/System/Config/Tabs.php +++ b/app/code/core/Mage/Backend/Block/System/Config/Tabs.php @@ -33,38 +33,44 @@ * @category Mage * @package Mage_Backend * @author Magento Core Team <core@magentocommerce.com> + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class Mage_Backend_Block_System_Config_Tabs extends Mage_Backend_Block_Widget { - /** * Tabs * - * @var array + * @var Mage_Backend_Model_Config_Structure_Element_Iterator */ protected $_tabs; /** - * @var Mage_Backend_Model_Config_StructureInterface + * Block template filename + * + * @var string */ - protected $_systemConfig; + protected $_template = 'system/config/tabs.phtml'; /** - * Block template filename + * Currently selected section id * * @var string */ - protected $_template = 'system/config/tabs.phtml'; + protected $_currentSectionId; /** - * @var Varien_Data_Collection_Factory + * Current website code + * + * @var string */ - protected $_collectionFactory; + protected $_websiteCode; /** - * @var Varien_Object_Factory + * Current store code + * + * @var string */ - protected $_objectFactory; + protected $_storeCode; /** * @param Mage_Core_Controller_Request_Http $request @@ -78,8 +84,7 @@ class Mage_Backend_Block_System_Config_Tabs extends Mage_Backend_Block_Widget * @param Mage_Core_Model_Store_Config $storeConfig * @param Mage_Core_Controller_Varien_Front $frontController * @param Mage_Core_Model_Factory_Helper $helperFactory - * @param Varien_Data_Collection_Factory $collectionFactory - * @param Varien_Object_Factory $objectFactory + * @param Mage_Backend_Model_Config_Structure $configStructure * @param array $data * * @SuppressWarnings(PHPMD.ExcessiveParameterList) @@ -96,201 +101,25 @@ class Mage_Backend_Block_System_Config_Tabs extends Mage_Backend_Block_Widget Mage_Core_Model_Store_Config $storeConfig, Mage_Core_Controller_Varien_Front $frontController, Mage_Core_Model_Factory_Helper $helperFactory, - Varien_Data_Collection_Factory $collectionFactory, - Varien_Object_Factory $objectFactory, + Mage_Backend_Model_Config_Structure $configStructure, array $data = array() ) { parent::__construct($request, $layout, $eventManager, $urlBuilder, $translator, $cache, $designPackage, $session, $storeConfig, $frontController, $helperFactory, $data ); - $this->_collectionFactory = $collectionFactory; - $this->_objectFactory = $objectFactory; - } - - - protected function _construct() - { - parent::_construct(); - $this->_systemConfig = $this->hasData('systemConfig') ? - $this->getData('systemConfig') : - Mage::getSingleton('Mage_Backend_Model_Config_Structure_Reader')->getConfiguration(); + $this->_tabs = $configStructure->getTabs(); $this->setId('system_config_tabs'); $this->setTitle($this->helper('Mage_Backend_Helper_Data')->__('Configuration')); - } + $this->_currentSectionId = $this->getRequest()->getParam('section'); - /** - * Sort sections/tabs - * - * @param mixed $a - * @param mixed $b - * @return int - */ - protected function _sort($a, $b) - { - $aSortOrder = isset($a['sortOrder']) ? (int)$a['sortOrder'] : 0; - $bSortOrder = isset($b['sortOrder']) ? (int)$b['sortOrder'] : 0; - return $aSortOrder < $bSortOrder ? -1 : ($aSortOrder > $bSortOrder ? 1 : 0); - } - - /** - * Initialize tabs - * - * @return Mage_Backend_Block_System_Config_Tabs - */ - public function initTabs() - { - $sections = $this->_systemConfig->getSections(); - $tabs = $this->_systemConfig->getTabs(); - - usort($sections, array($this, '_sort')); - usort($tabs, array($this, '_sort')); - - $this->_initializeTabs($tabs); - $current = $this->_initializeSections($sections); - - /** Set last sections */ - - /** @var Varien_Object $tab */ - foreach ($this->getTabs() as $tab) { - $sections = $tab->getSections(); - if ($sections) { - $sections->getLastItem()->setIsLast(true); - } - } - $this->helper('Mage_Backend_Helper_Data')->addPageHelpUrl($current . '/'); - - return $this; - } - - /** - * Initialize sections - * - * @param $sections - * @return string - */ - protected function _initializeSections($sections) - { - $current = $this->getRequest()->getParam('section'); - $websiteCode = $this->getRequest()->getParam('website'); - $storeCode = $this->getRequest()->getParam('store'); - - /** @var $section array */ - foreach ($sections as $section) { - $this->_eventManager->dispatch('adminhtml_block_system_config_init_tab_sections_before', - array('section' => $section) - ); - - $code = $section['id']; - $sectionAllowed = false; - if (isset($section['resource'])) { - $sectionAllowed = $this->checkSectionPermissions($section['resource']); - } - if ((empty($current) && $sectionAllowed)) { - $current = $code; - $this->getRequest()->setParam('section', $current); - } - - $helperName = $this->_systemConfig->getAttributeModule($section); - $label = $this->helper($helperName)->__($section['label']); - - if ($code == $current) { - if (!$this->getRequest()->getParam('website') && !$this->getRequest()->getParam('store')) { - $this->_addBreadcrumb($label); - } else { - $this->_addBreadcrumb($label, '', $this->getUrl('*/*/*', array('section' => $code))); - } - - $this->setActiveTab($section['tab']); - $this->setActiveSection($code); - } - - $hasChildren = $this->_systemConfig->hasChildren($section, $websiteCode, $storeCode); - if ($sectionAllowed && $hasChildren) { - $this->addSection($code, $section['tab'], array( - 'class' => isset($section['class']) ? $section['class'] : '', - 'label' => $label, - 'url' => $this->getUrl('*/*/*', array('_current' => true, 'section' => $code)), - )); - } - } - - return $current; - } - - /** - * Initialize tabs - * - * @param array $tabs - * @return void - */ - protected function _initializeTabs(array $tabs) - { - foreach ($tabs as $tab) { - $helperName = $this->_systemConfig->getAttributeModule($tab); - $label = $this->helper($helperName)->__($tab['label']); - - $this->addTab($tab['id'], array( - 'label' => $label, - 'class' => isset($tab['class']) ? $tab['class'] : '' - )); - } - } - - /** - * Add tab to tabs list - * - * @param string $code - * @param array $config - * @return Mage_Backend_Block_System_Config_Tabs - */ - public function addTab($code, $config) - { - $tab = $this->_objectFactory->create($config); - $tab->setId($code); - $this->_tabs[$code] = $tab; - return $this; - } - - /** - * Retrieve tab - * - * @param string $code - * @return Varien_Object - */ - public function getTab($code) - { - if(isset($this->_tabs[$code])) { - return $this->_tabs[$code]; - } - return null; - } - - /** - * Add section to tab - * - * @param string $code - * @param string $tabCode - * @param array $config - * @return Mage_Backend_Block_System_Config_Tabs - */ - public function addSection($code, $tabCode, $config) - { - if($tab = $this->getTab($tabCode)) { - if(!$tab->getSections()) { - $tab->setSections($this->_collectionFactory->create()); - } - $section = $this->_objectFactory->create($config); - $section->setId($code); - $tab->getSections()->addItem($section); - } - return $this; + $this->helper('Mage_Backend_Helper_Data')->addPageHelpUrl($this->getRequest()->getParam('section') . '/'); } /** * Get all tabs * - * @return Varien_Object[] + * @return Mage_Backend_Model_Config_Structure_Element_Iterator */ public function getTabs() { @@ -298,144 +127,25 @@ class Mage_Backend_Block_System_Config_Tabs extends Mage_Backend_Block_Widget } /** - * Get store select options - * - * @return array - */ - public function getStoreSelectOptions() - { - $section = $this->getRequest()->getParam('section'); - $curWebsite = $this->getRequest()->getParam('website'); - $curStore = $this->getRequest()->getParam('store'); - - /* @var $storeModel Mage_Core_Model_System_Store */ - $storeModel = Mage::getSingleton('Mage_Core_Model_System_Store'); - - $options = array(); - $options['default'] = array( - 'label' => $this->helper('Mage_Backend_Helper_Data')->__('Default Config'), - 'url' => $this->getUrl('*/*/*', array('section' => $section)), - 'selected' => !$curWebsite && !$curStore, - 'style' => 'background:#ccc; font-weight:bold;', - ); - - foreach ($storeModel->getWebsiteCollection() as $website) { - $websiteShow = false; - foreach ($storeModel->getGroupCollection() as $group) { - if ($group->getWebsiteId() != $website->getId()) { - continue; - } - $groupShow = false; - foreach ($storeModel->getStoreCollection() as $store) { - if ($store->getGroupId() != $group->getId()) { - continue; - } - if (!$websiteShow) { - $websiteShow = true; - $options['website_' . $website->getCode()] = array( - 'label' => $website->getName(), - 'url' => $this->getUrl('*/*/*', - array('section' => $section, 'website' => $website->getCode()) - ), - 'selected' => !$curStore && $curWebsite == $website->getCode(), - 'style' => 'padding-left:16px; background:#DDD; font-weight:bold;', - ); - } - if (!$groupShow) { - $groupShow = true; - $options['group_' . $group->getId() . '_open'] = array( - 'is_group' => true, - 'is_close' => false, - 'label' => $group->getName(), - 'style' => 'padding-left:32px;' - ); - } - $options['store_' . $store->getCode()] = array( - 'label' => $store->getName(), - 'url' => $this->getUrl('*/*/*', - array('section'=>$section, 'website' => $website->getCode(), 'store' => $store->getCode()) - ), - 'selected' => $curStore == $store->getCode(), - 'style' => '', - ); - } - if ($groupShow) { - $options['group_' . $group->getId() . '_close'] = array( - 'is_group' => true, - 'is_close' => true, - ); - } - } - } - - return $options; - } - - /** - * Get store button html code + * Retrieve section url by section id * + * @param Mage_Backend_Model_Config_Structure_Element_Section $section * @return string */ - public function getStoreButtonsHtml() + public function getSectionUrl(Mage_Backend_Model_Config_Structure_Element_Section $section) { - $curWebsite = $this->getRequest()->getParam('website'); - $curStore = $this->getRequest()->getParam('store'); - - $html = ''; - - if (!$curWebsite && !$curStore) { - $html .= $this->getLayout()->createBlock('Mage_Backend_Block_Widget_Button')->setData(array( - 'label' => $this->helper('Mage_Backend_Helper_Data')->__('New Website'), - 'onclick' => "location.href='" . $this->getUrl('*/system_website/new') . "'", - 'class' => 'add', - ))->toHtml(); - } elseif (!$curStore) { - $html .= $this->getLayout()->createBlock('Mage_Backend_Block_Widget_Button')->setData(array( - 'label' => $this->helper('Mage_Backend_Helper_Data')->__('Edit Website'), - 'onclick' => "location.href='" . - $this->getUrl('*/system_website/edit', array('website'=>$curWebsite)) . "'", - ))->toHtml(); - $html .= $this->getLayout()->createBlock('Mage_Backend_Block_Widget_Button')->setData(array( - 'label' => $this->helper('Mage_Backend_Helper_Data')->__('New Store View'), - 'onclick' => "location.href='" . - $this->getUrl('*/system_store/new', array('website'=>$curWebsite)) . "'", - 'class' => 'add', - ))->toHtml(); - $html .= $this->getLayout()->createBlock('Mage_Backend_Block_Widget_Button')->setData(array( - 'label' => $this->helper('Mage_Backend_Helper_Data')->__('Delete Website'), - 'onclick' => "location.href='" . - $this->getUrl('*/system_website/delete', array('website'=>$curWebsite)) . "'", - 'class' => 'delete', - ))->toHtml(); - } else { - $html .= $this->getLayout()->createBlock('Mage_Backend_Block_Widget_Button')->setData(array( - 'label' => $this->helper('Mage_Backend_Helper_Data')->__('Edit Store View'), - 'onclick' => "location.href='" . - $this->getUrl('*/system_store/edit', array('store'=>$curStore)) . - "'", - ))->toHtml(); - $html .= $this->getLayout()->createBlock('Mage_Backend_Block_Widget_Button')->setData(array( - 'label' => $this->helper('Mage_Backend_Helper_Data')->__('Delete Store View'), - 'onclick' => "location.href='" . - $this->getUrl('*/system_store/delete', array('store'=>$curStore)) . "'", - 'class' => 'delete', - ))->toHtml(); - } - - return $html; + return $this->getUrl('*/*/*', array('_current' => true, 'section' => $section->getId())); } /** - * Check if specified section can be displayed + * Check whether section should be displayed as active * - * @param string $aclResourceId + * @param Mage_Backend_Model_Config_Structure_Element_Section $section * @return bool */ - public function checkSectionPermissions($aclResourceId) + public function isSectionActive(Mage_Backend_Model_Config_Structure_Element_Section $section) { - if (!$aclResourceId || trim($aclResourceId) == "") { - return false; - } - return Mage::getSingleton('Mage_Core_Model_Authorization')->isAllowed($aclResourceId); + return $section->getId() == $this->_currentSectionId; } } + diff --git a/app/code/core/Mage/Backend/Block/Template.php b/app/code/core/Mage/Backend/Block/Template.php index d01d7f3289d7281438a0555daae6c4cc97f74a25..9b114fbc07531a749a551c7aa202f5587ad27c9f 100644 --- a/app/code/core/Mage/Backend/Block/Template.php +++ b/app/code/core/Mage/Backend/Block/Template.php @@ -102,7 +102,7 @@ class Mage_Backend_Block_Template extends Mage_Core_Block_Template */ protected function _toHtml() { - Mage::dispatchEvent('adminhtml_block_html_before', array('block' => $this)); + $this->_eventManager->dispatch('adminhtml_block_html_before', array('block' => $this)); return parent::_toHtml(); } } diff --git a/app/code/core/Mage/Backend/Block/Widget.php b/app/code/core/Mage/Backend/Block/Widget.php index 6cfda505637dfee8ee40c8c3e4d79d8d0f2ae3ce..7bb18459fcc007555611e4cf6602e0ffd4b63d9b 100644 --- a/app/code/core/Mage/Backend/Block/Widget.php +++ b/app/code/core/Mage/Backend/Block/Widget.php @@ -82,24 +82,28 @@ class Mage_Backend_Block_Widget extends Mage_Backend_Block_Template * @param string $label * @param string $onclick * @param string $class - * @param string $id + * @param string $buttonId * @return string */ - public function getButtonHtml($label, $onclick, $class='', $id=null) { + public function getButtonHtml($label, $onclick, $class = '', $buttonId = null) + { return $this->getLayout()->createBlock('Mage_Backend_Block_Widget_Button') ->setData(array( 'label' => $label, 'onclick' => $onclick, 'class' => $class, 'type' => 'button', - 'id' => $id, + 'id' => $buttonId, )) ->toHtml(); } public function getGlobalIcon() { - return '<img src="'.$this->getViewFileUrl('images/fam_link.gif').'" alt="'.$this->__('Global Attribute').'" title="'.$this->__('This attribute shares the same value in all the stores').'" class="attribute-global"/>'; + return '<img src="' . $this->getViewFileUrl('images/fam_link.gif') + . '" alt="' . $this->__('Global Attribute') + . '" title="' . $this->__('This attribute shares the same value in all the stores') + . '" class="attribute-global"/>'; } } diff --git a/app/code/core/Mage/Backend/Block/Widget/Breadcrumbs.php b/app/code/core/Mage/Backend/Block/Widget/Breadcrumbs.php index bc21c922ef205a1929b374323dbe749d6f81f390..9daa65542400c87bd2eea8be36f3d3096b57e8b9 100644 --- a/app/code/core/Mage/Backend/Block/Widget/Breadcrumbs.php +++ b/app/code/core/Mage/Backend/Block/Widget/Breadcrumbs.php @@ -42,11 +42,11 @@ class Mage_Backend_Block_Widget_Breadcrumbs extends Mage_Backend_Block_Template protected $_template = 'Mage_Backend::widget/breadcrumbs.phtml'; - protected function _construct() { - - $this->addLink(Mage::helper('Mage_Backend_Helper_Data')->__('Home'), Mage::helper('Mage_Backend_Helper_Data')->__('Home'), $this->getUrl('*')); + $this->addLink(Mage::helper('Mage_Backend_Helper_Data')->__('Home'), + Mage::helper('Mage_Backend_Helper_Data')->__('Home'), $this->getUrl('*') + ); } public function addLink($label, $title=null, $url=null) diff --git a/app/code/core/Mage/Backend/Block/Widget/Button.php b/app/code/core/Mage/Backend/Block/Widget/Button.php index 59509702923a601e4ecb4c5fa89c7a671ae3a764..a36edc5fcdfd8c5c907ed523c4d4903b7a285f5f 100644 --- a/app/code/core/Mage/Backend/Block/Widget/Button.php +++ b/app/code/core/Mage/Backend/Block/Widget/Button.php @@ -72,16 +72,21 @@ class Mage_Backend_Block_Widget_Button extends Mage_Backend_Block_Widget */ public function getAttributesHtml() { + $disabled = $this->getDisabled() ? 'disabled' : ''; + $title = $this->getTitle(); + if (!$title) { + $title = $this->getLabel(); + } $attributes = array( 'id' => $this->getId(), 'name' => $this->getElementName(), - 'title' => $this->getTitle() ? $this->getTitle() : $this->getLabel(), + 'title' => $title, 'type' => $this->getType(), - 'class' => 'scalable ' . $this->getClass() . ($this->getDisabled() ? ' disabled' : ''), + 'class' => 'scalable ' . $this->getClass() . ' ' . $disabled, 'onclick' => $this->getOnClick(), 'style' => $this->getStyle(), 'value' => $this->getValue(), - 'disabled' => $this->getDisabled() ? 'disabled' : '' + 'disabled' => $disabled ); if ($this->getDataAttr()) { foreach ($this->getDataAttr() as $key => $attr) { diff --git a/app/code/core/Mage/Backend/Block/Widget/Container.php b/app/code/core/Mage/Backend/Block/Widget/Container.php index 240f20eed1b08a8b122ac4d4b5ff64a91824d651..de4dc3a5f23ac266a956042900884273dcfc6a30 100644 --- a/app/code/core/Mage/Backend/Block/Widget/Container.php +++ b/app/code/core/Mage/Backend/Block/Widget/Container.php @@ -63,30 +63,30 @@ class Mage_Backend_Block_Widget_Container extends Mage_Backend_Block_Template /** * Add a button * - * @param string $id + * @param string $buttonId * @param array $data * @param integer $level * @param integer $sortOrder * @param string|null $region, that button should be displayed in ('header', 'footer', null) * @return Mage_Backend_Block_Widget_Container */ - protected function _addButton($id, $data, $level = 0, $sortOrder = 0, $region = 'header') + protected function _addButton($buttonId, $data, $level = 0, $sortOrder = 0, $region = 'header') { if (!isset($this->_buttons[$level])) { $this->_buttons[$level] = array(); } if (empty($data['id'])) { - $data['id'] = $id; + $data['id'] = $buttonId; } - $this->_buttons[$level][$id] = $data; - $this->_buttons[$level][$id]['region'] = $region; - if (empty($this->_buttons[$level][$id]['id'])) { - $this->_buttons[$level][$id]['id'] = $id; + $this->_buttons[$level][$buttonId] = $data; + $this->_buttons[$level][$buttonId]['region'] = $region; + if (empty($this->_buttons[$level][$buttonId]['id'])) { + $this->_buttons[$level][$buttonId]['id'] = $buttonId; } if ($sortOrder) { - $this->_buttons[$level][$id]['sort_order'] = $sortOrder; + $this->_buttons[$level][$buttonId]['sort_order'] = $sortOrder; } else { - $this->_buttons[$level][$id]['sort_order'] = count($this->_buttons[$level]) * 10; + $this->_buttons[$level][$buttonId]['sort_order'] = count($this->_buttons[$level]) * 10; } return $this; } @@ -94,29 +94,29 @@ class Mage_Backend_Block_Widget_Container extends Mage_Backend_Block_Template /** * Public wrapper for protected _addButton method * - * @param string $id + * @param string $buttonId * @param array $data * @param integer $level * @param integer $sortOrder * @param string|null $region, that button should be displayed in ('header', 'footer', null) * @return Mage_Backend_Block_Widget_Container */ - public function addButton($id, $data, $level = 0, $sortOrder = 0, $region = 'header') + public function addButton($buttonId, $data, $level = 0, $sortOrder = 0, $region = 'header') { - return $this->_addButton($id, $data, $level, $sortOrder, $region); + return $this->_addButton($buttonId, $data, $level, $sortOrder, $region); } /** * Remove existing button * - * @param string $id + * @param string $buttonId * @return Mage_Backend_Block_Widget_Container */ - protected function _removeButton($id) + protected function _removeButton($buttonId) { foreach ($this->_buttons as $level => $buttons) { - if (isset($buttons[$id])) { - unset($this->_buttons[$level][$id]); + if (isset($buttons[$buttonId])) { + unset($this->_buttons[$level][$buttonId]); } } return $this; @@ -125,38 +125,38 @@ class Mage_Backend_Block_Widget_Container extends Mage_Backend_Block_Template /** * Public wrapper for the _removeButton() method * - * @param string $id + * @param string $buttonId * @return Mage_Backend_Block_Widget_Container */ - public function removeButton($id) + public function removeButton($buttonId) { - return $this->_removeButton($id); + return $this->_removeButton($buttonId); } /** * Update specified button property * - * @param string $id + * @param string $buttonId * @param string|null $key * @param mixed $data * @return Mage_Backend_Block_Widget_Container */ - protected function _updateButton($id, $key=null, $data) + protected function _updateButton($buttonId, $key=null, $data) { foreach ($this->_buttons as $level => $buttons) { - if (isset($buttons[$id])) { + if (isset($buttons[$buttonId])) { if (!empty($key)) { - if ($child = $this->getChildBlock($id . '_button')) { + if ($child = $this->getChildBlock($buttonId . '_button')) { $child->setData($key, $data); } if ('level' == $key) { - $this->_buttons[$data][$id] = $this->_buttons[$level][$id]; - unset($this->_buttons[$level][$id]); + $this->_buttons[$data][$buttonId] = $this->_buttons[$level][$buttonId]; + unset($this->_buttons[$level][$buttonId]); } else { - $this->_buttons[$level][$id][$key] = $data; + $this->_buttons[$level][$buttonId][$key] = $data; } } else { - $this->_buttons[$level][$id] = $data; + $this->_buttons[$level][$buttonId] = $data; } break; } @@ -167,14 +167,14 @@ class Mage_Backend_Block_Widget_Container extends Mage_Backend_Block_Template /** * Public wrapper for protected _updateButton method * - * @param string $id + * @param string $buttonId * @param string|null $key * @param mixed $data * @return Mage_Backend_Block_Widget_Container */ - public function updateButton($id, $key=null, $data) + public function updateButton($buttonId, $key = null, $data) { - return $this->_updateButton($id, $key, $data); + return $this->_updateButton($buttonId, $key, $data); } /** @@ -184,9 +184,9 @@ class Mage_Backend_Block_Widget_Container extends Mage_Backend_Block_Template */ protected function _prepareLayout() { - foreach ($this->_buttons as $level => $buttons) { - foreach ($buttons as $id => $data) { - $childId = $this->_prepareButtonBlockId($id); + foreach ($this->_buttons as $buttons) { + foreach ($buttons as $buttonId => $data) { + $childId = $this->_prepareButtonBlockId($buttonId); $blockClassName = isset($data['class_name']) ? $data['class_name'] : null; $this->_addButtonChildBlock($childId, $blockClassName); } @@ -197,12 +197,12 @@ class Mage_Backend_Block_Widget_Container extends Mage_Backend_Block_Template /** * Prepare block id for button's id * - * @param string $id + * @param string $buttonId * @return string */ - protected function _prepareButtonBlockId($id) + protected function _prepareButtonBlockId($buttonId) { - return $id . '_button'; + return $buttonId . '_button'; } /** @@ -217,7 +217,7 @@ class Mage_Backend_Block_Widget_Container extends Mage_Backend_Block_Template if (null === $blockClassName) { $blockClassName = 'Mage_Backend_Block_Widget_Button'; } - $block = $this->getLayout()->createBlock($blockClassName, $this->getNameInLayout() . '-' . $childId); + $block = $this->getLayout()->createBlock($blockClassName, $this->getNameInLayout() . '-' . $childId); $this->setChild($childId, $block); return $block; } @@ -231,20 +231,15 @@ class Mage_Backend_Block_Widget_Container extends Mage_Backend_Block_Template public function getButtonsHtml($region = null) { $out = ''; - foreach ($this->_buttons as $level => $buttons) { - $_buttons = array(); - foreach ($buttons as $id => $data) { - $_buttons[$data['sort_order']]['id'] = $id; - $_buttons[$data['sort_order']]['data'] = $data; - } - ksort($_buttons); + foreach ($this->_buttons as $buttons) { + $_buttons = $this->_sortButtons($buttons); foreach ($_buttons as $button) { - $id = $button['id']; + $buttonId = $button['id']; $data = $button['data']; if ($region && isset($data['region']) && ($region != $data['region'])) { continue; } - $childId = $this->_prepareButtonBlockId($id); + $childId = $this->_prepareButtonBlockId($buttonId); $child = $this->getChildBlock($childId); if (!$child) { @@ -262,6 +257,23 @@ class Mage_Backend_Block_Widget_Container extends Mage_Backend_Block_Template return $out; } + /** + * Sort buttons by sort order + * + * @param array $buttons + * @return array + */ + public function _sortButtons($buttons) + { + $_buttons = array(); + foreach ($buttons as $buttonId => $data) { + $_buttons[$data['sort_order']]['id'] = $buttonId; + $_buttons[$data['sort_order']]['data'] = $data; + } + ksort($_buttons); + return $_buttons; + } + /** * Get header text * @@ -299,8 +311,8 @@ class Mage_Backend_Block_Widget_Container extends Mage_Backend_Block_Template */ public function hasFooterButtons() { - foreach ($this->_buttons as $level => $buttons) { - foreach ($buttons as $id => $data) { + foreach ($this->_buttons as $buttons) { + foreach ($buttons as $data) { if (isset($data['region']) && ('footer' == $data['region'])) { return true; } @@ -316,7 +328,7 @@ class Mage_Backend_Block_Widget_Container extends Mage_Backend_Block_Template */ protected function _toHtml() { - Mage::dispatchEvent('adminhtml_widget_container_html_before', array('block' => $this)); + $this->_eventManager->dispatch('adminhtml_widget_container_html_before', array('block' => $this)); return parent::_toHtml(); } } diff --git a/app/code/core/Mage/Backend/Block/Widget/Form.php b/app/code/core/Mage/Backend/Block/Widget/Form.php index 52db3ccfa25b4d6cfd35d2f3d8b7e7a07a17993f..d9f99b967c89f05b44fb41a8df5f5f844fb1456e 100644 --- a/app/code/core/Mage/Backend/Block/Widget/Form.php +++ b/app/code/core/Mage/Backend/Block/Widget/Form.php @@ -33,7 +33,6 @@ */ class Mage_Backend_Block_Widget_Form extends Mage_Backend_Block_Widget { - /** * Form Object * @@ -119,7 +118,7 @@ class Mage_Backend_Block_Widget_Form extends Mage_Backend_Block_Widget { $this->_form = $form; $this->_form->setParent($this); - $this->_form->setBaseUrl(Mage::getBaseUrl()); + $this->_form->setBaseUrl($this->_urlBuilder->getBaseUrl()); return $this; } @@ -168,7 +167,7 @@ class Mage_Backend_Block_Widget_Form extends Mage_Backend_Block_Widget $this->_addElementTypes($fieldset); foreach ($attributes as $attribute) { /* @var $attribute Mage_Eav_Model_Entity_Attribute */ - if (!$attribute || ($attribute->hasIsVisible() && !$attribute->getIsVisible())) { + if (!$this->_isAttributeVisible($attribute)) { continue; } if ( ($inputType = $attribute->getFrontend()->getInputType()) @@ -196,21 +195,50 @@ class Mage_Backend_Block_Widget_Form extends Mage_Backend_Block_Widget $element->setAfterElementHtml($this->_getAdditionalElementHtml($element)); - if ($inputType == 'select') { - $element->setValues($attribute->getSource()->getAllOptions(true, true)); - } else if ($inputType == 'multiselect') { - $element->setValues($attribute->getSource()->getAllOptions(false, true)); - $element->setCanBeEmpty(true); - } else if ($inputType == 'date') { - $element->setImage($this->getViewFileUrl('images/grid-cal.gif')); - $element->setDateFormat(Mage::app()->getLocale()->getDateFormatWithLongYear()); - } else if ($inputType == 'multiline') { - $element->setLineCount($attribute->getMultilineCount()); - } + $this->_applyTypeSpecificConfig($inputType, $element, $attribute); } } } + /** + * Check whether attribute is visible + * + * @param Mage_Eav_Model_Entity_Attribute $attribute + * @return bool + */ + protected function _isAttributeVisible(Mage_Eav_Model_Entity_Attribute $attribute) + { + return !(!$attribute || ($attribute->hasIsVisible() && !$attribute->getIsVisible())); + } + /** + * Apply configuration specific for different element type + * + * @param string $inputType + * @param Varien_Data_Form_Element_Abstract $element + * @param Mage_Eav_Model_Entity_Attribute $attribute + */ + protected function _applyTypeSpecificConfig($inputType, $element, Mage_Eav_Model_Entity_Attribute $attribute) + { + switch ($inputType) { + case 'select': + $element->setValues($attribute->getSource()->getAllOptions(true, true)); + break; + case 'multiselect': + $element->setValues($attribute->getSource()->getAllOptions(false, true)); + $element->setCanBeEmpty(true); + break; + case 'date': + $element->setImage($this->getViewFileUrl('images/grid-cal.gif')); + $element->setDateFormat(Mage::app()->getLocale()->getDateFormatWithLongYear()); + break; + case 'multiline': + $element->setLineCount($attribute->getMultilineCount()); + break; + default: + break; + } + } + /** * Add new element type * @@ -235,10 +263,11 @@ class Mage_Backend_Block_Widget_Form extends Mage_Backend_Block_Widget } /** - * Enter description here... + * Render additional element * * @param Varien_Data_Form_Element_Abstract $element * @return string + * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ protected function _getAdditionalElementHtml($element) { diff --git a/app/code/core/Mage/Backend/Block/Widget/Form/Container.php b/app/code/core/Mage/Backend/Block/Widget/Form/Container.php index 675da9e9b80d19f3f8e808f477352c39e6468a9a..00b3e4e96525d9e0ce9fc31ff8eca52cedcd8e62 100644 --- a/app/code/core/Mage/Backend/Block/Widget/Form/Container.php +++ b/app/code/core/Mage/Backend/Block/Widget/Form/Container.php @@ -48,12 +48,12 @@ class Mage_Backend_Block_Widget_Form_Container extends Mage_Backend_Block_Widget parent::_construct(); $this->_addButton('back', array( - 'label' => Mage::helper('Mage_Backend_Helper_Data')->__('Back'), + 'label' => $this->__('Back'), 'onclick' => 'setLocation(\'' . $this->getBackUrl() . '\')', 'class' => 'back', ), -1); $this->_addButton('reset', array( - 'label' => Mage::helper('Mage_Backend_Helper_Data')->__('Reset'), + 'label' => $this->__('Reset'), 'onclick' => 'setLocation(window.location.href)', ), -1); @@ -61,15 +61,15 @@ class Mage_Backend_Block_Widget_Form_Container extends Mage_Backend_Block_Widget if (! empty($objId)) { $this->_addButton('delete', array( - 'label' => Mage::helper('Mage_Backend_Helper_Data')->__('Delete'), + 'label' => $this->__('Delete'), 'class' => 'delete', - 'onclick' => 'deleteConfirm(\''. Mage::helper('Mage_Backend_Helper_Data')->__('Are you sure you want to do this?') - .'\', \'' . $this->getDeleteUrl() . '\')', + 'onclick' => 'deleteConfirm(\'' . $this->__('Are you sure you want to do this?') + . '\', \'' . $this->getDeleteUrl() . '\')', )); } $this->_addButton('save', array( - 'label' => Mage::helper('Mage_Backend_Helper_Data')->__('Save'), + 'label' => $this->__('Save'), 'class' => 'save', 'data_attr' => array( 'widget-button' => array('event' => 'save', 'related' => '#edit_form') diff --git a/app/code/core/Mage/Backend/Block/Widget/Form/Element/Dependence.php b/app/code/core/Mage/Backend/Block/Widget/Form/Element/Dependence.php index 32cd1370e40e187b42111f024d09ad4c17ef1132..78ed61b6599888fda560900f825c54711e00c354 100644 --- a/app/code/core/Mage/Backend/Block/Widget/Form/Element/Dependence.php +++ b/app/code/core/Mage/Backend/Block/Widget/Form/Element/Dependence.php @@ -107,7 +107,8 @@ class Mage_Backend_Block_Widget_Form_Element_Dependence extends Mage_Backend_Blo } return '<script type="text/javascript"> new FormElementDependenceController(' . $this->_getDependsJson() - . ($this->_configOptions ? ', ' . Mage::helper('Mage_Core_Helper_Data')->jsonEncode($this->_configOptions) : '') + . ($this->_configOptions ? ', ' + . Mage::helper('Mage_Core_Helper_Data')->jsonEncode($this->_configOptions) : '') . '); </script>'; } diff --git a/app/code/core/Mage/Backend/Block/Widget/Grid.php b/app/code/core/Mage/Backend/Block/Widget/Grid.php index 678acfb24025a115865db4a2ae9e2fee83be4f6f..dcf2b3947eeadd34830a8d05e74d00b04a2b47ab 100644 --- a/app/code/core/Mage/Backend/Block/Widget/Grid.php +++ b/app/code/core/Mage/Backend/Block/Widget/Grid.php @@ -316,11 +316,9 @@ class Mage_Backend_Block_Widget_Grid extends Mage_Backend_Block_Widget if (is_string($filter)) { $data = $this->helper('Mage_Backend_Helper_Data')->prepareFilterString($filter); $this->_setFilterValues($data); - } - else if ($filter && is_array($filter)) { + } else if ($filter && is_array($filter)) { $this->_setFilterValues($filter); - } - else if(0 !== sizeof($this->_defaultFilter)) { + } else if (0 !== sizeof($this->_defaultFilter)) { $this->_setFilterValues($this->_defaultFilter); } @@ -740,9 +738,7 @@ class Mage_Backend_Block_Widget_Grid extends Mage_Backend_Block_Widget $session->setData($sessionParamName, $param); } return $param; - } - elseif ($this->_saveParametersInSession && ($param = $session->getData($sessionParamName))) - { + } elseif ($this->_saveParametersInSession && ($param = $session->getData($sessionParamName))) { return $param; } @@ -821,7 +817,7 @@ class Mage_Backend_Block_Widget_Grid extends Mage_Backend_Block_Widget public function getMainButtonsHtml() { $html = ''; - if($this->getColumnSet()->isFilterVisible()) { + if ($this->getColumnSet()->isFilterVisible()) { $html.= $this->getResetFilterButtonHtml(); $html.= $this->getSearchButtonHtml(); } diff --git a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Checkbox.php b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Checkbox.php index 77135a2100adeddc443f0a21fa4847f53a674dda..8878e01db65187968b16a24a255f4b26019995a1 100644 --- a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Checkbox.php +++ b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Checkbox.php @@ -60,8 +60,7 @@ class Mage_Backend_Block_Widget_Grid_Column_Filter_Checkbox extends Mage_Backend { if ($this->getValue()) { return $this->getColumn()->getValue(); - } - else { + } else { return array( array('neq'=>$this->getColumn()->getValue()), array('is'=>new Zend_Db_Expr('NULL')) diff --git a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Country.php b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Country.php index 195f5a0172304f8f77d7feadefe32cf901f65973..04d9fe404feea819ff15daabd7d11b735a068ff8 100644 --- a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Country.php +++ b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Country.php @@ -36,7 +36,9 @@ class Mage_Backend_Block_Widget_Grid_Column_Filter_Country extends Mage_Backend_ $options = Mage::getResourceModel('Mage_Directory_Model_Resource_Country_Collection') ->load() ->toOptionArray(false); - array_unshift($options, array('value'=>'', 'label'=>Mage::helper('Mage_Backend_Helper_Data')->__('All Countries'))); + array_unshift($options, + array('value'=>'', 'label'=>Mage::helper('Mage_Backend_Helper_Data')->__('All Countries')) + ); return $options; } } diff --git a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Date.php b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Date.php index 7bd1a027f0bc38e8631433e3ae3aac6987a52353..a1ecdb63fcbeed43e08b818d939a39b0e8d45f06 100644 --- a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Date.php +++ b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Date.php @@ -54,13 +54,13 @@ class Mage_Backend_Block_Widget_Grid_Column_Filter_Date extends Mage_Backend_Blo . ' value="' . $this->getEscapedValue('from') . '" class="input-text no-changes" ' . $this->getUiId('filter', $this->_getHtmlName(), 'from') . '/>' . '</div>'; - $html.= '<div class="range-line date">' + $html .= '<div class="range-line date">' . '<span class="label">' . $this->__('To') . ' :</span>' . '<input type="text" name="' . $this->_getHtmlName() . '[to]" id="' . $htmlId . '_to"' . ' value="' . $this->getEscapedValue('to') . '" class="input-text no-changes" ' . $this->getUiId('filter', $this->_getHtmlName(), 'to') . '/>' . '</div></div>'; - $html .= '<input type="hidden" name="'.$this->_getHtmlName() . '[locale]"' + $html .= '<input type="hidden" name="' . $this->_getHtmlName() . '[locale]"' . ' value="' . $this->getLocale()->getLocaleCode() . '"/>'; $html .= '<script type="text/javascript"> (function( $ ) { diff --git a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Interface.php b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Interface.php index 505f480d47c6eb643c498facefb050ea72f23ad6..cbef880e346338da3bd339743d41221a8b3290a2 100644 --- a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Interface.php +++ b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Interface.php @@ -31,9 +31,11 @@ * @package Mage_Backend * @author Magento Core Team <core@magentocommerce.com> */ -interface Mage_Backend_Block_Widget_Grid_Column_Filter_Interface +interface Mage_Backend_Block_Widget_Grid_Column_Filter_Interface { public function getColumn(); + public function setColumn($column); + public function getHtml(); } diff --git a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Massaction.php b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Massaction.php index a16ee3a98f7bea2503d1319da4d53594e0b339b5..dde8b9d1b3b343eb018379f04d404e9d2dc8e14b 100644 --- a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Massaction.php +++ b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Massaction.php @@ -31,14 +31,14 @@ * @package Mage_Backend * @author Magento Core Team <core@magentocommerce.com> */ -class Mage_Backend_Block_Widget_Grid_Column_Filter_Massaction extends Mage_Backend_Block_Widget_Grid_Column_Filter_Checkbox +class Mage_Backend_Block_Widget_Grid_Column_Filter_Massaction + extends Mage_Backend_Block_Widget_Grid_Column_Filter_Checkbox { public function getCondition() { if ($this->getValue()) { return array('in'=> ( $this->getColumn()->getSelected() ? $this->getColumn()->getSelected() : array(0) )); - } - else { + } else { return array('nin'=> ( $this->getColumn()->getSelected() ? $this->getColumn()->getSelected() : array(0) )); } } diff --git a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Price.php b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Price.php index 82649595c51baa73e7720527be1a78834fbc5bec..10b2fd20fe5f3d225a951276fe77eb154f906d0b 100644 --- a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Price.php +++ b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Price.php @@ -39,10 +39,25 @@ class Mage_Backend_Block_Widget_Grid_Column_Filter_Price extends Mage_Backend_Bl public function getHtml() { $html = '<div class="range">'; - $html .= '<div class="range-line"><span class="label">' . Mage::helper('Mage_Backend_Helper_Data')->__('From').':</span> <input type="text" name="'.$this->_getHtmlName().'[from]" id="'.$this->_getHtmlId().'_from" value="'.$this->getEscapedValue('from').'" class="input-text no-changes" ' . $this->getUiId('filter', $this->_getHtmlName(), 'from') . '/></div>'; - $html .= '<div class="range-line"><span class="label">' . Mage::helper('Mage_Backend_Helper_Data')->__('To').' : </span><input type="text" name="'.$this->_getHtmlName().'[to]" id="'.$this->_getHtmlId().'_to" value="'.$this->getEscapedValue('to').'" class="input-text no-changes" ' . $this->getUiId('filter', $this->_getHtmlName(), 'to') . '/></div>'; - if ($this->getDisplayCurrencySelect()) - $html .= '<div class="range-line"><span class="label">' . Mage::helper('Mage_Backend_Helper_Data')->__('In').' : </span>' . $this->_getCurrencySelectHtml() . '</div>'; + $html .= '<div class="range-line"><span class="label">' + . Mage::helper('Mage_Backend_Helper_Data')->__('From') + . ':</span> <input type="text" name="' + . $this->_getHtmlName() + . '[from]" id="' . $this->_getHtmlId() . '_from" value="' + . $this->getEscapedValue('from') . '" class="input-text no-changes" ' + . $this->getUiId('filter', $this->_getHtmlName(), 'from') . '/></div>'; + $html .= '<div class="range-line"><span class="label">' + . Mage::helper('Mage_Backend_Helper_Data')->__('To') + . ' : </span><input type="text" name="' + . $this->_getHtmlName() . '[to]" id="' . $this->_getHtmlId() . '_to" value="'.$this->getEscapedValue('to') + . '" class="input-text no-changes" ' . $this->getUiId('filter', $this->_getHtmlName(), 'to') . '/></div>'; + + if ($this->getDisplayCurrencySelect()) { + $html .= '<div class="range-line"><span class="label">' + . Mage::helper('Mage_Backend_Helper_Data')->__('In') . ' : </span>' + . $this->_getCurrencySelectHtml() . '</div>'; + } + $html .= '</div>'; return $html; @@ -68,23 +83,25 @@ class Mage_Backend_Block_Widget_Grid_Column_Filter_Price extends Mage_Backend_Bl protected function _getCurrencyModel() { - if (is_null($this->_currencyModel)) + if (is_null($this->_currencyModel)) { $this->_currencyModel = Mage::getModel('Mage_Directory_Model_Currency'); + } return $this->_currencyModel; } protected function _getCurrencySelectHtml() { - $value = $this->getEscapedValue('currency'); - if (!$value) + if (!$value) { $value = $this->getColumn()->getCurrencyCode(); + } $html = ''; $html .= '<select name="'.$this->_getHtmlName().'[currency]" id="'.$this->_getHtmlId().'_currency">'; foreach ($this->_getCurrencyList() as $currency) { - $html .= '<option value="' . $currency . '" '.($currency == $value ? 'selected="selected"' : '').'>' . $currency . '</option>'; + $html .= '<option value="' . $currency . '" ' + . ($currency == $value ? 'selected="selected"' : '').'>' . $currency . '</option>'; } $html .= '</select>'; return $html; @@ -104,7 +121,9 @@ class Mage_Backend_Block_Widget_Grid_Column_Filter_Price extends Mage_Backend_Bl return $this->getData('value', $index); } $value = $this->getData('value'); - if ((isset($value['from']) && strlen($value['from']) > 0) || (isset($value['to']) && strlen($value['to']) > 0)) { + if ((isset($value['from']) && strlen($value['from']) > 0) + || (isset($value['to']) && strlen($value['to']) > 0) + ) { return $value; } return null; @@ -122,11 +141,13 @@ class Mage_Backend_Block_Widget_Grid_Column_Filter_Price extends Mage_Backend_Bl } $rate = $this->_getRate($displayCurrency, $this->getColumn()->getCurrencyCode()); - if (isset($value['from'])) + if (isset($value['from'])) { $value['from'] *= $rate; + } - if (isset($value['to'])) + if (isset($value['to'])) { $value['to'] *= $rate; + } $this->prepareRates($displayCurrency); return $value; diff --git a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Radio.php b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Radio.php index 3519ea9d0fe4e78b72d02c5f8616d16bb3b0de9f..b82320e2ae5137ae7ce3b7303bc491ea6851145e 100644 --- a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Radio.php +++ b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Radio.php @@ -55,8 +55,7 @@ class Mage_Backend_Block_Widget_Grid_Column_Filter_Radio extends Mage_Backend_Bl { if ($this->getValue()) { return $this->getColumn()->getValue(); - } - else { + } else { return array( array('neq'=>$this->getColumn()->getValue()), array('is'=>new Zend_Db_Expr('NULL')) diff --git a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Range.php b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Range.php index c243b7857bc712414f5de35b0545d625f4ce60d4..407f63194b0a319e725038b87cfdbf84024da914 100644 --- a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Range.php +++ b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Range.php @@ -35,8 +35,17 @@ class Mage_Backend_Block_Widget_Grid_Column_Filter_Range extends Mage_Backend_Bl { public function getHtml() { - $html = '<div class="range"><div class="range-line"><span class="label">' . Mage::helper('Mage_Backend_Helper_Data')->__('From').':</span> <input type="text" name="'.$this->_getHtmlName().'[from]" id="'.$this->_getHtmlId().'_from" value="'.$this->getEscapedValue('from').'" class="input-text no-changes" ' . $this->getUiId('filter', $this->_getHtmlName(), 'from') . '/></div>'; - $html .= '<div class="range-line"><span class="label">' . Mage::helper('Mage_Backend_Helper_Data')->__('To').' : </span><input type="text" name="'.$this->_getHtmlName().'[to]" id="'.$this->_getHtmlId().'_to" value="'.$this->getEscapedValue('to').'" class="input-text no-changes" ' . $this->getUiId('filter', $this->_getHtmlName(), 'to') . '/></div></div>'; + $html = '<div class="range"><div class="range-line"><span class="label">' + . Mage::helper('Mage_Backend_Helper_Data')->__('From') + . ':</span> <input type="text" name="' . $this->_getHtmlName() + . '[from]" id="'.$this->_getHtmlId() . '_from" value="' . $this->getEscapedValue('from') + . '" class="input-text no-changes" ' + . $this->getUiId('filter', $this->_getHtmlName(), 'from') . '/></div>'; + $html .= '<div class="range-line"><span class="label">' + . Mage::helper('Mage_Backend_Helper_Data')->__('To') + . ' : </span><input type="text" name="' . $this->_getHtmlName() . '[to]" id="' + . $this->_getHtmlId() . '_to" value="' . $this->getEscapedValue('to') . '" class="input-text no-changes" ' + . $this->getUiId('filter', $this->_getHtmlName(), 'to') . '/></div></div>'; return $html; } @@ -46,17 +55,17 @@ class Mage_Backend_Block_Widget_Grid_Column_Filter_Range extends Mage_Backend_Bl return $this->getData('value', $index); } $value = $this->getData('value'); - if ((isset($value['from']) && strlen($value['from']) > 0) || (isset($value['to']) && strlen($value['to']) > 0)) { + if ((isset($value['from']) && strlen($value['from']) > 0) + || (isset($value['to']) && strlen($value['to']) > 0) + ) { return $value; } return null; } - public function getCondition() { $value = $this->getValue(); return $value; } - } diff --git a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Select.php b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Select.php index b173ea881682af637428a0c4e74bdc9b0169e84d..cfa02ff9d1df5fda0291166e32f977a175c6fd04 100644 --- a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Select.php +++ b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Select.php @@ -64,7 +64,9 @@ class Mage_Backend_Block_Widget_Grid_Column_Filter_Select extends Mage_Backend_B protected function _renderOption($option, $value) { $selected = (($option['value'] == $value && (!is_null($value))) ? ' selected="selected"' : '' ); - return '<option value="'. $this->escapeHtml($option['value']).'"'.$selected.'>'.$this->escapeHtml($option['label']).'</option>'; + return '<option value="' + . $this->escapeHtml($option['value']).'"'.$selected.'>' + . $this->escapeHtml($option['label']) . '</option>'; } public function getHtml() @@ -73,7 +75,7 @@ class Mage_Backend_Block_Widget_Grid_Column_Filter_Select extends Mage_Backend_B . $this->getUiId('filter', $this->_getHtmlName()) . 'class="no-changes">'; $value = $this->getValue(); - foreach ($this->_getOptions() as $option){ + foreach ($this->_getOptions() as $option) { if (is_array($option['value'])) { $html .= '<optgroup label="' . $this->escapeHtml($option['label']) . '">'; foreach ($option['value'] as $subOption) { diff --git a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Text.php b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Text.php index f9be6c7007a4f5bf95061dbf3abb619941276f3b..8934bd4628528796e1e001ffaa9d8ccff73e7ccb 100644 --- a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Text.php +++ b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Text.php @@ -35,7 +35,11 @@ class Mage_Backend_Block_Widget_Grid_Column_Filter_Text extends Mage_Backend_Blo { public function getHtml() { - $html = '<div class="field-100"><input type="text" name="'.$this->_getHtmlName().'" id="'.$this->_getHtmlId().'" value="'.$this->getEscapedValue().'" class="input-text no-changes"' + $html = '<div class="field-100"><input type="text" name="' + . $this->_getHtmlName() + . '" id="'.$this->_getHtmlId() + . '" value="'.$this->getEscapedValue() + . '" class="input-text no-changes"' . $this->getUiId('filter', $this->_getHtmlName()) . ' /></div>'; return $html; } diff --git a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Theme.php b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Theme.php index 3056bad51bb5dffd6161cabfbf392762e0961193..7f1d9594af78009f7a93b0619173f3ae7a7316f6 100644 --- a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Theme.php +++ b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Theme.php @@ -48,9 +48,8 @@ class Mage_Backend_Block_Widget_Grid_Column_Filter_Theme 'label' => '' )); } - $htmlSelect = '<select name="%s" id="%s" class="no-changes" %s>%s</select>'; $html = sprintf( - $htmlSelect, + '<select name="%s" id="%s" class="no-changes" %s>%s</select>', $this->_getHtmlName(), $this->_getHtmlId(), $this->getUiId('filter', $this->_getHtmlName()), diff --git a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Abstract.php b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Abstract.php index a2007c7509d25117e999b0e247b64c3022b2e7c9..2b3143f6c4680732217d6a3dd8e00d780628165f 100644 --- a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Abstract.php +++ b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Abstract.php @@ -130,8 +130,7 @@ abstract class Mage_Backend_Block_Widget_Grid_Column_Renderer_Abstract $customWidth = $this->getColumn()->getData('width'); if ((null === $customWidth) || (preg_match('/^[0-9]+%?$/', $customWidth))) { $width = $customWidth; - } - elseif (preg_match('/^([0-9]+)px$/', $customWidth, $matches)) { + } elseif (preg_match('/^([0-9]+)px$/', $customWidth, $matches)) { $width = (int)$matches[1]; } } diff --git a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Action.php b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Action.php index 39aa003a0b3efc6ab97e231807cc89bfef65cef7..df959c145b6e4aaae21340004bb12a95653b6ae1 100644 --- a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Action.php +++ b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Action.php @@ -48,7 +48,7 @@ class Mage_Backend_Block_Widget_Grid_Column_Renderer_Action return ' '; } - if(sizeof($actions)==1 && !$this->getColumn()->getNoLink()) { + if (sizeof($actions)==1 && !$this->getColumn()->getNoLink()) { foreach ($actions as $action) { if ( is_array($action) ) { return $this->_toLinkHtml($action, $row); @@ -59,7 +59,7 @@ class Mage_Backend_Block_Widget_Grid_Column_Renderer_Action $out = '<select class="action-select" onchange="varienGridAction.execute(this);">' . '<option value=""></option>'; $i = 0; - foreach ($actions as $action){ + foreach ($actions as $action) { $i++; if ( is_array($action) ) { $out .= $this->_toOptionHtml($action, $row); @@ -102,7 +102,7 @@ class Mage_Backend_Block_Widget_Grid_Column_Renderer_Action $actionCaption = ''; $this->_transformActionData($action, $actionCaption, $row); - if(isset($action['confirm'])) { + if (isset($action['confirm'])) { $action['onclick'] = 'return window.confirm(\'' . addslashes($this->escapeHtml($action['confirm'])) . '\')'; @@ -124,7 +124,7 @@ class Mage_Backend_Block_Widget_Grid_Column_Renderer_Action protected function _transformActionData(&$action, &$actionCaption, Varien_Object $row) { foreach ( $action as $attribute => $value ) { - if(isset($action[$attribute]) && !is_array($action[$attribute])) { + if (isset($action[$attribute]) && !is_array($action[$attribute])) { $this->getColumn()->setFormat($action[$attribute]); $action[$attribute] = parent::render($row); } else { @@ -135,12 +135,12 @@ class Mage_Backend_Block_Widget_Grid_Column_Renderer_Action case 'caption': $actionCaption = $action['caption']; unset($action['caption']); - break; + break; case 'url': - if(is_array($action['url'])) { + if (is_array($action['url'])) { $params = array($action['field']=>$this->_getValue($row)); - if(isset($action['url']['params'])) { + if (isset($action['url']['params'])) { $params = array_merge($action['url']['params'], $params); } $action['href'] = $this->getUrl($action['url']['base'], $params); @@ -149,7 +149,7 @@ class Mage_Backend_Block_Widget_Grid_Column_Renderer_Action $action['href'] = $action['url']; } unset($action['url']); - break; + break; case 'popup': $action['onclick'] = diff --git a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Checkbox.php b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Checkbox.php index 3643ecbe73a66113d489157b47be5d431b9ad8ab..103dba701bb95c467395b2934cf3b2987d6f02c5 100644 --- a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Checkbox.php +++ b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Checkbox.php @@ -61,22 +61,20 @@ class Mage_Backend_Block_Widget_Grid_Column_Renderer_Checkbox $value = $row->getData($this->getColumn()->getIndex()); if (is_array($values)) { $checked = in_array($value, $values) ? ' checked="checked"' : ''; - } - else { + } else { $checked = ($value === $this->getColumn()->getValue()) ? ' checked="checked"' : ''; } $disabledValues = $this->getColumn()->getDisabledValues(); if (is_array($disabledValues)) { $disabled = in_array($value, $disabledValues) ? ' disabled="disabled"' : ''; - } - else { + } else { $disabled = ($value === $this->getColumn()->getDisabledValue()) ? ' disabled="disabled"' : ''; } $this->setDisabled($disabled); - if ($this->getNoObjectId() || $this->getColumn()->getUseIndex()){ + if ($this->getNoObjectId() || $this->getColumn()->getUseIndex()) { $v = $value; } else { $v = ($row->getId() != "") ? $row->getId():$value; @@ -107,7 +105,7 @@ class Mage_Backend_Block_Widget_Grid_Column_Renderer_Checkbox */ public function renderHeader() { - if($this->getColumn()->getHeader()) { + if ($this->getColumn()->getHeader()) { return parent::renderHeader(); } diff --git a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Currency.php b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Currency.php index cc5a421a1c0613b4c6422c104a53c8a83d82d61d..39ebddbd25ecb841219ecc93544515efd97acd85 100644 --- a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Currency.php +++ b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Currency.php @@ -170,4 +170,3 @@ class Mage_Backend_Block_Widget_Grid_Column_Renderer_Currency return parent::renderCss() . ' a-right'; } } - diff --git a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Date.php b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Date.php index e9118c97794434af21efc9042b977f0ca31b17ce..0c020a708e0094f4137c27b293f6929c08dbaccb 100644 --- a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Date.php +++ b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Date.php @@ -76,7 +76,7 @@ class Mage_Backend_Block_Widget_Grid_Column_Renderer_Date if ($data = $row->getData($this->getColumn()->getIndex())) { $format = $this->_getFormat(); try { - if($this->getColumn()->getGmtoffset()) { + if ($this->getColumn()->getGmtoffset()) { $data = Mage::app()->getLocale() ->date($data, Varien_Date::DATETIME_INTERNAL_FORMAT)->toString($format); } else { @@ -86,11 +86,13 @@ class Mage_Backend_Block_Widget_Grid_Column_Renderer_Date } catch (Exception $e) { - if($this->getColumn()->getTimezone()) { + if ($this->getColumn()->getTimezone()) { $data = Mage::app()->getLocale() ->date($data, Varien_Date::DATETIME_INTERNAL_FORMAT)->toString($format); } else { - $data = Mage::getSingleton('Mage_Core_Model_Locale')->date($data, null, null, false)->toString($format); + $data = Mage::getSingleton('Mage_Core_Model_Locale') + ->date($data, null, null, false) + ->toString($format); } } return $data; diff --git a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Options.php b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Options.php index 391c206ce8f97a9872e467d323ad51bec22984b2..515f18a21cddc03f99c89f083d094965c822596a 100644 --- a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Options.php +++ b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Options.php @@ -51,8 +51,7 @@ class Mage_Backend_Block_Widget_Grid_Column_Renderer_Options foreach ($value as $item) { if (isset($options[$item])) { $res[] = $this->escapeHtml($options[$item]); - } - elseif ($showMissingOptionValues) { + } elseif ($showMissingOptionValues) { $res[] = $this->escapeHtml($item); } } diff --git a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Price.php b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Price.php index 12f5e664fd30519ba375f54f502000e361342450..348a4aa3ab7b97ce430a0c3482554c96304d6baf 100644 --- a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Price.php +++ b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Price.php @@ -49,15 +49,15 @@ class Mage_Backend_Block_Widget_Grid_Column_Renderer_Price public function render(Varien_Object $row) { if ($data = $row->getData($this->getColumn()->getIndex())) { - $currency_code = $this->_getCurrencyCode($row); + $currencyCode = $this->_getCurrencyCode($row); - if (!$currency_code) { + if (!$currencyCode) { return $data; } $data = floatval($data) * $this->_getRate($row); $data = sprintf("%f", $data); - $data = Mage::app()->getLocale()->currency($currency_code)->toCurrency($data); + $data = Mage::app()->getLocale()->currency($currencyCode)->toCurrency($data); return $data; } return $this->getColumn()->getDefault(); diff --git a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Radio.php b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Radio.php index 854b3c8c81269426b57c686bc51165905d4b63de..762fa448015c339ec7024fe22f674c9e2a660cb2 100644 --- a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Radio.php +++ b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Radio.php @@ -68,15 +68,4 @@ class Mage_Backend_Block_Widget_Grid_Column_Renderer_Radio $html .= 'value="' . $row->getId() . '" class="radio"' . $checked . '/>'; return $html; } - - /* - public function renderHeader() - { - $checked = ''; - if ($filter = $this->getColumn()->getFilter()) { - $checked = $filter->getValue() ? 'checked' : ''; - } - return '<input type="checkbox" name="'.$this->getColumn()->getName().'" onclick="'.$this->getColumn()->getGrid()->getJsObjectName().'.checkCheckboxes(this)" class="checkbox" '.$checked.' title="'.Mage::helper('Mage_Backend_Helper_Data')->__('Select All').'"/>'; - } - */ } diff --git a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Select.php b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Select.php index 30863950463bac77ef1e7645b8c5d209b5425f19..59c1e5626e4c4a9d8f404c4910bc009bbf8e8d14 100644 --- a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Select.php +++ b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Select.php @@ -47,7 +47,7 @@ class Mage_Backend_Block_Widget_Grid_Column_Renderer_Select $name = $this->getColumn()->getName() ? $this->getColumn()->getName() : $this->getColumn()->getId(); $html = '<select name="' . $this->escapeHtml($name) . '" ' . $this->getColumn()->getValidateClass() . '>'; $value = $row->getData($this->getColumn()->getIndex()); - foreach ($this->getColumn()->getOptions() as $val => $label){ + foreach ($this->getColumn()->getOptions() as $val => $label) { $selected = ( ($val == $value && (!is_null($value))) ? ' selected="selected"' : '' ); $html .= '<option value="' . $this->escapeHtml($val) . '"' . $selected . '>'; $html .= $this->escapeHtml($label) . '</option>'; diff --git a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Store.php b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Store.php index 916c4da23c4df363eb66bd1309437b816e6ce321..f6026c2b1153ab6e524d16323ac6b1276318997f 100644 --- a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Store.php +++ b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Store.php @@ -103,8 +103,7 @@ class Mage_Backend_Block_Widget_Grid_Column_Renderer_Store if (empty($origStores)) { return ''; - } - elseif (in_array(0, $origStores) && count($origStores) == 1 && !$skipAllStoresLabel) { + } elseif (in_array(0, $origStores) && count($origStores) == 1 && !$skipAllStoresLabel) { return Mage::helper('Mage_Backend_Helper_Data')->__('All Store Views'); } diff --git a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Text.php b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Text.php index 47489b0ea9a983c745d71d57329a70d68de0e1af..72423c5fa8d6d6fed279132dc7905346e493db3c 100644 --- a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Text.php +++ b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Text.php @@ -57,8 +57,7 @@ class Mage_Backend_Block_Widget_Grid_Column_Renderer_Text $data = parent::_getValue($row); $string = is_null($data) ? $defaultValue : $data; return $this->escapeHtml($string); - } - elseif (preg_match_all($this->_variablePattern, $format, $matches)) { + } elseif (preg_match_all($this->_variablePattern, $format, $matches)) { // Parsing of format string $formattedString = $format; foreach ($matches[0] as $matchIndex=>$match) { diff --git a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Wrapline.php b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Wrapline.php index 8362837640d88c580b10427c0972c783331b0a60..1668ddbe99f4dd09c3d9373cb4a53a55fb76570e 100644 --- a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Wrapline.php +++ b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Renderer/Wrapline.php @@ -54,8 +54,9 @@ class Mage_Backend_Block_Widget_Grid_Column_Renderer_Wrapline $lineLength = $this->getColumn()->getData('lineLength') ? $this->getColumn()->getData('lineLength') : $this->_defaultMaxLineLength; - for($i = 0, $n = floor(Mage::helper('Mage_Core_Helper_String')->strlen($line) / $lineLength); $i <= $n; $i++) { - $wrappedLine .= Mage::helper('Mage_Core_Helper_String')->substr($line, ($lineLength * $i), $lineLength) . "<br />"; + for ($i = 0, $n = floor(Mage::helper('Mage_Core_Helper_String')->strlen($line) / $lineLength); $i <= $n; $i++) { + $wrappedLine .= Mage::helper('Mage_Core_Helper_String')->substr($line, ($lineLength * $i), $lineLength) + . "<br />"; } return $wrappedLine; } diff --git a/app/code/core/Mage/Backend/Block/Widget/Grid/Container.php b/app/code/core/Mage/Backend/Block/Widget/Grid/Container.php index 311c1f6ad7b9b8d5774bb4e10172f09515d29ff1..368dabd02da10a2789be61ba7b1e4192239b9d10 100644 --- a/app/code/core/Mage/Backend/Block/Widget/Grid/Container.php +++ b/app/code/core/Mage/Backend/Block/Widget/Grid/Container.php @@ -47,7 +47,7 @@ class Mage_Backend_Block_Widget_Grid_Container extends Mage_Backend_Block_Widget if (is_null($this->_addButtonLabel)) { $this->_addButtonLabel = $this->__('Add New'); } - if(is_null($this->_backButtonLabel)) { + if (is_null($this->_backButtonLabel)) { $this->_backButtonLabel = $this->__('Back'); } diff --git a/app/code/core/Mage/Backend/Block/Widget/Grid/Extended.php b/app/code/core/Mage/Backend/Block/Widget/Grid/Extended.php index 6020429197d9239983a7e0d59e49f4d7d93acdee..7b2cc261348b6b04d6436304115777a9a92ae29f 100644 --- a/app/code/core/Mage/Backend/Block/Widget/Grid/Extended.php +++ b/app/code/core/Mage/Backend/Block/Widget/Grid/Extended.php @@ -383,7 +383,7 @@ class Mage_Backend_Block_Widget_Grid_Extended { $this->setChild('massaction', $this->getLayout()->createBlock($this->getMassactionBlockName())); $this->_prepareMassaction(); - if($this->getMassactionBlock()->isAvailable()) { + if ($this->getMassactionBlock()->isAvailable()) { $this->_prepareMassactionColumn(); } return $this; @@ -574,7 +574,8 @@ class Mage_Backend_Block_Widget_Grid_Extended * * @return array */ - public function getSubTotalColumns() { + public function getSubTotalColumns() + { return $this->getColumns(); } @@ -660,7 +661,8 @@ class Mage_Backend_Block_Widget_Grid_Extended * @param Varien_Object $item * @return boolean */ - public function shouldRenderSubTotal($item) { + public function shouldRenderSubTotal($item) + { return ($this->_countSubTotals && count($this->_subtotals) > 0 && count($this->getMultipleRows($item)) > 0); } @@ -1026,8 +1028,7 @@ class Mage_Backend_Block_Widget_Grid_Extended $csv.= implode(',', $data)."\n"; } - if ($this->getCountTotals()) - { + if ($this->getCountTotals()) { $data = array(); foreach ($this->getColumns() as $column) { if (!$column->getIsSystem()) { @@ -1065,8 +1066,7 @@ class Mage_Backend_Block_Widget_Grid_Extended foreach ($this->getCollection() as $item) { $xml.= $item->toXml($indexes); } - if ($this->getCountTotals()) - { + if ($this->getCountTotals()) { $xml.= $this->getTotals()->toXml($indexes); } $xml.= '</items>'; @@ -1163,8 +1163,7 @@ class Mage_Backend_Block_Widget_Grid_Extended $data[] = $row; } - if ($this->getCountTotals()) - { + if ($this->getCountTotals()) { $row = array(); foreach ($this->getColumns() as $column) { if (!$column->getIsSystem()) { @@ -1259,7 +1258,7 @@ class Mage_Backend_Block_Widget_Grid_Extended public function getMainButtonsHtml() { $html = ''; - if($this->getFilterVisibility()) { + if ($this->getFilterVisibility()) { $html.= $this->getResetFilterButtonHtml(); $html.= $this->getSearchButtonHtml(); } diff --git a/app/code/core/Mage/Backend/Block/Widget/Grid/Massaction/Extended.php b/app/code/core/Mage/Backend/Block/Widget/Grid/Massaction/Extended.php index ea7aae57c69957a5ca3c140a8d9aa8ff00c5e991..fa0054339c46c1b2af78fc49473ced156a0ee2f2 100644 --- a/app/code/core/Mage/Backend/Block/Widget/Grid/Massaction/Extended.php +++ b/app/code/core/Mage/Backend/Block/Widget/Grid/Massaction/Extended.php @@ -84,7 +84,7 @@ class Mage_Backend_Block_Widget_Grid_Massaction_Extended extends Mage_Backend_Bl ->setMassaction($this) ->setId($itemId); - if($this->_items[$itemId]->getAdditional()) { + if ($this->_items[$itemId]->getAdditional()) { $this->_items[$itemId]->setAdditionalActionBlock($this->_items[$itemId]->getAdditional()); $this->_items[$itemId]->unsAdditional(); } @@ -100,7 +100,7 @@ class Mage_Backend_Block_Widget_Grid_Massaction_Extended extends Mage_Backend_Bl */ public function getItem($itemId) { - if(isset($this->_items[$itemId])) { + if (isset($this->_items[$itemId])) { return $this->_items[$itemId]; } @@ -199,7 +199,7 @@ class Mage_Backend_Block_Widget_Grid_Massaction_Extended extends Mage_Backend_Bl */ public function getSelectedJson() { - if($selected = $this->getRequest()->getParam($this->getFormFieldNameInternal())) { + if ($selected = $this->getRequest()->getParam($this->getFormFieldNameInternal())) { $selected = explode(',', $selected); return join(',', $selected); } else { @@ -214,7 +214,7 @@ class Mage_Backend_Block_Widget_Grid_Massaction_Extended extends Mage_Backend_Bl */ public function getSelected() { - if($selected = $this->getRequest()->getParam($this->getFormFieldNameInternal())) { + if ($selected = $this->getRequest()->getParam($this->getFormFieldNameInternal())) { $selected = explode(',', $selected); return $selected; } else { @@ -252,7 +252,7 @@ class Mage_Backend_Block_Widget_Grid_Massaction_Extended extends Mage_Backend_Bl $gridIds = $this->getParentBlock()->getCollection()->getAllIds(); - if(!empty($gridIds)) { + if (!empty($gridIds)) { return join(",", $gridIds); } return ''; diff --git a/app/code/core/Mage/Backend/Block/Widget/Grid/Massaction/Item.php b/app/code/core/Mage/Backend/Block/Widget/Grid/Massaction/Item.php index d8479a04bd9a7799025e2a90df399fd9e1847c84..b2d4b1426b2179eff941b9fb6cc9b95da878541c 100644 --- a/app/code/core/Mage/Backend/Block/Widget/Grid/Massaction/Item.php +++ b/app/code/core/Mage/Backend/Block/Widget/Grid/Massaction/Item.php @@ -67,11 +67,11 @@ class Mage_Backend_Block_Widget_Grid_Massaction_Item extends Mage_Backend_Block_ */ public function setAdditionalActionBlock($block) { - if(is_string($block)) { + if (is_string($block)) { $block = $this->getLayout()->createBlock($block); } elseif (is_array($block)) { $block = $this->_createFromConfig($block); - } elseif(!($block instanceof Mage_Core_Block_Abstract)) { + } elseif (!($block instanceof Mage_Core_Block_Abstract)) { Mage::throwException('Unknown block type'); } diff --git a/app/code/core/Mage/Backend/Block/Widget/Grid/Massaction/Item/Additional/Interface.php b/app/code/core/Mage/Backend/Block/Widget/Grid/Massaction/Item/Additional/Interface.php index 54724601235b4299aab20754a510b774536b11fe..af52b512c5810e6166113eeca728858dd4b59a49 100644 --- a/app/code/core/Mage/Backend/Block/Widget/Grid/Massaction/Item/Additional/Interface.php +++ b/app/code/core/Mage/Backend/Block/Widget/Grid/Massaction/Item/Additional/Interface.php @@ -34,5 +34,5 @@ */ interface Mage_Backend_Block_Widget_Grid_Massaction_Item_Additional_Interface { - function createFromConfiguration(array $configuration); + public function createFromConfiguration(array $configuration); } diff --git a/app/code/core/Mage/Backend/Block/Widget/Grid/Serializer.php b/app/code/core/Mage/Backend/Block/Widget/Grid/Serializer.php index f9e297e556b14a454677e796d21b43c65cb31ab4..c8a4d3f1d71ee42e0fd903129b45d9c0e8e19a6c 100644 --- a/app/code/core/Mage/Backend/Block/Widget/Grid/Serializer.php +++ b/app/code/core/Mage/Backend/Block/Widget/Grid/Serializer.php @@ -64,8 +64,7 @@ class Mage_Backend_Block_Widget_Grid_Serializer extends Mage_Core_Block_Template foreach ($names as $name) { $this->addColumnInputName($name); } - } - else { + } else { if (!in_array($names, $this->_inputsToSerialize)) { $this->_inputsToSerialize[] = $names; } @@ -95,8 +94,7 @@ class Mage_Backend_Block_Widget_Grid_Serializer extends Mage_Core_Block_Template $result = array(); if ($serializeData = $this->getSerializeData()) { $result = $serializeData; - } - elseif (!empty($this->_inputsToSerialize)) { + } elseif (!empty($this->_inputsToSerialize)) { return '{}'; } return Mage::helper('Mage_Core_Helper_Data')->jsonEncode($result); diff --git a/app/code/core/Mage/Backend/Block/Widget/Tabs.php b/app/code/core/Mage/Backend/Block/Widget/Tabs.php index b4286546f8daf4c8f100df0632018aff5cde6178..9b8bb361d07d6abdf4ba576a1a89d15f92c1d3e7 100644 --- a/app/code/core/Mage/Backend/Block/Widget/Tabs.php +++ b/app/code/core/Mage/Backend/Block/Widget/Tabs.php @@ -66,6 +66,12 @@ class Mage_Backend_Block_Widget_Tabs extends Mage_Backend_Block_Widget return $this->_destElementId; } + /** + * Set destination element id + * + * @param string $elementId + * @return Mage_Backend_Block_Widget_Tabs + */ public function setDestElementId($elementId) { $this->_destElementId = $elementId; @@ -97,32 +103,14 @@ class Mage_Backend_Block_Widget_Tabs extends Mage_Backend_Block_Widget { if (is_array($tab)) { $this->_tabs[$tabId] = new Varien_Object($tab); - } - elseif ($tab instanceof Varien_Object) { + } elseif ($tab instanceof Varien_Object) { $this->_tabs[$tabId] = $tab; if (!$this->_tabs[$tabId]->hasTabId()) { $this->_tabs[$tabId]->setTabId($tabId); } - } - elseif (is_string($tab)) { - if (strpos($tab, '_Block_')) { - $this->_tabs[$tabId] = $this->getLayout()->createBlock( - $tab, - $this->getNameInLayout() . '_tab_' . $tabId - ); - } - elseif ($this->getChildBlock($tab)) { - $this->_tabs[$tabId] = $this->getChildBlock($tab); - } - else { - $this->_tabs[$tabId] = null; - } - - if (!($this->_tabs[$tabId] instanceof Mage_Backend_Block_Widget_Tab_Interface)) { - throw new Exception(Mage::helper('Mage_Backend_Helper_Data')->__('Wrong tab configuration.')); - } - } - else { + } elseif (is_string($tab)) { + $this->_addTabByName($tab, $tabId); + } else { throw new Exception(Mage::helper('Mage_Backend_Helper_Data')->__('Wrong tab configuration.')); } @@ -137,12 +125,41 @@ class Mage_Backend_Block_Widget_Tabs extends Mage_Backend_Block_Widget $this->_tabs[$tabId]->setId($tabId); $this->_tabs[$tabId]->setTabId($tabId); - if (is_null($this->_activeTab)) $this->_activeTab = $tabId; - if (true === $this->_tabs[$tabId]->getActive()) $this->setActiveTab($tabId); + if (is_null($this->_activeTab)) { + $this->_activeTab = $tabId; + } + if (true === $this->_tabs[$tabId]->getActive()) { + $this->setActiveTab($tabId); + } return $this; } + /** + * Add tab by tab block name + * + * @param string $tab + * @param string $tabId + * @throws Exception + */ + protected function _addTabByName($tab, $tabId) + { + if (strpos($tab, '_Block_')) { + $this->_tabs[$tabId] = $this->getLayout()->createBlock( + $tab, + $this->getNameInLayout() . '_tab_' . $tabId + ); + } elseif ($this->getChildBlock($tab)) { + $this->_tabs[$tabId] = $this->getChildBlock($tab); + } else { + $this->_tabs[$tabId] = null; + } + + if (!($this->_tabs[$tabId] instanceof Mage_Backend_Block_Widget_Tab_Interface)) { + throw new Exception(Mage::helper('Mage_Backend_Helper_Data')->__('Wrong tab configuration.')); + } + } + public function getActiveTabId() { return $this->getTabId($this->_tabs[$this->_activeTab]); @@ -196,13 +213,13 @@ class Mage_Backend_Block_Widget_Tabs extends Mage_Backend_Block_Widget } $_new = array(); - foreach( $this->_tabs as $key => $tab ) { - foreach( $this->_tabs as $k => $t ) { - if( $t->getAfter() == $key ) { + foreach ($this->_tabs as $key => $tab ) { + foreach ($this->_tabs as $k => $t ) { + if ( $t->getAfter() == $key ) { $_new[$key] = $tab; $_new[$k] = $t; } else { - if( !$tab->getAfter() || !in_array($tab->getAfter(), array_keys($this->_tabs)) ) { + if ( !$tab->getAfter() || !in_array($tab->getAfter(), array_keys($this->_tabs)) ) { $_new[$key] = $tab; } } @@ -223,8 +240,10 @@ class Mage_Backend_Block_Widget_Tabs extends Mage_Backend_Block_Widget public function getTabsIds() { - if (empty($this->_tabs)) + if (empty($this->_tabs)) { return array(); + } + return array_keys($this->_tabs); } diff --git a/app/code/core/Mage/Backend/Controller/ActionAbstract.php b/app/code/core/Mage/Backend/Controller/ActionAbstract.php index f6b8ab7772a07cc86a11e7ed8f460c4e17e872d9..122fa0ed174e2bed8d35bdc01daec94daaedf4f1 100644 --- a/app/code/core/Mage/Backend/Controller/ActionAbstract.php +++ b/app/code/core/Mage/Backend/Controller/ActionAbstract.php @@ -194,16 +194,60 @@ abstract class Mage_Backend_Controller_ActionAbstract extends Mage_Core_Controll Mage::dispatchEvent('adminhtml_controller_action_predispatch_start', array()); parent::preDispatch(); + if (!$this->_processUrlKeys()) { + return $this; + } + + if ($this->getRequest()->isDispatched() + && $this->getRequest()->getActionName() !== 'denied' + && !$this->_isAllowed()) { + $this->_forward('denied'); + $this->setFlag('', self::FLAG_NO_DISPATCH, true); + return $this; + } + + if ($this->_isUrlChecked()) { + $this->setFlag('', self::FLAG_IS_URLS_CHECKED, true); + } + if (is_null(Mage::getSingleton('Mage_Backend_Model_Session')->getLocale())) { + Mage::getSingleton('Mage_Backend_Model_Session')->setLocale(Mage::app()->getLocale()->getLocaleCode()); + } + + return $this; + } + + /** + * Check whether url is checked + * + * @return bool + */ + protected function _isUrlChecked() + { + return !$this->getFlag('', self::FLAG_IS_URLS_CHECKED) + && !$this->getRequest()->getParam('forwarded') + && !$this->_getSession()->getIsUrlNotice(true) + && !Mage::getConfig()->getNode('global/can_use_base_url'); + } + + /** + * Check url keys. If non valid - redirect + * + * @return bool + */ + public function _processUrlKeys() + { $_isValidFormKey = true; $_isValidSecretKey = true; $_keyErrorMsg = ''; if (Mage::getSingleton('Mage_Backend_Model_Auth_Session')->isLoggedIn()) { if ($this->getRequest()->isPost()) { $_isValidFormKey = $this->_validateFormKey(); - $_keyErrorMsg = Mage::helper('Mage_Backend_Helper_Data')->__('Invalid Form Key. Please refresh the page.'); + $_keyErrorMsg = Mage::helper('Mage_Backend_Helper_Data') + ->__('Invalid Form Key. Please refresh the page.'); } elseif (Mage::getSingleton('Mage_Backend_Model_Url')->useSecretKey()) { $_isValidSecretKey = $this->_validateSecretKey(); - $_keyErrorMsg = Mage::helper('Mage_Backend_Helper_Data')->__('Invalid Secret Key. Please refresh the page.'); + $_keyErrorMsg = Mage::helper('Mage_Backend_Helper_Data') + ->__('Invalid Secret Key. Please refresh the page.'); } } if (!$_isValidFormKey || !$_isValidSecretKey) { @@ -217,28 +261,9 @@ abstract class Mage_Backend_Controller_ActionAbstract extends Mage_Core_Controll } else { $this->_redirect(Mage::getSingleton('Mage_Backend_Model_Url')->getStartupPageUrl()); } - return $this; - } - - if ($this->getRequest()->isDispatched() - && $this->getRequest()->getActionName() !== 'denied' - && !$this->_isAllowed()) { - $this->_forward('denied'); - $this->setFlag('', self::FLAG_NO_DISPATCH, true); - return $this; - } - - if (!$this->getFlag('', self::FLAG_IS_URLS_CHECKED) - && !$this->getRequest()->getParam('forwarded') - && !$this->_getSession()->getIsUrlNotice(true) - && !Mage::getConfig()->getNode('global/can_use_base_url')) { - $this->setFlag('', self::FLAG_IS_URLS_CHECKED, true); - } - if (is_null(Mage::getSingleton('Mage_Backend_Model_Session')->getLocale())) { - Mage::getSingleton('Mage_Backend_Model_Session')->setLocale(Mage::app()->getLocale()->getLocaleCode()); + return false; } - - return $this; + return true; } /** @@ -279,35 +304,45 @@ abstract class Mage_Backend_Controller_ActionAbstract extends Mage_Core_Controll $auth->getUser()->reload(); } if (!$auth->isLoggedIn()) { - $isRedirectNeeded = false; - if ($request->getPost('login') && $this->_performLogin()) { - $isRedirectNeeded = $this->_redirectIfNeededAfterLogin(); - } - if (!$isRedirectNeeded && !$request->getParam('forwarded')) { - if ($request->getParam('isIframe')) { - $request->setParam('forwarded', true) - ->setControllerName('auth') - ->setActionName('deniedIframe') - ->setDispatched(false); - } else if ($request->getParam('isAjax')) { - $request->setParam('forwarded', true) - ->setControllerName('auth') - ->setActionName('deniedJson') - ->setDispatched(false); - } else { - $request->setParam('forwarded', true) - ->setRouteName('adminhtml') - ->setControllerName('auth') - ->setActionName('login') - ->setDispatched(false); - } - } + $this->_processNotLoggedInUser($request); } } $auth->getAuthStorage()->refreshAcl(); return $this; } + /** + * Process not logged in user data + * + * @param Mage_Core_Controller_Request_Http $request + */ + protected function _processNotLoggedInUser(Mage_Core_Controller_Request_Http $request) + { + $isRedirectNeeded = false; + if ($request->getPost('login') && $this->_performLogin()) { + $isRedirectNeeded = $this->_redirectIfNeededAfterLogin(); + } + if (!$isRedirectNeeded && !$request->getParam('forwarded')) { + if ($request->getParam('isIframe')) { + $request->setParam('forwarded', true) + ->setControllerName('auth') + ->setActionName('deniedIframe') + ->setDispatched(false); + } else if ($request->getParam('isAjax')) { + $request->setParam('forwarded', true) + ->setControllerName('auth') + ->setActionName('deniedJson') + ->setDispatched(false); + } else { + $request->setParam('forwarded', true) + ->setRouteName('adminhtml') + ->setControllerName('auth') + ->setActionName('login') + ->setDispatched(false); + } + } + } + /** * Performs login, if user submitted login form * @@ -363,7 +398,7 @@ abstract class Mage_Backend_Controller_ActionAbstract extends Mage_Core_Controll public function deniedAction() { - $this->getResponse()->setHeader('HTTP/1.1','403 Forbidden'); + $this->getResponse()->setHeader('HTTP/1.1', '403 Forbidden'); if (!Mage::getSingleton('Mage_Backend_Model_Auth_Session')->isLoggedIn()) { $this->_redirect('*/auth/login'); return; @@ -392,10 +427,16 @@ abstract class Mage_Backend_Controller_ActionAbstract extends Mage_Core_Controll return $this; } + /** + * No route action + * + * @param null $coreRoute + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ public function norouteAction($coreRoute = null) { - $this->getResponse()->setHeader('HTTP/1.1','404 Not Found'); - $this->getResponse()->setHeader('Status','404 File not found'); + $this->getResponse()->setHeader('HTTP/1.1', '404 Not Found'); + $this->getResponse()->setHeader('Status', '404 File not found'); $this->loadLayout(array('default', 'adminhtml_noroute')); $this->renderLayout(); } @@ -469,6 +510,7 @@ abstract class Mage_Backend_Controller_ActionAbstract extends Mage_Core_Controll * Translate a phrase * * @return string + * @SuppressWarnings(PHPMD.ShortMethodName) */ public function __() { diff --git a/app/code/core/Mage/Backend/Controller/Router/Default.php b/app/code/core/Mage/Backend/Controller/Router/Default.php index adc207bc4ffe5e954e22646dce64f2af5c6214f7..43b53df357fdc6dff042dcd642c371c461a1c254 100644 --- a/app/code/core/Mage/Backend/Controller/Router/Default.php +++ b/app/code/core/Mage/Backend/Controller/Router/Default.php @@ -47,8 +47,7 @@ class Mage_Backend_Controller_Router_Default extends Mage_Core_Controller_Varien protected $_areaFrontName; /** - * Fetch area front name from params - * + * @param Magento_ObjectManager $objectManager * @param array $options * @throws InvalidArgumentException */ @@ -66,17 +65,30 @@ class Mage_Backend_Controller_Router_Default extends Mage_Core_Controller_Varien */ public function fetchDefault() { - $defaultModuleFrontName = (string) Mage::getConfig()->getNode('admin/routers/adminhtml/args/frontName'); + $moduleFrontName = (string) Mage::getConfig()->getNode('admin/routers/adminhtml/args/frontName'); // set defaults - $d = explode('/', $this->_getDefaultPath()); + $pathParts = explode('/', $this->_getDefaultPath()); $this->getFront()->setDefault(array( - 'area' => !empty($d[0]) ? $d[0] : '', - 'module' => !empty($d[1]) ? $d[1] : $defaultModuleFrontName, - 'controller' => !empty($d[2]) ? $d[2] : 'index', - 'action' => !empty($d[3]) ? $d[3] : 'index' + 'area' => $this->_getParamWithDefaultValue($pathParts, 0, ''), + 'module' => $this->_getParamWithDefaultValue($pathParts, 1, $moduleFrontName), + 'controller' => $this->_getParamWithDefaultValue($pathParts, 2, 'index'), + 'action' => $this->_getParamWithDefaultValue($pathParts, 3, 'index'), )); } + /** + * Retrieve array param by key, or default value + * + * @param array $array + * @param string $key + * @param mixed $defaultValue + * @return mixed + */ + protected function _getParamWithDefaultValue($array, $key, $defaultValue) + { + return !empty($array[$key]) ? $array[$key] : $defaultValue; + } + /** * Get router default request path * @return string @@ -100,6 +112,7 @@ class Mage_Backend_Controller_Router_Default extends Mage_Core_Controller_Varien * checking if we installed or not and doing redirect * * @return bool + * @SuppressWarnings(PHPMD.ExitExpression) */ protected function _afterModuleMatch() { @@ -128,6 +141,7 @@ class Mage_Backend_Controller_Router_Default extends Mage_Core_Controller_Varien * * @param string $path * @return bool + * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ protected function _shouldBeSecure($path) { @@ -153,6 +167,7 @@ class Mage_Backend_Controller_Router_Default extends Mage_Core_Controller_Varien * * @param string $configArea * @param bool $useRouterName + * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function collectRoutes($configArea, $useRouterName) { diff --git a/app/code/core/Mage/Backend/Controller/System/ConfigAbstract.php b/app/code/core/Mage/Backend/Controller/System/ConfigAbstract.php new file mode 100644 index 0000000000000000000000000000000000000000..707f39f5b2fef12efc6c5cc53b4285c4e7dc013b --- /dev/null +++ b/app/code/core/Mage/Backend/Controller/System/ConfigAbstract.php @@ -0,0 +1,162 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_Backend + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * System Configuration Abstract Controller + * + * @category Mage + * @package Mage_Backend + * @author Magento Core Team <core@magentocommerce.com> + */ +abstract class Mage_Backend_Controller_System_ConfigAbstract extends Mage_Backend_Controller_ActionAbstract +{ + /** + * Authorization model + * + * @var Mage_Core_Model_Authorization + */ + protected $_authorization; + + /** + * @var Mage_Backend_Model_Config_Structure + */ + protected $_configStructure; + + /** + * Authentication session + * + * @var Mage_Backend_Model_Auth_StorageInterface + */ + protected $_authSession; + + /** + * @param Zend_Controller_Request_Abstract $request + * @param Zend_Controller_Response_Abstract $response + * @param Magento_ObjectManager $objectManager + * @param Mage_Core_Controller_Varien_Front $frontController + * @param Mage_Core_Model_Authorization $authorization + * @param Mage_Backend_Model_Config_Structure $configStructure + * @param Mage_Backend_Model_Auth_StorageInterface $authSession + * @param array $invokeArgs + */ + public function __construct(Zend_Controller_Request_Abstract $request, + Zend_Controller_Response_Abstract $response, + Magento_ObjectManager $objectManager, + Mage_Core_Controller_Varien_Front $frontController, + Mage_Core_Model_Authorization $authorization, + Mage_Backend_Model_Config_Structure $configStructure, + Mage_Backend_Model_Auth_StorageInterface $authSession, + array $invokeArgs = array() + ) { + parent::__construct($request, $response, $objectManager, $frontController, $invokeArgs); + + $this->_authorization = $authorization; + $this->_configStructure = $configStructure; + $this->_authSession = $authSession; + } + + /** + * Controller pre-dispatch method + * Check if current section is found and is allowed + * + * @return Mage_Backend_Controller_ActionAbstract + */ + public function preDispatch() + { + parent::preDispatch(); + + $section = null; + if (!$this->getRequest()->getParam('section')) { + $section = $this->_configStructure->getFirstSection(); + $this->getRequest()->setParam('section', $section->getId()); + } else { + $this->_isSectionAllowed($this->getRequest()->getParam('section')); + } + return $this; + } + + /** + * Check is allow modify system configuration + * + * @return bool + */ + protected function _isAllowed() + { + return $this->_authorization->isAllowed('Mage_Adminhtml::config'); + } + + /** + * Check if specified section allowed in ACL + * + * Will forward to deniedAction(), if not allowed. + * + * @param string $sectionId + * @throws Exception + * @return bool + */ + protected function _isSectionAllowed($sectionId) + { + try { + if (false == $this->_configStructure->getElement($sectionId)->isAllowed()) { + throw new Exception(''); + } + return true; + } catch (Zend_Acl_Exception $e) { + $this->norouteAction(); + $this->setFlag('', self::FLAG_NO_DISPATCH, true); + return false; + } catch (Exception $e) { + $this->deniedAction(); + $this->setFlag('', self::FLAG_NO_DISPATCH, true); + return false; + } + } + + /** + * Save state of configuration field sets + * + * @param array $configState + * @return bool + */ + protected function _saveState($configState = array()) + { + $adminUser = $this->_authSession->getUser(); + if (is_array($configState)) { + $extra = $adminUser->getExtra(); + if (!is_array($extra)) { + $extra = array(); + } + if (!isset($extra['configState'])) { + $extra['configState'] = array(); + } + foreach ($configState as $fieldset => $state) { + $extra['configState'][$fieldset] = $state; + } + $adminUser->saveExtra($extra); + } + return true; + } +} diff --git a/app/code/core/Mage/Backend/Model/Acl/Config.php b/app/code/core/Mage/Backend/Model/Acl/Config.php index 24d356ed7611ba40e2e407d571a0678c99efb603..88239d5d31c91a0e38cbc7cae530ab131c526674 100644 --- a/app/code/core/Mage/Backend/Model/Acl/Config.php +++ b/app/code/core/Mage/Backend/Model/Acl/Config.php @@ -32,7 +32,7 @@ * @package Mage_Backend * @author Magento Core Team <core@magentocommerce.com> */ -class Mage_Backend_Model_Acl_Config +class Mage_Backend_Model_Acl_Config implements Mage_Core_Model_Acl_Config_ConfigInterface { const CACHE_ID = 'backend_acl_resources'; diff --git a/app/code/core/Mage/Backend/Model/Acl/Loader/Resource.php b/app/code/core/Mage/Backend/Model/Acl/Loader/Resource.php index a73dd13d19b94d965e0c1f935400bd0b3c36463a..9ab6962727c1243c60d6b765338af10806b07fb0 100644 --- a/app/code/core/Mage/Backend/Model/Acl/Loader/Resource.php +++ b/app/code/core/Mage/Backend/Model/Acl/Loader/Resource.php @@ -70,7 +70,7 @@ class Mage_Backend_Model_Acl_Loader_Resource implements Magento_Acl_Loader { /** @var $resourceConfig DOMElement */ foreach ($resources as $resourceConfig) { - if (!($resourceConfig instanceof DOMElement)){ + if (!($resourceConfig instanceof DOMElement)) { continue; } /** @var $resource Magento_Acl_Resource */ diff --git a/app/code/core/Mage/Backend/Model/Auth/Session.php b/app/code/core/Mage/Backend/Model/Auth/Session.php index 7eb99428a872f5d7cdc196d4b0064d80784d575f..ac2d55fb28c4b5ec641fc9913ff2fc697448e9ab 100644 --- a/app/code/core/Mage/Backend/Model/Auth/Session.php +++ b/app/code/core/Mage/Backend/Model/Auth/Session.php @@ -32,7 +32,9 @@ * @package Mage_Backend * @author Magento Core Team <core@magentocommerce.com> */ -class Mage_Backend_Model_Auth_Session extends Mage_Core_Model_Session_Abstract implements Mage_Backend_Model_Auth_StorageInterface +class Mage_Backend_Model_Auth_Session + extends Mage_Core_Model_Session_Abstract + implements Mage_Backend_Model_Auth_StorageInterface { const XML_PATH_SESSION_LIFETIME = 'admin/security/session_lifetime'; @@ -41,7 +43,7 @@ class Mage_Backend_Model_Auth_Session extends Mage_Core_Model_Session_Abstract i * * @var boolean */ - protected $_isFirstPageAfterLogin; + protected $_isFirstAfterLogin; /** * Access Control List builder @@ -135,7 +137,9 @@ class Mage_Backend_Model_Auth_Session extends Mage_Core_Model_Session_Abstract i if (!$acl->has($resource)) { return $acl->isAllowed($user->getAclRole(), null, $privilege); } - } catch (Exception $e) { } + } catch (Exception $e) { + + } } } return false; @@ -170,10 +174,10 @@ class Mage_Backend_Model_Auth_Session extends Mage_Core_Model_Session_Abstract i */ public function isFirstPageAfterLogin() { - if (is_null($this->_isFirstPageAfterLogin)) { - $this->_isFirstPageAfterLogin = $this->getData('is_first_visit', true); + if (is_null($this->_isFirstAfterLogin)) { + $this->_isFirstAfterLogin = $this->getData('is_first_visit', true); } - return $this->_isFirstPageAfterLogin; + return $this->_isFirstAfterLogin; } /** @@ -184,8 +188,8 @@ class Mage_Backend_Model_Auth_Session extends Mage_Core_Model_Session_Abstract i */ public function setIsFirstPageAfterLogin($value) { - $this->_isFirstPageAfterLogin = (bool)$value; - return $this->setIsFirstVisit($this->_isFirstPageAfterLogin); + $this->_isFirstAfterLogin = (bool)$value; + return $this->setIsFirstVisit($this->_isFirstAfterLogin); } /** diff --git a/app/code/core/Mage/Backend/Model/Config.php b/app/code/core/Mage/Backend/Model/Config.php index ece54bfb08e2808aa2687fc310afd052280efce2..f6afffa983cdb1e6ce3f269c8dc04eb43a066e97 100644 --- a/app/code/core/Mage/Backend/Model/Config.php +++ b/app/code/core/Mage/Backend/Model/Config.php @@ -43,11 +43,11 @@ class Mage_Backend_Model_Config extends Varien_Object protected $_eventManager; /** - * Reader that retreives structure of configuration edit form from storage + * System configuration structure * - * @var Mage_Backend_Model_Config_Structure_Reader + * @var Mage_Backend_Model_Config_Structure */ - protected $_structureReader; + protected $_configStructure; /** * Application config @@ -77,30 +77,47 @@ class Mage_Backend_Model_Config extends Varien_Object */ protected $_application; - public function __construct(array $data = array()) - { - $this->_eventManager = isset($data['eventManager']) ? - $data['eventManager'] : - Mage::getSingleton('Mage_Core_Model_Event_Manager'); - - $this->_structureReader = isset($data['structureReader']) ? - $data['structureReader'] : - Mage::getSingleton('Mage_Backend_Model_Config_Structure_Reader'); - - $this->_transactionFactory = isset($data['transactionFactory']) ? - $data['transactionFactory'] : - Mage::getSingleton('Mage_Core_Model_Resource_Transaction_Factory'); - - $this->_objectFactory = isset($data['objectFactory']) ? - $data['objectFactory'] : - Mage::getConfig(); - - $this->_appConfig = isset($data['applicationConfig']) ? - $data['applicationConfig'] : - Mage::getConfig(); + /** + * Config data loader + * + * @var Mage_Backend_Model_Config_Loader + */ + protected $_configLoader; - $this->_application = isset($data['application']) ? $data['application'] : Mage::app(); + /** + * Config data factory + * + * @var Mage_Backend_Model_Config_Loader + */ + protected $_configDataFactory; + /** + * @param Mage_Core_Model_App $application + * @param Mage_Core_Model_Config $config + * @param Mage_Core_Model_Event_Manager $eventManager + * @param Mage_Backend_Model_Config_Structure $configStructure + * @param Mage_Core_Model_Resource_Transaction_Factory $transactionFactory + * @param Mage_Backend_Model_Config_Loader $configLoader + * @param Mage_Core_Model_Config_Data_Factory $configDataFactory + * @param array $data + */ + public function __construct( + Mage_Core_Model_App $application, + Mage_Core_Model_Config $config, + Mage_Core_Model_Event_Manager $eventManager, + Mage_Backend_Model_Config_Structure $configStructure, + Mage_Core_Model_Resource_Transaction_Factory $transactionFactory, + Mage_Backend_Model_Config_Loader $configLoader, + Mage_Core_Model_Config_Data_Factory $configDataFactory, + array $data = array() + ) { + $this->_eventManager = $eventManager; + $this->_configStructure = $configStructure; + $this->_transactionFactory = $transactionFactory; + $this->_appConfig = $config; + $this->_application = $application; + $this->_configLoader = $configLoader; + $this->_configDataFactory = $configDataFactory; parent::__construct($data); } @@ -117,19 +134,12 @@ class Mage_Backend_Model_Config extends Varien_Object $this->_eventManager->dispatch('model_config_data_save_before', array('object' => $this)); - $section = $this->getSection(); - $website = $this->getWebsite(); - $store = $this->getStore(); + $sectionId = $this->getSection(); $groups = $this->getGroups(); - $scope = $this->getScope(); - $scopeId = $this->getScopeId(); - if (empty($groups)) { return $this; } - $sections = $this->_structureReader->getConfiguration()->getSections(); - $oldConfig = $this->_getConfig(true); $deleteTransaction = $this->_transactionFactory->create(); @@ -138,98 +148,120 @@ class Mage_Backend_Model_Config extends Varien_Object /* @var $saveTransaction Mage_Core_Model_Resource_Transaction */ // Extends for old config data - $oldConfigAdditionalGroups = array(); + $extraOldGroups = array(); - foreach ($groups as $group => $groupData) { + foreach ($groups as $groupId => $groupData) { + $this->_processGroup( + $groupId, $groupData, $groups, $sectionId, $extraOldGroups, $oldConfig, + $saveTransaction, $deleteTransaction + ); + } - /** - * Map field names if they were cloned - */ - $groupConfig = $sections[$section]['groups'][$group]; + $deleteTransaction->delete(); + $saveTransaction->save(); - if ($clonedFields = (isset($groupConfig['clone_fields']) && !empty($groupConfig['clone_fields']))) { - if (isset($groupConfig['clone_model']) && $groupConfig['clone_model']) { - $cloneModel = $this->_objectFactory->getModelInstance((string)$groupConfig['clone_model']); - } else { - Mage::throwException('Config form fieldset clone model required to be able to clone fields'); - } - $mappedFields = array(); + return $this; + } - if (isset($groupConfig['fields'])) { - $fieldsConfig = $groupConfig['fields']; + /** + * Process group data + * + * @param string $groupId + * @param array $groupData + * @param array $groups + * @param string $path + * @param array $extraOldGroups + * @param array $oldConfig + * @param Mage_Core_Model_Resource_Transaction $saveTransaction + * @param Mage_Core_Model_Resource_Transaction $deleteTransaction + */ + public function _processGroup( + $groupId, + array $groupData, + array $groups, + $path, + array &$extraOldGroups, + array &$oldConfig, + Mage_Core_Model_Resource_Transaction $saveTransaction, + Mage_Core_Model_Resource_Transaction $deleteTransaction + ) { + $groupPath = $path . '/' . $groupId; + $website = $this->getWebsite(); + $store = $this->getStore(); + $scope = $this->getScope(); + $scopeId = $this->getScopeId(); + /** + * + * Map field names if they were cloned + */ + /** @var $group Mage_Backend_Model_Config_Structure_Element_Group */ + $group = $this->_configStructure->getElement($groupPath); + + + // set value for group field entry by fieldname + // use extra memory + $fieldsetData = array(); + if (isset($groupData['fields'])) { + if ($group->shouldCloneFields()) { + $cloneModel = $group->getCloneModel(); + $mappedFields = array(); - foreach ($fieldsConfig as $field => $node) { - foreach ($cloneModel->getPrefixes() as $prefix) { - $mappedFields[$prefix['field'] . (string)$field] = (string)$field; - } + /** @var $field Mage_Backend_Model_Config_Structure_Element_Field */ + foreach ($group->getChildren() as $field) { + foreach ($cloneModel->getPrefixes() as $prefix) { + $mappedFields[$prefix['field'] . $field->getId()] = $field->getId(); } } } - // set value for group field entry by fieldname - // use extra memory - $fieldsetData = array(); - foreach ($groupData['fields'] as $field => $fieldData) { - $fieldsetData[$field] = (is_array($fieldData) && isset($fieldData['value'])) + foreach ($groupData['fields'] as $fieldId => $fieldData) { + $fieldsetData[$fieldId] = (is_array($fieldData) && isset($fieldData['value'])) ? $fieldData['value'] : null; } - foreach ($groupData['fields'] as $field => $fieldData) { - /** - * Get field backend model - */ - if (isset($groupConfig['fields'][$field]['backend_model'])) { - $backendClass = $groupConfig['fields'][$field]['backend_model']; - } else if ($clonedFields && - isset($mappedFields[$field]) && - isset($groupConfig['fields'][$mappedFields[$field]]['backend_model']) - ) { - $backendClass = $groupConfig['fields'][$mappedFields[$field]]['backend_model']; - } else { - $backendClass = 'Mage_Core_Model_Config_Data'; - } - - /* @var $dataObject Mage_Core_Model_Config_Data */ - $dataObject = $this->_objectFactory->getModelInstance($backendClass); - if (!$dataObject instanceof Mage_Core_Model_Config_Data) { - Mage::throwException('Invalid config field backend model: ' . $backendClass); + foreach ($groupData['fields'] as $fieldId => $fieldData) { + $originalFieldId = $fieldId; + if ($group->shouldCloneFields() && isset($mappedFields[$fieldId])) { + $originalFieldId = $mappedFields[$fieldId]; } + /** @var $field Mage_Backend_Model_Config_Structure_Element_Field */ + $field = $this->_configStructure->getElement($groupPath . '/' . $originalFieldId); + + /** @var Mage_Core_Model_Config_Data $backendModel */ + $backendModel = $field->hasBackendModel() ? + $field->getBackendModel() : + $this->_configDataFactory->create(); + + $data = array( + 'field' => $fieldId, + 'groups' => $groups, + 'group_id' => $group->getId(), + 'store_code' => $store, + 'website_code' => $website, + 'scope' => $scope, + 'scope_id' => $scopeId, + 'field_config' => $field->getData(), + 'fieldset_data' => $fieldsetData, + ); + $backendModel->addData($data); - if (isset($groupConfig['fields'][$field])) { - $fieldConfig = $groupConfig['fields'][$field]; - } else if ($clonedFields && isset($mappedFields[$field])) { - $fieldConfig = $groupConfig['fields'][$mappedFields[$field]]; - } - - $dataObject - ->setField($field) - ->setGroups($groups) - ->setGroupId($group) - ->setStoreCode($store) - ->setWebsiteCode($website) - ->setScope($scope) - ->setScopeId($scopeId) - ->setFieldConfig($fieldConfig) - ->setFieldsetData($fieldsetData); - - $this->_checkSingleStoreMode($fieldConfig, $dataObject); + $this->_checkSingleStoreMode($field, $backendModel); - if (!isset($fieldData['value'])) { + if (false == isset($fieldData['value'])) { $fieldData['value'] = null; } - $path = $section . '/' . $group . '/' . $field; - + $path = $field->getGroupPath() . '/' . $fieldId; /** * Look for custom defined field path */ - if ($fieldConfig && isset($fieldConfig['config_path'])) { - $configPath = (string)$fieldConfig['config_path']; + if ($field && $field->getConfigPath()) { + $configPath = $field->getConfigPath(); if (!empty($configPath) && strrpos($configPath, '/') > 0) { // Extend old data with specified section group $groupPath = substr($configPath, 0, strrpos($configPath, '/')); - if (!isset($oldConfigAdditionalGroups[$groupPath])) { + if (!isset($extraOldGroups[$groupPath])) { $oldConfig = $this->extendConfig($groupPath, true, $oldConfig); - $oldConfigAdditionalGroups[$groupPath] = true; + $extraOldGroups[$groupPath] = true; } $path = $configPath; } @@ -237,32 +269,34 @@ class Mage_Backend_Model_Config extends Varien_Object $inherit = !empty($fieldData['inherit']); - $dataObject->setPath($path) - ->setValue($fieldData['value']); + $backendModel->setPath($path)->setValue($fieldData['value']); if (isset($oldConfig[$path])) { - $dataObject->setConfigId($oldConfig[$path]['config_id']); + $backendModel->setConfigId($oldConfig[$path]['config_id']); /** * Delete config data if inherit */ if (!$inherit) { - $saveTransaction->addObject($dataObject); + $saveTransaction->addObject($backendModel); } else { - $deleteTransaction->addObject($dataObject); + $deleteTransaction->addObject($backendModel); } } elseif (!$inherit) { - $dataObject->unsConfigId(); - $saveTransaction->addObject($dataObject); + $backendModel->unsConfigId(); + $saveTransaction->addObject($backendModel); } } - } - $deleteTransaction->delete(); - $saveTransaction->save(); - - return $this; + if (isset($groupData['groups'])) { + foreach ($groupData['groups'] as $subGroupId => $subGroupData) { + $this->_processGroup( + $subGroupId, $subGroupData, $groups, $groupPath, $extraOldGroups, + $oldConfig, $saveTransaction, $deleteTransaction + ); + } + } } /** @@ -288,7 +322,7 @@ class Mage_Backend_Model_Config extends Varien_Object */ public function extendConfig($path, $full = true, $oldConfig = array()) { - $extended = $this->_getPathConfig($path, $full); + $extended = $this->_configLoader->getConfigByPath($path, $this->getScope(), $this->getScopeId(), $full); if (is_array($oldConfig) && !empty($oldConfig)) { return $oldConfig + $extended; } @@ -340,51 +374,26 @@ class Mage_Backend_Model_Config extends Varien_Object */ protected function _getConfig($full = true) { - return $this->_getPathConfig($this->getSection(), $full); - } - - /** - * Return formatted config data for specified path prefix - * - * @param string $path Config path prefix - * @param bool $full Simple config structure or not - * @return array - */ - protected function _getPathConfig($path, $full = true) - { - $configDataCollection = $this->_objectFactory->getModelInstance('Mage_Core_Model_Config_Data') - ->getCollection() - ->addScopeFilter($this->getScope(), $this->getScopeId(), $path); - - $config = array(); - foreach ($configDataCollection as $data) { - if ($full) { - $config[$data->getPath()] = array( - 'path' => $data->getPath(), - 'value' => $data->getValue(), - 'config_id' => $data->getConfigId() - ); - } - else { - $config[$data->getPath()] = $data->getValue(); - } - } - return $config; + return $this->_configLoader->getConfigByPath( + $this->getSection(), $this->getScope(), $this->getScopeId(), $full + ); } /** * Set correct scope if isSingleStoreMode = true * - * @param array $fieldConfig + * @param Mage_Backend_Model_Config_Structure_Element_Field $fieldConfig * @param Mage_Core_Model_Config_Data $dataObject */ - protected function _checkSingleStoreMode($fieldConfig, $dataObject) - { + protected function _checkSingleStoreMode( + Mage_Backend_Model_Config_Structure_Element_Field $fieldConfig, + $dataObject + ) { $isSingleStoreMode = $this->_application->isSingleStoreMode(); if (!$isSingleStoreMode) { return; } - if (!isset($fieldConfig['showInDefault']) || !(int)$fieldConfig['showInDefault']) { + if (!$fieldConfig->showInDefault()) { $websites = $this->_application->getWebsites(); $singleStoreWebsite = array_shift($websites); $dataObject->setScope('websites'); diff --git a/app/code/core/Mage/Backend/Model/Config/Backend/Admin/Observer.php b/app/code/core/Mage/Backend/Model/Config/Backend/Admin/Observer.php index f67efae74a3974081ad75c783aed058ab4ce3ceb..2dfce24d9c181dcd612230ff2e98303ae8cf8a0c 100644 --- a/app/code/core/Mage/Backend/Model/Config/Backend/Admin/Observer.php +++ b/app/code/core/Mage/Backend/Model/Config/Backend/Admin/Observer.php @@ -29,9 +29,9 @@ class Mage_Backend_Model_Config_Backend_Admin_Observer /** * Log out user and redirect him to new admin custom url * - * @param Varien_Event_Observer $observer + * @SuppressWarnings(PHPMD.ExitExpression) */ - public function afterCustomUrlChanged($observer) + public function afterCustomUrlChanged() { if (is_null(Mage::registry('custom_admin_path_redirect'))) { return; diff --git a/app/code/core/Mage/Backend/Model/Config/Backend/Admin/Password/Link/Expirationperiod.php b/app/code/core/Mage/Backend/Model/Config/Backend/Admin/Password/Link/Expirationperiod.php index 03e8f1258a13872c358e5733281adb4554bf440a..e55a475cb9518fb9758f3858d31b90ad06eeb9e7 100644 --- a/app/code/core/Mage/Backend/Model/Config/Backend/Admin/Password/Link/Expirationperiod.php +++ b/app/code/core/Mage/Backend/Model/Config/Backend/Admin/Password/Link/Expirationperiod.php @@ -42,12 +42,12 @@ class Mage_Backend_Model_Config_Backend_Admin_Password_Link_Expirationperiod protected function _beforeSave() { parent::_beforeSave(); - $resetPasswordLinkExpirationPeriod = (int)$this->getValue(); + $expirationPeriod = (int)$this->getValue(); - if ($resetPasswordLinkExpirationPeriod < 1) { - $resetPasswordLinkExpirationPeriod = (int)$this->getOldValue(); + if ($expirationPeriod < 1) { + $expirationPeriod = (int)$this->getOldValue(); } - $this->setValue((string)$resetPasswordLinkExpirationPeriod); + $this->setValue((string)$expirationPeriod); return $this; } } diff --git a/app/code/core/Mage/Backend/Model/Config/Backend/Admin/Usecustom.php b/app/code/core/Mage/Backend/Model/Config/Backend/Admin/Usecustom.php index 69ac98a9a9bdea156f35866846fb364c7a3bc97f..98ad3de82de69162831a6ac634c1c0c2934f800f 100644 --- a/app/code/core/Mage/Backend/Model/Config/Backend/Admin/Usecustom.php +++ b/app/code/core/Mage/Backend/Model/Config/Backend/Admin/Usecustom.php @@ -45,7 +45,9 @@ class Mage_Backend_Model_Config_Backend_Admin_Usecustom extends Mage_Core_Model_ if ($value == 1) { $customUrl = $this->getData('groups/url/fields/custom/value'); if (empty($customUrl)) { - Mage::throwException(Mage::helper('Mage_Backend_Helper_Data')->__('Please specify the admin custom URL.')); + Mage::throwException( + Mage::helper('Mage_Backend_Helper_Data')->__('Please specify the admin custom URL.') + ); } } diff --git a/app/code/core/Mage/Backend/Model/Config/Backend/Baseurl.php b/app/code/core/Mage/Backend/Model/Config/Backend/Baseurl.php index dd02f3274b9cc44aca8f4747b7e0c183a2d047a7..79e283f29d903c0dda053567feffe4cbf769a2f6 100644 --- a/app/code/core/Mage/Backend/Model/Config/Backend/Baseurl.php +++ b/app/code/core/Mage/Backend/Model/Config/Backend/Baseurl.php @@ -34,11 +34,16 @@ class Mage_Backend_Model_Config_Backend_Baseurl extends Mage_Core_Model_Config_D if (!preg_match('#^{{((un)?secure_)?(base|public)_url}}#', $value)) { $parsedUrl = parse_url($value); if (!isset($parsedUrl['scheme']) || !isset($parsedUrl['host'])) { - Mage::throwException(Mage::helper('Mage_Core_Helper_Data')->__('The %s you entered is invalid. Please make sure that it follows "http://domain.com/" format.', $this->getFieldConfig()->label)); + $fieldConfig = $this->getFieldConfig(); + $exceptionMsg = Mage::helper('Mage_Core_Helper_Data') + ->__('The %s you entered is invalid. Please make sure that it follows "http://domain.com/" format.', + $fieldConfig['label'] + ); + Mage::throwException($exceptionMsg); } } - $value = rtrim($value, '/'); + $value = rtrim($value, '/'); /** * If value is special ({{}}) we don't need add slash */ diff --git a/app/code/core/Mage/Backend/Model/Config/Backend/Currency/Abstract.php b/app/code/core/Mage/Backend/Model/Config/Backend/Currency/Abstract.php index bed148e39fae079096529dcf0ef207245d786421..f4b6df70963fc9c9ac54bf5a85090cc58ac200d6 100644 --- a/app/code/core/Mage/Backend/Model/Config/Backend/Currency/Abstract.php +++ b/app/code/core/Mage/Backend/Model/Config/Backend/Currency/Abstract.php @@ -44,7 +44,9 @@ abstract class Mage_Backend_Model_Config_Backend_Currency_Abstract extends Mage_ protected function _getAllowedCurrencies() { if ($this->getData('groups/options/fields/allow/inherit')) { - return explode(',', Mage::getConfig()->getNode('currency/options/allow', $this->getScope(), $this->getScopeId())); + return explode( + ',', Mage::getConfig()->getNode('currency/options/allow', $this->getScope(), $this->getScopeId()) + ); } return $this->getData('groups/options/fields/allow/value'); } diff --git a/app/code/core/Mage/Backend/Model/Config/Backend/Currency/Allow.php b/app/code/core/Mage/Backend/Model/Config/Backend/Currency/Allow.php index d05058d9f10284b9cf4549382e958b37eb1b2582..d5b56a051524e15c0eabba1995a50e0e7440a101 100644 --- a/app/code/core/Mage/Backend/Model/Config/Backend/Currency/Allow.php +++ b/app/code/core/Mage/Backend/Model/Config/Backend/Currency/Allow.php @@ -47,12 +47,18 @@ class Mage_Backend_Model_Config_Backend_Currency_Allow extends Mage_Backend_Mode $exceptions = array(); foreach ($this->_getAllowedCurrencies() as $currencyCode) { if (!in_array($currencyCode, $this->_getInstalledCurrencies())) { - $exceptions[] = Mage::helper('Mage_Backend_Helper_Data')->__('Selected allowed currency "%s" is not available in installed currencies.', Mage::app()->getLocale()->currency($currencyCode)->getName()); + $exceptions[] = Mage::helper('Mage_Backend_Helper_Data') + ->__('Selected allowed currency "%s" is not available in installed currencies.', + Mage::app()->getLocale()->currency($currencyCode)->getName() + ); } } if (!in_array($this->_getCurrencyDefault(), $this->_getAllowedCurrencies())) { - $exceptions[] = Mage::helper('Mage_Backend_Helper_Data')->__('Default display currency "%s" is not available in allowed currencies.', Mage::app()->getLocale()->currency($this->_getCurrencyDefault())->getName()); + $exceptions[] = Mage::helper('Mage_Backend_Helper_Data') + ->__('Default display currency "%s" is not available in allowed currencies.', + Mage::app()->getLocale()->currency($this->_getCurrencyDefault())->getName() + ); } if ($exceptions) { diff --git a/app/code/core/Mage/Backend/Model/Config/Backend/Currency/Base.php b/app/code/core/Mage/Backend/Model/Config/Backend/Currency/Base.php index 83838fc14f0cda3746a1bf53925ccd92fdcdc4df..cf51c64b2e14baee74572db3a7177febbcac6c65 100644 --- a/app/code/core/Mage/Backend/Model/Config/Backend/Currency/Base.php +++ b/app/code/core/Mage/Backend/Model/Config/Backend/Currency/Base.php @@ -44,7 +44,8 @@ class Mage_Backend_Model_Config_Backend_Currency_Base extends Mage_Backend_Model protected function _afterSave() { if (!in_array($this->getValue(), $this->_getInstalledCurrencies())) { - Mage::throwException(Mage::helper('Mage_Backend_Helper_Data')->__('Selected base currency is not available in installed currencies.')); + Mage::throwException(Mage::helper('Mage_Backend_Helper_Data') + ->__('Selected base currency is not available in installed currencies.')); } return $this; diff --git a/app/code/core/Mage/Backend/Model/Config/Backend/Currency/Cron.php b/app/code/core/Mage/Backend/Model/Config/Backend/Currency/Cron.php index d07ff33336dc76bc7280e774e0b2c6bcb8510630..74d2e13c1cfea2f6dfadde34349fbd46d7c6f851 100644 --- a/app/code/core/Mage/Backend/Model/Config/Backend/Currency/Cron.php +++ b/app/code/core/Mage/Backend/Model/Config/Backend/Currency/Cron.php @@ -38,18 +38,12 @@ class Mage_Backend_Model_Config_Backend_Currency_Cron extends Mage_Core_Model_Co protected function _afterSave() { - $enabled = $this->getData('groups/import/fields/enabled/value'); - $service = $this->getData('groups/import/fields/service/value'); $time = $this->getData('groups/import/fields/time/value'); $frequency = $this->getData('groups/import/fields/frequency/value'); - $errorEmail = $this->getData('groups/import/fields/error_email/value'); - $frequencyDaily = Mage_Cron_Model_Config_Source_Frequency::CRON_DAILY; $frequencyWeekly = Mage_Cron_Model_Config_Source_Frequency::CRON_WEEKLY; $frequencyMonthly = Mage_Cron_Model_Config_Source_Frequency::CRON_MONTHLY; - $cronDayOfWeek = date('N'); - $cronExprArray = array( intval($time[1]), # Minute intval($time[0]), # Hour diff --git a/app/code/core/Mage/Backend/Model/Config/Backend/Currency/Default.php b/app/code/core/Mage/Backend/Model/Config/Backend/Currency/Default.php index 6a570219bfc7eaadecb2415dd9cf7fe81f72ec32..343e4dffcd5341b1117004dfa52b20b0a2c7fedb 100644 --- a/app/code/core/Mage/Backend/Model/Config/Backend/Currency/Default.php +++ b/app/code/core/Mage/Backend/Model/Config/Backend/Currency/Default.php @@ -45,11 +45,17 @@ class Mage_Backend_Model_Config_Backend_Currency_Default extends Mage_Backend_Mo protected function _afterSave() { if (!in_array($this->getValue(), $this->_getInstalledCurrencies())) { - Mage::throwException(Mage::helper('Mage_Backend_Helper_Data')->__('Selected default display currency is not available in installed currencies.')); + Mage::throwException( + Mage::helper('Mage_Backend_Helper_Data') + ->__('Selected default display currency is not available in installed currencies.') + ); } if (!in_array($this->getValue(), $this->_getAllowedCurrencies())) { - Mage::throwException(Mage::helper('Mage_Backend_Helper_Data')->__('Selected default display currency is not available in allowed currencies.')); + Mage::throwException( + Mage::helper('Mage_Backend_Helper_Data') + ->__('Selected default display currency is not available in allowed currencies.') + ); } return $this; diff --git a/app/code/core/Mage/Backend/Model/Config/Backend/Email/Logo.php b/app/code/core/Mage/Backend/Model/Config/Backend/Email/Logo.php index 97854ec4aad2d49e54abd5a7f26b4d5550c6ae56..30c56284a1c320b9c678ebec6d710a3124251c8f 100644 --- a/app/code/core/Mage/Backend/Model/Config/Backend/Email/Logo.php +++ b/app/code/core/Mage/Backend/Model/Config/Backend/Email/Logo.php @@ -25,12 +25,12 @@ */ /** - * Backend model for uploading transactional emails custom logo image - * - * @category Mage - * @package Mage_Backend - * @author Magento Core Team <core@magentocommerce.com> - */ + * Backend model for uploading transactional emails custom logo image + * + * @category Mage + * @package Mage_Backend + * @author Magento Core Team <core@magentocommerce.com> + */ class Mage_Backend_Model_Config_Backend_Email_Logo extends Mage_Backend_Model_Config_Backend_Image { /** @@ -87,8 +87,10 @@ class Mage_Backend_Model_Config_Backend_Email_Logo extends Mage_Backend_Model_Co $fileTmpName = $_FILES['groups']['tmp_name'][$this->getGroupId()]['fields'][$this->getField()]['value']; if ($this->getOldValue() && ($fileTmpName || $deleteFlag)) { - $io = new Varien_Io_File(); - $io->rm($this->_getUploadRoot(self::UPLOAD_ROOT_TOKEN) . DS . self::UPLOAD_DIR . DS . $this->getOldValue()); + $ioService = new Varien_Io_File(); + $ioService->rm( + $this->_getUploadRoot(self::UPLOAD_ROOT_TOKEN) . DS . self::UPLOAD_DIR . DS . $this->getOldValue() + ); } return parent::_beforeSave(); } diff --git a/app/code/core/Mage/Backend/Model/Config/Backend/Email/Sender.php b/app/code/core/Mage/Backend/Model/Config/Backend/Email/Sender.php index 69013b4a37a53d6c2a3e122a53e132714e296414..243ba236e084bf3df6a942053175e7a2aabb9c14 100644 --- a/app/code/core/Mage/Backend/Model/Config/Backend/Email/Sender.php +++ b/app/code/core/Mage/Backend/Model/Config/Backend/Email/Sender.php @@ -43,11 +43,17 @@ class Mage_Backend_Model_Config_Backend_Email_Sender extends Mage_Core_Model_Con { $value = $this->getValue(); if (!preg_match("/^[\S ]+$/", $value)) { - Mage::throwException(Mage::helper('Mage_Backend_Helper_Data')->__('Invalid sender name "%s". Please use only visible characters and spaces.', $value)); + Mage::throwException( + Mage::helper('Mage_Backend_Helper_Data') + ->__('Invalid sender name "%s". Please use only visible characters and spaces.', $value) + ); } if (strlen($value) > 255) { - Mage::throwException(Mage::helper('Mage_Backend_Helper_Data')->__('Maximum sender name length is 255. Please correct your settings.')); + Mage::throwException( + Mage::helper('Mage_Backend_Helper_Data') + ->__('Maximum sender name length is 255. Please correct your settings.') + ); } return $this; } diff --git a/app/code/core/Mage/Backend/Model/Config/Backend/File.php b/app/code/core/Mage/Backend/Model/Config/Backend/File.php index 23433d89057618f813d9e9f085b76e22ff96500c..929db991b666a360f95375d037cde8510b8276a7 100644 --- a/app/code/core/Mage/Backend/Model/Config/Backend/File.php +++ b/app/code/core/Mage/Backend/Model/Config/Backend/File.php @@ -33,6 +33,11 @@ */ class Mage_Backend_Model_Config_Backend_File extends Mage_Core_Model_Config_Data { + /** + * @var Mage_Backend_Model_Config_Backend_File_RequestData + */ + protected $_requestData; + /** * Upload max file size in kilobytes * @@ -40,6 +45,28 @@ class Mage_Backend_Model_Config_Backend_File extends Mage_Core_Model_Config_Data */ protected $_maxFileSize = 0; + /** + * @param Mage_Core_Model_Event_Manager $eventDispatcher + * @param Mage_Core_Model_Cache $cacheManager + * @param Mage_Backend_Model_Config_Backend_File_RequestData $requestData + * @param Mage_Core_Model_Resource_Abstract $resource + * @param Varien_Data_Collection_Db $resourceCollection + * @param array $data + */ + public function __construct( + Mage_Core_Model_Event_Manager $eventDispatcher, + Mage_Core_Model_Cache $cacheManager, + Mage_Backend_Model_Config_Backend_File_RequestData $requestData, + Mage_Core_Model_Resource_Abstract $resource = null, + Varien_Data_Collection_Db $resourceCollection = null, + array $data = array() + ) { + parent::__construct($eventDispatcher, $cacheManager, $resource, $resourceCollection, $data); + $this->_requestData = $requestData; + } + + + /** * Save uploaded file before saving config value * @@ -48,16 +75,14 @@ class Mage_Backend_Model_Config_Backend_File extends Mage_Core_Model_Config_Data protected function _beforeSave() { $value = $this->getValue(); - if ($_FILES['groups']['tmp_name'][$this->getGroupId()]['fields'][$this->getField()]['value']){ + $tmpName = $this->_requestData->getTmpName($this->getPath()); + if ($tmpName) { $uploadDir = $this->_getUploadDir(); - try { $file = array(); - $tmpName = $_FILES['groups']['tmp_name']; - $file['tmp_name'] = $tmpName[$this->getGroupId()]['fields'][$this->getField()]['value']; - $name = $_FILES['groups']['name']; - $file['name'] = $name[$this->getGroupId()]['fields'][$this->getField()]['value']; + $file['tmp_name'] = $tmpName; + $file['name'] = $this->_requestData->getName($this->getPath()); $uploader = new Mage_Core_Model_File_Uploader($file); $uploader->setAllowedExtensions($this->_getAllowedExtensions()); $uploader->setAllowRenameFiles(true); @@ -96,7 +121,10 @@ class Mage_Backend_Model_Config_Backend_File extends Mage_Core_Model_Config_Data public function validateMaxSize($filePath) { if ($this->_maxFileSize > 0 && filesize($filePath) > ($this->_maxFileSize * 1024)) { - throw Mage::exception('Mage_Core', Mage::helper('Mage_Backend_Helper_Data')->__('Uploaded file is larger than %.2f kilobytes allowed by server', $this->_maxFileSize)); + throw Mage::exception('Mage_Core', + Mage::helper('Mage_Backend_Helper_Data') + ->__('Uploaded file is larger than %.2f kilobytes allowed by server', $this->_maxFileSize) + ); } } @@ -108,8 +136,8 @@ class Mage_Backend_Model_Config_Backend_File extends Mage_Core_Model_Config_Data protected function _addWhetherScopeInfo() { $fieldConfig = $this->getFieldConfig(); - $el = array_key_exists('upload_dir', $fieldConfig) ? $fieldConfig['upload_dir'] : array(); - return (is_array($el) && array_key_exists('scope_info', $el) && $el['scope_info']); + $dirParams = array_key_exists('upload_dir', $fieldConfig) ? $fieldConfig['upload_dir'] : array(); + return (is_array($dirParams) && array_key_exists('scope_info', $dirParams) && $dirParams['scope_info']); } /** @@ -131,11 +159,13 @@ class Mage_Backend_Model_Config_Backend_File extends Mage_Core_Model_Config_Data if (is_array($fieldConfig['upload_dir'])) { $uploadDir = $fieldConfig['upload_dir']['value']; - if (array_key_exists('scope_info', $fieldConfig['upload_dir']) && $fieldConfig['upload_dir']['scope_info']){ + if (array_key_exists('scope_info', $fieldConfig['upload_dir']) + && $fieldConfig['upload_dir']['scope_info'] + ) { $uploadDir = $this->_appendScopeInfo($uploadDir); } - if (array_key_exists('config', $fieldConfig['upload_dir'])){ + if (array_key_exists('config', $fieldConfig['upload_dir'])) { $uploadRoot = $this->_getUploadRoot($fieldConfig['upload_dir']['config']); $uploadDir = $uploadRoot . '/' . $uploadDir; } @@ -151,6 +181,7 @@ class Mage_Backend_Model_Config_Backend_File extends Mage_Core_Model_Config_Data * * @var string * @return string + * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ protected function _getUploadRoot($token) { diff --git a/app/code/core/Mage/Backend/Model/Config/Backend/File/RequestData.php b/app/code/core/Mage/Backend/Model/Config/Backend/File/RequestData.php new file mode 100644 index 0000000000000000000000000000000000000000..215d4bd76bf36b1a098bbbcf06981b332dd080d7 --- /dev/null +++ b/app/code/core/Mage/Backend/Model/Config/Backend/File/RequestData.php @@ -0,0 +1,84 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_Backend + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + + +class Mage_Backend_Model_Config_Backend_File_RequestData +{ + /** + * Retrieve uploaded file tmp name by path + * + * @param string $path + * @return string + */ + public function getTmpName($path) + { + return $this->_getParam('tmp_name', $path); + } + + /** + * Retrieve uploaded file name by path + * + * @param string $path + * @return string + */ + public function getName($path) + { + return $this->_getParam('name', $path); + } + + /** + * Get $_FILES superglobal value by path + * + * @param string $paramName + * @param string $path + * @return string + */ + protected function _getParam($paramName, $path) + { + $pathParts = explode('/', $path); + array_shift($pathParts); + $fieldId = array_pop($pathParts); + $firstGroupId = array_shift($pathParts); + if (!isset($_FILES['groups'][$paramName])) { + return null; + } + $groupData = $_FILES['groups'][$paramName]; + if (isset($groupData[$firstGroupId])) { + $groupData = $groupData[$firstGroupId]; + } + foreach ($pathParts as $groupId) { + if (isset($groupData['groups'][$groupId])) { + $groupData = $groupData['groups'][$groupId]; + } else { + return null; + } + } + if (isset($groupData['fields'][$fieldId]['value'])) { + return $groupData['fields'][$fieldId]['value']; + } + return null; + } +} \ No newline at end of file diff --git a/app/code/core/Mage/Backend/Model/Config/Backend/Image/Adapter.php b/app/code/core/Mage/Backend/Model/Config/Backend/Image/Adapter.php index 5e0fd265b8ac677301b545ad16888bf0255d164a..9884d66294c5e14b18212a42a9d97720f8081adc 100644 --- a/app/code/core/Mage/Backend/Model/Config/Backend/Image/Adapter.php +++ b/app/code/core/Mage/Backend/Model/Config/Backend/Image/Adapter.php @@ -48,7 +48,8 @@ class Mage_Backend_Model_Config_Backend_Image_Adapter extends Mage_Core_Model_Co try { $adapter->checkDependencies(); } catch (Exception $e) { - $message = Mage::helper('Mage_Core_Helper_Data')->__('The specified image adapter cannot be used because of some missed dependencies.'); + $message = Mage::helper('Mage_Core_Helper_Data') + ->__('The specified image adapter cannot be used because of some missed dependencies.'); throw new Mage_Core_Exception($message); } diff --git a/app/code/core/Mage/Backend/Model/Config/Backend/Image/Favicon.php b/app/code/core/Mage/Backend/Model/Config/Backend/Image/Favicon.php index 6259ae856e6ccd892dc9d4a9394c4be624eb6690..480781eb7ecebccbe57450a18b04bd7511d26e34 100644 --- a/app/code/core/Mage/Backend/Model/Config/Backend/Image/Favicon.php +++ b/app/code/core/Mage/Backend/Model/Config/Backend/Image/Favicon.php @@ -86,7 +86,8 @@ class Mage_Backend_Model_Config_Backend_Image_Favicon extends Mage_Backend_Model * @param $token * @return string */ - protected function _getUploadRoot($token) { + protected function _getUploadRoot($token) + { return Mage::getBaseDir($token); } } diff --git a/app/code/core/Mage/Api/Model/Server/Adapter/Interface.php b/app/code/core/Mage/Backend/Model/Config/Backend/Image/Logo.php similarity index 51% rename from app/code/core/Mage/Api/Model/Server/Adapter/Interface.php rename to app/code/core/Mage/Backend/Model/Config/Backend/Image/Logo.php index 9e2dcb40542f16b68d0653ba7b66b829a666d3a2..adb123a5905a6c8524a849253f7e2e9d9de36f99 100644 --- a/app/code/core/Mage/Api/Model/Server/Adapter/Interface.php +++ b/app/code/core/Mage/Backend/Model/Config/Backend/Image/Logo.php @@ -19,63 +19,65 @@ * needs please refer to http://www.magentocommerce.com for more information. * * @category Mage - * @package Mage_Api + * @package Mage_Backend * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ + /** - * Web service api server interface + * System config Logo image field backend model * * @category Mage - * @package Mage_Api + * @package Mage_Backend * @author Magento Core Team <core@magentocommerce.com> */ -interface Mage_Api_Model_Server_Adapter_Interface +class Mage_Backend_Model_Config_Backend_Image_Logo extends Mage_Backend_Model_Config_Backend_Image { /** - * Set handler class name for webservice + * The tail part of directory path for uploading * - * @param string $handler - * @return Mage_Api_Model_Server_Adapter_Interface */ - function setHandler($handler); + const UPLOAD_DIR = 'logo'; /** - * Retrive handler class name for webservice + * Token for the root part of directory path for uploading * - * @return string */ - function getHandler(); + const UPLOAD_ROOT = 'media'; /** - * Set webservice api controller + * Return path to directory for upload file * - * @param Mage_Api_Controller_Action $controller - * @return Mage_Api_Model_Server_Adapter_Interface - */ - function setController(Mage_Api_Controller_Action $controller); - - /** - * Retrive webservice api controller - * - * @return Mage_Api_Controller_Action + * @return string + * @throw Mage_Core_Exception */ - function getController(); + protected function _getUploadDir() + { + $uploadDir = $this->_appendScopeInfo(self::UPLOAD_DIR); + $uploadRoot = $this->_getUploadRoot(self::UPLOAD_ROOT); + $uploadDir = $uploadRoot . DIRECTORY_SEPARATOR . $uploadDir; + return $uploadDir; + } /** - * Run webservice + * Makes a decision about whether to add info about the scope. * - * @return Mage_Api_Model_Server_Adapter_Interface + * @return boolean */ - function run(); + protected function _addWhetherScopeInfo() + { + return true; + } /** - * Dispatch webservice fault + * Get real media dir path * - * @param int $code - * @param string $message + * @param $token + * @return string */ - function fault($code, $message); - -} // Class Mage_Api_Model_Server_Adapter_Interface End + protected function _getUploadRoot($token) + { + return Mage::getBaseDir($token); + } +} diff --git a/app/code/core/Mage/Backend/Model/Config/Backend/Locale.php b/app/code/core/Mage/Backend/Model/Config/Backend/Locale.php index 9c6c4ed76a1303fe52e0d3493e66911d421887c5..4f4fa3df7f1828bcb032feb923cb6ab76db55080 100644 --- a/app/code/core/Mage/Backend/Model/Config/Backend/Locale.php +++ b/app/code/core/Mage/Backend/Model/Config/Backend/Locale.php @@ -58,8 +58,7 @@ class Mage_Backend_Model_Config_Backend_Locale extends Mage_Core_Model_Config_Da $currencyName = Mage::app()->getLocale()->currency($data->getValue())->getName(); if ($match[1] == 'base') { $fieldName = Mage::helper('Mage_Backend_Helper_Data')->__('Base currency'); - } - else { + } else { $fieldName = Mage::helper('Mage_Backend_Helper_Data')->__('Display default currency'); } @@ -69,8 +68,10 @@ class Mage_Backend_Model_Config_Backend_Locale extends Mage_Core_Model_Config_Da break; case 'website': - $websiteName = Mage::getModel('Mage_Core_Model_Website')->load($data->getScopeId())->getName(); - $scopeName = Mage::helper('Mage_Backend_Helper_Data')->__('website(%s) scope', $websiteName); + $websiteName = Mage::getModel('Mage_Core_Model_Website') + ->load($data->getScopeId())->getName(); + $scopeName = Mage::helper('Mage_Backend_Helper_Data') + ->__('website(%s) scope', $websiteName); break; case 'store': @@ -79,7 +80,8 @@ class Mage_Backend_Model_Config_Backend_Locale extends Mage_Core_Model_Config_Da break; } - $exceptions[] = Mage::helper('Mage_Backend_Helper_Data')->__('Currency "%s" is used as %s in %s.', $currencyName, $fieldName, $scopeName); + $exceptions[] = Mage::helper('Mage_Backend_Helper_Data') + ->__('Currency "%s" is used as %s in %s.', $currencyName, $fieldName, $scopeName); } } } diff --git a/app/code/core/Mage/Backend/Model/Config/Backend/Log/Cron.php b/app/code/core/Mage/Backend/Model/Config/Backend/Log/Cron.php index 788899c32a2984d04ea9718ca4e459cd8d145dbf..c2ec86d2a97ebe65992fb62c0799cd7ce46265a4 100644 --- a/app/code/core/Mage/Backend/Model/Config/Backend/Log/Cron.php +++ b/app/code/core/Mage/Backend/Model/Config/Backend/Log/Cron.php @@ -47,14 +47,11 @@ class Mage_Backend_Model_Config_Backend_Log_Cron extends Mage_Core_Model_Config_ $enabled = $this->getData('groups/log/fields/enabled/value'); $time = $this->getData('groups/log/fields/time/value'); $frequncy = $this->getData('groups/log/fields/frequency/value'); - $errorEmail = $this->getData('groups/log/fields/error_email/value'); - $frequencyDaily = Mage_Cron_Model_Config_Source_Frequency::CRON_DAILY; $frequencyWeekly = Mage_Cron_Model_Config_Source_Frequency::CRON_WEEKLY; $frequencyMonthly = Mage_Cron_Model_Config_Source_Frequency::CRON_MONTHLY; if ($enabled) { - $cronDayOfWeek = date('N'); $cronExprArray = array( intval($time[1]), # Minute intval($time[0]), # Hour @@ -63,8 +60,7 @@ class Mage_Backend_Model_Config_Backend_Log_Cron extends Mage_Core_Model_Config_ ($frequncy == $frequencyWeekly) ? '1' : '*', # Day of the Week ); $cronExprString = join(' ', $cronExprArray); - } - else { + } else { $cronExprString = ''; } diff --git a/app/code/core/Mage/Backend/Model/Config/BackendFactory.php b/app/code/core/Mage/Backend/Model/Config/BackendFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..f0de30416c32548b56310b69bcead21e03017eca --- /dev/null +++ b/app/code/core/Mage/Backend/Model/Config/BackendFactory.php @@ -0,0 +1,59 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_Backend + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_Backend_Model_Config_BackendFactory +{ + /** + * Object manager + * + * @var Magento_ObjectManager + */ + protected $_objectManager; + + /** + * @param Magento_ObjectManager $objectmanager + */ + public function __construct(Magento_ObjectManager $objectmanager) + { + $this->_objectManager = $objectmanager; + } + + /** + * Create backend model by name + * + * @param string $modelName + * @return Mage_Core_Model_Config_Data + * @throws InvalidArgumentException + */ + public function create($modelName) + { + $model = $this->_objectManager->create($modelName); + if (!$model instanceof Mage_Core_Model_Config_Data) { + throw new InvalidArgumentException('Invalid config field backend model: ' . $modelName); + } + return $model; + } +} diff --git a/app/code/core/Mage/Backend/Model/Config/CommentFactory.php b/app/code/core/Mage/Backend/Model/Config/CommentFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..3f911d79655891bb406935d8e05d4352cff9343d --- /dev/null +++ b/app/code/core/Mage/Backend/Model/Config/CommentFactory.php @@ -0,0 +1,60 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_Backend + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * System configuration comment model factory + */ +class Mage_Backend_Model_Config_CommentFactory +{ + /** + * @var Magento_ObjectManager + */ + protected $_objectManager; + + /** + * @param Magento_ObjectManager $objectManager + */ + public function __construct(Magento_ObjectManager $objectManager) + { + $this->_objectManager = $objectManager; + } + + /** + * Create new config object + * + * @param string $type + * @return Mage_Backend_Model_Config_CommentInterface + * @throws InvalidArgumentException + */ + public function create($type) + { + $commentModel = $this->_objectManager->create($type); + if (!$commentModel instanceof Mage_Backend_Model_Config_CommentInterface) { + throw new InvalidArgumentException('Incorrect comment model provided'); + } + return $commentModel; + } +} diff --git a/app/code/core/Mage/Backend/Model/Config/CommentInterface.php b/app/code/core/Mage/Backend/Model/Config/CommentInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..6aedda9bb723b902ebb27fd368a61452bac53c6e --- /dev/null +++ b/app/code/core/Mage/Backend/Model/Config/CommentInterface.php @@ -0,0 +1,38 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_Backend + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * System configuration comment model interface + */ +interface Mage_Backend_Model_Config_CommentInterface +{ + /** + * Retrieve element comment by element value + * @param mixed $elementValue + * @return string + */ + public function getCommentText($elementValue); +} diff --git a/app/code/core/Mage/Backend/Model/Config/Loader.php b/app/code/core/Mage/Backend/Model/Config/Loader.php new file mode 100644 index 0000000000000000000000000000000000000000..f2dd75b042305abd00ad66978b6424401f95c27f --- /dev/null +++ b/app/code/core/Mage/Backend/Model/Config/Loader.php @@ -0,0 +1,78 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_Backend + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * System configuration loader + */ +class Mage_Backend_Model_Config_Loader +{ + /** + * Config data factory + * + * @var Mage_Core_Model_Config_Data_Factory + */ + protected $_configDataFactory; + + /** + * @param Mage_Core_Model_Config_Data_Factory $configDataFactory + */ + public function __construct(Mage_Core_Model_Config_Data_Factory $configDataFactory) + { + $this->_configDataFactory = $configDataFactory; + } + + /** + * Get configuration value by path + * + * @param string $path + * @param string $scope + * @param string $scopeId + * @param bool $full + * @return array + */ + public function getConfigByPath($path, $scope, $scopeId, $full = true) + { + $configDataCollection = $this->_configDataFactory->create(); + $configDataCollection = $configDataCollection + ->getCollection() + ->addScopeFilter($scope, $scopeId, $path); + + $config = array(); + $configDataCollection->load(); + foreach ($configDataCollection->getItems() as $data) { + if ($full) { + $config[$data->getPath()] = array( + 'path' => $data->getPath(), + 'value' => $data->getValue(), + 'config_id' => $data->getConfigId() + ); + } else { + $config[$data->getPath()] = $data->getValue(); + } + } + return $config; + } +} diff --git a/app/code/core/Mage/Adminhtml/Block/Api/User.php b/app/code/core/Mage/Backend/Model/Config/ScopeDefiner.php similarity index 57% rename from app/code/core/Mage/Adminhtml/Block/Api/User.php rename to app/code/core/Mage/Backend/Model/Config/ScopeDefiner.php index 26dbd977911ede2b94f38e75f12e5a08aca760d8..807ec52e2a743ab2b3cca7370618762891cb57b9 100644 --- a/app/code/core/Mage/Adminhtml/Block/Api/User.php +++ b/app/code/core/Mage/Backend/Model/Config/ScopeDefiner.php @@ -19,37 +19,44 @@ * needs please refer to http://www.magentocommerce.com for more information. * * @category Mage - * @package Mage_Adminhtml + * @package Mage_Backend * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ /** - * Adminhtml permissions user block - * - * @category Mage - * @package Mage_Adminhtml - * @author Magento Core Team <core@magentocommerce.com> + * System configuration scope */ -class Mage_Adminhtml_Block_Api_User extends Mage_Adminhtml_Block_Widget_Grid_Container +class Mage_Backend_Model_Config_ScopeDefiner { + const SCOPE_WEBSITE = 'website'; + const SCOPE_STORE = 'store'; + const SCOPE_DEFAULT = 'default'; - protected function _construct() + /** + * Request object + * + * @var Mage_Core_Controller_Request_Http + */ + protected $_request; + + /** + * @param Mage_Core_Controller_Request_Http $request + */ + public function __construct(Mage_Core_Controller_Request_Http $request) { - $this->_controller = 'api_user'; - $this->_headerText = Mage::helper('Mage_Adminhtml_Helper_Data')->__('Users'); - $this->_addButtonLabel = Mage::helper('Mage_Adminhtml_Helper_Data')->__('Add New User'); - parent::_construct(); + $this->_request = $request; } /** - * Prepare output HTML + * Retrieve current config scope * * @return string */ - protected function _toHtml() + public function getScope() { - Mage::dispatchEvent('api_user_html_before', array('block' => $this)); - return parent::_toHtml(); + return $this->_request->getParam('store') + ? self::SCOPE_STORE + : ($this->_request->getParam('website') ? self::SCOPE_WEBSITE : self::SCOPE_DEFAULT); } } diff --git a/app/code/core/Mage/Backend/Model/Config/Source/Admin/Page.php b/app/code/core/Mage/Backend/Model/Config/Source/Admin/Page.php index 9211f62b4855d6060bbc9615a527b36602d9e8f1..ec105cfde42c55dbb9ca8188646ff3698bd39be9 100644 --- a/app/code/core/Mage/Backend/Model/Config/Source/Admin/Page.php +++ b/app/code/core/Mage/Backend/Model/Config/Source/Admin/Page.php @@ -104,11 +104,10 @@ class Mage_Backend_Model_Config_Source_Admin_Page implements Mage_Core_Model_Opt if ($menuItem->hasChildren()) { $this->_createOptions($optionArray, $menuItem->getChildren(), $level + 1); } - } - else { + } else { $children = array(); - if($menuItem->hasChildren()) { + if ($menuItem->hasChildren()) { $this->_createOptions($children, $menuItem->getChildren(), $level + 1); } diff --git a/app/code/core/Mage/Backend/Model/Config/Source/Currency/Service.php b/app/code/core/Mage/Backend/Model/Config/Source/Currency/Service.php index ad491d2f404d4b030d020286dde452e9ae99e14b..b59a289a964ba0b71fb54bdcfa24ffefea822f0e 100644 --- a/app/code/core/Mage/Backend/Model/Config/Source/Currency/Service.php +++ b/app/code/core/Mage/Backend/Model/Config/Source/Currency/Service.php @@ -34,7 +34,7 @@ class Mage_Backend_Model_Config_Source_Currency_Service implements Mage_Core_Mod if (!$this->_options) { $services = Mage::getConfig()->getNode('global/currency/import/services')->asArray(); $this->_options = array(); - foreach( $services as $_code => $_options ) { + foreach ($services as $_code => $_options ) { $this->_options[] = array( 'label' => $_options['name'], 'value' => $_code, diff --git a/app/code/core/Mage/Backend/Model/Config/Source/Dev/Dbautoup.php b/app/code/core/Mage/Backend/Model/Config/Source/Dev/Dbautoup.php index 48b4655b1224e48326f8aef1aea237d26f4a4dda..78ff14344b4a4350d1533ff1a11cd36a8d9b8cc1 100644 --- a/app/code/core/Mage/Backend/Model/Config/Source/Dev/Dbautoup.php +++ b/app/code/core/Mage/Backend/Model/Config/Source/Dev/Dbautoup.php @@ -28,9 +28,18 @@ class Mage_Backend_Model_Config_Source_Dev_Dbautoup implements Mage_Core_Model_O public function toOptionArray() { return array( - array('value'=>Mage_Core_Model_Resource::AUTO_UPDATE_ALWAYS, 'label' => Mage::helper('Mage_Backend_Helper_Data')->__('Always (during development)')), - array('value'=>Mage_Core_Model_Resource::AUTO_UPDATE_ONCE, 'label' => Mage::helper('Mage_Backend_Helper_Data')->__('Only Once (version upgrade)')), - array('value'=>Mage_Core_Model_Resource::AUTO_UPDATE_NEVER, 'label' => Mage::helper('Mage_Backend_Helper_Data')->__('Never (production)')), + array( + 'value'=>Mage_Core_Model_Resource::AUTO_UPDATE_ALWAYS, + 'label' => Mage::helper('Mage_Backend_Helper_Data')->__('Always (during development)') + ), + array( + 'value'=>Mage_Core_Model_Resource::AUTO_UPDATE_ONCE, + 'label' => Mage::helper('Mage_Backend_Helper_Data')->__('Only Once (version upgrade)') + ), + array( + 'value'=>Mage_Core_Model_Resource::AUTO_UPDATE_NEVER, + 'label' => Mage::helper('Mage_Backend_Helper_Data')->__('Never (production)') + ), ); } diff --git a/app/code/core/Mage/Backend/Model/Config/Source/Email/Identity.php b/app/code/core/Mage/Backend/Model/Config/Source/Email/Identity.php index fee0b40776b216d536400c35813b53fb7f008bd4..affdd6cef2b209d56e210cbdc747a808664ba8d3 100644 --- a/app/code/core/Mage/Backend/Model/Config/Source/Email/Identity.php +++ b/app/code/core/Mage/Backend/Model/Config/Source/Email/Identity.php @@ -27,23 +27,45 @@ class Mage_Backend_Model_Config_Source_Email_Identity implements Mage_Core_Model_Option_ArrayInterface { + /** + * Email Identity options + * + * @var array + */ protected $_options = null; + + /** + * Configuration structure + * + * @var Mage_Backend_Model_Config_Structure + */ + protected $_configStructure; + + /** + * @param Mage_Backend_Model_Config_Structure $configStructure + */ + public function __construct(Mage_Backend_Model_Config_Structure $configStructure) + { + $this->_configStructure = $configStructure; + } + + /** + * Retrieve list of options + * + * @return array + */ public function toOptionArray() { if (is_null($this->_options)) { $this->_options = array(); - $config = Mage::getSingleton('Mage_Backend_Model_Config_Structure_Reader') - ->getConfiguration() - ->getSection('trans_email'); + /** @var $section Mage_Backend_Model_Config_Structure_Element_Section */ + $section = $this->_configStructure->getElement('trans_email'); - $groups = $config['groups']; - foreach ($groups as $field) { - $nodeName = $field['id']; - $label = (string) isset($field['label']) ? $field['label'] : ''; - $sortOrder = (int) isset($field['sortOrder']) ? $field['sortOrder'] : null; - $this->_options[$sortOrder] = array( - 'value' => preg_replace('#^ident_(.*)$#', '$1', $nodeName), - 'label' => Mage::helper('Mage_Backend_Helper_Data')->__($label) + /** @var $group Mage_Backend_Model_Config_Structure_Element_Group */ + foreach ($section->getChildren() as $group) { + $this->_options[] = array( + 'value' => preg_replace('#^ident_(.*)$#', '$1', $group->getId()), + 'label' => $group->getLabel() ); } ksort($this->_options); diff --git a/app/code/core/Mage/Backend/Model/Config/Source/Email/Template.php b/app/code/core/Mage/Backend/Model/Config/Source/Email/Template.php index daba2c6bbc83290903548cb2dccc2dc120538e84..ef2968c80aa7dc959fe0de8e40468776c28b3d2e 100644 --- a/app/code/core/Mage/Backend/Model/Config/Source/Email/Template.php +++ b/app/code/core/Mage/Backend/Model/Config/Source/Email/Template.php @@ -42,7 +42,7 @@ class Mage_Backend_Model_Config_Source_Email_Template extends Varien_Object */ public function toOptionArray() { - if(!$collection = Mage::registry('config_system_email_template')) { + if (!$collection = Mage::registry('config_system_email_template')) { $collection = Mage::getResourceModel('Mage_Core_Model_Resource_Email_Template_Collection') ->load(); diff --git a/app/code/core/Mage/Backend/Model/Config/Source/Locale/Currency/All.php b/app/code/core/Mage/Backend/Model/Config/Source/Locale/Currency/All.php index 12d6f561f348a4ddf1481a108ef439319d312438..b5115a19ba183c46138fbf69a9676d3dae938b1c 100644 --- a/app/code/core/Mage/Backend/Model/Config/Source/Locale/Currency/All.php +++ b/app/code/core/Mage/Backend/Model/Config/Source/Locale/Currency/All.php @@ -34,7 +34,7 @@ class Mage_Backend_Model_Config_Source_Locale_Currency_All $this->_options = Mage::app()->getLocale()->getOptionAllCurrencies(); } $options = $this->_options; - if(!$isMultiselect){ + if (!$isMultiselect) { array_unshift($options, array('value'=>'', 'label'=>'')); } diff --git a/app/code/core/Mage/Backend/Model/Config/Source/Storage/Media/Database.php b/app/code/core/Mage/Backend/Model/Config/Source/Storage/Media/Database.php index b874b7d728793d39ab6695cc002eb9a16c7ad675..0e9e59700c8fe5d90a5cdf0310e0364a75a2a8e6 100644 --- a/app/code/core/Mage/Backend/Model/Config/Source/Storage/Media/Database.php +++ b/app/code/core/Mage/Backend/Model/Config/Source/Storage/Media/Database.php @@ -67,7 +67,7 @@ class Mage_Backend_Model_Config_Source_Storage_Media_Database implements Mage_Co */ public function toOptionArray() { - $media_storages = array(); + $mediaStorages = array(); $this->_connections = (array) Mage::app()->getConfig()->getNode('global/resources')->children(); foreach (array_keys($this->_connections) as $connectionName) { @@ -76,12 +76,12 @@ class Mage_Backend_Model_Config_Source_Storage_Media_Database implements Mage_Co continue; } - $media_storages[] = array('value' => $connectionName, 'label' => $connectionName); + $mediaStorages[] = array('value' => $connectionName, 'label' => $connectionName); } - sort($media_storages); - reset($media_storages); + sort($mediaStorages); + reset($mediaStorages); - return $media_storages; + return $mediaStorages; } } diff --git a/app/code/core/Mage/Backend/Model/Config/SourceFactory.php b/app/code/core/Mage/Backend/Model/Config/SourceFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..65bb23b4634795c33b048a51c46c409bea600552 --- /dev/null +++ b/app/code/core/Mage/Backend/Model/Config/SourceFactory.php @@ -0,0 +1,55 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_Backend + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_Backend_Model_Config_SourceFactory +{ + /** + * Object manager + * + * @var Magento_ObjectManager + */ + protected $_objectManager; + + /** + * @param Magento_ObjectManager $objectManager + */ + public function __construct(Magento_ObjectManager $objectManager) + { + $this->_objectManager = $objectManager; + } + + /** + * Create backend model by name + * + * @param string $modelName + * @return mixed + */ + public function create($modelName) + { + $model = $this->_objectManager->get($modelName); + return $model; + } +} diff --git a/app/code/core/Mage/Backend/Model/Config/Structure.php b/app/code/core/Mage/Backend/Model/Config/Structure.php index 75ebc70e1cf590f111da26934323ed1fade848ab..773d0d33916b3467945b29ea4aa414381e4ff08a 100644 --- a/app/code/core/Mage/Backend/Model/Config/Structure.php +++ b/app/code/core/Mage/Backend/Model/Config/Structure.php @@ -25,319 +25,205 @@ */ /** - * System configuration structure reader + * System configuration structure */ -class Mage_Backend_Model_Config_Structure extends Magento_Config_XmlAbstract - implements Mage_Backend_Model_Config_StructureInterface +class Mage_Backend_Model_Config_Structure implements Mage_Backend_Model_Config_Structure_SearchInterface { /** - * Main Application object - * - * @var Mage_Core_Model_App - */ - protected $_app; - - /** - * Config structure toArray converter - * - * @var Mage_Backend_Model_Config_Structure_Converter + * Key that contains field type in structure array */ - protected $_converter; + const TYPE_KEY = '_elementType'; /** - * List of encrypted paths + * Configuration structure represented as tree * * @var array */ - protected $_encryptedPaths = array(); - - /** - * @var Mage_Core_Model_Factory_Helper - */ - protected $_helperFactory; - - /** - * @param array $data - */ - public function __construct(array $data = array()) - { - $this->_app = isset($data['app']) ? $data['app'] : Mage::app(); - $this->_converter = isset($data['converter']) - ? $data['converter'] - : Mage::getSingleton('Mage_Backend_Model_Config_Structure_Converter'); - $this->_helperFactory = isset($data['helperFactory']) - ? $data['helperFactory'] - : Mage::getSingleton('Mage_Core_Model_Factory_Helper'); - parent::__construct($data['sourceFiles']); - } - - public function __wakeUp() - { - $this->_app = Mage::app(); - $this->_helperFactory = Mage::getObjectManager()->get('Mage_Core_Model_Factory_Helper'); - } + protected $_data; /** - * Get absolute path to the XML-schema file + * Config tab iterator * - * @return string + * @var Mage_Backend_Model_Config_Structure_Element_Iterator_Tab */ - public function getSchemaFile() - { - return __DIR__ . '/Structure/system.xsd'; - } + protected $_tabIterator; /** - * Get absolute path to the XML-schema file + * Pool of config element flyweight objects * - * @return string + * @var Mage_Backend_Model_Config_Structure_Element_FlyweightFactory */ - public function getPerFileSchemaFile() - { - return __DIR__ . '/Structure/system_file.xsd'; - } + protected $_flyweightFactory; /** - * Extract configuration data from the DOM structure + * Provider of current config scope * - * @param DOMDocument $dom - * @return array|DOMNodeList + * @var Mage_Backend_Model_Config_ScopeDefiner */ - protected function _extractData(DOMDocument $dom) - { - $data = $this->_converter->convert($dom); - return $data['config']['system']; - } + protected $_scopeDefiner; /** - * Get XML-contents, initial for merging + * List of cached elements * - * @return string + * @var Mage_Backend_Model_Config_Structure_ElementInterface[] */ - protected function _getInitialXml() - { - return '<?xml version="1.0" encoding="utf-8"?><config><system></system></config>'; - } + protected $_elements; /** - * Get list of paths to identifiable nodes - * - * @return array + * @param Mage_Backend_Model_Config_Structure_Reader $structureReader + * @param Mage_Backend_Model_Config_Structure_Element_Iterator_Tab $tabIterator + * @param Mage_Backend_Model_Config_Structure_Element_FlyweightFactory $flyweightFactory + * @param Mage_Backend_Model_Config_ScopeDefiner $scopeDefiner */ - protected function _getIdAttributes() - { - return array( - '/config/system/tab' => 'id', - '/config/system/section' => 'id', - '/config/system/section/group' => 'id', - '/config/system/section/group/field' => 'id', - ); + public function __construct( + Mage_Backend_Model_Config_Structure_Reader $structureReader, + Mage_Backend_Model_Config_Structure_Element_Iterator_Tab $tabIterator, + Mage_Backend_Model_Config_Structure_Element_FlyweightFactory $flyweightFactory, + Mage_Backend_Model_Config_ScopeDefiner $scopeDefiner + ) { + $this->_data = $structureReader->getData(); + $this->_tabIterator = $tabIterator; + $this->_flyweightFactory = $flyweightFactory; + $this->_scopeDefiner = $scopeDefiner; } /** - * Retrieve all sections system configuration layout + * Retrieve tab iterator * - * @return array + * @return Mage_Backend_Model_Config_Structure_Element_Iterator */ - public function getSections() + public function getTabs() { - return $this->_data['sections']; + foreach ($this->_data['sections'] as $sectionId => $section) { + if (isset($section['tab']) && $section['tab']) { + $this->_data['tabs'][$section['tab']]['children'][$sectionId] = $section; + } + } + $this->_tabIterator->setElements($this->_data['tabs'], $this->_scopeDefiner->getScope()); + return $this->_tabIterator; } /** - * Retrieve list of tabs from + * Find element by path * - * @return array + * @param string $path + * @return Mage_Backend_Model_Config_Structure_ElementInterface|null */ - public function getTabs() + public function getElement($path) { - return $this->_data['tabs']; + return $this->getElementByPathParts(explode('/', $path)); } /** - * Retrieve defined section + * Retrieve first available section in config structure * - * @param string $sectionCode - * @param string $websiteCode - * @param string $storeCode - * @return array + * @return Mage_Backend_Model_Config_Structure_ElementInterface */ - public function getSection($sectionCode=null, $websiteCode=null, $storeCode=null) + public function getFirstSection() { - $key = $sectionCode ?: $websiteCode ?: $storeCode; - return isset($this->_data['sections'][$key]) ? $this->_data['sections'][$key] : null; + $tabs = $this->getTabs(); + $tabs->rewind(); + /** @var $tab Mage_Backend_Model_Config_Structure_Element_Tab */ + $tab = $tabs->current(); + $tab->getChildren()->rewind(); + return $tab->getChildren()->current(); } /** - * Check whether node has child node that can be shown + * Find element by path parts * - * @param Varien_Simplexml_Element $node - * @param string $websiteCode - * @param string $storeCode - * @return boolean + * @param array $pathParts + * @return Mage_Backend_Model_Config_Structure_ElementInterface|null */ - public function hasChildren($node, $websiteCode = null, $storeCode = null) + public function getElementByPathParts(array $pathParts) { - if (!$this->_canShowNode($node, $websiteCode, $storeCode)) { - return false; - } - - if (isset($node['groups'])) { - $children = $node['groups']; - } elseif (isset($node['fields'])) { - $children = $node['fields']; - } else { - return true; + $path = implode('_', $pathParts); + if (isset($this->_elements[$path])) { + return $this->_elements[$path]; } - - foreach ($children as $child) { - if ($this->hasChildren($child, $websiteCode, $storeCode)) { - return true; + $children = $this->_data['sections']; + $child = array(); + foreach ($pathParts as $pathPart) { + if (array_key_exists($pathPart, $children)) { + $child = $children[$pathPart]; + $children = array_key_exists('children', $child) ? $child['children'] : array(); + } else { + $child = $this->_createEmptyElement($pathParts); + break; } } - return false; - } - - /** - * Checks whether it is possible to show the node - * - * @param mixed $node - * @param string $websiteCode - * @param string $storeCode - * @return boolean - */ - protected function _canShowNode($node, $websiteCode = null, $storeCode = null) - { - $showTab = false; - if ($storeCode) { - $showTab = isset($node['showInStore']) ? (int)$node['showInStore'] : false; - } elseif ($websiteCode) { - $showTab = isset($node['showInWebsite']) ? (int)$node['showInWebsite'] : false; - } elseif (isset($node['showInDefault']) && $node['showInDefault']) { - $showTab = true; - } - - $showTab = $showTab || $this->_app->isSingleStoreMode(); - $showTab = $showTab && !($this->_app->isSingleStoreMode() - && isset($node['hide_in_single_store_mode']) && $node['hide_in_single_store_mode']); - return $showTab; + $this->_elements[$path] = $this->_flyweightFactory->create($child['_elementType']); + $this->_elements[$path]->setData($child, $this->_scopeDefiner->getScope()); + return $this->_elements[$path]; } /** - * Get translate module name + * Create empty element data * - * @param array $sectionNode - * @param array $groupNode - * @param array $fieldNode - * @return string + * @param array $pathParts + * @return array */ - public function getAttributeModule($sectionNode = null, $groupNode = null, $fieldNode = null) - { - $moduleName = 'Mage_Backend'; - if (isset($sectionNode['module'])) { - $moduleName = (string) $sectionNode['module']; - } - if (isset($groupNode['module'])) { - $moduleName = (string) $groupNode['module']; + protected function _createEmptyElement(array $pathParts) + { + switch (count($pathParts)) { + case 1: + $elementType = 'section'; + break; + case 2: + $elementType = 'group'; + break; + default: + $elementType = 'field'; } - if (isset($fieldNode['module'])) { - $moduleName = (string) $fieldNode['module']; - } - return $moduleName; + $elementId = array_pop($pathParts); + return array('id' => $elementId, 'path' => implode('/', $pathParts), '_elementType' => $elementType); } /** - * System configuration section, fieldset or field label getter + * Retrieve paths of fields that have provided attributes with provided values * - * @param string $sectionName - * @param string $groupName - * @param string $fieldName - * @throws InvalidArgumentException - * @return string + * @param string $attributeName + * @param mixed $attributeValue + * @return array */ - public function getSystemConfigNodeLabel($sectionName, $groupName = null, $fieldName = null) + public function getFieldPathsByAttribute($attributeName, $attributeValue) { - $sectionName = trim($sectionName, '/'); - $groupNode = $fieldNode = null; - $sectionNode = isset($this->_data['sections'][$sectionName]) ? $this->_data['sections'][$sectionName] : null; - if (!$sectionNode) { - throw new InvalidArgumentException( - $this->_helperFactory->get('Mage_Backend_Helper_Data')->__('Wrong section specified.') - ); - } - $currentNode = $sectionNode; - if (!empty($groupName)) { - $groupName = trim($groupName, '/'); - $groupNode = isset($sectionNode['groups'][$groupName]) ? $sectionNode['groups'][$groupName] : null; - if (!$groupNode) { - throw new InvalidArgumentException( - $this->_helperFactory->get('Mage_Backend_Helper_Data')->__('Wrong group specified.') - ); + $result = array(); + foreach ($this->_data['sections'] as $section) { + if (!isset($section['children'])) { + continue; } - $currentNode = $groupNode; - } - if (!empty($fieldName)) { - if (!empty($groupNode)) { - $fieldName = trim($fieldName, '/'); - $fieldNode = isset($groupNode['fields'][$fieldName]) ? $groupNode['fields'][$fieldName] : null; - if (!$fieldNode) { - throw new InvalidArgumentException( - $this->_helperFactory->get('Mage_Backend_Helper_Data')->__('Wrong field specified.') - ); + foreach ($section['children'] as $group) { + if (isset($group['children'])) { + $path = $section['id'] . '/' . $group['id']; + $result = array_merge($result, $this->_getGroupFieldPathsByAttribute( + $group['children'], $path, $attributeName, $attributeValue + )); } - $currentNode = $fieldNode; - } else { - Mage::throwException( - $this->_helperFactory->get('Mage_Backend_Helper_Data')->__('The group node name must be specified with field node name.') - ); } } - $moduleName = $this->getAttributeModule($sectionNode, $groupNode, $fieldNode); - return isset($currentNode['label']) - ? $this->_helperFactory->get($moduleName)->__((string)$currentNode['label']) - : ''; + return $result; } /** - * Look for encrypted node entries in all system.xml files and return them + * Find group fields with specified attribute and attribute value * - * @param bool $explodePathToEntities + * @param array $fields + * @param string $parentPath + * @param string $attributeName + * @param mixed $attributeValue * @return array */ - public function getEncryptedNodeEntriesPaths($explodePathToEntities = false) - { - if (!$this->_encryptedPaths) { - $this->_encryptedPaths = $this->getFieldsByAttribute( - 'backend_model', 'Mage_Backend_Model_Config_Backend_Encrypted', $explodePathToEntities - ); - } - return $this->_encryptedPaths; - } - - public function getFieldsByAttribute($attributeName, $attributeValue, $explodePathToEntities = false) + protected function _getGroupFieldPathsByAttribute(array $fields, $parentPath, $attributeName, $attributeValue) { $result = array(); - foreach ($this->_data['sections'] as $section) { - if (!isset($section['groups'])) { - continue; - } - foreach ($section['groups'] as $group) { - if (!isset($group['fields'])) { - continue; - } - foreach ($group['fields'] as $field) { - if (isset($field[$attributeName]) - && $field[$attributeName] == $attributeValue - ) { - if ($explodePathToEntities) { - $result[] = array( - 'section' => $section['id'], 'group' => $group['id'], 'field' => $field['id'] - ); - } else { - $result[] = $section['id'] . '/' . $group['id'] . '/' . $field['id']; - } - } - } + foreach ($fields as $field) { + if (isset($field['children'])) { + $result += $this->_getGroupFieldPathsByAttribute( + $field['children'], $parentPath . '/' . $field['id'], $attributeName, $attributeValue + ); + } else if (isset($field[$attributeName]) && $field[$attributeName] == $attributeValue) { + $result[] = $parentPath . '/' . $field['id']; } } return $result; diff --git a/app/code/core/Mage/Backend/Model/Config/Structure/Converter.php b/app/code/core/Mage/Backend/Model/Config/Structure/Converter.php index bc61ad1665113855418d344b7df2577a7e25605b..e6ee17388953241de444f85cbf75591d7e022f39 100644 --- a/app/code/core/Mage/Backend/Model/Config/Structure/Converter.php +++ b/app/code/core/Mage/Backend/Model/Config/Structure/Converter.php @@ -26,6 +26,24 @@ class Mage_Backend_Model_Config_Structure_Converter { + /** + * @var Mage_Backend_Model_Config_Structure_Mapper_Factory + */ + protected $_mapperFactory; + + /** + * Mapper type list + * + * @var array + */ + protected $_mapperList = array( + Mage_Backend_Model_Config_Structure_Mapper_Factory::MAPPER_PATH, + Mage_Backend_Model_Config_Structure_Mapper_Factory::MAPPER_DEPENDENCIES, + Mage_Backend_Model_Config_Structure_Mapper_Factory::MAPPER_ATTRIBUTE_INHERITANCE, + Mage_Backend_Model_Config_Structure_Mapper_Factory::MAPPER_IGNORE, + Mage_Backend_Model_Config_Structure_Mapper_Factory::MAPPER_SORTING, + ); + /** * Map of single=>plural sub-node names per node * @@ -33,13 +51,21 @@ class Mage_Backend_Model_Config_Structure_Converter * * @var array */ - protected $nameMap = array( - 'system' => array('tab' => 'tabs', 'section' => 'sections'), - 'section' => array('group' => 'groups'), - 'group' => array('field' => 'fields'), + protected $_nameMap = array( + 'system' => array('tab' => 'tabs', 'section'=> 'sections'), + 'section' => array('group' => 'children'), + 'group' => array('field' => 'children', 'group' => 'children'), 'depends' => array('field' => 'fields'), ); + /** + * @param Mage_Backend_Model_Config_Structure_Mapper_Factory $mapperFactory + */ + public function __construct(Mage_Backend_Model_Config_Structure_Mapper_Factory $mapperFactory) + { + $this->_mapperFactory = $mapperFactory; + } + /** * Retrieve DOMDocument as array * @@ -47,6 +73,25 @@ class Mage_Backend_Model_Config_Structure_Converter * @return mixed */ public function convert(DOMNode $root) + { + $result = $this->_convertDOMDocument($root); + + foreach ($this->_mapperList as $type) { + /** @var $mapper Mage_Backend_Model_Config_Structure_MapperInterface */ + $mapper = $this->_mapperFactory->create($type); + $result = $mapper->map($result); + } + + return $result; + } + + /** + * Retrieve DOMDocument as array + * + * @param DOMNode $root + * @return mixed + */ + protected function _convertDOMDocument(DOMNode $root) { $result = $this->_processAttributes($root); @@ -81,22 +126,19 @@ class Mage_Backend_Model_Config_Structure_Converter if ($childName == 'attribute') { $childName = $child->getAttribute('type'); } - $convertedChild = $this->convert($child); + $convertedChild = $this->_convertDOMDocument($child); break; } - if (array_key_exists($root->nodeName, $this->nameMap) - && array_key_exists($child->nodeName, $this->nameMap[$root->nodeName])) { - $childName = $this->nameMap[$root->nodeName][$child->nodeName]; + if (array_key_exists($root->nodeName, $this->_nameMap) + && array_key_exists($child->nodeName, $this->_nameMap[$root->nodeName])) { + $childName = $this->_nameMap[$root->nodeName][$child->nodeName]; $processedSubLists[] = $childName; + $convertedChild['_elementType'] = $child->nodeName; } if (in_array($childName, $processedSubLists)) { - if (is_array($convertedChild) && array_key_exists('id', $convertedChild)) { - $result[$childName][$convertedChild['id']] = $convertedChild; - } else { - $result[$childName][] = $convertedChild; - } + $result = $this->_addProcessedNode($convertedChild, $result, $childName); } else if (array_key_exists($childName, $result)) { $result[$childName] = array($result[$childName], $convertedChild); $processedSubLists[] = $childName; @@ -108,10 +150,32 @@ class Mage_Backend_Model_Config_Structure_Converter if (count($result) == 1 && array_key_exists('value', $result)) { $result = $result['value']; } + if ($result == array()) { + $result = null; + } return $result; } + /** + * Add converted child with processed name + * + * @param array $convertedChild + * @param array $result + * @param string $childName + * + * @return mixed + */ + protected function _addProcessedNode($convertedChild, $result, $childName) + { + if (is_array($convertedChild) && array_key_exists('id', $convertedChild)) { + $result[$childName][$convertedChild['id']] = $convertedChild; + } else { + $result[$childName][] = $convertedChild; + } + return $result; + } + /** * Process element attributes * diff --git a/app/code/core/Mage/Backend/Model/Config/Structure/Element/CompositeAbstract.php b/app/code/core/Mage/Backend/Model/Config/Structure/Element/CompositeAbstract.php new file mode 100644 index 0000000000000000000000000000000000000000..33eafc62f5b7892dcac3f1235caade61d138615a --- /dev/null +++ b/app/code/core/Mage/Backend/Model/Config/Structure/Element/CompositeAbstract.php @@ -0,0 +1,102 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_Backend + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +abstract class Mage_Backend_Model_Config_Structure_Element_CompositeAbstract + extends Mage_Backend_Model_Config_Structure_ElementAbstract +{ + /** + * Child elements iterator + * + * @var Mage_Backend_Model_Config_Structure_Element_Iterator + */ + protected $_childrenIterator; + + /** + * @param Mage_Core_Model_Factory_Helper $helperFactory + * @param Mage_Core_Model_App $application + * @param Mage_Backend_Model_Config_Structure_Element_Iterator $childrenIterator + */ + public function __construct( + Mage_Core_Model_Factory_Helper $helperFactory, + Mage_Core_Model_App $application, + Mage_Backend_Model_Config_Structure_Element_Iterator $childrenIterator + ) { + parent::__construct($helperFactory, $application); + $this->_childrenIterator = $childrenIterator; + } + + /** + * Set flyweight data + * + * @param array $data + * @param string $scope + */ + public function setData(array $data, $scope) + { + parent::setData($data, $scope); + $children = array_key_exists('children', $this->_data) && is_array($this->_data['children']) ? + $this->_data['children'] : + array(); + $this->_childrenIterator->setElements($children, $scope); + } + + /** + * Check whether element has visible child elements + * + * @return bool + */ + public function hasChildren() + { + foreach ($this->getChildren() as $child) { + return (bool)$child; + }; + return false; + } + + /** + * Retrieve children iterator + * + * @return Mage_Backend_Model_Config_Structure_Element_Iterator + */ + public function getChildren() + { + return $this->_childrenIterator; + } + + /** + * Check whether element is visible + * + * @return bool + */ + public function isVisible() + { + if (parent::isVisible()) { + return $this->hasChildren() || $this->getFrontendModel(); + } + return false; + } +} + diff --git a/app/code/core/Mage/Backend/Model/Config/Structure/Element/Dependency/Mapper.php b/app/code/core/Mage/Backend/Model/Config/Structure/Element/Dependency/Mapper.php new file mode 100644 index 0000000000000000000000000000000000000000..061fed4563bb05d5d29c812ba1415e4b4b88efc6 --- /dev/null +++ b/app/code/core/Mage/Backend/Model/Config/Structure/Element/Dependency/Mapper.php @@ -0,0 +1,107 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_Backend + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_Backend_Model_Config_Structure_Element_Dependency_Mapper +{ + /** + * Field locator model + * + * @var Mage_Backend_Model_Config_Structure_SearchInterface + */ + protected $_fieldLocator; + + + /** + * Application object + * + * @var Mage_Core_Model_App + */ + protected $_application; + + /** + * @param Mage_Core_Model_App $application + * @param Mage_Backend_Model_Config_Structure_SearchInterface $fieldLocator + */ + public function __construct( + Mage_Core_Model_App $application, + Mage_Backend_Model_Config_Structure_SearchInterface $fieldLocator + ) { + + $this->_fieldLocator = $fieldLocator; + $this->_application = $application; + } + + /** + * Retrieve field dependencies + * + * @param array $dependencies + * @param string $storeCode + * @param string $fieldPrefix + * @return array + */ + public function getDependencies($dependencies, $storeCode, $fieldPrefix = '') + { + $output = array(); + + foreach ($dependencies as $depend) { + /* @var array $depend */ + $fieldId = $fieldPrefix . array_pop($depend['dependPath']); + $depend['dependPath'][] = $fieldId; + $dependentId = implode('_', $depend['dependPath']); + + $shouldAddDependency = true; + + $dependentValue = $depend['value']; + + if (isset($depend['separator'])) { + $dependentValue = explode($depend['separator'], $dependentValue); + } + + /** @var Mage_Backend_Model_Config_Structure_Element_Field $dependentField */ + $dependentField = $this->_fieldLocator->getElement($depend['id']); + + /* + * If dependent field can't be shown in current scope and real dependent config value + * is not equal to preferred one, then hide dependence fields by adding dependence + * based on not shown field (not rendered field) + */ + if (false == $dependentField->isVisible()) { + $valueInStore = $this->_application + ->getStore($storeCode) + ->getConfig($dependentField->getPath($fieldPrefix)); + if (is_array($dependentValue)) { + $shouldAddDependency = !in_array($valueInStore, $dependentValue); + } else { + $shouldAddDependency = $dependentValue != $valueInStore; + } + } + if ($shouldAddDependency) { + $output[$dependentId] = $dependentValue; + } + } + return $output; + } +} diff --git a/app/code/core/Mage/Backend/Model/Config/Structure/Element/Field.php b/app/code/core/Mage/Backend/Model/Config/Structure/Element/Field.php new file mode 100644 index 0000000000000000000000000000000000000000..817fec538cc2e2e9895493934c956caefddb231f --- /dev/null +++ b/app/code/core/Mage/Backend/Model/Config/Structure/Element/Field.php @@ -0,0 +1,377 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_Backend + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_Backend_Model_Config_Structure_Element_Field + extends Mage_Backend_Model_Config_Structure_ElementAbstract +{ + /** + * Backend model factory + * + * @var Mage_Backend_Model_Config_BackendFactory + */ + protected $_backendFactory; + + /** + * Source model factory + * + * @var Mage_Backend_Model_Config_SourceFactory + */ + protected $_sourceFactory; + + /** + * Comment model factory + * + * @var Mage_Backend_Model_Config_CommentFactory + */ + protected $_commentFactory; + + /** + * + * @var Mage_Backend_Model_Config_Structure_Element_Dependency_Mapper + */ + protected $_dependencyMapper; + + /** + * Block factory + * + * @var Mage_Core_Model_BlockFactory + */ + protected $_blockFactory; + + /** + * @param Mage_Core_Model_Factory_Helper $helperFactory + * @param Mage_Core_Model_App $application + * @param Mage_Backend_Model_Config_BackendFactory $backendFactory + * @param Mage_Backend_Model_Config_SourceFactory $sourceFactory + * @param Mage_Backend_Model_Config_CommentFactory $commentFactory + * @param Mage_Core_Model_BlockFactory $blockFactory + * @param Mage_Backend_Model_Config_Structure_Element_Dependency_Mapper $dependencyMapper + */ + public function __construct( + Mage_Core_Model_Factory_Helper $helperFactory, + Mage_Core_Model_App $application, + Mage_Backend_Model_Config_BackendFactory $backendFactory, + Mage_Backend_Model_Config_SourceFactory $sourceFactory, + Mage_Backend_Model_Config_CommentFactory $commentFactory, + Mage_Core_Model_BlockFactory $blockFactory, + Mage_Backend_Model_Config_Structure_Element_Dependency_Mapper $dependencyMapper + ) { + parent::__construct($helperFactory, $application); + $this->_backendFactory = $backendFactory; + $this->_sourceFactory = $sourceFactory; + $this->_commentFactory = $commentFactory; + $this->_blockFactory = $blockFactory; + $this->_dependencyMapper = $dependencyMapper; + } + + /** + * Retrieve field label + * + * @param string $labelPrefix + * @return string + */ + public function getLabel($labelPrefix = '') + { + $label = ''; + if ($labelPrefix) { + $label .= $this->_helperFactory->get($this->_getTranslationModule())->__($labelPrefix) . ' '; + } + $label .= parent::getLabel(); + return $label; + } + + /** + * Retrieve field hint + * + * @return string + */ + public function getHint() + { + return $this->_getTranslatedAttribute('hint'); + } + + /** + * Retrieve comment + * + * @param string $currentValue + * @return string + */ + public function getComment($currentValue = '') + { + $comment = ''; + if (isset($this->_data['comment'])) { + if (is_array($this->_data['comment'])) { + if (isset($this->_data['comment']['model'])) { + $model = $this->_commentFactory->create($this->_data['comment']['model']); + $comment = $model->getCommentText($currentValue); + } + } else { + $comment = parent::getComment(); + } + } + return $comment; + } + + /** + * Retrieve tooltip text + * + * @return string + */ + public function getTooltip() + { + if (isset($this->_data['tooltip'])) { + return $this->_getTranslatedAttribute('tooltip'); + } elseif (isset($this->_data['tooltip_block'])) { + return $this->_blockFactory->createBlock($this->_data['tooltip_block'])->toHtml(); + } + return ''; + } + + /** + * Retrieve field type + * + * @return string + */ + public function getType() + { + return isset($this->_data['type']) ? $this->_data['type'] : 'text'; + } + + /** + * Retrieve frontend css class + * + * @return string + */ + public function getFrontendClass() + { + return isset($this->_data['frontend_class']) ? $this->_data['frontend_class'] : ''; + } + + /** + * Check whether field has backend model + * + * @return bool + */ + public function hasBackendModel() + { + return array_key_exists('backend_model', $this->_data) && $this->_data['backend_model']; + } + + /** + * Retrieve backend model + * + * @return Mage_Core_Model_Config_Data + */ + public function getBackendModel() + { + return $this->_backendFactory->create($this->_data['backend_model']); + } + + /** + * Retrieve field section id + * + * @return string + */ + public function getSectionId() + { + $parts = explode('/', $this->getPath()); + return current($parts); + } + + /** + * Retrieve field group path + * + * @return string + */ + public function getGroupPath() + { + return dirname($this->getPath()); + } + + /** + * Retrieve config path + * + * @return null|string + */ + public function getConfigPath() + { + return isset($this->_data['config_path']) ? $this->_data['config_path'] : null; + } + + /** + * Check whether field should be shown in default scope + * + * @return bool + */ + public function showInDefault() + { + return isset($this->_data['showInDefault']) && (int)$this->_data['showInDefault']; + } + + /** + * Check whether field should be shown in website scope + * + * @return bool + */ + public function showInWebsite() + { + return isset($this->_data['showInWebsite']) && (int)$this->_data['showInWebsite']; + } + + /** + * Check whether field should be shown in store scope + * + * @return bool + */ + public function showInStore() + { + return isset($this->_data['showInStore']) && (int)$this->_data['showInStore']; + } + + /** + * Populate form element with field data + * + * @param Varien_Data_Form_Element_Abstract $formField + */ + public function populateInput($formField) + { + $originalData = array(); + foreach ($this->_data as $key => $value) { + if (!is_array($value)) { + $originalData[$key] = $value; + } + } + $formField->setOriginalData($originalData); + } + + /** + * Check whether field has validation class + * + * @return bool + */ + public function hasValidation() + { + return isset($this->_data['validate']); + } + + /** + * Retrieve field validation class + * + * @return string + */ + public function getValidation() + { + return $this->_data['validate']; + } + + /** + * Check whether field can be empty + * + * @return bool + */ + public function canBeEmpty() + { + return isset($this->_data['can_be_empty']); + } + + /** + * Check whether field has source model + * + * @return bool + */ + public function hasSourceModel() + { + return isset($this->_data['source_model']); + } + + /** + * Retrieve source model option list + * + * @return array + */ + public function getOptions() + { + $factoryName = $this->_data['source_model']; + $method = false; + if (preg_match('/^([^:]+?)::([^:]+?)$/', $factoryName, $matches)) { + array_shift($matches); + list($factoryName, $method) = array_values($matches); + } + + $sourceModel = $this->_sourceFactory->create($factoryName); + if ($sourceModel instanceof Varien_Object) { + $sourceModel->setPath($this->getPath()); + } + if ($method) { + if ($this->getType() == 'multiselect') { + $optionArray = $sourceModel->$method(); + } else { + $optionArray = array(); + foreach ($sourceModel->$method() as $key => $value) { + if (is_array($value)) { + $optionArray[] = $value; + } else { + $optionArray[] = array('label' => $value, 'value' => $key); + } + } + } + } else { + $optionArray = $sourceModel->toOptionArray($this->getType() == 'multiselect'); + } + return $optionArray; + } + + /** + * Retrieve field dependencies + * + * @param $fieldPrefix + * @param $storeCode + * @return array + */ + public function getDependencies($fieldPrefix, $storeCode) + { + $dependencies = array(); + if (false == isset($this->_data['depends']['fields'])) { + return $dependencies; + } + $dependencies = $this->_dependencyMapper->getDependencies( + $this->_data['depends']['fields'], + $storeCode, + $fieldPrefix + ); + return $dependencies; + } + + /** + * Check whether element should be displayed for advanced users + * + * @return bool + */ + public function isAdvanced() + { + return isset($this->_data['advanced']) && $this->_data['advanced']; + } +} diff --git a/app/code/core/Mage/Api/Model/Resource/Roles/Collection.php b/app/code/core/Mage/Backend/Model/Config/Structure/Element/FlyweightFactory.php old mode 100755 new mode 100644 similarity index 53% rename from app/code/core/Mage/Api/Model/Resource/Roles/Collection.php rename to app/code/core/Mage/Backend/Model/Config/Structure/Element/FlyweightFactory.php index 6674846d93341a2b75443d7c85e49e82de1146d7..cf70be7176ad83e93de9eca2317d7a9bd8d2662e --- a/app/code/core/Mage/Api/Model/Resource/Roles/Collection.php +++ b/app/code/core/Mage/Backend/Model/Config/Structure/Element/FlyweightFactory.php @@ -19,49 +19,45 @@ * needs please refer to http://www.magentocommerce.com for more information. * * @category Mage - * @package Mage_Api + * @package Mage_Backend * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ - -/** - * Api Roles Resource Collection - * - * @category Mage - * @package Mage_Api - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api_Model_Resource_Roles_Collection extends Mage_Core_Model_Resource_Db_Collection_Abstract +class Mage_Backend_Model_Config_Structure_Element_FlyweightFactory { /** - * Resource collection initialization - * + * @var Magento_ObjectManager */ - protected function _construct() - { - $this->_init('Mage_Api_Model_Role', 'Mage_Api_Model_Resource_Role'); - } + protected $_objectManager; /** - * Init collection select + * Map of flyweight types * - * @return Mage_Api_Model_Resource_Roles_Collection + * @var array + */ + protected $_flyweightMap = array( + 'section' => 'Mage_Backend_Model_Config_Structure_Element_Section', + 'group' => 'Mage_Backend_Model_Config_Structure_Element_Group', + 'field' => 'Mage_Backend_Model_Config_Structure_Element_Field' + ); + + /** + * @param Magento_ObjectManager $objectManager */ - protected function _initSelect() + public function __construct(Magento_ObjectManager $objectManager) { - parent::_initSelect(); - $this->getSelect()->where('main_table.role_type = ?', Mage_Api_Model_Acl::ROLE_TYPE_GROUP); - return $this; + $this->_objectManager = $objectManager; } /** - * Convert items array to array for select options + * Create element flyweight flyweight * - * @return array + * @param string $type + * @return Mage_Backend_Model_Config_Structure_ElementInterface */ - public function toOptionArray() + public function create($type) { - return $this->_toOptionArray('role_id', 'role_name'); + return $this->_objectManager->create($this->_flyweightMap[$type]); } } diff --git a/app/code/core/Mage/Backend/Model/Config/Structure/Element/Group.php b/app/code/core/Mage/Backend/Model/Config/Structure/Element/Group.php new file mode 100644 index 0000000000000000000000000000000000000000..f1f84229c8a74132ae59e724ccc56bc5e768455d --- /dev/null +++ b/app/code/core/Mage/Backend/Model/Config/Structure/Element/Group.php @@ -0,0 +1,137 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_Backend + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_Backend_Model_Config_Structure_Element_Group + extends Mage_Backend_Model_Config_Structure_Element_CompositeAbstract +{ + /** + * Group clone model factory + * + * @var Mage_Backend_Model_Config_Clone_Factory + */ + protected $_cloneModelFactory; + + /** + * + * @var Mage_Backend_Model_Config_Structure_Element_Dependency_Mapper + */ + protected $_dependencyMapper; + + /** + * @param Mage_Core_Model_Factory_Helper $helperFactory + * @param Mage_Core_Model_App $application + * @param Mage_Backend_Model_Config_Structure_Element_Iterator_Field $childrenIterator + * @param Mage_Backend_Model_Config_Clone_Factory $cloneModelFactory + * @param Mage_Backend_Model_Config_Structure_Element_Dependency_Mapper $dependencyMapper + */ + public function __construct( + Mage_Core_Model_Factory_Helper $helperFactory, + Mage_Core_Model_App $application, + Mage_Backend_Model_Config_Structure_Element_Iterator_Field $childrenIterator, + Mage_Backend_Model_Config_Clone_Factory $cloneModelFactory, + Mage_Backend_Model_Config_Structure_Element_Dependency_Mapper $dependencyMapper + ) { + parent::__construct($helperFactory, $application, $childrenIterator); + $this->_cloneModelFactory = $cloneModelFactory; + $this->_dependencyMapper = $dependencyMapper; + } + + /** + * Should group fields be cloned + * + * @return bool + */ + public function shouldCloneFields() + { + return (isset($this->_data['clone_fields']) && !empty($this->_data['clone_fields'])); + } + + /** + * Retrieve clone model + * + * @return Mage_Core_Model_Abstract + */ + public function getCloneModel() + { + if (!isset($this->_data['clone_model']) || !$this->_data['clone_model']) { + Mage::throwException('Config form fieldset clone model required to be able to clone fields'); + } + return $this->_cloneModelFactory->create($this->_data['clone_model']); + } + + /** + * Populate form fieldset with group data + * + * @param Varien_Data_Form_Element_Fieldset $fieldset + */ + public function populateFieldset(Varien_Data_Form_Element_Fieldset $fieldset) + { + $originalData = array(); + foreach ($this->_data as $key => $value) { + if (!is_array($value)) { + $originalData[$key] = $value; + } + } + $fieldset->setOriginalData($originalData); + } + + /** + * Check whether group should be expanded + * + * @return bool + */ + public function isExpanded() + { + return (bool) (isset($this->_data['expanded']) ? (int) $this->_data['expanded'] : false); + } + + /** + * Retrieve group fieldset css + * + * @return string + */ + public function getFieldsetCss() + { + return array_key_exists('fieldset_css', $this->_data) ? $this->_data['fieldset_css'] : ''; + } + + /** + * Retrieve field dependencies + * + * @param $storeCode + * @return array + */ + public function getDependencies($storeCode) + { + $dependencies = array(); + if (false == isset($this->_data['depends']['fields'])) { + return $dependencies; + } + + $dependencies = $this->_dependencyMapper->getDependencies($this->_data['depends']['fields'], $storeCode); + return $dependencies; + } +} diff --git a/app/code/core/Mage/Backend/Model/Config/Structure/Element/Group/Proxy.php b/app/code/core/Mage/Backend/Model/Config/Structure/Element/Group/Proxy.php new file mode 100644 index 0000000000000000000000000000000000000000..4aa86a7a0eabcb1376ab5582fcf943e592fa4d92 --- /dev/null +++ b/app/code/core/Mage/Backend/Model/Config/Structure/Element/Group/Proxy.php @@ -0,0 +1,257 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_Backend + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_Backend_Model_Config_Structure_Element_Group_Proxy + extends Mage_Backend_Model_Config_Structure_Element_Group +{ + /** + * Object manager + * @var Magento_ObjectManager + */ + protected $_objectManager; + + /** + * @var Mage_Backend_Model_Config_Structure_Element_Group + */ + protected $_subject; + + /** + * @param Magento_ObjectManager $objectManger + */ + public function __construct(Magento_ObjectManager $objectManger) + { + $this->_objectManager = $objectManger; + } + + /** + * Retrieve subject + * + * @return Mage_Backend_Model_Config_Structure_Element_Group + */ + protected function _getSubject() + { + if (!$this->_subject) { + $this->_subject = $this->_objectManager->create('Mage_Backend_Model_Config_Structure_Element_Group'); + } + return $this->_subject; + } + + /** + * Set element data + * + * @param array $data + * @param string $scope + */ + public function setData(array $data, $scope) + { + $this->_getSubject()->setData($data, $scope); + } + + /** + * Retrieve element id + * + * @return string + */ + public function getId() + { + return $this->_getSubject()->getId(); + } + + /** + * Retrieve element label + * + * @return string + */ + public function getLabel() + { + return $this->_getSubject()->getLabel(); + } + + /** + * Retrieve element label + * + * @return string + */ + public function getComment() + { + return $this->_getSubject()->getComment(); + } + + /** + * Retrieve frontend model class name + * + * @return string + */ + public function getFrontendModel() + { + return $this->_getSubject()->getFrontendModel(); + } + + /** + * Retrieve arbitrary element attribute + * + * @param string $key + * @return mixed + */ + public function getAttribute($key) + { + return $this->_getSubject()->getAttribute($key); + } + + /** + * Check whether section is allowed for current user + * + * @return bool + */ + public function isAllowed() + { + return $this->_getSubject()->isAllowed(); + } + + /** + * Check whether element should be displayed + * + * @return bool + */ + public function isVisible($websiteCode = '', $storeCode = '') + { + return $this->_getSubject()->isVisible($websiteCode, $storeCode); + } + + /** + * Retrieve css class of a tab + * + * @return string + */ + public function getClass() + { + return $this->_getSubject()->getClass(); + } + + + /** + * Check whether element has visible child elements + * + * @return bool + */ + public function hasChildren() + { + return $this->_getSubject()->hasChildren(); + } + + /** + * Retrieve children iterator + * + * @return Mage_Backend_Model_Config_Structure_Element_Iterator + */ + public function getChildren() + { + return $this->_getSubject()->getChildren(); + } + + /** + * Should group fields be cloned + * + * @return bool + */ + public function shouldCloneFields() + { + return $this->_getSubject()->shouldCloneFields(); + } + + /** + * Retrieve clone model + * + * @return Mage_Core_Model_Abstract + */ + public function getCloneModel() + { + return $this->_getSubject()->getCloneModel(); + } + + /** + * Populate form fieldset with group data + * + * @param Varien_Data_Form_Element_Fieldset $fieldset + */ + public function populateFieldset(Varien_Data_Form_Element_Fieldset $fieldset) + { + $this->_getSubject()->populateFieldset($fieldset); + } + + /** + * Retrieve element data + * + * @return array + */ + public function getData() + { + return $this->_getSubject()->getData(); + } + + /** + * Retrieve element path + * + * @param string $fieldPrefix + * @return string + */ + public function getPath($fieldPrefix = '') + { + return $this->_getSubject()->getPath($fieldPrefix); + } + + /** + * Check whether element should be expanded + * + * @return bool + */ + public function isExpanded() + { + return $this->_getSubject()->isExpanded(); + } + + /** + * Retrieve fieldset css + * + * @return string + */ + public function getFieldsetCss() + { + return $this->_getSubject()->getFieldsetCss(); + } + + /** + * Retrieve element dependencies + * + * @param string $storeCode + * @return array + */ + public function getDependencies($storeCode) + { + return $this->_getSubject()->getDependencies($storeCode); + } +} + diff --git a/app/code/core/Mage/Backend/Model/Config/Structure/Element/Iterator.php b/app/code/core/Mage/Backend/Model/Config/Structure/Element/Iterator.php new file mode 100644 index 0000000000000000000000000000000000000000..fb64c5edce5b5c9fb76d5ed54669c746e622fb49 --- /dev/null +++ b/app/code/core/Mage/Backend/Model/Config/Structure/Element/Iterator.php @@ -0,0 +1,164 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_Backend + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_Backend_Model_Config_Structure_Element_Iterator implements Iterator +{ + /** + * List of element data + * + * @var Mage_Backend_Model_Config_Structure_ElementInterface[] + */ + protected $_elements; + + /** + * Config structure element flyweight + * + * @var Mage_Backend_Model_Config_Structure_ElementAbstract + */ + protected $_flyweight; + + /** + * Configuration scope + * + * @var string + */ + protected $_scope; + + /** + * Last element id + * + * @var string + */ + protected $_lastId; + + /** + * @param Mage_Backend_Model_Config_Structure_ElementAbstract $element + */ + public function __construct(Mage_Backend_Model_Config_Structure_ElementAbstract $element) + { + $this->_flyweight = $element; + } + + /** + * Set element data + * + * @param array $elements + * @param string $scope + */ + public function setElements(array $elements, $scope) + { + $this->_elements = $elements; + $this->_scope = $scope; + if (count($elements)) { + $lastElement = end($elements); + $this->_lastId = $lastElement['id']; + } + } + + /** + * Return the current element + * + * @return Mage_Backend_Model_Config_Structure_ElementInterface + */ + public function current() + { + return $this->_flyweight; + } + + /** + * Move forward to next element + * + * @return void Any returned value is ignored. + */ + public function next() + { + next($this->_elements); + if (current($this->_elements)) { + $this->_initFlyweight(current($this->_elements)); + if (!$this->current()->isVisible()) { + $this->next(); + } + } + } + + /** + * Initialize current flyweight + * + * @param array $element + */ + protected function _initFlyweight(array $element) + { + $this->_flyweight->setData($element, $this->_scope); + } + + /** + * Return the key of the current element + * + * @return mixed scalar on success, or null on failure. + */ + public function key() + { + key($this->_elements); + } + + /** + * Checks if current position is valid + * + * @return boolean The return value will be casted to boolean and then evaluated. + * Returns true on success or false on failure. + */ + public function valid() + { + return (bool) current($this->_elements); + } + + /** + * Rewind the Iterator to the first element + * + * @return void Any returned value is ignored. + */ + public function rewind() + { + reset($this->_elements); + if (current($this->_elements)) { + $this->_initFlyweight(current($this->_elements)); + if (!$this->current()->isVisible()) { + $this->next(); + } + } + } + + /** + * Check whether element is last in list + * + * @param Mage_Backend_Model_Config_Structure_ElementInterface $element + * @return bool + */ + public function isLast(Mage_Backend_Model_Config_Structure_ElementInterface $element) + { + return $element->getId() == $this->_lastId; + } +} diff --git a/app/code/core/Mage/Backend/Model/Config/Structure/Element/Iterator/Field.php b/app/code/core/Mage/Backend/Model/Config/Structure/Element/Iterator/Field.php new file mode 100644 index 0000000000000000000000000000000000000000..fe8a703281d394d8f5fd0f589825c1f0a422dbe9 --- /dev/null +++ b/app/code/core/Mage/Backend/Model/Config/Structure/Element/Iterator/Field.php @@ -0,0 +1,78 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_Backend + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_Backend_Model_Config_Structure_Element_Iterator_Field + extends Mage_Backend_Model_Config_Structure_Element_Iterator +{ + /** + * Group flyweight + * + * @var Mage_Backend_Model_Config_Structure_Element_Group + */ + protected $_groupFlyweight; + + /** + * Field element flyweight + * + * @var Mage_Backend_Model_Config_Structure_Element_Field + */ + protected $_fieldFlyweight; + + /** + * @param Mage_Backend_Model_Config_Structure_Element_Group $groupFlyweight + * @param Mage_Backend_Model_Config_Structure_Element_Field $fieldFlyweight + */ + public function __construct( + Mage_Backend_Model_Config_Structure_Element_Group $groupFlyweight, + Mage_Backend_Model_Config_Structure_Element_Field $fieldFlyweight + ) { + $this->_groupFlyweight = $groupFlyweight; + $this->_fieldFlyweight = $fieldFlyweight; + } + + /** + * Init current element + * + * @param array $element + * @throws LogicException + */ + protected function _initFlyweight(array $element) + { + if (!isset($element[Mage_Backend_Model_Config_Structure::TYPE_KEY])) { + throw new LogicException('System config structure element must contain "type" attribute'); + } + switch($element[Mage_Backend_Model_Config_Structure::TYPE_KEY]) { + case 'group': + $this->_flyweight = $this->_groupFlyweight; + break; + + case 'field': + default: + $this->_flyweight = $this->_fieldFlyweight; + } + parent::_initFlyweight($element); + } +} diff --git a/app/code/core/Mage/Backend/Model/Config/Structure/Element/Iterator/Group.php b/app/code/core/Mage/Backend/Model/Config/Structure/Element/Iterator/Group.php new file mode 100644 index 0000000000000000000000000000000000000000..42310eb6a7defd9f66c6df6b1e77bb29ed64851c --- /dev/null +++ b/app/code/core/Mage/Backend/Model/Config/Structure/Element/Iterator/Group.php @@ -0,0 +1,37 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_Backend + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_Backend_Model_Config_Structure_Element_Iterator_Group + extends Mage_Backend_Model_Config_Structure_Element_Iterator +{ + /** + * @param Mage_Backend_Model_Config_Structure_Element_Group $element + */ + public function __construct(Mage_Backend_Model_Config_Structure_Element_Group $element) + { + parent::__construct($element); + } +} diff --git a/app/code/core/Mage/Backend/Model/Config/Structure/Element/Iterator/Section.php b/app/code/core/Mage/Backend/Model/Config/Structure/Element/Iterator/Section.php new file mode 100644 index 0000000000000000000000000000000000000000..6dc28a54087547ae13b69d6cc7ab7760a9001fb0 --- /dev/null +++ b/app/code/core/Mage/Backend/Model/Config/Structure/Element/Iterator/Section.php @@ -0,0 +1,37 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_Backend + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_Backend_Model_Config_Structure_Element_Iterator_Section + extends Mage_Backend_Model_Config_Structure_Element_Iterator +{ + /** + * @param Mage_Backend_Model_Config_Structure_Element_Section $element + */ + public function __construct(Mage_Backend_Model_Config_Structure_Element_Section $element) + { + parent::__construct($element); + } +} diff --git a/app/code/core/Mage/Backend/Model/Config/Structure/Element/Iterator/Tab.php b/app/code/core/Mage/Backend/Model/Config/Structure/Element/Iterator/Tab.php new file mode 100644 index 0000000000000000000000000000000000000000..8fad105904f973355aa5d6136ebcaf44026a987e --- /dev/null +++ b/app/code/core/Mage/Backend/Model/Config/Structure/Element/Iterator/Tab.php @@ -0,0 +1,37 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_Backend + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_Backend_Model_Config_Structure_Element_Iterator_Tab + extends Mage_Backend_Model_Config_Structure_Element_Iterator +{ + /** + * @param Mage_Backend_Model_Config_Structure_Element_Tab $element + */ + public function __construct(Mage_Backend_Model_Config_Structure_Element_Tab $element) + { + parent::__construct($element); + } +} diff --git a/app/code/core/Mage/Backend/Model/Config/Structure/Element/Section.php b/app/code/core/Mage/Backend/Model/Config/Structure/Element/Section.php new file mode 100644 index 0000000000000000000000000000000000000000..329f57bbd3b4cfd93f9859b5b0ef4d3cd04a3a29 --- /dev/null +++ b/app/code/core/Mage/Backend/Model/Config/Structure/Element/Section.php @@ -0,0 +1,85 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_Backend + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_Backend_Model_Config_Structure_Element_Section + extends Mage_Backend_Model_Config_Structure_Element_CompositeAbstract +{ + /** + * Authorization service + * + * @var Mage_Core_Model_Authorization + */ + protected $_authorization; + + /** + * @param Mage_Core_Model_Factory_Helper $helperFactory + * @param Mage_Core_Model_App $application + * @param Mage_Backend_Model_Config_Structure_Element_Iterator $childrenIterator + * @param Mage_Core_Model_Authorization $authorization + */ + public function __construct( + Mage_Core_Model_Factory_Helper $helperFactory, + Mage_Core_Model_App $application, + Mage_Backend_Model_Config_Structure_Element_Iterator $childrenIterator, + Mage_Core_Model_Authorization $authorization + ) { + parent::__construct($helperFactory, $application, $childrenIterator); + $this->_authorization = $authorization; + } + + /** + * Retrieve section header css + * + * @return string + */ + public function getHeaderCss() + { + return isset($this->_data['header_css']) ? $this->_data['header_css'] : ''; + } + + /** + * Check whether section is allowed for current user + * + * @return bool + */ + public function isAllowed() + { + return isset($this->_data['resource']) ? $this->_authorization->isAllowed($this->_data['resource']) : false; + } + + /** + * Check whether element should be displayed + * + * @return bool + */ + public function isVisible() + { + if (!$this->isAllowed()) { + return false; + } + return parent::isVisible(); + } +} diff --git a/app/code/core/Mage/Backend/Model/Config/Structure/Element/Tab.php b/app/code/core/Mage/Backend/Model/Config/Structure/Element/Tab.php new file mode 100644 index 0000000000000000000000000000000000000000..2d3d5c527a3627541aa58125d16be2fbd3058cee --- /dev/null +++ b/app/code/core/Mage/Backend/Model/Config/Structure/Element/Tab.php @@ -0,0 +1,40 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_Backend + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_Backend_Model_Config_Structure_Element_Tab + extends Mage_Backend_Model_Config_Structure_Element_CompositeAbstract +{ + + /** + * Check whether tab is visible + * + * @return bool + */ + public function isVisible() + { + return $this->hasChildren(); + } +} diff --git a/app/code/core/Mage/Backend/Model/Config/Structure/ElementAbstract.php b/app/code/core/Mage/Backend/Model/Config/Structure/ElementAbstract.php new file mode 100644 index 0000000000000000000000000000000000000000..fe30dcb9d051cd26d205146d22714cd6f42776fa --- /dev/null +++ b/app/code/core/Mage/Backend/Model/Config/Structure/ElementAbstract.php @@ -0,0 +1,215 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_Backend + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +abstract class Mage_Backend_Model_Config_Structure_ElementAbstract + implements Mage_Backend_Model_Config_Structure_ElementInterface +{ + /** + * Element data + * + * @var array + */ + protected $_data = array(); + + /** + * Current configuration scope + * + * @var string + */ + protected $_scope; + + /** + * Helper factory + * + * @var Mage_Core_Model_Factory_Helper + */ + protected $_helperFactory; + + /** + * Application object + * + * @var Mage_Core_Model_App + */ + protected $_application; + + /** + * @param Mage_Core_Model_Factory_Helper $helperFactory + * @param Mage_Core_Model_App $application + */ + public function __construct( + Mage_Core_Model_Factory_Helper $helperFactory, + Mage_Core_Model_App $application + ) { + $this->_helperFactory = $helperFactory; + $this->_application = $application; + } + + /** + * Retrieve element translation module + * + * @return string + */ + protected function _getTranslationModule() + { + return (isset($this->_data['module']) ? $this->_data['module'] : 'Mage_Backend') . '_Helper_Data'; + } + + /** + * Translate element attribute + * + * @param string $code + * @return string + */ + protected function _getTranslatedAttribute($code) + { + if (false == array_key_exists($code, $this->_data)) { + return ''; + } + return $this->_helperFactory->get($this->_getTranslationModule())->__($this->_data[$code]); + } + + /** + * Set element data + * + * @param array $data + * @param string $scope + */ + public function setData(array $data, $scope) + { + $this->_data = $data; + $this->_scope = $scope; + } + + /** + * Retrieve flyweight data + * + * @return array + */ + public function getData() + { + return $this->_data; + } + + /** + * Retrieve element id + * + * @return string + */ + public function getId() + { + return isset($this->_data['id']) ? $this->_data['id'] : ''; + } + + /** + * Retrieve element label + * + * @return string + */ + public function getLabel() + { + return $this->_getTranslatedAttribute('label'); + } + + /** + * Retrieve element label + * + * @return string + */ + public function getComment() + { + return $this->_getTranslatedAttribute('comment'); + } + + /** + * Retrieve frontend model class name + * + * @return string + */ + public function getFrontendModel() + { + return isset($this->_data['frontend_model']) ? $this->_data['frontend_model'] : ''; + } + + /** + * Retrieve arbitrary element attribute + * + * @param string $key + * @return mixed + */ + public function getAttribute($key) + { + return array_key_exists($key, $this->_data) ? $this->_data[$key] : null; + } + + /** + * Check whether element should be displayed + * + * @return bool + */ + public function isVisible() + { + if ($this->_application->isSingleStoreMode()) { + return !(isset($this->_data['hide_in_single_store_mode']) && $this->_data['hide_in_single_store_mode']); + } + + $result = false; + switch ($this->_scope) { + case Mage_Backend_Model_Config_ScopeDefiner::SCOPE_STORE: + $result = isset($this->_data['showInStore']) && $this->_data['showInStore']; + break; + case Mage_Backend_Model_Config_ScopeDefiner::SCOPE_WEBSITE: + $result = isset($this->_data['showInWebsite']) && $this->_data['showInWebsite']; + break; + case Mage_Backend_Model_Config_ScopeDefiner::SCOPE_DEFAULT: + $result = isset($this->_data['showInDefault']) && $this->_data['showInDefault']; + break; + } + + return $result; + } + + /** + * Retrieve css class of a tab + * + * @return string + */ + public function getClass() + { + return isset($this->_data['class']) ? $this->_data['class'] : ''; + } + + /** + * Retrieve element config path + * + * @param string $fieldPrefix + * @return string + */ + public function getPath($fieldPrefix = '') + { + $path = isset($this->_data['path']) ? $this->_data['path'] : ''; + return $path . '/' . $fieldPrefix . $this->getId(); + } +} diff --git a/app/code/core/Mage/Catalog/Model/Product/Type/Api.php b/app/code/core/Mage/Backend/Model/Config/Structure/ElementInterface.php similarity index 60% rename from app/code/core/Mage/Catalog/Model/Product/Type/Api.php rename to app/code/core/Mage/Backend/Model/Config/Structure/ElementInterface.php index 244fc0c1474c619e6d3b9ec3ef9658faa5db9183..2db810da9db8372a31237528166e4f2a4c617799 100644 --- a/app/code/core/Mage/Catalog/Model/Product/Type/Api.php +++ b/app/code/core/Mage/Backend/Model/Config/Structure/ElementInterface.php @@ -19,36 +19,47 @@ * needs please refer to http://www.magentocommerce.com for more information. * * @category Mage - * @package Mage_Catalog + * @package Mage_Backend * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -/** - * Catalog product type api - * - * @category Mage - * @package Mage_Catalog - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Catalog_Model_Product_Type_Api extends Mage_Api_Model_Resource_Abstract +interface Mage_Backend_Model_Config_Structure_ElementInterface { /** - * Retrieve product type list + * Set element data + * + * @param array $data + * @param string $scope + */ + public function setData(array $data, $scope); + + /** + * Retrieve element configuration * * @return array */ - public function items() - { - $result = array(); + public function getData(); + + /** + * Retrieve element id + * + * @return string + */ + public function getId(); - foreach (Mage_Catalog_Model_Product_Type::getOptionArray() as $type=>$label) { - $result[] = array( - 'type' => $type, - 'label' => $label - ); - } + /** + * Retrieve element label + * + * @return string + */ + public function getLabel(); + + /** + * Check whether element is visible + * + * @return bool + */ + public function isVisible(); +} - return $result; - } -} // Class Mage_Catalog_Model_Product_Type_Api End diff --git a/app/code/core/Mage/Api/controllers/XmlrpcController.php b/app/code/core/Mage/Backend/Model/Config/Structure/Mapper/Attribute/Inheritance.php similarity index 71% rename from app/code/core/Mage/Api/controllers/XmlrpcController.php rename to app/code/core/Mage/Backend/Model/Config/Structure/Mapper/Attribute/Inheritance.php index 2a66e1bb8462984d3894557ce639da8b61cb4242..b8ca251194b9d1502afc2201e9387bab65dcd999 100644 --- a/app/code/core/Mage/Api/controllers/XmlrpcController.php +++ b/app/code/core/Mage/Backend/Model/Config/Structure/Mapper/Attribute/Inheritance.php @@ -19,23 +19,25 @@ * needs please refer to http://www.magentocommerce.com for more information. * * @category Mage - * @package Mage_Api + * @package Mage_Backend * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ /** - * Xml Rpc webservice controller - * - * @category Mage - * @package Mage_Api - * @author Magento Core Team <core@magentocommerce.com> + * System Configuration Attribute Inheritance Mapper */ -class Mage_Api_XmlrpcController extends Mage_Api_Controller_Action +class Mage_Backend_Model_Config_Structure_Mapper_Attribute_Inheritance + implements Mage_Backend_Model_Config_Structure_MapperInterface { - public function indexAction() + /** + * Apply map + * + * @param array $data + * @return array + */ + public function map(array $data) { - $this->_getServer()->init($this, 'xmlrpc') - ->run(); + return $data; } -} // Class Mage_Api_XmlrpcController End +} diff --git a/app/code/core/Mage/Backend/Model/Config/Structure/Mapper/Dependencies.php b/app/code/core/Mage/Backend/Model/Config/Structure/Mapper/Dependencies.php new file mode 100644 index 0000000000000000000000000000000000000000..3b8375a607317e31a44c22c641d3995136fb71c1 --- /dev/null +++ b/app/code/core/Mage/Backend/Model/Config/Structure/Mapper/Dependencies.php @@ -0,0 +1,114 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_Backend + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * System Configuration Dependencies Mapper + */ +class Mage_Backend_Model_Config_Structure_Mapper_Dependencies extends Mage_Backend_Model_Config_Structure_MapperAbstract +{ + /** + * Apply map + * + * @param array $data + * @return array + */ + public function map(array $data) + { + if ($this->_hasValue('config/system/sections', $data)) { + foreach ($data['config']['system']['sections'] as &$sectionConfig) { + $sectionConfig = $this->_processConfig($sectionConfig); + } + } + return $data; + } + + /** + * Process configuration + * + * @param array $config + * @return array + */ + protected function _processConfig($config) + { + $config = $this->_processDepends($config); + + if ($this->_hasValue('children', $config)) { + foreach ($config['children'] as &$subConfig) { + $subConfig = $this->_processConfig($subConfig); + } + } + return $config; + } + + /** + * Process dependencies configuration + * + * @param array $config + * @return array + */ + protected function _processDepends($config) + { + if ($this->_hasValue('depends/fields', $config)) { + foreach ($config['depends']['fields'] as &$field) { + $dependPath = $this->_getDependPath($field, $config); + $field['dependPath'] = $dependPath; + $field['id'] = implode('/', $dependPath); + } + } + return $config; + } + + /** + * Get depend path + * + * @param array $field + * @param array $config + * @return array + * @throws InvalidArgumentException + */ + protected function _getDependPath($field, $config) + { + $dependPath = $field['id']; + if (strpos($dependPath, '/') === false) { + $dependPath = '*/*/' . $dependPath; + } + $elementPath = $config['path'] . '/' . $config['id']; + + $dependPathParts = explode('/', $dependPath); + $elementPathParts = explode('/', $elementPath); + $output = array(); + foreach ($dependPathParts as $index => $path) { + if ($path === '*') { + if (false == array_key_exists($index, $elementPathParts)) { + throw new InvalidArgumentException('Invalid relative depends structure'); + } + $path = $elementPathParts[$index]; + } + $output[$index] = $path; + } + return $output; + } +} diff --git a/app/code/core/Mage/Backend/Model/Config/Structure/Mapper/Factory.php b/app/code/core/Mage/Backend/Model/Config/Structure/Mapper/Factory.php new file mode 100644 index 0000000000000000000000000000000000000000..87cfe3c5bce2a9a0825ae48d3ab0a3c1da404a87 --- /dev/null +++ b/app/code/core/Mage/Backend/Model/Config/Structure/Mapper/Factory.php @@ -0,0 +1,94 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_Backend + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * System Configuration Mapper Factory + */ +class Mage_Backend_Model_Config_Structure_Mapper_Factory +{ + const MAPPER_SORTING = 'sorting'; + const MAPPER_PATH = 'path'; + const MAPPER_IGNORE = 'ignore'; + const MAPPER_DEPENDENCIES = 'dependencies'; + const MAPPER_ATTRIBUTE_INHERITANCE = 'attribute_inheritance'; + + /** + * @var Magento_ObjectManager + */ + protected $_objectManager; + + /** + * @var array + */ + protected $_typeMap = array( + self::MAPPER_SORTING => 'Mage_Backend_Model_Config_Structure_Mapper_Sorting', + self::MAPPER_PATH => 'Mage_Backend_Model_Config_Structure_Mapper_Path', + self::MAPPER_IGNORE => 'Mage_Backend_Model_Config_Structure_Mapper_Ignore', + self::MAPPER_DEPENDENCIES => 'Mage_Backend_Model_Config_Structure_Mapper_Dependencies', + self::MAPPER_ATTRIBUTE_INHERITANCE => 'Mage_Backend_Model_Config_Structure_Mapper_Attribute_Inheritance', + ); + + public function __construct(Magento_ObjectManager $objectManager) + { + $this->_objectManager = $objectManager; + } + + /** + * Get mapper instance + * + * @param string $type + * @param array $arguments + * @return Mage_Backend_Model_Config_Structure_MapperInterface + * @throws Exception + */ + public function create($type, $arguments = array()) + { + $className = $this->_getMapperClassNameByType($type); + + /** @var Mage_Backend_Model_Config_Structure_MapperInterface $mapperInstance */ + $mapperInstance = $this->_objectManager->get($className, $arguments); + + if (false == ($mapperInstance instanceof Mage_Backend_Model_Config_Structure_MapperInterface)) { + throw new Exception('Mapper object is not instance on Mage_Backend_Model_Config_Structure_MapperInterface'); + } + return $mapperInstance; + } + + /** + * Get mapper class name by type + * + * @param string $type + * @return string mixed + * @throws InvalidArgumentException + */ + protected function _getMapperClassNameByType($type) + { + if (false == isset($this->_typeMap[$type])) { + throw new InvalidArgumentException('Invalid mapper type: ' . $type); + } + return $this->_typeMap[$type]; + } +} diff --git a/app/code/core/Mage/Backend/Model/Config/Structure/Mapper/Ignore.php b/app/code/core/Mage/Backend/Model/Config/Structure/Mapper/Ignore.php new file mode 100644 index 0000000000000000000000000000000000000000..5b278fbedfa18f854602a4b1d1f4e7efdbe03512 --- /dev/null +++ b/app/code/core/Mage/Backend/Model/Config/Structure/Mapper/Ignore.php @@ -0,0 +1,42 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_Backend + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * System Configuration Ignore Mapper + */ +class Mage_Backend_Model_Config_Structure_Mapper_Ignore implements Mage_Backend_Model_Config_Structure_MapperInterface +{ + /** + * Apply map + * + * @param array $data + * @return array + */ + public function map(array $data) + { + return $data; + } +} diff --git a/app/code/core/Mage/Backend/Model/Config/Structure/Mapper/Path.php b/app/code/core/Mage/Backend/Model/Config/Structure/Mapper/Path.php new file mode 100644 index 0000000000000000000000000000000000000000..e5f3609a5273880db90c32ad02a467bca1fa84db --- /dev/null +++ b/app/code/core/Mage/Backend/Model/Config/Structure/Mapper/Path.php @@ -0,0 +1,73 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_Backend + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * System Configuration Path Mapper + */ +class Mage_Backend_Model_Config_Structure_Mapper_Path extends Mage_Backend_Model_Config_Structure_MapperAbstract +{ + /** + * Apply map + * + * @param array $data + * @return array + */ + public function map(array $data) + { + if ($this->_hasValue('config/system/sections', $data)) { + foreach ($data['config']['system']['sections'] as &$sectionConfig) { + if ($this->_hasValue('children', $sectionConfig)) { + foreach ($sectionConfig['children'] as &$groupConfig) { + $groupConfig = $this->_processConfig($groupConfig, $sectionConfig); + } + } + } + } + return $data; + } + + /** + * Process configuration + * + * @param array $elementConfig + * @param array $parentConfig + * @return array + */ + protected function _processConfig(array $elementConfig, array $parentConfig) + { + $parentPath = $this->_hasValue('path', $parentConfig) ? $parentConfig['path'] . '/' : ''; + $parentPath .= $parentConfig['id']; + $elementConfig['path'] = $parentPath; + + if ($this->_hasValue('children', $elementConfig)) { + foreach ($elementConfig['children'] as &$subConfig) { + $subConfig = $this->_processConfig($subConfig, $elementConfig); + } + } + + return $elementConfig; + } +} diff --git a/app/code/core/Mage/Backend/Model/Config/Structure/Mapper/Sorting.php b/app/code/core/Mage/Backend/Model/Config/Structure/Mapper/Sorting.php new file mode 100644 index 0000000000000000000000000000000000000000..8c2369283c0b3efc71fbad6272110f16046660d2 --- /dev/null +++ b/app/code/core/Mage/Backend/Model/Config/Structure/Mapper/Sorting.php @@ -0,0 +1,82 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_Backend + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * System Configuration Sorting Mapper + */ +class Mage_Backend_Model_Config_Structure_Mapper_Sorting extends Mage_Backend_Model_Config_Structure_MapperAbstract +{ + /** + * Apply map + * + * @param array $data + * @return array + */ + public function map(array $data) + { + foreach ($data['config']['system'] as &$element) { + $element = $this->_processConfig($element); + } + return $data; + } + + protected function _processConfig($data) + { + foreach ($data as &$item) { + if ($this->_hasValue('children', $item)) { + $item['children'] = $this->_processConfig($item['children']); + } + } + uasort($data, array($this, '_cmp')); + return $data; + } + + + /** + * Compare elements + * + * @param array $elementA + * @param array $elementB + * @return int + */ + protected function _cmp($elementA, $elementB) + { + $sortIndexA = 0; + if ($this->_hasValue('sortOrder', $elementA)) { + $sortIndexA = intval($elementA['sortOrder']); + } + $sortIndexB = 0; + if ($this->_hasValue('sortOrder', $elementB)) { + $sortIndexB = intval($elementB['sortOrder']); + } + + if ($sortIndexA == $sortIndexB) { + return 0; + } + + return ($sortIndexA < $sortIndexB) ? -1 : 1; + } +} diff --git a/app/code/core/Mage/Customer/Model/Group/Api.php b/app/code/core/Mage/Backend/Model/Config/Structure/MapperAbstract.php similarity index 58% rename from app/code/core/Mage/Customer/Model/Group/Api.php rename to app/code/core/Mage/Backend/Model/Config/Structure/MapperAbstract.php index 5cafc8bd98286b5264460438f42c65b2d437081c..d2680b43c96b5feddbed664212e9a7e71ddc0e75 100644 --- a/app/code/core/Mage/Customer/Model/Group/Api.php +++ b/app/code/core/Mage/Backend/Model/Config/Structure/MapperAbstract.php @@ -19,35 +19,38 @@ * needs please refer to http://www.magentocommerce.com for more information. * * @category Mage - * @package Mage_Customer + * @package Mage_Backend * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ /** - * Customer groups api - * - * @category Mage - * @package Mage_Customer - * @author Magento Core Team <core@magentocommerce.com> + * System Configuration Converter Mapper Interface */ -class Mage_Customer_Model_Group_Api extends Mage_Api_Model_Resource_Abstract +abstract class Mage_Backend_Model_Config_Structure_MapperAbstract + implements Mage_Backend_Model_Config_Structure_MapperInterface { /** - * Retrieve groups + * Check value existence * - * @return array + * @param string $key + * @param array $target + * @return bool */ - public function items() + protected function _hasValue($key, $target) { - $collection = Mage::getModel('Mage_Customer_Model_Group')->getCollection(); - - $result = array(); - foreach ($collection as $group) { - /* @var $group Mage_Customer_Model_Group */ - $result[] = $group->toArray(array('customer_group_id', 'customer_group_code')); + if (false == is_array($target)) { + return false; } - return $result; + $paths = explode('/', $key); + foreach ($paths as $path) { + if (array_key_exists($path, $target)) { + $target = $target[$path]; + } else { + return false; + } + } + return true; } } diff --git a/app/code/core/Mage/Api/Model/Acl/Role/Group.php b/app/code/core/Mage/Backend/Model/Config/Structure/MapperInterface.php similarity index 78% rename from app/code/core/Mage/Api/Model/Acl/Role/Group.php rename to app/code/core/Mage/Backend/Model/Config/Structure/MapperInterface.php index 6ded6c4691b058b9597591103243bb00cd8ab726..73eececbe858a1e67c651192d44954ca5ea59a5b 100644 --- a/app/code/core/Mage/Api/Model/Acl/Role/Group.php +++ b/app/code/core/Mage/Backend/Model/Config/Structure/MapperInterface.php @@ -19,20 +19,21 @@ * needs please refer to http://www.magentocommerce.com for more information. * * @category Mage - * @package Mage_Api + * @package Mage_Backend * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ - /** - * Acl Group model - * - * @category Mage - * @package Mage_Api - * @author Magento Core Team <core@magentocommerce.com> + * System Configuration Converter Mapper Interface */ -class Mage_Api_Model_Acl_Role_Group extends Mage_Api_Model_Acl_Role_Generic +interface Mage_Backend_Model_Config_Structure_MapperInterface { - + /** + * Apply map + * + * @param array $data + * @return array + */ + public function map(array $data); } diff --git a/app/code/core/Mage/Backend/Model/Config/Structure/Reader.php b/app/code/core/Mage/Backend/Model/Config/Structure/Reader.php index ce2b2dccb6dc2ab921fa7b109bfc51549fe2cd49..bd04a65f98fb747eaa26ca8b637078416178f73b 100644 --- a/app/code/core/Mage/Backend/Model/Config/Structure/Reader.php +++ b/app/code/core/Mage/Backend/Model/Config/Structure/Reader.php @@ -33,57 +33,127 @@ * @package Mage_Backend * @author Magento Core Team <core@magentocommerce.com> */ -class Mage_Backend_Model_Config_Structure_Reader +class Mage_Backend_Model_Config_Structure_Reader extends Magento_Config_XmlAbstract { const CACHE_SYSTEM_CONFIGURATION_STRUCTURE = 'backend_system_configuration_structure'; /** - * @var Mage_Core_Model_Cache + * Turns runtime validation on/off + * + * @var bool */ - protected $_cache; + protected $_runtimeValidation; + /** + * @param Mage_Core_Model_Config $config + * @param Mage_Core_Model_Cache $cache + * @param Mage_Backend_Model_Config_Structure_Converter $structureConverter + * @param bool $runtimeValidation + */ + public function __construct( + Mage_Core_Model_Config $config, + Mage_Core_Model_Cache $cache, + Mage_Backend_Model_Config_Structure_Converter $structureConverter, + $runtimeValidation = true + ) { + $this->_runtimeValidation = $runtimeValidation; + $this->_converter = $structureConverter; + + if ($cache->canUse('config') + && ($cachedData = $cache->load(self::CACHE_SYSTEM_CONFIGURATION_STRUCTURE))) { + $this->_data = unserialize($cachedData); + } else { + $fileNames = $config + ->getModuleConfigurationFiles('adminhtml' . DIRECTORY_SEPARATOR . 'system.xml'); + parent::__construct($fileNames); + + if ($cache->canUse('config')) { + $cache->save( + serialize($this->_data), + self::CACHE_SYSTEM_CONFIGURATION_STRUCTURE, + array(Mage_Core_Model_Config::CACHE_TAG) + ); + } + } + } /** - * @var Mage_Core_Model_Config + * Get absolute path to the XML-schema file + * + * @return string */ - protected $_appConfig; + public function getSchemaFile() + { + return __DIR__ . '/system.xsd'; + } /** - * @param array $data + * Get absolute path to the XML-schema file + * + * @return string */ - public function __construct(array $data = array()) + public function getPerFileSchemaFile() { - $this->_appConfig = isset($data['config']) ? $data['config'] : Mage::getConfig(); - $this->_cache = isset($data['cache']) ? $data['cache'] : Mage::app()->getCacheInstance(); + return __DIR__ . '/system_file.xsd'; } /** - * Load system configuration + * Extract configuration data from the DOM structure * - * @return Mage_Backend_Model_Config_Structure + * @param DOMDocument $dom + * @return array|DOMNodeList */ - public function getConfiguration() + protected function _extractData(DOMDocument $dom) { - if ($this->_cache->canUse('config')) { - $cache = $this->_cache->load(self::CACHE_SYSTEM_CONFIGURATION_STRUCTURE); - if ($cache) { - return unserialize($cache); - } - } + $data = $this->_converter->convert($dom); + return $data['config']['system']; + } + + /** + * Get XML-contents, initial for merging + * + * @return string + */ + protected function _getInitialXml() + { + return '<?xml version="1.0" encoding="utf-8"?><config><system></system></config>'; + } - $fileNames = $this->_appConfig->getModuleConfigurationFiles('adminhtml' . DIRECTORY_SEPARATOR . 'system.xml'); - $config = $this->_appConfig->getModelInstance( - 'Mage_Backend_Model_Config_Structure', array('sourceFiles' => $fileNames) + /** + * Get list of paths to identifiable nodes + * + * @return array + */ + protected function _getIdAttributes() + { + return array( + '/config/system/tab' => 'id', + '/config/system/section' => 'id', + '/config/system/section/group' => 'id', + '/config/system/section/group/field' => 'id', + '/config/system/section/group/group/field' => 'id', + '/config/system/section/group/group/group/field' => 'id', + '/config/system/section/group/group/group/group/field' => 'id', ); + } - if ($this->_cache->canUse('config')) { - $this->_cache->save( - serialize($config), - self::CACHE_SYSTEM_CONFIGURATION_STRUCTURE, - array(Mage_Core_Model_Config::CACHE_TAG) - ); - } + /** + * Check whether runtime validation should be performed + * + * @return bool + */ + protected function _isRuntimeValidated() + { + return $this->_runtimeValidation; + } - return $config; + /** + * Retrieve all sections system configuration layout + * + * @return array + */ + public function getData() + { + return $this->_data; } } diff --git a/app/code/core/Mage/Api/Model/Resource/Role/Collection.php b/app/code/core/Mage/Backend/Model/Config/Structure/Search/Proxy.php old mode 100755 new mode 100644 similarity index 50% rename from app/code/core/Mage/Api/Model/Resource/Role/Collection.php rename to app/code/core/Mage/Backend/Model/Config/Structure/Search/Proxy.php index 0271898ca440e619cbb2394884769416f5bcd7d3..633f8da3c3d79a58d8d1a9d07d9a2f7b13d843fb --- a/app/code/core/Mage/Api/Model/Resource/Role/Collection.php +++ b/app/code/core/Mage/Backend/Model/Config/Structure/Search/Proxy.php @@ -19,51 +19,53 @@ * needs please refer to http://www.magentocommerce.com for more information. * * @category Mage - * @package Mage_Api + * @package Mage_Backend * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ - -/** - * Api Role Resource Collection - * - * @category Mage - * @package Mage_Api - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api_Model_Resource_Role_Collection extends Mage_Core_Model_Resource_Db_Collection_Abstract +class Mage_Backend_Model_Config_Structure_Search_Proxy implements Mage_Backend_Model_Config_Structure_SearchInterface { /** - * Resource collection initialization - * + * Object manager + * @var Magento_ObjectManager + */ + protected $_objectManager; + + /** + * @var Mage_Backend_Model_Config_Structure + */ + protected $_subject; + + /** + * @param Magento_ObjectManager $objectManager */ - protected function _construct() + public function __construct(Magento_ObjectManager $objectManager) { - $this->_init('Mage_Api_Model_Role', 'Mage_Api_Model_Resource_Role'); + $this->_objectManager = $objectManager; } /** - * Aet user filter + * Retrieve subject * - * @param int $userId - * @return Mage_Api_Model_Resource_Role_Collection + * @return Mage_Backend_Model_Config_Structure_SearchInterface */ - public function setUserFilter($userId) + protected function _getSubject() { - $this->addFieldToFilter('user_id', $userId); - $this->addFieldToFilter('role_type', Mage_Api_Model_Acl::ROLE_TYPE_GROUP); - return $this; + if (!$this->_subject) { + $this->_subject = $this->_objectManager->get('Mage_Backend_Model_Config_Structure'); + } + return $this->_subject; } /** - * Set roles filter + * Find element by path * - * @return Mage_Api_Model_Resource_Role_Collection + * @param string $path + * @return Mage_Backend_Model_Config_Structure_ElementInterface|null */ - public function setRolesFilter() + public function getElement($path) { - $this->addFieldToFilter('role_type', Mage_Api_Model_Acl::ROLE_TYPE_GROUP); - return $this; + return $this->_getSubject()->getElement($path); } } diff --git a/app/code/core/Mage/Backend/Model/Config/Structure/SearchInterface.php b/app/code/core/Mage/Backend/Model/Config/Structure/SearchInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..25fba5fee1dda8505c56de266bc60dd7a0e03de7 --- /dev/null +++ b/app/code/core/Mage/Backend/Model/Config/Structure/SearchInterface.php @@ -0,0 +1,35 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_Backend + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +interface Mage_Backend_Model_Config_Structure_SearchInterface +{ + /** + * Find element by path + * + * @param string $path + * @return Mage_Backend_Model_Config_Structure_ElementInterface|null + */ + public function getElement($path); +} diff --git a/app/code/core/Mage/Backend/Model/Config/Structure/system.xsd b/app/code/core/Mage/Backend/Model/Config/Structure/system.xsd index ca6082e4e84e9410e7526d27593fd763f80b6b25..ebbdee1b67c08552bf263853dca7932a6b8d7da2 100644 --- a/app/code/core/Mage/Backend/Model/Config/Structure/system.xsd +++ b/app/code/core/Mage/Backend/Model/Config/Structure/system.xsd @@ -83,6 +83,7 @@ <xs:attribute name="showInDefault" type="xs:int" use="optional" /> <xs:attribute name="showInStore" type="xs:int" use="optional" /> <xs:attribute name="showInWebsite" type="xs:int" use="optional" /> + <xs:attribute name="advanced" type="xs:boolean" use="optional" /> </xs:attributeGroup> <xs:element name="tab"> @@ -152,6 +153,8 @@ <xs:element name="comment" type="xs:string" /> <xs:element name="hide_in_single_store_mode" type="xs:int" /> <xs:element ref="field" /> + <xs:element ref="group" minOccurs="0" maxOccurs="unbounded"/> + <xs:element ref="depends" /> </xs:choice> </xs:sequence> @@ -200,6 +203,7 @@ <xs:element name="upload_dir" type="typeUploadDir" /> <xs:element ref="depends" /> <xs:element ref="attribute" /> + <xs:element ref="requires" /> </xs:choice> </xs:sequence> @@ -215,9 +219,80 @@ <xs:selector xpath=".//attribute"/> <xs:field xpath="@type"/> </xs:unique> + </xs:element> + + <xs:element name="requires"> + <xs:annotation> + <xs:documentation> + Field Requirements + </xs:documentation> + </xs:annotation> + + <xs:complexType> + <xs:sequence> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:element type="requiresField" name="field" /> + <xs:element type="requiresGroup" name="group" /> + </xs:choice> + </xs:sequence> + </xs:complexType> + <xs:unique name="uniqueRequiresFieldId"> + <xs:annotation> + <xs:documentation> + Attribute id is unique under field requires block + </xs:documentation> + </xs:annotation> + <xs:selector xpath=".//field"/> + <xs:field xpath="@id"/> + </xs:unique> + + <xs:unique name="uniqueRequiresGroupId"> + <xs:annotation> + <xs:documentation> + Attribute id is unique under group requires block + </xs:documentation> + </xs:annotation> + <xs:selector xpath=".//group"/> + <xs:field xpath="@id"/> + </xs:unique> </xs:element> + <xs:complexType name="requiresField" mixed="true"> + <xs:annotation> + <xs:documentation> + Required field resource. Recursive complex type + </xs:documentation> + </xs:annotation> + <xs:simpleContent> + <xs:extension base="xs:string"> + <xs:attribute name="id" type="typeElementPath" use="required" /> + </xs:extension> + </xs:simpleContent> + </xs:complexType> + + <xs:complexType name="requiresGroup"> + <xs:annotation> + <xs:documentation> + Required group resource. Recursive complex type + </xs:documentation> + </xs:annotation> + <xs:attribute name="id" type="typeElementPath" use="required" /> + </xs:complexType> + + <xs:simpleType name="typeElementPath"> + <xs:annotation> + <xs:documentation> + Element path attribute for elements section, group, field. + </xs:documentation> + </xs:annotation> + + <xs:restriction base="xs:string"> + <xs:pattern value="[a-zA-Z0-9_///*]{3,}" /> + <xs:minLength value="3" /> + </xs:restriction> + </xs:simpleType> + <xs:element name="attribute"> <xs:annotation> <xs:documentation> @@ -251,13 +326,13 @@ <xs:complexType> <xs:annotation> <xs:documentation> - Field resource. Recursive complex type. Define element is influence on current field + Field resource. Recursive complex type. Define element is influence on current field/group </xs:documentation> </xs:annotation> <xs:simpleContent> <xs:extension base="xs:string"> - <xs:attribute name="id" type="typeId" use="required" /> + <xs:attribute name="id" type="typeElementPath" use="required" /> <xs:attribute name="separator" type='xs:string' use='optional' /> </xs:extension> </xs:simpleContent> diff --git a/app/code/core/Mage/Backend/Model/Config/Structure/system_file.xsd b/app/code/core/Mage/Backend/Model/Config/Structure/system_file.xsd index ee929e3158c3b87b679af8086048bee4b2ff8009..4c2f34cb43f9148140b5102be6db402b55319058 100644 --- a/app/code/core/Mage/Backend/Model/Config/Structure/system_file.xsd +++ b/app/code/core/Mage/Backend/Model/Config/Structure/system_file.xsd @@ -83,6 +83,7 @@ <xs:attribute name="showInDefault" type="xs:int" use="optional" /> <xs:attribute name="showInStore" type="xs:int" use="optional" /> <xs:attribute name="showInWebsite" type="xs:int" use="optional" /> + <xs:attribute name="advanced" type="xs:boolean" use="optional" /> </xs:attributeGroup> <xs:element name="tab"> @@ -153,6 +154,8 @@ <xs:element name="comment" type="xs:string" /> <xs:element name="hide_in_single_store_mode" type="xs:int" /> <xs:element ref="field" /> + <xs:element ref="group" minOccurs="0" maxOccurs="unbounded"/> + <xs:element ref="depends" /> </xs:choice> </xs:sequence> @@ -201,6 +204,7 @@ <xs:element name="upload_dir" type="typeUploadDir" /> <xs:element ref="depends" /> <xs:element ref="attribute" /> + <xs:element ref="requires" /> </xs:choice> </xs:sequence> @@ -219,6 +223,78 @@ </xs:element> + <xs:element name="requires"> + <xs:annotation> + <xs:documentation> + Field Requirements + </xs:documentation> + </xs:annotation> + + <xs:complexType> + <xs:sequence> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:element type="requiresField" name="field" /> + <xs:element type="requiresGroup" name="group" /> + </xs:choice> + </xs:sequence> + </xs:complexType> + + <xs:unique name="uniqueRequiresFieldId"> + <xs:annotation> + <xs:documentation> + Attribute id is unique under field requires block + </xs:documentation> + </xs:annotation> + <xs:selector xpath=".//field"/> + <xs:field xpath="@id"/> + </xs:unique> + + <xs:unique name="uniqueRequiresGroupId"> + <xs:annotation> + <xs:documentation> + Attribute id is unique under group requires block + </xs:documentation> + </xs:annotation> + <xs:selector xpath=".//group"/> + <xs:field xpath="@id"/> + </xs:unique> + </xs:element> + + <xs:complexType name="requiresField" mixed="true"> + <xs:annotation> + <xs:documentation> + Required field resource. Recursive complex type + </xs:documentation> + </xs:annotation> + <xs:simpleContent> + <xs:extension base="xs:string"> + <xs:attribute name="id" type="typeElementPath" use="required" /> + </xs:extension> + </xs:simpleContent> + </xs:complexType> + + <xs:complexType name="requiresGroup"> + <xs:annotation> + <xs:documentation> + Required group resource. Recursive complex type + </xs:documentation> + </xs:annotation> + <xs:attribute name="id" type="typeElementPath" use="required" /> + </xs:complexType> + + <xs:simpleType name="typeElementPath"> + <xs:annotation> + <xs:documentation> + Element path attribute for elements section, group, field. + </xs:documentation> + </xs:annotation> + + <xs:restriction base="xs:string"> + <xs:pattern value="[a-zA-Z0-9_///*]{3,}" /> + <xs:minLength value="3" /> + </xs:restriction> + </xs:simpleType> + <xs:element name="attribute"> <xs:annotation> <xs:documentation> @@ -242,7 +318,7 @@ <xs:element name="depends"> <xs:annotation> <xs:documentation> - Describe which elements are regulator for current field + Describe which elements are regulator for current field/group </xs:documentation> </xs:annotation> @@ -258,7 +334,7 @@ <xs:simpleContent> <xs:extension base="xs:string"> - <xs:attribute name="id" type="typeId" use="required" /> + <xs:attribute name="id" type="typeElementPath" use="required" /> <xs:attribute name="separator" type='xs:string' use='optional' /> </xs:extension> </xs:simpleContent> @@ -359,6 +435,7 @@ <xs:pattern value="([a-zA-Z0-9_]+/{0,1}){1,}" /> </xs:restriction> </xs:simpleType> + <xs:complexType name="typeUploadDir"> <xs:annotation> <xs:documentation> @@ -378,6 +455,7 @@ <xs:minLength value="3" /> </xs:restriction> </xs:simpleType> + <xs:complexType name="typeUrl" mixed="true"> <xs:annotation> <xs:documentation> diff --git a/app/code/core/Mage/Backend/Model/Config/StructureInterface.php b/app/code/core/Mage/Backend/Model/Config/StructureInterface.php deleted file mode 100644 index 81fb81814cf22f97160d07f93d276c4d771bb1af..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Backend/Model/Config/StructureInterface.php +++ /dev/null @@ -1,80 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Backend - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - - -/** - * System configuration interface - * - * @category Mage - * @package Mage_Backend - * @author Magento Core Team <core@magentocommerce.com> - */ -interface Mage_Backend_Model_Config_StructureInterface -{ - /** - * Get all sections configuration - * - * @return array - */ - public function getSections(); - - /** - * Get section configuration - * - * @param string $sectionCode - * @param string $websiteCode - * @param string $storeCode - * @return array - */ - public function getSection($sectionCode = null, $websiteCode = null, $storeCode = null); - - /** - * Get all tabs configuration - * - * @return array - */ - public function getTabs(); - - /** - * Get translate module name - * - * @param array $section - * @param array $group - * @param array $field - * @return string - */ - public function getAttributeModule($section = null, $group = null, $field = null); - - /** - * Check whether node has child node that can be shown - * - * @param array $node - * @param string $websiteCode - * @param string $storeCode - * @return boolean - */ - public function hasChildren($node, $websiteCode = null, $storeCode = null); -} diff --git a/app/code/core/Mage/Backend/Model/Menu/Builder.php b/app/code/core/Mage/Backend/Model/Menu/Builder.php index 445f034bf2ebb56c663581074f93040f590dcd33..ebe1bdfd1594e47a9569fe4740b5fac54f3ee0ad 100644 --- a/app/code/core/Mage/Backend/Model/Menu/Builder.php +++ b/app/code/core/Mage/Backend/Model/Menu/Builder.php @@ -94,8 +94,8 @@ class Mage_Backend_Model_Menu_Builder // Build menu tree based on "parent" param foreach ($items as $id => $item) { - $sortOrder = isset($params[$id]['sortOrder']) ? $params[$id]['sortOrder'] : null; - $parentId = isset($params[$id]['parent']) ? $params[$id]['parent'] : null; + $sortOrder = $this->_getParam($params[$id], 'sortOrder'); + $parentId = $this->_getParam($params[$id], 'parent'); $isRemoved = isset($params[$id]['removed']); if ($isRemoved) { @@ -116,4 +116,17 @@ class Mage_Backend_Model_Menu_Builder return $this->_menu; } + + /** + * Retrieve param by name or default value + * + * @param array $params + * @param string $paramName + * @param mixed $defaultValue + * @return mixed + */ + protected function _getParam($params, $paramName, $defaultValue = null) + { + return isset($params[$paramName]) ? $params[$paramName] : $defaultValue; + } } diff --git a/app/code/core/Mage/Backend/Model/Menu/Item.php b/app/code/core/Mage/Backend/Model/Menu/Item.php index f9ee559c7cb79ec537ec7246d4332a2f5fd56d54..eec9eca4e50a45f8514b689e44b99107faf2ae8a 100644 --- a/app/code/core/Mage/Backend/Model/Menu/Item.php +++ b/app/code/core/Mage/Backend/Model/Menu/Item.php @@ -26,6 +26,8 @@ /** * Menu item. Should be used to create nested menu structures with Mage_Backend_Model_Menu + * + * @SuppressWarnings(PHPMD.TooManyFields) */ class Mage_Backend_Model_Menu_Item { @@ -191,11 +193,24 @@ class Mage_Backend_Model_Menu_Item $this->_id = $data['id']; $this->_title = $data['title']; - $this->_action = isset($data['action']) ? $data['action'] : null; - $this->_resource = isset($data['resource']) ? $data['resource'] : null; - $this->_dependsOnModule = isset($data['dependsOnModule']) ? $data['dependsOnModule'] : null; - $this->_dependsOnConfig = isset($data['dependsOnConfig']) ? $data['dependsOnConfig'] : null; - $this->_tooltip = isset($data['toolTip']) ? $data['toolTip'] : ''; + $this->_action = $this->_getArgument($data, 'action'); + $this->_resource = $this->_getArgument($data, 'resource'); + $this->_dependsOnModule = $this->_getArgument($data, 'dependsOnModule'); + $this->_dependsOnConfig = $this->_getArgument($data, 'dependsOnConfig'); + $this->_tooltip = $this->_getArgument($data, 'toolTip', ''); + } + + /** + * Retrieve argument element, or default value + * + * @param array $array + * @param mixed $key + * @param mixed $defaultValue + * @return mixed + */ + protected function _getArgument(array $array, $key, $defaultValue = null) + { + return isset($array[$key]) ? $array[$key] : $defaultValue; } /** diff --git a/app/code/core/Mage/Backend/Model/Url.php b/app/code/core/Mage/Backend/Model/Url.php index 65dc159ae1c9fd7e287d5319588d7cde057b7292..789f8e662a37b774a5b3d25ff1cd1f0acd937efa 100644 --- a/app/code/core/Mage/Backend/Model/Url.php +++ b/app/code/core/Mage/Backend/Model/Url.php @@ -69,38 +69,34 @@ class Mage_Backend_Model_Url extends Mage_Core_Model_Url protected $_coreSession; /** - * @var array + * Menu config + * + * @var Mage_Backend_Model_Menu_Config */ - protected $_routes; + protected $_menuConfig; - public function __construct(array $data = array()) - { + /** + * @param Mage_Backend_Helper_Data $backendHelper + * @param Mage_Core_Helper_Data $coreHelper + * @param Mage_Core_Model_Session $coreSession + * @param Mage_Core_Model_Store_Config $storeConfig + * @param Mage_Backend_Model_Menu_Config $menuConfig + * @param array $data + */ + public function __construct( + Mage_Backend_Helper_Data $backendHelper, + Mage_Core_Helper_Data $coreHelper, + Mage_Core_Model_Session $coreSession, + Mage_Core_Model_Store_Config $storeConfig, + Mage_Backend_Model_Menu_Config $menuConfig, + array $data = array() + ) { parent::__construct($data); - $this->_startupMenuItemId = isset($data['startupMenuItemId']) ? - $data['startupMenuItemId'] : - Mage::getStoreConfig(self::XML_PATH_STARTUP_MENU_ITEM); - - $this->_menu = isset($data['menu']) ? $data['menu'] : null; - - $this->_backendHelper = isset($data['backendHelper']) ? - $data['backendHelper'] : - Mage::helper('Mage_Backend_Helper_Data'); - - if (false == ($this->_backendHelper instanceof Mage_Backend_Helper_Data)) { - throw new InvalidArgumentException('Backend helper is corrupted'); - } - - $this->_coreSession = isset($data['coreSession']) ? - $data['coreSession'] : - Mage::getSingleton('Mage_Core_Model_Session'); - - $this->_coreHelper = isset($data['coreHelper']) ? - $data['coreHelper'] : - Mage::helper('Mage_Core_Helper_Data'); - - $this->_routes = isset($data['routes']) ? - $data['routes'] : - array(); + $this->_startupMenuItemId = $storeConfig->getConfig(self::XML_PATH_STARTUP_MENU_ITEM); + $this->_backendHelper = $backendHelper; + $this->_coreSession = $coreSession; + $this->_coreHelper = $coreHelper; + $this->_menuConfig = $menuConfig; } /** @@ -108,7 +104,7 @@ class Mage_Backend_Model_Url extends Mage_Core_Model_Url * * @return bool */ - public function getSecure() + public function isSecure() { if ($this->hasData('secure_is_forced')) { return $this->getData('secure'); @@ -155,14 +151,13 @@ class Mage_Backend_Model_Url extends Mage_Core_Model_Url return $result; } - $routeName = $this->getRouteName() ? $this->getRouteName() : '*'; - $controllerName = $this->getControllerName() ? $this->getControllerName() : $this->getDefaultControllerName(); - $actionName = $this->getActionName() ? $this->getActionName() : $this->getDefaultActionName(); + $routeName = $this->getRouteName('*'); + $controllerName = $this->getControllerName($this->getDefaultControllerName()); + $actionName = $this->getActionName($this->getDefaultActionName()); if ($cacheSecretKey) { $secret = array(self::SECRET_KEY_PARAM_NAME => "\${$routeName}/{$controllerName}/{$actionName}\$"); - } - else { + } else { $secret = array( self::SECRET_KEY_PARAM_NAME => $this->getSecretKey($routeName, $controllerName, $actionName) ); @@ -308,7 +303,7 @@ class Mage_Backend_Model_Url extends Mage_Core_Model_Url protected function _getMenu() { if (is_null($this->_menu)) { - $this->_menu = Mage::getSingleton('Mage_Backend_Model_Menu_Config')->getMenu(); + $this->_menu = $this->_menuConfig->getMenu(); } return $this->_menu; } diff --git a/app/code/core/Mage/Backend/controllers/Adminhtml/System/Config/SaveController.php b/app/code/core/Mage/Backend/controllers/Adminhtml/System/Config/SaveController.php new file mode 100644 index 0000000000000000000000000000000000000000..4e98bbd952c1e8304bc2e119dcd20cb84aa192ff --- /dev/null +++ b/app/code/core/Mage/Backend/controllers/Adminhtml/System/Config/SaveController.php @@ -0,0 +1,238 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_Backend + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * System Configuration Save Controller + * + * @category Mage + * @package Mage_Backend + * @author Magento Core Team <core@magentocommerce.com> + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class Mage_Backend_Adminhtml_System_Config_SaveController extends Mage_Backend_Controller_System_ConfigAbstract +{ + /** + * Backend Config Model Factory + * + * @var Mage_Backend_Model_Config_Factory + */ + protected $_configFactory; + + /** + * Core Config Model + * + * @var Mage_Core_Model_Config + */ + protected $_configModel; + + /** + * Event manager model + * + * @var Mage_Core_Model_Event_Manager + */ + protected $_eventManager; + + /** + * Application model + * + * @var Mage_Core_Model_App + */ + protected $_app; + + /** + * Constructor + * + * @param Zend_Controller_Request_Abstract $request + * @param Zend_Controller_Response_Abstract $response + * @param Magento_ObjectManager $objectManager + * @param Mage_Core_Controller_Varien_Front $frontController + * @param Mage_Core_Model_Authorization $authorization + * @param Mage_Backend_Model_Config_Structure $configStructure + * @param Mage_Core_Model_Config $configModel + * @param Mage_Backend_Model_Config_Factory $configFactory + * @param Mage_Core_Model_Event_Manager $eventManager + * @param Mage_Core_Model_App $app + * @param Mage_Backend_Model_Auth_StorageInterface $authSession + * @param array $invokeArgs + * + * @SuppressWarnings(PHPMD.ExcessiveParameterList) + */ + public function __construct(Zend_Controller_Request_Abstract $request, + Zend_Controller_Response_Abstract $response, + Magento_ObjectManager $objectManager, + Mage_Core_Controller_Varien_Front $frontController, + Mage_Core_Model_Authorization $authorization, + Mage_Backend_Model_Config_Structure $configStructure, + Mage_Core_Model_Config $configModel, + Mage_Backend_Model_Config_Factory $configFactory, + Mage_Core_Model_Event_Manager $eventManager, + Mage_Core_Model_App $app, + Mage_Backend_Model_Auth_StorageInterface $authSession, + array $invokeArgs = array() + ) { + parent::__construct($request, $response, $objectManager, $frontController, + $authorization, $configStructure, $authSession, $invokeArgs + ); + + $this->_authorization = $authorization; + $this->_configStructure = $configStructure; + $this->_configFactory = $configFactory; + $this->_eventManager = $eventManager; + $this->_app = $app; + $this->_configModel = $configModel; + } + + /** + * Save configuration + */ + public function indexAction() + { + try { + if (false == $this->_isSectionAllowed($this->getRequest()->getParam('section'))) { + throw new Exception($this->_getHelper()->__('This section is not allowed.')); + } + + // custom save logic + $this->_saveSection(); + $section = $this->getRequest()->getParam('section'); + $website = $this->getRequest()->getParam('website'); + $store = $this->getRequest()->getParam('store'); + + $configData = array( + 'section' => $section, + 'website' => $website, + 'store' => $store, + 'groups' => $this->_getGroupsForSave() + ); + /** @var Mage_Backend_Model_Config $configModel */ + $configModel = $this->_configFactory->create(array('data' => $configData)); + $configModel->save(); + + // re-init configuration + $this->_configModel->reinit(); + + $this->_eventManager->dispatch('admin_system_config_section_save_after', array( + 'website' => $website, 'store' => $store, 'section' => $section + )); + + $this->_app->reinitStores(); + + // website and store codes can be used in event implementation, so set them as well + $this->_eventManager->dispatch("admin_system_config_changed_section_{$section}", array( + 'website' => $website, 'store' => $store + )); + $this->_session->addSuccess($this->_getHelper()->__('The configuration has been saved.')); + } catch (Mage_Core_Exception $e) { + $messages = explode("\n", $e->getMessage()); + foreach ($messages as $message) { + $this->_session->addError($message); + } + } catch (Exception $e) { + $this->_session->addException($e, + $this->_getHelper()->__('An error occurred while saving this configuration:') . ' ' . $e->getMessage()); + } + + $this->_saveState($this->getRequest()->getPost('config_state')); + $this->_redirect('*/system_config/edit', array('_current' => array('section', 'website', 'store'))); + } + + /** + * Get groups for save + * + * @return array|null + */ + protected function _getGroupsForSave() + { + $groups = $this->getRequest()->getPost('groups'); + $files = $this->getRequest()->getFiles('groups'); + + if (isset($files['name']) && is_array($files['name'])) { + /** + * Carefully merge $_FILES and $_POST information + * None of '+=' or 'array_merge_recursive' can do this correct + */ + foreach ($files['name'] as $groupName => $group) { + $data = $this->_processNestedGroups($group); + if (false == empty($data)) { + $groups[$groupName] = $data; + } + } + } + return $groups; + } + + /** + * Process nested groups + * + * @param mixed $group + * @return array + */ + protected function _processNestedGroups($group) + { + $data = array(); + + if (isset($group['fields']) && is_array($group['fields'])) { + foreach ($group['fields'] as $fieldName => $field) { + if (false == empty($field['value'])) { + $data['fields'][$fieldName] = array('value' => $field['value']); + } + } + } + + if (isset($group['groups']) && is_array($group['groups'])) { + foreach ($group['groups'] as $groupName => $groupData) { + $nestedGroup = $this->_processNestedGroups($groupData); + if (false == empty($nestedGroup)) { + $data['groups'][$groupName] = $nestedGroup; + } + } + } + + return $data; + } + + /** + * Custom save logic for section + */ + protected function _saveSection() + { + $method = '_save' . uc_words($this->getRequest()->getParam('section'), ''); + if (method_exists($this, $method)) { + $this->$method(); + } + } + + /** + * Advanced save procedure + */ + protected function _saveAdvanced() + { + $this->_app->cleanCache(array('layout', Mage_Core_Model_Layout_Merge::LAYOUT_GENERAL_CACHE_TAG)); + } + + +} diff --git a/app/code/core/Mage/Backend/controllers/Adminhtml/System/ConfigController.php b/app/code/core/Mage/Backend/controllers/Adminhtml/System/ConfigController.php index 9a12507919f2bdbf484ef8e434415eb35e603550..893cd013f2153e9c4a2915d10337b3fc54aa741e 100644 --- a/app/code/core/Mage/Backend/controllers/Adminhtml/System/ConfigController.php +++ b/app/code/core/Mage/Backend/controllers/Adminhtml/System/ConfigController.php @@ -31,32 +31,8 @@ * @package Mage_Backend * @author Magento Core Team <core@magentocommerce.com> */ -class Mage_Backend_Adminhtml_System_ConfigController extends Mage_Backend_Controller_ActionAbstract +class Mage_Backend_Adminhtml_System_ConfigController extends Mage_Backend_Controller_System_ConfigAbstract { - /** - * Whether current section is allowed - * - * @var bool - */ - protected $_isSectionAllowed = true; - - /** - * Controller pre-dispatch method - * Check if current section is found and is allowed - * - * @return Mage_Backend_Adminhtml_System_ConfigController - */ - public function preDispatch() - { - parent::preDispatch(); - - if ($this->getRequest()->getParam('section')) { - $this->_isSectionAllowed = $this->_isSectionAllowed($this->getRequest()->getParam('section')); - } - - return $this; - } - /** * Index action * @@ -78,14 +54,12 @@ class Mage_Backend_Adminhtml_System_ConfigController extends Mage_Backend_Contro $website = $this->getRequest()->getParam('website'); $store = $this->getRequest()->getParam('store'); - /** @var $systemConfig Mage_Backend_Model_Config_Structure */ - $systemConfig = Mage::getSingleton('Mage_Backend_Model_Config_Structure_Reader')->getConfiguration(); - - $sections = $systemConfig->getSections($current); - $section = isset($sections[$current]) ? $sections[$current] : array(); - $hasChildren = $systemConfig->hasChildren($section, $website, $store); - if (!$hasChildren && $current) { - $this->_redirect('*/*/', array('website'=>$website, 'store'=>$store)); + /** @var $configStructure Mage_Backend_Model_Config_Structure */ + $configStructure = Mage::getSingleton('Mage_Backend_Model_Config_Structure'); + /** @var $section Mage_Backend_Model_Config_Structure_Element_Section */ + $section = $configStructure->getElement($current); + if ($current && !$section->isVisible($website, $store)) { + return $this->_redirect('*/*/', array('website' => $website, 'store' => $store)); } $this->loadLayout(); @@ -96,120 +70,10 @@ class Mage_Backend_Adminhtml_System_ConfigController extends Mage_Backend_Contro $this->_addBreadcrumb( Mage::helper('Mage_Backend_Helper_Data')->__('System'), Mage::helper('Mage_Backend_Helper_Data')->__('System'), - $this->getUrl('*/system') + $this->getUrl('*\/system') ); - $this->getLayout()->addBlock('Mage_Backend_Block_System_Config_Tabs', '', 'left')->initTabs(); - - if ($this->_isSectionAllowed) { - $this->_addContent($this->getLayout()->createBlock('Mage_Backend_Block_System_Config_Edit')->initForm()); - - $this->_addJs($this->getLayout() - ->createBlock('Mage_Backend_Block_Template') - ->setTemplate('Mage_Adminhtml::system/shipping/ups.phtml')); - $this->_addJs($this->getLayout() - ->createBlock('Mage_Backend_Block_Template') - ->setTemplate('system/config/js.phtml')); - $this->_addJs($this->getLayout() - ->createBlock('Mage_Backend_Block_Template') - ->setTemplate('Mage_Adminhtml::system/shipping/applicable_country.phtml')); - - $this->renderLayout(); - } - } - - /** - * Save configuration - */ - public function saveAction() - { - /* @var $session Mage_Adminhtml_Model_Session */ - $session = Mage::getSingleton('Mage_Backend_Model_Session'); - - try { - if (!$this->_isSectionAllowed($this->getRequest()->getParam('section'))) { - throw new Exception(Mage::helper('Mage_Backend_Helper_Data')->__('This section is not allowed.')); - } - - // custom save logic - $this->_saveSection(); - $section = $this->getRequest()->getParam('section'); - $website = $this->getRequest()->getParam('website'); - $store = $this->getRequest()->getParam('store'); - Mage::getModel('Mage_Backend_Model_Config')->setSection($section)->setWebsite($website) - ->setStore($store)->setGroups($this->_getGroupsForSave())->save(); - - // re-init configuration - Mage::getConfig()->reinit(); - Mage::dispatchEvent('admin_system_config_section_save_after', array( - 'website' => $website, 'store' => $store, 'section' => $section - )); - Mage::app()->reinitStores(); - - // website and store codes can be used in event implementation, so set them as well - Mage::dispatchEvent("admin_system_config_changed_section_{$section}", array( - 'website' => $website, 'store' => $store - )); - $session->addSuccess(Mage::helper('Mage_Backend_Helper_Data')->__('The configuration has been saved.')); - } catch (Mage_Core_Exception $e) { - $messages = explode("\n", $e->getMessage()); - array_walk($messages, create_function( - '$message', 'Mage::getSingleton(\'Mage_Backend_Model_Session\')->addError($message);' - )); - } catch (Exception $e) { - $session->addException($e, - Mage::helper('Mage_Backend_Helper_Data')->__('An error occurred while saving this configuration:') - . ' ' . $e->getMessage()); - } - - $this->_saveState($this->getRequest()->getPost('config_state')); - $this->_redirect('*/*/edit', array('_current' => array('section', 'website', 'store'))); - } - - /** - * Get groups for save - * - * @return array|null - */ - protected function _getGroupsForSave() - { - $groups = $this->getRequest()->getPost('groups'); - - if (isset($_FILES['groups']['name']) && is_array($_FILES['groups']['name'])) { - /** - * Carefully merge $_FILES and $_POST information - * None of '+=' or 'array_merge_recursive' can do this correct - */ - foreach ($_FILES['groups']['name'] as $groupName => $group) { - if (is_array($group)) { - foreach ($group['fields'] as $fieldName => $field) { - if (!empty($field['value'])) { - $groups[$groupName]['fields'][$fieldName] = array('value' => $field['value']); - } - } - } - } - } - return $groups; - } - - /** - * Custom save logic for section - */ - protected function _saveSection() - { - $method = '_save' . uc_words($this->getRequest()->getParam('section'), ''); - if (method_exists($this, $method)) { - $this->$method(); - } - } - - /** - * Advanced save procedure - */ - protected function _saveAdvanced() - { - Mage::app()->cleanCache(array('layout', Mage_Core_Model_Layout_Merge::LAYOUT_GENERAL_CACHE_TAG)); + $this->renderLayout(); } /** @@ -217,7 +81,7 @@ class Mage_Backend_Adminhtml_System_ConfigController extends Mage_Backend_Contro */ public function stateAction() { - if ($this->getRequest()->getParam('isAjax') == 1 && $this->getRequest()->getParam('container') != '' + if ($this->getRequest()->getParam('isAjax') && $this->getRequest()->getParam('container') != '' && $this->getRequest()->getParam('value') != '' ) { $configState = array( @@ -246,70 +110,4 @@ class Mage_Backend_Adminhtml_System_ConfigController extends Mage_Backend_Contro $content = $gridBlock->getCsvFile(); $this->_prepareDownloadResponse($fileName, $content); } - - /** - * Check is allow modify system configuration - * - * @return bool - */ - protected function _isAllowed() - { - return Mage::getSingleton('Mage_Core_Model_Authorization')->isAllowed('Mage_Adminhtml::config'); - } - - /** - * Check if specified section allowed in ACL - * - * Will forward to deniedAction(), if not allowed. - * - * @param string $section - * @throws Exception - * @return bool - */ - protected function _isSectionAllowed($section) - { - try { - $section = Mage::getSingleton('Mage_Backend_Model_Config_Structure_Reader') - ->getConfiguration() - ->getSection($section); - if (!Mage::getSingleton('Mage_Core_Model_Authorization')->isAllowed($section['resource'])) { - throw new Exception(''); - } - return true; - } catch (Zend_Acl_Exception $e) { - $this->norouteAction(); - $this->setFlag('', self::FLAG_NO_DISPATCH, true); - return false; - } catch (Exception $e) { - $this->deniedAction(); - $this->setFlag('', self::FLAG_NO_DISPATCH, true); - return false; - } - } - - /** - * Save state of configuration field sets - * - * @param array $configState - * @return bool - */ - protected function _saveState($configState = array()) - { - $adminUser = Mage::getSingleton('Mage_Backend_Model_Auth_Session')->getUser(); - if (is_array($configState)) { - $extra = $adminUser->getExtra(); - if (!is_array($extra)) { - $extra = array(); - } - if (!isset($extra['configState'])) { - $extra['configState'] = array(); - } - foreach ($configState as $fieldset => $state) { - $extra['configState'][$fieldset] = $state; - } - $adminUser->saveExtra($extra); - } - - return true; - } } diff --git a/app/code/core/Mage/Core/etc/adminhtml/system.xml b/app/code/core/Mage/Backend/etc/adminhtml/system.xml similarity index 94% rename from app/code/core/Mage/Core/etc/adminhtml/system.xml rename to app/code/core/Mage/Backend/etc/adminhtml/system.xml index 72bc05690df87769c4d38e4c8cc26b1cc572f945..df592ae623a42ce6c54cb19e2d6b2e489cf564ad 100644 --- a/app/code/core/Mage/Core/etc/adminhtml/system.xml +++ b/app/code/core/Mage/Backend/etc/adminhtml/system.xml @@ -20,23 +20,23 @@ * needs please refer to http://www.magentocommerce.com for more information. * * @category Mage - * @package Mage_Core + * @package Mage_Backend * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) */ --> <config> <system> - <tab id="general" translate="label" module="Mage_Core" sortOrder="100"> + <tab id="general" translate="label" module="Mage_Backend" sortOrder="100"> <label>General</label> </tab> - <tab id="service" translate="label" module="Mage_Core" sortOrder="99999"> + <tab id="service" translate="label" module="Mage_Backend" sortOrder="99999"> <label>Services</label> </tab> - <tab id="advanced" translate="label" module="Mage_Core" sortOrder="999999"> + <tab id="advanced" translate="label" module="Mage_Backend" sortOrder="999999"> <label>Advanced</label> </tab> - <section id="advanced" translate="label" module="Mage_Core" type="text" sortOrder="910" showInDefault="1" showInWebsite="1" showInStore="1"> + <section id="advanced" translate="label" module="Mage_Backend" type="text" sortOrder="910" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Advanced</label> <tab>advanced</tab> <resource>Mage_Adminhtml::advanced</resource> @@ -45,7 +45,7 @@ <frontend_model>Mage_Backend_Block_System_Config_Form_Fieldset_Modules_DisableOutput</frontend_model> </group> </section> - <section id="trans_email" translate="label" module="Mage_Core" type="text" sortOrder="90" showInDefault="1" showInWebsite="1" showInStore="1"> + <section id="trans_email" translate="label" module="Mage_Backend" type="text" sortOrder="90" showInDefault="1" showInWebsite="1" showInStore="1"> <class>separator-top</class> <label>Store Email Addresses</label> <tab>general</tab> @@ -116,7 +116,7 @@ </field> </group> </section> - <section id="design" translate="label" module="Mage_Core" type="text" sortOrder="30" showInDefault="1" showInWebsite="1" showInStore="1"> + <section id="design" translate="label" module="Mage_Backend" type="text" sortOrder="30" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Design</label> <tab>general</tab> <resource>Mage_Adminhtml::config_design</resource> @@ -169,7 +169,7 @@ </field> </group> </section> - <section id="dev" translate="label" module="Mage_Core" type="text" sortOrder="920" showInDefault="1" showInWebsite="1" showInStore="1"> + <section id="dev" translate="label" module="Mage_Backend" type="text" sortOrder="920" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Developer</label> <tab>advanced</tab> <resource>Mage_Adminhtml::dev</resource> @@ -180,7 +180,7 @@ <comment>Leave empty for access from any location.</comment> </field> </group> - <group id="debug" translate="label" type="text" sortOrder="20" showInDefault="1" showInWebsite="1" showInStore="1"> + <group id="debug" translate="label" type="text" sortOrder="20" showInDefault="0" showInWebsite="1" showInStore="1"> <label>Debug</label> <field id="template_hints" translate="label" type="select" sortOrder="20" showInDefault="0" showInWebsite="1" showInStore="1"> <label>Template Path Hints</label> @@ -261,7 +261,7 @@ </field> </group> </section> - <section id="general" translate="label" module="Mage_Core" type="text" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1"> + <section id="general" translate="label" module="Mage_Backend" type="text" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1"> <label>General</label> <tab>general</tab> <resource>Mage_Adminhtml::config_general</resource> @@ -332,7 +332,7 @@ </field> </group> </section> - <section id="system" translate="label" module="Mage_Core" type="text" sortOrder="900" showInDefault="1" showInWebsite="1" showInStore="1"> + <section id="system" translate="label" module="Mage_Backend" type="text" sortOrder="900" showInDefault="1" showInWebsite="1" showInStore="1"> <class>separator-top</class> <label>System</label> <tab>advanced</tab> @@ -364,7 +364,7 @@ </depends> </field> </group> - <group id="media_storage_configuration" translate="label" module="Mage_Core" type="text" sortOrder="900" showInDefault="1" showInWebsite="1" showInStore="1"> + <group id="media_storage_configuration" translate="label" module="Mage_Backend" type="text" sortOrder="900" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Storage Configuration for Media</label> <field id="media_storage" translate="label" type="select" sortOrder="100" showInDefault="1" showInWebsite="0" showInStore="0"> <label>Media Storage</label> @@ -387,7 +387,7 @@ </field> </group> </section> - <section id="admin" translate="label" module="Mage_Core" type="text" sortOrder="20" showInDefault="1" showInWebsite="0" showInStore="0"> + <section id="admin" translate="label" module="Mage_Backend" type="text" sortOrder="20" showInDefault="1" showInWebsite="0" showInStore="0"> <label>Admin</label> <tab>advanced</tab> <resource>Mage_Adminhtml::config_admin</resource> @@ -470,11 +470,11 @@ </field> </group> </section> - <section id="web" translate="label" module="Mage_Core" type="text" sortOrder="20" showInDefault="1" showInWebsite="1" showInStore="1"> + <section id="web" translate="label" module="Mage_Backend" type="text" sortOrder="20" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Web</label> <tab>general</tab> <resource>Mage_Adminhtml::web</resource> - <group id="url" translate="label" type="text" sortOrder="3" showInDefault="1" showInWebsite="1" showInStore="1"> + <group id="url" translate="label" type="text" sortOrder="3" showInDefault="1" showInWebsite="0" showInStore="0"> <label>Url Options</label> <field id="use_store" translate="label comment" type="select" sortOrder="10" showInDefault="1" showInWebsite="0" showInStore="0"> <label>Add Store Code to Urls</label> @@ -609,17 +609,6 @@ <source_model>Mage_Backend_Model_Config_Source_Yesno</source_model> </field> </group> - <group id="browser_capabilities" translate="label" type="text" sortOrder="200" showInDefault="1" showInWebsite="1" showInStore="1"> - <label>Browser Capabilities Detection</label> - <field id="cookies" translate="label" module="Mage_Cms" type="select" sortOrder="100" showInDefault="1" showInWebsite="1" showInStore="1"> - <label>Redirect to CMS-page if Cookies are Disabled</label> - <source_model>Mage_Backend_Model_Config_Source_Yesno</source_model> - </field> - <field id="javascript" translate="label" module="Mage_Cms" type="select" sortOrder="200" showInDefault="1" showInWebsite="1" showInStore="1"> - <label>Show Notice if JavaScript is Disabled</label> - <source_model>Mage_Backend_Model_Config_Source_Yesno</source_model> - </field> - </group> </section> </system> </config> diff --git a/app/code/core/Mage/Backend/etc/config.xml b/app/code/core/Mage/Backend/etc/config.xml index 1b78040696f99ae60963f07cf512a5c83497df35..7f78be87752c7ce4e13c3c3fda98cb387258c6f9 100644 --- a/app/code/core/Mage/Backend/etc/config.xml +++ b/app/code/core/Mage/Backend/etc/config.xml @@ -74,7 +74,50 @@ <di> <preferences> <Mage_Backend_Model_Auth_StorageInterface>Mage_Backend_Model_Auth_Session</Mage_Backend_Model_Auth_StorageInterface> + <Mage_Backend_Model_Config_Structure_SearchInterface>Mage_Backend_Model_Config_Structure</Mage_Backend_Model_Config_Structure_SearchInterface> </preferences> + <Mage_Backend_Model_Config_Structure_Element_Iterator_Tab> + <shared>0</shared> + </Mage_Backend_Model_Config_Structure_Element_Iterator_Tab> + <Mage_Backend_Model_Config_Structure_Element_Iterator_Section> + <shared>0</shared> + </Mage_Backend_Model_Config_Structure_Element_Iterator_Section> + <Mage_Backend_Model_Config_Structure_Element_Iterator_Group> + <shared>0</shared> + </Mage_Backend_Model_Config_Structure_Element_Iterator_Group> + <Mage_Backend_Model_Config_Structure_Element_Iterator_Field> + <parameters> + <groupFlyweight>Mage_Backend_Model_Config_Structure_Element_Group_Proxy</groupFlyweight> + </parameters> + <shared>0</shared> + </Mage_Backend_Model_Config_Structure_Element_Iterator_Field> + <Mage_Backend_Model_Config_Structure_Element_Dependency_Mapper> + <parameters> + <fieldLocator>Mage_Backend_Model_Config_Structure_Search_Proxy</fieldLocator> + </parameters> + <shared>0</shared> + </Mage_Backend_Model_Config_Structure_Element_Dependency_Mapper> + <Mage_Backend_Model_Config_Structure_Element_Tab> + <parameters> + <childrenIterator>Mage_Backend_Model_Config_Structure_Element_Iterator_Section</childrenIterator> + </parameters> + <shared>0</shared> + </Mage_Backend_Model_Config_Structure_Element_Tab> + <Mage_Backend_Model_Config_Structure_Element_Section> + <parameters> + <childrenIterator>Mage_Backend_Model_Config_Structure_Element_Iterator_Group</childrenIterator> + </parameters> + <shared>0</shared> + </Mage_Backend_Model_Config_Structure_Element_Section> + <Mage_Backend_Model_Config_Structure_Element_Group> + <parameters> + <childrenIterator>Mage_Backend_Model_Config_Structure_Element_Iterator_Field</childrenIterator> + </parameters> + <shared>0</shared> + </Mage_Backend_Model_Config_Structure_Element_Group> + <Mage_Backend_Model_Config_Structure_Element_Group_Proxy> + <shared>0</shared> + </Mage_Backend_Model_Config_Structure_Element_Group_Proxy> </di> </global> <admin> diff --git a/app/code/core/Mage/Backend/view/adminhtml/layout.xml b/app/code/core/Mage/Backend/view/adminhtml/layout.xml index 02a4a157f1543cba7872b5bc7906c0b8aaf4f6aa..898b5120d7b40437a8fc44daad68df66747940ad 100644 --- a/app/code/core/Mage/Backend/view/adminhtml/layout.xml +++ b/app/code/core/Mage/Backend/view/adminhtml/layout.xml @@ -44,8 +44,17 @@ </adminhtml_auth_login> <adminhtml_system_config_edit> + <reference name="js"> + <block type="Mage_Backend_Block_Template" template="Mage_Adminhtml::system/shipping/ups.phtml"/> + <block type="Mage_Backend_Block_Template" template="system/config/js.phtml"/> + <block type="Mage_Backend_Block_Template" template="Mage_Adminhtml::system/shipping/applicable_country.phtml"/> + </reference> <reference name="left"> + <block type="Mage_Backend_Block_System_Config_Tabs" name="adminhtml.system.config.tabs" before="-"/> <block type="Mage_Backend_Block_System_Config_Switcher" name="adminhtml.system.config.switcher" before="-"/> </reference> + <reference name="content"> + <block type="Mage_Backend_Block_System_Config_Edit" /> + </reference> </adminhtml_system_config_edit> </layout> diff --git a/app/code/core/Mage/Backend/view/adminhtml/store/switcher.phtml b/app/code/core/Mage/Backend/view/adminhtml/store/switcher.phtml index a4fbe6fb0823a4928cbc70db3c3f60cb8991b2c4..a5d5418bbc59aa3e6ce8b5a8f35b69ac7d5e1d85 100644 --- a/app/code/core/Mage/Backend/view/adminhtml/store/switcher.phtml +++ b/app/code/core/Mage/Backend/view/adminhtml/store/switcher.phtml @@ -44,7 +44,7 @@ <?php $showGroup = true; ?> <optgroup label=" <?php echo $this->escapeHtml($group->getName()) ?>"> <?php endif; ?> - <option value="<?php echo $this->escapeHtml($store->getId()) ?>"<?php if($this->getStoreId() == $store->getId()): ?> selected="selected"<?php endif; ?>> <?php echo $this->escapeHtml($store->getName()) ?></option> + <option value="<?php echo $this->escapeHtml($store->getId()) ?>"<?php if ($this->getStoreId() == $store->getId()): ?> selected="selected"<?php endif; ?>> <?php echo $this->escapeHtml($store->getName()) ?></option> <?php endforeach; ?> <?php if ($showGroup): ?> </optgroup> diff --git a/app/code/core/Mage/Backend/view/adminhtml/store/switcher/form/renderer/fieldset/element.phtml b/app/code/core/Mage/Backend/view/adminhtml/store/switcher/form/renderer/fieldset/element.phtml index f82a865ecbf86089151895e1f9be0c45fb0a0d76..e124bde16a9dbed524d2234b6b724cf4e2b0f150 100644 --- a/app/code/core/Mage/Backend/view/adminhtml/store/switcher/form/renderer/fieldset/element.phtml +++ b/app/code/core/Mage/Backend/view/adminhtml/store/switcher/form/renderer/fieldset/element.phtml @@ -31,7 +31,7 @@ $_trId = $_element->getHtmlContainerId(); $_class = $_element->getFieldsetHtmlClass(); ?> <?php if (!$_element->getNoDisplay()): ?> -<tr<?php if($_trId): ?> id="<?php echo $_trId ?>"<?php endif; ?>> +<tr<?php if ($_trId): ?> id="<?php echo $_trId ?>"<?php endif; ?>> <?php if ($_element->getType()=='hidden'): ?> <td colspan="2" class="hidden"><?php echo trim($_element->getElementHtml()) ?></td> <?php else: ?> diff --git a/app/code/core/Mage/Backend/view/adminhtml/system/config/edit.phtml b/app/code/core/Mage/Backend/view/adminhtml/system/config/edit.phtml index 207beea1733784f972e841ab3dd080ffcfe3965e..2641dc84d38a3b129ce3d9d047e3db228f3d15e8 100644 --- a/app/code/core/Mage/Backend/view/adminhtml/system/config/edit.phtml +++ b/app/code/core/Mage/Backend/view/adminhtml/system/config/edit.phtml @@ -38,7 +38,7 @@ <table cellspacing="0"> <tr> <td> - <h3<?php if($this->getHeaderCss()): ?> class="<?php echo $this->getHeaderCss()?>"<?php endif; ?>><?php echo Mage::helper('Mage_Backend_Helper_Data')->__($this->getTitle()) ?></h3> + <h3<?php if ($this->getHeaderCss()): ?> class="<?php echo $this->getHeaderCss()?>"<?php endif; ?>><?php echo Mage::helper('Mage_Backend_Helper_Data')->__($this->getTitle()) ?></h3> </td> <td class="form-buttons"><?php echo $this->getSaveButtonHtml() ?></td> </tr> diff --git a/app/code/core/Mage/Backend/view/adminhtml/system/config/js.phtml b/app/code/core/Mage/Backend/view/adminhtml/system/config/js.phtml index 2d64ba3a638cf961b5e1fdc173289a6516cde65f..9e6668669c792f97ecb6350882eb7ce8b204da3e 100644 --- a/app/code/core/Mage/Backend/view/adminhtml/system/config/js.phtml +++ b/app/code/core/Mage/Backend/view/adminhtml/system/config/js.phtml @@ -35,7 +35,7 @@ freeModel.prototype = { }, bindFreeMethodCutoffCostRelation : function(parentId) { - if(parentId) { + if (parentId) { // todo: fix bug in IE var freeMethodElements = $$('#'+parentId+' .free-method'); } else { @@ -91,7 +91,7 @@ originModel.prototype = { }, bindCountryRegionRelation : function(parentId) { - if(parentId) { + if (parentId) { // todo: fix bug in IE var countryElements = $$('#'+parentId+' .countries'); } else { @@ -154,9 +154,9 @@ originModel.prototype = { if (data.length) { var html = '<select name="'+this.regionElement.name+'" id="'+this.regionElement.id+'" class="required-entry select" title="'+this.regionElement.title+'"'+(disabled?" disabled":"")+'>'; for (var i in data) { - if(data[i].label) { + if (data[i].label) { html+= '<option value="'+data[i].value+'"'; - if(this.regionElement.value && (this.regionElement.value == data[i].value || this.regionElement.value == data[i].label)) { + if (this.regionElement.value && (this.regionElement.value == data[i].value || this.regionElement.value == data[i].label)) { html+= ' selected'; } html+='>'+data[i].label+'<\/option>'; @@ -215,15 +215,13 @@ perPageModel.prototype = { this.gridElement.up(1).show(); this.gridValuesElement.up(1).show(); - } - else if (this.listModeElement.value == 'grid-list' || this.listModeElement.value == 'list-grid') { + } else if (this.listModeElement.value == 'grid-list' || this.listModeElement.value == 'list-grid') { this.listElement.up(1).show(); this.listValuesElement.up(1).show(); this.gridElement.up(1).show(); this.gridValuesElement.up(1).show(); - } - else if (this.listModeElement.value == 'list') { + } else if (this.listModeElement.value == 'list') { this.listElement.up(1).show(); this.listValuesElement.up(1).show(); diff --git a/app/code/core/Mage/Backend/view/adminhtml/system/config/tabs.phtml b/app/code/core/Mage/Backend/view/adminhtml/system/config/tabs.phtml index f41e4524cb8e18e874bd5a9f9f7e9c3195753f62..a876246605664873d16bb00f0543cf28320544cf 100644 --- a/app/code/core/Mage/Backend/view/adminhtml/system/config/tabs.phtml +++ b/app/code/core/Mage/Backend/view/adminhtml/system/config/tabs.phtml @@ -23,22 +23,28 @@ * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) */ + +/** @var $this Mage_Backend_Block_System_Config_Tabs */ ?> -<?php if($this->getTitle()): ?> +<?php if ($this->getTitle()): ?> <h3><?php echo $this->getTitle() ?></h3> <?php endif ?> -<?php if($this->getTabs()): ?> +<?php if ($this->getTabs()): ?> <ul id="<?php echo $this->getId() ?>" class="tabs config-tabs"> -<?php foreach ($this->getTabs() as $_tab): ?> - <?php if($_tab->getSections()): ?> + <?php + /** @var $_tab Mage_Backend_Model_Config_Structure_Element_Tab */ + foreach ($this->getTabs() as $_tab): + ?> <li <?php if ($_tab->getClass()): ?>class="<?php echo $_tab->getClass() ?>"<?php endif ?>> <dl> <dt class="label" style=""><?php echo $_tab->getLabel() ?></dt> <?php $_iterator = 1; ?> - <?php foreach ($_tab->getSections() as $_section): ?> + <?php + /** @var $_section Mage_Backend_Model_Config_Structure_Element_Section */ + foreach ($_tab->getChildren() as $_section): ?> <dd> - <a href="<?php echo $_section->getUrl() ?>" class="<?php echo $_section->getClass() ?><?php if($_section->getId()==$this->getActiveSection()): ?> active<?php endif ?> <?php echo $_section->getIsLast()?'last':'' ?>"> - <span <?php if($_tab->getId()==$this->getActiveTab()): ?>class="active"<?php endif ?>> + <a href="<?php echo $this->getSectionUrl($_section) ?>" class="<?php echo $_section->getClass() ?><?php if ($this->isSectionActive($_section)): ?> active<?php endif ?> <?php echo $_tab->getChildren()->isLast($_section) ? 'last' : '' ?>"> + <span> <?php echo $_section->getLabel() ?> </span> </a> @@ -47,7 +53,8 @@ <?php endforeach; ?> </dl> </li> - <?php endif; ?> -<?php endforeach; ?> + <?php + endforeach; + ?> </ul> <?php endif; ?> diff --git a/app/code/core/Mage/Backend/view/adminhtml/widget/breadcrumbs.phtml b/app/code/core/Mage/Backend/view/adminhtml/widget/breadcrumbs.phtml index 9311a81f6e0fb010ce16552d6aa5fde4af012a5c..6f48e7097f6b0db9beb8c9b9ecbf938bf9d142e4 100644 --- a/app/code/core/Mage/Backend/view/adminhtml/widget/breadcrumbs.phtml +++ b/app/code/core/Mage/Backend/view/adminhtml/widget/breadcrumbs.phtml @@ -24,13 +24,13 @@ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) */ ?> -<?php if(!empty($links)): ?> +<?php if (!empty($links)): ?> <ul class="breadcrumbs"> <?php $_size=count($links); ?> <?php foreach ($links as $_index=>$_link): ?> <li> - <?php if(empty($_link['url'])): ?> - <?php if($_index!=$_size-1): ?> + <?php if (empty($_link['url'])): ?> + <?php if ($_index!=$_size-1): ?> <span><?php echo $this->escapeHtml($_link['label']) ?></span> <?php else: ?> <strong><?php echo $this->escapeHtml($_link['label']) ?></strong> @@ -38,7 +38,7 @@ <?php else: ?> <a href="<?php echo $_link['url'] ?>" title="<?php echo $this->escapeHtml($_link['title']) ?>"><?php echo $this->escapeHtml($_link['label']) ?></a> <?php endif; ?> - <?php if($_index!=$_size-1): ?> + <?php if ($_index!=$_size-1): ?> » <?php endif; ?> </li> diff --git a/app/code/core/Mage/Backend/view/adminhtml/widget/button/split.phtml b/app/code/core/Mage/Backend/view/adminhtml/widget/button/split.phtml index 5319806164629b1638a764d3853bcfeb22cfa49e..420cdc2c8a8c1a947e4440baf7549b5043b2a47e 100644 --- a/app/code/core/Mage/Backend/view/adminhtml/widget/button/split.phtml +++ b/app/code/core/Mage/Backend/view/adminhtml/widget/button/split.phtml @@ -37,10 +37,10 @@ <ul class="dropdown-menu" <?php echo $this->getUiId("dropdown-menu"); ?>> <?php foreach ($this->getOptions() as $key => $option): ?> <li> - <span class="item<?php if($option['default']):?> item-default<?php endif; ?>" onclick="<?php echo $option['onclick']?>", <?php echo $this->getUiId("item", $key)?>> + <span class="item<?php if ($option['default']):?> item-default<?php endif; ?>" onclick="<?php echo $option['onclick']?>", <?php echo $this->getUiId("item", $key)?>> <?php echo $option['label']?> </span> - <?php if(isset($option['hint'])): ?> + <?php if (isset($option['hint'])): ?> <div class="tooltip" <?php echo $this->getUiId("item", $key, "tooltip"); ?>> <a href="<?php echo $option['hint']['href'] ?>" class="help"><?php echo $option['hint']['label'] ?></a> </div> diff --git a/app/code/core/Mage/Backend/view/adminhtml/widget/form/element.phtml b/app/code/core/Mage/Backend/view/adminhtml/widget/form/element.phtml index c54aac0ef899416051178e78be4c0315b1709687..fce64d22a98abd140bbe3570ada4c6be58c14996 100644 --- a/app/code/core/Mage/Backend/view/adminhtml/widget/form/element.phtml +++ b/app/code/core/Mage/Backend/view/adminhtml/widget/form/element.phtml @@ -42,10 +42,10 @@ <?php break; case 'select': ?> <span class="form_row"> - <?php if($element->getLabel()): ?><label for="<?php echo $element->getHtmlId() ?>"><?php echo $element->getLabel() ?>:</label><?php endif; ?> + <?php if ($element->getLabel()): ?><label for="<?php echo $element->getHtmlId() ?>"><?php echo $element->getLabel() ?>:</label><?php endif; ?> <select name="<?php echo $element->getName() ?>" id="<?php echo $element->getHtmlId() ?>" class="select<?php echo $element->getClass() ?>" title="<?php echo $element->getTitle() ?>"> <?php foreach ($element->getValues() as $_value): ?> - <option <?php echo $_value->serialize() ?><?php if($_value->getValue() == $element->getValue()): ?> selected="selected"<?php endif; ?>><?php echo $_value->getLabel() ?></option> + <option <?php echo $_value->serialize() ?><?php if ($_value->getValue() == $element->getValue()): ?> selected="selected"<?php endif; ?>><?php echo $_value->getLabel() ?></option> <?php endforeach; ?> </select> </span> @@ -54,13 +54,13 @@ case 'button': case 'password': ?> <span class="form_row"> - <?php if($element->getLabel()): ?><label for="<?php echo $element->getHtmlId() ?>" <?php echo $this->getUiId('label') ?>><?php echo $element->getLabel() ?>:</label><?php endif; ?> + <?php if ($element->getLabel()): ?><label for="<?php echo $element->getHtmlId() ?>" <?php echo $this->getUiId('label') ?>><?php echo $element->getLabel() ?>:</label><?php endif; ?> <input type="<?php echo $element->getType() ?>" name="<?php echo $element->getName() ?>" id="<?php echo $element->getHtmlId() ?>" value="<?php echo $element->getValue() ?>" class="input-text <?php echo $element->getClass() ?>" title="<?php echo $element->getTitle() ?>" <?php echo ( $element->getOnClick() ? 'onClick="'.$element->getOnClick().'"' : '' ) ?>/> </span> <?php break; case 'radio': ?> <span class="form_row"> - <?php if($element->getLabel()): ?><label for="<?php echo $element->getHtmlId() ?>"><?php echo $element->getLabel() ?>:</label><?php endif; ?> + <?php if ($element->getLabel()): ?><label for="<?php echo $element->getHtmlId() ?>"><?php echo $element->getLabel() ?>:</label><?php endif; ?> <input type="<?php echo $element->getType() ?>" name="<?php echo $element->getName() ?>" id="<?php echo $element->getHtmlId() ?>" value="<?php echo $element->getValue() ?>" class="input-text <?php echo $element->getClass() ?>" title="<?php echo $element->getTitle() ?>"/> </span> <?php break; @@ -70,7 +70,7 @@ case 'radios': ?> <span class="form_row"> <label for="<?php echo $element->getHtmlId() ?>"><?php echo $element->getLabel() ?>:</label> - <?php foreach($element->getRadios() as $_radio): ?> + <?php foreach ($element->getRadios() as $_radio): ?> <input type="radio" name="<?php echo $_radio->getName() ?>" id="<?php echo $_radio->getHtmlId() ?>" value="<?php echo $_radio->getValue() ?>" class="input-radio <?php echo $_radio->getClass() ?>" title="<?php echo $_radio->getTitle() ?>" <?php echo ( $_radio->getValue() == $element->getChecked() ) ? 'checked="true"' : '' ?> > <?php echo $_radio->getLabel() ?> <?php endforeach; ?> </span> @@ -120,7 +120,7 @@ case 'checkbox': ?> <?php break; } ?> -<?php if($element->getScript()): ?> +<?php if ($element->getScript()): ?> <script type="text/javascript"> <?php echo $element->getScript() ?> </script> diff --git a/app/code/core/Mage/Backend/view/adminhtml/widget/form/element/gallery.phtml b/app/code/core/Mage/Backend/view/adminhtml/widget/form/element/gallery.phtml index 0d11070a573ab76fed8765cc92f5bd35e6904dfa..e25dac5732e92842309051aab56ecf0d4751e855 100644 --- a/app/code/core/Mage/Backend/view/adminhtml/widget/form/element/gallery.phtml +++ b/app/code/core/Mage/Backend/view/adminhtml/widget/form/element/gallery.phtml @@ -110,11 +110,9 @@ function addNewImage() if (j==2) { newCell.appendChild( new_row_input ); - } - else if (j==3) { + } else if (j==3) { newCell.innerHTML = new_row_button; - } - else { + } else { newCell.innerHTML = new_file_input.replace(/%j%/g, j).replace(/%id%/g, id); } @@ -131,8 +129,7 @@ function deleteImage(image) if (image>0) { document.getElementById('<?php echo $this->getElement()->getName() ?>_delete_'+image).value=image; document.getElementById('<?php echo $this->getElement()->getName() ?>_tr_'+image).style.display='none'; - } - else { + } else { image.parentNode.parentNode.parentNode.removeChild( image.parentNode.parentNode ); } } diff --git a/app/code/core/Mage/Backend/view/adminhtml/widget/form/renderer/element.phtml b/app/code/core/Mage/Backend/view/adminhtml/widget/form/renderer/element.phtml index 0ae8d4d52c5593b18efc4b40882f6b3477d6b85c..207c64474e82e4e5ed6246b1c1df6a02f82353fc 100644 --- a/app/code/core/Mage/Backend/view/adminhtml/widget/form/renderer/element.phtml +++ b/app/code/core/Mage/Backend/view/adminhtml/widget/form/renderer/element.phtml @@ -25,11 +25,11 @@ */ ?> <?php $_element = $this->getElement() ?> -<?php if($_element->getNoSpan() !== true): ?> +<?php if ($_element->getNoSpan() !== true): ?> <span class="field-row"> <?php endif; ?> <?php echo $_element->getLabelHtml() ?> <?php echo $_element->getElementHtml() ?> -<?php if($_element->getNoSpan() !== true): ?> +<?php if ($_element->getNoSpan() !== true): ?> </span> <?php endif; ?> diff --git a/app/code/core/Mage/Backend/view/adminhtml/widget/form/renderer/fieldset/element.phtml b/app/code/core/Mage/Backend/view/adminhtml/widget/form/renderer/fieldset/element.phtml index 15d1e2c0ac9ff23f3036785f001979a28a3a1b2e..89685bc56595abf698731afb8c959952c66051cb 100644 --- a/app/code/core/Mage/Backend/view/adminhtml/widget/form/renderer/fieldset/element.phtml +++ b/app/code/core/Mage/Backend/view/adminhtml/widget/form/renderer/fieldset/element.phtml @@ -32,7 +32,7 @@ $_trId = $_element->getHtmlContainerId(); $_class = $_element->getFieldsetHtmlClass(); ?> <?php if (!$_element->getNoDisplay()): ?> -<tr<?php if($_trId): ?> id="<?php echo $_trId ?>"<?php endif; ?> <?php echo $this->getUiId('form-row',$_element->getId()) ?>> +<tr<?php if ($_trId): ?> id="<?php echo $_trId ?>"<?php endif; ?> <?php echo $this->getUiId('form-row',$_element->getId()) ?>> <?php if ($_element->getType()=='hidden'): ?> <td colspan="2" class="hidden" <?php echo $this->getUiId($_element->getId()) ?>><?php echo trim($_element->getElementHtml()) ?></td> <?php else: ?> diff --git a/app/code/core/Mage/Backend/view/adminhtml/widget/grid.phtml b/app/code/core/Mage/Backend/view/adminhtml/widget/grid.phtml index 2ca34e782daf2b091b30be92f8288db05525ed70..a75bee8fff8e73e3eebe346ae817e856ed7dba72 100644 --- a/app/code/core/Mage/Backend/view/adminhtml/widget/grid.phtml +++ b/app/code/core/Mage/Backend/view/adminhtml/widget/grid.phtml @@ -38,9 +38,9 @@ /* @var $this Mage_Backend_Block_Widget_Grid */ $numColumns = sizeof($this->getColumns()); ?> -<?php if($this->getCollection()): ?> - <?php if($this->canDisplayContainer()): ?> - <?php if($this->getGridHeader()): ?> +<?php if ($this->getCollection()): ?> + <?php if ($this->canDisplayContainer()): ?> + <?php if ($this->getGridHeader()): ?> <div class="content-header"> <table cellspacing="0"> <tr> @@ -54,16 +54,16 @@ $numColumns = sizeof($this->getColumns()); <?php else: ?> <?php echo $this->getMessagesBlock()->getGroupedHtml() ?> <?php endif; ?> -<?php if($this->getPagerVisibility() || $this->getExportTypes() || $this->getChildBlock('grid.columnSet')->getFilterVisibility()): ?> +<?php if ($this->getPagerVisibility() || $this->getExportTypes() || $this->getChildBlock('grid.columnSet')->getFilterVisibility()): ?> <table cellspacing="0" class="actions"> <tr> - <?php if($this->getPagerVisibility()): ?> + <?php if ($this->getPagerVisibility()): ?> <td class="pager"> <?php echo $this->__('Page') ?> <?php $_curPage = $this->getCollection()->getCurPage() ?> <?php $_lastPage = $this->getCollection()->getLastPageNumber() ?> - <?php if($_curPage>1): ?> + <?php if ($_curPage>1): ?> <a href="#" title="<?php echo $this->__('Previous page') ?>" onclick="<?php echo $this->getJsObjectName() ?>.setPage('<?php echo ($_curPage-1) ?>');return false;" <?php echo $this->getUiId('previous') ?>><img src="<?php echo $this->getViewFileUrl('images/pager_arrow_left.gif') ?>" alt="Go to Previous page" class="arrow"/></a> <?php else: ?> <img src="<?php echo $this->getViewFileUrl('images/pager_arrow_left_off.gif') ?>" alt="Go to Previous page" class="arrow"/> @@ -71,7 +71,7 @@ $numColumns = sizeof($this->getColumns()); <input type="text" name="<?php echo $this->getVarNamePage() ?>" value="<?php echo $_curPage ?>" class="input-text page" onkeypress="<?php echo $this->getJsObjectName() ?>.inputPage(event, '<?php echo $_lastPage ?>')" <?php echo $this->getUiId('current-page') ?>/> - <?php if($_curPage < $_lastPage): ?> + <?php if ($_curPage < $_lastPage): ?> <a href="#" title="<?php echo $this->__('Next page') ?>" onclick="<?php echo $this->getJsObjectName() ?>.setPage('<?php echo ($_curPage+1) ?>');return false;"<?php echo $this->getUiId('next') ?>><img src="<?php echo $this->getViewFileUrl('images/pager_arrow_right.gif') ?>" alt="Go to Next page" class="arrow"/></a> <?php else: ?> <img src="<?php echo $this->getViewFileUrl('images/pager_arrow_right_off.gif') ?>" alt="Go to Previous page" class="arrow"/> @@ -81,24 +81,24 @@ $numColumns = sizeof($this->getColumns()); <span class="separator">|</span> <?php echo $this->__('View') ?> <select name="<?php echo $this->getVarNameLimit() ?>" onchange="<?php echo $this->getJsObjectName() ?>.loadByElement(this)" <?php echo $this->getUiId('per-page') ?>> - <option value="20"<?php if($this->getCollection()->getPageSize()==20): ?> selected="selected"<?php endif; ?>>20</option> - <option value="30"<?php if($this->getCollection()->getPageSize()==30): ?> selected="selected"<?php endif; ?>>30</option> - <option value="50"<?php if($this->getCollection()->getPageSize()==50): ?> selected="selected"<?php endif; ?>>50</option> - <option value="100"<?php if($this->getCollection()->getPageSize()==100): ?> selected="selected"<?php endif; ?>>100</option> - <option value="200"<?php if($this->getCollection()->getPageSize()==200): ?> selected="selected"<?php endif; ?>>200</option> + <option value="20"<?php if ($this->getCollection()->getPageSize()==20): ?> selected="selected"<?php endif; ?>>20</option> + <option value="30"<?php if ($this->getCollection()->getPageSize()==30): ?> selected="selected"<?php endif; ?>>30</option> + <option value="50"<?php if ($this->getCollection()->getPageSize()==50): ?> selected="selected"<?php endif; ?>>50</option> + <option value="100"<?php if ($this->getCollection()->getPageSize()==100): ?> selected="selected"<?php endif; ?>>100</option> + <option value="200"<?php if ($this->getCollection()->getPageSize()==200): ?> selected="selected"<?php endif; ?>>200</option> </select> <?php echo $this->__('per page') ?><span class="separator">|</span> <?php $countRecords = $this->getCollection()->getSize(); ?> <?php echo $this->__('Total %d records found', $countRecords) ?> <span id="<?php echo $this->getHtmlId() ?>-total-count" class="total-count no-display"<?php echo $this->getUiId('total-count') ?>><?php echo $countRecords ?></span> - <?php if($this->getRssLists()): ?> + <?php if ($this->getRssLists()): ?> <?php foreach ($this->getRssLists() as $_rss): ?> <span class="separator">|</span><a href="<?php echo $_rss->getUrl() ?>" class="link-feed"><?php echo $_rss->getLabel() ?></a> <?php endforeach ?> <?php endif; ?> </td> <?php endif ?> - <?php if($this->getChildBlock('grid.export')): ?> + <?php if ($this->getChildBlock('grid.export')): ?> <td class="export a-right"> <?php echo $this->getChildHtml('grid.export');?> </td> @@ -109,7 +109,7 @@ $numColumns = sizeof($this->getColumns()); </tr> </table> <?php endif; ?> -<?php if($this->getChildBlock('grid.massaction') && $this->getChildBlock('grid.massaction')->isAvailable()): ?> +<?php if ($this->getChildBlock('grid.massaction') && $this->getChildBlock('grid.massaction')->isAvailable()): ?> <?php echo $this->getChildHtml('grid.massaction') ?> <?php endif ?> <div class="grid"> @@ -122,30 +122,30 @@ $numColumns = sizeof($this->getColumns()); </div> </div> </div> -<?php if($this->canDisplayContainer()): ?> +<?php if ($this->canDisplayContainer()): ?> </div> <script type="text/javascript"> //<![CDATA[ <?php echo $this->getJsObjectName() ?>= new varienGrid('<?php echo $this->getId() ?>', '<?php echo $this->getGridUrl() ?>', '<?php echo $this->getVarNamePage() ?>', '<?php echo $this->getVarNameSort() ?>', '<?php echo $this->getVarNameDir() ?>', '<?php echo $this->getVarNameFilter() ?>'); <?php echo $this->getJsObjectName() ?>.useAjax = '<?php echo $this->getUseAjax() ?>'; - <?php if($this->getRowClickCallback()): ?> + <?php if ($this->getRowClickCallback()): ?> <?php echo $this->getJsObjectName() ?>.rowClickCallback = <?php echo $this->getRowClickCallback() ?>; <?php endif; ?> - <?php if($this->getCheckboxCheckCallback()): ?> + <?php if ($this->getCheckboxCheckCallback()): ?> <?php echo $this->getJsObjectName() ?>.checkboxCheckCallback = <?php echo $this->getCheckboxCheckCallback() ?>; <?php endif; ?> - <?php if($this->getRowInitCallback()): ?> + <?php if ($this->getRowInitCallback()): ?> <?php echo $this->getJsObjectName() ?>.initRowCallback = <?php echo $this->getRowInitCallback() ?>; <?php echo $this->getJsObjectName() ?>.initGridRows(); <?php endif; ?> - <?php if($this->getChildBlock('grid.massaction') && $this->getChildBlock('grid.massaction')->isAvailable()): ?> + <?php if ($this->getChildBlock('grid.massaction') && $this->getChildBlock('grid.massaction')->isAvailable()): ?> <?php echo $this->getChildBlock('grid.massaction')->getJavaScript() ?> <?php endif ?> <?php echo $this->getAdditionalJavaScript(); ?> //]]> </script> <?php endif; ?> -<?php if($this->getChildBlock('grid.js')): ?> +<?php if ($this->getChildBlock('grid.js')): ?> <?php echo $this->getChildHtml('grid.js');?> <?php endif;?> <?php endif ?> diff --git a/app/code/core/Mage/Backend/view/adminhtml/widget/grid/extended.phtml b/app/code/core/Mage/Backend/view/adminhtml/widget/grid/extended.phtml index 18cfcc923a6d95f893ea80f36177fbcf4a7fbc83..f4315e19f7950b475c5a45d1e44f8cf0c9983eca 100644 --- a/app/code/core/Mage/Backend/view/adminhtml/widget/grid/extended.phtml +++ b/app/code/core/Mage/Backend/view/adminhtml/widget/grid/extended.phtml @@ -40,9 +40,9 @@ $numColumns = sizeof($this->getColumns()); * @var Mage_Backend_Block_Widget_Grid_Extended $this */ ?> -<?php if($this->getCollection()): ?> - <?php if($this->canDisplayContainer()): ?> - <?php if($this->getGridHeader()): ?> +<?php if ($this->getCollection()): ?> + <?php if ($this->canDisplayContainer()): ?> + <?php if ($this->getGridHeader()): ?> <div class="content-header"> <table cellspacing="0"> <tr> @@ -56,16 +56,16 @@ $numColumns = sizeof($this->getColumns()); <?php else: ?> <?php echo $this->getMessagesBlock()->getGroupedHtml() ?> <?php endif; ?> -<?php if($this->getPagerVisibility() || $this->getExportTypes() || $this->getFilterVisibility()): ?> +<?php if ($this->getPagerVisibility() || $this->getExportTypes() || $this->getFilterVisibility()): ?> <table cellspacing="0" class="actions"> <tr> - <?php if($this->getPagerVisibility()): ?> + <?php if ($this->getPagerVisibility()): ?> <td class="pager"> <?php echo $this->__('Page') ?> <?php $_curPage = $this->getCollection()->getCurPage() ?> <?php $_lastPage = $this->getCollection()->getLastPageNumber() ?> - <?php if($_curPage>1): ?> + <?php if ($_curPage>1): ?> <a href="#" title="<?php echo $this->__('Previous page') ?>" onclick="<?php echo $this->getJsObjectName() ?>.setPage('<?php echo ($_curPage-1) ?>');return false;"><img src="<?php echo $this->getViewFileUrl('images/pager_arrow_left.gif') ?>" alt="Go to Previous page" class="arrow"/></a> <?php else: ?> <img src="<?php echo $this->getViewFileUrl('images/pager_arrow_left_off.gif') ?>" alt="Go to Previous page" class="arrow"/> @@ -73,7 +73,7 @@ $numColumns = sizeof($this->getColumns()); <input type="text" name="<?php echo $this->getVarNamePage() ?>" value="<?php echo $_curPage ?>" class="input-text page" onkeypress="<?php echo $this->getJsObjectName() ?>.inputPage(event, '<?php echo $_lastPage ?>')"/> - <?php if($_curPage < $_lastPage): ?> + <?php if ($_curPage < $_lastPage): ?> <a href="#" title="<?php echo $this->__('Next page') ?>" onclick="<?php echo $this->getJsObjectName() ?>.setPage('<?php echo ($_curPage+1) ?>');return false;"><img src="<?php echo $this->getViewFileUrl('images/pager_arrow_right.gif') ?>" alt="Go to Next page" class="arrow"/></a> <?php else: ?> <img src="<?php echo $this->getViewFileUrl('images/pager_arrow_right_off.gif') ?>" alt="Go to Previous page" class="arrow"/> @@ -83,23 +83,23 @@ $numColumns = sizeof($this->getColumns()); <span class="separator">|</span> <?php echo $this->__('View') ?> <select name="<?php echo $this->getVarNameLimit() ?>" onchange="<?php echo $this->getJsObjectName() ?>.loadByElement(this)"> - <option value="20"<?php if($this->getCollection()->getPageSize()==20): ?> selected="selected"<?php endif; ?>>20</option> - <option value="30"<?php if($this->getCollection()->getPageSize()==30): ?> selected="selected"<?php endif; ?>>30</option> - <option value="50"<?php if($this->getCollection()->getPageSize()==50): ?> selected="selected"<?php endif; ?>>50</option> - <option value="100"<?php if($this->getCollection()->getPageSize()==100): ?> selected="selected"<?php endif; ?>>100</option> - <option value="200"<?php if($this->getCollection()->getPageSize()==200): ?> selected="selected"<?php endif; ?>>200</option> + <option value="20"<?php if ($this->getCollection()->getPageSize()==20): ?> selected="selected"<?php endif; ?>>20</option> + <option value="30"<?php if ($this->getCollection()->getPageSize()==30): ?> selected="selected"<?php endif; ?>>30</option> + <option value="50"<?php if ($this->getCollection()->getPageSize()==50): ?> selected="selected"<?php endif; ?>>50</option> + <option value="100"<?php if ($this->getCollection()->getPageSize()==100): ?> selected="selected"<?php endif; ?>>100</option> + <option value="200"<?php if ($this->getCollection()->getPageSize()==200): ?> selected="selected"<?php endif; ?>>200</option> </select> <?php echo $this->__('per page') ?><span class="separator">|</span> <?php echo $this->__('Total %d records found', $this->getCollection()->getSize()) ?> <span id="<?php echo $this->getHtmlId() ?>-total-count" class="no-display"><?php echo $this->getCollection()->getSize() ?></span> - <?php if($this->getRssLists()): ?> + <?php if ($this->getRssLists()): ?> <?php foreach ($this->getRssLists() as $_rss): ?> <span class="separator">|</span><a href="<?php echo $_rss->getUrl() ?>" class="link-feed"><?php echo $_rss->getLabel() ?></a> <?php endforeach ?> <?php endif; ?> </td> <?php endif ?> - <?php if($this->getExportTypes()): ?> + <?php if ($this->getExportTypes()): ?> <td class="export a-right"> <img src="<?php echo $this->getViewFileUrl('images/icon_export.gif') ?>" alt="" class="v-middle"/> <?php echo $this->__('Export to:') ?> <select name="<?php echo $this->getId() ?>_export" id="<?php echo $this->getId() ?>_export" style="width:8em;"> @@ -116,7 +116,7 @@ $numColumns = sizeof($this->getColumns()); </tr> </table> <?php endif; ?> -<?php if($this->getMassactionBlock()->isAvailable()): ?> +<?php if ($this->getMassactionBlock()->isAvailable()): ?> <?php echo $this->getMassactionBlockHtml() ?> <?php endif ?> <div class="grid"> @@ -206,23 +206,23 @@ $numColumns = sizeof($this->getColumns()); </table> </div> </div> -<?php if($this->canDisplayContainer()): ?> +<?php if ($this->canDisplayContainer()): ?> </div> <script type="text/javascript"> //<![CDATA[ <?php echo $this->getJsObjectName() ?> = new varienGrid('<?php echo $this->getId() ?>', '<?php echo $this->getGridUrl() ?>', '<?php echo $this->getVarNamePage() ?>', '<?php echo $this->getVarNameSort() ?>', '<?php echo $this->getVarNameDir() ?>', '<?php echo $this->getVarNameFilter() ?>'); <?php echo $this->getJsObjectName() ?>.useAjax = '<?php echo $this->getUseAjax() ?>'; - <?php if($this->getRowClickCallback()): ?> + <?php if ($this->getRowClickCallback()): ?> <?php echo $this->getJsObjectName() ?>.rowClickCallback = <?php echo $this->getRowClickCallback() ?>; <?php endif; ?> - <?php if($this->getCheckboxCheckCallback()): ?> + <?php if ($this->getCheckboxCheckCallback()): ?> <?php echo $this->getJsObjectName() ?>.checkboxCheckCallback = <?php echo $this->getCheckboxCheckCallback() ?>; <?php endif; ?> - <?php if($this->getRowInitCallback()): ?> + <?php if ($this->getRowInitCallback()): ?> <?php echo $this->getJsObjectName() ?>.initRowCallback = <?php echo $this->getRowInitCallback() ?>; <?php echo $this->getJsObjectName() ?>.initGridRows(); <?php endif; ?> - <?php if($this->getMassactionBlock()->isAvailable()): ?> + <?php if ($this->getMassactionBlock()->isAvailable()): ?> <?php echo $this->getMassactionBlock()->getJavaScript() ?> <?php endif ?> <?php echo $this->getAdditionalJavaScript(); ?> diff --git a/app/code/core/Mage/Backend/view/adminhtml/widget/grid/massaction.phtml b/app/code/core/Mage/Backend/view/adminhtml/widget/grid/massaction.phtml index a9b00b564f16bb2e573b8b00f53889dc77a191f7..765ea80135e3796beb24203b72768a555bb6c0bb 100644 --- a/app/code/core/Mage/Backend/view/adminhtml/widget/grid/massaction.phtml +++ b/app/code/core/Mage/Backend/view/adminhtml/widget/grid/massaction.phtml @@ -51,7 +51,7 @@ <label><?php echo $this->__('Actions') ?></label> <select id="<?php echo $this->getHtmlId() ?>-select" class="required-entry select absolute-advice local-validation"<?php echo $this->getUiId('select') ?>> <option value=""></option> - <?php foreach($this->getItems() as $_item):?> + <?php foreach ($this->getItems() as $_item):?> <option value="<?php echo $_item->getId() ?>"<?php echo ($_item->getSelected() ? ' selected="selected"' : '')?>><?php echo $_item->getLabel() ?></option> <?php endforeach; ?> </select> @@ -68,7 +68,7 @@ </div> <div class="no-display"> - <?php foreach($this->getItems() as $_item): ?> + <?php foreach ($this->getItems() as $_item): ?> <div id="<?php echo $this->getHtmlId() ?>-item-<?php echo $_item->getId() ?>-block"> <?php if ('' != $_item->getBlockName()):?> <?php echo $this->getChildHtml($_item->getBlockName());?> @@ -80,7 +80,7 @@ </td> </tr> </table> -<?php if(!$this->getParentBlock()->canDisplayContainer()): ?> +<?php if (!$this->getParentBlock()->canDisplayContainer()): ?> <script type="text/javascript"> <?php echo $this->getJsObjectName() ?>.setGridIds('<?php echo $this->getGridIdsJson() ?>'); </script> diff --git a/app/code/core/Mage/Backend/view/adminhtml/widget/grid/massaction_extended.phtml b/app/code/core/Mage/Backend/view/adminhtml/widget/grid/massaction_extended.phtml index 5486cb38834b3f5a5ec5e3755c07e487dea2228d..90dbb90d73457aa90bde1d13bb1340bb1644be5a 100644 --- a/app/code/core/Mage/Backend/view/adminhtml/widget/grid/massaction_extended.phtml +++ b/app/code/core/Mage/Backend/view/adminhtml/widget/grid/massaction_extended.phtml @@ -54,7 +54,7 @@ <label><?php echo $this->__('Actions') ?></label> <select id="<?php echo $this->getHtmlId() ?>-select" class="required-entry select absolute-advice local-validation"> <option value=""></option> - <?php foreach($this->getItems() as $_item): ?> + <?php foreach ($this->getItems() as $_item): ?> <option value="<?php echo $_item->getId() ?>"<?php echo ($_item->getSelected() ? ' selected="selected"' : '')?>><?php echo $_item->getLabel() ?></option> <?php endforeach; ?> </select> @@ -71,7 +71,7 @@ </div> <div class="no-display"> - <?php foreach($this->getItems() as $_item): ?> + <?php foreach ($this->getItems() as $_item): ?> <div id="<?php echo $this->getHtmlId() ?>-item-<?php echo $_item->getId() ?>-block"> <?php echo $_item->getAdditionalActionBlockHtml() ?> </div> @@ -81,7 +81,7 @@ </td> </tr> </table> -<?php if(!$this->getParentBlock()->canDisplayContainer()): ?> +<?php if (!$this->getParentBlock()->canDisplayContainer()): ?> <script type="text/javascript"> <?php echo $this->getJsObjectName() ?>.setGridIds('<?php echo $this->getGridIdsJson() ?>'); </script> diff --git a/app/code/core/Mage/Backend/view/adminhtml/widget/tabs.phtml b/app/code/core/Mage/Backend/view/adminhtml/widget/tabs.phtml index 28a3cb4a92e4661da77b0e34f0cb117efa78e048..4ffa372dd8a9dad416737f1a982f87cfe8db9c0a 100644 --- a/app/code/core/Mage/Backend/view/adminhtml/widget/tabs.phtml +++ b/app/code/core/Mage/Backend/view/adminhtml/widget/tabs.phtml @@ -24,14 +24,14 @@ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) */ ?> -<?php if($this->getTitle()): ?> +<?php if ($this->getTitle()): ?> <h3 <?php echo $this->getUiId('title') ?>><?php echo $this->getTitle() ?></h3> <?php endif ?> -<?php if(!empty($tabs)): ?> +<?php if (!empty($tabs)): ?> <ul id="<?php echo $this->getId() ?>" <?php echo $this->getUiId('tab', $this->getId()) ?> class="tabs"> <?php foreach ($tabs as $_tab): ?> <?php if (!$this->canShowTab($_tab)): continue; endif; ?> - <li <?php if($this->getTabIsHidden($_tab)): ?> style="display:none"<?php endif; ?><?php echo $this->getUiId('tab', 'item', $_tab->getId()) ?>> + <li <?php if ($this->getTabIsHidden($_tab)): ?> style="display:none"<?php endif; ?><?php echo $this->getUiId('tab', 'item', $_tab->getId()) ?>> <a href="<?php echo $this->getTabUrl($_tab) ?>" id="<?php echo $this->getTabId($_tab) ?>" name="<?php echo $this->getTabId($_tab, false) ?>" title="<?php echo $this->getTabTitle($_tab) ?>" class="tab-item-link <?php echo $this->getTabClass($_tab) ?><?php if (preg_match('/\s?ajax\s?/', $_tab->getClass())) {?> notloaded<?php }?>"<?php echo $this->getUiId('tab', 'link', $_tab->getId()) ?>> <span><span class="changed" title="<?php echo $this->__('The information in this tab has been changed.') ?>"></span><span class="error" title="<?php echo $this->__('This tab contains invalid data. Please solve the problem before saving.') ?>"></span><?php echo $this->getTabLabel($_tab); ?></span> </a> diff --git a/app/code/core/Mage/Catalog/Model/Api/Resource.php b/app/code/core/Mage/Catalog/Model/Api/Resource.php deleted file mode 100644 index c6425292e10f69adabd65f48f30682c6050316d7..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Catalog/Model/Api/Resource.php +++ /dev/null @@ -1,132 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Catalog - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Catalog api resource - * - * @category Mage - * @package Mage_Catalog - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Catalog_Model_Api_Resource extends Mage_Api_Model_Resource_Abstract -{ - /** - * Default ignored attribute codes - * - * @var array - */ - protected $_ignoredAttributeCodes = array('entity_id', 'attribute_set_id', 'entity_type_id'); - - /** - * Default ignored attribute types - * - * @var array - */ - protected $_ignoredAttributeTypes = array(); - - /** - * Field name in session for saving store id - * @var string - */ - protected $_storeIdSessionField = 'store_id'; - - /** - * Check is attribute allowed - * - * @param Mage_Eav_Model_Entity_Attribute_Abstract $attribute - * @param array $attributes - * @return boolean - */ - protected function _isAllowedAttribute($attribute, $attributes = null) - { - if (is_array($attributes) - && !( in_array($attribute->getAttributeCode(), $attributes) - || in_array($attribute->getAttributeId(), $attributes))) { - return false; - } - - return !in_array($attribute->getFrontendInput(), $this->_ignoredAttributeTypes) - && !in_array($attribute->getAttributeCode(), $this->_ignoredAttributeCodes); - } - - /** - * Retrives store id from store code, if no store id specified, - * it use seted session or admin store - * - * @param string|int $store - * @return int - */ - protected function _getStoreId($store = null) - { - if (is_null($store)) { - $store = ($this->_getSession()->hasData($this->_storeIdSessionField) - ? $this->_getSession()->getData($this->_storeIdSessionField) : 0); - } - - try { - $storeId = Mage::app()->getStore($store)->getId(); - } catch (Mage_Core_Model_Store_Exception $e) { - $this->_fault('store_not_exists'); - } - - return $storeId; - } - - /** - * Return loaded product instance - * - * @param int|string $productId (SKU or ID) - * @param int|string $store - * @param string $identifierType - * @return Mage_Catalog_Model_Product - */ - protected function _getProduct($productId, $store = null, $identifierType = null) - { - $product = Mage::helper('Mage_Catalog_Helper_Product')->getProduct($productId, $this->_getStoreId($store), $identifierType); - return $product; - } - - /** - * Set current store for catalog. - * - * @param string|int $store - * @return int - */ - public function currentStore($store=null) - { - if (!is_null($store)) { - try { - $storeId = Mage::app()->getStore($store)->getId(); - } catch (Mage_Core_Model_Store_Exception $e) { - $this->_fault('store_not_exists'); - } - - $this->_getSession()->setData($this->_storeIdSessionField, $storeId); - } - - return $this->_getStoreId(); - } -} // Class Mage_Catalog_Model_Api_Resource End diff --git a/app/code/core/Mage/Catalog/Model/Api2/Product.php b/app/code/core/Mage/Catalog/Model/Api2/Product.php deleted file mode 100644 index c74ca97f98603bd0c73650c715a785e530add97f..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Catalog/Model/Api2/Product.php +++ /dev/null @@ -1,94 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Catalog - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Abstract Api2 model for product instance - * - * @category Mage - * @package Mage_Catalog - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Catalog_Model_Api2_Product extends Mage_Api2_Model_Resource -{ - /** - * Get available attributes of API resource - * - * @param string $userType - * @param string $operation - * @return array - */ - public function getAvailableAttributes($userType, $operation) - { - $attributes = $this->getAvailableAttributesFromConfig(); - /** @var $entityType Mage_Eav_Model_Entity_Type */ - $entityType = Mage::getModel('Mage_Eav_Model_Entity_Type')->loadByCode('catalog_product'); - $entityOnlyAttrs = $this->getEntityOnlyAttributes($userType, $operation); - /** @var $attribute Mage_Catalog_Model_Resource_Eav_Attribute */ - foreach ($entityType->getAttributeCollection() as $attribute) { - if ($this->_isAttributeVisible($attribute, $userType)) { - $attributes[$attribute->getAttributeCode()] = $attribute->getFrontendLabel(); - } - } - $excludedAttrs = $this->getExcludedAttributes($userType, $operation); - $includedAttrs = $this->getIncludedAttributes($userType, $operation); - foreach ($attributes as $code => $label) { - if (in_array($code, $excludedAttrs) || ($includedAttrs && !in_array($code, $includedAttrs))) { - unset($attributes[$code]); - } - if (in_array($code, $entityOnlyAttrs)) { - $attributes[$code] .= ' *'; - } - } - - return $attributes; - } - - /** - * Define if attribute should be visible for passed user type - * - * @param Mage_Catalog_Model_Resource_Eav_Attribute $attribute - * @param string $userType - * @return bool - */ - protected function _isAttributeVisible(Mage_Catalog_Model_Resource_Eav_Attribute $attribute, $userType) - { - $isAttributeVisible = false; - if ($userType == Mage_Api2_Model_Auth_User_Admin::USER_TYPE) { - $isAttributeVisible = $attribute->getIsVisible(); - } else { - $systemAttributesForNonAdmin = array( - 'sku', 'name', 'short_description', 'description', 'tier_price', 'meta_title', 'meta_description', - 'meta_keyword', - ); - if ($attribute->getIsUserDefined()) { - $isAttributeVisible = $attribute->getIsVisibleOnFront(); - } else if (in_array($attribute->getAttributeCode(), $systemAttributesForNonAdmin)) { - $isAttributeVisible = true; - } - } - return (bool)$isAttributeVisible; - } -} diff --git a/app/code/core/Mage/Catalog/Model/Api2/Product/Category.php b/app/code/core/Mage/Catalog/Model/Api2/Product/Category.php deleted file mode 100644 index 8cf924bdd1328aa4dd748a125b39086be627b433..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Catalog/Model/Api2/Product/Category.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Catalog - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Abstract Api2 model for product categories collection - * - * @category Mage - * @package Mage_Catalog - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Catalog_Model_Api2_Product_Category extends Mage_Api2_Model_Resource -{ -} diff --git a/app/code/core/Mage/Catalog/Model/Api2/Product/Category/Rest.php b/app/code/core/Mage/Catalog/Model/Api2/Product/Category/Rest.php deleted file mode 100644 index 0e6704db3234485d25cae5a93d1e7c9602ac3bac..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Catalog/Model/Api2/Product/Category/Rest.php +++ /dev/null @@ -1,105 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Catalog - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Abstract API2 class for product categories - * - * @category Mage - * @package Mage_Catalog - * @author Magento Core Team <core@magentocommerce.com> - */ -abstract class Mage_Catalog_Model_Api2_Product_Category_Rest extends Mage_Catalog_Model_Api2_Product_Rest -{ - /** - * Product category assign is not available - * - * @param array $data - */ - protected function _create(array $data) - { - $this->_critical(self::RESOURCE_METHOD_NOT_ALLOWED); - } - - /** - * Product category update is not available - * - * @param array $data - */ - protected function _update(array $data) - { - $this->_critical(self::RESOURCE_METHOD_NOT_ALLOWED); - } - - /** - * Retrieve product data - * - * @return array - */ - protected function _retrieveCollection() - { - $return = array(); - - foreach ($this->_getCategoryIds() as $categoryId) { - $return[] = array('category_id' => $categoryId); - } - return $return; - } - - /** - * Only admin have permissions for product category unassign - */ - protected function _delete() - { - $this->_critical(self::RESOURCE_METHOD_NOT_ALLOWED); - } - - /** - * Load category by id - * - * @param int $categoryId - * @return Mage_Catalog_Model_Category - */ - protected function _getCategoryById($categoryId) - { - /** @var $category Mage_Catalog_Model_Category */ - $category = Mage::getModel('Mage_Catalog_Model_Category')->setStoreId(0)->load($categoryId); - if (!$category->getId()) { - $this->_critical('Category not found', Mage_Api2_Model_Server::HTTP_NOT_FOUND); - } - - return $category; - } - - /** - * Get assigned categories ids - * - * @return array - */ - protected function _getCategoryIds() - { - return $this->_getProduct()->getCategoryCollection()->addIsActiveFilter()->getAllIds(); - } -} diff --git a/app/code/core/Mage/Catalog/Model/Api2/Product/Category/Rest/Admin/V1.php b/app/code/core/Mage/Catalog/Model/Api2/Product/Category/Rest/Admin/V1.php deleted file mode 100644 index 7bbef65ef79fd842f6cc85f1cc268bbfd982f6ee..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Catalog/Model/Api2/Product/Category/Rest/Admin/V1.php +++ /dev/null @@ -1,149 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Catalog - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 for product categories - * - * @category Mage - * @package Mage_Catalog - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Catalog_Model_Api2_Product_Category_Rest_Admin_V1 extends Mage_Catalog_Model_Api2_Product_Category_Rest -{ - /** - * Product category assign - * - * @param array $data - * @return string - */ - protected function _create(array $data) - { - /* @var $validator Mage_Api2_Model_Resource_Validator_Fields */ - $validator = Mage::getResourceModel('Mage_Api2_Model_Resource_Validator_Fields', - array('options' => - array('resource' => $this) - )); - if (!$validator->isValidData($data)) { - foreach ($validator->getErrors() as $error) { - $this->_error($error, Mage_Api2_Model_Server::HTTP_BAD_REQUEST); - } - $this->_critical(self::RESOURCE_DATA_PRE_VALIDATION_ERROR); - } - - $product = $this->_getProduct(); - $category = $this->_getCategoryById($data['category_id']); - - $categoryIds = $product->getCategoryIds(); - if (!is_array($categoryIds)) { - $categoryIds = array(); - } - if (in_array($category->getId(), $categoryIds)) { - $this->_critical(sprintf('Product #%d is already assigned to category #%d', - $product->getId(), $category->getId()), Mage_Api2_Model_Server::HTTP_BAD_REQUEST); - } - if ($category->getId() == Mage_Catalog_Model_Category::TREE_ROOT_ID) { - $this->_critical('Cannot assign product to tree root category.', Mage_Api2_Model_Server::HTTP_BAD_REQUEST); - } - $categoryIds[] = $category->getId(); - $product->setCategoryIds(implode(',', $categoryIds)); - - try{ - $product->save(); - } catch (Mage_Core_Exception $e) { - $this->_critical($e->getMessage(), Mage_Api2_Model_Server::HTTP_INTERNAL_ERROR); - } catch (Exception $e) { - $this->_critical(self::RESOURCE_INTERNAL_ERROR); - } - - return $this->_getLocation($category); - } - - /** - * Product category unassign - * - * @return bool - */ - protected function _delete() - { - $product = $this->_getProduct(); - $category = $this->_getCategoryById($this->getRequest()->getParam('category_id')); - - $categoryIds = $product->getCategoryIds(); - $categoryToBeDeletedId = array_search($category->getId(), $categoryIds); - if (false === $categoryToBeDeletedId) { - $this->_critical(sprintf('Product #%d isn\'t assigned to category #%d', - $product->getId(), $category->getId()), Mage_Api2_Model_Server::HTTP_BAD_REQUEST); - } - - // delete category - unset($categoryIds[$categoryToBeDeletedId]); - $product->setCategoryIds(implode(',', $categoryIds)); - - try{ - $product->save(); - } catch (Mage_Core_Exception $e) { - $this->_critical($e->getMessage(), Mage_Api2_Model_Server::HTTP_INTERNAL_ERROR); - } catch (Exception $e) { - $this->_critical(self::RESOURCE_INTERNAL_ERROR); - } - - return true; - } - - /** - * Return all assigned categories - * - * @return array - */ - protected function _getCategoryIds() - { - return $this->_getProduct()->getCategoryIds(); - } - - /** - * Get resource location - * - * @param Mage_Core_Model_Abstract $resource - * @return string URL - */ - protected function _getLocation($resource) - { - /** @var $apiTypeRoute Mage_Api2_Model_Route_ApiType */ - $apiTypeRoute = Mage::getModel('Mage_Api2_Model_Route_ApiType'); - - $chain = $apiTypeRoute->chain(new Zend_Controller_Router_Route( - $this->getConfig()->getRouteWithEntityTypeAction($this->getResourceType()) - )); - $params = array( - 'api_type' => $this->getRequest()->getApiType(), - 'id' => $this->getRequest()->getParam('id'), - 'category_id' => $resource->getId() - ); - $uri = $chain->assemble($params); - - return '/' . $uri; - } -} diff --git a/app/code/core/Mage/Catalog/Model/Api2/Product/Category/Rest/Customer/V1.php b/app/code/core/Mage/Catalog/Model/Api2/Product/Category/Rest/Customer/V1.php deleted file mode 100644 index 6bcd3e305a7d323ce106b2c7ce080ddf6f19cf00..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Catalog/Model/Api2/Product/Category/Rest/Customer/V1.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Catalog - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 for product categories - * - * @category Mage - * @package Mage_Catalog - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Catalog_Model_Api2_Product_Category_Rest_Customer_V1 extends Mage_Catalog_Model_Api2_Product_Category_Rest -{ -} diff --git a/app/code/core/Mage/Catalog/Model/Api2/Product/Category/Rest/Guest/V1.php b/app/code/core/Mage/Catalog/Model/Api2/Product/Category/Rest/Guest/V1.php deleted file mode 100644 index fa2002ea27c819101677e2e520b4de398f38f495..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Catalog/Model/Api2/Product/Category/Rest/Guest/V1.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Catalog - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 for product categories - * - * @category Mage - * @package Mage_Catalog - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Catalog_Model_Api2_Product_Category_Rest_Guest_V1 extends Mage_Catalog_Model_Api2_Product_Category_Rest -{ -} diff --git a/app/code/core/Mage/Catalog/Model/Api2/Product/Image.php b/app/code/core/Mage/Catalog/Model/Api2/Product/Image.php deleted file mode 100644 index 820b1506e4d1873a0c3af5da83dc7f007cadc35b..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Catalog/Model/Api2/Product/Image.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Catalog - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Abstract Api2 model for product image - * - * @category Mage - * @package Mage_Catalog - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Catalog_Model_Api2_Product_Image extends Mage_Api2_Model_Resource -{ -} diff --git a/app/code/core/Mage/Catalog/Model/Api2/Product/Image/Rest.php b/app/code/core/Mage/Catalog/Model/Api2/Product/Image/Rest.php deleted file mode 100644 index 23c636c22555d316709acae056acf52e2ef18964..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Catalog/Model/Api2/Product/Image/Rest.php +++ /dev/null @@ -1,222 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Catalog - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Abstract API2 class for product images resource - * - * @category Mage - * @package Mage_Catalog - * @author Magento Core Team <core@magentocommerce.com> - */ -abstract class Mage_Catalog_Model_Api2_Product_Image_Rest extends Mage_Catalog_Model_Api2_Product_Rest -{ - /** - * Attribute code for media gallery - */ - const GALLERY_ATTRIBUTE_CODE = 'media_gallery'; - - /** - * Allowed MIME types for image - * - * @var array - */ - protected $_mimeTypes = array( - 'image/jpg' => 'jpg', - 'image/jpeg' => 'jpg', - 'image/gif' => 'gif', - 'image/png' => 'png' - ); - - /** - * Retrieve product image data for customer and guest roles - * - * @throws Mage_Api2_Exception - * @return array - */ - protected function _retrieve() - { - $imageData = array(); - $imageId = (int)$this->getRequest()->getParam('image'); - $galleryData = $this->_getProduct()->getData(self::GALLERY_ATTRIBUTE_CODE); - - if (!isset($galleryData['images']) || !is_array($galleryData['images'])) { - $this->_critical(self::RESOURCE_NOT_FOUND); - } - foreach ($galleryData['images'] as $image) { - if ($image['value_id'] == $imageId && !$image['disabled']) { - $imageData = $this->_formatImageData($image); - break; - } - } - if (empty($imageData)) { - $this->_critical(self::RESOURCE_NOT_FOUND); - } - return $imageData; - } - - /** - * Retrieve product images data for customer and guest - * - * @return array - */ - protected function _retrieveCollection() - { - $images = array(); - $galleryData = $this->_getProduct()->getData(self::GALLERY_ATTRIBUTE_CODE); - if (isset($galleryData['images']) && is_array($galleryData['images'])) { - foreach ($galleryData['images'] as $image) { - if (!$image['disabled']) { - $images[] = $this->_formatImageData($image); - } - } - } - return $images; - } - - /** - * Retrieve media gallery - * - * @throws Mage_Api2_Exception - * @return Mage_Catalog_Model_Product_Attribute_Backend_Media - */ - protected function _getMediaGallery() - { - $attributes = $this->_getProduct()->getTypeInstance()->getSetAttributes($this->_getProduct()); - - if (!isset($attributes[self::GALLERY_ATTRIBUTE_CODE]) - || !$attributes[self::GALLERY_ATTRIBUTE_CODE] instanceof Mage_Eav_Model_Entity_Attribute_Abstract - ) { - $this->_critical('Requested product does not support images', Mage_Api2_Model_Server::HTTP_BAD_REQUEST); - } - $galleryAttribute = $attributes[self::GALLERY_ATTRIBUTE_CODE]; - /** @var $mediaGallery Mage_Catalog_Model_Product_Attribute_Backend_Media */ - $mediaGallery = $galleryAttribute->getBackend(); - return $mediaGallery; - } - - /** - * Create image data representation for API - * - * @param array $image - * @return array - */ - protected function _formatImageData($image) - { - $result = array( - 'id' => $image['value_id'], - 'label' => $image['label'], - 'position' => $image['position'], - 'exclude' => $image['disabled'], - 'url' => $this->_getMediaConfig()->getMediaUrl($image['file']), - 'types' => $this->_getImageTypesAssignedToProduct($image['file']) - ); - return $result; - } - - /** - * Retrieve image types assigned to product (base, small, thumbnail) - * - * @param string $imageFile - * @return array - */ - protected function _getImageTypesAssignedToProduct($imageFile) - { - $types = array(); - foreach ($this->_getProduct()->getMediaAttributes() as $attribute) { - if ($this->_getProduct()->getData($attribute->getAttributeCode()) == $imageFile) { - $types[] = $attribute->getAttributeCode(); - } - } - return $types; - } - - /** - * Retrieve media config - * - * @return Mage_Catalog_Model_Product_Media_Config - */ - protected function _getMediaConfig() - { - return Mage::getSingleton('Mage_Catalog_Model_Product_Media_Config'); - } - - /** - * Create file name from received data - * - * @param array $data - * @return string - */ - protected function _getFileName($data) - { - $fileName = 'image'; - if (isset($data['file_name']) && $data['file_name']) { - $fileName = $data['file_name']; - } - $fileName .= '.' . $this->_getExtensionByMimeType($data['file_mime_type']); - return $fileName; - } - - /** - * Retrieve file extension using MIME type - * - * @throws Mage_Api2_Exception - * @param string $mimeType - * @return string - */ - protected function _getExtensionByMimeType($mimeType) - { - if (!array_key_exists($mimeType, $this->_mimeTypes)) { - $this->_critical('Unsuppoted image MIME type', Mage_Api2_Model_Server::HTTP_BAD_REQUEST); - } - return $this->_mimeTypes[$mimeType]; - } - - /** - * Get file URI by its id. File URI is used by media backend to identify image - * - * @throws Mage_Api2_Exception - * @param int $imageId - * @return string - */ - protected function _getImageFileById($imageId) - { - $file = null; - $mediaGalleryData = $this->_getProduct()->getData('media_gallery'); - if (!isset($mediaGalleryData['images'])) { - $this->_critical(self::RESOURCE_NOT_FOUND); - } - foreach ($mediaGalleryData['images'] as $image) { - if ($image['value_id'] == $imageId) { - $file = $image['file']; - break; - } - } - if (!($file && $this->_getMediaGallery()->getImage($this->_getProduct(), $file))) { - $this->_critical(self::RESOURCE_NOT_FOUND); - } - return $file; - } -} diff --git a/app/code/core/Mage/Catalog/Model/Api2/Product/Image/Rest/Admin/V1.php b/app/code/core/Mage/Catalog/Model/Api2/Product/Image/Rest/Admin/V1.php deleted file mode 100644 index ecd4a943f6b042720031c081f45b59ab4205b459..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Catalog/Model/Api2/Product/Image/Rest/Admin/V1.php +++ /dev/null @@ -1,238 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Catalog - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 for product image. Admin role - * - * @category Mage - * @package Mage_Catalog - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Catalog_Model_Api2_Product_Image_Rest_Admin_V1 extends Mage_Catalog_Model_Api2_Product_Image_Rest -{ - /** - * Product image add - * - * @throws Mage_Api2_Exception - * @param array $data - * @return string - */ - protected function _create(array $data) - { - /* @var $validator Mage_Catalog_Model_Api2_Product_Image_Validator_Image */ - $validator = Mage::getModel('Mage_Catalog_Model_Api2_Product_Image_Validator_Image'); - if (!$validator->isValidData($data)) { - foreach ($validator->getErrors() as $error) { - $this->_error($error, Mage_Api2_Model_Server::HTTP_BAD_REQUEST); - } - $this->_critical(self::RESOURCE_DATA_PRE_VALIDATION_ERROR); - } - $imageFileContent = @base64_decode($data['file_content'], true); - if (!$imageFileContent) { - $this->_critical('The image content must be valid base64 encoded data', - Mage_Api2_Model_Server::HTTP_BAD_REQUEST); - } - unset($data['file_content']); - - $apiTempDir = Mage::getBaseDir('var') . DS . 'api' . DS . Mage::getSingleton('Mage_Api_Model_Session')->getSessionId(); - $imageFileName = $this->_getFileName($data); - - try { - $ioAdapter = new Varien_Io_File(); - $ioAdapter->checkAndCreateFolder($apiTempDir); - $ioAdapter->open(array('path' => $apiTempDir)); - $ioAdapter->write($imageFileName, $imageFileContent, 0666); - unset($imageFileContent); - - // try to create Image object to check if image data is valid - try { - $adapter = Mage::helper('Mage_Core_Helper_Data')->getImageAdapterType(); - new Varien_Image($apiTempDir . DS . $imageFileName, $adapter); - } catch (Exception $e) { - $ioAdapter->rmdir($apiTempDir, true); - $this->_critical($e->getMessage(), Mage_Api2_Model_Server::HTTP_INTERNAL_ERROR); - } - $product = $this->_getProduct(); - $imageFileUri = $this->_getMediaGallery() - ->addImage($product, $apiTempDir . DS . $imageFileName, null, false, false); - $ioAdapter->rmdir($apiTempDir, true); - // updateImage() must be called to add image data that is missing after addImage() call - $this->_getMediaGallery()->updateImage($product, $imageFileUri, $data); - - if (isset($data['types'])) { - $this->_getMediaGallery()->setMediaAttribute($product, $data['types'], $imageFileUri); - } - $product->save(); - return $this->_getImageLocation($this->_getCreatedImageId($imageFileUri)); - } catch (Mage_Core_Exception $e) { - $this->_critical($e->getMessage(), Mage_Api2_Model_Server::HTTP_INTERNAL_ERROR); - } catch (Exception $e) { - $this->_critical(self::RESOURCE_UNKNOWN_ERROR); - } - } - - /** - * Get added image ID - * - * @throws Mage_Api2_Exception - * @param string $imageFileUri - * @return int - */ - protected function _getCreatedImageId($imageFileUri) - { - $imageId = null; - - $imageData = Mage::getResourceModel('Mage_Catalog_Model_Resource_Product_Attribute_Backend_Media') - ->loadGallery($this->_getProduct(), $this->_getMediaGallery()); - foreach ($imageData as $image) { - if ($image['file'] == $imageFileUri) { - $imageId = $image['value_id']; - break; - } - } - if (!$imageId) { - $this->_critical('Unknown error during image save', Mage_Api2_Model_Server::HTTP_INTERNAL_ERROR); - } - return $imageId; - } - - /** - * Retrieve product images data - * - * @throws Mage_Api2_Exception - * @return array - */ - protected function _retrieve() - { - $result = array(); - $imageId = (int) $this->getRequest()->getParam('image'); - $galleryData = $this->_getProduct()->getData(self::GALLERY_ATTRIBUTE_CODE); - if (!isset($galleryData['images']) || !is_array($galleryData['images'])) { - $this->_critical('Product image not found', Mage_Api2_Model_Server::HTTP_NOT_FOUND); - } - foreach ($galleryData['images'] as &$image) { - if ($image['value_id'] == $imageId) { - $result = $this->_formatImageData($image); - break; - } - } - if (empty($result)) { - $this->_critical('Product image not found', Mage_Api2_Model_Server::HTTP_NOT_FOUND); - } - return $result; - } - - /** - * Update product image - * - * @throws Mage_Api2_Exception - * @param array $data - * @return bool - */ - protected function _update(array $data) - { - $imageId = (int)$this->getRequest()->getParam('image'); - $imageFileUri = $this->_getImageFileById($imageId); - $product = $this->_getProduct(); - $this->_getMediaGallery()->updateImage($product, $imageFileUri, $data); - if (isset($data['types']) && is_array($data['types'])) { - $assignedTypes = $this->_getImageTypesAssignedToProduct($imageFileUri); - $typesToBeCleared = array_diff($assignedTypes, $data['types']); - if (count($typesToBeCleared) > 0) { - $this->_getMediaGallery()->clearMediaAttribute($product, $typesToBeCleared); - } - $this->_getMediaGallery()->setMediaAttribute($product, $data['types'], $imageFileUri); - } - try { - $product->save(); - } catch (Mage_Core_Exception $e) { - $this->_critical($e->getMessage(), Mage_Api2_Model_Server::HTTP_INTERNAL_ERROR); - } catch (Exception $e) { - $this->_critical(self::RESOURCE_INTERNAL_ERROR); - } - } - - /** - * Product image delete - * - * @throws Mage_Api2_Exception - */ - protected function _delete() - { - $imageId = (int)$this->getRequest()->getParam('image'); - $product = $this->_getProduct(); - $imageFileUri = $this->_getImageFileById($imageId); - $this->_getMediaGallery()->removeImage($product, $imageFileUri); - try { - $product->save(); - } catch (Mage_Core_Exception $e) { - $this->_critical($e->getMessage(), Mage_Api2_Model_Server::HTTP_INTERNAL_ERROR); - } catch (Exception $e) { - $this->_critical(self::RESOURCE_INTERNAL_ERROR); - } - } - - /** - * Retrieve product images data - * - * @throws Mage_Api2_Exception - * @return array - */ - protected function _retrieveCollection() - { - $images = array(); - $galleryData = $this->_getProduct()->getData(self::GALLERY_ATTRIBUTE_CODE); - if (isset($galleryData['images']) && is_array($galleryData['images'])) { - foreach ($galleryData['images'] as $image) { - $images[] = $this->_formatImageData($image); - } - } - return $images; - } - - /** - * Get image resource location - * - * @param int $imageId - * @return string URL - */ - protected function _getImageLocation($imageId) - { - /* @var $apiTypeRoute Mage_Api2_Model_Route_ApiType */ - $apiTypeRoute = Mage::getModel('Mage_Api2_Model_Route_ApiType'); - - $chain = $apiTypeRoute->chain( - new Zend_Controller_Router_Route($this->getConfig()->getRouteWithEntityTypeAction($this->getResourceType())) - ); - $params = array( - 'api_type' => $this->getRequest()->getApiType(), - 'id' => $this->getRequest()->getParam('id'), - 'image' => $imageId - ); - $uri = $chain->assemble($params); - return '/' . $uri; - } -} diff --git a/app/code/core/Mage/Catalog/Model/Api2/Product/Image/Rest/Customer/V1.php b/app/code/core/Mage/Catalog/Model/Api2/Product/Image/Rest/Customer/V1.php deleted file mode 100644 index e573cb182210177013b9fc7db7de528d634e7d93..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Catalog/Model/Api2/Product/Image/Rest/Customer/V1.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Catalog - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 for product image. Customer role - * - * @category Mage - * @package Mage_Catalog - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Catalog_Model_Api2_Product_Image_Rest_Customer_V1 extends Mage_Catalog_Model_Api2_Product_Image_Rest -{ -} diff --git a/app/code/core/Mage/Catalog/Model/Api2/Product/Image/Rest/Guest/V1.php b/app/code/core/Mage/Catalog/Model/Api2/Product/Image/Rest/Guest/V1.php deleted file mode 100644 index 1c943e77938ea3e39c61054b0f14d59aadfb66ba..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Catalog/Model/Api2/Product/Image/Rest/Guest/V1.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Catalog - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 for product image. Guest role - * - * @category Mage - * @package Mage_Catalog - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Catalog_Model_Api2_Product_Image_Rest_Guest_V1 extends Mage_Catalog_Model_Api2_Product_Image_Rest -{ -} diff --git a/app/code/core/Mage/Catalog/Model/Api2/Product/Image/Validator/Image.php b/app/code/core/Mage/Catalog/Model/Api2/Product/Image/Validator/Image.php deleted file mode 100644 index 6aea6fdbbedc63b109e5e942d9120169da86f5a7..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Catalog/Model/Api2/Product/Image/Validator/Image.php +++ /dev/null @@ -1,53 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Catalog - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 Product image validator - * - * @category Mage - * @package Mage_Catalog - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Catalog_Model_Api2_Product_Image_Validator_Image extends Mage_Api2_Model_Resource_Validator -{ - /** - * Validate data. In case of validation failure return false, - * getErrors() could be used to retrieve list of validation error messages - * - * @param array $data - * @return bool - */ - public function isValidData(array $data) - { - if (!isset($data['file_content']) || !isset($data['file_mime_type']) || empty($data['file_content']) || - empty($data['file_mime_type']) - ) { - $this->_addError('The image is not specified'); - } - - return !count($this->getErrors()); - } -} diff --git a/app/code/core/Mage/Catalog/Model/Api2/Product/Rest.php b/app/code/core/Mage/Catalog/Model/Api2/Product/Rest.php deleted file mode 100644 index cb10291a76fc5b5ecbeb8f3bd1cdffedaf1ca870..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Catalog/Model/Api2/Product/Rest.php +++ /dev/null @@ -1,401 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Catalog - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Abstract API2 class for product instance - * - * @category Mage - * @package Mage_Catalog - * @author Magento Core Team <core@magentocommerce.com> - */ -abstract class Mage_Catalog_Model_Api2_Product_Rest extends Mage_Catalog_Model_Api2_Product -{ - /** - * Current loaded product - * - * @var Mage_Catalog_Model_Product - */ - protected $_product; - - /** - * Retrieve product data - * - * @return array - */ - protected function _retrieve() - { - $product = $this->_getProduct(); - - $this->_prepareProductForResponse($product); - return $product->getData(); - } - - /** - * Retrieve list of products - * - * @return array - */ - protected function _retrieveCollection() - { - /** @var $collection Mage_Catalog_Model_Resource_Product_Collection */ - $collection = Mage::getResourceModel('Mage_Catalog_Model_Resource_Product_Collection'); - $store = $this->_getStore(); - $entityOnlyAttributes = $this->getEntityOnlyAttributes($this->getUserType(), - Mage_Api2_Model_Resource::OPERATION_ATTRIBUTE_READ); - $availableAttributes = array_keys($this->getAvailableAttributes($this->getUserType(), - Mage_Api2_Model_Resource::OPERATION_ATTRIBUTE_READ)); - // available attributes not contain image attribute, but it needed for get image_url - $availableAttributes[] = 'image'; - $collection->addStoreFilter($store->getId()) - ->addPriceData($this->_getCustomerGroupId(), $store->getWebsiteId()) - ->addAttributeToSelect(array_diff($availableAttributes, $entityOnlyAttributes)) - ->addAttributeToFilter('visibility', array( - 'neq' => Mage_Catalog_Model_Product_Visibility::VISIBILITY_NOT_VISIBLE)) - ->addAttributeToFilter('status', array('eq' => Mage_Catalog_Model_Product_Status::STATUS_ENABLED)); - $this->_applyCategoryFilter($collection); - $this->_applyCollectionModifiers($collection); - $products = $collection->load(); - - /** @var Mage_Catalog_Model_Product $product */ - foreach ($products as $product) { - $this->_setProduct($product); - $this->_prepareProductForResponse($product); - } - return $products->toArray(); - } - - /** - * Apply filter by category id - * - * @param Mage_Catalog_Model_Resource_Product_Collection $collection - */ - protected function _applyCategoryFilter(Mage_Catalog_Model_Resource_Product_Collection $collection) - { - $categoryId = $this->getRequest()->getParam('category_id'); - if ($categoryId) { - $category = $this->_getCategoryById($categoryId); - if (!$category->getId()) { - $this->_critical('Category not found.', Mage_Api2_Model_Server::HTTP_BAD_REQUEST); - } - $collection->addCategoryFilter($category); - } - } - - /** - * Add special fields to product get response - * - * @param Mage_Catalog_Model_Product $product - */ - protected function _prepareProductForResponse(Mage_Catalog_Model_Product $product) - { - /** @var $productHelper Mage_Catalog_Helper_Product */ - $productHelper = Mage::helper('Mage_Catalog_Helper_Product'); - $productData = $product->getData(); - $product->setWebsiteId($this->_getStore()->getWebsiteId()); - // customer group is required in product for correct prices calculation - $product->setCustomerGroupId($this->_getCustomerGroupId()); - // calculate prices - $finalPrice = $product->getFinalPrice(); - $productData['regular_price_with_tax'] = $this->_applyTaxToPrice($product->getPrice(), true); - $productData['regular_price_without_tax'] = $this->_applyTaxToPrice($product->getPrice(), false); - $productData['final_price_with_tax'] = $this->_applyTaxToPrice($finalPrice, true); - $productData['final_price_without_tax'] = $this->_applyTaxToPrice($finalPrice, false); - - $productData['is_saleable'] = $product->getIsSalable(); - $productData['image_url'] = (string) Mage::helper('Mage_Catalog_Helper_Image')->init($product, 'image'); - - if ($this->getActionType() == self::ACTION_TYPE_ENTITY) { - // define URLs - $productData['url'] = $productHelper->getProductUrl($product->getId()); - /** @var $cartHelper Mage_Checkout_Helper_Cart */ - $cartHelper = Mage::helper('Mage_Checkout_Helper_Cart'); - $productData['buy_now_url'] = $cartHelper->getAddUrl($product); - - /** @var $stockItem Mage_CatalogInventory_Model_Stock_Item */ - $stockItem = $product->getStockItem(); - if (!$stockItem) { - $stockItem = Mage::getModel('Mage_CatalogInventory_Model_Stock_Item'); - $stockItem->loadByProduct($product); - } - $productData['is_in_stock'] = $stockItem->getIsInStock(); - - /** @var $reviewModel Mage_Review_Model_Review */ - $reviewModel = Mage::getModel('Mage_Review_Model_Review'); - $productData['total_reviews_count'] = $reviewModel->getTotalReviews($product->getId(), true, - $this->_getStore()->getId()); - - $productData['tier_price'] = $this->_getTierPrices(); - $productData['has_custom_options'] = count($product->getOptions()) > 0; - } else { - // remove tier price from response - $product->unsetData('tier_price'); - unset($productData['tier_price']); - } - $product->addData($productData); - } - - /** - * Product create only available for admin - * - * @param array $data - */ - protected function _create(array $data) - { - $this->_critical(self::RESOURCE_METHOD_NOT_ALLOWED); - } - - /** - * Product update only available for admin - * - * @param array $data - */ - protected function _update(array $data) - { - $this->_critical(self::RESOURCE_METHOD_NOT_ALLOWED); - } - - /** - * Product delete only available for admin - */ - protected function _delete() - { - $this->_critical(self::RESOURCE_METHOD_NOT_ALLOWED); - } - - /** - * Load product by its SKU or ID provided in request - * - * @return Mage_Catalog_Model_Product - */ - protected function _getProduct() - { - if (is_null($this->_product)) { - $productId = $this->getRequest()->getParam('id'); - /** @var $productHelper Mage_Catalog_Helper_Product */ - $productHelper = Mage::helper('Mage_Catalog_Helper_Product'); - $product = $productHelper->getProduct($productId, $this->_getStore()->getId()); - if (!($product->getId())) { - $this->_critical(self::RESOURCE_NOT_FOUND); - } - // check if product belongs to website current - if ($this->_getStore()->getId()) { - $isValidWebsite = in_array($this->_getStore()->getWebsiteId(), $product->getWebsiteIds()); - if (!$isValidWebsite) { - $this->_critical(self::RESOURCE_NOT_FOUND); - } - } - // Check display settings for customers & guests - if ($this->getApiUser()->getType() != Mage_Api2_Model_Auth_User_Admin::USER_TYPE) { - // check if product assigned to any website and can be shown - if ((!Mage::app()->hasSingleStore() && !count($product->getWebsiteIds())) - || !$productHelper->canShow($product) - ) { - $this->_critical(self::RESOURCE_NOT_FOUND); - } - } - $this->_product = $product; - } - return $this->_product; - } - - /** - * Set product - * - * @param Mage_Catalog_Model_Product $product - */ - protected function _setProduct(Mage_Catalog_Model_Product $product) - { - $this->_product = $product; - } - - /** - * Load category by id - * - * @param int $categoryId - * @return Mage_Catalog_Model_Category - */ - protected function _getCategoryById($categoryId) - { - return Mage::getModel('Mage_Catalog_Model_Category')->load($categoryId); - } - - /** - * Get product price with all tax settings processing - * - * @param float $price inputed product price - * @param bool $includingTax return price include tax flag - * @param null|Mage_Customer_Model_Address $shippingAddress - * @param null|Mage_Customer_Model_Address $billingAddress - * @param null|int $ctc customer tax class - * @param bool $priceIncludesTax flag that price parameter contain tax - * @return float - * @see Mage_Tax_Helper_Data::getPrice() - */ - protected function _getPrice($price, $includingTax = null, $shippingAddress = null, - $billingAddress = null, $ctc = null, $priceIncludesTax = null - ) { - $product = $this->_getProduct(); - $store = $this->_getStore(); - - if (is_null($priceIncludesTax)) { - /** @var $config Mage_Tax_Model_Config */ - $config = Mage::getSingleton('Mage_Tax_Model_Config'); - $priceIncludesTax = $config->priceIncludesTax($store) || $config->getNeedUseShippingExcludeTax(); - } - - $percent = $product->getTaxPercent(); - $includingPercent = null; - - $taxClassId = $product->getTaxClassId(); - if (is_null($percent)) { - if ($taxClassId) { - $request = Mage::getSingleton('Mage_Tax_Model_Calculation') - ->getRateRequest($shippingAddress, $billingAddress, $ctc, $store); - $percent = Mage::getSingleton('Mage_Tax_Model_Calculation')->getRate($request->setProductClassId($taxClassId)); - } - } - if ($taxClassId && $priceIncludesTax) { - $request = Mage::getSingleton('Mage_Tax_Model_Calculation')->getRateRequest(false, false, false, $store); - $includingPercent = Mage::getSingleton('Mage_Tax_Model_Calculation') - ->getRate($request->setProductClassId($taxClassId)); - } - - if ($percent === false || is_null($percent)) { - if ($priceIncludesTax && !$includingPercent) { - return $price; - } - } - $product->setTaxPercent($percent); - - if (!is_null($includingTax)) { - if ($priceIncludesTax) { - if ($includingTax) { - /** - * Recalculate price include tax in case of different rates - */ - if ($includingPercent != $percent) { - $price = $this->_calculatePrice($price, $includingPercent, false); - /** - * Using regular rounding. Ex: - * price incl tax = 52.76 - * store tax rate = 19.6% - * customer tax rate= 19% - * - * price excl tax = 52.76 / 1.196 = 44.11371237 ~ 44.11 - * tax = 44.11371237 * 0.19 = 8.381605351 ~ 8.38 - * price incl tax = 52.49531773 ~ 52.50 != 52.49 - * - * that why we need round prices excluding tax before applying tax - * this calculation is used for showing prices on catalog pages - */ - if ($percent != 0) { - $price = Mage::getSingleton('Mage_Tax_Model_Calculation')->round($price); - $price = $this->_calculatePrice($price, $percent, true); - } - } - } else { - $price = $this->_calculatePrice($price, $includingPercent, false); - } - } else { - if ($includingTax) { - $price = $this->_calculatePrice($price, $percent, true); - } - } - } else { - if ($priceIncludesTax) { - if ($includingTax) { - $price = $this->_calculatePrice($price, $includingPercent, false); - $price = $this->_calculatePrice($price, $percent, true); - } else { - $price = $this->_calculatePrice($price, $includingPercent, false); - } - } else { - if ($includingTax) { - $price = $this->_calculatePrice($price, $percent, true); - } - } - } - - return $store->roundPrice($price); - } - - /** - * Calculate price imcluding/excluding tax base on tax rate percent - * - * @param float $price - * @param float $percent - * @param bool $includeTax true - for calculate price including tax and false if price excluding tax - * @return float - */ - protected function _calculatePrice($price, $percent, $includeTax) - { - /** @var $calculator Mage_Tax_Model_Calculation */ - $calculator = Mage::getSingleton('Mage_Tax_Model_Calculation'); - $taxAmount = $calculator->calcTaxAmount($price, $percent, !$includeTax, false); - - return $includeTax ? $price + $taxAmount : $price - $taxAmount; - } - - /** - * Retrive tier prices in special format - * - * @return array - */ - protected function _getTierPrices() - { - $tierPrices = array(); - foreach ($this->_getProduct()->getTierPrice() as $tierPrice) { - $tierPrices[] = array( - 'qty' => $tierPrice['price_qty'], - 'price_with_tax' => $this->_applyTaxToPrice($tierPrice['price']), - 'price_without_tax' => $this->_applyTaxToPrice($tierPrice['price'], false) - ); - } - return $tierPrices; - } - - /** - * Default implementation. May be different for customer/guest/admin role. - * - * @return null - */ - protected function _getCustomerGroupId() - { - return null; - } - - /** - * Default implementation. May be different for customer/guest/admin role. - * - * @param float $price - * @param bool $withTax - * @return float - */ - protected function _applyTaxToPrice($price, $withTax = true) - { - return $price; - } -} diff --git a/app/code/core/Mage/Catalog/Model/Api2/Product/Rest/Admin/V1.php b/app/code/core/Mage/Catalog/Model/Api2/Product/Rest/Admin/V1.php deleted file mode 100644 index 9d8cc50c15a7ded465f31e5fffb8787575e915e6..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Catalog/Model/Api2/Product/Rest/Admin/V1.php +++ /dev/null @@ -1,395 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Catalog - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 for catalog_product (Admin) - * - * @category Mage - * @package Mage_Catalog - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Catalog_Model_Api2_Product_Rest_Admin_V1 extends Mage_Catalog_Model_Api2_Product_Rest -{ - /** - * The greatest decimal value which could be stored. Corresponds to DECIMAL (12,4) SQL type - */ - const MAX_DECIMAL_VALUE = 99999999.9999; - - /** - * Add special fields to product get response - * - * @param Mage_Catalog_Model_Product $product - */ - protected function _prepareProductForResponse(Mage_Catalog_Model_Product $product) - { - $pricesFilterKeys = array('price_id', 'all_groups', 'website_price'); - $groupPrice = $product->getData('group_price'); - $product->setData('group_price', $this->_filterOutArrayKeys($groupPrice, $pricesFilterKeys, true)); - $tierPrice = $product->getData('tier_price'); - $product->setData('tier_price', $this->_filterOutArrayKeys($tierPrice, $pricesFilterKeys, true)); - - $stockData = $product->getStockItem()->getData(); - $stockDataFilterKeys = array('item_id', 'product_id', 'stock_id', 'low_stock_date', 'type_id', - 'stock_status_changed_auto', 'stock_status_changed_automatically', 'product_name', 'store_id', - 'product_type_id', 'product_status_changed', 'product_changed_websites', - 'use_config_enable_qty_increments'); - $product->setData('stock_data', $this->_filterOutArrayKeys($stockData, $stockDataFilterKeys)); - $product->setData('product_type_name', $product->getTypeId()); - } - - /** - * Remove specified keys from associative or indexed array - * - * @param array $array - * @param array $keys - * @param bool $dropOrigKeys if true - return array as indexed array - * @return array - */ - protected function _filterOutArrayKeys(array $array, array $keys, $dropOrigKeys = false) - { - $isIndexedArray = is_array(reset($array)); - if ($isIndexedArray) { - foreach ($array as &$value) { - if (is_array($value)) { - $value = array_diff_key($value, array_flip($keys)); - } - } - if ($dropOrigKeys) { - $array = array_values($array); - } - unset($value); - } else { - $array = array_diff_key($array, array_flip($keys)); - } - - return $array; - } - - /** - * Retrieve list of products - * - * @return array - */ - protected function _retrieveCollection() - { - /** @var $collection Mage_Catalog_Model_Resource_Product_Collection */ - $collection = Mage::getResourceModel('Mage_Catalog_Model_Resource_Product_Collection'); - $store = $this->_getStore(); - $collection->setStoreId($store->getId()); - $collection->addAttributeToSelect(array_keys( - $this->getAvailableAttributes($this->getUserType(), Mage_Api2_Model_Resource::OPERATION_ATTRIBUTE_READ) - )); - $this->_applyCategoryFilter($collection); - $this->_applyCollectionModifiers($collection); - $products = $collection->load()->toArray(); - return $products; - } - - /** - * Delete product by its ID - * - * @throws Mage_Api2_Exception - */ - protected function _delete() - { - $product = $this->_getProduct(); - try { - $product->delete(); - } catch (Mage_Core_Exception $e) { - $this->_critical($e->getMessage(), Mage_Api2_Model_Server::HTTP_INTERNAL_ERROR); - } catch (Exception $e) { - $this->_critical(self::RESOURCE_INTERNAL_ERROR); - } - } - - /** - * Create product - * - * @param array $data - * @return string - */ - protected function _create(array $data) - { - /* @var $validator Mage_Catalog_Model_Api2_Product_Validator_Product */ - $validator = Mage::getModel('Mage_Catalog_Model_Api2_Product_Validator_Product', - array('options' => - array( - 'operation' => self::OPERATION_CREATE - ))); - - if (!$validator->isValidData($data)) { - foreach ($validator->getErrors() as $error) { - $this->_error($error, Mage_Api2_Model_Server::HTTP_BAD_REQUEST); - } - $this->_critical(self::RESOURCE_DATA_PRE_VALIDATION_ERROR); - } - - $type = $data['type_id']; - if ($type !== 'simple') { - $this->_critical("Creation of products with type '$type' is not implemented", - Mage_Api2_Model_Server::HTTP_METHOD_NOT_ALLOWED); - } - $set = $data['attribute_set_id']; - $sku = $data['sku']; - - /** @var $product Mage_Catalog_Model_Product */ - $product = Mage::getModel('Mage_Catalog_Model_Product') - ->setStoreId(Mage_Catalog_Model_Abstract::DEFAULT_STORE_ID) - ->setAttributeSetId($set) - ->setTypeId($type) - ->setSku($sku); - - foreach ($product->getMediaAttributes() as $mediaAttribute) { - $mediaAttrCode = $mediaAttribute->getAttributeCode(); - $product->setData($mediaAttrCode, 'no_selection'); - } - - $this->_prepareDataForSave($product, $data); - try { - $product->validate(); - $product->save(); - $this->_multicall($product->getId()); - } catch (Mage_Eav_Model_Entity_Attribute_Exception $e) { - $this->_critical(sprintf('Invalid attribute "%s": %s', $e->getAttributeCode(), $e->getMessage()), - Mage_Api2_Model_Server::HTTP_BAD_REQUEST); - } catch (Mage_Core_Exception $e) { - $this->_critical($e->getMessage(), Mage_Api2_Model_Server::HTTP_INTERNAL_ERROR); - } catch (Exception $e) { - $this->_critical(self::RESOURCE_UNKNOWN_ERROR); - } - - return $this->_getLocation($product); - } - - /** - * Update product by its ID - * - * @param array $data - */ - protected function _update(array $data) - { - /** @var $product Mage_Catalog_Model_Product */ - $product = $this->_getProduct(); - /* @var $validator Mage_Catalog_Model_Api2_Product_Validator_Product */ - $validator = Mage::getModel('Mage_Catalog_Model_Api2_Product_Validator_Product', - array('options' => - array( - 'operation' => self::OPERATION_UPDATE, - 'product' => $product - ))); - - if (!$validator->isValidData($data)) { - foreach ($validator->getErrors() as $error) { - $this->_error($error, Mage_Api2_Model_Server::HTTP_BAD_REQUEST); - } - $this->_critical(self::RESOURCE_DATA_PRE_VALIDATION_ERROR); - } - if (isset($data['sku'])) { - $product->setSku($data['sku']); - } - // attribute set and product type cannot be updated - unset($data['attribute_set_id']); - unset($data['type_id']); - $this->_prepareDataForSave($product, $data); - try { - $product->validate(); - $product->save(); - } catch (Mage_Eav_Model_Entity_Attribute_Exception $e) { - $this->_critical(sprintf('Invalid attribute "%s": %s', $e->getAttributeCode(), $e->getMessage()), - Mage_Api2_Model_Server::HTTP_BAD_REQUEST); - } catch (Mage_Core_Exception $e) { - $this->_critical($e->getMessage(), Mage_Api2_Model_Server::HTTP_INTERNAL_ERROR); - } catch (Exception $e) { - $this->_critical(self::RESOURCE_UNKNOWN_ERROR); - } - } - - /** - * Determine if stock management is enabled - * - * @param array $stockData - * @return bool - */ - protected function _isManageStockEnabled($stockData) - { - if (!(isset($stockData['use_config_manage_stock']) && $stockData['use_config_manage_stock'])) { - $manageStock = isset($stockData['manage_stock']) && $stockData['manage_stock']; - } else { - $manageStock = Mage::getStoreConfig( - Mage_CatalogInventory_Model_Stock_Item::XML_PATH_ITEM . 'manage_stock'); - } - return (bool) $manageStock; - } - - /** - * Check if value from config is used - * - * @param array $data - * @param string $field - * @return bool - */ - protected function _isConfigValueUsed($data, $field) - { - return isset($data["use_config_$field"]) && $data["use_config_$field"]; - } - - /** - * Set additional data before product save - * - * @param Mage_Catalog_Model_Product $product - * @param array $productData - */ - protected function _prepareDataForSave($product, $productData) - { - if (isset($productData['stock_data'])) { - if (!$product->isObjectNew() && !isset($productData['stock_data']['manage_stock'])) { - $productData['stock_data']['manage_stock'] = $product->getStockItem()->getManageStock(); - } - $this->_filterStockData($productData['stock_data']); - } else { - $productData['stock_data'] = array( - 'use_config_manage_stock' => 1, - 'use_config_min_sale_qty' => 1, - 'use_config_max_sale_qty' => 1, - ); - } - $product->setStockData($productData['stock_data']); - // save gift options - $this->_filterConfigValueUsed($productData, array('gift_message_available', 'gift_wrapping_available')); - if (isset($productData['use_config_gift_message_available'])) { - $product->setData('use_config_gift_message_available', $productData['use_config_gift_message_available']); - if (!$productData['use_config_gift_message_available'] - && ($product->getData('gift_message_available') === null)) { - $product->setData('gift_message_available', (int) Mage::getStoreConfig( - Mage_GiftMessage_Helper_Message::XPATH_CONFIG_GIFT_MESSAGE_ALLOW_ITEMS, $product->getStoreId())); - } - } - if (isset($productData['use_config_gift_wrapping_available'])) { - $product->setData('use_config_gift_wrapping_available', $productData['use_config_gift_wrapping_available']); - if (!$productData['use_config_gift_wrapping_available'] - && ($product->getData('gift_wrapping_available') === null) - ) { - $xmlPathGiftWrappingAvailable = 'sales/gift_options/wrapping_allow_items'; - $product->setData('gift_wrapping_available', (int)Mage::getStoreConfig( - $xmlPathGiftWrappingAvailable, $product->getStoreId())); - } - } - - if (isset($productData['website_ids']) && is_array($productData['website_ids'])) { - $product->setWebsiteIds($productData['website_ids']); - } - // Create Permanent Redirect for old URL key - if (!$product->isObjectNew() && isset($productData['url_key']) - && isset($productData['url_key_create_redirect']) - ) { - $product->setData('save_rewrites_history', (bool)$productData['url_key_create_redirect']); - } - /** @var $attribute Mage_Catalog_Model_Resource_Eav_Attribute */ - foreach ($product->getTypeInstance()->getEditableAttributes($product) as $attribute) { - //Unset data if object attribute has no value in current store - if (Mage_Catalog_Model_Abstract::DEFAULT_STORE_ID !== (int)$product->getStoreId() - && !$product->getExistsStoreValueFlag($attribute->getAttributeCode()) - && !$attribute->isScopeGlobal() - ) { - $product->setData($attribute->getAttributeCode(), false); - } - - if ($this->_isAllowedAttribute($attribute)) { - if (isset($productData[$attribute->getAttributeCode()])) { - $product->setData( - $attribute->getAttributeCode(), - $productData[$attribute->getAttributeCode()] - ); - } - } - } - } - - /** - * Filter stock data values - * - * @param array $stockData - */ - protected function _filterStockData(&$stockData) - { - $fieldsWithPossibleDefautlValuesInConfig = array('manage_stock', 'min_sale_qty', 'max_sale_qty', 'backorders', - 'qty_increments', 'notify_stock_qty', 'min_qty', 'enable_qty_increments'); - $this->_filterConfigValueUsed($stockData, $fieldsWithPossibleDefautlValuesInConfig); - - if ($this->_isManageStockEnabled($stockData)) { - if (isset($stockData['qty']) && (float)$stockData['qty'] > self::MAX_DECIMAL_VALUE) { - $stockData['qty'] = self::MAX_DECIMAL_VALUE; - } - if (isset($stockData['min_qty']) && (int)$stockData['min_qty'] < 0) { - $stockData['min_qty'] = 0; - } - if (!isset($stockData['is_decimal_divided']) || $stockData['is_qty_decimal'] == 0) { - $stockData['is_decimal_divided'] = 0; - } - } else { - $nonManageStockFields = array('manage_stock', 'use_config_manage_stock', 'min_sale_qty', - 'use_config_min_sale_qty', 'max_sale_qty', 'use_config_max_sale_qty'); - foreach ($stockData as $field => $value) { - if (!in_array($field, $nonManageStockFields)) { - unset($stockData[$field]); - } - } - } - } - - /** - * Filter out fields if Use Config Settings option used - * - * @param array $data - * @param string $fields - */ - protected function _filterConfigValueUsed(&$data, $fields) { - foreach($fields as $field) { - if ($this->_isConfigValueUsed($data, $field)) { - unset($data[$field]); - } - } - } - - /** - * Check if attribute is allowed - * - * @param Mage_Eav_Model_Entity_Attribute_Abstract $attribute - * @param array $attributes - * @return boolean - */ - protected function _isAllowedAttribute($attribute, $attributes = null) - { - $isAllowed = true; - if (is_array($attributes) - && !(in_array($attribute->getAttributeCode(), $attributes) - || in_array($attribute->getAttributeId(), $attributes)) - ) { - $isAllowed = false; - } - return $isAllowed; - } -} diff --git a/app/code/core/Mage/Catalog/Model/Api2/Product/Rest/Customer/V1.php b/app/code/core/Mage/Catalog/Model/Api2/Product/Rest/Customer/V1.php deleted file mode 100644 index f54dd8905262b3bdbf5c5b69e53468f900580e56..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Catalog/Model/Api2/Product/Rest/Customer/V1.php +++ /dev/null @@ -1,90 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Catalog - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 for catalog_product (Customer) - * - * @category Mage - * @package Mage_Catalog - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Catalog_Model_Api2_Product_Rest_Customer_V1 extends Mage_Catalog_Model_Api2_Product_Rest -{ - /** - * Current logged in customer - * - * @var Mage_Customer_Model_Customer - */ - protected $_customer; - - /** - * Get customer group - * - * @return int - */ - protected function _getCustomerGroupId() - { - return $this->_getCustomer()->getGroupId(); - } - - /** - * Define product price with or without taxes - * - * @param float $price - * @param bool $withTax - * @return float - */ - protected function _applyTaxToPrice($price, $withTax = true) - { - $customer = $this->_getCustomer(); - /** @var $session Mage_Customer_Model_Session */ - $session = Mage::getSingleton('Mage_Customer_Model_Session'); - $session->setCustomerId($customer->getId()); - $price = $this->_getPrice($price, $withTax, $customer->getPrimaryShippingAddress(), - $customer->getPrimaryBillingAddress(), $customer->getTaxClassId()); - $session->setCustomerId(null); - - return $price; - } - - /** - * Retrieve current customer - * - * @return Mage_Customer_Model_Customer - */ - protected function _getCustomer() - { - if (is_null($this->_customer)) { - /** @var $customer Mage_Customer_Model_Customer */ - $customer = Mage::getModel('Mage_Customer_Model_Customer')->load($this->getApiUser()->getUserId()); - if (!$customer->getId()) { - $this->_critical('Customer not found.', Mage_Api2_Model_Server::HTTP_INTERNAL_ERROR); - } - $this->_customer = $customer; - } - return $this->_customer; - } -} diff --git a/app/code/core/Mage/Catalog/Model/Api2/Product/Rest/Guest/V1.php b/app/code/core/Mage/Catalog/Model/Api2/Product/Rest/Guest/V1.php deleted file mode 100644 index ac8fccd7a697b055699a9656d38b951840fdb448..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Catalog/Model/Api2/Product/Rest/Guest/V1.php +++ /dev/null @@ -1,57 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Catalog - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 for catalog_product (Guest) - * - * @category Mage - * @package Mage_Catalog - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Catalog_Model_Api2_Product_Rest_Guest_V1 extends Mage_Catalog_Model_Api2_Product_Rest -{ - /** - * Get customer group - * - * @return int - */ - protected function _getCustomerGroupId() - { - return Mage_Customer_Model_Group::NOT_LOGGED_IN_ID; - } - - /** - * Define product price with or without taxes - * - * @param float $price - * @param bool $withTax - * @return float - */ - protected function _applyTaxToPrice($price, $withTax = true) - { - return $this->_getPrice($price, $withTax); - } -} diff --git a/app/code/core/Mage/Catalog/Model/Api2/Product/Validator/Product.php b/app/code/core/Mage/Catalog/Model/Api2/Product/Validator/Product.php deleted file mode 100644 index 8bc2a0f22c0171b33811bad6465e3cf3bc540b9f..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Catalog/Model/Api2/Product/Validator/Product.php +++ /dev/null @@ -1,610 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Catalog - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 catalog_product Validator - * - * @category Mage - * @package Mage_Catalog - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Catalog_Model_Api2_Product_Validator_Product extends Mage_Api2_Model_Resource_Validator -{ - /** - * The greatest decimal value which could be stored. Corresponds to DECIMAL (12,4) SQL type - */ - const MAX_DECIMAL_VALUE = 99999999.9999; - - /** - * Validator product - * - * @var Mage_Catalog_Model_Product - */ - protected $_product = null; - - /** - * Validation operation - * - * @var string - */ - protected $_operation = null; - - public function __construct($options) - { - if (isset($options['product'])) { - if ($options['product'] instanceof Mage_Catalog_Model_Product) { - $this->_product = $options['product']; - } else { - throw new Exception("Passed parameter 'product' is wrong."); - } - } - - if (!isset($options['operation']) || empty($options['operation'])) { - throw new Exception("Passed parameter 'operation' is empty."); - } - $this->_operation = $options['operation']; - } - - /** - * Get validator product - * - * @return Mage_Catalog_Model_Product|null - */ - protected function _getProduct() - { - return $this->_product; - } - - /** - * Is update mode - * - * @return bool - */ - protected function _isUpdate() - { - return $this->_operation == Mage_Api2_Model_Resource::OPERATION_UPDATE; - } - - /** - * Validate product data - * - * @param array $data - * @return bool - */ - public function isValidData(array $data) - { - if ($this->_isUpdate()) { - $product = $this->_getProduct(); - if (!is_null($product) && $product->getId()) { - $data['attribute_set_id'] = $product->getAttributeSetId(); - $data['type_id'] = $product->getTypeId(); - } - } - - try { - $this->_validateProductType($data); - /** @var $productEntity Mage_Eav_Model_Entity_Type */ - $productEntity = Mage::getModel('Mage_Eav_Model_Entity_Type')->loadByCode(Mage_Catalog_Model_Product::ENTITY); - $this->_validateAttributeSet($data, $productEntity); - $this->_validateSku($data); - $this->_validateGiftOptions($data); - $this->_validateGroupPrice($data); - $this->_validateTierPrice($data); - $this->_validateStockData($data); - $this->_validateAttributes($data, $productEntity); - $isSatisfied = count($this->getErrors()) == 0; - } catch (Mage_Api2_Exception $e) { - $this->_addError($e->getMessage()); - $isSatisfied = false; - } - - - return $isSatisfied; - } - - /** - * Collect required EAV attributes, validate applicable attributes and validate source attributes values - * - * @param array $data - * @param Mage_Eav_Model_Entity_Type $productEntity - * @return array - */ - protected function _validateAttributes($data, $productEntity) - { - if (!isset($data['attribute_set_id']) || empty($data['attribute_set_id'])) { - $this->_critical('Missing "attribute_set_id" in request.', Mage_Api2_Model_Server::HTTP_BAD_REQUEST); - } - if (!isset($data['type_id']) || empty($data['type_id'])) { - $this->_critical('Missing "type_id" in request.', Mage_Api2_Model_Server::HTTP_BAD_REQUEST); - } - // Validate weight - if (isset($data['weight']) && !empty($data['weight']) && $data['weight'] > 0 - && !Zend_Validate::is($data['weight'], 'Between', array(0, self::MAX_DECIMAL_VALUE))) { - $this->_addError('The "weight" value is not within the specified range.'); - } - // msrp_display_actual_price_type attribute values needs to be a string to pass validation - // see Mage_Catalog_Model_Product_Attribute_Source_Msrp_Type_Price::getAllOptions() - if (isset($data['msrp_display_actual_price_type'])) { - $data['msrp_display_actual_price_type'] = (string) $data['msrp_display_actual_price_type']; - } - $requiredAttributes = array('attribute_set_id'); - $positiveNumberAttributes = array('weight', 'price', 'special_price', 'msrp'); - /** @var $attribute Mage_Catalog_Model_Resource_Eav_Attribute */ - foreach ($productEntity->getAttributeCollection($data['attribute_set_id']) as $attribute) { - $attributeCode = $attribute->getAttributeCode(); - $value = false; - $isSet = false; - if (isset($data[$attribute->getAttributeCode()])) { - $value = $data[$attribute->getAttributeCode()]; - $isSet = true; - } - $applicable = false; - if (!$attribute->getApplyTo() || in_array($data['type_id'], $attribute->getApplyTo())) { - $applicable = true; - } - - if (!$applicable && !$attribute->isStatic() && $isSet) { - $productTypes = Mage_Catalog_Model_Product_Type::getTypes(); - $this->_addError(sprintf('Attribute "%s" is not applicable for product type "%s"', $attributeCode, - $productTypes[$data['type_id']]['label'])); - } - - if ($applicable && $isSet) { - // Validate dropdown attributes - if ($attribute->usesSource() - // skip check when field will be validated later as a required one - && !(empty($value) && $attribute->getIsRequired())) { - $allowedValues = $this->_getAttributeAllowedValues($attribute->getSource()->getAllOptions()); - if (!is_array($value)) { - // make validation of select and multiselect identical - $value = array($value); - } - foreach ($value as $selectValue) { - $useStrictMode = !is_numeric($selectValue); - if (!in_array($selectValue, $allowedValues, $useStrictMode) - && !$this->_isConfigValueUsed($data, $attributeCode)) { - $this->_addError(sprintf('Invalid value "%s" for attribute "%s".', - $selectValue, $attributeCode)); - } - } - } - // Validate datetime attributes - if ($attribute->getBackendType() == 'datetime') { - try { - $attribute->getBackend()->formatDate($value); - } catch (Zend_Date_Exception $e) { - $this->_addError(sprintf('Invalid date in the "%s" field.', $attributeCode)); - } - } - // Validate positive number required attributes - if (in_array($attributeCode, $positiveNumberAttributes) && (!empty($value) && $value !== 0) - && (!is_numeric($value) || $value < 0) - ) { - $this->_addError(sprintf('Please enter a number 0 or greater in the "%s" field.', $attributeCode)); - } - } - - if ($applicable && $attribute->getIsRequired() && $attribute->getIsVisible()) { - if (!in_array($attributeCode, $positiveNumberAttributes) || $value !== 0) { - $requiredAttributes[] = $attribute->getAttributeCode(); - } - } - } - - foreach ($requiredAttributes as $key) { - if (!array_key_exists($key, $data)) { - if (!$this->_isUpdate()) { - $this->_addError(sprintf('Missing "%s" in request.', $key)); - continue; - } - } else if (!is_numeric($data[$key]) && empty($data[$key])) { - $this->_addError(sprintf('Empty value for "%s" in request.', $key)); - } - } - } - - /** - * Validate product type - * - * @param array $data - * @return bool - */ - protected function _validateProductType($data) - { - if ($this->_isUpdate()) { - return true; - } - if (!isset($data['type_id']) || empty($data['type_id'])) { - $this->_critical('Missing "type_id" in request.', Mage_Api2_Model_Server::HTTP_BAD_REQUEST); - } - if (!array_key_exists($data['type_id'], Mage_Catalog_Model_Product_Type::getTypes())) { - $this->_critical('Invalid product type.', Mage_Api2_Model_Server::HTTP_BAD_REQUEST); - } - } - - /** - * Validate attribute set - * - * @param array $data - * @param Mage_Eav_Model_Entity_Type $productEntity - * @return bool - */ - protected function _validateAttributeSet($data, $productEntity) - { - if ($this->_isUpdate()) { - return true; - } - if (!isset($data['attribute_set_id']) || empty($data['attribute_set_id'])) { - $this->_critical('Missing "attribute_set_id" in request.', Mage_Api2_Model_Server::HTTP_BAD_REQUEST); - } - /** @var $attributeSet Mage_Eav_Model_Entity_Attribute_Set */ - $attributeSet = Mage::getModel('Mage_Eav_Model_Entity_Attribute_Set')->load($data['attribute_set_id']); - if (!$attributeSet->getId() || $productEntity->getEntityTypeId() != $attributeSet->getEntityTypeId()) { - $this->_critical('Invalid attribute set.', Mage_Api2_Model_Server::HTTP_BAD_REQUEST); - } - } - - /** - * Validate SKU - * - * @param array $data - * @return bool - */ - protected function _validateSku($data) - { - if ($this->_isUpdate() && !isset($data['sku'])) { - return true; - } - if (!Zend_Validate::is((string)$data['sku'], 'StringLength', array('min' => 0, 'max' => 64))) { - $this->_addError('SKU length should be 64 characters maximum.'); - } - } - - /** - * Validate product gift options data - * - * @param array $data - */ - protected function _validateGiftOptions($data) - { - if (isset($data['gift_wrapping_price'])) { - if (!(is_numeric($data['gift_wrapping_price']) && $data['gift_wrapping_price'] >= 0)) { - $this->_addError('Please enter a number 0 or greater in the "gift_wrapping_price" field.'); - } - } - } - - /** - * Validate Group Price complex attribute - * - * @param array $data - */ - protected function _validateGroupPrice($data) - { - if (isset($data['group_price']) && is_array($data['group_price'])) { - $groupPrices = $data['group_price']; - foreach ($groupPrices as $index => $groupPrice) { - $fieldSet = 'group_price:' . $index; - $this->_validateWebsiteIdForGroupPrice($groupPrice, $fieldSet); - $this->_validateCustomerGroup($groupPrice, $fieldSet); - $this->_validatePositiveNumber($groupPrice, $fieldSet, 'price', true, true); - } - } - } - - /** - * Validate Tier Price complex attribute - * - * @param array $data - */ - protected function _validateTierPrice($data) - { - if (isset($data['tier_price']) && is_array($data['tier_price'])) { - $tierPrices = $data['tier_price']; - foreach ($tierPrices as $index => $tierPrice) { - $fieldSet = 'tier_price:' . $index; - $this->_validateWebsiteIdForGroupPrice($tierPrice, $fieldSet); - $this->_validateCustomerGroup($tierPrice, $fieldSet); - $this->_validatePositiveNumber($tierPrice, $fieldSet, 'price_qty'); - $this->_validatePositiveNumber($tierPrice, $fieldSet, 'price'); - } - } - } - - /** - * Check if website id is appropriate according to price scope settings - * - * @param array $data - * @param string $fieldSet - */ - protected function _validateWebsiteIdForGroupPrice($data, $fieldSet) - { - if (!isset($data['website_id'])) { - $this->_addError(sprintf('The "website_id" value in the "%s" set is a required field.', $fieldSet)); - } else { - /** @var $catalogHelper Mage_Catalog_Helper_Data */ - $catalogHelper = Mage::helper('Mage_Catalog_Helper_Data'); - $website = Mage::getModel('Mage_Core_Model_Website')->load($data['website_id']); - $isAllWebsitesValue = is_numeric($data['website_id']) && ($data['website_id'] == 0); - $isGlobalPriceScope = (int)$catalogHelper->getPriceScope() == Mage_Catalog_Helper_Data::PRICE_SCOPE_GLOBAL; - if (is_null($website->getId()) || ($isGlobalPriceScope && !$isAllWebsitesValue)) { - $this->_addError(sprintf('Invalid "website_id" value in the "%s" set.', $fieldSet)); - } - } - } - - /** - * Validate product inventory data - * - * @param array $data - */ - protected function _validateStockData($data) - { - if (isset($data['stock_data']) && is_array($data['stock_data'])) { - $stockData = $data['stock_data']; - $fieldSet = 'stock_data'; - if (!(isset($stockData['use_config_manage_stock']) && $stockData['use_config_manage_stock'])) { - $this->_validateBoolean($stockData, $fieldSet, 'manage_stock'); - } - if ($this->_isManageStockEnabled($stockData)) { - $this->_validateNumeric($stockData, $fieldSet, 'qty'); - $this->_validatePositiveNumber($stockData, $fieldSet, 'min_qty', false, true, true); - $this->_validateNumeric($stockData, $fieldSet, 'notify_stock_qty', false, true); - $this->_validateBoolean($stockData, $fieldSet, 'is_qty_decimal'); - if (isset($stockData['is_qty_decimal']) && (bool) $stockData['is_qty_decimal'] == true) { - $this->_validateBoolean($stockData, $fieldSet, 'is_decimal_divided'); - } - $this->_validateBoolean($stockData, $fieldSet, 'enable_qty_increments', true); - if (isset($stockData['enable_qty_increments']) && (bool) $stockData['enable_qty_increments'] == true) { - $this->_validatePositiveNumeric($stockData, $fieldSet, 'qty_increments', false, true); - } - if (Mage::helper('Mage_Catalog_Helper_Data')->isModuleEnabled('Mage_CatalogInventory')) { - $this->_validateSource($stockData, $fieldSet, 'backorders', - 'cataloginventory/source_backorders', true); - $this->_validateSource($stockData, $fieldSet, 'is_in_stock', 'cataloginventory/source_stock'); - } - } - - $this->_validatePositiveNumeric($stockData, $fieldSet, 'min_sale_qty', false, true); - $this->_validatePositiveNumeric($stockData, $fieldSet, 'max_sale_qty', false, true); - } - } - - /** - * Determine if stock management is enabled - * - * @param array $stockData - * @return bool - */ - protected function _isManageStockEnabled($stockData) - { - if (!(isset($stockData['use_config_manage_stock']) && $stockData['use_config_manage_stock'])) { - $manageStock = isset($stockData['manage_stock']) && $stockData['manage_stock']; - } else { - $manageStock = Mage::getStoreConfig( - Mage_CatalogInventory_Model_Stock_Item::XML_PATH_ITEM . 'manage_stock'); - } - return (bool) $manageStock; - } - - /** - * Validate Customer Group field - * - * @param string $fieldSet - * @param array $data - */ - protected function _validateCustomerGroup($data, $fieldSet) - { - if (!isset($data['cust_group'])) { - $this->_addError(sprintf('The "cust_group" value in the "%s" set is a required field.', $fieldSet)); - } else { - if (!is_numeric($data['cust_group'])) { - $this->_addError(sprintf('Invalid "cust_group" value in the "%s" set', $fieldSet)); - } else { - $customerGroup = Mage::getModel('Mage_Customer_Model_Group')->load($data['cust_group']); - if (is_null($customerGroup->getId())) { - $this->_addError(sprintf('Invalid "cust_group" value in the "%s" set', $fieldSet)); - } - } - } - } - - /** - * Validate field to be positive number - * - * @param array $data - * @param string $fieldSet - * @param string $field - * @param bool $required - * @param bool $equalsZero - * @param bool $skipIfConfigValueUsed - */ - protected function _validatePositiveNumber($data, $fieldSet, $field, $required = true, $equalsZero = false, - $skipIfConfigValueUsed = false) - { - // in case when 'Use Config Settings' is selected no validation needed - if (!($skipIfConfigValueUsed && $this->_isConfigValueUsed($data, $field))) { - if (!isset($data[$field]) && $required) { - $this->_addError(sprintf('The "%s" value in the "%s" set is a required field.', $field, $fieldSet)); - } - - if (isset($data[$field])) { - $isValid = $equalsZero ? $data[$field] >= 0 : $data[$field] > 0; - if (!(is_numeric($data[$field]) && $isValid)) { - $message = $equalsZero - ? 'Please enter a number 0 or greater in the "%s" field in the "%s" set.' - : 'Please enter a number greater than 0 in the "%s" field in the "%s" set.'; - $this->_addError(sprintf($message, $field, $fieldSet)); - } - } - } - } - - /** - * Validate field to be a positive number - * - * @param array $data - * @param string $fieldSet - * @param string $field - * @param bool $required - * @param bool $skipIfConfigValueUsed - */ - protected function _validatePositiveNumeric($data, $fieldSet, $field, $required = false, - $skipIfConfigValueUsed = false) - { - // in case when 'Use Config Settings' is selected no validation needed - if (!($skipIfConfigValueUsed && $this->_isConfigValueUsed($data, $field))) { - if (!isset($data[$field]) && $required) { - $this->_addError(sprintf('The "%s" value in the "%s" set is a required field.',$field, $fieldSet)); - } - - if (isset($data[$field]) && (!is_numeric($data[$field]) || $data[$field] < 0)) { - $this->_addError(sprintf('Please use numbers only in the "%s" field in the "%s" set. ' . - 'Please avoid spaces or other non numeric characters.', $field, $fieldSet)); - } - } - } - - /** - * Validate field to be a number - * - * @param array $data - * @param string $fieldSet - * @param string $field - * @param bool $required - * @param bool $skipIfConfigValueUsed - */ - protected function _validateNumeric($data, $fieldSet, $field, $required = false, $skipIfConfigValueUsed = false) - { - // in case when 'Use Config Settings' is selected no validation needed - if (!($skipIfConfigValueUsed && $this->_isConfigValueUsed($data, $field))) { - if (!isset($data[$field]) && $required) { - $this->_addError(sprintf('The "%s" value in the "%s" set is a required field.',$field, $fieldSet)); - } - - if (isset($data[$field]) && !is_numeric($data[$field])) { - $this->_addError(sprintf('Please enter a valid number in the "%s" field in the "%s" set.', - $field, $fieldSet)); - } - } - } - - /** - * Validate dropdown fields value - * - * @param array $data - * @param string $fieldSet - * @param string $field - * @param string $sourceModelName - * @param bool $skipIfConfigValueUsed - */ - protected function _validateSource($data, $fieldSet, $field, $sourceModelName, $skipIfConfigValueUsed = false) - { - // in case when 'Use Config Settings' is selected no validation needed - if (!($skipIfConfigValueUsed && $this->_isConfigValueUsed($data, $field))) { - if (isset($data[$field])) { - $sourceModel = Mage::getSingleton($sourceModelName); - if ($sourceModel) { - $allowedValues = $this->_getAttributeAllowedValues($sourceModel->toOptionArray()); - $useStrictMode = !is_numeric($data[$field]); - if (!in_array($data[$field], $allowedValues, $useStrictMode)) { - $this->_addError(sprintf('Invalid "%s" value in the "%s" set.', $field, $fieldSet)); - } - } - } - } - } - - /** - * Validate bolean fields value - * - * @param array $data - * @param string $fieldSet - * @param string $field - * @param bool $skipIfConfigValueUsed - */ - protected function _validateBoolean($data, $fieldSet, $field, $skipIfConfigValueUsed = false) - { - // in case when 'Use Config Settings' is selected no validation needed - if (!($skipIfConfigValueUsed && $this->_isConfigValueUsed($data, $field))) { - if (isset($data[$field])) { - $allowedValues = $this->_getAttributeAllowedValues( - Mage::getSingleton('Mage_Eav_Model_Entity_Attribute_Source_Boolean')->getAllOptions()); - $useStrictMode = !is_numeric($data[$field]); - if (!in_array($data[$field], $allowedValues, $useStrictMode)) { - $this->_addError(sprintf('Invalid "%s" value in the "%s" set.', $field, $fieldSet)); - } - } - } - } - - /** - * Retrieve all attribute allowed values from source model in plain array format - * - * @param array $options - * @return array - */ - protected function _getAttributeAllowedValues(array $options) - { - $values = array(); - foreach ($options as $option) { - if (isset($option['value'])) { - $value = $option['value']; - if (is_array($value)) { - $values = array_merge($values, $this->_getAttributeAllowedValues($value)); - } else { - $values[] = $value; - } - } - } - - return $values; - } - - /** - * Check if value from config is used - * - * @param array $data - * @param string $field - * @return bool - */ - protected function _isConfigValueUsed($data, $field) - { - return isset($data["use_config_$field"]) && $data["use_config_$field"]; - } - - /** - * Throw API2 exception - * - * @param string $message - * @param int $code - * @throws Mage_Api2_Exception - */ - protected function _critical($message, $code) - { - throw new Mage_Api2_Exception($message, $code); - } -} diff --git a/app/code/core/Mage/Catalog/Model/Api2/Product/Website.php b/app/code/core/Mage/Catalog/Model/Api2/Product/Website.php deleted file mode 100644 index d305f7a67ad7144073fe50736bd40cfe3dbefbba..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Catalog/Model/Api2/Product/Website.php +++ /dev/null @@ -1,69 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Catalog - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Abstract Api2 model for product website resource - * - * @category Mage - * @package Mage_Catalog - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Catalog_Model_Api2_Product_Website extends Mage_Api2_Model_Resource -{ - /** - * Load product by id - * - * @param int $id - * @throws Mage_Api2_Exception - * @return Mage_Catalog_Model_Product - */ - protected function _loadProductById($id) - { - /* @var $product Mage_Catalog_Model_Product */ - $product = Mage::getModel('Mage_Catalog_Model_Product')->load($id); - if (!$product->getId()) { - $this->_critical(sprintf('Product #%s not found.', $id), Mage_Api2_Model_Server::HTTP_NOT_FOUND); - } - return $product; - } - - /** - * Load website by id - * - * @param int $id - * @throws Mage_Api2_Exception - * @return Mage_Core_Model_Website - */ - protected function _loadWebsiteById($id) - { - /* @var $website Mage_Core_Model_Website */ - $website = Mage::getModel('Mage_Core_Model_Website')->load($id); - if (!$website->getId()) { - $this->_critical(sprintf('Website #%s not found.', $id), Mage_Api2_Model_Server::HTTP_NOT_FOUND); - } - return $website; - } -} diff --git a/app/code/core/Mage/Catalog/Model/Api2/Product/Website/Rest.php b/app/code/core/Mage/Catalog/Model/Api2/Product/Website/Rest.php deleted file mode 100644 index 0a56caabc81d7fd0e93316037324436736bbdfd1..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Catalog/Model/Api2/Product/Website/Rest.php +++ /dev/null @@ -1,258 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Catalog - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Abstract API2 class for product website resource - * - * @category Mage - * @package Mage_Catalog - * @author Magento Core Team <core@magentocommerce.com> - */ -abstract class Mage_Catalog_Model_Api2_Product_Website_Rest extends Mage_Catalog_Model_Api2_Product_Website -{ - /** - * Product website retrieve is not available - */ - protected function _retrieve() - { - $this->_critical(self::RESOURCE_METHOD_NOT_ALLOWED); - } - - /** - * Get product websites list - * - * @return array - */ - protected function _retrieveCollection() - { - $return = array(); - foreach ($this->_loadProductById($this->getRequest()->getParam('product_id'))->getWebsiteIds() as $websiteId) { - $return[] = array('website_id' => $websiteId); - } - return $return; - } - - /** - * Product website assign - * - * @param array $data - * @return string - */ - protected function _create(array $data) - { - /* @var $product Mage_Catalog_Model_Product */ - $product = $this->_loadProductById($this->getRequest()->getParam('product_id')); - - /* @var $validator Mage_Catalog_Model_Api2_Product_Website_Validator_Admin_Website */ - $validator = Mage::getModel('Mage_Catalog_Model_Api2_Product_Website_Validator_Admin_Website'); - if (!$validator->isValidDataForWebsiteAssignmentToProduct($product, $data)) { - foreach ($validator->getErrors() as $error) { - $this->_error($error, Mage_Api2_Model_Server::HTTP_BAD_REQUEST); - } - $this->_critical(self::RESOURCE_DATA_PRE_VALIDATION_ERROR); - } - - $websiteIds = $product->getWebsiteIds(); - /* @var $website Mage_Core_Model_Website */ - $website = Mage::getModel('Mage_Core_Model_Website')->load($data['website_id']); - $websiteIds[] = $website->getId(); // Existence of a website is checked in the validator - $product->setWebsiteIds($websiteIds); - - try{ - $product->save(); - - /** - * Do copying data to stores - */ - if (isset($data['copy_to_stores'])) { - foreach ($data['copy_to_stores'] as $storeData) { - Mage::getModel('Mage_Catalog_Model_Product') - ->setStoreId($storeData['store_from']) - ->load($product->getId()) - ->setStoreId($storeData['store_to']) - ->save(); - } - } - - } catch (Mage_Core_Exception $e) { - $this->_critical($e->getMessage(), Mage_Api2_Model_Server::HTTP_INTERNAL_ERROR); - } catch (Exception $e) { - $this->_critical(self::RESOURCE_INTERNAL_ERROR); - } - - return $this->_getLocation($website, $product); - } - - /** - * Product website assign - * - * @param array $data - * @return string - */ - protected function _multiCreate(array $data) - { - /* @var $product Mage_Catalog_Model_Product */ - $product = $this->_loadProductById($this->getRequest()->getParam('product_id')); - $websiteIds = $product->getWebsiteIds(); - foreach ($data as $singleData) { - try { - if (!is_array($singleData)) { - $this->_errorMessage(self::RESOURCE_DATA_INVALID, Mage_Api2_Model_Server::HTTP_BAD_REQUEST); - $this->_critical(self::RESOURCE_DATA_PRE_VALIDATION_ERROR); - } - /* @var $validator Mage_Catalog_Model_Api2_Product_Website_Validator_Admin_Website */ - $validator = Mage::getModel('Mage_Catalog_Model_Api2_Product_Website_Validator_Admin_Website'); - if (!$validator->isValidDataForWebsiteAssignmentToProduct($product, $singleData)) { - foreach ($validator->getErrors() as $error) { - $this->_errorMessage($error, Mage_Api2_Model_Server::HTTP_BAD_REQUEST, array( - 'website_id' => isset($singleData['website_id']) ? $singleData['website_id'] : null, - 'product_id' => $product->getId(), - )); - } - $this->_critical(self::RESOURCE_DATA_PRE_VALIDATION_ERROR); - } - - /* @var $website Mage_Core_Model_Website */ - $website = Mage::getModel('Mage_Core_Model_Website')->load($singleData['website_id']); - $websiteIds[] = $website->getId(); // Existence of a website is checked in the validator - $product->setWebsiteIds($websiteIds); - - $product->save(); - - /** - * Do copying data to stores - */ - if (isset($singleData['copy_to_stores'])) { - foreach ($singleData['copy_to_stores'] as $storeData) { - Mage::getModel('Mage_Catalog_Model_Product') - ->setStoreId($storeData['store_from']) - ->load($product->getId()) - ->setStoreId($storeData['store_to']) - ->save(); - } - } - - $this->_successMessage( - Mage_Api2_Model_Resource::RESOURCE_UPDATED_SUCCESSFUL, - Mage_Api2_Model_Server::HTTP_OK, - array( - 'website_id' => $website->getId(), - 'product_id' => $product->getId(), - ) - ); - } catch (Mage_Api2_Exception $e) { - // pre-validation errors are already added - if ($e->getMessage() != self::RESOURCE_DATA_PRE_VALIDATION_ERROR) { - $this->_errorMessage( - $e->getMessage(), - $e->getCode(), - array( - 'website_id' => isset($singleData['website_id']) ? $singleData['website_id'] : null, - 'product_id' => $product->getId(), - ) - ); - } - } catch (Exception $e) { - $this->_errorMessage( - Mage_Api2_Model_Resource::RESOURCE_INTERNAL_ERROR, - Mage_Api2_Model_Server::HTTP_INTERNAL_ERROR, - array( - 'website_id' => isset($singleData['website_id']) ? $singleData['website_id'] : null, - 'product_id' => $product->getId(), - ) - ); - } - } - } - - /** - * Product websites update is not available - * - * @param array $data - */ - protected function _update(array $data) - { - $this->_critical(self::RESOURCE_METHOD_NOT_ALLOWED); - } - - /** - * Product website unassign - */ - protected function _delete() - { - /* @var $product Mage_Catalog_Model_Product */ - $product = $this->_loadProductById($this->getRequest()->getParam('product_id')); - - /* @var $website Mage_Core_Model_Website */ - $website = $this->_loadWebsiteById($this->getRequest()->getParam('website_id')); - - /* @var $validator Mage_Catalog_Model_Api2_Product_Website_Validator_Admin_Website */ - $validator = Mage::getModel('Mage_Catalog_Model_Api2_Product_Website_Validator_Admin_Website'); - if (!$validator->isWebsiteAssignedToProduct($website, $product)) { - foreach ($validator->getErrors() as $error) { - $this->_error($error, Mage_Api2_Model_Server::HTTP_BAD_REQUEST); - } - $this->_critical(self::RESOURCE_DATA_PRE_VALIDATION_ERROR); - } - - $websiteIds = $product->getWebsiteIds(); - // Existence of a key is checked in the validator - unset($websiteIds[array_search($website->getId(), $websiteIds)]); - $product->setWebsiteIds($websiteIds); - - try { - $product->save(); - } catch (Mage_Core_Exception $e) { - $this->_critical($e->getMessage(), Mage_Api2_Model_Server::HTTP_INTERNAL_ERROR); - } catch (Exception $e) { - $this->_critical(self::RESOURCE_INTERNAL_ERROR); - } - } - - /** - * Get resource location - * - * @param Mage_Core_Model_Website $website - * @return string URL - */ - protected function _getLocation($website) - { - /* @var $apiTypeRoute Mage_Api2_Model_Route_ApiType */ - $apiTypeRoute = Mage::getModel('Mage_Api2_Model_Route_ApiType'); - - $chain = $apiTypeRoute->chain( - new Zend_Controller_Router_Route($this->getConfig()->getRouteWithEntityTypeAction($this->getResourceType())) - ); - $params = array( - 'api_type' => $this->getRequest()->getApiType(), - 'product_id' => $this->getRequest()->getParam('product_id'), - 'website_id' => $website->getId() - ); - $uri = $chain->assemble($params); - - return '/' . $uri; - } -} diff --git a/app/code/core/Mage/Catalog/Model/Api2/Product/Website/Rest/Admin/V1.php b/app/code/core/Mage/Catalog/Model/Api2/Product/Website/Rest/Admin/V1.php deleted file mode 100644 index 986143b0f53734c2ea29ad27174185761f60c2f4..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Catalog/Model/Api2/Product/Website/Rest/Admin/V1.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Catalog - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 for product website resource - * - * @category Mage - * @package Mage_Catalog - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Catalog_Model_Api2_Product_Website_Rest_Admin_V1 extends Mage_Catalog_Model_Api2_Product_Website_Rest -{ -} diff --git a/app/code/core/Mage/Catalog/Model/Api2/Product/Website/Validator/Admin/Website.php b/app/code/core/Mage/Catalog/Model/Api2/Product/Website/Validator/Admin/Website.php deleted file mode 100644 index 1ca84aa41c58ca1f25e7ce841217eb876335dbaf..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Catalog/Model/Api2/Product/Website/Validator/Admin/Website.php +++ /dev/null @@ -1,177 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_CatalogInventory - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 Website Validator - * - * @category Mage - * @package Mage_Catalog - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Catalog_Model_Api2_Product_Website_Validator_Admin_Website extends Mage_Api2_Model_Resource_Validator -{ - /** - * Validate data for website assignment to product. - * If fails validation, then this method returns false, and - * getErrors() will return an array of errors that explain why the - * validation failed. - * - * @param Mage_Catalog_Model_Product $product - * @param array $data - * @return bool - */ - public function isValidDataForWebsiteAssignmentToProduct(Mage_Catalog_Model_Product $product, array $data) - { - // Validate website id - if (!isset($data['website_id']) || !is_numeric($data['website_id'])) { - $this->_addError('Invalid value for "website_id" in request.'); - return false; - } - - // Validate website - /* @var $website Mage_Core_Model_Website */ - $website = Mage::getModel('Mage_Core_Model_Website')->load($data['website_id']); - if (!$website->getId()) { - $this->_addError(sprintf('Website #%d not found.', $data['website_id'])); - return false; - } - - // Validate product to website association - if (in_array($website->getId(), $product->getWebsiteIds())) { - $this->_addError(sprintf('Product #%d is already assigned to website #%d', $product->getId(), - $website->getId())); - return false; - } - - // Validate "Copy To Stores" data and associations - $this->_addErrorsIfCopyToStoresDataIsNotValid($product, $website, $data); - - return !count($this->getErrors()); - } - - /** - * Validate "Copy To Stores" data and associations. - * - * @param Mage_Catalog_Model_Product $product - * @param Mage_Core_Model_Website $website - * @param array $data - * @return \Mage_Catalog_Model_Api2_Product_Website_Validator_Admin_Website - */ - protected function _addErrorsIfCopyToStoresDataIsNotValid($product, $website, $data) - { - if (isset($data['copy_to_stores'])) { - foreach ($data['copy_to_stores'] as $storeData) { - $this->_checkStoreFrom($product, $website, $storeData); - $this->_checkStoreTo($website, $storeData); - } - } - return $this; - } - - /** - * Check if it possible to copy from store "store_from" - * - * @param Mage_Catalog_Model_Product $product - * @param Mage_Core_Model_Website $website - * @param array $storeData - * @return \Mage_Catalog_Model_Api2_Product_Website_Validator_Admin_Website - */ - protected function _checkStoreFrom($product, $website, $storeData) - { - if (!isset($storeData['store_from']) || !is_numeric($storeData['store_from'])) { - $this->_addError(sprintf('Invalid value for "store_from" for the website with ID #%d.', - $website->getId())); - return $this; - } - - // Check if the store with the specified ID (from which we will copy the information) exists - // and if it belongs to the product being edited - $storeFrom = Mage::getModel('Mage_Core_Model_Store')->load($storeData['store_from']); - if (!$storeFrom->getId()) { - $this->_addError(sprintf('Store not found #%d for website #%d.', $storeData['store_from'], - $website->getId())); - return $this; - } - - if (!in_array($storeFrom->getId(), $product->getStoreIds())) { - $this->_addError(sprintf('Store #%d from which we will copy the information does not belong' - . ' to the product #%d being edited.', $storeFrom->getId(), $product->getId())); - } - - return $this; - } - - /** - * Check if it possible to copy into store "store_to" - * - * @param Mage_Core_Model_Website $website - * @param array $storeData - * @return \Mage_Catalog_Model_Api2_Product_Website_Validator_Admin_Website - */ - protected function _checkStoreTo($website, $storeData) - { - if (!isset($storeData['store_to']) || !is_numeric($storeData['store_to'])) { - $this->_addError(sprintf('Invalid value for "store_to" for the website with ID #%d.', - $website->getId())); - return $this; - } - - // Check if the store with the specified ID (to which we will copy the information) exists - // and if it belongs to the website being added - $storeTo = Mage::getModel('Mage_Core_Model_Store')->load($storeData['store_to']); - if (!$storeTo->getId()) { - $this->_addError(sprintf('Store not found #%d for website #%d.', $storeData['store_to'], - $website->getId())); - return $this; - } - - if (!in_array($storeTo->getId(), $website->getStoreIds())) { - $this->_addError(sprintf('Store #%d to which we will copy the information does not belong' - . ' to the website #%d being added.', $storeTo->getId(), $website->getId())); - } - - return $this; - } - - /** - * Validate is valid association for website unassignment from product. - * If fails validation, then this method returns false, and - * getErrors() will return an array of errors that explain why the - * validation failed. - * - * @param Mage_Core_Model_Website $website - * @param Mage_Catalog_Model_Product $product - * @return bool - */ - public function isWebsiteAssignedToProduct(Mage_Core_Model_Website $website, Mage_Catalog_Model_Product $product) - { - if (false === array_search($website->getId(), $product->getWebsiteIds())) { - $this->_addError(sprintf('Product #%d isn\'t assigned to website #%d', $product->getId(), - $website->getId())); - } - return !count($this->getErrors()); - } -} diff --git a/app/code/core/Mage/Catalog/Model/Category/Api.php b/app/code/core/Mage/Catalog/Model/Category/Api.php deleted file mode 100644 index 2ae8aaae5a2e128f6092ff75e3254265764feea8..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Catalog/Model/Category/Api.php +++ /dev/null @@ -1,524 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Catalog - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Catalog category api - * - * @category Mage - * @package Mage_Catalog - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Catalog_Model_Category_Api extends Mage_Catalog_Model_Api_Resource -{ - public function __construct() - { - $this->_storeIdSessionField = 'category_store_id'; - } - - /** - * Retrive level of categories for category/store view/website - * - * @param string|int $website - * @param string|int $store - * @param int $categoryId - * @return array - */ - public function level($website = null, $store = null, $categoryId = null) - { - $ids = array(); - $storeId = Mage_Catalog_Model_Category::DEFAULT_STORE_ID; - - // load root categories of website - if (null !== $website) { - try { - $website = Mage::app()->getWebsite($website); - if (null === $store) { - if (null === $categoryId) { - foreach ($website->getStores() as $store) { - /* @var $store Mage_Core_Model_Store */ - $ids[] = $store->getRootCategoryId(); - } - } else { - $ids = $categoryId; - } - } elseif (in_array($store, $website->getStoreIds())) { - $storeId = Mage::app()->getStore($store)->getId(); - $ids = (null === $categoryId)? $store->getRootCategoryId() : $categoryId; - } else { - $this->_fault('store_not_exists'); - } - } catch (Mage_Core_Exception $e) { - $this->_fault('website_not_exists', $e->getMessage()); - } - } - elseif (null !== $store) { - // load children of root category of store - if (null === $categoryId) { - try { - $store = Mage::app()->getStore($store); - $storeId = $store->getId(); - $ids = $store->getRootCategoryId(); - } catch (Mage_Core_Model_Store_Exception $e) { - $this->_fault('store_not_exists'); - } - } - // load children of specified category id - else { - $storeId = $this->_getStoreId($store); - $ids = (int)$categoryId; - } - } - // load all root categories - else { - $ids = (null === $categoryId)? Mage_Catalog_Model_Category::TREE_ROOT_ID : $categoryId; - } - - $collection = Mage::getModel('Mage_Catalog_Model_Category')->getCollection() - ->setStoreId($storeId) - ->addAttributeToSelect('name') - ->addAttributeToSelect('is_active'); - - if (is_array($ids)) { - $collection->addFieldToFilter('entity_id', array('in' => $ids)); - } else { - $collection->addFieldToFilter('parent_id', $ids); - } - - // Only basic category data - $result = array(); - foreach ($collection as $category) { - /* @var $category Mage_Catalog_Model_Category */ - $result[] = array( - 'category_id' => $category->getId(), - 'parent_id' => $category->getParentId(), - 'name' => $category->getName(), - 'is_active' => $category->getIsActive(), - 'position' => $category->getPosition(), - 'level' => $category->getLevel() - ); - } - - return $result; - } - - /** - * Retrieve category tree - * - * @param int|null $parentId - * @param string|int|null $store - * @return array - */ - public function tree($parentId = null, $store = null) - { - if (is_null($parentId) && !is_null($store)) { - $parentId = Mage::app()->getStore($this->_getStoreId($store))->getRootCategoryId(); - } elseif (is_null($parentId)) { - $parentId = 1; - } - - /* @var $tree Mage_Catalog_Model_Resource_Category_Tree */ - $tree = Mage::getResourceSingleton('Mage_Catalog_Model_Resource_Category_Tree') - ->load(); - - $root = $tree->getNodeById($parentId); - - if($root && $root->getId() == 1) { - $root->setName(Mage::helper('Mage_Catalog_Helper_Data')->__('Root')); - } - - $collection = Mage::getModel('Mage_Catalog_Model_Category')->getCollection() - ->setStoreId($this->_getStoreId($store)) - ->addAttributeToSelect('name') - ->addAttributeToSelect('is_active'); - - $tree->addCollectionData($collection, true); - - return $this->_nodeToArray($root); - } - - /** - * Convert node to array - * - * @param Varien_Data_Tree_Node $node - * @return array - */ - protected function _nodeToArray(Varien_Data_Tree_Node $node) - { - // Only basic category data - $result = array(); - $result['category_id'] = $node->getId(); - $result['parent_id'] = $node->getParentId(); - $result['name'] = $node->getName(); - $result['is_active'] = $node->getIsActive(); - $result['position'] = $node->getPosition(); - $result['level'] = $node->getLevel(); - $result['children'] = array(); - - foreach ($node->getChildren() as $child) { - $result['children'][] = $this->_nodeToArray($child); - } - - return $result; - } - - /** - * Initialize and return category model - * - * @param int $categoryId - * @param string|int $store - * @return Mage_Catalog_Model_Category - */ - protected function _initCategory($categoryId, $store = null) - { - $category = Mage::getModel('Mage_Catalog_Model_Category') - ->setStoreId($this->_getStoreId($store)) - ->load($categoryId); - - if (!$category->getId()) { - $this->_fault('not_exists'); - } - - return $category; - } - - /** - * Retrieve category data - * - * @param int $categoryId - * @param string|int $store - * @param array $attributes - * @return array - */ - public function info($categoryId, $store = null, $attributes = null) - { - $category = $this->_initCategory($categoryId, $store); - - // Basic category data - $result = array(); - $result['category_id'] = $category->getId(); - - $result['is_active'] = $category->getIsActive(); - $result['position'] = $category->getPosition(); - $result['level'] = $category->getLevel(); - - foreach ($category->getAttributes() as $attribute) { - if ($this->_isAllowedAttribute($attribute, $attributes)) { - $result[$attribute->getAttributeCode()] = $category->getData($attribute->getAttributeCode()); - } - } - $result['parent_id'] = $category->getParentId(); - $result['children'] = $category->getChildren(); - $result['all_children'] = $category->getAllChildren(); - - return $result; - } - - /** - * Create new category - * - * @param int $parentId - * @param array $categoryData - * @param int|string|null $store - * @return int - */ - public function create($parentId, $categoryData, $store = null) - { - $parent_category = $this->_initCategory($parentId, $store); - $category = Mage::getModel('Mage_Catalog_Model_Category') - ->setStoreId($this->_getStoreId($store)); - - $category->addData(array('path'=>implode('/',$parent_category->getPathIds()))); - - $category ->setAttributeSetId($category->getDefaultAttributeSetId()); - /* @var $category Mage_Catalog_Model_Category */ - - foreach ($category->getAttributes() as $attribute) { - if ($this->_isAllowedAttribute($attribute) - && isset($categoryData[$attribute->getAttributeCode()])) { - $category->setData( - $attribute->getAttributeCode(), - $categoryData[$attribute->getAttributeCode()] - ); - } - } - - $category->setParentId($parent_category->getId()); - - try { - $validate = $category->validate(); - if ($validate !== true) { - foreach ($validate as $code => $error) { - if ($error === true) { - Mage::throwException(Mage::helper('Mage_Catalog_Helper_Data')->__('Attribute "%s" is required.', $code)); - } - else { - Mage::throwException($error); - } - } - } - - $category->save(); - } - catch (Mage_Core_Exception $e) { - $this->_fault('data_invalid', $e->getMessage()); - } - - return $category->getId(); - } - - /** - * Update category data - * - * @param int $categoryId - * @param array $categoryData - * @param string|int $store - * @return boolean - */ - public function update($categoryId, $categoryData, $store = null) - { - $category = $this->_initCategory($categoryId, $store); - - foreach ($category->getAttributes() as $attribute) { - if ($this->_isAllowedAttribute($attribute) - && isset($categoryData[$attribute->getAttributeCode()])) { - $category->setData( - $attribute->getAttributeCode(), - $categoryData[$attribute->getAttributeCode()] - ); - } - } - - try { - $validate = $category->validate(); - if ($validate !== true) { - foreach ($validate as $code => $error) { - if ($error === true) { - Mage::throwException(Mage::helper('Mage_Catalog_Helper_Data')->__('Attribute "%s" is required.', $code)); - } - else { - Mage::throwException($error); - } - } - } - - $category->save(); - } catch (Mage_Core_Exception $e) { - $this->_fault('data_invalid', $e->getMessage()); - } catch (Mage_Eav_Model_Entity_Attribute_Exception $e) { - $this->_fault('data_invalid', $e->getMessage()); - } - - return true; - } - - /** - * Move category in tree - * - * @param int $categoryId - * @param int $parentId - * @param int $afterId - * @return boolean - */ - public function move($categoryId, $parentId, $afterId = null) - { - $category = $this->_initCategory($categoryId); - $parent_category = $this->_initCategory($parentId); - - // if $afterId is null - move category to the down - if ($afterId === null && $parent_category->hasChildren()) { - $parentChildren = $parent_category->getChildren(); - $afterId = array_pop(explode(',', $parentChildren)); - } - - if( strpos($parent_category->getPath(), $category->getPath()) === 0) { - $this->_fault('not_moved', "Operation do not allow to move a parent category to any of children category"); - } - - try { - $category->move($parentId, $afterId); - } catch (Mage_Core_Exception $e) { - $this->_fault('not_moved', $e->getMessage()); - } - - return true; - } - - /** - * Delete category - * - * @param int $categoryId - * @return boolean - */ - public function delete($categoryId) - { - if (Mage_Catalog_Model_Category::TREE_ROOT_ID == $categoryId) { - $this->_fault('not_deleted', 'Cannot remove the system category.'); - } - - $category = $this->_initCategory($categoryId); - - try { - $category->delete(); - } catch (Mage_Core_Exception $e) { - $this->_fault('not_deleted', $e->getMessage()); - } - - return true; - } - - /** - * Get product Id from sku or from product id - * - * @param int|string $productId - * @param string $identifierType - * @return int - */ - protected function _getProductId($productId, $identifierType = null) - { - $product = Mage::helper('Mage_Catalog_Helper_Product')->getProduct($productId, null, $identifierType); - if (!$product->getId()) { - $this->_fault('not_exists','Product not exists.'); - } - return $product->getId(); - } - - - /** - * Retrieve list of assigned products to category - * - * @param int $categoryId - * @param string|int $store - * @return array - */ - public function assignedProducts($categoryId, $store = null) - { - $category = $this->_initCategory($categoryId); - - $storeId = $this->_getStoreId($store); - $collection = $category->setStoreId($storeId)->getProductCollection(); - ($storeId == 0)? $collection->addOrder('position', 'asc') : $collection->setOrder('position', 'asc');; - - $result = array(); - - foreach ($collection as $product) { - $result[] = array( - 'product_id' => $product->getId(), - 'type' => $product->getTypeId(), - 'set' => $product->getAttributeSetId(), - 'sku' => $product->getSku(), - 'position' => $product->getCatIndexPosition() - ); - } - - return $result; - } - - /** - * Assign product to category - * - * @param int $categoryId - * @param int $productId - * @param int $position - * @param string|null $identifierType - * @return boolean - */ - public function assignProduct($categoryId, $productId, $position = null, $identifierType = null) - { - $category = $this->_initCategory($categoryId); - $positions = $category->getProductsPosition(); - $productId = $this->_getProductId($productId, $identifierType); - $positions[$productId] = $position; - $category->setPostedProducts($positions); - - try { - $category->save(); - } catch (Mage_Core_Exception $e) { - $this->_fault('data_invalid', $e->getMessage()); - } - - return true; - } - - - /** - * Update product assignment - * - * @param int $categoryId - * @param int $productId - * @param int $position - * @param string|null $identifierType - * @return boolean - */ - public function updateProduct($categoryId, $productId, $position = null, $identifierType = null) - { - $category = $this->_initCategory($categoryId); - $positions = $category->getProductsPosition(); - $productId = $this->_getProductId($productId, $identifierType); - if (!isset($positions[$productId])) { - $this->_fault('product_not_assigned'); - } - $positions[$productId] = $position; - $category->setPostedProducts($positions); - - try { - $category->save(); - } catch (Mage_Core_Exception $e) { - $this->_fault('data_invalid', $e->getMessage()); - } - - return true; - } - - /** - * Remove product assignment from category - * - * @param int $categoryId - * @param int $productId - * @param string|null $identifierType - * @return boolean - */ - public function removeProduct($categoryId, $productId, $identifierType = null) - { - $category = $this->_initCategory($categoryId); - $positions = $category->getProductsPosition(); - $productId = $this->_getProductId($productId, $identifierType); - if (!isset($positions[$productId])) { - $this->_fault('product_not_assigned'); - } - - unset($positions[$productId]); - $category->setPostedProducts($positions); - - try { - $category->save(); - } catch (Mage_Core_Exception $e) { - $this->_fault('data_invalid', $e->getMessage()); - } - - return true; - } - -} diff --git a/app/code/core/Mage/Catalog/Model/Category/Api/V2.php b/app/code/core/Mage/Catalog/Model/Category/Api/V2.php deleted file mode 100644 index e796f2304c51bbac4ea16eb77a8b7bca9527cb4d..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Catalog/Model/Category/Api/V2.php +++ /dev/null @@ -1,165 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Catalog - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Catalog category api - * - * @category Mage - * @package Mage_Catalog - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Catalog_Model_Category_Api_V2 extends Mage_Catalog_Model_Category_Api -{ - /** - * Retrieve category data - * - * @param int $categoryId - * @param string|int $store - * @param array $attributes - * @return array - */ - public function info($categoryId, $store = null, $attributes = null) - { - $category = $this->_initCategory($categoryId, $store); - - // Basic category data - $result = array(); - $result['category_id'] = $category->getId(); - - $result['is_active'] = $category->getIsActive(); - $result['position'] = $category->getPosition(); - $result['level'] = $category->getLevel(); - - foreach ($category->getAttributes() as $attribute) { - if ($this->_isAllowedAttribute($attribute, $attributes)) { - $result[$attribute->getAttributeCode()] = $category->getDataUsingMethod($attribute->getAttributeCode()); - } - } - $result['parent_id'] = $category->getParentId(); - $result['children'] = $category->getChildren(); - $result['all_children'] = $category->getAllChildren(); - - return $result; - } - - /** - * Create new category - * - * @param int $parentId - * @param array $categoryData - * @return int - */ - public function create($parentId, $categoryData, $store = null) - { - $parent_category = $this->_initCategory($parentId, $store); - - /* @var $category Mage_Catalog_Model_Category */ - $category = Mage::getModel('Mage_Catalog_Model_Category') - ->setStoreId($this->_getStoreId($store)); - - $category->addData(array('path'=>implode('/',$parent_category->getPathIds()))); - - $category ->setAttributeSetId($category->getDefaultAttributeSetId()); - - - foreach ($category->getAttributes() as $attribute) { - $_attrCode = $attribute->getAttributeCode(); - if ($this->_isAllowedAttribute($attribute) - && isset($categoryData->$_attrCode)) { - $category->setData( - $attribute->getAttributeCode(), - $categoryData->$_attrCode - ); - } - } - $category->setParentId($parent_category->getId()); - try { - $validate = $category->validate(); - if ($validate !== true) { - foreach ($validate as $code => $error) { - if ($error === true) { - Mage::throwException(Mage::helper('Mage_Catalog_Helper_Data')->__('Attribute "%s" is required.', $code)); - } - else { - Mage::throwException($error); - } - } - } - - $category->save(); - } - catch (Mage_Core_Exception $e) { - $this->_fault('data_invalid', $e->getMessage()); - } - - return $category->getId(); - } - - /** - * Update category data - * - * @param int $categoryId - * @param array $categoryData - * @param string|int $store - * @return boolean - */ - public function update($categoryId, $categoryData, $store = null) - { - $category = $this->_initCategory($categoryId, $store); - - foreach ($category->getAttributes() as $attribute) { - $_attrCode = $attribute->getAttributeCode(); - if ($this->_isAllowedAttribute($attribute) - && isset($categoryData->$_attrCode)) { - $category->setData( - $attribute->getAttributeCode(), - $categoryData->$_attrCode - ); - } - } - - try { - $validate = $category->validate(); - if ($validate !== true) { - foreach ($validate as $code => $error) { - if ($error === true) { - Mage::throwException(Mage::helper('Mage_Catalog_Helper_Data')->__('Attribute "%s" is required.', $code)); - } - else { - Mage::throwException($error); - } - } - } - $category->save(); - } catch (Mage_Core_Exception $e) { - $this->_fault('data_invalid', $e->getMessage()); - } catch (Mage_Eav_Model_Entity_Attribute_Exception $e) { - $this->_fault('data_invalid', $e->getMessage()); - } - - return true; - } -} diff --git a/app/code/core/Mage/Catalog/Model/Category/Attribute/Api.php b/app/code/core/Mage/Catalog/Model/Category/Attribute/Api.php deleted file mode 100644 index 7df4abac64155ab8e8cfa3fde130aaf350592396..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Catalog/Model/Category/Attribute/Api.php +++ /dev/null @@ -1,109 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Catalog - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Catalog category attribute api - * - * @category Mage - * @package Mage_Catalog - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Catalog_Model_Category_Attribute_Api extends Mage_Catalog_Model_Api_Resource -{ - public function __construct() - { - $this->_storeIdSessionField = 'category_store_id'; - } - - /** - * Retrieve category attributes - * - * @return array - */ - public function items() - { - $attributes = Mage::getModel('Mage_Catalog_Model_Category')->getAttributes(); - $result = array(); - - foreach ($attributes as $attribute) { - /* @var $attribute Mage_Catalog_Model_Resource_Eav_Attribute */ - if ($this->_isAllowedAttribute($attribute)) { - if (!$attribute->getId() || $attribute->isScopeGlobal()) { - $scope = 'global'; - } elseif ($attribute->isScopeWebsite()) { - $scope = 'website'; - } else { - $scope = 'store'; - } - - $result[] = array( - 'attribute_id' => $attribute->getId(), - 'code' => $attribute->getAttributeCode(), - 'type' => $attribute->getFrontendInput(), - 'required' => $attribute->getIsRequired(), - 'scope' => $scope - ); - } - } - - return $result; - } - - /** - * Retrieve category attribute options - * - * @param int|string $attributeId - * @param string|int $store - * @return array - */ - public function options($attributeId, $store = null) - { - $attribute = Mage::getModel('Mage_Catalog_Model_Category') - ->setStoreId($this->_getStoreId($store)) - ->getResource() - ->getAttribute($attributeId); - - if (!$attribute) { - $this->_fault('not_exists'); - } - - $result = array(); - if ($attribute->usesSource()) { - foreach ($attribute->getSource()->getAllOptions(false) as $optionId=>$optionValue) { - if (is_array($optionValue)) { - $result[] = $optionValue; - } else { - $result[] = array( - 'value' => $optionId, - 'label' => $optionValue - ); - } - } - } - - return $result; - } -} // Class Mage_Catalog_Model_Category_Attribute_Api End diff --git a/app/code/core/Mage/Catalog/Model/Category/Attribute/Api/V2.php b/app/code/core/Mage/Catalog/Model/Category/Attribute/Api/V2.php deleted file mode 100644 index f5e96bf793084a09771c39271c631715f88ace44..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Catalog/Model/Category/Attribute/Api/V2.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Catalog - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Catalog category attribute api V2 - * - * @category Mage - * @package Mage_Catalog - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Catalog_Model_Category_Attribute_Api_V2 extends Mage_Catalog_Model_Category_Attribute_Api -{ -} diff --git a/app/code/core/Mage/Catalog/Model/Product/Api.php b/app/code/core/Mage/Catalog/Model/Product/Api.php deleted file mode 100644 index f2d0a5f2b42dd57d074999dc64d9c7b52f79c32a..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Catalog/Model/Product/Api.php +++ /dev/null @@ -1,454 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Catalog - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Catalog product api - * - * @category Mage - * @package Mage_Catalog - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Catalog_Model_Product_Api extends Mage_Catalog_Model_Api_Resource -{ - protected $_filtersMap = array( - 'product_id' => 'entity_id', - 'set' => 'attribute_set_id', - 'type' => 'type_id' - ); - - protected $_defaultProductAttributeList = array( - 'type_id', - 'category_ids', - 'website_ids', - 'name', - 'description', - 'short_description', - 'sku', - 'weight', - 'status', - 'url_key', - 'url_path', - 'visibility', - 'has_options', - 'gift_message_available', - 'price', - 'special_price', - 'special_from_date', - 'special_to_date', - 'tax_class_id', - 'tier_price', - 'meta_title', - 'meta_keyword', - 'meta_description', - 'custom_design', - 'custom_layout_update', - 'options_container', - 'image_label', - 'small_image_label', - 'thumbnail_label', - 'created_at', - 'updated_at' - ); - - public function __construct() - { - $this->_storeIdSessionField = 'product_store_id'; - $this->_ignoredAttributeTypes[] = 'gallery'; - $this->_ignoredAttributeTypes[] = 'media_image'; - } - - /** - * Retrieve list of products with basic info (id, sku, type, set, name) - * - * @param null|object|array $filters - * @param string|int $store - * @return array - */ - public function items($filters = null, $store = null) - { - $collection = Mage::getModel('Mage_Catalog_Model_Product')->getCollection() - ->addStoreFilter($this->_getStoreId($store)) - ->addAttributeToSelect('name'); - - /** @var $apiHelper Mage_Api_Helper_Data */ - $apiHelper = Mage::helper('Mage_Api_Helper_Data'); - $filters = $apiHelper->parseFilters($filters, $this->_filtersMap); - try { - foreach ($filters as $field => $value) { - $collection->addFieldToFilter($field, $value); - } - } catch (Mage_Core_Exception $e) { - $this->_fault('filters_invalid', $e->getMessage()); - } - $result = array(); - foreach ($collection as $product) { - $result[] = array( - 'product_id' => $product->getId(), - 'sku' => $product->getSku(), - 'name' => $product->getName(), - 'set' => $product->getAttributeSetId(), - 'type' => $product->getTypeId(), - 'category_ids' => $product->getCategoryIds(), - 'website_ids' => $product->getWebsiteIds() - ); - } - return $result; - } - - /** - * Retrieve product info - * - * @param int|string $productId - * @param string|int $store - * @param array $attributes - * @return array - */ - public function info($productId, $store = null, $attributes = null, $identifierType = null) - { - $product = $this->_getProduct($productId, $store, $identifierType); - - - $result = array( // Basic product data - 'product_id' => $product->getId(), - 'sku' => $product->getSku(), - 'set' => $product->getAttributeSetId(), - 'type' => $product->getTypeId(), - 'categories' => $product->getCategoryIds(), - 'websites' => $product->getWebsiteIds() - ); - - foreach ($product->getTypeInstance()->getEditableAttributes($product) as $attribute) { - if ($this->_isAllowedAttribute($attribute, $attributes)) { - $result[$attribute->getAttributeCode()] = $product->getData( - $attribute->getAttributeCode()); - } - } - - return $result; - } - - /** - * Create new product. - * - * @param string $type - * @param int $set - * @param string $sku - * @param array $productData - * @param string $store - * @return int - */ - public function create($type, $set, $sku, $productData, $store = null) - { - if (!$type || !$set || !$sku) { - $this->_fault('data_invalid'); - } - - $this->_checkProductTypeExists($type); - $this->_checkProductAttributeSet($set); - - /** @var $product Mage_Catalog_Model_Product */ - $product = Mage::getModel('Mage_Catalog_Model_Product'); - $product->setStoreId($this->_getStoreId($store)) - ->setAttributeSetId($set) - ->setTypeId($type) - ->setSku($sku); - - if (!isset($productData['stock_data']) || !is_array($productData['stock_data'])) { - //Set default stock_data if not exist in product data - $product->setStockData(array('use_config_manage_stock' => 0)); - } - - foreach ($product->getMediaAttributes() as $mediaAttribute) { - $mediaAttrCode = $mediaAttribute->getAttributeCode(); - $product->setData($mediaAttrCode, 'no_selection'); - } - - $this->_prepareDataForSave($product, $productData); - - try { - /** - * @todo implement full validation process with errors returning which are ignoring now - * @todo see Mage_Catalog_Model_Product::validate() - */ - if (is_array($errors = $product->validate())) { - $strErrors = array(); - foreach($errors as $code => $error) { - if ($error === true) { - $error = Mage::helper('Mage_Catalog_Helper_Data')->__('Attribute "%s" is invalid.', $code); - } - $strErrors[] = $error; - } - $this->_fault('data_invalid', implode("\n", $strErrors)); - } - - $product->save(); - } catch (Mage_Core_Exception $e) { - $this->_fault('data_invalid', $e->getMessage()); - } - - return $product->getId(); - } - - /** - * Update product data - * - * @param int|string $productId - * @param array $productData - * @param string|int $store - * @return boolean - */ - public function update($productId, $productData, $store = null, $identifierType = null) - { - $product = $this->_getProduct($productId, $store, $identifierType); - - $this->_prepareDataForSave($product, $productData); - - try { - /** - * @todo implement full validation process with errors returning which are ignoring now - * @todo see Mage_Catalog_Model_Product::validate() - */ - if (is_array($errors = $product->validate())) { - $strErrors = array(); - foreach($errors as $code => $error) { - if ($error === true) { - $error = Mage::helper('Mage_Catalog_Helper_Data')->__('Value for "%s" is invalid.', $code); - } else { - $error = Mage::helper('Mage_Catalog_Helper_Data')->__('Value for "%s" is invalid: %s', $code, $error); - } - $strErrors[] = $error; - } - $this->_fault('data_invalid', implode("\n", $strErrors)); - } - - $product->save(); - } catch (Mage_Core_Exception $e) { - $this->_fault('data_invalid', $e->getMessage()); - } - - return true; - } - - /** - * Set additional data before product saved - * - * @param Mage_Catalog_Model_Product $product - * @param array $productData - * @return object - */ - protected function _prepareDataForSave($product, $productData) - { - if (isset($productData['website_ids']) && is_array($productData['website_ids'])) { - $product->setWebsiteIds($productData['website_ids']); - } - - foreach ($product->getTypeInstance()->getEditableAttributes($product) as $attribute) { - //Unset data if object attribute has no value in current store - if (Mage_Catalog_Model_Abstract::DEFAULT_STORE_ID !== (int) $product->getStoreId() - && !$product->getExistsStoreValueFlag($attribute->getAttributeCode()) - && !$attribute->isScopeGlobal() - ) { - $product->setData($attribute->getAttributeCode(), false); - } - - if ($this->_isAllowedAttribute($attribute)) { - if (isset($productData[$attribute->getAttributeCode()])) { - $product->setData( - $attribute->getAttributeCode(), - $productData[$attribute->getAttributeCode()] - ); - } elseif (isset($productData['additional_attributes']['single_data'][$attribute->getAttributeCode()])) { - $product->setData( - $attribute->getAttributeCode(), - $productData['additional_attributes']['single_data'][$attribute->getAttributeCode()] - ); - } elseif (isset($productData['additional_attributes']['multi_data'][$attribute->getAttributeCode()])) { - $product->setData( - $attribute->getAttributeCode(), - $productData['additional_attributes']['multi_data'][$attribute->getAttributeCode()] - ); - } - } - } - - if (isset($productData['categories']) && is_array($productData['categories'])) { - $product->setCategoryIds($productData['categories']); - } - - if (isset($productData['websites']) && is_array($productData['websites'])) { - foreach ($productData['websites'] as &$website) { - if (is_string($website)) { - try { - $website = Mage::app()->getWebsite($website)->getId(); - } catch (Exception $e) { } - } - } - $product->setWebsiteIds($productData['websites']); - } - - if (Mage::app()->hasSingleStore()) { - $product->setWebsiteIds(array(Mage::app()->getStore(true)->getWebsite()->getId())); - } - - if (isset($productData['stock_data']) && is_array($productData['stock_data'])) { - $product->setStockData($productData['stock_data']); - } - - if (isset($productData['tier_price']) && is_array($productData['tier_price'])) { - $tierPrices = Mage::getModel('Mage_Catalog_Model_Product_Attribute_Tierprice_Api') - ->prepareTierPrices($product, $productData['tier_price']); - $product->setData(Mage_Catalog_Model_Product_Attribute_Tierprice_Api::ATTRIBUTE_CODE, $tierPrices); - } - } - - /** - * Update product special price - * - * @param int|string $productId - * @param float $specialPrice - * @param string $fromDate - * @param string $toDate - * @param string|int $store - * @return boolean - */ - public function setSpecialPrice($productId, $specialPrice = null, $fromDate = null, $toDate = null, $store = null) - { - return $this->update($productId, array( - 'special_price' => $specialPrice, - 'special_from_date' => $fromDate, - 'special_to_date' => $toDate - ), $store); - } - - /** - * Retrieve product special price - * - * @param int|string $productId - * @param string|int $store - * @return array - */ - public function getSpecialPrice($productId, $store = null) - { - return $this->info($productId, $store, array('special_price', 'special_from_date', 'special_to_date')); - } - - /** - * Delete product - * - * @param int|string $productId - * @return boolean - */ - public function delete($productId, $identifierType = null) - { - $product = $this->_getProduct($productId, null, $identifierType); - - try { - $product->delete(); - } catch (Mage_Core_Exception $e) { - $this->_fault('not_deleted', $e->getMessage()); - } - - return true; - } - - /** - * Get list of additional attributes which are not in default create/update list - * - * @param $productType - * @param $attributeSetId - * @return array - */ - public function getAdditionalAttributes($productType, $attributeSetId) - { - $this->_checkProductTypeExists($productType); - $this->_checkProductAttributeSet($attributeSetId); - - /** @var $product Mage_Catalog_Model_Product */ - $product = Mage::getModel('Mage_Catalog_Model_Product'); - $productAttributes = $product->setAttributeSetId($attributeSetId) - ->setTypeId($productType) - ->getTypeInstance() - ->getEditableAttributes($product); - - $result = array(); - foreach ($productAttributes as $attribute) { - /* @var $attribute Mage_Catalog_Model_Resource_Eav_Attribute */ - if ($attribute->isInSet($attributeSetId) && $this->_isAllowedAttribute($attribute) - && !in_array($attribute->getAttributeCode(), $this->_defaultProductAttributeList)) { - - if ($attribute->isScopeGlobal()) { - $scope = 'global'; - } elseif ($attribute->isScopeWebsite()) { - $scope = 'website'; - } else { - $scope = 'store'; - } - - $result[] = array( - 'attribute_id' => $attribute->getId(), - 'code' => $attribute->getAttributeCode(), - 'type' => $attribute->getFrontendInput(), - 'required' => $attribute->getIsRequired(), - 'scope' => $scope - ); - } - } - - return $result; - } - - /** - * Check if product type exists - * - * @param $productType - * @throw Mage_Api_Exception - * @return void - */ - protected function _checkProductTypeExists($productType) - { - if (!in_array($productType, array_keys(Mage::getModel('Mage_Catalog_Model_Product_Type')->getOptionArray()))) { - $this->_fault('product_type_not_exists'); - } - } - - /** - * Check if attributeSet is exits and in catalog_product entity group type - * - * @param $attributeSetId - * @throw Mage_Api_Exception - * @return void - */ - protected function _checkProductAttributeSet($attributeSetId) - { - $attributeSet = Mage::getModel('Mage_Eav_Model_Entity_Attribute_Set')->load($attributeSetId); - if (is_null($attributeSet->getId())) { - $this->_fault('product_attribute_set_not_exists'); - } - if (Mage::getModel('Mage_Catalog_Model_Product')->getResource()->getTypeId() != $attributeSet->getEntityTypeId()) { - $this->_fault('product_attribute_set_not_valid'); - } - } -} // Class Mage_Catalog_Model_Product_Api End diff --git a/app/code/core/Mage/Catalog/Model/Product/Api/V2.php b/app/code/core/Mage/Catalog/Model/Product/Api/V2.php deleted file mode 100644 index 3f275a953bb0abee6bf0b61dadea87861abcf708..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Catalog/Model/Product/Api/V2.php +++ /dev/null @@ -1,319 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Catalog - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Catalog product api V2 - * - * @category Mage - * @package Mage_Catalog - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Catalog_Model_Product_Api_V2 extends Mage_Catalog_Model_Product_Api -{ - /** - * Retrieve product info - * - * @param int|string $productId - * @param string|int $store - * @param stdClass $attributes - * @return array - */ - public function info($productId, $store = null, $attributes = null, $identifierType = null) - { - $product = $this->_getProduct($productId, $store, $identifierType); - - $result = array( // Basic product data - 'product_id' => $product->getId(), - 'sku' => $product->getSku(), - 'set' => $product->getAttributeSetId(), - 'type' => $product->getTypeId(), - 'categories' => $product->getCategoryIds(), - 'websites' => $product->getWebsiteIds() - ); - - $allAttributes = array(); - if (!empty($attributes->attributes)) { - $allAttributes = array_merge($allAttributes, $attributes->attributes); - } else { - foreach ($product->getTypeInstance()->getEditableAttributes($product) as $attribute) { - if ($this->_isAllowedAttribute($attribute, $attributes)) { - $allAttributes[] = $attribute->getAttributeCode(); - } - } - } - - $_additionalAttributeCodes = array(); - if (!empty($attributes->additional_attributes)) { - foreach ($attributes->additional_attributes as $k => $_attributeCode) { - $allAttributes[] = $_attributeCode; - $_additionalAttributeCodes[] = $_attributeCode; - } - } - - $_additionalAttribute = 0; - foreach ($product->getTypeInstance()->getEditableAttributes($product) as $attribute) { - if ($this->_isAllowedAttribute($attribute, $allAttributes)) { - if (in_array($attribute->getAttributeCode(), $_additionalAttributeCodes)) { - $result['additional_attributes'][$_additionalAttribute]['key'] = $attribute->getAttributeCode(); - $result['additional_attributes'][$_additionalAttribute]['value'] = $product - ->getData($attribute->getAttributeCode()); - $_additionalAttribute++; - } else { - $result[$attribute->getAttributeCode()] = $product->getData($attribute->getAttributeCode()); - } - } - } - - return $result; - } - - /** - * Create new product. - * - * @param string $type - * @param int $set - * @param string $sku - * @param array $productData - * @param string $store - * @return int - */ - public function create($type, $set, $sku, $productData, $store = null) - { - if (!$type || !$set || !$sku) { - $this->_fault('data_invalid'); - } - - $this->_checkProductTypeExists($type); - $this->_checkProductAttributeSet($set); - - /** @var $product Mage_Catalog_Model_Product */ - $product = Mage::getModel('Mage_Catalog_Model_Product'); - $product->setStoreId($this->_getStoreId($store)) - ->setAttributeSetId($set) - ->setTypeId($type) - ->setSku($sku); - - if (!property_exists($productData, 'stock_data')) { - //Set default stock_data if not exist in product data - $_stockData = array('use_config_manage_stock' => 0); - $product->setStockData($_stockData); - } - - foreach ($product->getMediaAttributes() as $mediaAttribute) { - $mediaAttrCode = $mediaAttribute->getAttributeCode(); - $product->setData($mediaAttrCode, 'no_selection'); - } - - $this->_prepareDataForSave($product, $productData); - - try { - /** - * @todo implement full validation process with errors returning which are ignoring now - * @todo see Mage_Catalog_Model_Product::validate() - */ - if (is_array($errors = $product->validate())) { - $strErrors = array(); - foreach($errors as $code => $error) { - if ($error === true) { - $error = Mage::helper('Mage_Catalog_Helper_Data')->__('Attribute "%s" is invalid.', $code); - } - $strErrors[] = $error; - } - $this->_fault('data_invalid', implode("\n", $strErrors)); - } - - $product->save(); - } catch (Mage_Core_Exception $e) { - $this->_fault('data_invalid', $e->getMessage()); - } - - return $product->getId(); - } - - /** - * Update product data - * - * @param int|string $productId - * @param array $productData - * @param string|int $store - * @return boolean - */ - public function update($productId, $productData, $store = null, $identifierType = null) - { - $product = $this->_getProduct($productId, $store, $identifierType); - - $this->_prepareDataForSave($product, $productData); - - try { - /** - * @todo implement full validation process with errors returning which are ignoring now - * @todo see Mage_Catalog_Model_Product::validate() - */ - if (is_array($errors = $product->validate())) { - $strErrors = array(); - foreach($errors as $code => $error) { - if ($error === true) { - $error = Mage::helper('Mage_Catalog_Helper_Data')->__('Value for "%s" is invalid.', $code); - } else { - $error = Mage::helper('Mage_Catalog_Helper_Data')->__('Value for "%s" is invalid: %s', $code, $error); - } - $strErrors[] = $error; - } - $this->_fault('data_invalid', implode("\n", $strErrors)); - } - - $product->save(); - } catch (Mage_Core_Exception $e) { - $this->_fault('data_invalid', $e->getMessage()); - } - - return true; - } - - /** - * Set additional data before product saved - * - * @param Mage_Catalog_Model_Product $product - * @param array $productData - * @return object - */ - protected function _prepareDataForSave ($product, $productData) - { - if (property_exists($productData, 'website_ids') && is_array($productData->website_ids)) { - $product->setWebsiteIds($productData->website_ids); - } - - if (property_exists($productData, 'additional_attributes')) { - if (property_exists($productData->additional_attributes, 'single_data')) { - foreach ($productData->additional_attributes->single_data as $_attribute) { - $_attrCode = $_attribute->key; - $productData->$_attrCode = $_attribute->value; - } - } - if (property_exists($productData->additional_attributes, 'multi_data')) { - foreach ($productData->additional_attributes->multi_data as $_attribute) { - $_attrCode = $_attribute->key; - $productData->$_attrCode = $_attribute->value; - } - } - unset($productData->additional_attributes); - } - - foreach ($product->getTypeInstance()->getEditableAttributes($product) as $attribute) { - $_attrCode = $attribute->getAttributeCode(); - - //Unset data if object attribute has no value in current store - if (Mage_Catalog_Model_Abstract::DEFAULT_STORE_ID !== (int) $product->getStoreId() - && !$product->getExistsStoreValueFlag($_attrCode) - && !$attribute->isScopeGlobal() - ) { - $product->setData($_attrCode, false); - } - - if ($this->_isAllowedAttribute($attribute) && (isset($productData->$_attrCode))) { - $product->setData( - $_attrCode, - $productData->$_attrCode - ); - } - } - - if (property_exists($productData, 'categories') && is_array($productData->categories)) { - $product->setCategoryIds($productData->categories); - } - - if (property_exists($productData, 'websites') && is_array($productData->websites)) { - foreach ($productData->websites as &$website) { - if (is_string($website)) { - try { - $website = Mage::app()->getWebsite($website)->getId(); - } catch (Exception $e) { } - } - } - $product->setWebsiteIds($productData->websites); - } - - if (Mage::app()->hasSingleStore()) { - $product->setWebsiteIds(array(Mage::app()->getStore(true)->getWebsite()->getId())); - } - - if (property_exists($productData, 'stock_data')) { - $_stockData = array(); - foreach ($productData->stock_data as $key => $value) { - $_stockData[$key] = $value; - } - $product->setStockData($_stockData); - } - - if (property_exists($productData, 'tier_price')) { - $tierPrices = Mage::getModel('Mage_Catalog_Model_Product_Attribute_Tierprice_Api_V2') - ->prepareTierPrices($product, $productData->tier_price); - $product->setData(Mage_Catalog_Model_Product_Attribute_Tierprice_Api_V2::ATTRIBUTE_CODE, $tierPrices); - } - } - - /** - * Update product special price - * - * @param int|string $productId - * @param float $specialPrice - * @param string $fromDate - * @param string $toDate - * @param string|int $store - * @param string $identifierType OPTIONAL If 'sku' - search product by SKU, if any except for NULL - search by ID, - * otherwise - try to determine identifier type automatically - * @return boolean - */ - public function setSpecialPrice($productId, $specialPrice = null, $fromDate = null, $toDate = null, $store = null, - $identifierType = null - ) { - $obj = new stdClass(); - $obj->special_price = $specialPrice; - $obj->special_from_date = $fromDate; - $obj->special_to_date = $toDate; - return $this->update($productId, $obj, $store, $identifierType); - } - - /** - * Retrieve product special price - * - * @param int|string $productId - * @param string|int $store - * @return array - */ - public function getSpecialPrice($productId, $store = null) - { - return $this->info($productId, $store, array( - 'attributes' => array( - 'special_price', - 'special_from_date', - 'special_to_date' - ) - ) - ); - } - -} diff --git a/app/code/core/Mage/Catalog/Model/Product/Attribute/Api.php b/app/code/core/Mage/Catalog/Model/Product/Attribute/Api.php deleted file mode 100644 index b73e4b5a8770829dc1d467a20f86e4b962b3d863..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Catalog/Model/Product/Attribute/Api.php +++ /dev/null @@ -1,526 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Catalog - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Catalog product attribute api - * - * @category Mage - * @package Mage_Catalog - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Catalog_Model_Product_Attribute_Api extends Mage_Catalog_Model_Api_Resource -{ - /** - * Product entity type id - * - * @var int - */ - protected $_entityTypeId; - - /** - * Constructor. Initializes default values. - */ - public function __construct() - { - $this->_storeIdSessionField = 'product_store_id'; - $this->_ignoredAttributeCodes[] = 'type_id'; - $this->_ignoredAttributeTypes[] = 'gallery'; - $this->_ignoredAttributeTypes[] = 'media_image'; - $this->_entityTypeId = Mage::getModel('Mage_Eav_Model_Entity')->setType('catalog_product')->getTypeId(); - } - - /** - * Retrieve attributes from specified attribute set - * - * @param int $setId - * @return array - */ - public function items($setId) - { - $attributes = Mage::getModel('Mage_Catalog_Model_Product')->getResource() - ->loadAllAttributes() - ->getSortedAttributes($setId); - $result = array(); - - foreach ($attributes as $attribute) { - /* @var $attribute Mage_Catalog_Model_Resource_Eav_Attribute */ - if ((!$attribute->getId() || $attribute->isInSet($setId)) - && $this->_isAllowedAttribute($attribute)) { - - if (!$attribute->getId() || $attribute->isScopeGlobal()) { - $scope = 'global'; - } elseif ($attribute->isScopeWebsite()) { - $scope = 'website'; - } else { - $scope = 'store'; - } - - $result[] = array( - 'attribute_id' => $attribute->getId(), - 'code' => $attribute->getAttributeCode(), - 'type' => $attribute->getFrontendInput(), - 'required' => $attribute->getIsRequired(), - 'scope' => $scope - ); - } - } - - return $result; - } - - /** - * Retrieve attribute options - * - * @param int $attributeId - * @param string|int $store - * @return array - */ - public function options($attributeId, $store = null) - { - $storeId = $this->_getStoreId($store); - $attribute = Mage::getModel('Mage_Catalog_Model_Product') - ->setStoreId($storeId) - ->getResource() - ->getAttribute($attributeId); - - /* @var $attribute Mage_Catalog_Model_Entity_Attribute */ - if (!$attribute) { - $this->_fault('not_exists'); - } - $options = array(); - if ($attribute->usesSource()) { - foreach ($attribute->getSource()->getAllOptions() as $optionId => $optionValue) { - if (is_array($optionValue)) { - $options[] = $optionValue; - } else { - $options[] = array( - 'value' => $optionId, - 'label' => $optionValue - ); - } - } - } - - return $options; - } - - /** - * Retrieve list of possible attribute types - * - * @return array - */ - public function types() - { - return Mage::getModel('Mage_Catalog_Model_Product_Attribute_Source_Inputtype')->toOptionArray(); - } - - /** - * Create new product attribute - * - * @param array $data input data - * @return integer - */ - public function create($data) - { - /** @var $model Mage_Catalog_Model_Resource_Eav_Attribute */ - $model = Mage::getModel('Mage_Catalog_Model_Resource_Eav_Attribute'); - /** @var $helper Mage_Catalog_Helper_Product */ - $helper = Mage::helper('Mage_Catalog_Helper_Product'); - - if (empty($data['attribute_code']) || !is_array($data['frontend_label'])) { - $this->_fault('invalid_parameters'); - } - - //validate attribute_code - if (!preg_match('/^[a-z][a-z_0-9]{0,254}$/', $data['attribute_code'])) { - $this->_fault('invalid_code'); - } - - //validate frontend_input - $allowedTypes = array(); - foreach ($this->types() as $type) { - $allowedTypes[] = $type['value']; - } - if (!in_array($data['frontend_input'], $allowedTypes)) { - $this->_fault('invalid_frontend_input'); - } - - $data['source_model'] = $helper->getAttributeSourceModelByInputType($data['frontend_input']); - $data['backend_model'] = $helper->getAttributeBackendModelByInputType($data['frontend_input']); - if (is_null($model->getIsUserDefined()) || $model->getIsUserDefined() != 0) { - $data['backend_type'] = $model->getBackendTypeByInput($data['frontend_input']); - } - - $this->_prepareDataForSave($data); - - $model->addData($data); - $model->setEntityTypeId($this->_entityTypeId); - $model->setIsUserDefined(1); - - try { - $model->save(); - // clear translation cache because attribute labels are stored in translation - Mage::app()->cleanCache(array(Mage_Core_Model_Translate::CACHE_TAG)); - } catch (Exception $e) { - $this->_fault('unable_to_save', $e->getMessage()); - } - - return (int) $model->getId(); - } - - /** - * Update product attribute - * - * @param string|integer $attribute attribute code or ID - * @param array $data - * @return boolean - */ - public function update($attribute, $data) - { - $model = $this->_getAttribute($attribute); - - if ($model->getEntityTypeId() != $this->_entityTypeId) { - $this->_fault('can_not_edit'); - } - - $data['attribute_code'] = $model->getAttributeCode(); - $data['is_user_defined'] = $model->getIsUserDefined(); - $data['frontend_input'] = $model->getFrontendInput(); - - $this->_prepareDataForSave($data); - - $model->addData($data); - try { - $model->save(); - // clear translation cache because attribute labels are stored in translation - Mage::app()->cleanCache(array(Mage_Core_Model_Translate::CACHE_TAG)); - return true; - } catch (Exception $e) { - $this->_fault('unable_to_save', $e->getMessage()); - } - } - - /** - * Remove attribute - * - * @param integer|string $attribute attribute ID or code - * @return boolean - */ - public function remove($attribute) - { - $model = $this->_getAttribute($attribute); - - if ($model->getEntityTypeId() != $this->_entityTypeId) { - $this->_fault('can_not_delete'); - } - - try { - $model->delete(); - return true; - } catch (Exception $e) { - $this->_fault('can_not_delete', $e->getMessage()); - } - } - - /** - * Get full information about attribute with list of options - * - * @param integer|string $attribute attribute ID or code - * @return array - */ - public function info($attribute) - { - $model = $this->_getAttribute($attribute); - - if ($model->isScopeGlobal()) { - $scope = 'global'; - } elseif ($model->isScopeWebsite()) { - $scope = 'website'; - } else { - $scope = 'store'; - } - - $frontendLabels = array( - array( - 'store_id' => 0, - 'label' => $model->getFrontendLabel() - ) - ); - foreach ($model->getStoreLabels() as $store_id => $label) { - $frontendLabels[] = array( - 'store_id' => $store_id, - 'label' => $label - ); - } - - $result = array( - 'attribute_id' => $model->getId(), - 'attribute_code' => $model->getAttributeCode(), - 'frontend_input' => $model->getFrontendInput(), - 'default_value' => $model->getDefaultValue(), - 'is_unique' => $model->getIsUnique(), - 'is_required' => $model->getIsRequired(), - 'apply_to' => $model->getApplyTo(), - 'is_configurable' => $model->getIsConfigurable(), - 'is_searchable' => $model->getIsSearchable(), - 'is_visible_in_advanced_search' => $model->getIsVisibleInAdvancedSearch(), - 'is_comparable' => $model->getIsComparable(), - 'is_used_for_promo_rules' => $model->getIsUsedForPromoRules(), - 'is_visible_on_front' => $model->getIsVisibleOnFront(), - 'used_in_product_listing' => $model->getUsedInProductListing(), - 'frontend_label' => $frontendLabels - ); - if ($model->getFrontendInput() != 'price') { - $result['scope'] = $scope; - } - - // set additional fields to different types - switch ($model->getFrontendInput()) { - case 'text': - $result['additional_fields'] = array( - 'frontend_class' => $model->getFrontendClass(), - 'is_html_allowed_on_front' => $model->getIsHtmlAllowedOnFront(), - 'used_for_sort_by' => $model->getUsedForSortBy() - ); - break; - case 'textarea': - $result['additional_fields'] = array( - 'is_wysiwyg_enabled' => $model->getIsWysiwygEnabled(), - 'is_html_allowed_on_front' => $model->getIsHtmlAllowedOnFront(), - ); - break; - case 'date': - case 'boolean': - $result['additional_fields'] = array( - 'used_for_sort_by' => $model->getUsedForSortBy() - ); - break; - case 'multiselect': - $result['additional_fields'] = array( - 'is_filterable' => $model->getIsFilterable(), - 'is_filterable_in_search' => $model->getIsFilterableInSearch(), - 'position' => $model->getPosition() - ); - break; - case 'select': - case 'price': - $result['additional_fields'] = array( - 'is_filterable' => $model->getIsFilterable(), - 'is_filterable_in_search' => $model->getIsFilterableInSearch(), - 'position' => $model->getPosition(), - 'used_for_sort_by' => $model->getUsedForSortBy() - ); - break; - default: - $result['additional_fields'] = array(); - break; - } - - // set options - $options = $this->options($model->getId()); - // remove empty first element - if ($model->getFrontendInput() != 'boolean') { - array_shift($options); - } - - if (count($options) > 0) { - $result['options'] = $options; - } - - return $result; - } - - /** - * Add option to select or multiselect attribute - * - * @param integer|string $attribute attribute ID or code - * @param array $data - * @return bool - */ - public function addOption($attribute, $data) - { - $model = $this->_getAttribute($attribute); - - if (!$model->usesSource()) { - $this->_fault('invalid_frontend_input'); - } - - /** @var $helperCatalog Mage_Catalog_Helper_Data */ - $helperCatalog = Mage::helper('Mage_Catalog_Helper_Data'); - - $optionLabels = array(); - foreach ($data['label'] as $label) { - $storeId = $label['store_id']; - $labelText = $helperCatalog->stripTags($label['value']); - if (is_array($storeId)) { - foreach ($storeId as $multiStoreId) { - $optionLabels[$multiStoreId] = $labelText; - } - } else { - $optionLabels[$storeId] = $labelText; - } - } - // data in the following format is accepted by the model - // it simulates parameters of the request made to - // Mage_Adminhtml_Catalog_Product_AttributeController::saveAction() - $modelData = array( - 'option' => array( - 'value' => array( - 'option_1' => $optionLabels - ), - 'order' => array( - 'option_1' => (int) $data['order'] - ) - ) - ); - if ($data['is_default']) { - $modelData['default'][] = 'option_1'; - } - - $model->addData($modelData); - try { - $model->save(); - } catch (Exception $e) { - $this->_fault('unable_to_add_option', $e->getMessage()); - } - - return true; - } - - /** - * Remove option from select or multiselect attribute - * - * @param integer|string $attribute attribute ID or code - * @param integer $optionId option to remove ID - * @return bool - */ - public function removeOption($attribute, $optionId) - { - $model = $this->_getAttribute($attribute); - - if (!$model->usesSource()) { - $this->_fault('invalid_frontend_input'); - } - - // data in the following format is accepted by the model - // it simulates parameters of the request made to - // Mage_Adminhtml_Catalog_Product_AttributeController::saveAction() - $modelData = array( - 'option' => array( - 'value' => array( - $optionId => array() - ), - 'delete' => array( - $optionId => '1' - ) - ) - ); - $model->addData($modelData); - try { - $model->save(); - } catch (Exception $e) { - $this->_fault('unable_to_remove_option', $e->getMessage()); - } - - return true; - } - - /** - * Prepare request input data for saving - * - * @param array $data input data - * @return void - */ - protected function _prepareDataForSave(&$data) - { - /** @var $helperCatalog Mage_Catalog_Helper_Data */ - $helperCatalog = Mage::helper('Mage_Catalog_Helper_Data'); - - if ($data['scope'] == 'global') { - $data['is_global'] = Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_GLOBAL; - } else if ($data['scope'] == 'website') { - $data['is_global'] = Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_WEBSITE; - } else { - $data['is_global'] = Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_STORE; - } - if (!isset($data['is_configurable'])) { - $data['is_configurable'] = 0; - } - if (!isset($data['is_filterable'])) { - $data['is_filterable'] = 0; - } - if (!isset($data['is_filterable_in_search'])) { - $data['is_filterable_in_search'] = 0; - } - if (!isset($data['apply_to'])) { - $data['apply_to'] = array(); - } - // set frontend labels array with store_id as keys - if (isset($data['frontend_label']) && is_array($data['frontend_label'])) { - $labels = array(); - foreach ($data['frontend_label'] as $label) { - $storeId = $label['store_id']; - $labelText = $helperCatalog->stripTags($label['label']); - $labels[$storeId] = $labelText; - } - $data['frontend_label'] = $labels; - } - // set additional fields - if (isset($data['additional_fields']) && is_array($data['additional_fields'])) { - $data = array_merge($data, $data['additional_fields']); - unset($data['additional_fields']); - } - //default value - if (!empty($data['default_value'])) { - $data['default_value'] = $helperCatalog->stripTags($data['default_value']); - } - } - - /** - * Load model by attribute ID or code - * - * @param integer|string $attribute - * @return Mage_Catalog_Model_Resource_Eav_Attribute - */ - protected function _getAttribute($attribute) - { - $model = Mage::getResourceModel('Mage_Catalog_Model_Resource_Eav_Attribute') - ->setEntityTypeId($this->_entityTypeId); - - if (is_numeric($attribute)) { - $model->load(intval($attribute)); - } else { - $model->load($attribute, 'attribute_code'); - } - - if (!$model->getId()) { - $this->_fault('not_exists'); - } - - return $model; - } - -} // Class Mage_Catalog_Model_Product_Attribute_Api End diff --git a/app/code/core/Mage/Catalog/Model/Product/Attribute/Api/V2.php b/app/code/core/Mage/Catalog/Model/Product/Attribute/Api/V2.php deleted file mode 100644 index ffdee65ccde74789458001be0a3b9b90aa691a09..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Catalog/Model/Product/Attribute/Api/V2.php +++ /dev/null @@ -1,99 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Catalog - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Catalog product attribute api - * - * @category Mage - * @package Mage_Catalog - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Catalog_Model_Product_Attribute_Api_V2 extends Mage_Catalog_Model_Product_Attribute_Api -{ - /** - * Create new product attribute - * - * @param array $data input data - * @return integer - */ - public function create($data) - { - $helper = Mage::helper('Mage_Api_Helper_Data'); - $helper->v2AssociativeArrayUnpacker($data); - Mage::helper('Mage_Api_Helper_Data')->toArray($data); - return parent::create($data); - } - - /** - * Update product attribute - * - * @param string|integer $attribute attribute code or ID - * @param array $data - * @return boolean - */ - public function update($attribute, $data) - { - $helper = Mage::helper('Mage_Api_Helper_Data'); - $helper->v2AssociativeArrayUnpacker($data); - Mage::helper('Mage_Api_Helper_Data')->toArray($data); - return parent::update($attribute, $data); - } - - /** - * Add option to select or multiselect attribute - * - * @param integer|string $attribute attribute ID or code - * @param array $data - * @return bool - */ - public function addOption($attribute, $data) - { - Mage::helper('Mage_Api_Helper_Data')->toArray($data); - return parent::addOption($attribute, $data); - } - - /** - * Get full information about attribute with list of options - * - * @param integer|string $attribute attribute ID or code - * @return array - */ - public function info($attribute) - { - $result = parent::info($attribute); - if (!empty($result['additional_fields'])){ - $keys = array_keys($result['additional_fields']); - foreach ($keys as $key ) { - $result['additional_fields'][] = array( - 'key' => $key, - 'value' => $result['additional_fields'][$key] - ); - unset($result['additional_fields'][$key]); - } - } - return $result; - } -} diff --git a/app/code/core/Mage/Catalog/Model/Product/Attribute/Media/Api.php b/app/code/core/Mage/Catalog/Model/Product/Attribute/Media/Api.php deleted file mode 100644 index f3fc4c8572ab6334ff850a30305505e72b81507e..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Catalog/Model/Product/Attribute/Media/Api.php +++ /dev/null @@ -1,417 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Catalog - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Catalog product media api - * - * @category Mage - * @package Mage_Catalog - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Catalog_Model_Product_Attribute_Media_Api extends Mage_Catalog_Model_Api_Resource -{ - /** - * Attribute code for media gallery - * - */ - const ATTRIBUTE_CODE = 'media_gallery'; - - /** - * Allowed mime types for image - * - * @var array - */ - protected $_mimeTypes = array( - 'image/jpeg' => 'jpg', - 'image/gif' => 'gif', - 'image/png' => 'png' - ); - - public function __construct() - { - $this->_storeIdSessionField = 'product_store_id'; - } - - /** - * Retrieve images for product - * - * @param int|string $productId - * @param string|int $store - * @return array - */ - public function items($productId, $store = null, $identifierType = null) - { - $product = $this->_initProduct($productId, $store, $identifierType); - - $gallery = $this->_getGalleryAttribute($product); - - $galleryData = $product->getData(self::ATTRIBUTE_CODE); - - if (!isset($galleryData['images']) || !is_array($galleryData['images'])) { - return array(); - } - - $result = array(); - - foreach ($galleryData['images'] as &$image) { - $result[] = $this->_imageToArray($image, $product); - } - - return $result; - } - - /** - * Retrieve image data - * - * @param int|string $productId - * @param string $file - * @param string|int $store - * @return array - */ - public function info($productId, $file, $store = null, $identifierType = null) - { - $product = $this->_initProduct($productId, $store, $identifierType); - - $gallery = $this->_getGalleryAttribute($product); - - if (!$image = $gallery->getBackend()->getImage($product, $file)) { - $this->_fault('not_exists'); - } - - return $this->_imageToArray($image, $product); - } - - /** - * Create new image for product and return image filename - * - * @throws Mage_Api_Exception - * @param int|string $productId - * @param array $data - * @param string|int $store - * @return string - */ - public function create($productId, $data, $store = null, $identifierType = null) - { - $data = $this->_prepareImageData($data); - - $product = $this->_initProduct($productId, $store, $identifierType); - - $gallery = $this->_getGalleryAttribute($product); - - if (!isset($data['file']) || !isset($data['file']['mime']) || !isset($data['file']['content'])) { - $this->_fault('data_invalid', Mage::helper('Mage_Catalog_Helper_Data')->__('The image is not specified.')); - } - - if (!isset($this->_mimeTypes[$data['file']['mime']])) { - $this->_fault('data_invalid', Mage::helper('Mage_Catalog_Helper_Data')->__('Invalid image type.')); - } - - $fileContent = @base64_decode($data['file']['content'], true); - if (!$fileContent) { - $this->_fault('data_invalid', Mage::helper('Mage_Catalog_Helper_Data')->__('The image contents is not valid base64 data.')); - } - - unset($data['file']['content']); - - $tmpDirectory = Mage::getBaseDir('var') . DS . 'api' . DS . $this->_getSession()->getSessionId(); - - if (isset($data['file']['name']) && $data['file']['name']) { - $fileName = $data['file']['name']; - } else { - $fileName = 'image'; - } - $fileName .= '.' . $this->_mimeTypes[$data['file']['mime']]; - - $ioAdapter = new Varien_Io_File(); - try { - // Create temporary directory for api - $ioAdapter->checkAndCreateFolder($tmpDirectory); - $ioAdapter->open(array('path'=>$tmpDirectory)); - // Write image file - $ioAdapter->write($fileName, $fileContent, 0666); - unset($fileContent); - - // try to create Image object - it fails with Exception if image is not supported - try { - $adapter = Mage::helper('Mage_Core_Helper_Data')->getImageAdapterType(); - new Varien_Image($tmpDirectory . DS . $fileName, $adapter); - } catch (Exception $e) { - // Remove temporary directory - $ioAdapter->rmdir($tmpDirectory, true); - - throw new Mage_Core_Exception($e->getMessage()); - } - - // Adding image to gallery - $file = $gallery->getBackend()->addImage( - $product, - $tmpDirectory . DS . $fileName, - null, - true - ); - - // Remove temporary directory - $ioAdapter->rmdir($tmpDirectory, true); - - $gallery->getBackend()->updateImage($product, $file, $data); - - if (isset($data['types'])) { - $gallery->getBackend()->setMediaAttribute($product, $data['types'], $file); - } - - $product->save(); - } catch (Mage_Core_Exception $e) { - $this->_fault('not_created', $e->getMessage()); - } catch (Exception $e) { - $this->_fault('not_created', Mage::helper('Mage_Catalog_Helper_Data')->__('Cannot create image.')); - } - - return $gallery->getBackend()->getRenamedImage($file); - } - - /** - * Update image data - * - * @param int|string $productId - * @param string $file - * @param array $data - * @param string|int $store - * @return boolean - */ - public function update($productId, $file, $data, $store = null, $identifierType = null) - { - $data = $this->_prepareImageData($data); - - $product = $this->_initProduct($productId, $store, $identifierType); - - $gallery = $this->_getGalleryAttribute($product); - - if (!$gallery->getBackend()->getImage($product, $file)) { - $this->_fault('not_exists'); - } - - if (isset($data['file']['mime']) && isset($data['file']['content'])) { - if (!isset($this->_mimeTypes[$data['file']['mime']])) { - $this->_fault('data_invalid', Mage::helper('Mage_Catalog_Helper_Data')->__('Invalid image type.')); - } - - $fileContent = @base64_decode($data['file']['content'], true); - if (!$fileContent) { - $this->_fault('data_invalid', Mage::helper('Mage_Catalog_Helper_Data')->__('Image content is not valid base64 data.')); - } - - unset($data['file']['content']); - - $ioAdapter = new Varien_Io_File(); - try { - $fileName = Mage::getBaseDir('media'). DS . 'catalog' . DS . 'product' . $file; - $ioAdapter->open(array('path'=>dirname($fileName))); - $ioAdapter->write(basename($fileName), $fileContent, 0666); - - } catch(Exception $e) { - $this->_fault('not_created', Mage::helper('Mage_Catalog_Helper_Data')->__('Can\'t create image.')); - } - } - - $gallery->getBackend()->updateImage($product, $file, $data); - - if (isset($data['types']) && is_array($data['types'])) { - $oldTypes = array(); - foreach ($product->getMediaAttributes() as $attribute) { - if ($product->getData($attribute->getAttributeCode()) == $file) { - $oldTypes[] = $attribute->getAttributeCode(); - } - } - - $clear = array_diff($oldTypes, $data['types']); - - if (count($clear) > 0) { - $gallery->getBackend()->clearMediaAttribute($product, $clear); - } - - $gallery->getBackend()->setMediaAttribute($product, $data['types'], $file); - } - - try { - $product->save(); - } catch (Mage_Core_Exception $e) { - $this->_fault('not_updated', $e->getMessage()); - } - - return true; - } - - /** - * Remove image from product - * - * @param int|string $productId - * @param string $file - * @return boolean - */ - public function remove($productId, $file, $identifierType = null) - { - $product = $this->_initProduct($productId, null, $identifierType); - - $gallery = $this->_getGalleryAttribute($product); - - if (!$gallery->getBackend()->getImage($product, $file)) { - $this->_fault('not_exists'); - } - - $gallery->getBackend()->removeImage($product, $file); - - try { - $product->save(); - } catch (Mage_Core_Exception $e) { - $this->_fault('not_removed', $e->getMessage()); - } - - return true; - } - - - /** - * Retrieve image types (image, small_image, thumbnail, etc...) - * - * @param int $setId - * @return array - */ - public function types($setId) - { - $attributes = Mage::getModel('Mage_Catalog_Model_Product')->getResource() - ->loadAllAttributes() - ->getSortedAttributes($setId); - - $result = array(); - - foreach ($attributes as $attribute) { - /* @var $attribute Mage_Catalog_Model_Resource_Eav_Attribute */ - if ($attribute->isInSet($setId) - && $attribute->getFrontendInput() == 'media_image') { - if ($attribute->isScopeGlobal()) { - $scope = 'global'; - } elseif ($attribute->isScopeWebsite()) { - $scope = 'website'; - } else { - $scope = 'store'; - } - - $result[] = array( - 'code' => $attribute->getAttributeCode(), - 'scope' => $scope - ); - } - } - - return $result; - } - - /** - * Prepare data to create or update image - * - * @param array $data - * @return array - */ - protected function _prepareImageData($data) - { - return $data; - } - - /** - * Retrieve gallery attribute from product - * - * @param Mage_Catalog_Model_Product $product - * @param Mage_Catalog_Model_Resource_Attribute|boolean - */ - protected function _getGalleryAttribute($product) - { - $attributes = $product->getTypeInstance() - ->getSetAttributes($product); - - if (!isset($attributes[self::ATTRIBUTE_CODE])) { - $this->_fault('not_media'); - } - - return $attributes[self::ATTRIBUTE_CODE]; - } - - /** - * Retrie - * ve media config - * - * @return Mage_Catalog_Model_Product_Media_Config - */ - protected function _getMediaConfig() - { - return Mage::getSingleton('Mage_Catalog_Model_Product_Media_Config'); - } - - /** - * Converts image to api array data - * - * @param array $image - * @param Mage_Catalog_Model_Product $product - * @return array - */ - protected function _imageToArray(&$image, $product) - { - $result = array( - 'file' => $image['file'], - 'label' => $image['label'], - 'position' => $image['position'], - 'exclude' => $image['disabled'], - 'url' => $this->_getMediaConfig()->getMediaUrl($image['file']), - 'types' => array() - ); - - - foreach ($product->getMediaAttributes() as $attribute) { - if ($product->getData($attribute->getAttributeCode()) == $image['file']) { - $result['types'][] = $attribute->getAttributeCode(); - } - } - - return $result; - } - - /** - * Retrieve product - * - * @param int|string $productId - * @param string|int $store - * @param string $identifierType - * @return Mage_Catalog_Model_Product - */ - protected function _initProduct($productId, $store = null, $identifierType = null) - { - $product = Mage::helper('Mage_Catalog_Helper_Product')->getProduct($productId, $this->_getStoreId($store), $identifierType); - if (!$product->getId()) { - $this->_fault('product_not_exists'); - } - - return $product; - } -} // Class Mage_Catalog_Model_Product_Attribute_Media_Api End diff --git a/app/code/core/Mage/Catalog/Model/Product/Attribute/Media/Api/V2.php b/app/code/core/Mage/Catalog/Model/Product/Attribute/Media/Api/V2.php deleted file mode 100644 index 477cadae960c82b80ee61e34f1f3e28311b213c7..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Catalog/Model/Product/Attribute/Media/Api/V2.php +++ /dev/null @@ -1,53 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Catalog - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Catalog product media api V2 - * - * @category Mage - * @package Mage_Catalog - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Catalog_Model_Product_Attribute_Media_Api_V2 extends Mage_Catalog_Model_Product_Attribute_Media_Api -{ - /** - * Prepare data to create or update image - * - * @param stdClass $data - * @return array - */ - protected function _prepareImageData($data) - { - if( !is_object($data) ) { - return parent::_prepareImageData($data); - } - $_imageData = get_object_vars($data); - if( isset($data->file) && is_object($data->file) ) { - $_imageData['file'] = get_object_vars($data->file); - } - return parent::_prepareImageData($_imageData); - } -} diff --git a/app/code/core/Mage/Catalog/Model/Product/Attribute/Set/Api.php b/app/code/core/Mage/Catalog/Model/Product/Attribute/Set/Api.php deleted file mode 100644 index 1134c768a4fee60cc48a8c57cf5f0fc25e021086..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Catalog/Model/Product/Attribute/Set/Api.php +++ /dev/null @@ -1,287 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Catalog - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Catalog product attribute set api - * - * @category Mage - * @package Mage_Catalog - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Catalog_Model_Product_Attribute_Set_Api extends Mage_Api_Model_Resource_Abstract -{ - /** - * Retrieve attribute set list - * - * @return array - */ - public function items() - { - $entityType = Mage::getModel('Mage_Catalog_Model_Product')->getResource()->getEntityType(); - $collection = Mage::getResourceModel('Mage_Eav_Model_Resource_Entity_Attribute_Set_Collection') - ->setEntityTypeFilter($entityType->getId()); - - $result = array(); - foreach ($collection as $attributeSet) { - $result[] = array( - 'set_id' => $attributeSet->getId(), - 'name' => $attributeSet->getAttributeSetName() - ); - - } - - return $result; - } - - /** - * Create new attribute set based on another set - * - * @param string $attributeSetName - * @param string $skeletonSetId - * @return integer - */ - public function create($attributeSetName, $skeletonSetId) - { - // check if set with requested $skeletonSetId exists - if (!Mage::getModel('Mage_Eav_Model_Entity_Attribute_Set')->load($skeletonSetId)->getId()){ - $this->_fault('invalid_skeleton_set_id'); - } - // get catalog product entity type id - $entityTypeId = Mage::getModel('Mage_Catalog_Model_Product')->getResource()->getTypeId(); - /** @var $attributeSet Mage_Eav_Model_Entity_Attribute_Set */ - $attributeSet = Mage::getModel('Mage_Eav_Model_Entity_Attribute_Set') - ->setEntityTypeId($entityTypeId) - ->setAttributeSetName($attributeSetName); - try { - // check if name is valid - $attributeSet->validate(); - // copy parameters to new set from skeleton set - $attributeSet->save(); - $attributeSet->initFromSkeleton($skeletonSetId)->save(); - } catch (Mage_Eav_Exception $e) { - $this->_fault('invalid_data', $e->getMessage()); - } catch (Exception $e) { - $this->_fault('create_attribute_set_error', $e->getMessage()); - } - return (int)$attributeSet->getId(); - } - - /** - * Remove attribute set - * - * @param string $attributeSetId - * @param bool $forceProductsRemove - * @return bool - */ - public function remove($attributeSetId, $forceProductsRemove = false) - { - // if attribute set has related goods and $forceProductsRemove is not set throw exception - if (!$forceProductsRemove) { - /** @var $catalogProductsCollection Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection */ - $catalogProductsCollection = Mage::getModel('Mage_Catalog_Model_Product')->getCollection() - ->addFieldToFilter('attribute_set_id', $attributeSetId); - if (count($catalogProductsCollection)) { - $this->_fault('attribute_set_has_related_products'); - } - } - $attributeSet = Mage::getModel('Mage_Eav_Model_Entity_Attribute_Set')->load($attributeSetId); - // check if set with requested id exists - if (!$attributeSet->getId()){ - $this->_fault('invalid_attribute_set_id'); - } - try { - $attributeSet->delete(); - } catch (Exception $e) { - $this->_fault('remove_attribute_set_error', $e->getMessage()); - } - return true; - } - - /** - * Add attribute to attribute set - * - * @param string $attributeId - * @param string $attributeSetId - * @param string|null $attributeGroupId - * @param string $sortOrder - * @return bool - */ - public function attributeAdd($attributeId, $attributeSetId, $attributeGroupId = null, $sortOrder = '0') - { - // check if attribute with requested id exists - /** @var $attribute Mage_Eav_Model_Entity_Attribute */ - $attribute = Mage::getModel('Mage_Eav_Model_Entity_Attribute')->load($attributeId); - if (!$attribute->getId()) { - $this->_fault('invalid_attribute_id'); - } - // check if attribute set with requested id exists - /** @var $attributeSet Mage_Eav_Model_Entity_Attribute_Set */ - $attributeSet = Mage::getModel('Mage_Eav_Model_Entity_Attribute_Set')->load($attributeSetId); - if (!$attributeSet->getId()) { - $this->_fault('invalid_attribute_set_id'); - } - if (!empty($attributeGroupId)) { - // check if attribute group with requested id exists - if (!Mage::getModel('Mage_Eav_Model_Entity_Attribute_Group')->load($attributeGroupId)->getId()) { - $this->_fault('invalid_attribute_group_id'); - } - } else { - // define default attribute group id for current attribute set - $attributeGroupId = $attributeSet->getDefaultGroupId(); - } - $attribute->setAttributeSetId($attributeSet->getId())->loadEntityAttributeIdBySet(); - if ($attribute->getEntityAttributeId()) { - $this->_fault('attribute_is_already_in_set'); - } - try { - $attribute->setEntityTypeId($attributeSet->getEntityTypeId()) - ->setAttributeSetId($attributeSetId) - ->setAttributeGroupId($attributeGroupId) - ->setSortOrder($sortOrder) - ->save(); - } catch (Exception $e) { - $this->_fault('add_attribute_error', $e->getMessage()); - } - return true; - } - - /** - * Remove attribute from attribute set - * - * @param string $attributeId - * @param string $attributeSetId - * @return bool - */ - public function attributeRemove($attributeId, $attributeSetId) - { - // check if attribute with requested id exists - /** @var $attribute Mage_Eav_Model_Entity_Attribute */ - $attribute = Mage::getModel('Mage_Eav_Model_Entity_Attribute')->load($attributeId); - if (!$attribute->getId()) { - $this->_fault('invalid_attribute_id'); - } - // check if attribute set with requested id exists - /** @var $attributeSet Mage_Eav_Model_Entity_Attribute_Set */ - $attributeSet = Mage::getModel('Mage_Eav_Model_Entity_Attribute_Set')->load($attributeSetId); - if (!$attributeSet->getId()) { - $this->_fault('invalid_attribute_set_id'); - } - // check if attribute is in set - $attribute->setAttributeSetId($attributeSet->getId())->loadEntityAttributeIdBySet(); - if (!$attribute->getEntityAttributeId()) { - $this->_fault('attribute_is_not_in_set'); - } - try { - // delete record from eav_entity_attribute - // using entity_attribute_id loaded by loadEntityAttributeIdBySet() - $attribute->deleteEntity(); - } catch (Exception $e) { - $this->_fault('remove_attribute_error', $e->getMessage()); - } - - return true; - } - - /** - * Create group within existing attribute set - * - * @param string|int $attributeSetId - * @param string $groupName - * @return int - */ - public function groupAdd($attributeSetId, $groupName) - { - /** @var $group Mage_Eav_Model_Entity_Attribute_Group */ - $group = Mage::getModel('Mage_Eav_Model_Entity_Attribute_Group'); - $group->setAttributeSetId($attributeSetId) - ->setAttributeGroupName( - Mage::helper('Mage_Catalog_Helper_Data')->stripTags($groupName) - ); - if ($group->itemExists()) { - $this->_fault('group_already_exists'); - } - try { - $group->save(); - } catch (Exception $e) { - $this->_fault('group_add_error', $e->getMessage()); - } - return (int)$group->getId(); - } - - /** - * Rename existing group - * - * @param string|int $groupId - * @param string $groupName - * @return boolean - */ - public function groupRename($groupId, $groupName) - { - $model = Mage::getModel('Mage_Eav_Model_Entity_Attribute_Group')->load($groupId); - - if (!$model->getAttributeGroupName()) { - $this->_fault('invalid_attribute_group_id'); - } - - $model->setAttributeGroupName( - Mage::helper('Mage_Catalog_Helper_Data')->stripTags($groupName) - ); - try { - $model->save(); - } catch (Exception $e) { - $this->_fault('group_rename_error', $e->getMessage()); - } - return true; - } - - /** - * Remove group from existing attribute set - * - * @param string|int $attributeGroupId - * @return bool - */ - public function groupRemove($attributeGroupId) - { - /** @var $group Mage_Catalog_Model_Product_Attribute_Group */ - $group = Mage::getModel('Mage_Catalog_Model_Product_Attribute_Group')->load($attributeGroupId); - if (!$group->getId()) { - $this->_fault('invalid_attribute_group_id'); - } - if ($group->hasConfigurableAttributes()) { - $this->_fault('group_has_configurable_attributes'); - } - if ($group->hasSystemAttributes()) { - $this->_fault('group_has_system_attributes'); - } - try { - $group->delete(); - } catch (Exception $e) { - $this->_fault('group_remove_error', $e->getMessage()); - } - return true; - } - -} // Class Mage_Catalog_Model_Product_Attribute_Set_Api End diff --git a/app/code/core/Mage/Catalog/Model/Product/Attribute/Set/Api/V2.php b/app/code/core/Mage/Catalog/Model/Product/Attribute/Set/Api/V2.php deleted file mode 100644 index ddb8973ebf6b15737ae23040b334c0b7512b928e..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Catalog/Model/Product/Attribute/Set/Api/V2.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Catalog - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Catalog product attribute set api V2 - * - * @category Mage - * @package Mage_Catalog - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Catalog_Model_Product_Attribute_Set_Api_V2 extends Mage_Catalog_Model_Product_Attribute_Set_Api -{ -} diff --git a/app/code/core/Mage/Catalog/Model/Product/Attribute/Tierprice/Api.php b/app/code/core/Mage/Catalog/Model/Product/Attribute/Tierprice/Api.php deleted file mode 100644 index 52e03704dd5a568195549ebdcadf1a1c98c163fd..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Catalog/Model/Product/Attribute/Tierprice/Api.php +++ /dev/null @@ -1,183 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Catalog - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Catalog Product tier price api - * - * @category Mage - * @package Mage_Catalog - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Catalog_Model_Product_Attribute_Tierprice_Api extends Mage_Catalog_Model_Api_Resource -{ - const ATTRIBUTE_CODE = 'tier_price'; - - public function __construct() - { - $this->_storeIdSessionField = 'product_store_id'; - } - - public function info($productId, $identifierType = null) - { - $product = $this->_initProduct($productId, $identifierType); - $tierPrices = $product->getData(self::ATTRIBUTE_CODE); - - if (!is_array($tierPrices)) { - return array(); - } - - $result = array(); - - foreach ($tierPrices as $tierPrice) { - $row = array(); - $row['customer_group_id'] = (empty($tierPrice['all_groups']) ? $tierPrice['cust_group'] : 'all' ); - $row['website'] = ($tierPrice['website_id'] ? - Mage::app()->getWebsite($tierPrice['website_id'])->getCode() : - 'all' - ); - $row['qty'] = $tierPrice['price_qty']; - $row['price'] = $tierPrice['price']; - - $result[] = $row; - } - - return $result; - } - - /** - * Update tier prices of product - * - * @param int|string $productId - * @param array $tierPrices - * @return boolean - */ - public function update($productId, $tierPrices, $identifierType = null) - { - $product = $this->_initProduct($productId, $identifierType); - - $updatedTierPrices = $this->prepareTierPrices($product, $tierPrices); - if (is_null($updatedTierPrices)) { - $this->_fault('data_invalid', Mage::helper('Mage_Catalog_Helper_Data')->__('Invalid Tier Prices')); - } - - $product->setData(self::ATTRIBUTE_CODE, $updatedTierPrices); - try { - /** - * @todo implement full validation process with errors returning which are ignoring now - * @todo see Mage_Catalog_Model_Product::validate() - */ - if (is_array($errors = $product->validate())) { - $strErrors = array(); - foreach($errors as $code=>$error) { - $strErrors[] = ($error === true)? Mage::helper('Mage_Catalog_Helper_Data')->__('Value for "%s" is invalid.', $code) : Mage::helper('Mage_Catalog_Helper_Data')->__('Value for "%s" is invalid: %s', $code, $error); - } - $this->_fault('data_invalid', implode("\n", $strErrors)); - } - - $product->save(); - } catch (Mage_Core_Exception $e) { - $this->_fault('not_updated', $e->getMessage()); - } - - return true; - } - - /** - * Prepare tier prices for save - * - * @param Mage_Catalog_Model_Product $product - * @param array $tierPrices - * @return array - */ - public function prepareTierPrices($product, $tierPrices = null) - { - if (!is_array($tierPrices)) { - return null; - } - - if (!is_array($tierPrices)) { - $this->_fault('data_invalid', Mage::helper('Mage_Catalog_Helper_Data')->__('Invalid Tier Prices')); - } - - $updateValue = array(); - - foreach ($tierPrices as $tierPrice) { - if (!is_array($tierPrice) - || !isset($tierPrice['qty']) - || !isset($tierPrice['price'])) { - $this->_fault('data_invalid', Mage::helper('Mage_Catalog_Helper_Data')->__('Invalid Tier Prices')); - } - - if (!isset($tierPrice['website']) || $tierPrice['website'] == 'all') { - $tierPrice['website'] = 0; - } else { - try { - $tierPrice['website'] = Mage::app()->getWebsite($tierPrice['website'])->getId(); - } catch (Mage_Core_Exception $e) { - $tierPrice['website'] = 0; - } - } - - if (intval($tierPrice['website']) > 0 && !in_array($tierPrice['website'], $product->getWebsiteIds())) { - $this->_fault('data_invalid', Mage::helper('Mage_Catalog_Helper_Data')->__('Invalid tier prices. The product is not associated to the requested website.')); - } - - if (!isset($tierPrice['customer_group_id'])) { - $tierPrice['customer_group_id'] = 'all'; - } - - if ($tierPrice['customer_group_id'] == 'all') { - $tierPrice['customer_group_id'] = Mage_Customer_Model_Group::CUST_GROUP_ALL; - } - - $updateValue[] = array( - 'website_id' => $tierPrice['website'], - 'cust_group' => $tierPrice['customer_group_id'], - 'price_qty' => $tierPrice['qty'], - 'price' => $tierPrice['price'] - ); - } - - return $updateValue; - } - - /** - * Retrieve product - * - * @param int $productId - * @param string $identifierType - * @return Mage_Catalog_Model_Product - */ - protected function _initProduct($productId, $identifierType = null) - { - $product = Mage::helper('Mage_Catalog_Helper_Product')->getProduct($productId, $this->_getStoreId(), $identifierType); - if (!$product->getId()) { - $this->_fault('product_not_exists'); - } - - return $product; - } -} // Class Mage_Catalog_Model_Product_Attribute_Tierprice End diff --git a/app/code/core/Mage/Catalog/Model/Product/Attribute/Tierprice/Api/V2.php b/app/code/core/Mage/Catalog/Model/Product/Attribute/Tierprice/Api/V2.php deleted file mode 100644 index aacbd0476c265a821b9714611afbc1c472b48176..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Catalog/Model/Product/Attribute/Tierprice/Api/V2.php +++ /dev/null @@ -1,91 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Catalog - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Catalog Product tier price api V2 - * - * @category Mage - * @package Mage_Catalog - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Catalog_Model_Product_Attribute_Tierprice_Api_V2 extends Mage_Catalog_Model_Product_Attribute_Tierprice_Api -{ - /** - * Prepare tier prices for save - * - * @param Mage_Catalog_Model_Product $product - * @param array $tierPrices - * @return array - */ - public function prepareTierPrices($product, $tierPrices = null) - { - if (!is_array($tierPrices)) { - return null; - } - - $updateValue = array(); - - foreach ($tierPrices as $tierPrice) { - if (!is_object($tierPrice) - || !isset($tierPrice->qty) - || !isset($tierPrice->price)) { - $this->_fault('data_invalid', Mage::helper('Mage_Catalog_Helper_Data')->__('Invalid Tier Prices')); - } - - if (!isset($tierPrice->website) || $tierPrice->website == 'all') { - $tierPrice->website = 0; - } else { - try { - $tierPrice->website = Mage::app()->getWebsite($tierPrice->website)->getId(); - } catch (Mage_Core_Exception $e) { - $tierPrice->website = 0; - } - } - - if (intval($tierPrice->website) > 0 && !in_array($tierPrice->website, $product->getWebsiteIds())) { - $this->_fault('data_invalid', Mage::helper('Mage_Catalog_Helper_Data')->__('Invalid tier prices. The product is not associated to the requested website.')); - } - - if (!isset($tierPrice->customer_group_id)) { - $tierPrice->customer_group_id = 'all'; - } - - if ($tierPrice->customer_group_id == 'all') { - $tierPrice->customer_group_id = Mage_Customer_Model_Group::CUST_GROUP_ALL; - } - - $updateValue[] = array( - 'website_id' => $tierPrice->website, - 'cust_group' => $tierPrice->customer_group_id, - 'price_qty' => $tierPrice->qty, - 'price' => $tierPrice->price - ); - - } - - return $updateValue; - } -} diff --git a/app/code/core/Mage/Catalog/Model/Product/Link/Api.php b/app/code/core/Mage/Catalog/Model/Product/Link/Api.php deleted file mode 100644 index 0790447e420e32f3888ed8393868b0ab0361bbd7..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Catalog/Model/Product/Link/Api.php +++ /dev/null @@ -1,349 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Catalog - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Catalog product link api - * - * @category Mage - * @package Mage_Catalog - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Catalog_Model_Product_Link_Api extends Mage_Catalog_Model_Api_Resource -{ - /** - * Product link type mapping, used for references and validation - * - * @var array - */ - protected $_typeMap = array( - 'related' => Mage_Catalog_Model_Product_Link::LINK_TYPE_RELATED, - 'up_sell' => Mage_Catalog_Model_Product_Link::LINK_TYPE_UPSELL, - 'cross_sell' => Mage_Catalog_Model_Product_Link::LINK_TYPE_CROSSSELL, - 'grouped' => Mage_Catalog_Model_Product_Link::LINK_TYPE_GROUPED - ); - - public function __construct() - { - $this->_storeIdSessionField = 'product_store_id'; - } - - /** - * Retrieve product link associations - * - * @param string $type - * @param int|sku $productId - * @param string $identifierType - * @return array - */ - public function items($type, $productId, $identifierType = null) - { - $typeId = $this->_getTypeId($type); - - $product = $this->_initProduct($productId, $identifierType); - - $link = $product->getLinkInstance() - ->setLinkTypeId($typeId); - - $collection = $this->_initCollection($link, $product); - - $result = array(); - - foreach ($collection as $linkedProduct) { - $row = array( - 'product_id' => $linkedProduct->getId(), - 'type' => $linkedProduct->getTypeId(), - 'set' => $linkedProduct->getAttributeSetId(), - 'sku' => $linkedProduct->getSku() - ); - - foreach ($link->getAttributes() as $attribute) { - $row[$attribute['code']] = $linkedProduct->getData($attribute['code']); - } - - $result[] = $row; - } - - return $result; - } - - /** - * Add product link association - * - * @param string $type - * @param int|string $productId - * @param int|string $linkedProductId - * @param array $data - * @param string $identifierType - * @return boolean - */ - public function assign($type, $productId, $linkedProductId, $data = array(), $identifierType = null) - { - $typeId = $this->_getTypeId($type); - - $product = $this->_initProduct($productId, $identifierType); - - $link = $product->getLinkInstance() - ->setLinkTypeId($typeId); - - $collection = $this->_initCollection($link, $product); - $idBySku = $product->getIdBySku($linkedProductId); - if ($idBySku) { - $linkedProductId = $idBySku; - } - - $links = $this->_collectionToEditableArray($collection); - - $links[(int)$linkedProductId] = array(); - - foreach ($collection->getLinkModel()->getAttributes() as $attribute) { - if (isset($data[$attribute['code']])) { - $links[(int)$linkedProductId][$attribute['code']] = $data[$attribute['code']]; - } - } - - try { - if ($type == 'grouped') { - $link->getResource()->saveGroupedLinks($product, $links, $typeId); - } else { - $link->getResource()->saveProductLinks($product, $links, $typeId); - } - - $_linkInstance = Mage::getSingleton('Mage_Catalog_Model_Product_Link'); - $_linkInstance->saveProductRelations($product); - - $indexerStock = Mage::getModel('Mage_CatalogInventory_Model_Stock_Status'); - $indexerStock->updateStatus($productId); - - $indexerPrice = Mage::getResourceModel('Mage_Catalog_Model_Resource_Product_Indexer_Price'); - $indexerPrice->reindexProductIds($productId); - } catch (Exception $e) { - $this->_fault('data_invalid', Mage::helper('Mage_Catalog_Helper_Data')->__('Link product does not exist.')); - } - - return true; - } - - /** - * Update product link association info - * - * @param string $type - * @param int|string $productId - * @param int|string $linkedProductId - * @param array $data - * @param string $identifierType - * @return boolean - */ - public function update($type, $productId, $linkedProductId, $data = array(), $identifierType = null) - { - $typeId = $this->_getTypeId($type); - - $product = $this->_initProduct($productId, $identifierType); - - $link = $product->getLinkInstance() - ->setLinkTypeId($typeId); - - $collection = $this->_initCollection($link, $product); - - $links = $this->_collectionToEditableArray($collection); - - $idBySku = $product->getIdBySku($linkedProductId); - if ($idBySku) { - $linkedProductId = $idBySku; - } - - foreach ($collection->getLinkModel()->getAttributes() as $attribute) { - if (isset($data[$attribute['code']])) { - $links[(int)$linkedProductId][$attribute['code']] = $data[$attribute['code']]; - } - } - - try { - if ($type == 'grouped') { - $link->getResource()->saveGroupedLinks($product, $links, $typeId); - } else { - $link->getResource()->saveProductLinks($product, $links, $typeId); - } - - $_linkInstance = Mage::getSingleton('Mage_Catalog_Model_Product_Link'); - $_linkInstance->saveProductRelations($product); - - $indexerStock = Mage::getModel('Mage_CatalogInventory_Model_Stock_Status'); - $indexerStock->updateStatus($productId); - - $indexerPrice = Mage::getResourceModel('Mage_Catalog_Model_Resource_Product_Indexer_Price'); - $indexerPrice->reindexProductIds($productId); - } catch (Exception $e) { - $this->_fault('data_invalid', Mage::helper('Mage_Catalog_Helper_Data')->__('Link product does not exist.')); - } - - return true; - } - - /** - * Remove product link association - * - * @param string $type - * @param int|string $productId - * @param int|string $linkedProductId - * @param string $identifierType - * @return boolean - */ - public function remove($type, $productId, $linkedProductId, $identifierType = null) - { - $typeId = $this->_getTypeId($type); - - $product = $this->_initProduct($productId, $identifierType); - - $link = $product->getLinkInstance() - ->setLinkTypeId($typeId); - - $collection = $this->_initCollection($link, $product); - - $idBySku = $product->getIdBySku($linkedProductId); - if ($idBySku) { - $linkedProductId = $idBySku; - } - - $links = $this->_collectionToEditableArray($collection); - - if (isset($links[$linkedProductId])) { - unset($links[$linkedProductId]); - } - - try { - $link->getResource()->saveProductLinks($product, $links, $typeId); - } catch (Exception $e) { - $this->_fault('not_removed'); - } - - return true; - } - - /** - * Retrieve attribute list for specified type - * - * @param string $type - * @return array - */ - public function attributes($type) - { - $typeId = $this->_getTypeId($type); - - $attributes = Mage::getModel('Mage_Catalog_Model_Product_Link') - ->getAttributes($typeId); - - $result = array(); - - foreach ($attributes as $attribute) { - $result[] = array( - 'code' => $attribute['code'], - 'type' => $attribute['type'] - ); - } - - return $result; - } - - /** - * Retrieve link types - * - * @return array - */ - public function types() - { - return array_keys($this->_typeMap); - } - - /** - * Retrieve link type id by code - * - * @param string $type - * @return int - */ - protected function _getTypeId($type) - { - if (!isset($this->_typeMap[$type])) { - $this->_fault('type_not_exists'); - } - - return $this->_typeMap[$type]; - } - - /** - * Initialize and return product model - * - * @param int $productId - * @param string $identifierType - * @return Mage_Catalog_Model_Product - */ - protected function _initProduct($productId, $identifierType = null) - { - $product = Mage::helper('Mage_Catalog_Helper_Product')->getProduct($productId, null, $identifierType); - if (!$product->getId()) { - $this->_fault('product_not_exists'); - } - - return $product; - } - - /** - * Initialize and return linked products collection - * - * @param Mage_Catalog_Model_Product_Link $link - * @param Mage_Catalog_Model_Product $product - * @return Mage_Catalog_Model_Resource_Product_Link_Product_Collection - */ - protected function _initCollection($link, $product) - { - $collection = $link - ->getProductCollection() - ->setIsStrongMode() - ->setProduct($product); - - return $collection; - } - - /** - * Export collection to editable array - * - * @param Mage_Catalog_Model_Resource_Product_Link_Product_Collection $collection - * @return array - */ - protected function _collectionToEditableArray($collection) - { - $result = array(); - - foreach ($collection as $linkedProduct) { - $result[$linkedProduct->getId()] = array(); - - foreach ($collection->getLinkModel()->getAttributes() as $attribute) { - $result[$linkedProduct->getId()][$attribute['code']] = $linkedProduct->getData($attribute['code']); - } - } - - return $result; - } -} // Class Mage_Catalog_Model_Product_Link_Api End diff --git a/app/code/core/Mage/Catalog/Model/Product/Link/Api/V2.php b/app/code/core/Mage/Catalog/Model/Product/Link/Api/V2.php deleted file mode 100644 index 8598891e6ebf04c9bc791cb30dfdc29bc0f844eb..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Catalog/Model/Product/Link/Api/V2.php +++ /dev/null @@ -1,119 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Catalog - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Catalog product link api V2 - * - * @category Mage - * @package Mage_Catalog - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Catalog_Model_Product_Link_Api_V2 extends Mage_Catalog_Model_Product_Link_Api -{ - /** - * Add product link association - * - * @param string $type - * @param int|string $productId - * @param int|string $linkedProductId - * @param array $data - * @return boolean - */ - public function assign($type, $productId, $linkedProductId, $data = array(), $identifierType = null) - { - $typeId = $this->_getTypeId($type); - - $product = $this->_initProduct($productId, $identifierType); - - $link = $product->getLinkInstance() - ->setLinkTypeId($typeId); - - $collection = $this->_initCollection($link, $product); - $idBySku = $product->getIdBySku($linkedProductId); - if ($idBySku) { - $linkedProductId = $idBySku; - } - - $links = $this->_collectionToEditableArray($collection); - - $links[(int)$linkedProductId] = array(); - foreach ($collection->getLinkModel()->getAttributes() as $attribute) { - if (isset($data->$attribute['code'])) { - $links[(int)$linkedProductId][$attribute['code']] = $data->$attribute['code']; - } - } - - try { - $link->getResource()->saveProductLinks($product, $links, $typeId); - } catch (Exception $e) { - $this->_fault('data_invalid', Mage::helper('Mage_Catalog_Helper_Data')->__('Link product does not exist.')); - } - - return true; - } - - /** - * Update product link association info - * - * @param string $type - * @param int|string $productId - * @param int|string $linkedProductId - * @param array $data - * @return boolean - */ - public function update($type, $productId, $linkedProductId, $data = array(), $identifierType = null) - { - $typeId = $this->_getTypeId($type); - - $product = $this->_initProduct($productId, $identifierType); - - $link = $product->getLinkInstance() - ->setLinkTypeId($typeId); - - $collection = $this->_initCollection($link, $product); - - $links = $this->_collectionToEditableArray($collection); - - $idBySku = $product->getIdBySku($linkedProductId); - if ($idBySku) { - $linkedProductId = $idBySku; - } - - foreach ($collection->getLinkModel()->getAttributes() as $attribute) { - if (isset($data->$attribute['code'])) { - $links[(int)$linkedProductId][$attribute['code']] = $data->$attribute['code']; - } - } - - try { - $link->getResource()->saveProductLinks($product, $links, $typeId); - } catch (Exception $e) { - $this->_fault('data_invalid', Mage::helper('Mage_Catalog_Helper_Data')->__('Link product does not exist.')); - } - - return true; - } -} diff --git a/app/code/core/Mage/Catalog/Model/Product/Option/Api.php b/app/code/core/Mage/Catalog/Model/Product/Option/Api.php deleted file mode 100644 index 35034f007f0fb587e8a5ed5caea305fb10a26379..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Catalog/Model/Product/Option/Api.php +++ /dev/null @@ -1,327 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Catalog - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Catalog product options api - * - * @category Mage - * @package Mage_Catalog - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Catalog_Model_Product_Option_Api extends Mage_Catalog_Model_Api_Resource -{ - - /** - * Add custom option to product - * - * @param string $productId - * @param array $data - * @param int|string|null $store - * @return bool $isAdded - */ - public function add($productId, $data, $store = null) - { - $product = $this->_getProduct($productId, $store, null); - if (!(is_array($data['additional_fields']) and count($data['additional_fields']))) { - $this->_fault('invalid_data'); - } - if (!$this->_isTypeAllowed($data['type'])) { - $this->_fault('invalid_type'); - } - $this->_prepareAdditionalFields( - $data, - $product->getOptionInstance()->getGroupByType($data['type']) - ); - $this->_saveProductCustomOption($product, $data); - return true; - } - - /** - * Update product custom option data - * - * @param string $optionId - * @param array $data - * @param int|string|null $store - * @return bool - */ - public function update($optionId, $data, $store = null) - { - /** @var $option Mage_Catalog_Model_Product_Option */ - $option = Mage::getModel('Mage_Catalog_Model_Product_Option')->load($optionId); - if (!$option->getId()) { - $this->_fault('option_not_exists'); - } - $product = $this->_getProduct($option->getProductId(), $store, null); - $option = $product->getOptionById($optionId); - if (isset($data['type']) and !$this->_isTypeAllowed($data['type'])) { - $this->_fault('invalid_type'); - } - if (isset($data['additional_fields'])) { - $this->_prepareAdditionalFields( - $data, - $option->getGroupByType() - ); - } - foreach ($option->getValues() as $valueId => $value) { - if(isset($data['values'][$valueId])) { - $data['values'][$valueId] = array_merge($value->getData(), $data['values'][$valueId]); - } - } - $data = array_merge($option->getData(), $data); - $this->_saveProductCustomOption($product, $data); - return true; - } - - /** - * Prepare custom option data for saving by model. Used for custom option add and update - * - * @param array $data - * @param string $groupType - * @return void - */ - protected function _prepareAdditionalFields(&$data, $groupType) - { - if (is_array($data['additional_fields'])) { - if ($groupType != Mage_Catalog_Model_Product_Option::OPTION_GROUP_SELECT) { - // reset can be used as there should be the only - // element in 'additional_fields' for options of all types except those from Select group - $field = reset($data['additional_fields']); - if (!(is_array($field) and count($field))) { - $this->_fault('invalid_data'); - } else { - foreach ($field as $key => $value) { - $data[$key] = $value; - } - } - } else { - // convert Select rows array to appropriate format for saving in the model - foreach ($data['additional_fields'] as $row) { - if (!(is_array($row) and count($row))) { - $this->_fault('invalid_data'); - } else { - foreach ($row as $key => $value) { - $row[$key] = Mage::helper('Mage_Catalog_Helper_Data')->stripTags($value); - } - if (!empty($row['value_id'])) { - // map 'value_id' to 'option_type_id' - $row['option_type_id'] = $row['value_id']; - unset($row['value_id']); - $data['values'][$row['option_type_id']] = $row; - } else { - $data['values'][] = $row; - } - } - } - } - } - unset($data['additional_fields']); - } - - /** - * Save product custom option data. Used for custom option add and update. - * - * @param Mage_Catalog_Model_Product $product - * @param array $data - * @return void - */ - protected function _saveProductCustomOption($product, $data) - { - foreach ($data as $key => $value) { - if (is_string($value)) { - $data[$key] = Mage::helper('Mage_Catalog_Helper_Data')->stripTags($value); - } - } - // setProductOptions expects data to be an array of options arrays - $data = array($data); - if (!$product->getOptionsReadonly()) { - $product->setProductOptions($data); - } - $product->setCanSaveCustomOptions(!$product->getOptionsReadonly()); - try { - // an empty request can be set as event parameter - // because it is not used for options changing in observers - Mage::dispatchEvent( - 'catalog_product_prepare_save', - array('product' => $product, 'request' => new Mage_Core_Controller_Request_Http()) - ); - $product->save(); - } catch (Exception $e) { - $this->_fault('save_option_error', $e->getMessage()); - } - } - - /** - * Read list of possible custom option types from module config - * - * @return array - */ - public function types() - { - $path = Mage_Catalog_Model_Config_Source_Product_Options_Type::PRODUCT_OPTIONS_GROUPS_PATH; - $types = array(); - foreach (Mage::getConfig()->getNode($path)->children() as $group) { - $groupTypes = Mage::getConfig()->getNode($path . '/' . $group->getName() . '/types')->children(); - /** @var $type Mage_Core_Model_Config_Element */ - foreach($groupTypes as $type){ - $labelPath = $path . '/' . $group->getName() . '/types/' . $type->getName() . '/label'; - $types[] = array( - 'label' => (string) Mage::getConfig()->getNode($labelPath), - 'value' => $type->getName() - ); - } - } - return $types; - } - - /** - * Get full information about custom option in product - * - * @param int|string $optionId - * @param int|string|null $store - * @return array - */ - public function info($optionId, $store = null) - { - /** @var $option Mage_Catalog_Model_Product_Option */ - $option = Mage::getModel('Mage_Catalog_Model_Product_Option')->load($optionId); - if (!$option->getId()) { - $this->_fault('option_not_exists'); - } - /** @var $product Mage_Catalog_Model_Product */ - $product = $this->_getProduct($option->getProductId(), $store, null); - $option = $product->getOptionById($optionId); - $result = array( - 'title' => $option->getTitle(), - 'type' => $option->getType(), - 'is_require' => $option->getIsRequire(), - 'sort_order' => $option->getSortOrder(), - // additional_fields should be two-dimensional array for all option types - 'additional_fields' => array( - array( - 'price' => $option->getPrice(), - 'price_type' => $option->getPriceType(), - 'sku' => $option->getSku() - ) - ) - ); - // Set additional fields to each type group - switch ($option->getGroupByType()) { - case Mage_Catalog_Model_Product_Option::OPTION_GROUP_TEXT: - $result['additional_fields'][0]['max_characters'] = $option->getMaxCharacters(); - break; - case Mage_Catalog_Model_Product_Option::OPTION_GROUP_FILE: - $result['additional_fields'][0]['file_extension'] = $option->getFileExtension(); - $result['additional_fields'][0]['image_size_x'] = $option->getImageSizeX(); - $result['additional_fields'][0]['image_size_y'] = $option->getImageSizeY(); - break; - case Mage_Catalog_Model_Product_Option::OPTION_GROUP_SELECT: - $result['additional_fields'] = array(); - foreach ($option->getValuesCollection() as $value) { - $result['additional_fields'][] = array( - 'value_id' => $value->getId(), - 'title' => $value->getTitle(), - 'price' => $value->getPrice(), - 'price_type' => $value->getPriceType(), - 'sku' => $value->getSku(), - 'sort_order' => $value->getSortOrder() - ); - } - break; - default: - break; - } - - return $result; - } - - /** - * Retrieve list of product custom options - * - * @param string $productId - * @param int|string|null $store - * @return array - */ - public function items($productId, $store = null) - { - $result = array(); - $product = $this->_getProduct($productId, $store, null); - /** @var $option Mage_Catalog_Model_Product_Option */ - foreach ($product->getProductOptionsCollection() as $option) { - $result[] = array( - 'option_id' => $option->getId(), - 'title' => $option->getTitle(), - 'type' => $option->getType(), - 'is_require' => $option->getIsRequire(), - 'sort_order' => $option->getSortOrder() - ); - } - return $result; - } - - /** - * Remove product custom option - * - * @param string $optionId - * @return boolean - */ - public function remove($optionId) - { - /** @var $option Mage_Catalog_Model_Product_Option */ - $option = Mage::getModel('Mage_Catalog_Model_Product_Option')->load($optionId); - if (!$option->getId()) { - $this->_fault('option_not_exists'); - } - try { - $option->getValueInstance()->deleteValue($optionId); - $option->deletePrices($optionId); - $option->deleteTitles($optionId); - $option->delete(); - } catch (Exception $e){ - $this->fault('delete_option_error'); - } - return true; - } - - /** - * Check is type in allowed set - * - * @param string $type - * @return bool - */ - protected function _isTypeAllowed($type) - { - $allowedTypes = array(); - foreach($this->types() as $optionType){ - $allowedTypes[] = $optionType['value']; - } - - if (!in_array($type, $allowedTypes)) { - return false; - } - return true; - } - -} diff --git a/app/code/core/Mage/Catalog/Model/Product/Option/Api/V2.php b/app/code/core/Mage/Catalog/Model/Product/Option/Api/V2.php deleted file mode 100644 index 602da8840bb20a924e56614ed17c9b570791ba95..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Catalog/Model/Product/Option/Api/V2.php +++ /dev/null @@ -1,81 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Catalog - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Catalog product options api - * - * @category Mage - * @package Mage_Catalog - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Catalog_Model_Product_Option_Api_V2 extends Mage_Catalog_Model_Product_Option_Api -{ - - /** - * Add custom option to product - * - * @param string $productId - * @param array $data - * @param int|string|null $store - * @return bool - */ - public function add($productId, $data, $store = null) - { - Mage::helper('Mage_Api_Helper_Data')->toArray($data); - return parent::add($productId, $data, $store); - } - - /** - * Update product custom option data - * - * @param string $optionId - * @param array $data - * @param int|string|null $store - * @return bool - */ - public function update($optionId, $data, $store = null) - { - Mage::helper('Mage_Api_Helper_Data')->toArray($data); - return parent::update($optionId, $data, $store); - } - - /** - * Retrieve list of product custom options - * - * @param string $productId - * @param int|string|null $store - * @return array - */ - public function items($productId, $store = null) - { - $result = parent::items($productId, $store); - foreach ($result as $key => $option) { - $result[$key] = Mage::helper('Mage_Api_Helper_Data')->wsiArrayPacker($option); - } - return $result; - } - -} diff --git a/app/code/core/Mage/Catalog/Model/Product/Option/Value/Api.php b/app/code/core/Mage/Catalog/Model/Product/Option/Value/Api.php deleted file mode 100644 index 71b4b3bfe32267059399fa8bc09b98818d921c3c..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Catalog/Model/Product/Option/Value/Api.php +++ /dev/null @@ -1,226 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Catalog - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Catalog product option values api - * - * @category Mage - * @package Mage_Catalog - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Catalog_Model_Product_Option_Value_Api extends Mage_Catalog_Model_Api_Resource -{ - /** - * Retrieve values from specified option - * - * @param string $optionId - * @param int|string|null $store - * @return array - */ - public function items($optionId, $store = null) - { - /** @var $option Mage_Catalog_Model_Product_Option */ - $option = $this->_prepareOption($optionId, $store); - $productOptionValues = $option->getValuesCollection(); - $result = array(); - foreach($productOptionValues as $value){ - $result[] = array( - 'value_id' => $value->getId(), - 'title' => $value->getTitle(), - 'price' => $value->getPrice(), - 'price_type' => $value->getPriceType(), - 'sku' => $value->getSku(), - 'sort_order' => $value->getSortOrder() - ); - } - return $result; - } - - /** - * Retrieve specified option value info - * - * @param string $valueId - * @param int|string|null $store - * @return array - */ - public function info($valueId, $store = null) - { - /** @var $productOptionValue Mage_Catalog_Model_Product_Option_Value */ - $productOptionValue = Mage::getModel('Mage_Catalog_Model_Product_Option_Value')->load($valueId); - if (!$productOptionValue->getId()) { - $this->_fault('value_not_exists'); - } - $storeId = $this->_getStoreId($store); - $productOptionValues = $productOptionValue - ->getValuesByOption( - array($valueId), - $productOptionValue->getOptionId(), - $storeId - ) - ->addTitleToResult($storeId) - ->addPriceToResult($storeId); - - $result = $productOptionValues->toArray(); - // reset can be used as the only item is expected - $result = reset($result['items']); - if (empty($result)) { - $this->_fault('value_not_exists'); - } - // map option_type_id to value_id - $result['value_id'] = $result['option_type_id']; - unset($result['option_type_id']); - return $result; - } - - /** - * Add new values to select option - * - * @param string $optionId - * @param array $data - * @param int|string|null $store - * @return bool - */ - public function add($optionId, $data, $store = null) - { - /** @var $option Mage_Catalog_Model_Product_Option */ - $option = $this->_prepareOption($optionId, $store); - /** @var $optionValueModel Mage_Catalog_Model_Product_Option_Value */ - $optionValueModel = Mage::getModel('Mage_Catalog_Model_Product_Option_Value'); - $optionValueModel->setOption($option); - foreach ($data as &$optionValue) { - foreach ($optionValue as &$value) { - $value = Mage::helper('Mage_Catalog_Helper_Data')->stripTags($value); - } - } - $optionValueModel->setValues($data); - try { - $optionValueModel->saveValues(); - } catch (Exception $e) { - $this->_fault('add_option_value_error', $e->getMessage()); - } - return true; - } - - /** - * Update value to select option - * - * @param string $valueId - * @param array $data - * @param int|string|null $store - * @return bool - */ - public function update($valueId, $data, $store = null) - { - /** @var $productOptionValue Mage_Catalog_Model_Product_Option_Value */ - $productOptionValue = Mage::getModel('Mage_Catalog_Model_Product_Option_Value')->load($valueId); - if (!$productOptionValue->getId()) { - $this->_fault('value_not_exists'); - } - - /** @var $option Mage_Catalog_Model_Product_Option */ - $option = $this->_prepareOption($productOptionValue->getOptionId(), $store); - if (!$option->getId()) { - $this->_fault('option_not_exists'); - } - $productOptionValue->setOption($option); - // Sanitize data - foreach ($data as $key => $value) { - $data[$key] = Mage::helper('Mage_Catalog_Helper_Data')->stripTags($value); - } - if (!isset($data['title']) OR empty($data['title'])) { - $this->_fault('option_value_title_required'); - } - $data['option_type_id'] = $valueId; - $data['store_id'] = $this->_getStoreId($store); - $productOptionValue->addValue($data); - $productOptionValue->setData($data); - - try { - $productOptionValue->save()->saveValues(); - } catch (Exception $e) { - $this->_fault('update_option_value_error', $e->getMessage()); - } - - return true; - } - - /** - * Delete value from select option - * - * @param int $valueId - * @return boolean - */ - public function remove($valueId) - { - /** @var $optionValue Mage_Catalog_Model_Product_Option_Value */ - $optionValue = Mage::getModel('Mage_Catalog_Model_Product_Option_Value')->load($valueId); - if (!$optionValue->getId()) { - $this->_fault('value_not_exists'); - } - - // check values count - if(count($this->items($optionValue->getOptionId())) <= 1){ - $this->_fault('cant_delete_last_value'); - } - - try { - $optionValue->delete(); - } catch (Mage_Core_Exception $e) { - $this->_fault('not_deleted', $e->getMessage()); - } - - return true; - } - - /** - * Load option by id and store - * - * @param string $optionId - * @param int|string|null $store - * @return Mage_Catalog_Model_Product_Option - */ - protected function _prepareOption($optionId, $store = null) - { - /** @var $option Mage_Catalog_Model_Product_Option */ - $option = Mage::getModel('Mage_Catalog_Model_Product_Option'); - if (is_string($store) || is_integer($store)) { - $storeId = $this->_getStoreId($store); - $option->setStoreId($storeId); - } - $option->load($optionId); - if (isset($storeId)) { - $option->setData('store_id', $storeId); - } - if (!$option->getId()) { - $this->_fault('option_not_exists'); - } - if ($option->getGroupByType() != Mage_Catalog_Model_Product_Option::OPTION_GROUP_SELECT) { - $this->_fault('invalid_option_type'); - } - return $option; - } - -} diff --git a/app/code/core/Mage/Catalog/Model/Product/Option/Value/Api/V2.php b/app/code/core/Mage/Catalog/Model/Product/Option/Value/Api/V2.php deleted file mode 100644 index cc7a5dac9bcbc1328d19b66923489943f0c4c611..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Catalog/Model/Product/Option/Value/Api/V2.php +++ /dev/null @@ -1,104 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Catalog - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Catalog product option values api - * - * @category Mage - * @package Mage_Catalog - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Catalog_Model_Product_Option_Value_Api_V2 extends Mage_Catalog_Model_Product_Option_Value_Api -{ - /** - * Retrieve values from specified option - * - * @param string $optionId - * @param int|string|null $store - * @return array - */ - public function items($optionId, $store = null) - { - $result = parent::items($optionId, $store); - foreach ($result as $key => $optionValue) { - $result[$key] = Mage::helper('Mage_Api_Helper_Data')->wsiArrayPacker($optionValue); - } - return $result; - } - - /** - * Retrieve specified option value info - * - * @param string $valueId - * @param int|string|null $store - * @return array - */ - public function info($valueId, $store = null) - { - return Mage::helper('Mage_Api_Helper_Data')->wsiArrayPacker( - parent::info($valueId, $store) - ); - } - - /** - * Add new values to select option - * - * @param string $optionId - * @param array $data - * @param int|string|null $store - * @return bool - */ - public function add($optionId, $data, $store = null) - { - Mage::helper('Mage_Api_Helper_Data')->toArray($data); - return parent::add($optionId, $data, $store); - } - - /** - * Update value to select option - * - * @param string $valueId - * @param array $data - * @param int|string|null $store - * @return bool - */ - public function update($valueId, $data, $store = null) - { - Mage::helper('Mage_Api_Helper_Data')->toArray($data); - return parent::update($valueId, $data, $store); - } - - /** - * Delete value from select option - * - * @param int $valueId - * @return boolean - */ - public function remove($valueId) - { - return parent::remove($valueId); - } -} diff --git a/app/code/core/Mage/Catalog/Model/Product/Type/Api/V2.php b/app/code/core/Mage/Catalog/Model/Product/Type/Api/V2.php deleted file mode 100644 index 8856916a0396dbeb04250ab72f30f00a65605642..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Catalog/Model/Product/Type/Api/V2.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Catalog - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Catalog product type api V2 - * - * @category Mage - * @package Mage_Catalog - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Catalog_Model_Product_Type_Api_V2 extends Mage_Catalog_Model_Product_Type_Api -{ -} diff --git a/app/code/core/Mage/Catalog/etc/api.xml b/app/code/core/Mage/Catalog/etc/api.xml deleted file mode 100644 index 9e1d971ae8b1c1b04e9b3a134e455c5e7863dfed..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Catalog/etc/api.xml +++ /dev/null @@ -1,518 +0,0 @@ -<?xml version="1.0"?> -<!-- -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Academic Free License (AFL 3.0) - * that is bundled with this package in the file LICENSE_AFL.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/afl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Catalog - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) - */ ---> -<config> - <api> - <resources> - <catalog_category translate="title" module="Mage_Catalog"> - <model>Mage_Catalog_Model_Category_Api</model> - <title>Category API</title> - <acl>catalog/category</acl> - <methods> - <currentStore> - <title>Set/Get current store view</title> - </currentStore> - <tree translate="title" module="Mage_Catalog"> - <title>Retrieve hierarchical tree</title> - <acl>catalog/category/tree</acl> - </tree> - <level translate="title" module="Mage_Catalog"> - <title>Retrieve one level of categories by website/store view/parent category</title> - </level> - <info translate="title" module="Mage_Catalog"> - <title>Retrieve category data</title> - <acl>catalog/category/info</acl> - </info> - <create translate="title" module="Mage_Catalog"> - <title>Create new category</title> - <acl>catalog/category/create</acl> - </create> - <update translate="title" module="Mage_Catalog"> - <title>Update category</title> - <acl>catalog/category/update</acl> - </update> - <move translate="title" module="Mage_Catalog"> - <title>Move category in tree</title> - <acl>catalog/category/move</acl> - </move> - <delete translate="title" module="Mage_Catalog"> - <title>Delete category</title> - <acl>catalog/category/delete</acl> - </delete> - <assignedProducts translate="title" module="Mage_Catalog"> - <title>Retrieve list of assigned products</title> - <acl>catalog/category/product</acl> - </assignedProducts> - <assignProduct translate="title" module="Mage_Catalog"> - <title>Assign product to category</title> - <acl>catalog/category/product/assign</acl> - </assignProduct> - <updateProduct translate="title" module="Mage_Catalog"> - <title>Update assigned product</title> - <acl>catalog/category/product/update</acl> - </updateProduct> - <removeProduct translate="title" module="Mage_Catalog"> - <title>Remove product assignment</title> - <acl>catalog/category/product/remove</acl> - </removeProduct> - </methods> - <faults module="Mage_Catalog"> - <store_not_exists> - <code>100</code> - <message>Requested store view not found.</message> - </store_not_exists> - <website_not_exists> - <code>101</code> - <message>Requested website not found.</message> - </website_not_exists> - <not_exists> - <code>102</code> - <message>Category not exists.</message> - </not_exists> - <data_invalid> - <code>103</code> - <message>Invalid data given. Details in error message.</message> - </data_invalid> - <not_moved> - <code>104</code> - <message>Category not moved. Details in error message.</message> - </not_moved> - <not_deleted> - <code>105</code> - <message>Category not deleted. Details in error message.</message> - </not_deleted> - <product_not_assigned> - <code>106</code> - <message>Requested product is not assigned to category.</message> - </product_not_assigned> - </faults> - </catalog_category> - <catalog_category_attribute translate="title" module="Mage_Catalog"> - <title>Category attributes API</title> - <model>Mage_Catalog_Model_Category_Attribute_Api</model> - <acl>catalog/category</acl> - <methods> - <currentStore translate="title" module="Mage_Catalog"> - <title>Set/Get current store view</title> - </currentStore> - <list translate="title" module="Mage_Catalog"> - <title>Retrieve category attributes</title> - <method>items</method> - </list> - <options translate="title" module="Mage_Catalog"> - <title>Retrieve attribute options</title> - </options> - </methods> - <faults module="Mage_Catalog"> - <store_not_exists> - <code>100</code> - <message>Requested store view not found.</message> - </store_not_exists> - <not_exists> - <code>101</code> - <message>Requested attribute not found.</message> - </not_exists> - </faults> - </catalog_category_attribute> - <catalog_product translate="title" module="Mage_Catalog"> - <title>Product API</title> - <model>Mage_Catalog_Model_Product_Api</model> - <acl>catalog/product</acl> - <methods> - <currentStore translate="title" module="Mage_Catalog"> - <title>Set/Get current store view</title> - </currentStore> - <list translate="title" module="Mage_Catalog"> - <title>Retrieve products list by filters</title> - <method>items</method> - <acl>catalog/product/info</acl> - </list> - <info translate="title" module="Mage_Catalog"> - <title>Retrieve product</title> - <acl>catalog/product/info</acl> - </info> - <create translate="title" module="Mage_Catalog"> - <title>Create new product</title> - <acl>catalog/product/create</acl> - </create> - <update translate="title" module="Mage_Catalog"> - <title>Update product</title> - <acl>catalog/product/update</acl> - </update> - <delete translate="title" module="Mage_Catalog"> - <title>Delete product</title> - <acl>catalog/product/delete</acl> - </delete> - <getSpecialPrice translate="title" module="Mage_Catalog"> - <title>Get special price</title> - </getSpecialPrice> - <setSpecialPrice translate="title" module="Mage_Catalog"> - <title>Set special price</title> - <acl>catalog/product/update</acl> - </setSpecialPrice> - </methods> - <faults module="Mage_Catalog"> - <store_not_exists> - <code>100</code> - <message>Requested store view not found.</message> - </store_not_exists> - <not_exists> - <code>101</code> - <message>Product not exists.</message> - </not_exists> - <data_invalid> - <code>102</code> - <message>Invalid data given. Details in error message.</message> - </data_invalid> - <not_deleted> - <code>103</code> - <message>Product not deleted. Details in error message.</message> - </not_deleted> - </faults> - </catalog_product> - <catalog_product_attribute translate="title" module="Mage_Catalog"> - <title>Product attributes API</title> - <model>Mage_Catalog_Model_Product_Attribute_Api</model> - <acl>catalog/product</acl> - <methods> - <currentStore translate="title" module="Mage_Catalog"> - <title>Set/Get current store view</title> - <acl>catalog/product/attribute/write</acl> - </currentStore> - <list translate="title" module="Mage_Catalog"> - <title>Retrieve attribute list</title> - <method>items</method> - <acl>catalog/product/attribute/read</acl> - </list> - <options translate="title" module="Mage_Catalog"> - <title>Retrieve attribute options</title> - <acl>catalog/product/attribute/read</acl> - </options> - </methods> - <faults module="Mage_Catalog"> - <store_not_exists> - <code>100</code> - <message>Requested store view not found.</message> - </store_not_exists> - <not_exists> - <code>101</code> - <message>Requested attribute not found.</message> - </not_exists> - </faults> - </catalog_product_attribute> - <catalog_product_attribute_set translate="title" module="Mage_Catalog"> - <title>Product attribute sets API</title> - <model>Mage_Catalog_Model_Product_Attribute_Set_Api</model> - <acl>catalog/product</acl> - <methods> - <list translate="title" module="Mage_Catalog"> - <title>Retrieve product attribute sets</title> - <method>items</method> - </list> - </methods> - <faults module="Mage_Catalog"> - </faults> - </catalog_product_attribute_set> - <catalog_product_type translate="title" module="Mage_Catalog"> - <title>Product types API</title> - <model>Mage_Catalog_Model_Product_Type_Api</model> - <acl>catalog/product</acl> - <methods> - <list translate="title" module="Mage_Catalog"> - <title>Retrieve product types</title> - <method>items</method> - </list> - </methods> - <faults module="Mage_Catalog"> - </faults> - </catalog_product_type> - <catalog_product_attribute_media translate="title" module="Mage_Catalog"> - <title>Product Images API</title> - <model>Mage_Catalog_Model_Product_Attribute_Media_Api</model> - <acl>catalog/product/media</acl> - <methods> - <currentStore translate="title" module="Mage_Catalog"> - <title>Set/Get current store view</title> - </currentStore> - <list translate="title" module="Mage_Catalog"> - <title>Retrieve product image list</title> - <method>items</method> - </list> - <info translate="title" module="Mage_Catalog"> - <title>Retrieve product image</title> - </info> - <types translate="title" module="Mage_Catalog"> - <title>Retrieve product image types</title> - </types> - <create translate="title" module="Mage_Catalog"> - <title>Upload new product image </title> - <acl>catalog/product/media/create</acl> - </create> - <update translate="title" module="Mage_Catalog"> - <title>Update product image</title> - <acl>catalog/product/media/update</acl> - </update> - <remove translate="title" module="Mage_Catalog"> - <title>Remove product image</title> - <acl>catalog/product/media/remove</acl> - </remove> - </methods> - <faults module="Mage_Catalog"> - <store_not_exists> - <code>100</code> - <message>Requested store view not found.</message> - </store_not_exists> - <product_not_exists> - <code>101</code> - <message>Product not exists.</message> - </product_not_exists> - <data_invalid> - <code>102</code> - <message>Invalid data given. Details in error message.</message> - </data_invalid> - <not_exists> - <code>103</code> - <message>Requested image not exists in product images' gallery.</message> - </not_exists> - <not_created> - <code>104</code> - <message>Image creation failed. Details in error message.</message> - </not_created> - <not_updated> - <code>105</code> - <message>Image not updated. Details in error message.</message> - </not_updated> - <not_removed> - <code>106</code> - <message>Image not removed. Details in error message.</message> - </not_removed> - <not_media> - <code>107</code> - <message>Requested product doesn't support images</message> - </not_media> - </faults> - </catalog_product_attribute_media> - <catalog_product_attribute_tier_price translate="title" module="Mage_Catalog"> - <title>Product Tier Price API</title> - <model>Mage_Catalog_Model_Product_Attribute_Tierprice_Api</model> - <acl>catalog/product</acl> - <methods> - <info translate="title" module="Mage_Catalog"> - <title>Retrieve product tier prices</title> - </info> - <update translate="title" module="Mage_Catalog"> - <title>Update product tier prices</title> - <acl>catalog/product/update_tier_price</acl> - </update> - </methods> - <faults module="Mage_Catalog"> - <product_not_exists> - <code>100</code> - <message>Product not exists.</message> - </product_not_exists> - <data_invalid> - <code>101</code> - <message>Invalid data given. Details in error message.</message> - </data_invalid> - <not_updated> - <code>102</code> - <message>Tier prices not updated. Details in error message.</message> - </not_updated> - </faults> - </catalog_product_attribute_tier_price> - <catalog_product_link translate="title" module="Mage_Catalog"> - <title>Product links API (related, cross sells, up sells)</title> - <model>Mage_Catalog_Model_Product_Link_Api</model> - <acl>catalog/product/link</acl> - <methods> - <list translate="title" module="Mage_Catalog"> - <title>Retrieve linked products</title> - <method>items</method> - </list> - <assign translate="title" module="Mage_Catalog"> - <title>Assign product link</title> - <acl>catalog/product/link/assign</acl> - </assign> - <update translate="title" module="Mage_Catalog"> - <title>Update product link</title> - <acl>catalog/product/link/update</acl> - </update> - <remove translate="title" module="Mage_Catalog"> - <title>Remove product link</title> - <acl>catalog/product/link/remove</acl> - </remove> - <types translate="title" module="Mage_Catalog"> - <title>Retrieve product link types</title> - </types> - <attributes translate="title" module="Mage_Catalog"> - <title>Retrieve product link type attributes</title> - </attributes> - </methods> - <faults module="Mage_Catalog"> - <type_not_exists> - <code>100</code> - <message>Given invalid link type.</message> - </type_not_exists> - <product_not_exists> - <code>101</code> - <message>Product not exists.</message> - </product_not_exists> - <data_invalid> - <code>102</code> - <message>Invalid data given. Details in error message.</message> - </data_invalid> - <not_removed> - <code>104</code> - <message>Product link not removed.</message> - </not_removed> - </faults> - </catalog_product_link> - </resources> - <resources_alias> - <category>catalog_category</category> - <category_attribute>catalog_category_attribute</category_attribute> - <product>catalog_product</product> - <product_attribute>catalog_product_attribute</product_attribute> - <product_attribute_set>catalog_product_attribute_set</product_attribute_set> - <product_type>catalog_product_type</product_type> - <product_link>catalog_product_link</product_link> - <product_attribute_media>catalog_product_attribute_media</product_attribute_media> - <product_media>catalog_product_attribute_media</product_media> - <product_attribute_tier_price>catalog_product_attribute_tier_price</product_attribute_tier_price> - <product_tier_price>catalog_product_attribute_tier_price</product_tier_price> - </resources_alias> - <v2> - <resources_function_prefix> - <category>catalogCategory</category> - <category_attribute>catalogCategoryAttribute</category_attribute> - <product>catalogProduct</product> - <product_attribute>catalogProductAttribute</product_attribute> - <product_attribute_set>catalogProductAttributeSet</product_attribute_set> - <product_type>catalogProductType</product_type> - <product_tier_price>catalogProductAttributeTierPrice</product_tier_price> - <product_attribute_media>catalogProductAttributeMedia</product_attribute_media> - <product_link>catalogProductLink</product_link> - </resources_function_prefix> - </v2> - <acl> - <resources> - <catalog translate="title" module="Mage_Catalog"> - <title>Catalog</title> - <sort_order>1</sort_order> - <category translate="title" module="Mage_Catalog"> - <title>Category</title> - <create translate="title" module="Mage_Catalog"> - <title>Create</title> - </create> - <update translate="title" module="Mage_Catalog"> - <title>Update</title> - </update> - <move translate="title" module="Mage_Catalog"> - <title>Move</title> - </move> - <delete translate="title" module="Mage_Catalog"> - <title>Delete</title> - </delete> - <tree translate="title" module="Mage_Catalog"> - <title>Retrieve categories tree</title> - </tree> - <info translate="title" module="Mage_Catalog"> - <title>Retrieve category data</title> - </info> - <product translate="title" module="Mage_Catalog"> - <title>Assigned Products</title> - <sort_order>100</sort_order> - <assign translate="title" module="Mage_Catalog"> - <title>Assign</title> - </assign> - <update translate="title" module="Mage_Catalog"> - <title>Update</title> - </update> - <remove translate="title" module="Mage_Catalog"> - <title>Remove</title> - </remove> - </product> - </category> - <product translate="title" module="Mage_Catalog"> - <title>Product</title> - <create translate="title" module="Mage_Catalog"> - <title>Create</title> - </create> - <update translate="title" module="Mage_Catalog"> - <title>Update</title> - </update> - <delete translate="title" module="Mage_Catalog"> - <title>Delete</title> - </delete> - <update_tier_price translate="title" module="Mage_Catalog"> - <title>Update Tier Price</title> - </update_tier_price> - <info translate="title" module="Mage_Catalog"> - <title>Retrieve products data</title> - </info> - <attribute translate="title" module="Mage_Catalog"> - <title>Product Attributes</title> - <sort_order>100</sort_order> - <read translate="title" module="Mage_Catalog"> - <title>Retrieve attribute data</title> - </read> - <write translate="title" module="Mage_Catalog"> - <title>Change or Retrieve attribute store view</title> - </write> - </attribute> - <link translate="title" module="Mage_Catalog"> - <title>Link (Related, Up sell, Cross sell)</title> - <sort_order>101</sort_order> - <assign translate="title" module="Mage_Catalog"> - <title>Assign</title> - </assign> - <update translate="title" module="Mage_Catalog"> - <title>Update</title> - </update> - <remove translate="title" module="Mage_Catalog"> - <title>Remove</title> - </remove> - </link> - <media translate="title" module="Mage_Catalog"> - <title>Product Images</title> - <sort_order>102</sort_order> - <create translate="title" module="Mage_Catalog"> - <title>Create (Upload)</title> - </create> - <update translate="title" module="Mage_Catalog"> - <title>Update</title> - </update> - <remove translate="title" module="Mage_Catalog"> - <title>Remove</title> - </remove> - </media> - </product> - </catalog> - </resources> - </acl> - </api> -</config> diff --git a/app/code/core/Mage/Catalog/etc/api2.xml b/app/code/core/Mage/Catalog/etc/api2.xml deleted file mode 100644 index 22fffeee6f9e775480c892b0ad9a8bbcc90a9970..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Catalog/etc/api2.xml +++ /dev/null @@ -1,370 +0,0 @@ -<?xml version="1.0"?> -<!-- -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Academic Free License (AFL 3.0) - * that is bundled with this package in the file LICENSE_AFL.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/afl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Catalog - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) - */ ---> -<config> - <api2> - <resource_groups> - <catalog translate="title" module="Mage_Api2"> - <title>Catalog</title> - <sort_order>30</sort_order> - <children> - <catalog_product translate="title" module="Mage_Api2"> - <title>Product</title> - <sort_order>50</sort_order> - </catalog_product> - </children> - </catalog> - </resource_groups> - <resources> - <product translate="title" module="Mage_Api2"> - <group>catalog_product</group> - <model>Mage_Catalog_Model_Api2_Product</model> - <working_model>Mage_Catalog_Model_Product</working_model> - <title>Catalog Product</title> - <sort_order>10</sort_order> - <privileges> - <admin> - <create>1</create> - <retrieve>1</retrieve> - <update>1</update> - <delete>1</delete> - </admin> - <customer> - <retrieve>1</retrieve> - </customer> - <guest> - <retrieve>1</retrieve> - </guest> - </privileges> - <attributes translate="entity_id type_id attribute_set_id stock_data image_url is_saleable total_reviews_count url buy_now_url has_custom_options is_in_stock regular_price_with_tax regular_price_without_tax final_price_with_tax final_price_without_tax use_config_gift_message_available use_config_gift_wrapping_available url_key_create_redirect" module="Mage_Api2"> - <entity_id>Product ID</entity_id> - <type_id>Product Type</type_id> - <attribute_set_id>Attribute Set</attribute_set_id> - <stock_data>Inventory Data</stock_data> - <image_url>Default Image</image_url> - <is_saleable>Salability Status</is_saleable> - <total_reviews_count>Total Reviews Count</total_reviews_count> - <url>Product URL</url> - <buy_now_url>Buy Now URL</buy_now_url> - <has_custom_options>Has Custom Options</has_custom_options> - <is_in_stock>Stock Status</is_in_stock> - <regular_price_with_tax>Regular Price With Tax</regular_price_with_tax> - <regular_price_without_tax>Regular Price Without Tax</regular_price_without_tax> - <final_price_with_tax>Final Price With Tax</final_price_with_tax> - <final_price_without_tax>Final Price Without Tax</final_price_without_tax> - <use_config_gift_message_available>Use Config Settings for Allow Gift Message</use_config_gift_message_available> - <use_config_gift_wrapping_available>Use Config Settings for Allow Gift Wrapping</use_config_gift_wrapping_available> - <url_key_create_redirect>Create Permanent Redirect for old URL</url_key_create_redirect> - </attributes> - <entity_only_attributes> - <customer> - <read> - <has_custom_options>1</has_custom_options> - <tier_price>1</tier_price> - <total_reviews_count>1</total_reviews_count> - <url>1</url> - <buy_now_url>1</buy_now_url> - <has_custom_options>1</has_custom_options> - <is_in_stock>1</is_in_stock> - </read> - </customer> - <guest> - <read> - <has_custom_options>1</has_custom_options> - <tier_price>1</tier_price> - <total_reviews_count>1</total_reviews_count> - <url>1</url> - <buy_now_url>1</buy_now_url> - <has_custom_options>1</has_custom_options> - <is_in_stock>1</is_in_stock> - </read> - </guest> - </entity_only_attributes> - <exclude_attributes> - <customer> - <read> - <attribute_set_id>1</attribute_set_id> - <stock_data>1/</stock_data> - <use_config_gift_message_available>1</use_config_gift_message_available> - <use_config_gift_wrapping_available>1</use_config_gift_wrapping_available> - <url_key_create_redirect>1</url_key_create_redirect> - </read> - </customer> - <guest> - <read> - <attribute_set_id>1</attribute_set_id> - <stock_data>1</stock_data> - <use_config_gift_message_available>1</use_config_gift_message_available> - <use_config_gift_wrapping_available>1</use_config_gift_wrapping_available> - <url_key_create_redirect>1</url_key_create_redirect> - </read> - </guest> - <admin> - <read> - <allow_open_amount>1</allow_open_amount> - <giftcard_amounts>1</giftcard_amounts> - <open_amount_min>1</open_amount_min> - <open_amount_max>1</open_amount_max> - <image>1</image> - <is_recurring>1</is_recurring> - <gallery>1</gallery> - <media_gallery>1</media_gallery> - <price_view>1</price_view> - <small_image>1</small_image> - <image_url>1</image_url> - <is_saleable>1</is_saleable> - <total_reviews_count>1</total_reviews_count> - <url>1</url> - <buy_now_url>1</buy_now_url> - <has_custom_options>1</has_custom_options> - <is_in_stock>1</is_in_stock> - <regular_price_with_tax>1</regular_price_with_tax> - <regular_price_without_tax>1</regular_price_without_tax> - <final_price_with_tax>1</final_price_with_tax> - <final_price_without_tax>1</final_price_without_tax> - <recurring_profile>1</recurring_profile> - <thumbnail>1</thumbnail> - <url_key_create_redirect>1</url_key_create_redirect> - </read> - <write> - <allow_open_amount>1</allow_open_amount> - <giftcard_amounts>1</giftcard_amounts> - <open_amount_min>1</open_amount_min> - <open_amount_max>1</open_amount_max> - <image>1</image> - <is_recurring>1</is_recurring> - <gallery>1</gallery> - <media_gallery>1</media_gallery> - <price_view>1</price_view> - <small_image>1</small_image> - <image_url>1</image_url> - <is_saleable>1</is_saleable> - <total_reviews_count>1</total_reviews_count> - <url>1</url> - <buy_now_url>1</buy_now_url> - <has_custom_options>1</has_custom_options> - <is_in_stock>1</is_in_stock> - <regular_price_with_tax>1</regular_price_with_tax> - <regular_price_without_tax>1</regular_price_without_tax> - <final_price_with_tax>1</final_price_with_tax> - <final_price_without_tax>1</final_price_without_tax> - <recurring_profile>1</recurring_profile> - <thumbnail>1</thumbnail> - <entity_id>1</entity_id> - </write> - </admin> - </exclude_attributes> - <routes> - <route_entity> - <route>/products/:id</route> - <action_type>entity</action_type> - </route_entity> - <route_entity_with_store> - <route>/products/:id/store/:store</route> - <action_type>entity</action_type> - </route_entity_with_store> - <route_collection> - <route>/products</route> - <action_type>collection</action_type> - </route_collection> - <route_collection_with_store> - <route>/products/store/:store</route> - <action_type>collection</action_type> - </route_collection_with_store> - <route_collection_with_category> - <route>/products/category/:category_id</route> - <action_type>collection</action_type> - </route_collection_with_category> - <route_collection_with_store_and_category> - <route>/products/store/:store/category/:category_id</route> - <action_type>collection</action_type> - </route_collection_with_store_and_category> - <route_collection_with_category_and_store> - <route>/products/category/:category_id/store/:store</route> - <action_type>collection</action_type> - </route_collection_with_category_and_store> - </routes> - <versions>1</versions> - </product> - <product_category translate="title" module="Mage_Api2"> - <group>catalog_product</group> - <model>Mage_Catalog_Model_Api2_Product_Category</model> - <working_model>Mage_Catalog_Model_Category</working_model> - <title>Product Category</title> - <sort_order>40</sort_order> - <privileges> - <admin> - <create>1</create> - <retrieve>1</retrieve> - <delete>1</delete> - </admin> - <customer> - <retrieve>1</retrieve> - </customer> - <guest> - <retrieve>1</retrieve> - </guest> - </privileges> - <attributes translate="category_id" module="Mage_Api2"> - <category_id>Category ID</category_id> - </attributes> - <routes> - <route_collection> - <route>/products/:id/categories</route> - <action_type>collection</action_type> - </route_collection> - <route_entity> - <route>/products/:id/categories/:category_id</route> - <action_type>entity</action_type> - </route_entity> - </routes> - <validators> - <fields> - <category_id> - <required>1</required> - <int translate="message" module="Mage_Api2"> - <type>Int</type> - <message>Please use numbers only in "category_id" field.</message> - </int> - </category_id> - </fields> - </validators> - <versions>1</versions> - </product_category> - <product_image translate="title" module="Mage_Api2"> - <group>catalog_product</group> - <model>Mage_Catalog_Model_Api2_Product_Image</model> - <title>Product Image</title> - <sort_order>70</sort_order> - <privileges> - <admin> - <create>1</create> - <retrieve>1</retrieve> - <update>1</update> - <delete>1</delete> - </admin> - <customer> - <retrieve>1</retrieve> - </customer> - <guest> - <retrieve>1</retrieve> - </guest> - </privileges> - <attributes translate="id file_name file_content file_mime_type label position types exclude url" module="Mage_Api2"> - <id>ID</id> - <file_name>File Name</file_name> - <file_content>File Content</file_content> - <file_mime_type>File MIME Type</file_mime_type> - <label>Label</label> - <position>Position</position> - <types>Type</types> - <exclude>Exclude</exclude> - <url>URL</url> - </attributes> - <exclude_attributes> - <customer> - <read> - <file_name>1</file_name> - <file_content>1</file_content> - <file_mime_type>1/</file_mime_type> - <exclude>1/</exclude> - </read> - </customer> - <guest> - <read> - <file_name>1</file_name> - <file_content>1</file_content> - <file_mime_type>1/</file_mime_type> - <exclude>1/</exclude> - </read> - </guest> - <admin> - <read> - <file_name>1</file_name> - <file_content>1</file_content> - <file_mime_type>1/</file_mime_type> - </read> - <write> - <id>1</id> - <url>1</url> - </write> - </admin> - </exclude_attributes> - <routes> - <route_entity> - <route>/products/:id/images/:image</route> - <action_type>entity</action_type> - </route_entity> - <route_entity_with_store> - <route>/products/:id/images/:image/store/:store</route> - <action_type>entity</action_type> - </route_entity_with_store> - <route_collection> - <route>/products/:id/images</route> - <action_type>collection</action_type> - </route_collection> - <route_collection_with_store> - <route>/products/:id/images/store/:store</route> - <action_type>collection</action_type> - </route_collection_with_store> - </routes> - <versions>1</versions> - </product_image> - <product_website translate="title" module="Mage_Api2"> - <group>catalog_product</group> - <model>Mage_Catalog_Model_Api2_Product_Website</model> - <working_model>Mage_Catalog_Model_Product_Website</working_model> - <title>Product Website</title> - <sort_order>100</sort_order> - <privileges> - <admin> - <create>1</create> - <retrieve>1</retrieve> - <delete>1</delete> - </admin> - </privileges> - <force_attributes> - <admin> - <website_id>1</website_id> - <copy_to_stores>1</copy_to_stores> - </admin> - </force_attributes> - <routes> - <route_entity> - <route>/products/:product_id/websites/:website_id</route> - <action_type>entity</action_type> - </route_entity> - <route_collection> - <route>/products/:product_id/websites</route> - <action_type>collection</action_type> - </route_collection> - </routes> - <versions>1</versions> - </product_website> - </resources> - </api2> -</config> diff --git a/app/code/core/Mage/Catalog/etc/wsdl.xml b/app/code/core/Mage/Catalog/etc/wsdl.xml deleted file mode 100644 index 1aba78ee8757748e4a2942d8007fc5fd912937c7..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Catalog/etc/wsdl.xml +++ /dev/null @@ -1,2294 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<definitions xmlns:typens="urn:{{var wsdl.name}}" xmlns:xsd="http://www.w3.org/2001/XMLSchema" - xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" - xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" - xmlns="http://schemas.xmlsoap.org/wsdl/" - name="{{var wsdl.name}}" targetNamespace="urn:{{var wsdl.name}}"> - <types> - <schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:Magento"> - <import namespace="http://schemas.xmlsoap.org/soap/encoding/" - schemaLocation="http://schemas.xmlsoap.org/soap/encoding/"/> - <complexType name="catalogProductEntityArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:catalogProductEntity[]"/> - </restriction> - </complexContent> - </complexType> - <complexType name="catalogProductAdditionalAttributesEntity"> - <all> - <element name="multi_data" type="typens:associativeMultiArray" minOccurs="0" /> - <element name="single_data" type="typens:associativeArray" minOccurs="0" /> - </all> - </complexType> - <complexType name="catalogProductEntity"> - <all> - <element name="product_id" type="xsd:string"/> - <element name="sku" type="xsd:string"/> - <element name="name" type="xsd:string"/> - <element name="set" type="xsd:string"/> - <element name="type" type="xsd:string"/> - <element name="category_ids" type="typens:ArrayOfString"/> - <element name="website_ids" type="typens:ArrayOfString"/> - </all> - </complexType> - <complexType name="catalogProductRequestAttributes"> - <all> - <element name="attributes" type="typens:ArrayOfString" minOccurs="0"/> - <element name="additional_attributes" type="typens:ArrayOfString" minOccurs="0"/> - </all> - </complexType> - <complexType name="catalogProductReturnEntity"> - <all> - <element name="product_id" type="xsd:string" minOccurs="0"/> - <element name="sku" type="xsd:string" minOccurs="0"/> - <element name="set" type="xsd:string" minOccurs="0"/> - <element name="type" type="xsd:string" minOccurs="0"/> - <element name="categories" type="typens:ArrayOfString" minOccurs="0"/> - <element name="websites" type="typens:ArrayOfString" minOccurs="0"/> - <element name="created_at" type="xsd:string" minOccurs="0"/> - <element name="updated_at" type="xsd:string" minOccurs="0"/> - <element name="type_id" type="xsd:string" minOccurs="0"/> - <element name="name" type="xsd:string" minOccurs="0"/> - <element name="description" type="xsd:string" minOccurs="0"/> - <element name="short_description" type="xsd:string" minOccurs="0"/> - <element name="weight" type="xsd:string" minOccurs="0"/> - <element name="status" type="xsd:string" minOccurs="0"/> - <element name="url_key" type="xsd:string" minOccurs="0"/> - <element name="url_path" type="xsd:string" minOccurs="0"/> - <element name="visibility" type="xsd:string" minOccurs="0"/> - <element name="category_ids" type="typens:ArrayOfString" minOccurs="0"/> - <element name="website_ids" type="typens:ArrayOfString" minOccurs="0"/> - <element name="has_options" type="xsd:string" minOccurs="0"/> - <element name="gift_message_available" type="xsd:string" minOccurs="0"/> - <element name="price" type="xsd:string" minOccurs="0"/> - <element name="special_price" type="xsd:string" minOccurs="0"/> - <element name="special_from_date" type="xsd:string" minOccurs="0"/> - <element name="special_to_date" type="xsd:string" minOccurs="0"/> - <element name="tax_class_id" type="xsd:string" minOccurs="0"/> - <element name="tier_price" type="typens:catalogProductTierPriceEntityArray" minOccurs="0"/> - <element name="meta_title" type="xsd:string" minOccurs="0"/> - <element name="meta_keyword" type="xsd:string" minOccurs="0"/> - <element name="meta_description" type="xsd:string" minOccurs="0"/> - <element name="custom_design" type="xsd:string" minOccurs="0"/> - <element name="custom_layout_update" type="xsd:string" minOccurs="0"/> - <element name="options_container" type="xsd:string" minOccurs="0"/> - <element name="additional_attributes" type="typens:associativeArray" minOccurs="0"/> - </all> - </complexType> - <complexType name="catalogProductCreateEntity"> - <all> - <element name="categories" type="typens:ArrayOfString" minOccurs="0"/> - <element name="websites" type="typens:ArrayOfString" minOccurs="0"/> - <element name="name" type="xsd:string" minOccurs="0"/> - <element name="description" type="xsd:string" minOccurs="0"/> - <element name="short_description" type="xsd:string" minOccurs="0"/> - <element name="weight" type="xsd:string" minOccurs="0"/> - <element name="status" type="xsd:string" minOccurs="0"/> - <element name="url_key" type="xsd:string" minOccurs="0"/> - <element name="url_path" type="xsd:string" minOccurs="0"/> - <element name="visibility" type="xsd:string" minOccurs="0"/> - <element name="category_ids" type="typens:ArrayOfString" minOccurs="0"/> - <element name="website_ids" type="typens:ArrayOfString" minOccurs="0"/> - <element name="has_options" type="xsd:string" minOccurs="0"/> - <element name="gift_message_available" type="xsd:string" minOccurs="0"/> - <element name="price" type="xsd:string" minOccurs="0"/> - <element name="special_price" type="xsd:string" minOccurs="0"/> - <element name="special_from_date" type="xsd:string" minOccurs="0"/> - <element name="special_to_date" type="xsd:string" minOccurs="0"/> - <element name="tax_class_id" type="xsd:string" minOccurs="0"/> - <element name="tier_price" type="typens:catalogProductTierPriceEntityArray" minOccurs="0"/> - <element name="meta_title" type="xsd:string" minOccurs="0"/> - <element name="meta_keyword" type="xsd:string" minOccurs="0"/> - <element name="meta_description" type="xsd:string" minOccurs="0"/> - <element name="custom_design" type="xsd:string" minOccurs="0"/> - <element name="custom_layout_update" type="xsd:string" minOccurs="0"/> - <element name="options_container" type="xsd:string" minOccurs="0"/> - <element name="additional_attributes" type="typens:catalogProductAdditionalAttributesEntity" minOccurs="0"/> - </all> - </complexType> - <complexType name="catalogProductAttributeSetEntity"> - <all> - <element name="set_id" type="xsd:int" minOccurs="0"/> - <element name="name" type="xsd:string" minOccurs="0"/> - </all> - </complexType> - <complexType name="catalogProductAttributeSetEntityArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:catalogProductAttributeSetEntity[]"/> - </restriction> - </complexContent> - </complexType> - <complexType name="catalogProductTypeEntity"> - <all> - <element name="type" type="xsd:string" minOccurs="0"/> - <element name="label" type="xsd:string" minOccurs="0"/> - </all> - </complexType> - <complexType name="catalogProductTypeEntityArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:catalogProductTypeEntity[]"/> - </restriction> - </complexContent> - </complexType> - <complexType name="catalogProductTierPriceEntity"> - <all> - <element name="customer_group_id" type="xsd:string" minOccurs="0"/> - <element name="website" type="xsd:string" minOccurs="0"/> - <element name="qty" type="xsd:int" minOccurs="0"/> - <element name="price" type="xsd:double" minOccurs="0"/> - </all> - </complexType> - <complexType name="catalogProductTierPriceEntityArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:catalogProductTierPriceEntity[]"/> - </restriction> - </complexContent> - </complexType> - <complexType name="ArrayOfCatalogCategoryEntities"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:catalogCategoryEntity[]"/> - </restriction> - </complexContent> - </complexType> - <complexType name="catalogCategoryEntity"> - <all> - <element name="category_id" type="xsd:int"/> - <element name="parent_id" type="xsd:int"/> - <element name="name" type="xsd:string"/> - <element name="is_active" type="xsd:int"/> - <element name="position" type="xsd:int"/> - <element name="level" type="xsd:int"/> - <element name="children" type="typens:ArrayOfCatalogCategoryEntities"/> - </all> - </complexType> - <complexType name="catalogCategoryEntityNoChildren"> - <all> - <element name="category_id" type="xsd:int"/> - <element name="parent_id" type="xsd:int"/> - <element name="name" type="xsd:string"/> - <element name="is_active" type="xsd:int"/> - <element name="position" type="xsd:int"/> - <element name="level" type="xsd:int"/> - </all> - </complexType> - <complexType name="ArrayOfCatalogCategoryEntitiesNoChildren"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:catalogCategoryEntityNoChildren[]"/> - </restriction> - </complexContent> - </complexType> - <complexType name="catalogCategoryTree"> - <all> - <element name="category_id" type="xsd:int"/> - <element name="parent_id" type="xsd:int"/> - <element name="name" type="xsd:string"/> - <element name="position" type="xsd:int"/> - <element name="level" type="xsd:int"/> - <element name="children" type="typens:ArrayOfCatalogCategoryEntities"/> - </all> - </complexType> - <complexType name="catalogCategoryEntityCreate"> - <all> - <element name="name" type="xsd:string" minOccurs="0"/> - <element name="is_active" type="xsd:int" minOccurs="0"/> - <element name="position" type="xsd:int" minOccurs="0"/> - <!-- position parameter is deprecated, category anyway will be positioned in the end of list - and you can not set position directly, use catalog_category.move instead --> - <element name="available_sort_by" type="typens:ArrayOfString" minOccurs="0"/> - <element name="custom_design" type="xsd:string" minOccurs="0"/> - <element name="custom_design_apply" type="xsd:int" minOccurs="0"/> - <element name="custom_design_from" type="xsd:string" minOccurs="0"/> - <element name="custom_design_to" type="xsd:string" minOccurs="0"/> - <element name="custom_layout_update" type="xsd:string" minOccurs="0"/> - <element name="default_sort_by" type="xsd:string" minOccurs="0"/> - <element name="description" type="xsd:string" minOccurs="0"/> - <element name="display_mode" type="xsd:string" minOccurs="0"/> - <element name="is_anchor" type="xsd:int" minOccurs="0"/> - <element name="landing_page" type="xsd:int" minOccurs="0"/> - <element name="meta_description" type="xsd:string" minOccurs="0"/> - <element name="meta_keywords" type="xsd:string" minOccurs="0"/> - <element name="meta_title" type="xsd:string" minOccurs="0"/> - <element name="page_layout" type="xsd:string" minOccurs="0"/> - <element name="url_key" type="xsd:string" minOccurs="0"/> - <element name="include_in_menu" type="xsd:int" minOccurs="0"/> - </all> - </complexType> - <complexType name="catalogCategoryInfo"> - <all> - <element name="category_id" type="xsd:string"/> - <element name="is_active" type="xsd:int"/> - <element name="position" type="xsd:string"/> - <element name="level" type="xsd:string"/> - <element name="parent_id" type="xsd:string"/> - <element name="all_children" type="xsd:string"/> - <element name="children" type="xsd:string"/> - <element name="created_at" type="xsd:string" minOccurs="0"/> - <element name="updated_at" type="xsd:string" minOccurs="0"/> - <element name="name" type="xsd:string" minOccurs="0"/> - <element name="url_key" type="xsd:string" minOccurs="0"/> - <element name="description" type="xsd:string" minOccurs="0"/> - <element name="meta_title" type="xsd:string" minOccurs="0"/> - <element name="meta_keywords" type="xsd:string" minOccurs="0"/> - <element name="meta_description" type="xsd:string" minOccurs="0"/> - <element name="path" type="xsd:string" minOccurs="0"/> - <element name="url_path" type="xsd:string" minOccurs="0"/> - <element name="children_count" type="xsd:int" minOccurs="0"/> - <element name="display_mode" type="xsd:string" minOccurs="0"/> - <element name="is_anchor" type="xsd:int" minOccurs="0"/> - <element name="available_sort_by" type="typens:ArrayOfString" minOccurs="0"/> - <element name="custom_design" type="xsd:string" minOccurs="0"/> - <element name="custom_design_apply" type="xsd:string" minOccurs="0"/> - <element name="custom_design_from" type="xsd:string" minOccurs="0"/> - <element name="custom_design_to" type="xsd:string" minOccurs="0"/> - <element name="page_layout" type="xsd:string" minOccurs="0"/> - <element name="custom_layout_update" type="xsd:string" minOccurs="0"/> - <element name="default_sort_by" type="xsd:string" minOccurs="0"/> - <element name="landing_page" type="xsd:int" minOccurs="0"/> - </all> - </complexType> - <complexType name="catalogAssignedProduct"> - <all> - <element name="product_id" type="xsd:int"/> - <element name="type" type="xsd:string"/> - <element name="set" type="xsd:int"/> - <element name="sku" type="xsd:string"/> - <element name="position" type="xsd:int"/> - </all> - </complexType> - <complexType name="catalogAssignedProductArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:catalogAssignedProduct[]"/> - </restriction> - </complexContent> - </complexType> - <complexType name="catalogAttributeEntity"> - <all> - <element name="attribute_id" type="xsd:int" minOccurs="0"/> - <element name="code" type="xsd:string" minOccurs="0"/> - <element name="type" type="xsd:string" minOccurs="0"/> - <element name="required" type="xsd:string" minOccurs="0"/> - <element name="scope" type="xsd:string" minOccurs="0"/> - </all> - </complexType> - <complexType name="catalogAttributeEntityArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:catalogAttributeEntity[]"/> - </restriction> - </complexContent> - </complexType> - <complexType name="catalogAttributeOptionEntity"> - <all> - <element name="label" type="xsd:string"/> - <element name="value" type="xsd:string"/> - </all> - </complexType> - <complexType name="catalogAttributeOptionEntityArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:catalogAttributeOptionEntity[]"/> - </restriction> - </complexContent> - </complexType> - <complexType name="catalogProductImageEntity"> - <all> - <element name="file" type="xsd:string"/> - <element name="label" type="xsd:string"/> - <element name="position" type="xsd:string"/> - <element name="exclude" type="xsd:string"/> - <element name="url" type="xsd:string"/> - <element name="types" type="typens:ArrayOfString"/> - </all> - </complexType> - <complexType name="catalogProductImageEntityArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:catalogProductImageEntity[]"/> - </restriction> - </complexContent> - </complexType> - <complexType name="catalogProductAttributeMediaTypeEntity"> - <all> - <element name="code" type="xsd:string"/> - <element name="scope" type="xsd:string"/> - </all> - </complexType> - <complexType name="catalogProductAttributeMediaTypeEntityArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" - wsdl:arrayType="typens:catalogProductAttributeMediaTypeEntity[]"/> - </restriction> - </complexContent> - </complexType> - <complexType name="catalogProductImageFileEntity"> - <all> - <element name="content" type="xsd:string"/> - <element name="mime" type="xsd:string"/> - <element name="name" type="xsd:string" minOccurs="0"/> - </all> - </complexType> - <complexType name="catalogProductAttributeMediaCreateEntity"> - <all> - <element name="file" type="typens:catalogProductImageFileEntity" minOccurs="0"/> - <element name="label" type="xsd:string" minOccurs="0"/> - <element name="position" type="xsd:string" minOccurs="0"/> - <element name="types" type="typens:ArrayOfString" minOccurs="0"/> - <element name="exclude" type="xsd:string" minOccurs="0"/> - <element name="remove" type="xsd:string" minOccurs="0"/> - </all> - </complexType> - <complexType name="catalogProductLinkEntity"> - <all> - <element name="product_id" type="xsd:string" minOccurs="0"/> - <element name="type" type="xsd:string" minOccurs="0"/> - <element name="set" type="xsd:string" minOccurs="0"/> - <element name="sku" type="xsd:string" minOccurs="0"/> - <element name="position" type="xsd:string" minOccurs="0"/> - <element name="qty" type="xsd:string" minOccurs="0"/> - </all> - </complexType> - <complexType name="catalogProductLinkEntityArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:catalogProductLinkEntity[]"/> - </restriction> - </complexContent> - </complexType> - <complexType name="catalogProductLinkAttributeEntity"> - <all> - <element name="code" type="xsd:string" minOccurs="0"/> - <element name="type" type="xsd:string" minOccurs="0"/> - </all> - </complexType> - <complexType name="catalogProductLinkAttributeEntityArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:catalogProductLinkAttributeEntity[]"/> - </restriction> - </complexContent> - </complexType> - <complexType name="catalogProductAttributeFrontendLabelEntity"> - <all> - <element name="store_id" type="xsd:string" /> - <element name="label" type="xsd:string" /> - </all> - </complexType> - <complexType name="catalogProductAttributeFrontendLabelArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:catalogProductAttributeFrontendLabelEntity[]"/> - </restriction> - </complexContent> - </complexType> - <complexType name="catalogProductAttributeEntityToCreate"> - <all> - <element name="attribute_code" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <element name="frontend_input" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <element name="scope" type="xsd:string" minOccurs="0" /> - <element name="default_value" type="xsd:string" minOccurs="0" /> - <element name="is_unique" type="xsd:int" minOccurs="0" /> - <element name="is_required" type="xsd:int" minOccurs="0" /> - <element name="apply_to" type="typens:ArrayOfString" minOccurs="0" /> - <element name="is_configurable" type="xsd:int" minOccurs="0" /> - <element name="is_searchable" type="xsd:int" minOccurs="0" /> - <element name="is_visible_in_advanced_search" type="xsd:int" minOccurs="0" /> - <element name="is_comparable" type="xsd:int" minOccurs="0" /> - <element name="is_used_for_promo_rules" type="xsd:int" minOccurs="0" /> - <element name="is_visible_on_front" type="xsd:int" minOccurs="0" /> - <element name="used_in_product_listing" type="xsd:int" minOccurs="0" /> - <element name="additional_fields" type="typens:associativeArray" minOccurs="0"/> - <element name="frontend_label" type="typens:catalogProductAttributeFrontendLabelArray" minOccurs="1" /> - </all> - </complexType> - <complexType name="catalogProductAttributeEntityToUpdate"> - <all> - <element name="scope" type="xsd:string" minOccurs="0" /> - <element name="default_value" type="xsd:string" minOccurs="0" /> - <element name="is_unique" type="xsd:int" minOccurs="0" /> - <element name="is_required" type="xsd:int" minOccurs="0" /> - <element name="apply_to" type="typens:ArrayOfString" minOccurs="0" /> - <element name="is_configurable" type="xsd:int" minOccurs="0" /> - <element name="is_searchable" type="xsd:int" minOccurs="0" /> - <element name="is_visible_in_advanced_search" type="xsd:int" minOccurs="0" /> - <element name="is_comparable" type="xsd:int" minOccurs="0" /> - <element name="is_used_for_promo_rules" type="xsd:int" minOccurs="0" /> - <element name="is_visible_on_front" type="xsd:int" minOccurs="0" /> - <element name="used_in_product_listing" type="xsd:int" minOccurs="0" /> - <element name="additional_fields" type="typens:associativeArray" minOccurs="0"/> - <element name="frontend_label" type="typens:catalogProductAttributeFrontendLabelArray" minOccurs="1" /> - </all> - </complexType> - <complexType name="catalogProductAttributeEntity"> - <all> - <element name="attribute_id" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <element name="attribute_code" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <element name="frontend_input" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <element name="scope" type="xsd:string" minOccurs="0" /> - <element name="default_value" type="xsd:string" minOccurs="0" /> - <element name="is_unique" type="xsd:int" minOccurs="0" /> - <element name="is_required" type="xsd:int" minOccurs="0" /> - <element name="apply_to" type="typens:ArrayOfString" minOccurs="0" /> - <element name="is_configurable" type="xsd:int" minOccurs="0" /> - <element name="is_searchable" type="xsd:int" minOccurs="0" /> - <element name="is_visible_in_advanced_search" type="xsd:int" minOccurs="0" /> - <element name="is_comparable" type="xsd:int" minOccurs="0" /> - <element name="is_used_for_promo_rules" type="xsd:int" minOccurs="0" /> - <element name="is_visible_on_front" type="xsd:int" minOccurs="0" /> - <element name="used_in_product_listing" type="xsd:int" minOccurs="0" /> - <element name="additional_fields" type="typens:associativeArray" minOccurs="0"/> - <element name="options" type="typens:catalogAttributeOptionEntityArray" minOccurs="0"/> - <element name="frontend_label" type="typens:catalogProductAttributeFrontendLabelArray" minOccurs="1" /> - </all> - </complexType> - <complexType name="catalogProductAttributeOptionLabelEntity"> - <all> - <element name="store_id" type="typens:ArrayOfString" /> - <element name="value" type="xsd:string" /> - </all> - </complexType> - <complexType name="catalogProductAttributeOptionLabelArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:catalogProductAttributeOptionLabelEntity[]"/> - </restriction> - </complexContent> - </complexType> - <complexType name="catalogProductAttributeOptionEntityToAdd"> - <all> - <element name="label" type="typens:catalogProductAttributeOptionLabelArray" /> - <element name="order" type="xsd:int" /> - <element name="is_default" type="xsd:int" /> - </all> - </complexType> - <complexType name="catalogProductCustomOptionAdditionalFieldsEntity"> - <all> - <element name="title" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <element name="price" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <element name="price_type" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <element name="sku" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <element name="max_characters" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <element name="sort_order" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <element name="file_extension" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <element name="image_size_x" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <element name="image_size_y" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <element name="value_id" type="xsd:string" minOccurs="0" maxOccurs="1" /> - </all> - </complexType> - <complexType name="catalogProductCustomOptionAdditionalFieldsArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:catalogProductCustomOptionAdditionalFieldsEntity[]"/> - </restriction> - </complexContent> - </complexType> - <complexType name="catalogProductCustomOptionToAdd"> - <all> - <element name="title" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <element name="type" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <element name="sort_order" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <element name="is_require" type="xsd:int" minOccurs="0" maxOccurs="1" /> - <element name="additional_fields" type="typens:catalogProductCustomOptionAdditionalFieldsArray" minOccurs="1" maxOccurs="1" /> - </all> - </complexType> - <complexType name="catalogProductCustomOptionToUpdate"> - <all> - <element name="title" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <element name="type" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <element name="sort_order" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <element name="is_require" type="xsd:int" minOccurs="0" maxOccurs="1" /> - <element name="additional_fields" type="typens:catalogProductCustomOptionAdditionalFieldsArray" minOccurs="0" maxOccurs="1" /> - </all> - </complexType> - <complexType name="catalogProductCustomOptionInfoEntity"> - <all> - <element name="title" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <element name="type" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <element name="sort_order" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <element name="is_require" type="xsd:int" minOccurs="1" maxOccurs="1" /> - <element name="additional_fields" type="typens:catalogProductCustomOptionAdditionalFieldsArray" minOccurs="1" maxOccurs="1" /> - </all> - </complexType> - <complexType name="catalogProductCustomOptionListEntity"> - <all> - <element name="option_id" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <element name="title" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <element name="type" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <element name="sort_order" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <element name="is_require" type="xsd:int" minOccurs="1" maxOccurs="1" /> - </all> - </complexType> - <complexType name="catalogProductCustomOptionListArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:catalogProductCustomOptionListEntity[]"/> - </restriction> - </complexContent> - </complexType> - <complexType name="catalogProductCustomOptionTypesEntity"> - <all> - <element name="label" type="xsd:string"/> - <element name="value" type="xsd:string"/> - </all> - </complexType> - <complexType name="catalogProductCustomOptionTypesArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:catalogProductCustomOptionTypesEntity[]"/> - </restriction> - </complexContent> - </complexType> - <complexType name="catalogProductCustomOptionValueInfoEntity"> - <all> - <element name="value_id" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <element name="option_id" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <element name="sku" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <element name="sort_order" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <element name="default_price" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <element name="default_price_type" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <element name="store_price" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <element name="store_price_type" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <element name="price" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <element name="price_type" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <element name="default_title" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <element name="store_title" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <element name="title" type="xsd:string" minOccurs="1" maxOccurs="1" /> - </all> - </complexType> - <complexType name="catalogProductCustomOptionValueListEntity"> - <all> - <element name="value_id" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <element name="title" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <element name="price" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <element name="price_type" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <element name="sku" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <element name="sort_order" type="xsd:string" minOccurs="1" maxOccurs="1" /> - </all> - </complexType> - <complexType name="catalogProductCustomOptionValueListArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:catalogProductCustomOptionValueListEntity[]"/> - </restriction> - </complexContent> - </complexType> - <complexType name="catalogProductCustomOptionValueAddEntity"> - <all> - <element name="title" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <element name="price" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <element name="price_type" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <element name="sku" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <element name="sort_order" type="xsd:string" minOccurs="0" maxOccurs="1" /> - </all> - </complexType> - <complexType name="catalogProductCustomOptionValueAddArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:catalogProductCustomOptionValueAddEntity[]"/> - </restriction> - </complexContent> - </complexType> - <complexType name="catalogProductCustomOptionValueUpdateEntity"> - <all> - <element name="title" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <element name="price" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <element name="price_type" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <element name="sku" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <element name="sort_order" type="xsd:string" minOccurs="0" maxOccurs="1" /> - </all> - </complexType> - </schema> - </types> - <message name="catalogProductCurrentStoreRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="storeView" type="xsd:string"/> - </message> - <message name="catalogProductCurrentStoreResponse"> - <part name="storeView" type="xsd:int"/> - </message> - <message name="catalogProductListRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="filters" type="typens:filters"/> - <part name="storeView" type="xsd:string"/> - </message> - <message name="catalogProductListResponse"> - <part name="storeView" type="typens:catalogProductEntityArray"/> - </message> - <message name="catalogProductInfoRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="product" type="xsd:string"/> - <part name="storeView" type="xsd:string"/> - <part name="attributes" type="typens:catalogProductRequestAttributes"/> - <part name="productIdentifierType" type="xsd:string"/> - </message> - <message name="catalogProductInfoResponse"> - <part name="info" type="typens:catalogProductReturnEntity"/> - </message> - <message name="catalogProductCreateRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="type" type="xsd:string"/> - <part name="set" type="xsd:string"/> - <part name="sku" type="xsd:string"/> - <part name="productData" type="typens:catalogProductCreateEntity"/> - <part name="storeView" type="xsd:string"/> - </message> - <message name="catalogProductCreateResponse"> - <part name="result" type="xsd:int"/> - </message> - <message name="catalogProductUpdateRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="product" type="xsd:string"/> - <part name="productData" type="typens:catalogProductCreateEntity"/> - <part name="storeView" type="xsd:string"/> - <part name="productIdentifierType" type="xsd:string"/> - </message> - <message name="catalogProductUpdateResponse"> - <part name="result" type="xsd:boolean"/> - </message> - <message name="catalogProductSetSpecialPriceRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="product" type="xsd:string"/> - <part name="specialPrice" type="xsd:string"/> - <part name="fromDate" type="xsd:string"/> - <part name="toDate" type="xsd:string"/> - <part name="storeView" type="xsd:string"/> - <part name="productIdentifierType" type="xsd:string"/> - </message> - <message name="catalogProductSetSpecialPriceResponse"> - <part name="result" type="xsd:int"/> - </message> - <message name="catalogProductGetSpecialPriceRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="product" type="xsd:string"/> - <part name="storeView" type="xsd:string"/> - <part name="productIdentifierType" type="xsd:string"/> - </message> - <message name="catalogProductGetSpecialPriceResponse"> - <part name="result" type="typens:catalogProductReturnEntity"/> - </message> - <message name="catalogProductDeleteRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="product" type="xsd:string"/> - <part name="productIdentifierType" type="xsd:string"/> - </message> - <message name="catalogProductDeleteResponse"> - <part name="result" type="xsd:int"/> - </message> - <message name="catalogProductAttributeCurrentStoreRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="storeView" type="xsd:string"/> - </message> - <message name="catalogProductAttributeCurrentStoreResponse"> - <part name="storeView" type="xsd:int"/> - </message> - <message name="catalogProductListOfAdditionalAttributesRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="productType" type="xsd:string" /> - <part name="attributeSetId" type="xsd:string" /> - </message> - <message name="catalogProductListOfAdditionalAttributesResponse"> - <part name="result" type="typens:catalogAttributeEntityArray" /> - </message> - <message name="catalogProductAttributeListRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="setId" type="xsd:int"/> - </message> - <message name="catalogProductAttributeListResponse"> - <part name="result" type="typens:catalogAttributeEntityArray"/> - </message> - <message name="catalogProductAttributeOptionsRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="attributeId" type="xsd:string"/> - <part name="storeView" type="xsd:string"/> - </message> - <message name="catalogProductAttributeOptionsResponse"> - <part name="result" type="typens:catalogAttributeOptionEntityArray"/> - </message> - <message name="catalogProductAttributeSetCreateRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="attributeSetName" type="xsd:string"/> - <part name="skeletonSetId" type="xsd:string"/> - </message> - <message name="catalogProductAttributeSetCreateResponse"> - <part name="setId" type="xsd:int"/> - </message> - <message name="catalogProductAttributeSetRemoveRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="attributeSetId" type="xsd:string"/> - <part name="forceProductsRemove" type="xsd:string"/> - </message> - <message name="catalogProductAttributeSetRemoveResponse"> - <part name="isRemoved" type="xsd:boolean"/> - </message> - <message name="catalogProductAttributeSetListRequest"> - <part name="sessionId" type="xsd:string"/> - </message> - <message name="catalogProductAttributeSetListResponse"> - <part name="result" type="typens:catalogProductAttributeSetEntityArray"/> - </message> - <message name="catalogProductAttributeSetAttributeAddRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="attributeId" type="xsd:string" /> - <part name="attributeSetId" type="xsd:string" /> - <part name="attributeGroupId" type="xsd:string"/> - <part name="sortOrder" type="xsd:string" /> - </message> - <message name="catalogProductAttributeSetAttributeAddResponse"> - <part name="isAdded" type="xsd:boolean" /> - </message> - <message name="catalogProductAttributeSetAttributeRemoveRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="attributeId" type="xsd:string" /> - <part name="attributeSetId" type="xsd:string" /> - </message> - <message name="catalogProductAttributeSetAttributeRemoveResponse"> - <part name="isRemoved" type="xsd:boolean" /> - </message> - <message name="catalogProductAttributeSetGroupAddRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="attributeSetId" type="xsd:string" /> - <part name="groupName" type="xsd:string" /> - </message> - <message name="catalogProductAttributeSetGroupAddResponse"> - <part name="result" type="xsd:int" /> - </message> - <message name="catalogProductAttributeSetGroupRenameRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="groupId" type="xsd:string" /> - <part name="groupName" type="xsd:string" /> - </message> - <message name="catalogProductAttributeSetGroupRenameResponse"> - <part name="result" type="xsd:boolean" /> - </message> - <message name="catalogProductAttributeSetGroupRemoveRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="attributeGroupId" type="xsd:string" /> - </message> - <message name="catalogProductAttributeSetGroupRemoveResponse"> - <part name="result" type="xsd:boolean" /> - </message> - <message name="catalogProductAttributeTypesRequest"> - <part name="sessionId" type="xsd:string"/> - </message> - <message name="catalogProductAttributeTypesResponse"> - <part name="result" type="typens:catalogAttributeOptionEntityArray" /> - </message> - <message name="catalogProductAttributeCreateRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="data" type="typens:catalogProductAttributeEntityToCreate"/> - </message> - <message name="catalogProductAttributeCreateResponse"> - <part name="result" type="xsd:int" /> - </message> - <message name="catalogProductAttributeRemoveRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="attribute" type="xsd:string"/> - </message> - <message name="catalogProductAttributeRemoveResponse"> - <part name="result" type="xsd:boolean" /> - </message> - <message name="catalogProductAttributeInfoRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="attribute" type="xsd:string"/> - </message> - <message name="catalogProductAttributeInfoResponse"> - <part name="result" type="typens:catalogProductAttributeEntity" /> - </message> - <message name="catalogProductAttributeUpdateRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="attribute" type="xsd:string"/> - <part name="data" type="typens:catalogProductAttributeEntityToUpdate"/> - </message> - <message name="catalogProductAttributeUpdateResponse"> - <part name="result" type="xsd:boolean" /> - </message> - <message name="catalogProductAttributeAddOptionRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="attribute" type="xsd:string"/> - <part name="data" type="typens:catalogProductAttributeOptionEntityToAdd"/> - </message> - <message name="catalogProductAttributeAddOptionResponse"> - <part name="result" type="xsd:boolean" /> - </message> - <message name="catalogProductAttributeRemoveOptionRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="attribute" type="xsd:string"/> - <part name="optionId" type="xsd:string"/> - </message> - <message name="catalogProductAttributeRemoveOptionResponse"> - <part name="result" type="xsd:boolean" /> - </message> - <message name="catalogProductTypeListRequest"> - <part name="sessionId" type="xsd:string"/> - </message> - <message name="catalogProductTypeListResponse"> - <part name="result" type="typens:catalogProductTypeEntityArray"/> - </message> - <message name="catalogProductAttributeTierPriceInfoRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="product" type="xsd:string"/> - <part name="productIdentifierType" type="xsd:string"/> - </message> - <message name="catalogProductAttributeTierPriceInfoResponse"> - <part name="result" type="typens:catalogProductTierPriceEntityArray"/> - </message> - <message name="catalogProductAttributeTierPriceUpdateRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="product" type="xsd:string"/> - <part name="tier_price" type="typens:catalogProductTierPriceEntityArray"/> - <part name="productIdentifierType" type="xsd:string"/> - </message> - <message name="catalogProductAttributeTierPriceUpdateResponse"> - <part name="result" type="xsd:int"/> - </message> - <message name="catalogProductAttributeMediaCurrentStoreRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="storeView" type="xsd:string"/> - </message> - <message name="catalogProductAttributeMediaCurrentStoreResponse"> - <part name="storeView" type="xsd:int"/> - </message> - <message name="catalogProductAttributeMediaListRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="product" type="xsd:string"/> - <part name="storeView" type="xsd:string"/> - <part name="productIdentifierType" type="xsd:string"/> - </message> - <message name="catalogProductAttributeMediaListResponse"> - <part name="result" type="typens:catalogProductImageEntityArray"/> - </message> - <message name="catalogProductAttributeMediaInfoRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="product" type="xsd:string"/> - <part name="file" type="xsd:string"/> - <part name="storeView" type="xsd:string"/> - <part name="productIdentifierType" type="xsd:string"/> - </message> - <message name="catalogProductAttributeMediaInfoResponse"> - <part name="result" type="typens:catalogProductImageEntity"/> - </message> - <message name="catalogProductAttributeMediaTypesRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="setId" type="xsd:string"/> - </message> - <message name="catalogProductAttributeMediaTypesResponse"> - <part name="result" type="typens:catalogProductAttributeMediaTypeEntityArray"/> - </message> - <message name="catalogProductAttributeMediaCreateRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="product" type="xsd:string"/> - <part name="data" type="typens:catalogProductAttributeMediaCreateEntity"/> - <part name="storeView" type="xsd:string"/> - <part name="productIdentifierType" type="xsd:string"/> - </message> - <message name="catalogProductAttributeMediaCreateResponse"> - <part name="result" type="xsd:string"/> - </message> - <message name="catalogProductAttributeMediaUpdateRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="product" type="xsd:string"/> - <part name="file" type="xsd:string"/> - <part name="data" type="typens:catalogProductAttributeMediaCreateEntity"/> - <part name="storeView" type="xsd:string"/> - <part name="productIdentifierType" type="xsd:string"/> - </message> - <message name="catalogProductAttributeMediaUpdateResponse"> - <part name="result" type="xsd:boolean"/> - </message> - <message name="catalogProductAttributeMediaRemoveRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="product" type="xsd:string"/> - <part name="file" type="xsd:string"/> - <part name="productIdentifierType" type="xsd:string"/> - </message> - <message name="catalogProductAttributeMediaRemoveResponse"> - <part name="result" type="xsd:boolean"/> - </message> - <message name="catalogProductLinkListRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="type" type="xsd:string"/> - <part name="product" type="xsd:string"/> - <part name="productIdentifierType" type="xsd:string"/> - </message> - <message name="catalogProductLinkListResponse"> - <part name="result" type="typens:catalogProductLinkEntityArray"/> - </message> - <message name="catalogProductLinkAssignRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="type" type="xsd:string"/> - <part name="product" type="xsd:string"/> - <part name="linkedProduct" type="xsd:string"/> - <part name="data" type="typens:catalogProductLinkEntity"/> - <part name="productIdentifierType" type="xsd:string"/> - </message> - <message name="catalogProductLinkAssignResponse"> - <part name="result" type="xsd:boolean"/> - </message> - <message name="catalogProductLinkUpdateRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="type" type="xsd:string"/> - <part name="product" type="xsd:string"/> - <part name="linkedProduct" type="xsd:string"/> - <part name="data" type="typens:catalogProductLinkEntity"/> - <part name="productIdentifierType" type="xsd:string"/> - </message> - <message name="catalogProductLinkUpdateResponse"> - <part name="result" type="xsd:boolean"/> - </message> - <message name="catalogProductLinkRemoveRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="type" type="xsd:string"/> - <part name="product" type="xsd:string"/> - <part name="linkedProduct" type="xsd:string"/> - <part name="productIdentifierType" type="xsd:string"/> - </message> - <message name="catalogProductLinkRemoveResponse"> - <part name="result" type="xsd:boolean"/> - </message> - <message name="catalogProductLinkTypesRequest"> - <part name="sessionId" type="xsd:string"/> - </message> - <message name="catalogProductLinkTypesResponse"> - <part name="result" type="typens:ArrayOfString"/> - </message> - <message name="catalogProductLinkAttributesRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="type" type="xsd:string"/> - </message> - <message name="catalogProductLinkAttributesResponse"> - <part name="result" type="typens:catalogProductLinkAttributeEntityArray"/> - </message> - <message name="catalogCategoryCurrentStoreRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="storeView" type="xsd:string"/> - </message> - <message name="catalogCategoryCurrentStoreResponse"> - <part name="storeView" type="xsd:int"/> - </message> - <message name="catalogProductCustomOptionAddRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="productId" type="xsd:string"/> - <part name="data" type="typens:catalogProductCustomOptionToAdd"/> - <part name="store" type="xsd:string"/> - </message> - <message name="catalogProductCustomOptionAddResponse"> - <part name="result" type="xsd:boolean"/> - </message> - <message name="catalogProductCustomOptionUpdateRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="optionId" type="xsd:string"/> - <part name="data" type="typens:catalogProductCustomOptionToUpdate"/> - <part name="store" type="xsd:string"/> - </message> - <message name="catalogProductCustomOptionUpdateResponse"> - <part name="result" type="xsd:boolean"/> - </message> - <message name="catalogProductCustomOptionListRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="productId" type="xsd:string"/> - <part name="store" type="xsd:string"/> - </message> - <message name="catalogProductCustomOptionListResponse"> - <part name="result" type="typens:catalogProductCustomOptionListArray"/> - </message> - <message name="catalogProductCustomOptionTypesRequest"> - <part name="sessionId" type="xsd:string"/> - </message> - <message name="catalogProductCustomOptionTypesResponse"> - <part name="result" type="typens:catalogProductCustomOptionTypesArray"/> - </message> - <message name="catalogProductCustomOptionInfoRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="optionId" type="xsd:string"/> - <part name="store" type="xsd:string"/> - </message> - <message name="catalogProductCustomOptionInfoResponse"> - <part name="result" type="typens:catalogProductCustomOptionInfoEntity"/> - </message> - <message name="catalogProductCustomOptionRemoveRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="optionId" type="xsd:string"/> - </message> - <message name="catalogProductCustomOptionRemoveResponse"> - <part name="result" type="xsd:boolean"/> - </message> - <message name="catalogProductCustomOptionValueListRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="optionId" type="xsd:string"/> - <part name="store" type="xsd:string"/> - </message> - <message name="catalogProductCustomOptionValueListResponse"> - <part name="result" type="typens:catalogProductCustomOptionValueListArray"/> - </message> - <message name="catalogProductCustomOptionValueInfoRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="valueId" type="xsd:string"/> - <part name="store" type="xsd:string"/> - </message> - <message name="catalogProductCustomOptionValueInfoResponse"> - <part name="result" type="typens:catalogProductCustomOptionValueInfoEntity"/> - </message> - <message name="catalogProductCustomOptionValueAddRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="optionId" type="xsd:string"/> - <part name="data" type="typens:catalogProductCustomOptionValueAddArray"/> - <part name="store" type="xsd:string"/> - </message> - <message name="catalogProductCustomOptionValueAddResponse"> - <part name="result" type="xsd:boolean"/> - </message> - <message name="catalogProductCustomOptionValueUpdateRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="valueId" type="xsd:string"/> - <part name="data" type="typens:catalogProductCustomOptionValueUpdateEntity"/> - <part name="storeId" type="xsd:string"/> - </message> - <message name="catalogProductCustomOptionValueUpdateResponse"> - <part name="result" type="xsd:boolean"/> - </message> - <message name="catalogProductCustomOptionValueRemoveRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="valueId" type="xsd:string"/> - </message> - <message name="catalogProductCustomOptionValueRemoveResponse"> - <part name="result" type="xsd:boolean"/> - </message> - <message name="catalogCategoryTreeRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="parentId" type="xsd:string"/> - <part name="storeView" type="xsd:string"/> - </message> - <message name="catalogCategoryTreeResponse"> - <part name="tree" type="typens:catalogCategoryTree"/> - </message> - <message name="catalogCategoryLevelRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="website" type="xsd:string"/> - <part name="storeView" type="xsd:string"/> - <part name="parentCategory" type="xsd:string"/> - </message> - <message name="catalogCategoryLevelResponse"> - <part name="tree" type="typens:ArrayOfCatalogCategoryEntitiesNoChildren"/> - </message> - <message name="catalogCategoryInfoRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="categoryId" type="xsd:int"/> - <part name="storeView" type="xsd:string"/> - <part name="attributes" type="typens:ArrayOfString"/> - </message> - <message name="catalogCategoryInfoResponse"> - <part name="info" type="typens:catalogCategoryInfo"/> - </message> - <message name="catalogCategoryCreateRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="parentId" type="xsd:int"/> - <part name="categoryData" type="typens:catalogCategoryEntityCreate"/> - <part name="storeView" type="xsd:string"/> - </message> - <message name="catalogCategoryCreateResponse"> - <part name="attribute_id" type="xsd:int"/> - </message> - <message name="catalogCategoryUpdateRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="categoryId" type="xsd:int"/> - <part name="categoryData" type="typens:catalogCategoryEntityCreate"/> - <part name="storeView" type="xsd:string"/> - </message> - <message name="catalogCategoryUpdateResponse"> - <part name="id" type="xsd:boolean"/> - </message> - <message name="catalogCategoryMoveRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="categoryId" type="xsd:int"/> - <part name="parentId" type="xsd:int"/> - <part name="afterId" type="xsd:string"/> - </message> - <message name="catalogCategoryMoveResponse"> - <part name="id" type="xsd:boolean"/> - </message> - <message name="catalogCategoryDeleteRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="categoryId" type="xsd:int"/> - </message> - <message name="catalogCategoryDeleteResponse"> - <part name="result" type="xsd:boolean"/> - </message> - <message name="catalogCategoryAssignedProductsRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="categoryId" type="xsd:int"/> - </message> - <message name="catalogCategoryAssignedProductsResponse"> - <part name="result" type="typens:catalogAssignedProductArray"/> - </message> - <message name="catalogCategoryAssignProductRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="categoryId" type="xsd:int"/> - <part name="product" type="xsd:string"/> - <part name="position" type="xsd:string"/> - <part name="productIdentifierType" type="xsd:string"/> - </message> - <message name="catalogCategoryAssignProductResponse"> - <part name="result" type="xsd:boolean"/> - </message> - <message name="catalogCategoryUpdateProductRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="categoryId" type="xsd:int"/> - <part name="product" type="xsd:string"/> - <part name="position" type="xsd:string"/> - <part name="productIdentifierType" type="xsd:string"/> - </message> - <message name="catalogCategoryUpdateProductResponse"> - <part name="result" type="xsd:boolean"/> - </message> - <message name="catalogCategoryRemoveProductRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="categoryId" type="xsd:int"/> - <part name="product" type="xsd:string"/> - <part name="productIdentifierType" type="xsd:string"/> - </message> - <message name="catalogCategoryRemoveProductResponse"> - <part name="result" type="xsd:boolean"/> - </message> - <message name="catalogCategoryAttributeCurrentStoreRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="storeView" type="xsd:string"/> - </message> - <message name="catalogCategoryAttributeCurrentStoreResponse"> - <part name="storeView" type="xsd:int"/> - </message> - <message name="catalogCategoryAttributeListRequest"> - <part name="sessionId" type="xsd:string"/> - </message> - <message name="catalogCategoryAttributeListResponse"> - <part name="result" type="typens:catalogAttributeEntityArray"/> - </message> - <message name="catalogCategoryAttributeOptionsRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="attributeId" type="xsd:string"/> - <part name="storeView" type="xsd:string"/> - </message> - <message name="catalogCategoryAttributeOptionsResponse"> - <part name="result" type="typens:catalogAttributeOptionEntityArray"/> - </message> - <portType name="{{var wsdl.handler}}PortType"> - <operation name="catalogCategoryCurrentStore"> - <documentation>Set_Get current store view</documentation> - <input message="typens:catalogCategoryCurrentStoreRequest"/> - <output message="typens:catalogCategoryCurrentStoreResponse"/> - </operation> - <operation name="catalogCategoryTree"> - <documentation>Retrieve hierarchical tree of categories.</documentation> - <input message="typens:catalogCategoryTreeRequest"/> - <output message="typens:catalogCategoryTreeResponse"/> - </operation> - <operation name="catalogCategoryLevel"> - <documentation>Retrieve hierarchical tree of categories.</documentation> - <input message="typens:catalogCategoryLevelRequest"/> - <output message="typens:catalogCategoryLevelResponse"/> - </operation> - <operation name="catalogCategoryInfo"> - <documentation>Retrieve hierarchical tree of categories.</documentation> - <input message="typens:catalogCategoryInfoRequest"/> - <output message="typens:catalogCategoryInfoResponse"/> - </operation> - <operation name="catalogCategoryCreate"> - <documentation>Create new category and return its id.</documentation> - <input message="typens:catalogCategoryCreateRequest"/> - <output message="typens:catalogCategoryCreateResponse"/> - </operation> - <operation name="catalogCategoryUpdate"> - <documentation>Update category</documentation> - <input message="typens:catalogCategoryUpdateRequest"/> - <output message="typens:catalogCategoryUpdateResponse"/> - </operation> - <operation name="catalogCategoryMove"> - <documentation>Move category in tree</documentation> - <input message="typens:catalogCategoryMoveRequest"/> - <output message="typens:catalogCategoryMoveResponse"/> - </operation> - <operation name="catalogCategoryDelete"> - <documentation>Delete category</documentation> - <input message="typens:catalogCategoryDeleteRequest"/> - <output message="typens:catalogCategoryDeleteResponse"/> - </operation> - <operation name="catalogCategoryAssignedProducts"> - <documentation>Retrieve list of assigned products</documentation> - <input message="typens:catalogCategoryAssignedProductsRequest"/> - <output message="typens:catalogCategoryAssignedProductsResponse"/> - </operation> - <operation name="catalogCategoryAssignProduct"> - <documentation>Assign product to category</documentation> - <input message="typens:catalogCategoryAssignProductRequest"/> - <output message="typens:catalogCategoryAssignProductResponse"/> - </operation> - <operation name="catalogCategoryUpdateProduct"> - <documentation>Update assigned product</documentation> - <input message="typens:catalogCategoryUpdateProductRequest"/> - <output message="typens:catalogCategoryUpdateProductResponse"/> - </operation> - <operation name="catalogCategoryRemoveProduct"> - <documentation>Remove product assignment from category</documentation> - <input message="typens:catalogCategoryRemoveProductRequest"/> - <output message="typens:catalogCategoryRemoveProductResponse"/> - </operation> - <operation name="catalogCategoryAttributeCurrentStore"> - <documentation>Set/Get current store view</documentation> - <input message="typens:catalogCategoryAttributeCurrentStoreRequest"/> - <output message="typens:catalogCategoryAttributeCurrentStoreResponse"/> - </operation> - <operation name="catalogCategoryAttributeList"> - <documentation>Retrieve category attributes</documentation> - <input message="typens:catalogCategoryAttributeListRequest"/> - <output message="typens:catalogCategoryAttributeListResponse"/> - </operation> - <operation name="catalogCategoryAttributeOptions"> - <documentation>Retrieve attribute options</documentation> - <input message="typens:catalogCategoryAttributeOptionsRequest"/> - <output message="typens:catalogCategoryAttributeOptionsResponse"/> - </operation> - <operation name="catalogProductCurrentStore"> - <documentation>Set/Get current store view</documentation> - <input message="typens:catalogProductCurrentStoreRequest"/> - <output message="typens:catalogProductCurrentStoreResponse"/> - </operation> - <operation name="catalogProductList"> - <documentation>Retrieve products list by filters</documentation> - <input message="typens:catalogProductListRequest"/> - <output message="typens:catalogProductListResponse"/> - </operation> - <operation name="catalogProductInfo"> - <documentation>Retrieve product</documentation> - <input message="typens:catalogProductInfoRequest"/> - <output message="typens:catalogProductInfoResponse"/> - </operation> - <operation name="catalogProductCreate"> - <documentation>Create new product and return product id</documentation> - <input message="typens:catalogProductCreateRequest"/> - <output message="typens:catalogProductCreateResponse"/> - </operation> - <operation name="catalogProductUpdate"> - <documentation>Update product</documentation> - <input message="typens:catalogProductUpdateRequest"/> - <output message="typens:catalogProductUpdateResponse"/> - </operation> - <operation name="catalogProductSetSpecialPrice"> - <documentation>Update product special price</documentation> - <input message="typens:catalogProductSetSpecialPriceRequest"/> - <output message="typens:catalogProductSetSpecialPriceResponse"/> - </operation> - <operation name="catalogProductGetSpecialPrice"> - <documentation>Get product special price data</documentation> - <input message="typens:catalogProductGetSpecialPriceRequest"/> - <output message="typens:catalogProductGetSpecialPriceResponse"/> - </operation> - <operation name="catalogProductDelete"> - <documentation>Delete product</documentation> - <input message="typens:catalogProductDeleteRequest"/> - <output message="typens:catalogProductDeleteResponse"/> - </operation> - <operation name="catalogProductAttributeCurrentStore"> - <documentation>Set/Get current store view</documentation> - <input message="typens:catalogProductAttributeCurrentStoreRequest"/> - <output message="typens:catalogProductAttributeCurrentStoreResponse"/> - </operation> - <operation name="catalogProductListOfAdditionalAttributes"> - <documentation>Get list of additional attributes which are not in default create/update list</documentation> - <input message="typens:catalogProductListOfAdditionalAttributesRequest"/> - <output message="typens:catalogProductListOfAdditionalAttributesResponse"/> - </operation> - <operation name="catalogProductAttributeList"> - <documentation>Retrieve attribute list</documentation> - <input message="typens:catalogProductAttributeListRequest"/> - <output message="typens:catalogProductAttributeListResponse"/> - </operation> - <operation name="catalogProductAttributeOptions"> - <documentation>Retrieve attribute options</documentation> - <input message="typens:catalogProductAttributeOptionsRequest"/> - <output message="typens:catalogProductAttributeOptionsResponse"/> - </operation> - <operation name="catalogProductAttributeSetCreate"> - <documentation>Create product attribute set based on another set</documentation> - <input message="typens:catalogProductAttributeSetCreateRequest"/> - <output message="typens:catalogProductAttributeSetCreateResponse"/> - </operation> - <operation name="catalogProductAttributeSetRemove"> - <documentation>Remove product attribute set</documentation> - <input message="typens:catalogProductAttributeSetRemoveRequest"/> - <output message="typens:catalogProductAttributeSetRemoveResponse"/> - </operation> - <operation name="catalogProductAttributeSetList"> - <documentation>Retrieve product attribute sets</documentation> - <input message="typens:catalogProductAttributeSetListRequest"/> - <output message="typens:catalogProductAttributeSetListResponse"/> - </operation> - <operation name="catalogProductAttributeSetAttributeAdd"> - <documentation>Add attribute into attribute set</documentation> - <input message="typens:catalogProductAttributeSetAttributeAddRequest"/> - <output message="typens:catalogProductAttributeSetAttributeAddResponse"/> - </operation> - <operation name="catalogProductAttributeSetAttributeRemove"> - <documentation>Remove attribute from attribute set</documentation> - <input message="typens:catalogProductAttributeSetAttributeRemoveRequest"/> - <output message="typens:catalogProductAttributeSetAttributeRemoveResponse"/> - </operation> - <operation name="catalogProductAttributeSetGroupAdd"> - <documentation>Create group within existing attribute set</documentation> - <input message="typens:catalogProductAttributeSetGroupAddRequest"/> - <output message="typens:catalogProductAttributeSetGroupAddResponse"/> - </operation> - <operation name="catalogProductAttributeSetGroupRename"> - <documentation>Rename existing group</documentation> - <input message="typens:catalogProductAttributeSetGroupRenameRequest"/> - <output message="typens:catalogProductAttributeSetGroupRenameResponse"/> - </operation> - <operation name="catalogProductAttributeSetGroupRemove"> - <documentation>Remove group from attribute set</documentation> - <input message="typens:catalogProductAttributeSetGroupRemoveRequest"/> - <output message="typens:catalogProductAttributeSetGroupRemoveResponse"/> - </operation> - <operation name="catalogProductAttributeTypes"> - <documentation>Get list of possible attribute types</documentation> - <input message="typens:catalogProductAttributeTypesRequest"/> - <output message="typens:catalogProductAttributeTypesResponse"/> - </operation> - <operation name="catalogProductAttributeCreate"> - <documentation>Create new attribute</documentation> - <input message="typens:catalogProductAttributeCreateRequest"/> - <output message="typens:catalogProductAttributeCreateResponse"/> - </operation> - <operation name="catalogProductAttributeRemove"> - <documentation>Delete attribute</documentation> - <input message="typens:catalogProductAttributeRemoveRequest"/> - <output message="typens:catalogProductAttributeRemoveResponse"/> - </operation> - <operation name="catalogProductAttributeInfo"> - <documentation>Get full information about attribute with list of options</documentation> - <input message="typens:catalogProductAttributeInfoRequest"/> - <output message="typens:catalogProductAttributeInfoResponse"/> - </operation> - <operation name="catalogProductAttributeUpdate"> - <documentation>Update attribute</documentation> - <input message="typens:catalogProductAttributeUpdateRequest"/> - <output message="typens:catalogProductAttributeUpdateResponse"/> - </operation> - <operation name="catalogProductAttributeAddOption"> - <documentation>Add option to attribute</documentation> - <input message="typens:catalogProductAttributeAddOptionRequest"/> - <output message="typens:catalogProductAttributeAddOptionResponse"/> - </operation> - <operation name="catalogProductAttributeRemoveOption"> - <documentation>Remove option from attribute</documentation> - <input message="typens:catalogProductAttributeRemoveOptionRequest"/> - <output message="typens:catalogProductAttributeRemoveOptionResponse"/> - </operation> - <operation name="catalogProductTypeList"> - <documentation>Retrieve product types</documentation> - <input message="typens:catalogProductTypeListRequest"/> - <output message="typens:catalogProductTypeListResponse"/> - </operation> - <operation name="catalogProductAttributeTierPriceInfo"> - <documentation>Retrieve product tier prices</documentation> - <input message="typens:catalogProductAttributeTierPriceInfoRequest"/> - <output message="typens:catalogProductAttributeTierPriceInfoResponse"/> - </operation> - <operation name="catalogProductAttributeTierPriceUpdate"> - <documentation>Update product tier prices</documentation> - <input message="typens:catalogProductAttributeTierPriceUpdateRequest"/> - <output message="typens:catalogProductAttributeTierPriceUpdateResponse"/> - </operation> - <operation name="catalogProductAttributeMediaCurrentStore"> - <documentation>Set/Get current store view</documentation> - <input message="typens:catalogProductAttributeMediaCurrentStoreRequest"/> - <output message="typens:catalogProductAttributeMediaCurrentStoreResponse"/> - </operation> - <operation name="catalogProductAttributeMediaList"> - <documentation>Retrieve product image list</documentation> - <input message="typens:catalogProductAttributeMediaListRequest"/> - <output message="typens:catalogProductAttributeMediaListResponse"/> - </operation> - <operation name="catalogProductAttributeMediaInfo"> - <documentation>Retrieve product image data</documentation> - <input message="typens:catalogProductAttributeMediaInfoRequest"/> - <output message="typens:catalogProductAttributeMediaInfoResponse"/> - </operation> - <operation name="catalogProductAttributeMediaTypes"> - <documentation>Retrieve product image types</documentation> - <input message="typens:catalogProductAttributeMediaTypesRequest"/> - <output message="typens:catalogProductAttributeMediaTypesResponse"/> - </operation> - <operation name="catalogProductAttributeMediaCreate"> - <documentation>Upload new product image</documentation> - <input message="typens:catalogProductAttributeMediaCreateRequest"/> - <output message="typens:catalogProductAttributeMediaCreateResponse"/> - </operation> - <operation name="catalogProductAttributeMediaUpdate"> - <documentation>Update product image</documentation> - <input message="typens:catalogProductAttributeMediaUpdateRequest"/> - <output message="typens:catalogProductAttributeMediaUpdateResponse"/> - </operation> - <operation name="catalogProductAttributeMediaRemove"> - <documentation>Remove product image</documentation> - <input message="typens:catalogProductAttributeMediaRemoveRequest"/> - <output message="typens:catalogProductAttributeMediaRemoveResponse"/> - </operation> - <operation name="catalogProductLinkList"> - <documentation>Retrieve linked products</documentation> - <input message="typens:catalogProductLinkListRequest"/> - <output message="typens:catalogProductLinkListResponse"/> - </operation> - <operation name="catalogProductLinkAssign"> - <documentation>Assign product link</documentation> - <input message="typens:catalogProductLinkAssignRequest"/> - <output message="typens:catalogProductLinkAssignResponse"/> - </operation> - <operation name="catalogProductLinkUpdate"> - <documentation>Update product link</documentation> - <input message="typens:catalogProductLinkUpdateRequest"/> - <output message="typens:catalogProductLinkUpdateResponse"/> - </operation> - <operation name="catalogProductLinkRemove"> - <documentation>Remove product link</documentation> - <input message="typens:catalogProductLinkRemoveRequest"/> - <output message="typens:catalogProductLinkRemoveResponse"/> - </operation> - <operation name="catalogProductLinkTypes"> - <documentation>Retrieve product link types</documentation> - <input message="typens:catalogProductLinkTypesRequest"/> - <output message="typens:catalogProductLinkTypesResponse"/> - </operation> - <operation name="catalogProductLinkAttributes"> - <documentation>Retrieve product link type attributes</documentation> - <input message="typens:catalogProductLinkAttributesRequest"/> - <output message="typens:catalogProductLinkAttributesResponse"/> - </operation> - <operation name="catalogProductCustomOptionAdd"> - <documentation>Add new custom option into product</documentation> - <input message="typens:catalogProductCustomOptionAddRequest"/> - <output message="typens:catalogProductCustomOptionAddResponse"/> - </operation> - <operation name="catalogProductCustomOptionUpdate"> - <documentation>Update product custom option</documentation> - <input message="typens:catalogProductCustomOptionUpdateRequest"/> - <output message="typens:catalogProductCustomOptionUpdateResponse"/> - </operation> - <operation name="catalogProductCustomOptionTypes"> - <documentation>Get list of available custom option types</documentation> - <input message="typens:catalogProductCustomOptionTypesRequest"/> - <output message="typens:catalogProductCustomOptionTypesResponse"/> - </operation> - <operation name="catalogProductCustomOptionInfo"> - <documentation>Get full information about custom option in product</documentation> - <input message="typens:catalogProductCustomOptionInfoRequest"/> - <output message="typens:catalogProductCustomOptionInfoResponse"/> - </operation> - <operation name="catalogProductCustomOptionList"> - <documentation>Retrieve list of product custom options</documentation> - <input message="typens:catalogProductCustomOptionListRequest"/> - <output message="typens:catalogProductCustomOptionListResponse"/> - </operation> - <operation name="catalogProductCustomOptionRemove"> - <documentation>Remove custom option</documentation> - <input message="typens:catalogProductCustomOptionRemoveRequest"/> - <output message="typens:catalogProductCustomOptionRemoveResponse"/> - </operation> - <operation name="catalogProductCustomOptionValueInfo"> - <documentation>Retrieve custom option value info</documentation> - <input message="typens:catalogProductCustomOptionValueInfoRequest"/> - <output message="typens:catalogProductCustomOptionValueInfoResponse"/> - </operation> - <operation name="catalogProductCustomOptionValueList"> - <documentation>Retrieve custom option values list</documentation> - <input message="typens:catalogProductCustomOptionValueListRequest"/> - <output message="typens:catalogProductCustomOptionValueListResponse"/> - </operation> - <operation name="catalogProductCustomOptionValueAdd"> - <documentation>Add new custom option values</documentation> - <input message="typens:catalogProductCustomOptionValueAddRequest"/> - <output message="typens:catalogProductCustomOptionValueAddResponse"/> - </operation> - <operation name="catalogProductCustomOptionValueUpdate"> - <documentation>Update custom option value</documentation> - <input message="typens:catalogProductCustomOptionValueUpdateRequest"/> - <output message="typens:catalogProductCustomOptionValueUpdateResponse"/> - </operation> - <operation name="catalogProductCustomOptionValueRemove"> - <documentation>Remove value from custom option</documentation> - <input message="typens:catalogProductCustomOptionValueRemoveRequest"/> - <output message="typens:catalogProductCustomOptionValueRemoveResponse"/> - </operation> - </portType> - <binding name="{{var wsdl.handler}}Binding" type="typens:{{var wsdl.handler}}PortType"> - <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/> - <operation name="catalogCategoryCurrentStore"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogCategoryTree"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogCategoryLevel"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogCategoryInfo"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogCategoryCreate"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogCategoryUpdate"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogCategoryMove"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogCategoryDelete"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogCategoryAssignedProducts"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogCategoryAssignProduct"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogCategoryUpdateProduct"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogCategoryRemoveProduct"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductCurrentStore"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductListOfAdditionalAttributes"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductList"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductInfo"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductCreate"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductUpdate"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductSetSpecialPrice"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductGetSpecialPrice"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductDelete"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductAttributeCurrentStore"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductAttributeSetCreate"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductAttributeList"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductAttributeOptions"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductAttributeSetRemove"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductAttributeSetList"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductAttributeSetAttributeAdd"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductAttributeSetAttributeRemove"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductAttributeSetGroupAdd"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductAttributeSetGroupRename"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductAttributeSetGroupRemove"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductAttributeTypes"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductAttributeCreate"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogCategoryAttributeCurrentStore"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductAttributeMediaCurrentStore"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductAttributeRemove"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductAttributeInfo"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductAttributeUpdate"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductAttributeAddOption"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductAttributeRemoveOption"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductTypeList"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductAttributeTierPriceInfo"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductAttributeTierPriceUpdate"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogCategoryAttributeList"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogCategoryAttributeOptions"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductAttributeMediaList"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductAttributeMediaInfo"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductAttributeMediaTypes"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductAttributeMediaCreate"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductAttributeMediaUpdate"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductAttributeMediaRemove"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductLinkList"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductLinkAssign"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductLinkUpdate"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductLinkRemove"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductLinkTypes"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductLinkAttributes"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductCustomOptionAdd"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductCustomOptionUpdate"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductCustomOptionInfo"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductCustomOptionTypes"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductCustomOptionValueInfo"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductCustomOptionValueList"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductCustomOptionValueAdd"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductCustomOptionValueUpdate"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductCustomOptionValueRemove"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductCustomOptionList"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductCustomOptionRemove"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - </binding> - <service name="{{var wsdl.name}}Service"> - <port name="{{var wsdl.handler}}Port" binding="typens:{{var wsdl.handler}}Binding"> - <soap:address location="{{var wsdl.url}}"/> - </port> - </service> -</definitions> diff --git a/app/code/core/Mage/Catalog/etc/wsi.xml b/app/code/core/Mage/Catalog/etc/wsi.xml deleted file mode 100644 index d3918cf476bfd67061eaca241af954da4fd5aef8..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Catalog/etc/wsi.xml +++ /dev/null @@ -1,2772 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<wsdl:definitions xmlns:typens="urn:{{var wsdl.name}}" - xmlns:xsd="http://www.w3.org/2001/XMLSchema" - xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" - xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" - xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" - name="{{var wsdl.name}}" - targetNamespace="urn:{{var wsdl.name}}"> - <wsdl:types> - <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:{{var wsdl.name}}"> - <xsd:complexType name="catalogProductEntityArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:catalogProductEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductEntity"> - <xsd:sequence> - <xsd:element name="product_id" type="xsd:string" /> - <xsd:element name="sku" type="xsd:string" /> - <xsd:element name="name" type="xsd:string" /> - <xsd:element name="set" type="xsd:string" /> - <xsd:element name="type" type="xsd:string" /> - <xsd:element name="category_ids" type="typens:ArrayOfString" /> - <xsd:element name="website_ids" type="typens:ArrayOfString" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductRequestAttributes"> - <xsd:sequence> - <xsd:element name="attributes" type="typens:ArrayOfString" minOccurs="0" /> - <xsd:element name="additional_attributes" type="typens:ArrayOfString" minOccurs="0" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductReturnEntity"> - <xsd:sequence> - <xsd:element name="product_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="sku" type="xsd:string" minOccurs="0" /> - <xsd:element name="set" type="xsd:string" minOccurs="0" /> - <xsd:element name="type" type="xsd:string" minOccurs="0" /> - <xsd:element name="categories" type="typens:ArrayOfString" minOccurs="0" /> - <xsd:element name="websites" type="typens:ArrayOfString" minOccurs="0" /> - <xsd:element name="created_at" type="xsd:string" minOccurs="0" /> - <xsd:element name="updated_at" type="xsd:string" minOccurs="0" /> - <xsd:element name="type_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="name" type="xsd:string" minOccurs="0" /> - <xsd:element name="description" type="xsd:string" minOccurs="0" /> - <xsd:element name="short_description" type="xsd:string" minOccurs="0" /> - <xsd:element name="weight" type="xsd:string" minOccurs="0" /> - <xsd:element name="status" type="xsd:string" minOccurs="0" /> - <xsd:element name="url_key" type="xsd:string" minOccurs="0" /> - <xsd:element name="url_path" type="xsd:string" minOccurs="0" /> - <xsd:element name="visibility" type="xsd:string" minOccurs="0" /> - <xsd:element name="category_ids" type="typens:ArrayOfString" minOccurs="0" /> - <xsd:element name="website_ids" type="typens:ArrayOfString" minOccurs="0" /> - <xsd:element name="has_options" type="xsd:string" minOccurs="0" /> - <xsd:element name="gift_message_available" type="xsd:string" minOccurs="0" /> - <xsd:element name="price" type="xsd:string" minOccurs="0" /> - <xsd:element name="special_price" type="xsd:string" minOccurs="0" /> - <xsd:element name="special_from_date" type="xsd:string" minOccurs="0" /> - <xsd:element name="special_to_date" type="xsd:string" minOccurs="0" /> - <xsd:element name="tax_class_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="tier_price" type="typens:catalogProductTierPriceEntityArray" minOccurs="0" /> - <xsd:element name="meta_title" type="xsd:string" minOccurs="0" /> - <xsd:element name="meta_keyword" type="xsd:string" minOccurs="0" /> - <xsd:element name="meta_description" type="xsd:string" minOccurs="0" /> - <xsd:element name="custom_design" type="xsd:string" minOccurs="0" /> - <xsd:element name="custom_layout_update" type="xsd:string" minOccurs="0" /> - <xsd:element name="options_container" type="xsd:string" minOccurs="0" /> - <xsd:element name="additional_attributes" type="typens:associativeArray" minOccurs="0" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductCreateEntity"> - <xsd:sequence> - <xsd:element name="categories" type="typens:ArrayOfString" minOccurs="0" /> - <xsd:element name="websites" type="typens:ArrayOfString" minOccurs="0" /> - <xsd:element name="name" type="xsd:string" minOccurs="0" /> - <xsd:element name="description" type="xsd:string" minOccurs="0" /> - <xsd:element name="short_description" type="xsd:string" minOccurs="0" /> - <xsd:element name="weight" type="xsd:string" minOccurs="0" /> - <xsd:element name="status" type="xsd:string" minOccurs="0" /> - <xsd:element name="url_key" type="xsd:string" minOccurs="0" /> - <xsd:element name="url_path" type="xsd:string" minOccurs="0" /> - <xsd:element name="visibility" type="xsd:string" minOccurs="0" /> - <xsd:element name="category_ids" type="typens:ArrayOfString" minOccurs="0" /> - <xsd:element name="website_ids" type="typens:ArrayOfString" minOccurs="0" /> - <xsd:element name="has_options" type="xsd:string" minOccurs="0" /> - <xsd:element name="gift_message_available" type="xsd:string" minOccurs="0" /> - <xsd:element name="price" type="xsd:string" minOccurs="0" /> - <xsd:element name="special_price" type="xsd:string" minOccurs="0" /> - <xsd:element name="special_from_date" type="xsd:string" minOccurs="0" /> - <xsd:element name="special_to_date" type="xsd:string" minOccurs="0" /> - <xsd:element name="tax_class_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="tier_price" type="typens:catalogProductTierPriceEntityArray" minOccurs="0" /> - <xsd:element name="meta_title" type="xsd:string" minOccurs="0" /> - <xsd:element name="meta_keyword" type="xsd:string" minOccurs="0" /> - <xsd:element name="meta_description" type="xsd:string" minOccurs="0" /> - <xsd:element name="custom_design" type="xsd:string" minOccurs="0" /> - <xsd:element name="custom_layout_update" type="xsd:string" minOccurs="0" /> - <xsd:element name="options_container" type="xsd:string" minOccurs="0" /> - <xsd:element name="additional_attributes" type="typens:associativeArray" minOccurs="0" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductAttributeSetEntity"> - <xsd:sequence> - <xsd:element name="set_id" type="xsd:int" minOccurs="0" /> - <xsd:element name="name" type="xsd:string" minOccurs="0" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductAttributeSetEntityArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:catalogProductAttributeSetEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductTypeEntity"> - <xsd:sequence> - <xsd:element name="type" type="xsd:string" minOccurs="0" /> - <xsd:element name="label" type="xsd:string" minOccurs="0" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductTypeEntityArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:catalogProductTypeEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductTierPriceEntity"> - <xsd:sequence> - <xsd:element name="customer_group_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="website" type="xsd:string" minOccurs="0" /> - <xsd:element name="qty" type="xsd:int" minOccurs="0" /> - <xsd:element name="price" type="xsd:double" minOccurs="0" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductTierPriceEntityArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:catalogProductTierPriceEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="ArrayOfCatalogCategoryEntities"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:catalogCategoryEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogCategoryEntity"> - <xsd:sequence> - <xsd:element name="category_id" type="xsd:int" /> - <xsd:element name="parent_id" type="xsd:int" /> - <xsd:element name="name" type="xsd:string" /> - <xsd:element name="is_active" type="xsd:int" /> - <xsd:element name="position" type="xsd:int" /> - <xsd:element name="level" type="xsd:int" /> - <xsd:element name="children" type="typens:ArrayOfCatalogCategoryEntities" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogCategoryEntityNoChildren"> - <xsd:sequence> - <xsd:element name="category_id" type="xsd:int" /> - <xsd:element name="parent_id" type="xsd:int" /> - <xsd:element name="name" type="xsd:string" /> - <xsd:element name="is_active" type="xsd:int" /> - <xsd:element name="position" type="xsd:int" /> - <xsd:element name="level" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="ArrayOfCatalogCategoryEntitiesNoChildren"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:catalogCategoryEntityNoChildren" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogCategoryTree"> - <xsd:sequence> - <xsd:element name="category_id" type="xsd:int" /> - <xsd:element name="parent_id" type="xsd:int" /> - <xsd:element name="name" type="xsd:string" /> - <xsd:element name="position" type="xsd:int" /> - <xsd:element name="level" type="xsd:int" /> - <xsd:element name="children" type="typens:ArrayOfCatalogCategoryEntities" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogCategoryEntityCreate"> - <xsd:sequence> - <xsd:element name="name" type="xsd:string" minOccurs="0" /> - <xsd:element name="is_active" type="xsd:int" minOccurs="0" /> - <xsd:element name="position" type="xsd:int" minOccurs="0" /> - <xsd:element name="available_sort_by" type="typens:ArrayOfString" minOccurs="0" /> - <xsd:element name="custom_design" type="xsd:string" minOccurs="0" /> - <xsd:element name="custom_design_apply" type="xsd:int" minOccurs="0" /> - <xsd:element name="custom_design_from" type="xsd:string" minOccurs="0" /> - <xsd:element name="custom_design_to" type="xsd:string" minOccurs="0" /> - <xsd:element name="custom_layout_update" type="xsd:string" minOccurs="0" /> - <xsd:element name="default_sort_by" type="xsd:string" minOccurs="0" /> - <xsd:element name="description" type="xsd:string" minOccurs="0" /> - <xsd:element name="display_mode" type="xsd:string" minOccurs="0" /> - <xsd:element name="is_anchor" type="xsd:int" minOccurs="0" /> - <xsd:element name="landing_page" type="xsd:int" minOccurs="0" /> - <xsd:element name="meta_description" type="xsd:string" minOccurs="0" /> - <xsd:element name="meta_keywords" type="xsd:string" minOccurs="0" /> - <xsd:element name="meta_title" type="xsd:string" minOccurs="0" /> - <xsd:element name="page_layout" type="xsd:string" minOccurs="0" /> - <xsd:element name="url_key" type="xsd:string" minOccurs="0" /> - <xsd:element name="include_in_menu" type="xsd:int" minOccurs="0" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogCategoryInfo"> - <xsd:sequence> - <xsd:element name="category_id" type="xsd:string" /> - <xsd:element name="is_active" type="xsd:int" /> - <xsd:element name="position" type="xsd:string" /> - <xsd:element name="level" type="xsd:string" /> - <xsd:element name="parent_id" type="xsd:string" /> - <xsd:element name="all_children" type="xsd:string" /> - <xsd:element name="children" type="xsd:string" /> - <xsd:element name="created_at" type="xsd:string" minOccurs="0" /> - <xsd:element name="updated_at" type="xsd:string" minOccurs="0" /> - <xsd:element name="name" type="xsd:string" minOccurs="0" /> - <xsd:element name="url_key" type="xsd:string" minOccurs="0" /> - <xsd:element name="description" type="xsd:string" minOccurs="0" /> - <xsd:element name="meta_title" type="xsd:string" minOccurs="0" /> - <xsd:element name="meta_keywords" type="xsd:string" minOccurs="0" /> - <xsd:element name="meta_description" type="xsd:string" minOccurs="0" /> - <xsd:element name="path" type="xsd:string" minOccurs="0" /> - <xsd:element name="url_path" type="xsd:string" minOccurs="0" /> - <xsd:element name="children_count" type="xsd:int" minOccurs="0" /> - <xsd:element name="display_mode" type="xsd:string" minOccurs="0" /> - <xsd:element name="is_anchor" type="xsd:int" minOccurs="0" /> - <xsd:element name="available_sort_by" type="typens:ArrayOfString" minOccurs="0" /> - <xsd:element name="custom_design" type="xsd:string" minOccurs="0" /> - <xsd:element name="custom_design_apply" type="xsd:string" minOccurs="0" /> - <xsd:element name="custom_design_from" type="xsd:string" minOccurs="0" /> - <xsd:element name="custom_design_to" type="xsd:string" minOccurs="0" /> - <xsd:element name="page_layout" type="xsd:string" minOccurs="0" /> - <xsd:element name="custom_layout_update" type="xsd:string" minOccurs="0" /> - <xsd:element name="default_sort_by" type="xsd:string" minOccurs="0" /> - <xsd:element name="landing_page" type="xsd:int" minOccurs="0" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogAssignedProduct"> - <xsd:sequence> - <xsd:element name="product_id" type="xsd:int" /> - <xsd:element name="type" type="xsd:string" /> - <xsd:element name="set" type="xsd:int" /> - <xsd:element name="sku" type="xsd:string" /> - <xsd:element name="position" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogAssignedProductArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:catalogAssignedProduct" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogAttributeEntity"> - <xsd:sequence> - <xsd:element name="attribute_id" type="xsd:int" minOccurs="0" /> - <xsd:element name="code" type="xsd:string" minOccurs="0" /> - <xsd:element name="type" type="xsd:string" minOccurs="0" /> - <xsd:element name="required" type="xsd:string" minOccurs="0" /> - <xsd:element name="scope" type="xsd:string" minOccurs="0" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogAttributeEntityArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:catalogAttributeEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogAttributeOptionEntity"> - <xsd:sequence> - <xsd:element name="label" type="xsd:string" /> - <xsd:element name="value" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogAttributeOptionEntityArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:catalogAttributeOptionEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductImageEntity"> - <xsd:sequence> - <xsd:element name="file" type="xsd:string" /> - <xsd:element name="label" type="xsd:string" /> - <xsd:element name="position" type="xsd:string" /> - <xsd:element name="exclude" type="xsd:string" /> - <xsd:element name="url" type="xsd:string" /> - <xsd:element name="types" type="typens:ArrayOfString" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductImageEntityArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:catalogProductImageEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductAttributeMediaTypeEntity"> - <xsd:sequence> - <xsd:element name="code" type="xsd:string" /> - <xsd:element name="scope" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductAttributeMediaTypeEntityArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:catalogProductAttributeMediaTypeEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductImageFileEntity"> - <xsd:sequence> - <xsd:element name="content" type="xsd:string" /> - <xsd:element name="mime" type="xsd:string" /> - <xsd:element name="name" type="xsd:string" minOccurs="0" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductAttributeMediaCreateEntity"> - <xsd:sequence> - <xsd:element name="file" type="typens:catalogProductImageFileEntity" minOccurs="0" /> - <xsd:element name="label" type="xsd:string" minOccurs="0" /> - <xsd:element name="position" type="xsd:string" minOccurs="0" /> - <xsd:element name="types" type="typens:ArrayOfString" minOccurs="0" /> - <xsd:element name="exclude" type="xsd:string" minOccurs="0" /> - <xsd:element name="remove" type="xsd:string" minOccurs="0" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductLinkEntity"> - <xsd:sequence> - <xsd:element name="product_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="type" type="xsd:string" minOccurs="0" /> - <xsd:element name="set" type="xsd:string" minOccurs="0" /> - <xsd:element name="sku" type="xsd:string" minOccurs="0" /> - <xsd:element name="position" type="xsd:string" minOccurs="0" /> - <xsd:element name="qty" type="xsd:string" minOccurs="0" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductLinkEntityArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:catalogProductLinkEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductLinkAttributeEntity"> - <xsd:sequence> - <xsd:element name="code" type="xsd:string" minOccurs="0" /> - <xsd:element name="type" type="xsd:string" minOccurs="0" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductLinkAttributeEntityArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:catalogProductLinkAttributeEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductAttributeFrontendLabelEntity"> - <xsd:sequence> - <element name="store_id" type="xsd:string" /> - <element name="label" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductAttributeFrontendLabelArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:catalogProductAttributeFrontendLabelEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductAttributeEntityToCreate"> - <xsd:sequence> - <xsd:element name="attribute_code" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="frontend_input" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="scope" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="default_value" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="is_unique" type="xsd:int" minOccurs="0" maxOccurs="1" /> - <xsd:element name="is_required" type="xsd:int" minOccurs="0" maxOccurs="1" /> - <xsd:element name="apply_to" type="typens:ArrayOfString" minOccurs="0" maxOccurs="1" /> - <xsd:element name="is_configurable" type="xsd:int" minOccurs="0" maxOccurs="1" /> - <xsd:element name="is_searchable" type="xsd:int" minOccurs="0" maxOccurs="1" /> - <xsd:element name="is_visible_in_advanced_search" type="xsd:int" minOccurs="0" maxOccurs="1" /> - <xsd:element name="is_comparable" type="xsd:int" minOccurs="0" maxOccurs="1" /> - <xsd:element name="is_used_for_promo_rules" type="xsd:int" minOccurs="0" maxOccurs="1" /> - <xsd:element name="is_visible_on_front" type="xsd:int" minOccurs="0" maxOccurs="1" /> - <xsd:element name="used_in_product_listing" type="xsd:int" minOccurs="0" maxOccurs="1" /> - <xsd:element name="additional_fields" type="typens:associativeArray" minOccurs="0" maxOccurs="1" /> - <xsd:element name="frontend_label" type="typens:catalogProductAttributeFrontendLabelArray" minOccurs="0" maxOccurs="1" /> - </xsd:sequence> - </xsd:complexType> - - <xsd:complexType name="catalogProductCustomOptionAdditionalFieldsEntity"> - <xsd:sequence> - <xsd:element name="title" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="price" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="price_type" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="sku" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="max_characters" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="sort_order" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="file_extension" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="image_size_x" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="image_size_y" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="value_id" type="xsd:string" minOccurs="0" maxOccurs="1" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductCustomOptionAdditionalFieldsArray"> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="unbounded" name="complexObjectArray" type="typens:catalogProductCustomOptionAdditionalFieldsEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductCustomOptionToAdd"> - <xsd:sequence> - <xsd:element name="title" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="type" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="sort_order" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="is_require" type="xsd:int" minOccurs="0" maxOccurs="1" /> - <xsd:element name="additional_fields" type="typens:catalogProductCustomOptionAdditionalFieldsArray" minOccurs="1" maxOccurs="1" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductCustomOptionToUpdate"> - <xsd:sequence> - <xsd:element name="title" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="type" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="sort_order" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="is_require" type="xsd:int" minOccurs="0" maxOccurs="1" /> - <xsd:element name="additional_fields" type="typens:catalogProductCustomOptionAdditionalFieldsArray" minOccurs="0" maxOccurs="1" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductCustomOptionInfoEntity"> - <xsd:sequence> - <xsd:element name="title" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="type" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="sort_order" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="is_require" type="xsd:int" minOccurs="1" maxOccurs="1" /> - <xsd:element name="additional_fields" type="typens:catalogProductCustomOptionAdditionalFieldsArray" minOccurs="1" maxOccurs="1" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductCustomOptionListEntity"> - <xsd:sequence> - <xsd:element name="option_id" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="title" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="type" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="sort_order" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="is_require" type="xsd:int" minOccurs="1" maxOccurs="1" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductCustomOptionListArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:catalogProductCustomOptionListEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductCustomOptionTypesEntity"> - <xsd:sequence> - <xsd:element name="label" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="value" type="xsd:string" minOccurs="1" maxOccurs="1" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductCustomOptionTypesArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:catalogProductCustomOptionTypesEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductCustomOptionValueInfoEntity"> - <xsd:sequence> - <xsd:element name="value_id" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="option_id" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="sku" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="sort_order" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="default_price" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="default_price_type" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="store_price" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="store_price_type" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="price" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="price_type" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="default_title" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="store_title" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="title" type="xsd:string" minOccurs="1" maxOccurs="1" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductCustomOptionValueListEntity"> - <xsd:sequence> - <xsd:element name="value_id" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="title" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="price" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="price_type" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="sku" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="sort_order" type="xsd:string" minOccurs="1" maxOccurs="1" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductCustomOptionValueListArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:catalogProductCustomOptionValueListEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductCustomOptionValueAddEntity"> - <xsd:sequence> - <xsd:element name="title" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="price" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="price_type" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="sku" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="sort_order" type="xsd:string" minOccurs="0" maxOccurs="1" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductCustomOptionValueAddArray"> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="unbounded" name="complexObjectArray" type="typens:catalogProductCustomOptionValueAddEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductCustomOptionValueUpdateEntity"> - <xsd:sequence> - <xsd:element name="title" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="price" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="price_type" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="sku" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="sort_order" type="xsd:string" minOccurs="0" maxOccurs="1" /> - </xsd:sequence> - </xsd:complexType> - <xsd:element name="catalogProductCurrentStoreRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductCurrentStoreResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductListRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="filters" type="typens:filters" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductListResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:catalogProductEntityArray" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductInfoRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="productId" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="attributes" type="typens:catalogProductRequestAttributes" /> - <xsd:element minOccurs="0" maxOccurs="1" name="identifierType" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductInfoResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:catalogProductReturnEntity" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductCreateRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="type" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="set" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="sku" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="productData" type="typens:catalogProductCreateEntity" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductCreateResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductUpdateRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="productId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="productData" type="typens:catalogProductCreateEntity" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="identifierType" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductUpdateResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:boolean" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductSetSpecialPriceRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="productId" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="specialPrice" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="fromDate" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="toDate" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductSetSpecialPriceResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductGetSpecialPriceRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="productId" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductGetSpecialPriceResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:catalogProductReturnEntity" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductDeleteRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="productId" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="identifierType" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductDeleteResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductAttributeCurrentStoreRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductAttributeCurrentStoreResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductAttributeListRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="setId" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductAttributeListResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:catalogAttributeEntityArray" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductAttributeOptionsRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="attributeId" type="xsd:int" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductAttributeOptionsResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:catalogAttributeOptionEntityArray" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductCustomOptionAddRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="productId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="data" type="typens:catalogProductCustomOptionToAdd" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductCustomOptionAddResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductCustomOptionUpdateRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="optionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="data" type="typens:catalogProductCustomOptionToUpdate" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductCustomOptionUpdateResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductCustomOptionTypesRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductCustomOptionTypesResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:catalogProductCustomOptionTypesArray" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductCustomOptionListRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="productId" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductCustomOptionListResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:catalogProductCustomOptionListArray" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductCustomOptionInfoRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="optionId" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductCustomOptionInfoResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:catalogProductCustomOptionInfoEntity" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductCustomOptionRemoveRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="optionId" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductCustomOptionRemoveResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductCustomOptionValueListRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="optionId" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductCustomOptionValueListResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:catalogProductCustomOptionValueListArray" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductCustomOptionValueInfoRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="valueId" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductCustomOptionValueInfoResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:catalogProductCustomOptionValueInfoEntity" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductCustomOptionValueAddRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="optionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="data" type="typens:catalogProductCustomOptionValueAddArray" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductCustomOptionValueAddResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductCustomOptionValueUpdateRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="valueId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="data" type="typens:catalogProductCustomOptionValueUpdateEntity" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductCustomOptionValueUpdateResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductCustomOptionValueRemoveRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="valueId" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductCustomOptionValueRemoveResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductAttributeSetCreateRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="attributeSetName" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="skeletonSetId" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductAttributeSetCreateResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductAttributeSetRemoveRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="attributeSetId" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="forceProductsRemove" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductAttributeSetRemoveResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductAttributeSetListRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductAttributeSetListResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:catalogProductAttributeSetEntityArray" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductAttributeSetAttributeAddRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="attributeId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="attributeSetId" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="attributeGroupId" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="sortOrder" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductAttributeSetAttributeAddResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductAttributeSetAttributeRemoveRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="attributeId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="attributeSetId" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductAttributeSetAttributeRemoveResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductAttributeSetGroupAddRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="attributeSetId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="groupName" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductAttributeSetGroupAddResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductAttributeSetGroupRenameRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="groupId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="groupName" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductAttributeSetGroupRenameResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductAttributeSetGroupRemoveRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="attributeGroupId" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductAttributeSetGroupRemoveResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductTypeListRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductTypeListResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:catalogProductTypeEntityArray" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductAttributeTierPriceInfoRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="productId" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="identifierType" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductAttributeTierPriceInfoResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:catalogProductTierPriceEntityArray" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductAttributeTierPriceUpdateRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="productId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="tierPrices" type="typens:catalogProductTierPriceEntityArray" /> - <xsd:element minOccurs="0" maxOccurs="1" name="identifierType" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductAttributeTierPriceUpdateResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductAttributeMediaCurrentStoreRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductAttributeMediaCurrentStoreResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductAttributeMediaListRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="productId" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="identifierType" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductAttributeMediaListResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:catalogProductImageEntityArray" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductAttributeMediaInfoRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="productId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="file" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="identifierType" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductAttributeMediaInfoResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:catalogProductImageEntity" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductAttributeMediaTypesRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="setId" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductAttributeMediaTypesResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:catalogProductAttributeMediaTypeEntityArray" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductAttributeMediaCreateRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="productId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="data" type="typens:catalogProductAttributeMediaCreateEntity" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="identifierType" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductAttributeMediaCreateResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductAttributeMediaUpdateRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="productId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="file" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="data" type="typens:catalogProductAttributeMediaCreateEntity" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="identifierType" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductAttributeMediaUpdateResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductAttributeMediaRemoveRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="productId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="file" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="identifierType" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductAttributeMediaRemoveResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductLinkListRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="type" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="productId" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="identifierType" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductLinkListResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:catalogProductLinkEntityArray" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductLinkAssignRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="type" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="productId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="linkedProductId" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="data" type="typens:catalogProductLinkEntity" /> - <xsd:element minOccurs="0" maxOccurs="1" name="identifierType" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductLinkAssignResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductLinkUpdateRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="type" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="productId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="linkedProductId" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="data" type="typens:catalogProductLinkEntity" /> - <xsd:element minOccurs="0" maxOccurs="1" name="identifierType" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductLinkUpdateResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductLinkRemoveRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="type" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="productId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="linkedProductId" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="identifierType" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductLinkRemoveResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductLinkTypesRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductLinkTypesResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:ArrayOfString" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductLinkAttributesRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="type" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductLinkAttributesResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:catalogProductLinkAttributeEntityArray" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogCategoryCurrentStoreRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogCategoryCurrentStoreResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogCategoryTreeRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="parentId" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogCategoryTreeResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:catalogCategoryTree" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogCategoryLevelRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="website" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="categoryId" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogCategoryLevelResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:ArrayOfCatalogCategoryEntitiesNoChildren" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogCategoryInfoRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="categoryId" type="xsd:int" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="attributes" type="typens:ArrayOfString" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogCategoryInfoResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:catalogCategoryInfo" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogCategoryCreateRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="parentId" type="xsd:int" /> - <xsd:element minOccurs="1" maxOccurs="1" name="categoryData" type="typens:catalogCategoryEntityCreate" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogCategoryCreateResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogCategoryUpdateRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="categoryId" type="xsd:int" /> - <xsd:element minOccurs="1" maxOccurs="1" name="categoryData" type="typens:catalogCategoryEntityCreate" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogCategoryUpdateResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:boolean" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogCategoryMoveRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="categoryId" type="xsd:int" /> - <xsd:element minOccurs="1" maxOccurs="1" name="parentId" type="xsd:int" /> - <xsd:element minOccurs="1" maxOccurs="1" name="afterId" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogCategoryMoveResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:boolean" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogCategoryDeleteRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="categoryId" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogCategoryDeleteResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:boolean" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogCategoryAssignedProductsRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="categoryId" type="xsd:int" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogCategoryAssignedProductsResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:catalogAssignedProductArray" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogCategoryAssignProductRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="categoryId" type="xsd:int" /> - <xsd:element minOccurs="1" maxOccurs="1" name="productId" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="position" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="identifierType" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogCategoryAssignProductResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:boolean" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogCategoryUpdateProductRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="categoryId" type="xsd:int" /> - <xsd:element minOccurs="1" maxOccurs="1" name="productId" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="position" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="identifierType" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogCategoryUpdateProductResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:boolean" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogCategoryRemoveProductRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="categoryId" type="xsd:int" /> - <xsd:element minOccurs="1" maxOccurs="1" name="productId" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="identifierType" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogCategoryRemoveProductResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:boolean" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogCategoryAttributeListRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogCategoryAttributeListResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:catalogAttributeEntityArray" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogCategoryAttributeOptionsRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="attributeId" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogCategoryAttributeOptionsResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:catalogAttributeOptionEntityArray" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogCategoryAttributeCurrentStoreRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogCategoryAttributeCurrentStoreResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductAttributeCreateRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="data" type="typens:catalogProductAttributeEntityToCreate" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductAttributeCreateResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - </xsd:schema> - </wsdl:types> - <wsdl:message name="catalogProductCurrentStoreRequest"> - <wsdl:part name="parameters" element="typens:catalogProductCurrentStoreRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductCurrentStoreResponse"> - <wsdl:part name="parameters" element="typens:catalogProductCurrentStoreResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductListRequest"> - <wsdl:part name="parameters" element="typens:catalogProductListRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductListResponse"> - <wsdl:part name="parameters" element="typens:catalogProductListResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductInfoRequest"> - <wsdl:part name="parameters" element="typens:catalogProductInfoRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductInfoResponse"> - <wsdl:part name="parameters" element="typens:catalogProductInfoResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductCreateRequest"> - <wsdl:part name="parameters" element="typens:catalogProductCreateRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductCreateResponse"> - <wsdl:part name="parameters" element="typens:catalogProductCreateResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductUpdateRequest"> - <wsdl:part name="parameters" element="typens:catalogProductUpdateRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductUpdateResponse"> - <wsdl:part name="parameters" element="typens:catalogProductUpdateResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductSetSpecialPriceRequest"> - <wsdl:part name="parameters" element="typens:catalogProductSetSpecialPriceRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductSetSpecialPriceResponse"> - <wsdl:part name="parameters" element="typens:catalogProductSetSpecialPriceResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductGetSpecialPriceRequest"> - <wsdl:part name="parameters" element="typens:catalogProductGetSpecialPriceRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductGetSpecialPriceResponse"> - <wsdl:part name="parameters" element="typens:catalogProductGetSpecialPriceResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductDeleteRequest"> - <wsdl:part name="parameters" element="typens:catalogProductDeleteRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductDeleteResponse"> - <wsdl:part name="parameters" element="typens:catalogProductDeleteResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductAttributeCurrentStoreRequest"> - <wsdl:part name="parameters" element="typens:catalogProductAttributeCurrentStoreRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductAttributeCurrentStoreResponse"> - <wsdl:part name="parameters" element="typens:catalogProductAttributeCurrentStoreResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductAttributeListRequest"> - <wsdl:part name="parameters" element="typens:catalogProductAttributeListRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductAttributeListResponse"> - <wsdl:part name="parameters" element="typens:catalogProductAttributeListResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductAttributeOptionsRequest"> - <wsdl:part name="parameters" element="typens:catalogProductAttributeOptionsRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductAttributeOptionsResponse"> - <wsdl:part name="parameters" element="typens:catalogProductAttributeOptionsResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductCustomOptionAddRequest"> - <wsdl:part name="parameters" element="typens:catalogProductCustomOptionAddRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductCustomOptionAddResponse"> - <wsdl:part name="parameters" element="typens:catalogProductCustomOptionAddResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductCustomOptionUpdateRequest"> - <wsdl:part name="parameters" element="typens:catalogProductCustomOptionUpdateRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductCustomOptionUpdateResponse"> - <wsdl:part name="parameters" element="typens:catalogProductCustomOptionUpdateResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductCustomOptionTypesRequest"> - <wsdl:part name="parameters" element="typens:catalogProductCustomOptionTypesRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductCustomOptionTypesResponse"> - <wsdl:part name="parameters" element="typens:catalogProductCustomOptionTypesResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductCustomOptionListRequest"> - <wsdl:part name="parameters" element="typens:catalogProductCustomOptionListRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductCustomOptionListResponse"> - <wsdl:part name="parameters" element="typens:catalogProductCustomOptionListResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductCustomOptionInfoRequest"> - <wsdl:part name="parameters" element="typens:catalogProductCustomOptionInfoRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductCustomOptionInfoResponse"> - <wsdl:part name="parameters" element="typens:catalogProductCustomOptionInfoResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductCustomOptionRemoveRequest"> - <wsdl:part name="parameters" element="typens:catalogProductCustomOptionRemoveRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductCustomOptionRemoveResponse"> - <wsdl:part name="parameters" element="typens:catalogProductCustomOptionRemoveResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductCustomOptionValueListRequest"> - <wsdl:part name="parameters" element="typens:catalogProductCustomOptionValueListRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductCustomOptionValueListResponse"> - <wsdl:part name="parameters" element="typens:catalogProductCustomOptionValueListResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductCustomOptionValueAddRequest"> - <wsdl:part name="parameters" element="typens:catalogProductCustomOptionValueAddRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductCustomOptionValueAddResponse"> - <wsdl:part name="parameters" element="typens:catalogProductCustomOptionValueAddResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductCustomOptionValueInfoRequest"> - <wsdl:part name="parameters" element="typens:catalogProductCustomOptionValueInfoRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductCustomOptionValueInfoResponse"> - <wsdl:part name="parameters" element="typens:catalogProductCustomOptionValueInfoResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductCustomOptionValueUpdateRequest"> - <wsdl:part name="parameters" element="typens:catalogProductCustomOptionValueUpdateRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductCustomOptionValueUpdateResponse"> - <wsdl:part name="parameters" element="typens:catalogProductCustomOptionValueUpdateResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductCustomOptionValueRemoveRequest"> - <wsdl:part name="parameters" element="typens:catalogProductCustomOptionValueRemoveRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductCustomOptionValueRemoveResponse"> - <wsdl:part name="parameters" element="typens:catalogProductCustomOptionValueRemoveResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductAttributeSetCreateRequest"> - <wsdl:part name="parameters" element="typens:catalogProductAttributeSetCreateRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductAttributeSetCreateResponse"> - <wsdl:part name="parameters" element="typens:catalogProductAttributeSetCreateResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductAttributeSetRemoveRequest"> - <wsdl:part name="parameters" element="typens:catalogProductAttributeSetRemoveRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductAttributeSetRemoveResponse"> - <wsdl:part name="parameters" element="typens:catalogProductAttributeSetRemoveResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductAttributeSetListRequest"> - <wsdl:part name="parameters" element="typens:catalogProductAttributeSetListRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductAttributeSetListResponse"> - <wsdl:part name="parameters" element="typens:catalogProductAttributeSetListResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductAttributeSetAttributeAddRequest"> - <wsdl:part name="parameters" element="typens:catalogProductAttributeSetAttributeAddRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductAttributeSetAttributeAddResponse"> - <wsdl:part name="parameters" element="typens:catalogProductAttributeSetAttributeAddResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductAttributeSetAttributeRemoveRequest"> - <wsdl:part name="parameters" element="typens:catalogProductAttributeSetAttributeRemoveRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductAttributeSetAttributeRemoveResponse"> - <wsdl:part name="parameters" element="typens:catalogProductAttributeSetAttributeRemoveResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductAttributeSetGroupAddRequest"> - <wsdl:part name="parameters" element="typens:catalogProductAttributeSetGroupAddRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductAttributeSetGroupAddResponse"> - <wsdl:part name="parameters" element="typens:catalogProductAttributeSetGroupAddResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductAttributeSetGroupRenameRequest"> - <wsdl:part name="parameters" element="typens:catalogProductAttributeSetGroupRenameRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductAttributeSetGroupRenameResponse"> - <wsdl:part name="parameters" element="typens:catalogProductAttributeSetGroupRenameResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductAttributeSetGroupRemoveRequest"> - <wsdl:part name="parameters" element="typens:catalogProductAttributeSetGroupRemoveRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductAttributeSetGroupRemoveResponse"> - <wsdl:part name="parameters" element="typens:catalogProductAttributeSetGroupRemoveResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductTypeListRequest"> - <wsdl:part name="parameters" element="typens:catalogProductTypeListRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductTypeListResponse"> - <wsdl:part name="parameters" element="typens:catalogProductTypeListResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductAttributeTierPriceInfoRequest"> - <wsdl:part name="parameters" element="typens:catalogProductAttributeTierPriceInfoRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductAttributeTierPriceInfoResponse"> - <wsdl:part name="parameters" element="typens:catalogProductAttributeTierPriceInfoResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductAttributeTierPriceUpdateRequest"> - <wsdl:part name="parameters" element="typens:catalogProductAttributeTierPriceUpdateRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductAttributeTierPriceUpdateResponse"> - <wsdl:part name="parameters" element="typens:catalogProductAttributeTierPriceUpdateResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductAttributeMediaCurrentStoreRequest"> - <wsdl:part name="parameters" element="typens:catalogProductAttributeMediaCurrentStoreRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductAttributeMediaCurrentStoreResponse"> - <wsdl:part name="parameters" element="typens:catalogProductAttributeMediaCurrentStoreResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductAttributeMediaListRequest"> - <wsdl:part name="parameters" element="typens:catalogProductAttributeMediaListRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductAttributeMediaListResponse"> - <wsdl:part name="parameters" element="typens:catalogProductAttributeMediaListResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductAttributeMediaInfoRequest"> - <wsdl:part name="parameters" element="typens:catalogProductAttributeMediaInfoRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductAttributeMediaInfoResponse"> - <wsdl:part name="parameters" element="typens:catalogProductAttributeMediaInfoResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductAttributeMediaTypesRequest"> - <wsdl:part name="parameters" element="typens:catalogProductAttributeMediaTypesRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductAttributeMediaTypesResponse"> - <wsdl:part name="parameters" element="typens:catalogProductAttributeMediaTypesResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductAttributeMediaCreateRequest"> - <wsdl:part name="parameters" element="typens:catalogProductAttributeMediaCreateRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductAttributeMediaCreateResponse"> - <wsdl:part name="parameters" element="typens:catalogProductAttributeMediaCreateResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductAttributeMediaUpdateRequest"> - <wsdl:part name="parameters" element="typens:catalogProductAttributeMediaUpdateRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductAttributeMediaUpdateResponse"> - <wsdl:part name="parameters" element="typens:catalogProductAttributeMediaUpdateResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductAttributeMediaRemoveRequest"> - <wsdl:part name="parameters" element="typens:catalogProductAttributeMediaRemoveRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductAttributeMediaRemoveResponse"> - <wsdl:part name="parameters" element="typens:catalogProductAttributeMediaRemoveResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductLinkListRequest"> - <wsdl:part name="parameters" element="typens:catalogProductLinkListRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductLinkListResponse"> - <wsdl:part name="parameters" element="typens:catalogProductLinkListResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductLinkAssignRequest"> - <wsdl:part name="parameters" element="typens:catalogProductLinkAssignRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductLinkAssignResponse"> - <wsdl:part name="parameters" element="typens:catalogProductLinkAssignResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductLinkUpdateRequest"> - <wsdl:part name="parameters" element="typens:catalogProductLinkUpdateRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductLinkUpdateResponse"> - <wsdl:part name="parameters" element="typens:catalogProductLinkUpdateResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductLinkRemoveRequest"> - <wsdl:part name="parameters" element="typens:catalogProductLinkRemoveRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductLinkRemoveResponse"> - <wsdl:part name="parameters" element="typens:catalogProductLinkRemoveResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductLinkTypesRequest"> - <wsdl:part name="parameters" element="typens:catalogProductLinkTypesRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductLinkTypesResponse"> - <wsdl:part name="parameters" element="typens:catalogProductLinkTypesResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductLinkAttributesRequest"> - <wsdl:part name="parameters" element="typens:catalogProductLinkAttributesRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductLinkAttributesResponse"> - <wsdl:part name="parameters" element="typens:catalogProductLinkAttributesResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogCategoryCurrentStoreRequest"> - <wsdl:part name="parameters" element="typens:catalogCategoryCurrentStoreRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogCategoryCurrentStoreResponse"> - <wsdl:part name="parameters" element="typens:catalogCategoryCurrentStoreResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogCategoryTreeRequest"> - <wsdl:part name="parameters" element="typens:catalogCategoryTreeRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogCategoryTreeResponse"> - <wsdl:part name="parameters" element="typens:catalogCategoryTreeResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogCategoryLevelRequest"> - <wsdl:part name="parameters" element="typens:catalogCategoryLevelRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogCategoryLevelResponse"> - <wsdl:part name="parameters" element="typens:catalogCategoryLevelResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogCategoryInfoRequest"> - <wsdl:part name="parameters" element="typens:catalogCategoryInfoRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogCategoryInfoResponse"> - <wsdl:part name="parameters" element="typens:catalogCategoryInfoResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogCategoryCreateRequest"> - <wsdl:part name="parameters" element="typens:catalogCategoryCreateRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogCategoryCreateResponse"> - <wsdl:part name="parameters" element="typens:catalogCategoryCreateResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogCategoryUpdateRequest"> - <wsdl:part name="parameters" element="typens:catalogCategoryUpdateRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogCategoryUpdateResponse"> - <wsdl:part name="parameters" element="typens:catalogCategoryUpdateResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogCategoryMoveRequest"> - <wsdl:part name="parameters" element="typens:catalogCategoryMoveRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogCategoryMoveResponse"> - <wsdl:part name="parameters" element="typens:catalogCategoryMoveResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogCategoryDeleteRequest"> - <wsdl:part name="parameters" element="typens:catalogCategoryDeleteRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogCategoryDeleteResponse"> - <wsdl:part name="parameters" element="typens:catalogCategoryDeleteResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogCategoryAssignedProductsRequest"> - <wsdl:part name="parameters" element="typens:catalogCategoryAssignedProductsRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogCategoryAssignedProductsResponse"> - <wsdl:part name="parameters" element="typens:catalogCategoryAssignedProductsResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogCategoryAssignProductRequest"> - <wsdl:part name="parameters" element="typens:catalogCategoryAssignProductRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogCategoryAssignProductResponse"> - <wsdl:part name="parameters" element="typens:catalogCategoryAssignProductResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogCategoryUpdateProductRequest"> - <wsdl:part name="parameters" element="typens:catalogCategoryUpdateProductRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogCategoryUpdateProductResponse"> - <wsdl:part name="parameters" element="typens:catalogCategoryUpdateProductResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogCategoryRemoveProductRequest"> - <wsdl:part name="parameters" element="typens:catalogCategoryRemoveProductRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogCategoryRemoveProductResponse"> - <wsdl:part name="parameters" element="typens:catalogCategoryRemoveProductResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogCategoryAttributeCurrentStoreRequest"> - <wsdl:part name="parameters" element="typens:catalogCategoryAttributeCurrentStoreRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogCategoryAttributeCurrentStoreResponse"> - <wsdl:part name="parameters" element="typens:catalogCategoryAttributeCurrentStoreResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogCategoryAttributeListRequest"> - <wsdl:part name="parameters" element="typens:catalogCategoryAttributeListRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogCategoryAttributeListResponse"> - <wsdl:part name="parameters" element="typens:catalogCategoryAttributeListResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogCategoryAttributeOptionsRequest"> - <wsdl:part name="parameters" element="typens:catalogCategoryAttributeOptionsRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogCategoryAttributeOptionsResponse"> - <wsdl:part name="parameters" element="typens:catalogCategoryAttributeOptionsResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductAttributeCreateRequest"> - <wsdl:part name="parameters" element="typens:catalogProductAttributeCreateRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductAttributeCreateResponse"> - <wsdl:part name="parameters" element="typens:catalogProductAttributeCreateResponseParam" /> - </wsdl:message> - <wsdl:portType name="{{var wsdl.handler}}PortType"> - <wsdl:operation name="catalogCategoryCurrentStore"> - <wsdl:documentation>Set_Get current store view</wsdl:documentation> - <wsdl:input message="typens:catalogCategoryCurrentStoreRequest" /> - <wsdl:output message="typens:catalogCategoryCurrentStoreResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogCategoryTree"> - <wsdl:documentation>Retrieve hierarchical tree of categories.</wsdl:documentation> - <wsdl:input message="typens:catalogCategoryTreeRequest" /> - <wsdl:output message="typens:catalogCategoryTreeResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogCategoryLevel"> - <wsdl:documentation>Retrieve hierarchical tree of categories.</wsdl:documentation> - <wsdl:input message="typens:catalogCategoryLevelRequest" /> - <wsdl:output message="typens:catalogCategoryLevelResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogCategoryInfo"> - <wsdl:documentation>Retrieve hierarchical tree of categories.</wsdl:documentation> - <wsdl:input message="typens:catalogCategoryInfoRequest" /> - <wsdl:output message="typens:catalogCategoryInfoResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogCategoryCreate"> - <wsdl:documentation>Create new category and return its id.</wsdl:documentation> - <wsdl:input message="typens:catalogCategoryCreateRequest" /> - <wsdl:output message="typens:catalogCategoryCreateResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogCategoryUpdate"> - <wsdl:documentation>Update category</wsdl:documentation> - <wsdl:input message="typens:catalogCategoryUpdateRequest" /> - <wsdl:output message="typens:catalogCategoryUpdateResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogCategoryMove"> - <wsdl:documentation>Move category in tree</wsdl:documentation> - <wsdl:input message="typens:catalogCategoryMoveRequest" /> - <wsdl:output message="typens:catalogCategoryMoveResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogCategoryDelete"> - <wsdl:documentation>Delete category</wsdl:documentation> - <wsdl:input message="typens:catalogCategoryDeleteRequest" /> - <wsdl:output message="typens:catalogCategoryDeleteResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogCategoryAssignedProducts"> - <wsdl:documentation>Retrieve list of assigned products</wsdl:documentation> - <wsdl:input message="typens:catalogCategoryAssignedProductsRequest" /> - <wsdl:output message="typens:catalogCategoryAssignedProductsResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogCategoryAssignProduct"> - <wsdl:documentation>Assign product to category</wsdl:documentation> - <wsdl:input message="typens:catalogCategoryAssignProductRequest" /> - <wsdl:output message="typens:catalogCategoryAssignProductResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogCategoryUpdateProduct"> - <wsdl:documentation>Update assigned product</wsdl:documentation> - <wsdl:input message="typens:catalogCategoryUpdateProductRequest" /> - <wsdl:output message="typens:catalogCategoryUpdateProductResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogCategoryRemoveProduct"> - <wsdl:documentation>Remove product assignment from category</wsdl:documentation> - <wsdl:input message="typens:catalogCategoryRemoveProductRequest" /> - <wsdl:output message="typens:catalogCategoryRemoveProductResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogCategoryAttributeCurrentStore"> - <wsdl:documentation>Set/Get current store view</wsdl:documentation> - <wsdl:input message="typens:catalogCategoryAttributeCurrentStoreRequest" /> - <wsdl:output message="typens:catalogCategoryAttributeCurrentStoreResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogCategoryAttributeList"> - <wsdl:documentation>Retrieve category attributes</wsdl:documentation> - <wsdl:input message="typens:catalogCategoryAttributeListRequest" /> - <wsdl:output message="typens:catalogCategoryAttributeListResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogCategoryAttributeOptions"> - <wsdl:documentation>Retrieve attribute options</wsdl:documentation> - <wsdl:input message="typens:catalogCategoryAttributeOptionsRequest" /> - <wsdl:output message="typens:catalogCategoryAttributeOptionsResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductCurrentStore"> - <wsdl:documentation>Set/Get current store view</wsdl:documentation> - <wsdl:input message="typens:catalogProductCurrentStoreRequest" /> - <wsdl:output message="typens:catalogProductCurrentStoreResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductList"> - <wsdl:documentation>Retrieve products list by filters</wsdl:documentation> - <wsdl:input message="typens:catalogProductListRequest" /> - <wsdl:output message="typens:catalogProductListResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductInfo"> - <wsdl:documentation>Retrieve product</wsdl:documentation> - <wsdl:input message="typens:catalogProductInfoRequest" /> - <wsdl:output message="typens:catalogProductInfoResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductCreate"> - <wsdl:documentation>Create new product and return product id</wsdl:documentation> - <wsdl:input message="typens:catalogProductCreateRequest" /> - <wsdl:output message="typens:catalogProductCreateResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductUpdate"> - <wsdl:documentation>Update product</wsdl:documentation> - <wsdl:input message="typens:catalogProductUpdateRequest" /> - <wsdl:output message="typens:catalogProductUpdateResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductSetSpecialPrice"> - <wsdl:documentation>Update product special price</wsdl:documentation> - <wsdl:input message="typens:catalogProductSetSpecialPriceRequest" /> - <wsdl:output message="typens:catalogProductSetSpecialPriceResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductGetSpecialPrice"> - <wsdl:documentation>Get product special price data</wsdl:documentation> - <wsdl:input message="typens:catalogProductGetSpecialPriceRequest" /> - <wsdl:output message="typens:catalogProductGetSpecialPriceResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductDelete"> - <wsdl:documentation>Delete product</wsdl:documentation> - <wsdl:input message="typens:catalogProductDeleteRequest" /> - <wsdl:output message="typens:catalogProductDeleteResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductAttributeCurrentStore"> - <wsdl:documentation>Set/Get current store view</wsdl:documentation> - <wsdl:input message="typens:catalogProductAttributeCurrentStoreRequest" /> - <wsdl:output message="typens:catalogProductAttributeCurrentStoreResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductAttributeList"> - <wsdl:documentation>Retrieve attribute list</wsdl:documentation> - <wsdl:input message="typens:catalogProductAttributeListRequest" /> - <wsdl:output message="typens:catalogProductAttributeListResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductAttributeOptions"> - <wsdl:documentation>Retrieve attribute options</wsdl:documentation> - <wsdl:input message="typens:catalogProductAttributeOptionsRequest" /> - <wsdl:output message="typens:catalogProductAttributeOptionsResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductCustomOptionAdd"> - <wsdl:documentation>Add new custom option into product</wsdl:documentation> - <wsdl:input message="typens:catalogProductCustomOptionAddRequest" /> - <wsdl:output message="typens:catalogProductCustomOptionAddResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductCustomOptionUpdate"> - <wsdl:documentation>Update product custom option</wsdl:documentation> - <wsdl:input message="typens:catalogProductCustomOptionUpdateRequest" /> - <wsdl:output message="typens:catalogProductCustomOptionUpdateResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductCustomOptionTypes"> - <wsdl:documentation>Get list of available custom option types </wsdl:documentation> - <wsdl:input message="typens:catalogProductCustomOptionTypesRequest" /> - <wsdl:output message="typens:catalogProductCustomOptionTypesResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductCustomOptionList"> - <wsdl:documentation>Retrieve list of product custom options</wsdl:documentation> - <wsdl:input message="typens:catalogProductCustomOptionListRequest" /> - <wsdl:output message="typens:catalogProductCustomOptionListResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductCustomOptionInfo"> - <wsdl:documentation>Get full information about custom option in product</wsdl:documentation> - <wsdl:input message="typens:catalogProductCustomOptionInfoRequest" /> - <wsdl:output message="typens:catalogProductCustomOptionInfoResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductCustomOptionRemove"> - <wsdl:documentation>Remove custom option</wsdl:documentation> - <wsdl:input message="typens:catalogProductCustomOptionRemoveRequest" /> - <wsdl:output message="typens:catalogProductCustomOptionRemoveResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductCustomOptionValueList"> - <wsdl:documentation>Retrieve custom option values list</wsdl:documentation> - <wsdl:input message="typens:catalogProductCustomOptionValueListRequest" /> - <wsdl:output message="typens:catalogProductCustomOptionValueListResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductCustomOptionValueAdd"> - <wsdl:documentation>Add new custom option values</wsdl:documentation> - <wsdl:input message="typens:catalogProductCustomOptionValueAddRequest" /> - <wsdl:output message="typens:catalogProductCustomOptionValueAddResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductCustomOptionValueInfo"> - <wsdl:documentation>Retrieve custom option value info</wsdl:documentation> - <wsdl:input message="typens:catalogProductCustomOptionValueInfoRequest" /> - <wsdl:output message="typens:catalogProductCustomOptionValueInfoResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductCustomOptionValueUpdate"> - <wsdl:documentation>Update custom option value</wsdl:documentation> - <wsdl:input message="typens:catalogProductCustomOptionValueUpdateRequest" /> - <wsdl:output message="typens:catalogProductCustomOptionValueUpdateResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductCustomOptionValueRemove"> - <wsdl:documentation>Remove value from custom option</wsdl:documentation> - <wsdl:input message="typens:catalogProductCustomOptionValueRemoveRequest" /> - <wsdl:output message="typens:catalogProductCustomOptionValueRemoveResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductAttributeSetCreate"> - <wsdl:documentation>Create product attribute set based on another set</wsdl:documentation> - <wsdl:input message="typens:catalogProductAttributeSetCreateRequest" /> - <wsdl:output message="typens:catalogProductAttributeSetCreateResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductAttributeSetRemove"> - <wsdl:documentation>Remove product attribute set</wsdl:documentation> - <wsdl:input message="typens:catalogProductAttributeSetRemoveRequest" /> - <wsdl:output message="typens:catalogProductAttributeSetRemoveResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductAttributeSetList"> - <wsdl:documentation>Retrieve product attribute sets</wsdl:documentation> - <wsdl:input message="typens:catalogProductAttributeSetListRequest" /> - <wsdl:output message="typens:catalogProductAttributeSetListResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductAttributeSetAttributeAdd"> - <wsdl:documentation>Add attribute into attribute set</wsdl:documentation> - <wsdl:input message="typens:catalogProductAttributeSetAttributeAddRequest" /> - <wsdl:output message="typens:catalogProductAttributeSetAttributeAddResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductAttributeSetAttributeRemove"> - <wsdl:documentation>Remove attribute from attribute set</wsdl:documentation> - <wsdl:input message="typens:catalogProductAttributeSetAttributeRemoveRequest" /> - <wsdl:output message="typens:catalogProductAttributeSetAttributeRemoveResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductAttributeSetGroupAdd"> - <wsdl:documentation>Create group within existing attribute set</wsdl:documentation> - <wsdl:input message="typens:catalogProductAttributeSetGroupAddRequest" /> - <wsdl:output message="typens:catalogProductAttributeSetGroupAddResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductAttributeSetGroupRename"> - <wsdl:documentation>Rename existing group</wsdl:documentation> - <wsdl:input message="typens:catalogProductAttributeSetGroupRenameRequest" /> - <wsdl:output message="typens:catalogProductAttributeSetGroupRenameResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductAttributeSetGroupRemove"> - <wsdl:documentation>Remove group from attribute set</wsdl:documentation> - <wsdl:input message="typens:catalogProductAttributeSetGroupRemoveRequest" /> - <wsdl:output message="typens:catalogProductAttributeSetGroupRemoveResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductTypeList"> - <wsdl:documentation>Retrieve product types</wsdl:documentation> - <wsdl:input message="typens:catalogProductTypeListRequest" /> - <wsdl:output message="typens:catalogProductTypeListResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductAttributeTierPriceInfo"> - <wsdl:documentation>Retrieve product tier prices</wsdl:documentation> - <wsdl:input message="typens:catalogProductAttributeTierPriceInfoRequest" /> - <wsdl:output message="typens:catalogProductAttributeTierPriceInfoResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductAttributeTierPriceUpdate"> - <wsdl:documentation>Update product tier prices</wsdl:documentation> - <wsdl:input message="typens:catalogProductAttributeTierPriceUpdateRequest" /> - <wsdl:output message="typens:catalogProductAttributeTierPriceUpdateResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductAttributeMediaCurrentStore"> - <wsdl:documentation>Set/Get current store view</wsdl:documentation> - <wsdl:input message="typens:catalogProductAttributeMediaCurrentStoreRequest" /> - <wsdl:output message="typens:catalogProductAttributeMediaCurrentStoreResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductAttributeMediaList"> - <wsdl:documentation>Retrieve product image list</wsdl:documentation> - <wsdl:input message="typens:catalogProductAttributeMediaListRequest" /> - <wsdl:output message="typens:catalogProductAttributeMediaListResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductAttributeMediaInfo"> - <wsdl:documentation>Retrieve product image data</wsdl:documentation> - <wsdl:input message="typens:catalogProductAttributeMediaInfoRequest" /> - <wsdl:output message="typens:catalogProductAttributeMediaInfoResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductAttributeMediaTypes"> - <wsdl:documentation>Retrieve product image types</wsdl:documentation> - <wsdl:input message="typens:catalogProductAttributeMediaTypesRequest" /> - <wsdl:output message="typens:catalogProductAttributeMediaTypesResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductAttributeMediaCreate"> - <wsdl:documentation>Upload new product image</wsdl:documentation> - <wsdl:input message="typens:catalogProductAttributeMediaCreateRequest" /> - <wsdl:output message="typens:catalogProductAttributeMediaCreateResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductAttributeMediaUpdate"> - <wsdl:documentation>Update product image</wsdl:documentation> - <wsdl:input message="typens:catalogProductAttributeMediaUpdateRequest" /> - <wsdl:output message="typens:catalogProductAttributeMediaUpdateResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductAttributeMediaRemove"> - <wsdl:documentation>Remove product image</wsdl:documentation> - <wsdl:input message="typens:catalogProductAttributeMediaRemoveRequest" /> - <wsdl:output message="typens:catalogProductAttributeMediaRemoveResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductLinkList"> - <wsdl:documentation>Retrieve linked products</wsdl:documentation> - <wsdl:input message="typens:catalogProductLinkListRequest" /> - <wsdl:output message="typens:catalogProductLinkListResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductLinkAssign"> - <wsdl:documentation>Assign product link</wsdl:documentation> - <wsdl:input message="typens:catalogProductLinkAssignRequest" /> - <wsdl:output message="typens:catalogProductLinkAssignResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductLinkUpdate"> - <wsdl:documentation>Update product link</wsdl:documentation> - <wsdl:input message="typens:catalogProductLinkUpdateRequest" /> - <wsdl:output message="typens:catalogProductLinkUpdateResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductLinkRemove"> - <wsdl:documentation>Remove product link</wsdl:documentation> - <wsdl:input message="typens:catalogProductLinkRemoveRequest" /> - <wsdl:output message="typens:catalogProductLinkRemoveResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductLinkTypes"> - <wsdl:documentation>Retrieve product link types</wsdl:documentation> - <wsdl:input message="typens:catalogProductLinkTypesRequest" /> - <wsdl:output message="typens:catalogProductLinkTypesResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductLinkAttributes"> - <wsdl:documentation>Retrieve product link type attributes</wsdl:documentation> - <wsdl:input message="typens:catalogProductLinkAttributesRequest" /> - <wsdl:output message="typens:catalogProductLinkAttributesResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductAttributeCreate"> - <wsdl:documentation>Create new attribute</wsdl:documentation> - <wsdl:input message="typens:catalogProductAttributeCreateRequest" /> - <wsdl:output message="typens:catalogProductAttributeCreateResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductAttributeRemove"> - <wsdl:documentation>Delete attribute</wsdl:documentation> - <wsdl:input message="typens:catalogProductAttributeRemoveRequest" /> - <wsdl:output message="typens:catalogProductAttributeRemoveResponse" /> - </wsdl:operation> - </wsdl:portType> - <wsdl:binding name="{{var wsdl.handler}}Binding" type="typens:{{var wsdl.handler}}PortType"> - <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" /> - <wsdl:operation name="catalogCategoryCurrentStore"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogCategoryTree"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogCategoryLevel"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogCategoryInfo"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogCategoryCreate"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogCategoryUpdate"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogCategoryMove"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogCategoryDelete"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogCategoryAssignedProducts"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogCategoryAssignProduct"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogCategoryUpdateProduct"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogCategoryRemoveProduct"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductCurrentStore"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductList"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductInfo"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductCreate"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductUpdate"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductSetSpecialPrice"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductGetSpecialPrice"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductDelete"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductAttributeCurrentStore"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductAttributeList"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductAttributeOptions"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductCustomOptionAdd"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductCustomOptionUpdate"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductCustomOptionTypes"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductCustomOptionList"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductCustomOptionInfo"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductCustomOptionRemove"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductCustomOptionValueList"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductCustomOptionValueInfo"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductCustomOptionValueAdd"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductCustomOptionValueUpdate"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductCustomOptionValueRemove"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductAttributeSetCreate"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductAttributeSetRemove"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductAttributeSetList"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductAttributeSetAttributeAdd"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductAttributeSetAttributeRemove"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductAttributeSetGroupAdd"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductAttributeSetGroupRename"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductAttributeSetGroupRemove"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductTypeList"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductAttributeTierPriceInfo"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductAttributeTierPriceUpdate"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogCategoryAttributeCurrentStore"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogCategoryAttributeList"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogCategoryAttributeOptions"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductAttributeMediaCurrentStore"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductAttributeMediaList"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductAttributeMediaInfo"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductAttributeMediaTypes"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductAttributeMediaCreate"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductAttributeMediaUpdate"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductAttributeMediaRemove"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductLinkList"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductLinkAssign"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductLinkUpdate"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductLinkRemove"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductLinkTypes"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductLinkAttributes"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductAttributeCreate"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - </wsdl:binding> - <wsdl:service name="{{var wsdl.name}}Service"> - <wsdl:port name="{{var wsdl.handler}}Port" binding="typens:{{var wsdl.handler}}Binding"> - <soap:address location="{{var wsdl.url}}" /> - </wsdl:port> - </wsdl:service> -</wsdl:definitions> diff --git a/app/code/core/Mage/CatalogInventory/Model/Api2/Stock/Item.php b/app/code/core/Mage/CatalogInventory/Model/Api2/Stock/Item.php deleted file mode 100644 index 6ed1d2d320df528dd978bad3e88246c25536bfe0..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/CatalogInventory/Model/Api2/Stock/Item.php +++ /dev/null @@ -1,52 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_CatalogInventory - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 class for stock item - * - * @category Mage - * @package Mage_CatalogInventory - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_CatalogInventory_Model_Api2_Stock_Item extends Mage_Api2_Model_Resource -{ - /** - * Load stock item by id - * - * @param int $id - * @throws Mage_Api2_Exception - * @return Mage_CatalogInventory_Model_Stock_Item - */ - protected function _loadStockItemById($id) - { - /* @var $stockItem Mage_CatalogInventory_Model_Stock_Item */ - $stockItem = Mage::getModel('Mage_CatalogInventory_Model_Stock_Item')->load($id); - if (!$stockItem->getId()) { - $this->_critical(self::RESOURCE_NOT_FOUND); - } - return $stockItem; - } -} diff --git a/app/code/core/Mage/CatalogInventory/Model/Api2/Stock/Item/Rest.php b/app/code/core/Mage/CatalogInventory/Model/Api2/Stock/Item/Rest.php deleted file mode 100644 index 1fa5977155ba75f36b9d4577bd8403450fbd8126..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/CatalogInventory/Model/Api2/Stock/Item/Rest.php +++ /dev/null @@ -1,163 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_CatalogInventory - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Abstract API2 class for stock item - * - * @category Mage - * @package Mage_CatalogInventory - * @author Magento Core Team <core@magentocommerce.com> - */ -abstract class Mage_CatalogInventory_Model_Api2_Stock_Item_Rest - extends Mage_CatalogInventory_Model_Api2_Stock_Item -{ - /** - * Retrieve information about specified stock item - * - * @throws Mage_Api2_Exception - * @return array - */ - protected function _retrieve() - { - /* @var $stockItem Mage_CatalogInventory_Model_Stock_Item */ - $stockItem = $this->_loadStockItemById($this->getRequest()->getParam('id')); - return $stockItem->getData(); - } - - /** - * Get stock items list - * - * @return array - */ - protected function _retrieveCollection() - { - $data = $this->_getCollectionForRetrieve()->load()->toArray(); - return isset($data['items']) ? $data['items'] : $data; - } - - /** - * Retrieve stock items collection - * - * @return Mage_CatalogInventory_Model_Resource_Stock_Item_Collection - */ - protected function _getCollectionForRetrieve() - { - /* @var $collection Mage_CatalogInventory_Model_Resource_Stock_Item_Collection */ - $collection = Mage::getResourceModel('Mage_CatalogInventory_Model_Resource_Stock_Item_Collection'); - $this->_applyCollectionModifiers($collection); - return $collection; - } - - /** - * Update specified stock item - * - * @param array $data - * @throws Mage_Api2_Exception - */ - protected function _update(array $data) - { - /* @var $stockItem Mage_CatalogInventory_Model_Stock_Item */ - $stockItem = $this->_loadStockItemById($this->getRequest()->getParam('id')); - - /* @var $validator Mage_CatalogInventory_Model_Api2_Stock_Item_Validator_Item */ - $validator = Mage::getModel('Mage_CatalogInventory_Model_Api2_Stock_Item_Validator_Item', array( - 'options' => array('resource' => $this)) - ); - - if (!$validator->isValidData($data)) { - foreach ($validator->getErrors() as $error) { - $this->_error($error, Mage_Api2_Model_Server::HTTP_BAD_REQUEST); - } - $this->_critical(self::RESOURCE_DATA_PRE_VALIDATION_ERROR); - } - - $stockItem->addData($data); - try { - $stockItem->save(); - } catch (Mage_Core_Exception $e) { - $this->_error($e->getMessage(), Mage_Api2_Model_Server::HTTP_INTERNAL_ERROR); - } catch (Exception $e) { - $this->_critical(self::RESOURCE_INTERNAL_ERROR); - } - } - - /** - * Update specified stock items - * - * @param array $data - */ - protected function _multiUpdate(array $data) - { - foreach ($data as $itemData) { - try { - if (!is_array($itemData)) { - $this->_errorMessage(self::RESOURCE_DATA_INVALID, Mage_Api2_Model_Server::HTTP_BAD_REQUEST); - $this->_critical(self::RESOURCE_DATA_PRE_VALIDATION_ERROR); - } - - /* @var $validator Mage_CatalogInventory_Model_Api2_Stock_Item_Validator_Item */ - $validator = Mage::getModel('Mage_CatalogInventory_Model_Api2_Stock_Item_Validator_Item', array( - 'options' => array('resource' => $this)) - ); - if (!$validator->isValidSingleItemDataForMultiUpdate($itemData)) { - foreach ($validator->getErrors() as $error) { - $this->_errorMessage($error, Mage_Api2_Model_Server::HTTP_BAD_REQUEST, array( - 'item_id' => isset($itemData['item_id']) ? $itemData['item_id'] : null - )); - } - $this->_critical(self::RESOURCE_DATA_PRE_VALIDATION_ERROR); - } - - // Existence of a item is checked in the validator - /* @var $stockItem Mage_CatalogInventory_Model_Stock_Item */ - $stockItem = $this->_loadStockItemById($itemData['item_id']); - - unset($itemData['item_id']); // item_id is not for update - $stockItem->addData($itemData); - $stockItem->save(); - - $this->_successMessage(self::RESOURCE_UPDATED_SUCCESSFUL, Mage_Api2_Model_Server::HTTP_OK, array( - 'item_id' => $stockItem->getId() - )); - } catch (Mage_Api2_Exception $e) { - // pre-validation errors are already added - if ($e->getMessage() != self::RESOURCE_DATA_PRE_VALIDATION_ERROR) { - $this->_errorMessage($e->getMessage(), $e->getCode(), array( - 'item_id' => isset($itemData['item_id']) ? $itemData['item_id'] : null - )); - } - } catch (Exception $e) { - $this->_errorMessage( - Mage_Api2_Model_Resource::RESOURCE_INTERNAL_ERROR, - Mage_Api2_Model_Server::HTTP_INTERNAL_ERROR, - array( - 'item_id' => isset($itemData['item_id']) ? $itemData['item_id'] : null - ) - ); - } - } - } -} diff --git a/app/code/core/Mage/CatalogInventory/Model/Api2/Stock/Item/Rest/Admin/V1.php b/app/code/core/Mage/CatalogInventory/Model/Api2/Stock/Item/Rest/Admin/V1.php deleted file mode 100644 index e64df4852091e97ffa79e39287c2928c2020d462..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/CatalogInventory/Model/Api2/Stock/Item/Rest/Admin/V1.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_CatalogInventory - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 class for stock item (admin) - * - * @category Mage - * @package Mage_CatalogInventory - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_CatalogInventory_Model_Api2_Stock_Item_Rest_Admin_V1 extends Mage_CatalogInventory_Model_Api2_Stock_Item_Rest -{ -} diff --git a/app/code/core/Mage/CatalogInventory/Model/Api2/Stock/Item/Validator/Item.php b/app/code/core/Mage/CatalogInventory/Model/Api2/Stock/Item/Validator/Item.php deleted file mode 100644 index e80b05d4a48fb4b4c67ff5c4cbe2e1ebafc489a2..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/CatalogInventory/Model/Api2/Stock/Item/Validator/Item.php +++ /dev/null @@ -1,62 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_CatalogInventory - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 Stock Item Validator - * - * @category Mage - * @package Mage_CatalogInventory - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_CatalogInventory_Model_Api2_Stock_Item_Validator_Item extends Mage_Api2_Model_Resource_Validator_Fields -{ - /** - * Validate data. - * If fails validation, then this method returns false, and - * getErrors() will return an array of errors that explain why the - * validation failed. - * - * @param array $data - * @return bool - */ - public function isValidSingleItemDataForMultiUpdate(array $data) - { - // Validate item id - if (!isset($data['item_id']) || !is_numeric($data['item_id'])) { - $this->_addError('Invalid value for "item_id" in request.'); - } else { - // Validate Stock Item - /* @var $stockItem Mage_CatalogInventory_Model_Stock_Item */ - $stockItem = Mage::getModel('Mage_CatalogInventory_Model_Stock_Item')->load($data['item_id']); - if (!$stockItem->getId()) { - $this->_addError(sprintf('StockItem #%d not found.', $data['item_id'])); - } else { - parent::isValidData($data); - } - } - return !count($this->getErrors()); - } -} diff --git a/app/code/core/Mage/CatalogInventory/Model/Stock/Item/Api.php b/app/code/core/Mage/CatalogInventory/Model/Stock/Item/Api.php deleted file mode 100644 index 5da00a0aaf31d0bec88941db82b920487dc6da0d..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/CatalogInventory/Model/Stock/Item/Api.php +++ /dev/null @@ -1,129 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_CatalogInventory - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Catalog inventory api - * - * @category Mage - * @package Mage_CatalogInventory - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_CatalogInventory_Model_Stock_Item_Api extends Mage_Catalog_Model_Api_Resource -{ - public function __construct() - { - $this->_storeIdSessionField = 'product_store_id'; - } - - public function items($productIds) - { - if (!is_array($productIds)) { - $productIds = array($productIds); - } - - $product = Mage::getModel('Mage_Catalog_Model_Product'); - - foreach ($productIds as &$productId) { - if ($newId = $product->getIdBySku($productId)) { - $productId = $newId; - } - } - - $collection = Mage::getModel('Mage_Catalog_Model_Product') - ->getCollection() - ->setFlag('require_stock_items', true) - ->addFieldToFilter('entity_id', array('in'=>$productIds)); - - $result = array(); - - foreach ($collection as $product) { - if ($product->getStockItem()) { - $result[] = array( - 'product_id' => $product->getId(), - 'sku' => $product->getSku(), - 'qty' => $product->getStockItem()->getQty(), - 'is_in_stock' => $product->getStockItem()->getIsInStock() - ); - } - } - - return $result; - } - - public function update($productId, $data) - { - $product = Mage::getModel('Mage_Catalog_Model_Product'); - - if ($newId = $product->getIdBySku($productId)) { - $productId = $newId; - } - - $product->setStoreId($this->_getStoreId()) - ->load($productId); - - if (!$product->getId()) { - $this->_fault('not_exists'); - } - - if (!$stockData = $product->getStockData()) { - $stockData = array(); - } - - if (isset($data['qty'])) { - $stockData['qty'] = $data['qty']; - } - - if (isset($data['is_in_stock'])) { - $stockData['is_in_stock'] = $data['is_in_stock']; - } - - if (isset($data['manage_stock'])) { - $stockData['manage_stock'] = $data['manage_stock']; - } - - if (isset($data['use_config_manage_stock'])) { - $stockData['use_config_manage_stock'] = $data['use_config_manage_stock']; - } - - if (isset($data['use_config_backorders'])) { - $stockData['use_config_backorders'] = $data['use_config_backorders']; - } - - if (isset($data['backorders'])) { - $stockData['backorders'] = $data['backorders']; - } - - $product->setStockData($stockData); - - try { - $product->save(); - } catch (Mage_Core_Exception $e) { - $this->_fault('not_updated', $e->getMessage()); - } - - return true; - } -} // Class Mage_CatalogInventory_Model_Stock_Item_Api End diff --git a/app/code/core/Mage/CatalogInventory/Model/Stock/Item/Api/V2.php b/app/code/core/Mage/CatalogInventory/Model/Stock/Item/Api/V2.php deleted file mode 100644 index 7c096d3b182eb5fec291bd2b26f3b691f8abb6a2..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/CatalogInventory/Model/Stock/Item/Api/V2.php +++ /dev/null @@ -1,89 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_CatalogInventory - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Catalog inventory api V2 - * - * @category Mage - * @package Mage_CatalogInventory - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_CatalogInventory_Model_Stock_Item_Api_V2 extends Mage_CatalogInventory_Model_Stock_Item_Api -{ - public function update($productId, $data) - { - $product = Mage::getModel('Mage_Catalog_Model_Product'); - - if ($newId = $product->getIdBySku($productId)) { - $productId = $newId; - } - - $product->setStoreId($this->_getStoreId()) - ->load($productId); - - if (!$product->getId()) { - $this->_fault('not_exists'); - } - - if (!$stockData = $product->getStockData()) { - $stockData = array(); - } - - if (isset($data->qty)) { - $stockData['qty'] = $data->qty; - } - - if (isset($data->is_in_stock)) { - $stockData['is_in_stock'] = $data->is_in_stock; - } - - if (isset($data->manage_stock)) { - $stockData['manage_stock'] = $data->manage_stock; - } - - if (isset($data->use_config_manage_stock)) { - $stockData['use_config_manage_stock'] = $data->use_config_manage_stock; - } - - if (isset($data->use_config_backorders)) { - $stockData['use_config_backorders'] = $data->use_config_backorders; - } - - if (isset($data->backorders)) { - $stockData['backorders'] = $data->backorders; - } - - $product->setStockData($stockData); - - try { - $product->save(); - } catch (Mage_Core_Exception $e) { - $this->_fault('not_updated', $e->getMessage()); - } - - return true; - } -} diff --git a/app/code/core/Mage/CatalogInventory/etc/api.xml b/app/code/core/Mage/CatalogInventory/etc/api.xml deleted file mode 100644 index fca60d4b464f8b5a7f07dfc3bc62d7382b39f5c4..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/CatalogInventory/etc/api.xml +++ /dev/null @@ -1,81 +0,0 @@ -<?xml version="1.0"?> -<!-- -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Academic Free License (AFL 3.0) - * that is bundled with this package in the file LICENSE_AFL.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/afl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_CatalogInventory - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) - */ ---> -<config> - <api> - <resources> - <cataloginventory_stock_item translate="title" module="Mage_CatalogInventory"> - <model>Mage_CatalogInventory_Model_Stock_Item_Api</model> - <title>Inventory API</title> - <acl>cataloginventory</acl> - <methods> - <list translate="title" module="Mage_CatalogInventory"> - <title>Retrieve stock data by product ids</title> - <method>items</method> - <acl>cataloginventory/info</acl> - </list> - <update translate="title" module="Mage_CatalogInventory"> - <title>Update product stock data</title> - <acl>cataloginventory/update</acl> - </update> - </methods> - <faults module="Mage_CatalogInventory"> - <not_exists> - <code>101</code> - <message>Product not exists.</message> - </not_exists> - <not_updated> - <code>102</code> - <message>Product inventory not updated. Details in error message.</message> - </not_updated> - </faults> - </cataloginventory_stock_item> - </resources> - <resources_alias> - <product_stock>cataloginventory_stock_item</product_stock> - </resources_alias> - <v2> - <resources_function_prefix> - <product_stock>catalogInventoryStockItem</product_stock> - </resources_function_prefix> - </v2> - <acl> - <resources> - <cataloginventory translate="title" module="Mage_CatalogInventory"> - <title>Catalog Inventory</title> - <sort_order>4</sort_order> - <update translate="title" module="Mage_CatalogInventory"> - <title>Update</title> - </update> - <info translate="title" module="Mage_CatalogInventory"> - <title>Retrieve stock data</title> - </info> - </cataloginventory> - </resources> - </acl> - </api> -</config> diff --git a/app/code/core/Mage/CatalogInventory/etc/api2.xml b/app/code/core/Mage/CatalogInventory/etc/api2.xml deleted file mode 100644 index f8a0bf0bdc53a14cdf08dfea93561eaa417bc81d..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/CatalogInventory/etc/api2.xml +++ /dev/null @@ -1,267 +0,0 @@ -<?xml version="1.0"?> -<!-- -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Academic Free License (AFL 3.0) - * that is bundled with this package in the file LICENSE_AFL.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/afl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_CatalogInventory - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) - */ ---> -<config> - <api2> - <resource_groups> - <cataloginventory translate="title" module="Mage_Api2"> - <title>CatalogInventory</title> - <sort_order>120</sort_order> - </cataloginventory> - </resource_groups> - <resources> - <stock_item translate="title" module="Mage_Api2"> - <group>cataloginventory</group> - <model>Mage_CatalogInventory_Model_Api2_Stock_Item</model> - <working_model>Mage_CatalogInventory_Model_Stock_Item</working_model> - <title>Stock Item</title> - <privileges> - <admin> - <retrieve>1</retrieve> - <update>1</update> - </admin> - </privileges> - <attributes translate="item_id product_id stock_id qty min_qty use_config_min_qty is_qty_decimal backorders use_config_backorders min_sale_qty use_config_min_sale_qty max_sale_qty use_config_max_sale_qty is_in_stock low_stock_date notify_stock_qty use_config_notify_stock_qty manage_stock use_config_manage_stock stock_status_changed_auto use_config_qty_increments qty_increments use_config_enable_qty_inc enable_qty_increments is_decimal_divided" module="Mage_Api2"> - <item_id>Item ID</item_id> - <product_id>Product ID</product_id> - <stock_id>Stock ID</stock_id> - <qty>Qty</qty> - <min_qty>Qty for Item's Status to Become Out of Stock</min_qty> - <use_config_min_qty>Use Config Settings for Qty for Item's Status to Become Out of Stock</use_config_min_qty> - <is_qty_decimal>Qty Uses Decimals</is_qty_decimal> - <backorders>Backorders</backorders> - <use_config_backorders>Use Config Settings for Backorders</use_config_backorders> - <min_sale_qty>Minimum Qty Allowed in Shopping Cart</min_sale_qty> - <use_config_min_sale_qty>Use Config Settings for Minimum Qty Allowed in Shopping Cart</use_config_min_sale_qty> - <max_sale_qty>Maximum Qty Allowed in Shopping Cart</max_sale_qty> - <use_config_max_sale_qty>Use Config Settings for Maximum Qty Allowed in Shopping Cart</use_config_max_sale_qty> - <is_in_stock>Stock Availability</is_in_stock> - <low_stock_date>Low Stock Date</low_stock_date> - <notify_stock_qty>Notify for Quantity Below</notify_stock_qty> - <use_config_notify_stock_qty>Use Config Settings for Notify for Quantity Below</use_config_notify_stock_qty> - <manage_stock>Manage Stock</manage_stock> - <use_config_manage_stock>Use Config Settings for Manage Stock</use_config_manage_stock> - <stock_status_changed_auto>Automatically Return Credit Memo Item to Stock</stock_status_changed_auto> - <use_config_qty_increments>Use Config Settings for Qty Increments</use_config_qty_increments> - <qty_increments>Qty Increments</qty_increments> - <use_config_enable_qty_inc>Use Config Settings for Enable Qty Increments</use_config_enable_qty_inc> - <enable_qty_increments>Enable Qty Increments</enable_qty_increments> - <is_decimal_divided>Can Be Divided into Multiple Boxes for Shipping</is_decimal_divided> - </attributes> - <exclude_attributes> - <admin> - <write> - <item_id>1</item_id> - <product_id>1</product_id> - <stock_id>1</stock_id> - <low_stock_date>1</low_stock_date> - </write> - </admin> - </exclude_attributes> - <force_attributes> - <admin> - <item_id>1</item_id> - </admin> - </force_attributes> - <routes> - <route_entity> - <route>/stockitems/:id</route> - <action_type>entity</action_type> - </route_entity> - <route_collection> - <route>/stockitems</route> - <action_type>collection</action_type> - </route_collection> - </routes> - <validators> - <fields> - <manage_stock> - <regex translate="message" module="Mage_Api2"> - <type>Regex</type> - <options><pattern>/^[0,1]$/</pattern></options> - <message>The "manage_stock" field must be set to 0 or 1.</message> - </regex> - </manage_stock> - <use_config_manage_stock> - <regex translate="message" module="Mage_Api2"> - <type>Regex</type> - <options><pattern>/^[0,1]$/</pattern></options> - <message>The "use_config_manage_stock" field must be set to 0 or 1.</message> - </regex> - </use_config_manage_stock> - <qty> - <required>1</required> - <between> - <type>Between</type> - <options><min>-99999999.9999</min><max>99999999.9999</max></options> - </between> - </qty> - <min_qty> - <float translate="message" module="Mage_Api2"> - <type>Float</type> - <message>Please enter a valid number in "min_qty" field</message> - </float> - <between> - <type>Between</type> - <options><min>0</min><max>99999999.9999</max></options> - </between> - </min_qty> - <use_config_min_qty> - <regex translate="message" module="Mage_Api2"> - <type>Regex</type> - <options><pattern>/^[0,1]$/</pattern></options> - <message>The "use_config_min_qty" field must be set to 0 or 1.</message> - </regex> - </use_config_min_qty> - <is_qty_decimal> - <regex translate="message" module="Mage_Api2"> - <type>Regex</type> - <options><pattern>/^[0,1]$/</pattern></options> - <message>The "is_qty_decimal" field must be set to 0 or 1.</message> - </regex> - </is_qty_decimal> - <backorders> - <regex translate="message" module="Mage_Api2"> - <type>Regex</type> - <options><pattern>/^[0,1,2]$/</pattern></options> - <message>The "is_qty_decimal" field must be set to 0, 1, or 2.</message> - </regex> - </backorders> - <use_config_backorders> - <regex translate="message" module="Mage_Api2"> - <type>Regex</type> - <options><pattern>/^[0,1]$/</pattern></options> - <message>The "use_config_backorders" field must be set to 0 or 1.</message> - </regex> - </use_config_backorders> - <min_sale_qty> - <int translate="message" module="Mage_Api2"> - <type>Int</type> - <message>Please enter a valid number in "min_sale_qty" field</message> - </int> - <between> - <type>Between</type> - <options><min>0</min><max>99999999</max></options> - </between> - </min_sale_qty> - <use_config_min_sale_qty> - <regex translate="message" module="Mage_Api2"> - <type>Regex</type> - <options><pattern>/^[0,1]$/</pattern></options> - <message>The "use_config_min_sale_qty" field must be set to 0 or 1.</message> - </regex> - </use_config_min_sale_qty> - <max_sale_qty> - <int translate="message" module="Mage_Api2"> - <type>Int</type> - <message>Please enter a valid number in "max_sale_qty" field</message> - </int> - <between> - <type>Between</type> - <options><min>0</min><max>99999999</max></options> - </between> - </max_sale_qty> - <use_config_max_sale_qty> - <regex translate="message" module="Mage_Api2"> - <type>Regex</type> - <options><pattern>/^[0,1]$/</pattern></options> - <message>The "use_config_max_sale_qty" field must be set to 0 or 1.</message> - </regex> - </use_config_max_sale_qty> - <is_in_stock> - <regex translate="message" module="Mage_Api2"> - <type>Regex</type> - <options><pattern>/^[0,1]$/</pattern></options> - <message>The "is_in_stock" field must be set to 0 or 1.</message> - </regex> - </is_in_stock> - <notify_stock_qty> - <float translate="message" module="Mage_Api2"> - <type>Float</type> - <message>Please enter a valid number in "notify_stock_qty" field</message> - </float> - </notify_stock_qty> - <use_config_notify_stock_qty> - <regex translate="message" module="Mage_Api2"> - <type>Regex</type> - <options><pattern>/^[0,1]$/</pattern></options> - <message>The "use_config_notify_stock_qty" field must be set to 0 or 1.</message> - </regex> - </use_config_notify_stock_qty> - <stock_status_changed_auto> - <regex translate="message" module="Mage_Api2"> - <type>Regex</type> - <options><pattern>/^[0,1]$/</pattern></options> - <message>The "stock_status_changed_auto" field must be set to 0 or 1.</message> - </regex> - </stock_status_changed_auto> - <use_config_qty_increments> - <regex translate="message" module="Mage_Api2"> - <type>Regex</type> - <options><pattern>/^[0,1]$/</pattern></options> - <message>The "use_config_qty_increments" field must be set to 0 or 1.</message> - </regex> - </use_config_qty_increments> - <qty_increments> - <int translate="message" module="Mage_Api2"> - <type>Int</type> - <message>Please use numbers only in "qty_increments" field. Please avoid spaces or other characters such as dots or commas.</message> - </int> - <between translate="message" module="Mage_Api2"> - <type>Between</type> - <options><min>0</min><max>99999999</max></options> - <message>Please use numbers only in "qty_increments" field. Please avoid spaces or other characters such as dots or commas.</message> - </between> - </qty_increments> - <use_config_enable_qty_inc> - <regex translate="message" module="Mage_Api2"> - <type>Regex</type> - <options><pattern>/^[0,1]$/</pattern></options> - <message>The "use_config_enable_qty_inc" field must be set to 0 or 1.</message> - </regex> - </use_config_enable_qty_inc> - <enable_qty_increments> - <regex translate="message" module="Mage_Api2"> - <type>Regex</type> - <options><pattern>/^[0,1]$/</pattern></options> - <message>The "enable_qty_increments" field must be set to 0 or 1.</message> - </regex> - </enable_qty_increments> - <is_decimal_divided> - <regex translate="message" module="Mage_Api2"> - <type>Regex</type> - <options><pattern>/^[0,1]$/</pattern></options> - <message>The "is_decimal_divided" field must be set to 0 or 1.</message> - </regex> - </is_decimal_divided> - </fields> - </validators> - <versions>1</versions> - </stock_item> - </resources> - </api2> -</config> diff --git a/app/code/core/Mage/CatalogInventory/etc/wsdl.xml b/app/code/core/Mage/CatalogInventory/etc/wsdl.xml deleted file mode 100644 index 6291e9cc039c808324dde7c81965c9368f8655b8..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/CatalogInventory/etc/wsdl.xml +++ /dev/null @@ -1,102 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<definitions xmlns:typens="urn:{{var wsdl.name}}" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" - xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns="http://schemas.xmlsoap.org/wsdl/" - name="{{var wsdl.name}}" targetNamespace="urn:{{var wsdl.name}}"> - <types> - <schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:Magento"> - <import namespace="http://schemas.xmlsoap.org/soap/encoding/" schemaLocation="http://schemas.xmlsoap.org/soap/encoding/" /> - <complexType name="catalogInventoryStockItemEntity"> - <all> - <element name="product_id" type="xsd:string" minOccurs="0" /> - <element name="sku" type="xsd:string" minOccurs="0" /> - <element name="qty" type="xsd:string" minOccurs="0" /> - <element name="is_in_stock" type="xsd:string" minOccurs="0" /> - </all> - </complexType> - <complexType name="catalogInventoryStockItemEntityArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:catalogInventoryStockItemEntity[]" /> - </restriction> - </complexContent> - </complexType> - <complexType name="catalogInventoryStockItemUpdateEntity"> - <all> - <element name="qty" type="xsd:string" minOccurs="0" /> - <element name="is_in_stock" type="xsd:int" minOccurs="0" /> - <element name="manage_stock" type="xsd:int" minOccurs="0" /> - <element name="use_config_manage_stock" type="xsd:int" minOccurs="0" /> - <element name="min_qty" type="xsd:int" minOccurs="0" /> - <element name="use_config_min_qty" type="xsd:int" minOccurs="0" /> - <element name="min_sale_qty" type="xsd:int" minOccurs="0" /> - <element name="use_config_min_sale_qty" type="xsd:int" minOccurs="0" /> - <element name="max_sale_qty" type="xsd:int" minOccurs="0" /> - <element name="use_config_max_sale_qty" type="xsd:int" minOccurs="0" /> - <element name="is_qty_decimal" type="xsd:int" minOccurs="0" /> - <element name="backorders" type="xsd:int" minOccurs="0" /> - <element name="use_config_backorders" type="xsd:int" minOccurs="0" /> - <element name="notify_stock_qty" type="xsd:int" minOccurs="0" /> - <element name="use_config_notify_stock_qty" type="xsd:int" minOccurs="0" /> - </all> - </complexType> - <complexType name="catalogProductCreateEntity"> - <all> - <element name="stock_data" type="typens:catalogInventoryStockItemUpdateEntity" minOccurs="0" /> - </all> - </complexType> - </schema> - </types> - <message name="catalogInventoryStockItemListRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="products" type="typens:ArrayOfString" /> - </message> - <message name="catalogInventoryStockItemListResponse"> - <part name="result" type="typens:catalogInventoryStockItemEntityArray" /> - </message> - <message name="catalogInventoryStockItemUpdateRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="product" type="xsd:string" /> - <part name="data" type="typens:catalogInventoryStockItemUpdateEntity" /> - </message> - <message name="catalogInventoryStockItemUpdateResponse"> - <part name="result" type="xsd:int" /> - </message> - <portType name="{{var wsdl.handler}}PortType"> - <operation name="catalogInventoryStockItemList"> - <documentation>Retrieve stock data by product ids</documentation> - <input message="typens:catalogInventoryStockItemListRequest" /> - <output message="typens:catalogInventoryStockItemListResponse" /> - </operation> - <operation name="catalogInventoryStockItemUpdate"> - <documentation>Update product stock data</documentation> - <input message="typens:catalogInventoryStockItemUpdateRequest" /> - <output message="typens:catalogInventoryStockItemUpdateResponse" /> - </operation> - </portType> - <binding name="{{var wsdl.handler}}Binding" type="typens:{{var wsdl.handler}}PortType"> - <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" /> - <operation name="catalogInventoryStockItemList"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="catalogInventoryStockItemUpdate"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - </binding> - <service name="{{var wsdl.name}}Service"> - <port name="{{var wsdl.handler}}Port" binding="typens:{{var wsdl.handler}}Binding"> - <soap:address location="{{var wsdl.url}}" /> - </port> - </service> -</definitions> diff --git a/app/code/core/Mage/CatalogInventory/etc/wsi.xml b/app/code/core/Mage/CatalogInventory/etc/wsi.xml deleted file mode 100644 index 6812d85cb0547701931247ae6ab92bd75f4bda87..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/CatalogInventory/etc/wsi.xml +++ /dev/null @@ -1,133 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<wsdl:definitions xmlns:typens="urn:{{var wsdl.name}}" - xmlns:xsd="http://www.w3.org/2001/XMLSchema" - xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" - xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" - xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" - name="{{var wsdl.name}}" - targetNamespace="urn:{{var wsdl.name}}"> - <wsdl:types> - <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:{{var wsdl.name}}"> - <xsd:complexType name="catalogInventoryStockItemEntity"> - <xsd:sequence> - <xsd:element name="product_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="sku" type="xsd:string" minOccurs="0" /> - <xsd:element name="qty" type="xsd:string" minOccurs="0" /> - <xsd:element name="is_in_stock" type="xsd:string" minOccurs="0" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogInventoryStockItemEntityArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:catalogInventoryStockItemEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogInventoryStockItemUpdateEntity"> - <xsd:sequence> - <xsd:element name="qty" type="xsd:string" minOccurs="0" /> - <xsd:element name="is_in_stock" type="xsd:int" minOccurs="0" /> - <xsd:element name="manage_stock" type="xsd:int" minOccurs="0" /> - <xsd:element name="use_config_manage_stock" type="xsd:int" minOccurs="0" /> - <xsd:element name="min_qty" type="xsd:int" minOccurs="0" /> - <xsd:element name="use_config_min_qty" type="xsd:int" minOccurs="0" /> - <xsd:element name="min_sale_qty" type="xsd:int" minOccurs="0" /> - <xsd:element name="use_config_min_sale_qty" type="xsd:int" minOccurs="0" /> - <xsd:element name="max_sale_qty" type="xsd:int" minOccurs="0" /> - <xsd:element name="use_config_max_sale_qty" type="xsd:int" minOccurs="0" /> - <xsd:element name="is_qty_decimal" type="xsd:int" minOccurs="0" /> - <xsd:element name="backorders" type="xsd:int" minOccurs="0" /> - <xsd:element name="use_config_backorders" type="xsd:int" minOccurs="0" /> - <xsd:element name="notify_stock_qty" type="xsd:int" minOccurs="0" /> - <xsd:element name="use_config_notify_stock_qty" type="xsd:int" minOccurs="0" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductCreateEntity"> - <xsd:sequence> - <xsd:element name="stock_data" type="typens:catalogInventoryStockItemUpdateEntity" minOccurs="0" /> - </xsd:sequence> - </xsd:complexType> - - - <xsd:element name="catalogInventoryStockItemListRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="productIds" type="typens:ArrayOfString" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogInventoryStockItemListResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:catalogInventoryStockItemEntityArray" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogInventoryStockItemUpdateRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="productId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="data" type="typens:catalogInventoryStockItemUpdateEntity" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogInventoryStockItemUpdateResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - </xsd:schema> - </wsdl:types> - <wsdl:message name="catalogInventoryStockItemListRequest"> - <wsdl:part name="parameters" element="typens:catalogInventoryStockItemListRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogInventoryStockItemListResponse"> - <wsdl:part name="parameters" element="typens:catalogInventoryStockItemListResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogInventoryStockItemUpdateRequest"> - <wsdl:part name="parameters" element="typens:catalogInventoryStockItemUpdateRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogInventoryStockItemUpdateResponse"> - <wsdl:part name="parameters" element="typens:catalogInventoryStockItemUpdateResponseParam" /> - </wsdl:message> - <wsdl:portType name="{{var wsdl.handler}}PortType"> - <wsdl:operation name="catalogInventoryStockItemList"> - <wsdl:documentation>Retrieve stock data by product ids</wsdl:documentation> - <wsdl:input message="typens:catalogInventoryStockItemListRequest" /> - <wsdl:output message="typens:catalogInventoryStockItemListResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogInventoryStockItemUpdate"> - <wsdl:documentation>Update product stock data</wsdl:documentation> - <wsdl:input message="typens:catalogInventoryStockItemUpdateRequest" /> - <wsdl:output message="typens:catalogInventoryStockItemUpdateResponse" /> - </wsdl:operation> - </wsdl:portType> - <wsdl:binding name="{{var wsdl.handler}}Binding" type="typens:{{var wsdl.handler}}PortType"> - <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" /> - <wsdl:operation name="catalogInventoryStockItemList"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogInventoryStockItemUpdate"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - </wsdl:binding> - <wsdl:service name="{{var wsdl.name}}Service"> - <wsdl:port name="{{var wsdl.handler}}Port" binding="typens:{{var wsdl.handler}}Binding"> - <soap:address location="{{var wsdl.url}}" /> - </wsdl:port> - </wsdl:service> -</wsdl:definitions> diff --git a/app/code/core/Mage/Checkout/Model/Api/Resource.php b/app/code/core/Mage/Checkout/Model/Api/Resource.php deleted file mode 100644 index 803a1c827673d755caa772b39ddd48cb28b151e7..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Checkout/Model/Api/Resource.php +++ /dev/null @@ -1,238 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Checkout - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Checkout api resource - * - * @category Mage - * @package Mage_Checkout - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Checkout_Model_Api_Resource extends Mage_Api_Model_Resource_Abstract -{ - /** - * Attributes map array per entity type - * - * @var array - */ - protected $_attributesMap = array( - 'global' => array(), - ); - - /** - * Default ignored attribute codes per entity type - * - * @var array - */ - protected $_ignoredAttributeCodes = array( - 'global' => array('entity_id', 'attribute_set_id', 'entity_type_id') - ); - - /** - * Field name in session for saving store id - * @var string - */ - protected $_storeIdSessionField = 'store_id'; - - - /** - * Check if quote already exist with provided quoteId for creating - * - * @param int $quoteId - * @return bool - */ - protected function _isQuoteExist($quoteId) - { - if (empty($quoteId)) { - return false; - } - - try { - $quote = $this->_getQuote($quoteId); - } catch (Mage_Api_Exception $e) { - return false; - } - - if (!is_null($quote->getId())) { - $this->_fault('quote_already_exist'); - } - - return false; - } - - /** - * Retrieves store id from store code, if no store id specified, - * it use set session or admin store - * - * @param string|int $store - * @return int - */ - protected function _getStoreId($store = null) - { - if (is_null($store)) { - $store = ($this->_getSession()->hasData($this->_storeIdSessionField) - ? $this->_getSession()->getData($this->_storeIdSessionField) : 0); - } - - try { - $storeId = Mage::app()->getStore($store)->getId(); - - } catch (Mage_Core_Model_Store_Exception $e) { - $this->_fault('store_not_exists'); - } - - return $storeId; - } - - /** - * Retrieves quote by quote identifier and store code or by quote identifier - * - * @param int $quoteId - * @param string|int $store - * @return Mage_Sales_Model_Quote - */ - protected function _getQuote($quoteId, $store = null) - { - /** @var $quote Mage_Sales_Model_Quote */ - $quote = Mage::getModel('Mage_Sales_Model_Quote'); - - if (!(is_string($store) || is_integer($store))) { - $quote->loadByIdWithoutStore($quoteId); - } else { - $storeId = $this->_getStoreId($store); - - $quote->setStoreId($storeId) - ->load($quoteId); - } - if (is_null($quote->getId())) { - $this->_fault('quote_not_exists'); - } - - return $quote; - } - - /** - * Get store identifier by quote identifier - * - * @param int $quoteId - * @return int - */ - protected function _getStoreIdFromQuote($quoteId) - { - /** @var $quote Mage_Sales_Model_Quote */ - $quote = Mage::getModel('Mage_Sales_Model_Quote') - ->loadByIdWithoutStore($quoteId); - - return $quote->getStoreId(); - } - - /** - * Update attributes for entity - * - * @param array $data - * @param Mage_Core_Model_Abstract $object - * @param string $type - * @param array|null $attributes - * @return Mage_Checkout_Model_Api_Resource - */ - protected function _updateAttributes($data, $object, $type, array $attributes = null) - { - foreach ($data as $attribute=>$value) { - if ($this->_isAllowedAttribute($attribute, $type, $attributes)) { - $object->setData($attribute, $value); - } - } - - return $this; - } - - /** - * Retrieve entity attributes values - * - * @param Mage_Core_Model_Abstract $object - * @param string $type - * @param array $attributes - * @return Mage_Checkout_Model_Api_Resource - */ - protected function _getAttributes($object, $type, array $attributes = null) - { - $result = array(); - - if (!is_object($object)) { - return $result; - } - - foreach ($object->getData() as $attribute=>$value) { - if (is_object($value)) { - continue; - } - - if ($this->_isAllowedAttribute($attribute, $type, $attributes)) { - $result[$attribute] = $value; - } - } - - foreach ($this->_attributesMap['global'] as $alias=>$attributeCode) { - $result[$alias] = $object->getData($attributeCode); - } - - if (isset($this->_attributesMap[$type])) { - foreach ($this->_attributesMap[$type] as $alias=>$attributeCode) { - $result[$alias] = $object->getData($attributeCode); - } - } - - return $result; - } - - /** - * Check is attribute allowed to usage - * - * @param Mage_Eav_Model_Entity_Attribute_Abstract $attribute - * @param string $type - * @param array $attributes - * @return bool - */ - protected function _isAllowedAttribute($attributeCode, $type, array $attributes = null) - { - if (!empty($attributes) - && !(in_array($attributeCode, $attributes))) { - return false; - } - - if (in_array($attributeCode, $this->_ignoredAttributeCodes['global'])) { - return false; - } - - if (isset($this->_ignoredAttributeCodes[$type]) - && in_array($attributeCode, $this->_ignoredAttributeCodes[$type])) { - return false; - } - - return true; - } - -} diff --git a/app/code/core/Mage/Checkout/Model/Api/Resource/Customer.php b/app/code/core/Mage/Checkout/Model/Api/Resource/Customer.php deleted file mode 100644 index 92468a41c67b796bd77007e6e474b6f2fa237306..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Checkout/Model/Api/Resource/Customer.php +++ /dev/null @@ -1,213 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Checkout - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Checkout api resource for Customer - * - * @category Mage - * @package Mage_Checkout - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Checkout_Model_Api_Resource_Customer extends Mage_Checkout_Model_Api_Resource -{ - /** - * Customer address types - */ - const ADDRESS_BILLING = Mage_Sales_Model_Quote_Address::TYPE_BILLING; - const ADDRESS_SHIPPING = Mage_Sales_Model_Quote_Address::TYPE_SHIPPING; - - /** - * Customer checkout types - */ - const MODE_CUSTOMER = Mage_Checkout_Model_Type_Onepage::METHOD_CUSTOMER; - const MODE_REGISTER = Mage_Checkout_Model_Type_Onepage::METHOD_REGISTER; - const MODE_GUEST = Mage_Checkout_Model_Type_Onepage::METHOD_GUEST; - - - /** - * - */ - protected function _getCustomer($customerId) - { - /** @var $customer Mage_Customer_Model_Customer */ - $customer = Mage::getModel('Mage_Customer_Model_Customer') - ->load($customerId); - if (!$customer->getId()) { - $this->_fault('customer_not_exists'); - } - - return $customer; - } - - /** - * Get customer address by identifier - * - * @param int $addressId - * @return Mage_Customer_Model_Address - */ - protected function _getCustomerAddress($addressId) - { - $address = Mage::getModel('Mage_Customer_Model_Address')->load((int)$addressId); - if (is_null($address->getId())) { - $this->_fault('invalid_address_id'); - } - - $address->explodeStreetAddress(); - if ($address->getRegionId()) { - $address->setRegion($address->getRegionId()); - } - return $address; - } - - /** - * @param Mage_Sales_Model_Quote $quote - * @return bool - */ - public function prepareCustomerForQuote(Mage_Sales_Model_Quote $quote) - { - $isNewCustomer = false; - switch ($quote->getCheckoutMethod()) { - case self::MODE_GUEST: - $this->_prepareGuestQuote($quote); - break; - case self::MODE_REGISTER: - $this->_prepareNewCustomerQuote($quote); - $isNewCustomer = true; - break; - default: - $this->_prepareCustomerQuote($quote); - break; - } - - return $isNewCustomer; - } - - /** - * Prepare quote for guest checkout order submit - * - * @param Mage_Sales_Model_Quote $quote - * @return Mage_Checkout_Model_Api_Resource_Customer - */ - protected function _prepareGuestQuote(Mage_Sales_Model_Quote $quote) - { - $quote->setCustomerId(null) - ->setCustomerEmail($quote->getBillingAddress()->getEmail()) - ->setCustomerIsGuest(true) - ->setCustomerGroupId(Mage_Customer_Model_Group::NOT_LOGGED_IN_ID); - return $this; - } - - /** - * Prepare quote for customer registration and customer order submit - * - * @param Mage_Sales_Model_Quote $quote - * @return Mage_Checkout_Model_Api_Resource_Customer - */ - protected function _prepareNewCustomerQuote(Mage_Sales_Model_Quote $quote) - { - $billing = $quote->getBillingAddress(); - $shipping = $quote->isVirtual() ? null : $quote->getShippingAddress(); - - //$customer = Mage::getModel('Mage_Customer_Model_Customer'); - $customer = $quote->getCustomer(); - /* @var $customer Mage_Customer_Model_Customer */ - $customerBilling = $billing->exportCustomerAddress(); - $customer->addAddress($customerBilling); - $billing->setCustomerAddress($customerBilling); - $customerBilling->setIsDefaultBilling(true); - if ($shipping && !$shipping->getSameAsBilling()) { - $customerShipping = $shipping->exportCustomerAddress(); - $customer->addAddress($customerShipping); - $shipping->setCustomerAddress($customerShipping); - $customerShipping->setIsDefaultShipping(true); - } else { - $customerBilling->setIsDefaultShipping(true); - } - - Mage::helper('Mage_Core_Helper_Data')->copyFieldset('checkout_onepage_quote', 'to_customer', $quote, $customer); - $customer->setPassword($customer->decryptPassword($quote->getPasswordHash())); - $customer->setPasswordHash($customer->hashPassword($customer->getPassword())); - $quote->setCustomer($customer) - ->setCustomerId(true); - - return $this; - } - - /** - * Prepare quote for customer order submit - * - * @param Mage_Sales_Model_Quote $quote - * @return Mage_Checkout_Model_Api_Resource_Customer - */ - protected function _prepareCustomerQuote(Mage_Sales_Model_Quote $quote) - { - $billing = $quote->getBillingAddress(); - $shipping = $quote->isVirtual() ? null : $quote->getShippingAddress(); - - $customer = $quote->getCustomer(); - if (!$billing->getCustomerId() || $billing->getSaveInAddressBook()) { - $customerBilling = $billing->exportCustomerAddress(); - $customer->addAddress($customerBilling); - $billing->setCustomerAddress($customerBilling); - } - if ($shipping && ((!$shipping->getCustomerId() && !$shipping->getSameAsBilling()) - || (!$shipping->getSameAsBilling() && $shipping->getSaveInAddressBook()))) { - $customerShipping = $shipping->exportCustomerAddress(); - $customer->addAddress($customerShipping); - $shipping->setCustomerAddress($customerShipping); - } - - if (isset($customerBilling) && !$customer->getDefaultBilling()) { - $customerBilling->setIsDefaultBilling(true); - } - if ($shipping && isset($customerShipping) && !$customer->getDefaultShipping()) { - $customerShipping->setIsDefaultShipping(true); - } else if (isset($customerBilling) && !$customer->getDefaultShipping()) { - $customerBilling->setIsDefaultShipping(true); - } - $quote->setCustomer($customer); - - return $this; - } - - /** - * Involve new customer to system - * - * @param Mage_Sales_Model_Quote $quote - * @return Mage_Checkout_Model_Api_Resource_Customer - */ - public function involveNewCustomer(Mage_Sales_Model_Quote $quote) - { - $customer = $quote->getCustomer(); - if ($customer->isConfirmationRequired()) { - $customer->sendNewAccountEmail('confirmation'); - } else { - $customer->sendNewAccountEmail(); - } - - return $this; - } -} diff --git a/app/code/core/Mage/Checkout/Model/Api/Resource/Product.php b/app/code/core/Mage/Checkout/Model/Api/Resource/Product.php deleted file mode 100644 index 8dee2febcf920d04e989fdd9d25072d4f59e845b..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Checkout/Model/Api/Resource/Product.php +++ /dev/null @@ -1,128 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Checkout - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API Resource class for product - */ -class Mage_Checkout_Model_Api_Resource_Product extends Mage_Checkout_Model_Api_Resource -{ - /** - * Default ignored attribute codes - * - * @var array - */ - protected $_ignoredAttributeCodes = array('entity_id', 'attribute_set_id', 'entity_type_id'); - - /** - * Return loaded product instance - * - * @param int|string $productId (SKU or ID) - * @param int|string $store - * @param string $identifierType - * @return Mage_Catalog_Model_Product - */ - protected function _getProduct($productId, $store = null, $identifierType = null) - { - $product = Mage::helper('Mage_Catalog_Helper_Product')->getProduct($productId, - $this->_getStoreId($store), - $identifierType - ); - return $product; - } - - /** - * Get request for product add to cart procedure - * - * @param mixed $requestInfo - * @return Varien_Object - */ - protected function _getProductRequest($requestInfo) - { - if ($requestInfo instanceof Varien_Object) { - $request = $requestInfo; - } elseif (is_numeric($requestInfo)) { - $request = new Varien_Object(); - $request->setQty($requestInfo); - } else { - $request = new Varien_Object($requestInfo); - } - - if (!$request->hasQty()) { - $request->setQty(1); - } - return $request; - } - - /** - * Get QuoteItem by Product and request info - * - * @param Mage_Sales_Model_Quote $quote - * @param Mage_Catalog_Model_Product $product - * @param Varien_Object $requestInfo - * @return Mage_Sales_Model_Quote_Item - * @throw Mage_Core_Exception - */ - protected function _getQuoteItemByProduct(Mage_Sales_Model_Quote $quote, - Mage_Catalog_Model_Product $product, - Varien_Object $requestInfo) - { - $cartCandidates = $product->getTypeInstance() - ->prepareForCartAdvanced($requestInfo, - $product, - Mage_Catalog_Model_Product_Type_Abstract::PROCESS_MODE_FULL - ); - - /** - * Error message - */ - if (is_string($cartCandidates)) { - throw Mage::throwException($cartCandidates); - } - - /** - * If prepare process return one object - */ - if (!is_array($cartCandidates)) { - $cartCandidates = array($cartCandidates); - } - - /** @var $item Mage_Sales_Model_Quote_Item */ - $item = null; - foreach ($cartCandidates as $candidate) { - if ($candidate->getParentProductId()) { - continue; - } - - $item = $quote->getItemByProduct($candidate); - } - - if (is_null($item)) { - $item = Mage::getModel('Mage_Sales_Model_Quote_Item'); - } - - return $item; - } -} diff --git a/app/code/core/Mage/Checkout/Model/Cart/Api.php b/app/code/core/Mage/Checkout/Model/Cart/Api.php deleted file mode 100644 index a8d941352539fa4b428d14c80fdcecd37f0704a6..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Checkout/Model/Cart/Api.php +++ /dev/null @@ -1,219 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Checkout - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Shopping cart api - * - * @category Mage - * @package Mage_Checkout - * @author Magento Core Team <core@magentocommerce.com> - */ - -class Mage_Checkout_Model_Cart_Api extends Mage_Checkout_Model_Api_Resource -{ - public function __construct() - { - $this->_storeIdSessionField = "cart_store_id"; - $this->_attributesMap['quote'] = array('quote_id' => 'entity_id'); - $this->_attributesMap['quote_customer'] = array('customer_id' => 'entity_id'); - $this->_attributesMap['quote_address'] = array('address_id' => 'entity_id'); - $this->_attributesMap['quote_payment'] = array('payment_id' => 'entity_id'); - } - - /** - * Create new quote for shopping cart - * - * @param int|string $store - * @return int - */ - public function create($store = null) - { - $storeId = $this->_getStoreId($store); - - try { - /*@var $quote Mage_Sales_Model_Quote*/ - $quote = Mage::getModel('Mage_Sales_Model_Quote'); - $quote->setStoreId($storeId) - ->setIsActive(false) - ->setIsMultiShipping(false) - ->save(); - } catch (Mage_Core_Exception $e) { - $this->_fault('create_quote_fault', $e->getMessage()); - } - return (int) $quote->getId(); - } - - /** - * Retrieve full information about quote - * - * @param $quoteId - * @param $store - * @return array - */ - public function info($quoteId, $store = null) - { - $quote = $this->_getQuote($quoteId, $store); - - if ($quote->getGiftMessageId() > 0) { - $quote->setGiftMessage( - Mage::getSingleton('Mage_GiftMessage_Model_Message')->load($quote->getGiftMessageId())->getMessage() - ); - } - - $result = $this->_getAttributes($quote, 'quote'); - $result['shipping_address'] = $this->_getAttributes($quote->getShippingAddress(), 'quote_address'); - $result['billing_address'] = $this->_getAttributes($quote->getBillingAddress(), 'quote_address'); - $result['items'] = array(); - - foreach ($quote->getAllItems() as $item) { - if ($item->getGiftMessageId() > 0) { - $item->setGiftMessage( - Mage::getSingleton('Mage_GiftMessage_Model_Message')->load($item->getGiftMessageId())->getMessage() - ); - } - - $result['items'][] = $this->_getAttributes($item, 'quote_item'); - } - - $result['payment'] = $this->_getAttributes($quote->getPayment(), 'quote_payment'); - - return $result; - } - - /** - * @param $quoteId - * @param $store - * @return void - */ - public function totals($quoteId, $store = null) - { - $quote = $this->_getQuote($quoteId, $store); - - $totals = $quote->getTotals(); - - $totalsResult = array(); - foreach ($totals as $total) { - $totalsResult[] = array( - "title" => $total->getTitle(), - "amount" => $total->getValue() - ); - } - return $totalsResult; - } - - /** - * Create an order from the shopping cart (quote) - * - * @param $quoteId - * @param $store - * @param $agreements array - * @return string - */ - public function createOrder($quoteId, $store = null, $agreements = null) - { - $requiredAgreements = Mage::helper('Mage_Checkout_Helper_Data')->getRequiredAgreementIds(); - if (!empty($requiredAgreements)) { - $diff = array_diff($agreements, $requiredAgreements); - if (!empty($diff)) { - $this->_fault('required_agreements_are_not_all'); - } - } - - $quote = $this->_getQuote($quoteId, $store); - if ($quote->getIsMultiShipping()) { - $this->_fault('invalid_checkout_type'); - } - if ($quote->getCheckoutMethod() == Mage_Checkout_Model_Api_Resource_Customer::MODE_GUEST - && !Mage::helper('Mage_Checkout_Helper_Data')->isAllowedGuestCheckout($quote, $quote->getStoreId())) { - $this->_fault('guest_checkout_is_not_enabled'); - } - - /** @var $customerResource Mage_Checkout_Model_Api_Resource_Customer */ - $customerResource = Mage::getModel('Mage_Checkout_Model_Api_Resource_Customer'); - $isNewCustomer = $customerResource->prepareCustomerForQuote($quote); - - try { - $quote->collectTotals(); - /** @var $service Mage_Sales_Model_Service_Quote */ - $service = Mage::getModel('Mage_Sales_Model_Service_Quote', array('quote' => $quote)); - $service->submitAll(); - - if ($isNewCustomer) { - try { - $customerResource->involveNewCustomer($quote); - } catch (Exception $e) { - Mage::logException($e); - } - } - - $order = $service->getOrder(); - if ($order) { - Mage::dispatchEvent('checkout_type_onepage_save_order_after', - array('order' => $order, 'quote' => $quote)); - - try { - $order->sendNewOrderEmail(); - } catch (Exception $e) { - Mage::logException($e); - } - } - - Mage::dispatchEvent( - 'checkout_submit_all_after', - array('order' => $order, 'quote' => $quote) - ); - } catch (Mage_Core_Exception $e) { - $this->_fault('create_order_fault', $e->getMessage()); - } - - return $order->getIncrementId(); - } - - /** - * @param $quoteId - * @param $store - * @return array - */ - public function licenseAgreement($quoteId, $store = null) - { - $quote = $this->_getQuote($quoteId, $store); - $storeId = $quote->getStoreId(); - - $agreements = array(); - if (Mage::getStoreConfigFlag('checkout/options/enable_agreements')) { - $agreementsCollection = Mage::getModel('Mage_Checkout_Model_Agreement')->getCollection() - ->addStoreFilter($storeId) - ->addFieldToFilter('is_active', 1); - - foreach ($agreementsCollection as $_a) { - /** @var $_a Mage_Checkout_Model_Agreement */ - $agreements[] = $this->_getAttributes($_a, "quote_agreement"); - } - } - - return $agreements; - } -} diff --git a/app/code/core/Mage/Checkout/Model/Cart/Coupon/Api.php b/app/code/core/Mage/Checkout/Model/Cart/Coupon/Api.php deleted file mode 100644 index 32a0d1ba59922028e387e7edee04fbab981aa511..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Checkout/Model/Cart/Coupon/Api.php +++ /dev/null @@ -1,109 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Checkout - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Shopping cart api - * - * @category Mage - * @package Mage_Checkout - * @author Magento Core Team <core@magentocommerce.com> - */ - -class Mage_Checkout_Model_Cart_Coupon_Api extends Mage_Checkout_Model_Api_Resource -{ - /** - * @param $quoteId - * @param $couponCode - * @param $storeId - * @return bool - */ - public function add($quoteId, $couponCode, $store = null) - { - return $this->_applyCoupon($quoteId, $couponCode, $store = null); - } - - /** - * @param $quoteId - * @param $storeId - * @return void - */ - public function remove($quoteId, $store = null) - { - $couponCode = ''; - return $this->_applyCoupon($quoteId, $couponCode, $store); - } - - /** - * @param $quoteId - * @param $storeId - * @return string - */ - public function get($quoteId, $store = null) - { - $quote = $this->_getQuote($quoteId, $store); - - return $quote->getCouponCode(); - } - - /** - * @param $quoteId - * @param $couponCode - * @param $store - * @return bool - */ - protected function _applyCoupon($quoteId, $couponCode, $store = null) - { - $quote = $this->_getQuote($quoteId, $store); - - if (!$quote->getItemsCount()) { - $this->_fault('quote_is_empty'); - } - - $oldCouponCode = $quote->getCouponCode(); - if (!strlen($couponCode) && !strlen($oldCouponCode)) { - return false; - } - - try { - $quote->getShippingAddress()->setCollectShippingRates(true); - $quote->setCouponCode(strlen($couponCode) ? $couponCode : '') - ->collectTotals() - ->save(); - } catch (Exception $e) { - $this->_fault("cannot_apply_coupon_code", $e->getMessage()); - } - - if ($couponCode) { - if (!$couponCode == $quote->getCouponCode()) { - $this->_fault('coupon_code_is_not_valid'); - } - } - - return true; - } - - -} diff --git a/app/code/core/Mage/Checkout/Model/Cart/Coupon/Api/V2.php b/app/code/core/Mage/Checkout/Model/Cart/Coupon/Api/V2.php deleted file mode 100644 index 0955718728ffeae91c0e93a13d561d5d2dc18fd5..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Checkout/Model/Cart/Coupon/Api/V2.php +++ /dev/null @@ -1,38 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Checkout - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Shopping cart api - * - * @category Mage - * @package Mage_Checkout - * @author Magento Core Team <core@magentocommerce.com> - */ - -class Mage_Checkout_Model_Cart_Coupon_Api_V2 extends Mage_Checkout_Model_Cart_Coupon_Api -{ - -} diff --git a/app/code/core/Mage/Checkout/Model/Cart/Customer/Api.php b/app/code/core/Mage/Checkout/Model/Cart/Customer/Api.php deleted file mode 100644 index 8f62dc8fcc81ffc0581d48e9cda5b10083a399bc..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Checkout/Model/Cart/Customer/Api.php +++ /dev/null @@ -1,239 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Checkout - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Shopping cart api for customer data - * - * @category Mage - * @package Mage_Checkout - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Checkout_Model_Cart_Customer_Api extends Mage_Checkout_Model_Api_Resource_Customer -{ - public function __construct() - { - $this->_storeIdSessionField = "cart_store_id"; - - $this->_attributesMap['quote'] = array('quote_id' => 'entity_id'); - $this->_attributesMap['quote_customer'] = array('customer_id' => 'entity_id'); - $this->_attributesMap['quote_address'] = array('address_id' => 'entity_id'); - } - - /** - * Set customer for shopping cart - * - * @param int $quoteId - * @param array|object $customerData - * @param int | string $store - * @return int - */ - public function set($quoteId, $customerData, $store = null) - { - $quote = $this->_getQuote($quoteId, $store); - - $customerData = $this->_prepareCustomerData($customerData); - if (!isset($customerData['mode'])) { - $this->_fault('customer_mode_is_unknown'); - } - - switch($customerData['mode']) { - case self::MODE_CUSTOMER: - /** @var $customer Mage_Customer_Model_Customer */ - $customer = $this->_getCustomer($customerData['entity_id']); - $customer->setMode(self::MODE_CUSTOMER); - break; - - case self::MODE_REGISTER: - case self::MODE_GUEST: - /** @var $customer Mage_Customer_Model_Customer */ - $customer = Mage::getModel('Mage_Customer_Model_Customer') - ->setData($customerData); - - if ($customer->getMode() == self::MODE_GUEST) { - $password = $customer->generatePassword(); - - $customer - ->setPassword($password) - ->setConfirmation($password); - } - - $isCustomerValid = $customer->validate(); - if ($isCustomerValid !== true && is_array($isCustomerValid)) { - $this->_fault('customer_data_invalid', implode(PHP_EOL, $isCustomerValid)); - } - break; - } - - try { - $quote - ->setCustomer($customer) - ->setCheckoutMethod($customer->getMode()) - ->setPasswordHash($customer->encryptPassword($customer->getPassword())) - ->save(); - } catch (Mage_Core_Exception $e) { - $this->_fault('customer_not_set', $e->getMessage()); - } - - return true; - } - - /** - * @param int $quoteId - * @param array of array|object $customerAddressData - * @param int|string $store - * @return int - */ - public function setAddresses($quoteId, $customerAddressData, $store = null) - { - $quote = $this->_getQuote($quoteId, $store); - - $customerAddressData = $this->_prepareCustomerAddressData($customerAddressData); - if (is_null($customerAddressData)) { - $this->_fault('customer_address_data_empty'); - } - - foreach ($customerAddressData as $addressItem) { -// switch($addressItem['mode']) { -// case self::ADDRESS_BILLING: - /** @var $address Mage_Sales_Model_Quote_Address */ - $address = Mage::getModel('Mage_Sales_Model_Quote_Address'); -// break; -// case self::ADDRESS_SHIPPING: -// /** @var $address Mage_Sales_Model_Quote_Address */ -// $address = Mage::getModel('Mage_Sales_Model_Quote_Address'); -// break; -// } - $addressMode = $addressItem['mode']; - unset($addressItem['mode']); - - if (!empty($addressItem['entity_id'])) { - $customerAddress = $this->_getCustomerAddress($addressItem['entity_id']); - if ($customerAddress->getCustomerId() != $quote->getCustomerId()) { - $this->_fault('address_not_belong_customer'); - } - $address->importCustomerAddress($customerAddress); - - } else { - $address->setData($addressItem); - } - - $address->implodeStreetAddress(); - - if (($validateRes = $address->validate())!==true) { - $this->_fault('customer_address_invalid', implode(PHP_EOL, $validateRes)); - } - - switch($addressMode) { - case self::ADDRESS_BILLING: - $address->setEmail($quote->getCustomer()->getEmail()); - - if (!$quote->isVirtual()) { - $usingCase = isset($addressItem['use_for_shipping']) ? (int)$addressItem['use_for_shipping'] : 0; - switch($usingCase) { - case 0: - $shippingAddress = $quote->getShippingAddress(); - $shippingAddress->setSameAsBilling(0); - break; - case 1: - $billingAddress = clone $address; - $billingAddress->unsAddressId()->unsAddressType(); - - $shippingAddress = $quote->getShippingAddress(); - $shippingMethod = $shippingAddress->getShippingMethod(); - $shippingAddress->addData($billingAddress->getData()) - ->setSameAsBilling(1) - ->setShippingMethod($shippingMethod) - ->setCollectShippingRates(true); - break; - } - } - $quote->setBillingAddress($address); - break; - - case self::ADDRESS_SHIPPING: - $address->setCollectShippingRates(true) - ->setSameAsBilling(0); - $quote->setShippingAddress($address); - break; - } - - } - - try { - $quote - ->collectTotals() - ->save(); - } catch (Exception $e) { - $this->_fault('address_is_not_set', $e->getMessage()); - } - - return true; - } - - /** - * Prepare customer entered data for implementing - * - * @param array $customerData - * @return array - */ - protected function _prepareCustomerData($data) - { - foreach ($this->_attributesMap['quote_customer'] as $attributeAlias=>$attributeCode) { - if(isset($data[$attributeAlias])) - { - $data[$attributeCode] = $data[$attributeAlias]; - unset($data[$attributeAlias]); - } - } - return $data; - } - - /** - * Prepare customer entered data for implementing - * - * @param array $data - * @return array - */ - protected function _prepareCustomerAddressData($data) - { - if (!is_array($data) || !is_array($data[0])) { - return null; - } - - $dataAddresses = array(); - foreach($data as $addressItem) { - foreach ($this->_attributesMap['quote_address'] as $attributeAlias=>$attributeCode) { - if(isset($addressItem[$attributeAlias])) - { - $addressItem[$attributeCode] = $addressItem[$attributeAlias]; - unset($addressItem[$attributeAlias]); - } - } - $dataAddresses[] = $addressItem; - } - return $dataAddresses; - } -} diff --git a/app/code/core/Mage/Checkout/Model/Cart/Customer/Api/V2.php b/app/code/core/Mage/Checkout/Model/Cart/Customer/Api/V2.php deleted file mode 100644 index 4eaa745347928812a17b86d2d6597523bc34e645..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Checkout/Model/Cart/Customer/Api/V2.php +++ /dev/null @@ -1,70 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Checkout - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Shoping cart api for customer data - * - * @category Mage - * @package Mage_Checkout - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Checkout_Model_Cart_Customer_Api_V2 extends Mage_Checkout_Model_Cart_Customer_Api -{ - /** - * Prepare customer entered data for implementing - * - * @param object $data - * @return array - */ - protected function _prepareCustomerData($data) - { - if (null !== ($_data = get_object_vars($data))) { - return parent::_prepareCustomerData($_data); - } - return array(); - } - - /** - * Prepare customer entered data for implementing - * - * @param object $data - * @return array - */ - protected function _prepareCustomerAddressData($data) - { - if (is_array($data)) { - $dataAddresses = array(); - foreach($data as $addressItem) { - if (null !== ($_addressItem = get_object_vars($addressItem))) { - $dataAddresses[] = $_addressItem; - } - } - return parent::_prepareCustomerAddressData($dataAddresses); - } - - return null; - } -} diff --git a/app/code/core/Mage/Checkout/Model/Cart/Payment/Api.php b/app/code/core/Mage/Checkout/Model/Cart/Payment/Api.php deleted file mode 100644 index 9bed56b4b7ea52b2f40ccd02c387316d81b8efcd..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Checkout/Model/Cart/Payment/Api.php +++ /dev/null @@ -1,191 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Checkout - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Shopping cart api - * - * @category Mage - * @package Mage_Checkout - * @author Magento Core Team <core@magentocommerce.com> - */ - -class Mage_Checkout_Model_Cart_Payment_Api extends Mage_Checkout_Model_Api_Resource -{ - - protected function _preparePaymentData($data) - { - if (!(is_array($data) && is_null($data[0]))) { - return array(); - } - - return $data; - } - - /** - * @param $method - * @param $quote - * @return bool - */ - protected function _canUsePaymentMethod($method, $quote) - { - if ( !($method->isGateway() || $method->canUseInternal()) ) { - return false; - } - - if (!$method->canUseForCountry($quote->getBillingAddress()->getCountry())) { - return false; - } - - if (!$method->canUseForCurrency(Mage::app()->getStore($quote->getStoreId())->getBaseCurrencyCode())) { - return false; - } - - /** - * Checking for min/max order total for assigned payment method - */ - $total = $quote->getBaseGrandTotal(); - $minTotal = $method->getConfigData('min_order_total'); - $maxTotal = $method->getConfigData('max_order_total'); - - if ((!empty($minTotal) && ($total < $minTotal)) || (!empty($maxTotal) && ($total > $maxTotal))) { - return false; - } - - return true; - } - - protected function _getPaymentMethodAvailableCcTypes($method) - { - $ccTypes = Mage::getSingleton('Mage_Payment_Model_Config')->getCcTypes(); - $methodCcTypes = explode(',',$method->getConfigData('cctypes')); - foreach ($ccTypes as $code=>$title) { - if (!in_array($code, $methodCcTypes)) { - unset($ccTypes[$code]); - } - } - if (empty($ccTypes)) { - return null; - } - - return $ccTypes; - } - - /** - * @param $quoteId - * @param $store - * @return array - */ - public function getPaymentMethodsList($quoteId, $store=null) - { - $quote = $this->_getQuote($quoteId, $store); - $store = $quote->getStoreId(); - - $total = $quote->getBaseSubtotal(); - - $methodsResult = array(); - $methods = Mage::helper('Mage_Payment_Helper_Data')->getStoreMethods($store, $quote); - foreach ($methods as $key=>$method) { - /** @var $method Mage_Payment_Model_Method_Abstract */ - if ($this->_canUsePaymentMethod($method, $quote) - && ($total != 0 - || $method->getCode() == 'free' - || ($quote->hasRecurringItems() && $method->canManageRecurringProfiles()))) { - $methodsResult[] = - array( - "code" => $method->getCode(), - "title" => $method->getTitle(), - "ccTypes" => $this->_getPaymentMethodAvailableCcTypes($method) - ); - } - } - - return $methodsResult; - } - - /** - * @param $quoteId - * @param $paymentData - * @param $store - * @return bool - */ - public function setPaymentMethod($quoteId, $paymentData, $store=null) - { - $quote = $this->_getQuote($quoteId, $store); - $store = $quote->getStoreId(); - - $paymentData = $this->_preparePaymentData($paymentData); - - if (empty($paymentData)) { - $this->_fault("payment_method_empty"); - } - - if ($quote->isVirtual()) { - // check if billing address is set - if (is_null($quote->getBillingAddress()->getId()) ) { - $this->_fault('billing_address_is_not_set'); - } - $quote->getBillingAddress()->setPaymentMethod(isset($paymentData['method']) ? $paymentData['method'] : null); - } else { - // check if shipping address is set - if (is_null($quote->getShippingAddress()->getId()) ) { - $this->_fault('shipping_address_is_not_set'); - } - $quote->getShippingAddress()->setPaymentMethod(isset($paymentData['method']) ? $paymentData['method'] : null); - } - - if (!$quote->isVirtual() && $quote->getShippingAddress()) { - $quote->getShippingAddress()->setCollectShippingRates(true); - } - - $total = $quote->getBaseSubtotal(); - $methods = Mage::helper('Mage_Payment_Helper_Data')->getStoreMethods($store, $quote); - foreach ($methods as $key=>$method) { - if ($method->getCode() == $paymentData['method']) { - /** @var $method Mage_Payment_Model_Method_Abstract */ - if (!($this->_canUsePaymentMethod($method, $quote) - && ($total != 0 - || $method->getCode() == 'free' - || ($quote->hasRecurringItems() && $method->canManageRecurringProfiles())))) { - $this->_fault("method_not_allowed"); - } - } - } - - try { - $payment = $quote->getPayment(); - $payment->importData($paymentData); - - - $quote->setTotalsCollectedFlag(false) - ->collectTotals() - ->save(); - } catch (Mage_Core_Exception $e) { - $this->_fault('payment_method_is_not_set', $e->getMessage()); - } - return true; - } - -} diff --git a/app/code/core/Mage/Checkout/Model/Cart/Payment/Api/V2.php b/app/code/core/Mage/Checkout/Model/Cart/Payment/Api/V2.php deleted file mode 100644 index c0c13c383dff6ef3966780a053d87a0901d4f113..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Checkout/Model/Cart/Payment/Api/V2.php +++ /dev/null @@ -1,45 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Checkout - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Shopping cart api - * - * @category Mage - * @package Mage_Checkout - * @author Magento Core Team <core@magentocommerce.com> - */ - - class Mage_Checkout_Model_Cart_Payment_Api_V2 extends Mage_Checkout_Model_Cart_Payment_Api -{ - protected function _preparePaymentData($data) - { - if (null !== ($_data = get_object_vars($data))) { - return parent::_preparePaymentData($_data); - } - - return array(); - } -} diff --git a/app/code/core/Mage/Checkout/Model/Cart/Product/Api.php b/app/code/core/Mage/Checkout/Model/Cart/Product/Api.php deleted file mode 100644 index b88e869605c842f83d77d8082975e3b0e34f9830..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Checkout/Model/Cart/Product/Api.php +++ /dev/null @@ -1,328 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Checkout - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Shopping cart api for product - * - * @category Mage - * @package Mage_Checkout - * @author Magento Core Team <core@magentocommerce.com> - */ - -class Mage_Checkout_Model_Cart_Product_Api extends Mage_Checkout_Model_Api_Resource_Product -{ - /** - * Base preparation of product data - * - * @param mixed $data - * @return null|array - */ - protected function _prepareProductsData($data) - { - return is_array($data) ? $data : null; - } - - /** - * @param $quoteId - * @param $productsData - * @param $store - * @return bool - */ - public function add($quoteId, $productsData, $store=null) - { - $quote = $this->_getQuote($quoteId, $store); - if (empty($store)) { - $store = $quote->getStoreId(); - } - - $productsData = $this->_prepareProductsData($productsData); - if (empty($productsData)) { - $this->_fault('invalid_product_data'); - } - - $errors = array(); - foreach ($productsData as $productItem) { - if (isset($productItem['product_id'])) { - $productByItem = $this->_getProduct($productItem['product_id'], $store, "id"); - } else if (isset($productItem['sku'])) { - $productByItem = $this->_getProduct($productItem['sku'], $store, "sku"); - } else { - $errors[] = Mage::helper('Mage_Checkout_Helper_Data')->__("One item of products do not have identifier or sku"); - continue; - } - - $productRequest = $this->_getProductRequest($productItem); - try { - $result = $quote->addProduct($productByItem, $productRequest); - if (is_string($result)) { - Mage::throwException($result); - } - } catch (Mage_Core_Exception $e) { - $errors[] = $e->getMessage(); - } - } - - if (!empty($errors)) { - $this->_fault("add_product_fault", implode(PHP_EOL, $errors)); - } - - try { - $quote->collectTotals()->save(); - } catch(Exception $e) { - $this->_fault("add_product_quote_save_fault", $e->getMessage()); - } - - return true; - } - - /** - * @param $quoteId - * @param $productsData - * @param $store - * @return bool - */ - public function update($quoteId, $productsData, $store=null) - { - $quote = $this->_getQuote($quoteId, $store); - if (empty($store)) { - $store = $quote->getStoreId(); - } - - $productsData = $this->_prepareProductsData($productsData); - if (empty($productsData)) { - $this->_fault('invalid_product_data'); - } - - $errors = array(); - foreach ($productsData as $productItem) { - if (isset($productItem['product_id'])) { - $productByItem = $this->_getProduct($productItem['product_id'], $store, "id"); - } else if (isset($productItem['sku'])) { - $productByItem = $this->_getProduct($productItem['sku'], $store, "sku"); - } else { - $errors[] = Mage::helper('Mage_Checkout_Helper_Data')->__("One item of products do not have identifier or sku"); - continue; - } - - /** @var $quoteItem Mage_Sales_Model_Quote_Item */ - $quoteItem = $this->_getQuoteItemByProduct($quote, $productByItem, - $this->_getProductRequest($productItem)); - if (is_null($quoteItem->getId())) { - $errors[] = Mage::helper('Mage_Checkout_Helper_Data')->__("One item of products is not belong any of quote item"); - continue; - } - - if ($productItem['qty'] > 0) { - $quoteItem->setQty($productItem['qty']); - } - } - - if (!empty($errors)) { - $this->_fault("update_product_fault", implode(PHP_EOL, $errors)); - } - - try { - $quote->save(); - } catch(Exception $e) { - $this->_fault("update_product_quote_save_fault", $e->getMessage()); - } - - return true; - } - - /** - * @param $quoteId - * @param $productsData - * @param $store - * @return bool - */ - public function remove($quoteId, $productsData, $store=null) - { - $quote = $this->_getQuote($quoteId, $store); - if (empty($store)) { - $store = $quote->getStoreId(); - } - - $productsData = $this->_prepareProductsData($productsData); - if (empty($productsData)) { - $this->_fault('invalid_product_data'); - } - - $errors = array(); - foreach ($productsData as $productItem) { - if (isset($productItem['product_id'])) { - $productByItem = $this->_getProduct($productItem['product_id'], $store, "id"); - } else if (isset($productItem['sku'])) { - $productByItem = $this->_getProduct($productItem['sku'], $store, "sku"); - } else { - $errors[] = Mage::helper('Mage_Checkout_Helper_Data')->__("One item of products do not have identifier or sku"); - continue; - } - - try { - /** @var $quoteItem Mage_Sales_Model_Quote_Item */ - $quoteItem = $this->_getQuoteItemByProduct($quote, $productByItem, - $this->_getProductRequest($productItem)); - if (is_null($quoteItem->getId())) { - $errors[] = Mage::helper('Mage_Checkout_Helper_Data')->__("One item of products is not belong any of quote item"); - continue; - } - $quote->removeItem($quoteItem->getId()); - } catch (Mage_Core_Exception $e) { - $errors[] = $e->getMessage(); - } - } - - if (!empty($errors)) { - $this->_fault("remove_product_fault", implode(PHP_EOL, $errors)); - } - - try { - $quote->save(); - } catch(Exception $e) { - $this->_fault("remove_product_quote_save_fault", $e->getMessage()); - } - - return true; - } - - /** - * @param $quoteId - * @param $store - * @return array - */ - public function items($quoteId, $store = null) - { - $quote = $this->_getQuote($quoteId, $store); - if (empty($store)) { - $store = $quote->getStoreId(); - } - - if (!$quote->getItemsCount()) { - return array(); - } - - $productsResult = array(); - foreach ($quote->getAllItems() as $item) { - /** @var $item Mage_Sales_Model_Quote_Item */ - $product = $item->getProduct(); - $productsResult[] = array( // Basic product data - 'product_id' => $product->getId(), - 'sku' => $product->getSku(), - 'name' => $product->getName(), - 'set' => $product->getAttributeSetId(), - 'type' => $product->getTypeId(), - 'category_ids' => $product->getCategoryIds(), - 'website_ids' => $product->getWebsiteIds() - ); - } - - return $productsResult; - } - - /** - * @param $quoteId - * @param $productsData - * @param $store - * @return bool - */ - public function moveToCustomerQuote($quoteId, $productsData, $store=null) - { - $quote = $this->_getQuote($quoteId, $store); - - if (empty($store)) { - $store = $quote->getStoreId(); - } - - $customer = $quote->getCustomer(); - if (is_null($customer->getId())) { - $this->_fault('customer_not_set_for_quote'); - } - - /** @var $customerQuote Mage_Sales_Model_Quote */ - $customerQuote = Mage::getModel('Mage_Sales_Model_Quote') - ->setStoreId($store) - ->loadByCustomer($customer); - - if (is_null($customerQuote->getId())) { - $this->_fault('customer_quote_not_exist'); - } - - if ($customerQuote->getId() == $quote->getId()) { - $this->_fault('quotes_are_similar'); - } - - $productsData = $this->_prepareProductsData($productsData); - if (empty($productsData)) { - $this->_fault('invalid_product_data'); - } - - $errors = array(); - foreach($productsData as $key => $productItem){ - if (isset($productItem['product_id'])) { - $productByItem = $this->_getProduct($productItem['product_id'], $store, "id"); - } else if (isset($productItem['sku'])) { - $productByItem = $this->_getProduct($productItem['sku'], $store, "sku"); - } else { - $errors[] = Mage::helper('Mage_Checkout_Helper_Data')->__("One item of products do not have identifier or sku"); - continue; - } - - try { - /** @var $quoteItem Mage_Sales_Model_Quote_Item */ - $quoteItem = $this->_getQuoteItemByProduct($quote, $productByItem, - $this->_getProductRequest($productItem)); - if($quoteItem->getId()){ - $customerQuote->addItem($quoteItem); - $quote->removeItem($quoteItem->getId()); - unset($productsData[$key]); - } else { - $errors[] = Mage::helper('Mage_Checkout_Helper_Data')->__("One item of products is not belong any of quote item"); - } - } catch (Mage_Core_Exception $e) { - $errors[] = $e->getMessage(); - } - } - - if (count($productsData) || !empty($errors)) { - $this->_fault('unable_to_move_all_products', implode(PHP_EOL, $errors)); - } - - try { - $customerQuote - ->collectTotals() - ->save(); - - $quote - ->collectTotals() - ->save(); - } catch (Exception $e) { - $this->_fault("product_move_quote_save_fault", $e->getMessage()); - } - - return true; - } -} diff --git a/app/code/core/Mage/Checkout/Model/Cart/Product/Api/V2.php b/app/code/core/Mage/Checkout/Model/Cart/Product/Api/V2.php deleted file mode 100644 index df942b2d04f65dce3ac798f1fcb46b021c505ae2..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Checkout/Model/Cart/Product/Api/V2.php +++ /dev/null @@ -1,76 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Checkout - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Shopping cart api for product - * - * @category Mage - * @package Mage_Checkout - * @author Magento Core Team <core@magentocommerce.com> - */ - -class Mage_Checkout_Model_Cart_Product_Api_V2 extends Mage_Checkout_Model_Cart_Product_Api -{ - - /** - * Return an Array of Object attributes. - * - * @param Mixed $data - * @return Array - */ - protected function _prepareProductsData($data){ - if (is_object($data)) { - $arr = get_object_vars($data); - foreach ($arr as $key => $value) { - $assocArr = array(); - if (is_array($value)) { - foreach ($value as $v) { - if (is_object($v) && count(get_object_vars($v))==2 - && isset($v->key) && isset($v->value)) { - $assocArr[$v->key] = $v->value; - } - } - } - if (!empty($assocArr)) { - $arr[$key] = $assocArr; - } - } - $arr = $this->_prepareProductsData($arr); - return parent::_prepareProductsData($arr); - } - if (is_array($data)) { - foreach ($data as $key => $value) { - if (is_object($value) || is_array($value)) { - $data[$key] = $this->_prepareProductsData($value); - } else { - $data[$key] = $value; - } - } - return parent::_prepareProductsData($data); - } - return $data; - } -} diff --git a/app/code/core/Mage/Checkout/Model/Cart/Shipping/Api.php b/app/code/core/Mage/Checkout/Model/Cart/Shipping/Api.php deleted file mode 100644 index 3373cceb7a2cecf7928b9759e3247c437f1be9af..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Checkout/Model/Cart/Shipping/Api.php +++ /dev/null @@ -1,116 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Checkout - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Shopping cart api - * - * @category Mage - * @package Mage_Checkout - * @author Magento Core Team <core@magentocommerce.com> - */ - -class Mage_Checkout_Model_Cart_Shipping_Api extends Mage_Checkout_Model_Api_Resource -{ - public function __construct() - { - $this->_ignoredAttributeCodes['quote_shipping_rate'] = array('address_id', 'created_at', 'updated_at', 'rate_id', 'carrier_sort_order'); - } - - /** - * Set an Shipping Method for Shopping Cart - * - * @param $quoteId - * @param $shippingMethod - * @param $store - * @return bool - */ - public function setShippingMethod($quoteId, $shippingMethod, $store = null) - { - $quote = $this->_getQuote($quoteId, $store); - - $quoteShippingAddress = $quote->getShippingAddress(); - if(is_null($quoteShippingAddress->getId()) ) { - $this->_fault("shipping_address_is_not_set"); - } - - $rate = $quote->getShippingAddress()->collectShippingRates()->getShippingRateByCode($shippingMethod); - if (!$rate) { - $this->_fault('shipping_method_is_not_available'); - } - - try { - $quote->getShippingAddress()->setShippingMethod($shippingMethod); - $quote->collectTotals()->save(); - } catch(Mage_Core_Exception $e) { - $this->_fault('shipping_method_is_not_set', $e->getMessage()); - } - - return true; - } - - /** - * Get list of available shipping methods - * - * @param $quoteId - * @param $store - * @return array - */ - public function getShippingMethodsList($quoteId, $store=null) - { - $quote = $this->_getQuote($quoteId, $store); - - $quoteShippingAddress = $quote->getShippingAddress(); - if (is_null($quoteShippingAddress->getId())) { - $this->_fault("shipping_address_is_not_set"); - } - - try { - $quoteShippingAddress->collectShippingRates()->save(); - $groupedRates = $quoteShippingAddress->getGroupedAllShippingRates(); - - $ratesResult = array(); - foreach ($groupedRates as $carrierCode => $rates ) { - $carrierName = $carrierCode; - if (!is_null(Mage::getStoreConfig('carriers/'.$carrierCode.'/title'))) { - $carrierName = Mage::getStoreConfig('carriers/'.$carrierCode.'/title'); - } - - foreach ($rates as $rate) { - $rateItem = $this->_getAttributes($rate, "quote_shipping_rate"); - $rateItem['carrierName'] = $carrierName; - $ratesResult[] = $rateItem; - unset($rateItem); - } - } - } catch (Mage_Core_Exception $e) { - $this->_fault('shipping_methods_list_could_not_be_retrived', $e->getMessage()); - } - - return $ratesResult; - } - - -} diff --git a/app/code/core/Mage/Checkout/Model/Cart/Shipping/Api/V2.php b/app/code/core/Mage/Checkout/Model/Cart/Shipping/Api/V2.php deleted file mode 100644 index b2c314c8a09b2476f0121181d9c003d010f908b0..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Checkout/Model/Cart/Shipping/Api/V2.php +++ /dev/null @@ -1,38 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Checkout - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Shopping cart api - * - * @category Mage - * @package Mage_Checkout - * @author Magento Core Team <core@magentocommerce.com> - */ - -class Mage_Checkout_Model_Cart_Shipping_Api_V2 extends Mage_Checkout_Model_Cart_Shipping_Api -{ - -} diff --git a/app/code/core/Mage/Checkout/etc/api.xml b/app/code/core/Mage/Checkout/etc/api.xml deleted file mode 100644 index 5a15344503163bde7ed10ded506584a452a45e77..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Checkout/etc/api.xml +++ /dev/null @@ -1,511 +0,0 @@ -<?xml version="1.0"?> -<!-- -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Academic Free License (AFL 3.0) - * that is bundled with this package in the file LICENSE_AFL.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/afl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Checkout - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) - */ ---> -<config> - <api> - <resources> - <cart translate="title" module="Mage_Checkout"> - <model>Mage_Checkout_Model_Cart_Api</model> - <title>Shopping Cart</title> - <acl>cart</acl> - <methods> - <create translate="title" module="Mage_Checkout"> - <title>Create shopping cart</title> - <method>create</method> - <acl>cart/create</acl> - </create> - <order translate="title" module="Mage_Checkout"> - <title>Create an order from shopping cart</title> - <method>createOrder</method> - <acl>cart/order</acl> - </order> - <info translate="title" module="Mage_Checkout"> - <title>Retrieve information about shopping cart</title> - <method>info</method> - <acl>cart/info</acl> - </info> - <totals translate="title" module="Mage_Checkout"> - <title>Get total prices for shopping cart</title> - <method>totals</method> - <acl>cart/totals</acl> - </totals> - <license translate="title" module="Mage_Checkout"> - <title>Get terms and conditions</title> - <method>licenseAgreement</method> - <acl>cart/license</acl> - </license> - </methods> - <faults module="Mage_Checkout"> - <store_not_exists> - <code>1001</code> - <message>Can not make operation because store is not exists</message> - </store_not_exists> - <quote_not_exists> - <code>1002</code> - <message>Can not make operation because quote is not exists</message> - </quote_not_exists> - <quote_create_fault> - <code>1003</code> - <message>Can not create a quote. </message> - </quote_create_fault> - <quote_already_exists> - <code>1004</code> - <message>Can not create a quote because quote with such identifier is already exists</message> - </quote_already_exists> - <required_agreements_are_not_all> - <code>1005</code> - <message>You did not set all required agreements</message> - </required_agreements_are_not_all> - <invalid_checkout_type> - <code>1006</code> - <message>The checkout type is not valid. Select single checkout type.</message> - </invalid_checkout_type> - <guest_checkout_is_not_enabled> - <code>1007</code> - <message>Checkout is not available for guest</message> - </guest_checkout_is_not_enabled> - <create_order_fault> - <code>1008</code> - <message>Can not create an order. </message> - </create_order_fault> - </faults> - </cart> - <cart_product translate="title" module="Mage_Checkout"> - <model>Mage_Checkout_Model_Cart_Product_Api</model> - <title>Cart Product API</title> - <acl>cart/product</acl> - <methods> - <add translate="title" module="Mage_Checkout"> - <title>Add product to shopping cart</title> - <method>add</method> - <acl>cart/product/add</acl> - </add> - <update translate="title" module="Mage_Checkout"> - <title>Update product quantities in shopping cart</title> - <method>update</method> - <acl>cart/product/update</acl> - </update> - <remove translate="title" module="Mage_Checkout"> - <title>Remove product from shopping cart</title> - <method>remove</method> - <acl>cart/product/remove</acl> - </remove> - <list translate="title" module="Mage_Checkout"> - <title>Get list of products in shopping cart</title> - <method>items</method> - <acl>cart/product/list</acl> - </list> - <moveToCustomerQuote> - <title>Move product(s) to customer quote</title> - <method>moveToCustomerQuote</method> - <acl>cart/product/moveToCustomerQuote</acl> - </moveToCustomerQuote> - </methods> - <faults module="Mage_Checkout"> - <store_not_exists> - <code>1001</code> - <message>Can not make operation because store is not exists</message> - </store_not_exists> - <quote_not_exists> - <code>1002</code> - <message>Can not make operation because quote is not exists</message> - </quote_not_exists> - <invalid_product_data> - <code>1021</code> - <message>Product's data is not valid.</message> - </invalid_product_data> - <add_product_fault> - <code>1022</code> - <message>Product(s) could not be added. </message> - </add_product_fault> - <add_product_quote_save_fault> - <code>1023</code> - <message>Quote could not be saved during adding product(s) operation.</message> - </add_product_quote_save_fault> - <update_product_fault> - <code>1024</code> - <message>Product(s) could not be updated. </message> - </update_product_fault> - <update_product_quote_save_fault> - <code>1025</code> - <message>Quote could not be saved during updating product(s) operation.</message> - </update_product_quote_save_fault> - <remove_product_fault> - <code>1026</code> - <message>Product(s) could not be removed. </message> - </remove_product_fault> - <remove_product_quote_save_fault> - <code>1027</code> - <message>Quote could not be saved during removing product(s) operation.</message> - </remove_product_quote_save_fault> - <customer_not_set_for_quote> - <code>1028</code> - <message>Customer is not set for quote.</message> - </customer_not_set_for_quote> - <customer_quote_not_exist> - <code>1029</code> - <message>Customer's quote is not existed.</message> - </customer_quote_not_exist> - <quotes_are_similar> - <code>1030</code> - <message>Quotes are identical.</message> - </quotes_are_similar> - <unable_to_move_all_products> - <code>1031</code> - <message>Product(s) could not be moved. </message> - </unable_to_move_all_products> - <product_move_quote_save_fault> - <code>1032</code> - <message>One of quote could not be saved during moving product(s) operation.</message> - </product_move_quote_save_fault> - </faults> - </cart_product> - <cart_customer translate="title" module="Mage_Checkout"> - <model>Mage_Checkout_Model_Cart_Customer_Api</model> - <title>Customer Information</title> - <acl>cart/customer</acl> - <methods> - <set translate="title" module="Mage_Checkout"> - <title>Set customer for shopping cart</title> - <method>set</method> - <acl>cart/customer/set</acl> - </set> - <addresses translate="title" module="Mage_Checkout"> - <title>Set customer's addresses in shopping cart</title> - <method>setAddresses</method> - <acl>cart/customer/addresses</acl> - </addresses> - </methods> - <faults module="Mage_Checkout"> - <store_not_exists> - <code>1001</code> - <message>Can not make operation because store is not exists</message> - </store_not_exists> - <quote_not_exists> - <code>1002</code> - <message>Can not make operation because quote is not exists</message> - </quote_not_exists> - <customer_not_set> - <code>1041</code> - <message>Customer is not set. </message> - </customer_not_set> - <customer_not_exists> - <code>1042</code> - <message>The customer's identifier is not valid or customer is not existed</message> - </customer_not_exists> - <customer_not_created> - <code>1043</code> - <message>Customer could not be created. </message> - </customer_not_created> - <customer_data_invalid> - <code>1044</code> - <message>Customer data is not valid. </message> - </customer_data_invalid> - <customer_mode_is_unknown> - <code>1045</code> - <message>Customer's mode is unknown</message> - </customer_mode_is_unknown> - <customer_address_data_empty> - <code>1051</code> - <message>Customer address data is empty.</message> - </customer_address_data_empty> - <customer_address_invalid> - <code>1052</code> - <message>Customer's address data is not valid.</message> - </customer_address_invalid> - <invalid_address_id> - <code>1053</code> - <message>The customer's address identifier is not valid</message> - </invalid_address_id> - <address_is_not_set> - <code>1054</code> - <message>Customer address is not set.</message> - </address_is_not_set> - <address_not_belong_customer> - <code>1055</code> - <message>Customer address identifier do not belong customer, which set in quote</message> - </address_not_belong_customer> - </faults> - </cart_customer> - <cart_shipping translate="title" module="Mage_Checkout"> - <model>Mage_Checkout_Model_Cart_Shipping_Api</model> - <title>Shipping information</title> - <acl>cart/shipping</acl> - <methods> - <method translate="title" module="Mage_Checkout"> - <title>Set shipping method</title> - <method>setShippingMethod</method> - <acl>cart/shipping/method</acl> - </method> - <list translate="title" module="Mage_Checkout"> - <title>Get list of available shipping methods</title> - <method>getShippingMethodsList</method> - <acl>cart/shipping/list</acl> - </list> - </methods> - <faults module="Mage_Checkout"> - <store_not_exists> - <code>1001</code> - <message>Can not make operation because store is not exists</message> - </store_not_exists> - <quote_not_exists> - <code>1002</code> - <message>Can not make operation because quote is not exists</message> - </quote_not_exists> - <shipping_address_is_not_set> - <code>1061</code> - <message>Can not make operation because of customer shipping address is not set</message> - </shipping_address_is_not_set> - <shipping_method_is_not_available> - <code>1062</code> - <message>Shipping method is not available</message> - </shipping_method_is_not_available> - <shipping_method_is_not_set> - <code>1063</code> - <message>Can not set shipping method. </message> - </shipping_method_is_not_set> - <shipping_methods_list_could_not_be_retrived> - <code>1064</code> - <message>Can not receive list of shipping methods. </message> - </shipping_methods_list_could_not_be_retrived> - </faults> - </cart_shipping> - <cart_payment translate="title" module="Mage_Checkout"> - <model>Mage_Checkout_Model_Cart_Payment_Api</model> - <title>Payment method information</title> - <acl>cart/payment</acl> - <methods> - <method translate="title" module="Mage_Checkout"> - <title>Set payment method</title> - <method>setPaymentMethod</method> - <acl>cart/payment/method</acl> - </method> - <list translate="title" module="Mage_Checkout"> - <title>Get list of available payment methods</title> - <method>getPaymentMethodsList</method> - <acl>cart/payment/list</acl> - </list> - </methods> - <faults module="Mage_Checkout"> - <store_not_exists> - <code>1001</code> - <message>Can not make operation because store is not exists</message> - </store_not_exists> - <quote_not_exists> - <code>1002</code> - <message>Can not make operation because quote is not exists</message> - </quote_not_exists> - <payment_method_empty> - <code>1071</code> - <message>Payment method data is empty.</message> - </payment_method_empty> - <billing_address_is_not_set> - <code>1072</code> - <message>Customer's billing address is not set. Required for payment method data.</message> - </billing_address_is_not_set> - <shipping_address_is_not_set> - <code>1073</code> - <message>Customer's shipping address is not set. Required for payment method data.</message> - </shipping_address_is_not_set> - <method_not_allowed> - <code>1074</code> - <message>Payment method is not allowed</message> - </method_not_allowed> - <payment_method_is_not_set> - <code>1075</code> - <message>Payment method is not set. </message> - </payment_method_is_not_set> - </faults> - </cart_payment> - <cart_coupon translate="title" module="Mage_Checkout"> - <model>Mage_Checkout_Model_Cart_Coupon_Api</model> - <title>Shopping cart ability to set coupon code</title> - <acl>cart/coupon</acl> - <methods> - <add translate="title" module="Mage_Checkout"> - <title>Add coupon code for shopping cart</title> - <method>add</method> - <acl>cart/coupon/add</acl> - </add> - <remove translate="title" module="Mage_Checkout"> - <title>Remove coupon code from shopping cart</title> - <method>remove</method> - <acl>cart/coupon/remove</acl> - </remove> - </methods> - <faults module="Mage_Checkout"> - <store_not_exists> - <code>1001</code> - <message>Can not make operation because store is not exists</message> - </store_not_exists> - <quote_not_exists> - <code>1002</code> - <message>Can not make operation because quote is not exists</message> - </quote_not_exists> - <quote_is_empty> - <code>1081</code> - <message>Coupon could not be applied because quote is empty.</message> - </quote_is_empty> - <cannot_apply_coupon_code> - <code>1082</code> - <message>Coupon could not be applied.</message> - </cannot_apply_coupon_code> - <coupon_code_is_not_valid> - <code>1083</code> - <message>Coupon is not valid.</message> - </coupon_code_is_not_valid> - </faults> - </cart_coupon> - </resources> - <resources_alias> - <cart_customer_address>cart_customer</cart_customer_address> - </resources_alias> - <rest> - <mapping> - <cart_product> - <post> - <method>add</method> - </post> - <delete> - <method>remove</method> - </delete> - </cart_product> - <cart_shipping> - <post> - <method>method</method> - </post> - </cart_shipping> - <cart_payment> - <post> - <method>method</method> - </post> - </cart_payment> - <cart_customer> - <post> - <method>set</method> - </post> - </cart_customer> - <cart_customer_address> - <post> - <method>addresses</method> - </post> - </cart_customer_address> - <cart_payment> - <post> - <method>method</method> - </post> - </cart_payment> - </mapping> - </rest> - <acl> - <resources> - <cart translate="title" module="Mage_Checkout"> - <title>Shopping Cart</title> - <create translate="title" module="Mage_Checkout"> - <title>Create shopping cart</title> - </create> - <order translate="title" module="Mage_Checkout"> - <title>Create an order from shopping cart</title> - </order> - <info translate="title" module="Mage_Checkout"> - <title>Retrieve information about shopping cart</title> - </info> - <totals translate="title" module="Mage_Checkout"> - <title>Get total prices for shopping cart</title> - </totals> - <license translate="title" module="Mage_Checkout"> - <title>Get terms and conditions</title> - </license> - <product translate="title" module="Mage_Checkout"> - <title>Products</title> - <add translate="title" module="Mage_Checkout"> - <title>Add product(s) to shopping cart</title> - </add> - <update translate="title" module="Mage_Checkout"> - <title>Update product(s) quantities in shopping cart</title> - </update> - <remove translate="title" module="Mage_Checkout"> - <title>Remove product(s) from shopping cart</title> - </remove> - <list translate="title" module="Mage_Checkout"> - <title>Get list of products in shopping cart</title> - </list> - <moveToCustomerQuote> - <title>Move product(s) to customer quote</title> - </moveToCustomerQuote> - </product> - <customer translate="title" module="Mage_Checkout"> - <title>Customer's information</title> - <set translate="title" module="Mage_Checkout"> - <title>Set customer for shopping cart</title> - </set> - <addresses translate="title" module="Mage_Checkout"> - <title>Set customer's addresses in shopping cart</title> - </addresses> - </customer> - <shipping translate="title" module="Mage_Checkout"> - <title>Shipping methods in shopping cart</title> - <method translate="title" module="Mage_Checkout"> - <title>Set shipping method</title> - </method> - <list translate="title" module="Mage_Checkout"> - <title>Get list of available shipping methods</title> - </list> - </shipping> - <payment translate="title" module="Mage_Checkout"> - <title>Payment methods in shopping cart</title> - <method translate="title" module="Mage_Checkout"> - <title>Set payment method</title> - </method> - <list translate="title" module="Mage_Checkout"> - <title>Get list of available payment methods</title> - </list> - </payment> - <coupon> - <title>Shopping cart ability to set coupon code</title> - <add> - <title>Add coupon code for shopping cart</title> - </add> - <remove> - <title>Remove coupon code from shopping cart</title> - </remove> - </coupon> - </cart> - </resources> - </acl> - <v2> - <resources_function_prefix> - <cart>shoppingCart</cart> - <cart_product>shoppingCartProduct</cart_product> - <cart_customer>shoppingCartCustomer</cart_customer> - <cart_shipping>shoppingCartShipping</cart_shipping> - <cart_payment>shoppingCartPayment</cart_payment> - <cart_coupon>shoppingCartCoupon</cart_coupon> - </resources_function_prefix> - </v2> - </api> -</config> diff --git a/app/code/core/Mage/Checkout/etc/wsdl.xml b/app/code/core/Mage/Checkout/etc/wsdl.xml deleted file mode 100644 index d2b78e36ffa3c471338d3de7a022e453f7f324f6..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Checkout/etc/wsdl.xml +++ /dev/null @@ -1,772 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<definitions xmlns:typens="urn:{{var wsdl.name}}" xmlns:xsd="http://www.w3.org/2001/XMLSchema" - xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" - xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" - xmlns="http://schemas.xmlsoap.org/wsdl/" - name="{{var wsdl.name}}" targetNamespace="urn:{{var wsdl.name}}"> - <types> - <schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:Magento"> - <complexType name="shoppingCartAddressEntity"> - <all> - <element name="address_id" type="xsd:string" minOccurs="0"/> - <element name="created_at" type="xsd:string" minOccurs="0"/> - <element name="updated_at" type="xsd:string" minOccurs="0"/> - <element name="customer_id" type="xsd:string" minOccurs="0"/> - <element name="save_in_address_book" type="xsd:int" minOccurs="0"/> - <element name="customer_address_id" type="xsd:string" minOccurs="0"/> - <element name="address_type" type="xsd:string" minOccurs="0"/> - <element name="email" type="xsd:string" minOccurs="0"/> - <element name="prefix" type="xsd:string" minOccurs="0"/> - <element name="firstname" type="xsd:string" minOccurs="0"/> - <element name="middlename" type="xsd:string" minOccurs="0"/> - <element name="lastname" type="xsd:string" minOccurs="0"/> - <element name="suffix" type="xsd:string" minOccurs="0"/> - <element name="company" type="xsd:string" minOccurs="0"/> - <element name="street" type="xsd:string" minOccurs="0"/> - <element name="city" type="xsd:string" minOccurs="0"/> - <element name="region" type="xsd:string" minOccurs="0"/> - <element name="region_id" type="xsd:string" minOccurs="0"/> - <element name="postcode" type="xsd:string" minOccurs="0"/> - <element name="country_id" type="xsd:string" minOccurs="0"/> - <element name="telephone" type="xsd:string" minOccurs="0"/> - <element name="fax" type="xsd:string" minOccurs="0"/> - <element name="same_as_billing" type="xsd:int" minOccurs="0"/> - <element name="free_shipping" type="xsd:int" minOccurs="0"/> - <element name="shipping_method" type="xsd:string" minOccurs="0"/> - <element name="shipping_description" type="xsd:string" minOccurs="0"/> - <element name="weight" type="xsd:double" minOccurs="0"/> - <element name="fax" type="xsd:string" minOccurs="0"/> - </all> - </complexType> - <complexType name="shoppingCartItemEntity"> - <all> - <element name="item_id" type="xsd:string" minOccurs="0"/> - <element name="created_at" type="xsd:string" minOccurs="0"/> - <element name="updated_at" type="xsd:string" minOccurs="0"/> - <element name="product_id" type="xsd:string" minOccurs="0"/> - <element name="store_id" type="xsd:string" minOccurs="0"/> - <element name="parent_item_id" type="xsd:string" minOccurs="0"/> - <element name="is_virtual" type="xsd:int" minOccurs="0"/> - <element name="sku" type="xsd:string" minOccurs="0"/> - <element name="name" type="xsd:string" minOccurs="0"/> - <element name="description" type="xsd:string" minOccurs="0"/> - <element name="applied_rule_ids" type="xsd:string" minOccurs="0"/> - <element name="additional_data" type="xsd:string" minOccurs="0"/> - <element name="free_shipping" type="xsd:string" minOccurs="0"/> - <element name="is_qty_decimal" type="xsd:string" minOccurs="0"/> - <element name="no_discount" type="xsd:string" minOccurs="0"/> - <element name="weight" type="xsd:double" minOccurs="0"/> - <element name="qty" type="xsd:double" minOccurs="0"/> - <element name="price" type="xsd:double" minOccurs="0"/> - <element name="base_price" type="xsd:double" minOccurs="0"/> - <element name="custom_price" type="xsd:double" minOccurs="0"/> - <element name="discount_percent" type="xsd:double" minOccurs="0"/> - <element name="discount_amount" type="xsd:double" minOccurs="0"/> - <element name="base_discount_amount" type="xsd:double" minOccurs="0"/> - <element name="tax_percent" type="xsd:double" minOccurs="0"/> - <element name="tax_amount" type="xsd:double" minOccurs="0"/> - <element name="base_tax_amount" type="xsd:double" minOccurs="0"/> - <element name="row_total" type="xsd:double" minOccurs="0"/> - <element name="base_row_total" type="xsd:double" minOccurs="0"/> - <element name="row_total_with_discount" type="xsd:double" minOccurs="0"/> - <element name="row_weight" type="xsd:double" minOccurs="0"/> - <element name="product_type" type="xsd:string" minOccurs="0"/> - <element name="base_tax_before_discount" type="xsd:double" minOccurs="0"/> - <element name="tax_before_discount" type="xsd:double" minOccurs="0"/> - <element name="original_custom_price" type="xsd:double" minOccurs="0"/> - <element name="base_cost" type="xsd:double" minOccurs="0"/> - <element name="price_incl_tax" type="xsd:double" minOccurs="0"/> - <element name="base_price_incl_tax" type="xsd:double" minOccurs="0"/> - <element name="row_total_incl_tax" type="xsd:double" minOccurs="0"/> - <element name="base_row_total_incl_tax" type="xsd:double" minOccurs="0"/> - <element name="gift_message_id" type="xsd:string" minOccurs="0"/> - <element name="gift_message" type="xsd:string" minOccurs="0"/> - <element name="gift_message_available" type="xsd:string" minOccurs="0"/> - <element name="weee_tax_applied" type="xsd:double" minOccurs="0"/> - <element name="weee_tax_applied_amount" type="xsd:double" minOccurs="0"/> - <element name="weee_tax_applied_row_amount" type="xsd:double" minOccurs="0"/> - <element name="base_weee_tax_applied_amount" type="xsd:double" minOccurs="0"/> - <element name="base_weee_tax_applied_row_amnt" type="xsd:double" minOccurs="0"/> - <element name="weee_tax_disposition" type="xsd:double" minOccurs="0"/> - <element name="weee_tax_row_disposition" type="xsd:double" minOccurs="0"/> - <element name="base_weee_tax_disposition" type="xsd:double" minOccurs="0"/> - <element name="base_weee_tax_row_disposition" type="xsd:double" minOccurs="0"/> - <element name="tax_class_id" type="xsd:string" minOccurs="0"/> - </all> - </complexType> - <complexType name="shoppingCartItemEntityArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:shoppingCartItemEntity[]"/> - </restriction> - </complexContent> - </complexType> - <complexType name="shoppingCartPaymentEntity"> - <all> - <element name="payment_id" type="xsd:string" minOccurs="0"/> - <element name="created_at" type="xsd:string" minOccurs="0"/> - <element name="updated_at" type="xsd:string" minOccurs="0"/> - <element name="method" type="xsd:string" minOccurs="0"/> - <element name="cc_type" type="xsd:string" minOccurs="0"/> - <element name="cc_number_enc" type="xsd:string" minOccurs="0"/> - <element name="cc_last4" type="xsd:string" minOccurs="0"/> - <element name="cc_cid_enc" type="xsd:string" minOccurs="0"/> - <element name="cc_owner" type="xsd:string" minOccurs="0"/> - <element name="cc_exp_month" type="xsd:string" minOccurs="0"/> - <element name="cc_exp_year" type="xsd:string" minOccurs="0"/> - <element name="cc_ss_owner" type="xsd:string" minOccurs="0"/> - <element name="cc_ss_start_month" type="xsd:string" minOccurs="0"/> - <element name="cc_ss_start_year" type="xsd:string" minOccurs="0"/> - <element name="cc_ss_issue" type="xsd:string" minOccurs="0"/> - <element name="po_number" type="xsd:string" minOccurs="0"/> - <element name="additional_data" type="xsd:string" minOccurs="0"/> - <element name="additional_information" type="xsd:string" minOccurs="0"/> - </all> - </complexType> - <complexType name="shoppingCartInfoEntity"> - <all> - <element name="store_id" type="xsd:string" minOccurs="0"/> - <element name="created_at" type="xsd:string" minOccurs="0"/> - <element name="updated_at" type="xsd:string" minOccurs="0"/> - <element name="converted_at" type="xsd:string" minOccurs="0"/> - <element name="quote_id" type="xsd:int" minOccurs="0"/> - <element name="is_active" type="xsd:int" minOccurs="0"/> - <element name="is_virtual" type="xsd:int" minOccurs="0"/> - <element name="is_multi_shipping" type="xsd:int" minOccurs="0"/> - <element name="items_count" type="xsd:double" minOccurs="0"/> - <element name="items_qty" type="xsd:double" minOccurs="0"/> - <element name="orig_order_id" type="xsd:string" minOccurs="0"/> - <element name="store_to_base_rate" type="xsd:string" minOccurs="0"/> - <element name="store_to_quote_rate" type="xsd:string" minOccurs="0"/> - <element name="base_currency_code" type="xsd:string" minOccurs="0"/> - <element name="store_currency_code" type="xsd:string" minOccurs="0"/> - <element name="quote_currency_code" type="xsd:string" minOccurs="0"/> - <element name="grand_total" type="xsd:string" minOccurs="0"/> - <element name="base_grand_total" type="xsd:string" minOccurs="0"/> - <element name="checkout_method" type="xsd:string" minOccurs="0"/> - <element name="customer_id" type="xsd:string" minOccurs="0"/> - <element name="customer_tax_class_id" type="xsd:string" minOccurs="0"/> - <element name="customer_group_id" type="xsd:int" minOccurs="0"/> - <element name="customer_email" type="xsd:string" minOccurs="0"/> - <element name="customer_prefix" type="xsd:string" minOccurs="0"/> - <element name="customer_firstname" type="xsd:string" minOccurs="0"/> - <element name="customer_middlename" type="xsd:string" minOccurs="0"/> - <element name="customer_lastname" type="xsd:string" minOccurs="0"/> - <element name="customer_suffix" type="xsd:string" minOccurs="0"/> - <element name="customer_note" type="xsd:string" minOccurs="0"/> - <element name="customer_note_notify" type="xsd:string" minOccurs="0"/> - <element name="customer_is_guest" type="xsd:string" minOccurs="0"/> - <element name="applied_rule_ids" type="xsd:string" minOccurs="0"/> - <element name="reserved_order_id" type="xsd:string" minOccurs="0"/> - <element name="password_hash" type="xsd:string" minOccurs="0"/> - <element name="coupon_code" type="xsd:string" minOccurs="0"/> - <element name="global_currency_code" type="xsd:string" minOccurs="0"/> - <element name="base_to_global_rate" type="xsd:double" minOccurs="0"/> - <element name="base_to_quote_rate" type="xsd:double" minOccurs="0"/> - <element name="customer_taxvat" type="xsd:string" minOccurs="0"/> - <element name="customer_gender" type="xsd:string" minOccurs="0"/> - <element name="subtotal" type="xsd:double" minOccurs="0"/> - <element name="base_subtotal" type="xsd:double" minOccurs="0"/> - <element name="subtotal_with_discount" type="xsd:double" minOccurs="0"/> - <element name="base_subtotal_with_discount" type="xsd:double" minOccurs="0"/> - <element name="ext_shipping_info" type="xsd:string" minOccurs="0"/> - <element name="gift_message_id" type="xsd:string" minOccurs="0"/> - <element name="gift_message" type="xsd:string" minOccurs="0"/> - <element name="customer_balance_amount_used" type="xsd:double" minOccurs="0"/> - <element name="base_customer_bal_amount_used" type="xsd:double" minOccurs="0"/> - <element name="use_customer_balance" type="xsd:string" minOccurs="0"/> - <element name="gift_cards_amount" type="xsd:string" minOccurs="0"/> - <element name="base_gift_cards_amount" type="xsd:string" minOccurs="0"/> - <element name="gift_cards_amount_used" type="xsd:string" minOccurs="0"/> - <element name="use_reward_points" type="xsd:string" minOccurs="0"/> - <element name="reward_points_balance" type="xsd:string" minOccurs="0"/> - <element name="base_reward_currency_amount" type="xsd:string" minOccurs="0"/> - <element name="reward_currency_amount" type="xsd:string" minOccurs="0"/> - <element name="shipping_address" type="typens:shoppingCartAddressEntity" minOccurs="0"/> - <element name="billing_address" type="typens:shoppingCartAddressEntity" minOccurs="0"/> - <element name="items" type="typens:shoppingCartItemEntityArray" minOccurs="0"/> - <element name="payment" type="typens:shoppingCartPaymentEntity" minOccurs="0"/> - </all> - </complexType> - <complexType name="shoppingCartTotalsEntity"> - <all> - <element name="title" type="xsd:string" minOccurs="0"/> - <element name="amount" type="xsd:double" minOccurs="0"/> - </all> - </complexType> - <complexType name="shoppingCartTotalsEntityArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:shoppingCartTotalsEntity[]"/> - </restriction> - </complexContent> - </complexType> - <complexType name="shoppingCartLicenseEntity"> - <all> - <element name="agreement_id" type="xsd:string" minOccurs="0"/> - <element name="name" type="xsd:string" minOccurs="0"/> - <element name="content" type="xsd:string" minOccurs="0"/> - <element name="is_active" type="xsd:int" minOccurs="0"/> - <element name="is_html" type="xsd:int" minOccurs="0"/> - </all> - </complexType> - <complexType name="shoppingCartLicenseEntityArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:shoppingCartLicenseEntity[]"/> - </restriction> - </complexContent> - </complexType> - - <complexType name="shoppingCartProductEntity"> - <all> - <element name="product_id" type="xsd:string" minOccurs="0"/> - <element name="sku" type="xsd:string" minOccurs="0"/> - <element name="qty" type="xsd:double" minOccurs="0"/> - <element name="options" type="typens:associativeArray" minOccurs="0"/> - <element name="bundle_option" type="typens:associativeArray" minOccurs="0"/> - <element name="bundle_option_qty" type="typens:associativeArray" minOccurs="0"/> - <element name="links" type="typens:ArrayOfString" minOccurs="0"/> - </all> - </complexType> - <complexType name="shoppingCartProductEntityArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:shoppingCartProductEntity[]"/> - </restriction> - </complexContent> - </complexType> - <complexType name="shoppingCartProductResponseEntityArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:catalogProductEntity[]"/> - </restriction> - </complexContent> - </complexType> - <complexType name="shoppingCartCustomerEntity"> - <all> - <element name="mode" type="xsd:string" minOccurs="0"/> - <element name="customer_id" type="xsd:int" minOccurs="0"/> - <element name="email" type="xsd:string" minOccurs="0"/> - <element name="firstname" type="xsd:string" minOccurs="0"/> - <element name="lastname" type="xsd:string" minOccurs="0"/> - <element name="password" type="xsd:string" minOccurs="0"/> - <element name="confirmation" type="xsd:string" minOccurs="0"/> - <element name="website_id" type="xsd:int" minOccurs="0"/> - <element name="store_id" type="xsd:int" minOccurs="0"/> - <element name="group_id" type="xsd:int" minOccurs="0"/> - </all> - </complexType> - <complexType name="shoppingCartCustomerAddressEntity"> - <all> - <element name="mode" type="xsd:string" minOccurs="0"/> - <element name="address_id" type="xsd:string" minOccurs="0"/> - <element name="firstname" type="xsd:string" minOccurs="0"/> - <element name="lastname" type="xsd:string" minOccurs="0"/> - <element name="company" type="xsd:string" minOccurs="0"/> - <element name="street" type="xsd:string" minOccurs="0"/> - <element name="city" type="xsd:string" minOccurs="0"/> - <element name="region" type="xsd:string" minOccurs="0"/> - <element name="region_id" type="xsd:string" minOccurs="0"/> - <element name="postcode" type="xsd:string" minOccurs="0"/> - <element name="country_id" type="xsd:string" minOccurs="0"/> - <element name="telephone" type="xsd:string" minOccurs="0"/> - <element name="fax" type="xsd:string" minOccurs="0"/> - <element name="is_default_billing" type="xsd:int" minOccurs="0"/> - <element name="is_default_shipping" type="xsd:int" minOccurs="0"/> - </all> - </complexType> - <complexType name="shoppingCartCustomerAddressEntityArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:shoppingCartCustomerAddressEntity[]"/> - </restriction> - </complexContent> - </complexType> - <complexType name="shoppingCartShippingMethodEntity"> - <all> - <element name="code" type="xsd:string" minOccurs="0"/> - <element name="carrier" type="xsd:string" minOccurs="0"/> - <element name="carrier_title" type="xsd:string" minOccurs="0"/> - <element name="method" type="xsd:string" minOccurs="0"/> - <element name="method_title" type="xsd:string" minOccurs="0"/> - <element name="method_description" type="xsd:string" minOccurs="0"/> - <element name="price" type="xsd:double" minOccurs="0"/> - </all> - </complexType> - <complexType name="shoppingCartShippingMethodEntityArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:shoppingCartShippingMethodEntity[]"/> - </restriction> - </complexContent> - </complexType> - - <complexType name="shoppingCartPaymentMethodEntity"> - <all> - <element name="po_number" type="xsd:string" minOccurs="0"/> - <element name="method" type="xsd:string" minOccurs="0"/> - <element name="cc_cid" type="xsd:string" minOccurs="0"/> - <element name="cc_owner" type="xsd:string" minOccurs="0"/> - <element name="cc_number" type="xsd:string" minOccurs="0"/> - <element name="cc_type" type="xsd:string" minOccurs="0"/> - <element name="cc_exp_year" type="xsd:string" minOccurs="0"/> - <element name="cc_exp_month" type="xsd:string" minOccurs="0"/> - </all> - </complexType> - <complexType name="shoppingCartPaymentMethodResponseEntityArray"> - <all> - <element name="code" type="xsd:string"/> - <element name="title" type="xsd:string"/> - <element name="cc_types" type="typens:associativeArray"/> - </all> - </complexType> - </schema> - </types> - <message name="shoppingCartCreateRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="storeId" type="xsd:string"/> - </message> - <message name="shoppingCartCreateResponse"> - <part name="quoteId" type="xsd:int"/> - </message> - <message name="shoppingCartOrderRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="quoteId" type="xsd:int"/> - <part name="storeId" type="xsd:string"/> - <part name="licenses" type="typens:ArrayOfString"/> - </message> - <message name="shoppingCartOrderResponse"> - <part name="result" type="xsd:string"/> - </message> - <message name="shoppingCartInfoRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="quoteId" type="xsd:int"/> - <part name="storeId" type="xsd:string"/> - </message> - <message name="shoppingCartInfoResponse"> - <part name="result" type="typens:shoppingCartInfoEntity"/> - </message> - <message name="shoppingCartTotalsRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="quoteId" type="xsd:int"/> - <part name="storeId" type="xsd:string"/> - </message> - <message name="shoppingCartTotalsResponse"> - <part name="result" type="typens:shoppingCartTotalsEntityArray"/> - </message> - <message name="shoppingCartLicenseRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="quoteId" type="xsd:int"/> - <part name="storeId" type="xsd:string"/> - </message> - <message name="shoppingCartLicenseResponse"> - <part name="result" type="typens:shoppingCartLicenseEntityArray"/> - </message> - <message name="shoppingCartProductAddRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="quoteId" type="xsd:int"/> - <part name="products" type="typens:shoppingCartProductEntityArray"/> - <part name="storeId" type="xsd:string"/> - </message> - <message name="shoppingCartProductAddResponse"> - <part name="result" type="xsd:boolean"/> - </message> - <message name="shoppingCartProductUpdateRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="quoteId" type="xsd:int"/> - <part name="products" type="typens:shoppingCartProductEntityArray"/> - <part name="storeId" type="xsd:string"/> - </message> - <message name="shoppingCartProductUpdateResponse"> - <part name="result" type="xsd:boolean"/> - </message> - <message name="shoppingCartProductRemoveRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="quoteId" type="xsd:int"/> - <part name="products" type="typens:shoppingCartProductEntityArray"/> - <part name="storeId" type="xsd:string"/> - </message> - <message name="shoppingCartProductRemoveResponse"> - <part name="result" type="xsd:boolean"/> - </message> - <message name="shoppingCartProductListRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="quoteId" type="xsd:int"/> - <part name="storeId" type="xsd:string"/> - </message> - <message name="shoppingCartProductListResponse"> - <part name="result" type="typens:shoppingCartProductResponseEntityArray"/> - </message> - <message name="shoppingCartProductMoveToCustomerQuoteRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="quoteId" type="xsd:int"/> - <part name="products" type="typens:shoppingCartProductEntityArray"/> - <part name="storeId" type="xsd:string"/> - </message> - <message name="shoppingCartProductMoveToCustomerQuoteResponse"> - <part name="result" type="xsd:boolean"/> - </message> - <message name="shoppingCartCustomerSetRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="quoteId" type="xsd:int"/> - <part name="customer" type="typens:shoppingCartCustomerEntity"/> - <part name="storeId" type="xsd:string"/> - </message> - <message name="shoppingCartCustomerSetResponse"> - <part name="result" type="xsd:boolean"/> - </message> - <message name="shoppingCartCustomerAddressesRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="quoteId" type="xsd:int"/> - <part name="customer" type="typens:shoppingCartCustomerAddressEntityArray"/> - <part name="storeId" type="xsd:string"/> - </message> - <message name="shoppingCartCustomerAddressesResponse"> - <part name="result" type="xsd:boolean"/> - </message> - <message name="shoppingCartShippingMethodRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="quoteId" type="xsd:int"/> - <part name="method" type="xsd:string"/> - <part name="storeId" type="xsd:string"/> - </message> - <message name="shoppingCartShippingMethodResponse"> - <part name="result" type="xsd:boolean"/> - </message> - <message name="shoppingCartShippingListRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="quoteId" type="xsd:int"/> - <part name="storeId" type="xsd:string"/> - </message> - <message name="shoppingCartShippingListResponse"> - <part name="result" type="typens:shoppingCartShippingMethodEntityArray"/> - </message> - <message name="shoppingCartPaymentMethodRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="quoteId" type="xsd:int"/> - <part name="method" type="typens:shoppingCartPaymentMethodEntity"/> - <part name="storeId" type="xsd:string"/> - </message> - <message name="shoppingCartPaymentMethodResponse"> - <part name="result" type="xsd:boolean"/> - </message> - <message name="shoppingCartPaymentListRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="quoteId" type="xsd:int"/> - <part name="storeId" type="xsd:string"/> - </message> - <message name="shoppingCartPaymentListResponse"> - <part name="result" type="typens:shoppingCartPaymentMethodResponseEntityArray"/> - </message> - <message name="shoppingCartCouponAddRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="quoteId" type="xsd:int"/> - <part name="couponCode" type="xsd:string"/> - <part name="storeId" type="xsd:string"/> - </message> - <message name="shoppingCartCouponAddResponse"> - <part name="result" type="xsd:boolean"/> - </message> - <message name="shoppingCartCouponRemoveRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="quoteId" type="xsd:int"/> - <part name="storeId" type="xsd:string"/> - </message> - <message name="shoppingCartCouponRemoveResponse"> - <part name="result" type="xsd:boolean"/> - </message> - <portType name="{{var wsdl.handler}}PortType"> - <operation name="shoppingCartCreate"> - <documentation>Create shopping cart</documentation> - <input message="typens:shoppingCartCreateRequest"/> - <output message="typens:shoppingCartCreateResponse"/> - </operation> - <operation name="shoppingCartInfo"> - <documentation>Retrieve information about shopping cart</documentation> - <input message="typens:shoppingCartInfoRequest"/> - <output message="typens:shoppingCartInfoResponse"/> - </operation> - <operation name="shoppingCartOrder"> - <documentation>Create an order from shopping cart</documentation> - <input message="typens:shoppingCartOrderRequest"/> - <output message="typens:shoppingCartOrderResponse"/> - </operation> - <operation name="shoppingCartTotals"> - <documentation>Get total prices for shopping cart</documentation> - <input message="typens:shoppingCartTotalsRequest"/> - <output message="typens:shoppingCartTotalsResponse"/> - </operation> - <operation name="shoppingCartLicense"> - <documentation>Get terms and conditions</documentation> - <input message="typens:shoppingCartLicenseRequest"/> - <output message="typens:shoppingCartLicenseResponse"/> - </operation> - <operation name="shoppingCartProductAdd"> - <documentation>Add product(s) to shopping cart</documentation> - <input message="typens:shoppingCartProductAddRequest"/> - <output message="typens:shoppingCartProductAddResponse"/> - </operation> - <operation name="shoppingCartProductUpdate"> - <documentation>Update product(s) quantities in shopping cart</documentation> - <input message="typens:shoppingCartProductUpdateRequest"/> - <output message="typens:shoppingCartProductUpdateResponse"/> - </operation> - <operation name="shoppingCartProductRemove"> - <documentation>Remove product(s) from shopping cart</documentation> - <input message="typens:shoppingCartProductRemoveRequest"/> - <output message="typens:shoppingCartProductRemoveResponse"/> - </operation> - <operation name="shoppingCartProductList"> - <documentation>Get list of products in shopping cart</documentation> - <input message="typens:shoppingCartProductListRequest"/> - <output message="typens:shoppingCartProductListResponse"/> - </operation> - <operation name="shoppingCartProductMoveToCustomerQuote"> - <documentation>Move product(s) to customer quote</documentation> - <input message="typens:shoppingCartProductMoveToCustomerQuoteRequest"/> - <output message="typens:shoppingCartProductMoveToCustomerQuoteResponse"/> - </operation> - <operation name="shoppingCartCustomerSet"> - <documentation>Set customer for shopping cart</documentation> - <input message="typens:shoppingCartCustomerSetRequest"/> - <output message="typens:shoppingCartCustomerSetResponse"/> - </operation> - <operation name="shoppingCartCustomerAddresses"> - <documentation>Set customer's addresses in shopping cart</documentation> - <input message="typens:shoppingCartCustomerAddressesRequest"/> - <output message="typens:shoppingCartCustomerAddressesResponse"/> - </operation> - <operation name="shoppingCartShippingMethod"> - <documentation>Set shipping method</documentation> - <input message="typens:shoppingCartShippingMethodRequest"/> - <output message="typens:shoppingCartShippingMethodResponse"/> - </operation> - <operation name="shoppingCartShippingList"> - <documentation>Get list of available shipping methods</documentation> - <input message="typens:shoppingCartShippingListRequest"/> - <output message="typens:shoppingCartShippingListResponse"/> - </operation> - <operation name="shoppingCartPaymentMethod"> - <documentation>Set payment method</documentation> - <input message="typens:shoppingCartPaymentMethodRequest"/> - <output message="typens:shoppingCartPaymentMethodResponse"/> - </operation> - <operation name="shoppingCartPaymentList"> - <documentation>Get list of available payment methods</documentation> - <input message="typens:shoppingCartPaymentListRequest"/> - <output message="typens:shoppingCartPaymentListResponse"/> - </operation> - <operation name="shoppingCartCouponAdd"> - <documentation>Add coupon code for shopping cart</documentation> - <input message="typens:shoppingCartCouponAddRequest"/> - <output message="typens:shoppingCartCouponAddResponse"/> - </operation> - <operation name="shoppingCartCouponRemove"> - <documentation>Remove coupon code from shopping cart</documentation> - <input message="typens:shoppingCartCouponRemoveRequest"/> - <output message="typens:shoppingCartCouponRemoveResponse"/> - </operation> - </portType> - <binding name="{{var wsdl.handler}}Binding" type="typens:{{var wsdl.handler}}PortType"> - <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/> - <operation name="shoppingCartCreate"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="shoppingCartInfo"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="shoppingCartTotals"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="shoppingCartOrder"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="shoppingCartLicense"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="shoppingCartProductAdd"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="shoppingCartProductUpdate"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="shoppingCartProductRemove"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="shoppingCartProductList"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="shoppingCartProductMoveToCustomerQuote"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="shoppingCartCustomerSet"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="shoppingCartCustomerAddresses"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="shoppingCartShippingMethod"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="shoppingCartShippingList"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="shoppingCartPaymentMethod"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="shoppingCartPaymentList"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="shoppingCartCouponAdd"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="shoppingCartCouponRemove"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - </binding> -</definitions> diff --git a/app/code/core/Mage/Checkout/etc/wsi.xml b/app/code/core/Mage/Checkout/etc/wsi.xml deleted file mode 100644 index cd443aac5248bebe46d5cd370707a1fdf34634ff..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Checkout/etc/wsi.xml +++ /dev/null @@ -1,977 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<wsdl:definitions xmlns:typens="urn:{{var wsdl.name}}" - xmlns:xsd="http://www.w3.org/2001/XMLSchema" - xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" - xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" - xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" - name="{{var wsdl.name}}" - targetNamespace="urn:{{var wsdl.name}}"> - <wsdl:types> - <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:{{var wsdl.name}}"> - <xsd:complexType name="shoppingCartAddressEntity"> - <xsd:sequence> - <xsd:element name="address_id" type="xsd:string" minOccurs="0"/> - <xsd:element name="created_at" type="xsd:string" minOccurs="0"/> - <xsd:element name="updated_at" type="xsd:string" minOccurs="0"/> - <xsd:element name="customer_id" type="xsd:string" minOccurs="0"/> - <xsd:element name="save_in_address_book" type="xsd:int" minOccurs="0"/> - <xsd:element name="customer_address_id" type="xsd:string" minOccurs="0"/> - <xsd:element name="address_type" type="xsd:string" minOccurs="0"/> - <xsd:element name="email" type="xsd:string" minOccurs="0"/> - <xsd:element name="prefix" type="xsd:string" minOccurs="0"/> - <xsd:element name="firstname" type="xsd:string" minOccurs="0"/> - <xsd:element name="middlename" type="xsd:string" minOccurs="0"/> - <xsd:element name="lastname" type="xsd:string" minOccurs="0"/> - <xsd:element name="suffix" type="xsd:string" minOccurs="0"/> - <xsd:element name="company" type="xsd:string" minOccurs="0"/> - <xsd:element name="street" type="xsd:string" minOccurs="0"/> - <xsd:element name="city" type="xsd:string" minOccurs="0"/> - <xsd:element name="region" type="xsd:string" minOccurs="0"/> - <xsd:element name="region_id" type="xsd:string" minOccurs="0"/> - <xsd:element name="postcode" type="xsd:string" minOccurs="0"/> - <xsd:element name="country_id" type="xsd:string" minOccurs="0"/> - <xsd:element name="telephone" type="xsd:string" minOccurs="0"/> - <xsd:element name="fax" type="xsd:string" minOccurs="0"/> - <xsd:element name="same_as_billing" type="xsd:int" minOccurs="0"/> - <xsd:element name="free_shipping" type="xsd:int" minOccurs="0"/> - <xsd:element name="shipping_method" type="xsd:string" minOccurs="0"/> - <xsd:element name="shipping_description" type="xsd:string" minOccurs="0"/> - <xsd:element name="weight" type="xsd:double" minOccurs="0"/> - <xsd:element name="fax" type="xsd:string" minOccurs="0"/> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="shoppingCartItemEntity"> - <xsd:sequence> - <xsd:element name="item_id" type="xsd:string" minOccurs="0"/> - <xsd:element name="created_at" type="xsd:string" minOccurs="0"/> - <xsd:element name="updated_at" type="xsd:string" minOccurs="0"/> - <xsd:element name="product_id" type="xsd:string" minOccurs="0"/> - <xsd:element name="store_id" type="xsd:string" minOccurs="0"/> - <xsd:element name="parent_item_id" type="xsd:string" minOccurs="0"/> - <xsd:element name="is_virtual" type="xsd:int" minOccurs="0"/> - <xsd:element name="sku" type="xsd:string" minOccurs="0"/> - <xsd:element name="name" type="xsd:string" minOccurs="0"/> - <xsd:element name="description" type="xsd:string" minOccurs="0"/> - <xsd:element name="applied_rule_ids" type="xsd:string" minOccurs="0"/> - <xsd:element name="additional_data" type="xsd:string" minOccurs="0"/> - <xsd:element name="free_shipping" type="xsd:string" minOccurs="0"/> - <xsd:element name="is_qty_decimal" type="xsd:string" minOccurs="0"/> - <xsd:element name="no_discount" type="xsd:string" minOccurs="0"/> - <xsd:element name="weight" type="xsd:double" minOccurs="0"/> - <xsd:element name="qty" type="xsd:double" minOccurs="0"/> - <xsd:element name="price" type="xsd:double" minOccurs="0"/> - <xsd:element name="base_price" type="xsd:double" minOccurs="0"/> - <xsd:element name="custom_price" type="xsd:double" minOccurs="0"/> - <xsd:element name="discount_percent" type="xsd:double" minOccurs="0"/> - <xsd:element name="discount_amount" type="xsd:double" minOccurs="0"/> - <xsd:element name="base_discount_amount" type="xsd:double" minOccurs="0"/> - <xsd:element name="tax_percent" type="xsd:double" minOccurs="0"/> - <xsd:element name="tax_amount" type="xsd:double" minOccurs="0"/> - <xsd:element name="base_tax_amount" type="xsd:double" minOccurs="0"/> - <xsd:element name="row_total" type="xsd:double" minOccurs="0"/> - <xsd:element name="base_row_total" type="xsd:double" minOccurs="0"/> - <xsd:element name="row_total_with_discount" type="xsd:double" minOccurs="0"/> - <xsd:element name="row_weight" type="xsd:double" minOccurs="0"/> - <xsd:element name="product_type" type="xsd:string" minOccurs="0"/> - <xsd:element name="base_tax_before_discount" type="xsd:double" minOccurs="0"/> - <xsd:element name="tax_before_discount" type="xsd:double" minOccurs="0"/> - <xsd:element name="original_custom_price" type="xsd:double" minOccurs="0"/> - <xsd:element name="base_cost" type="xsd:double" minOccurs="0"/> - <xsd:element name="price_incl_tax" type="xsd:double" minOccurs="0"/> - <xsd:element name="base_price_incl_tax" type="xsd:double" minOccurs="0"/> - <xsd:element name="row_total_incl_tax" type="xsd:double" minOccurs="0"/> - <xsd:element name="base_row_total_incl_tax" type="xsd:double" minOccurs="0"/> - <xsd:element name="gift_message_id" type="xsd:string" minOccurs="0"/> - <xsd:element name="gift_message" type="xsd:string" minOccurs="0"/> - <xsd:element name="gift_message_available" type="xsd:string" minOccurs="0"/> - <xsd:element name="weee_tax_applied" type="xsd:double" minOccurs="0"/> - <xsd:element name="weee_tax_applied_amount" type="xsd:double" minOccurs="0"/> - <xsd:element name="weee_tax_applied_row_amount" type="xsd:double" minOccurs="0"/> - <xsd:element name="base_weee_tax_applied_amount" type="xsd:double" minOccurs="0"/> - <xsd:element name="base_weee_tax_applied_row_amnt" type="xsd:double" minOccurs="0"/> - <xsd:element name="weee_tax_disposition" type="xsd:double" minOccurs="0"/> - <xsd:element name="weee_tax_row_disposition" type="xsd:double" minOccurs="0"/> - <xsd:element name="base_weee_tax_disposition" type="xsd:double" minOccurs="0"/> - <xsd:element name="base_weee_tax_row_disposition" type="xsd:double" minOccurs="0"/> - <xsd:element name="tax_class_id" type="xsd:string" minOccurs="0"/> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="shoppingCartItemEntityArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:shoppingCartItemEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="shoppingCartPaymentEntity"> - <xsd:sequence> - <xsd:element name="payment_id" type="xsd:string" minOccurs="0"/> - <xsd:element name="created_at" type="xsd:string" minOccurs="0"/> - <xsd:element name="updated_at" type="xsd:string" minOccurs="0"/> - <xsd:element name="method" type="xsd:string" minOccurs="0"/> - <xsd:element name="cc_type" type="xsd:string" minOccurs="0"/> - <xsd:element name="cc_number_enc" type="xsd:string" minOccurs="0"/> - <xsd:element name="cc_last4" type="xsd:string" minOccurs="0"/> - <xsd:element name="cc_cid_enc" type="xsd:string" minOccurs="0"/> - <xsd:element name="cc_owner" type="xsd:string" minOccurs="0"/> - <xsd:element name="cc_exp_month" type="xsd:string" minOccurs="0"/> - <xsd:element name="cc_exp_year" type="xsd:string" minOccurs="0"/> - <xsd:element name="cc_ss_owner" type="xsd:string" minOccurs="0"/> - <xsd:element name="cc_ss_start_month" type="xsd:string" minOccurs="0"/> - <xsd:element name="cc_ss_start_year" type="xsd:string" minOccurs="0"/> - <xsd:element name="cc_ss_issue" type="xsd:string" minOccurs="0"/> - <xsd:element name="po_number" type="xsd:string" minOccurs="0"/> - <xsd:element name="additional_data" type="xsd:string" minOccurs="0"/> - <xsd:element name="additional_information" type="xsd:string" minOccurs="0"/> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="shoppingCartInfoEntity"> - <xsd:sequence> - <xsd:element name="store_id" type="xsd:string" minOccurs="0"/> - <xsd:element name="created_at" type="xsd:string" minOccurs="0"/> - <xsd:element name="updated_at" type="xsd:string" minOccurs="0"/> - <xsd:element name="converted_at" type="xsd:string" minOccurs="0"/> - <xsd:element name="quote_id" type="xsd:int" minOccurs="0"/> - <xsd:element name="is_active" type="xsd:int" minOccurs="0"/> - <xsd:element name="is_virtual" type="xsd:int" minOccurs="0"/> - <xsd:element name="is_multi_shipping" type="xsd:int" minOccurs="0"/> - <xsd:element name="items_count" type="xsd:double" minOccurs="0"/> - <xsd:element name="items_qty" type="xsd:double" minOccurs="0"/> - <xsd:element name="orig_order_id" type="xsd:string" minOccurs="0"/> - <xsd:element name="store_to_base_rate" type="xsd:string" minOccurs="0"/> - <xsd:element name="store_to_quote_rate" type="xsd:string" minOccurs="0"/> - <xsd:element name="base_currency_code" type="xsd:string" minOccurs="0"/> - <xsd:element name="store_currency_code" type="xsd:string" minOccurs="0"/> - <xsd:element name="quote_currency_code" type="xsd:string" minOccurs="0"/> - <xsd:element name="grand_total" type="xsd:string" minOccurs="0"/> - <xsd:element name="base_grand_total" type="xsd:string" minOccurs="0"/> - <xsd:element name="checkout_method" type="xsd:string" minOccurs="0"/> - <xsd:element name="customer_id" type="xsd:string" minOccurs="0"/> - <xsd:element name="customer_tax_class_id" type="xsd:string" minOccurs="0"/> - <xsd:element name="customer_group_id" type="xsd:int" minOccurs="0"/> - <xsd:element name="customer_email" type="xsd:string" minOccurs="0"/> - <xsd:element name="customer_prefix" type="xsd:string" minOccurs="0"/> - <xsd:element name="customer_firstname" type="xsd:string" minOccurs="0"/> - <xsd:element name="customer_middlename" type="xsd:string" minOccurs="0"/> - <xsd:element name="customer_lastname" type="xsd:string" minOccurs="0"/> - <xsd:element name="customer_suffix" type="xsd:string" minOccurs="0"/> - <xsd:element name="customer_note" type="xsd:string" minOccurs="0"/> - <xsd:element name="customer_note_notify" type="xsd:string" minOccurs="0"/> - <xsd:element name="customer_is_guest" type="xsd:string" minOccurs="0"/> - <xsd:element name="applied_rule_ids" type="xsd:string" minOccurs="0"/> - <xsd:element name="reserved_order_id" type="xsd:string" minOccurs="0"/> - <xsd:element name="password_hash" type="xsd:string" minOccurs="0"/> - <xsd:element name="coupon_code" type="xsd:string" minOccurs="0"/> - <xsd:element name="global_currency_code" type="xsd:string" minOccurs="0"/> - <xsd:element name="base_to_global_rate" type="xsd:double" minOccurs="0"/> - <xsd:element name="base_to_quote_rate" type="xsd:double" minOccurs="0"/> - <xsd:element name="customer_taxvat" type="xsd:string" minOccurs="0"/> - <xsd:element name="customer_gender" type="xsd:string" minOccurs="0"/> - <xsd:element name="subtotal" type="xsd:double" minOccurs="0"/> - <xsd:element name="base_subtotal" type="xsd:double" minOccurs="0"/> - <xsd:element name="subtotal_with_discount" type="xsd:double" minOccurs="0"/> - <xsd:element name="base_subtotal_with_discount" type="xsd:double" minOccurs="0"/> - <xsd:element name="ext_shipping_info" type="xsd:string" minOccurs="0"/> - <xsd:element name="gift_message_id" type="xsd:string" minOccurs="0"/> - <xsd:element name="gift_message" type="xsd:string" minOccurs="0"/> - <xsd:element name="customer_balance_amount_used" type="xsd:double" minOccurs="0"/> - <xsd:element name="base_customer_bal_amount_used" type="xsd:double" minOccurs="0"/> - <xsd:element name="use_customer_balance" type="xsd:string" minOccurs="0"/> - <xsd:element name="gift_cards_amount" type="xsd:string" minOccurs="0"/> - <xsd:element name="base_gift_cards_amount" type="xsd:string" minOccurs="0"/> - <xsd:element name="gift_cards_amount_used" type="xsd:string" minOccurs="0"/> - <xsd:element name="use_reward_points" type="xsd:string" minOccurs="0"/> - <xsd:element name="reward_points_balance" type="xsd:string" minOccurs="0"/> - <xsd:element name="base_reward_currency_amount" type="xsd:string" minOccurs="0"/> - <xsd:element name="reward_currency_amount" type="xsd:string" minOccurs="0"/> - <xsd:element name="shipping_address" type="typens:shoppingCartAddressEntity" minOccurs="0"/> - <xsd:element name="billing_address" type="typens:shoppingCartAddressEntity" minOccurs="0"/> - <xsd:element name="items" type="typens:shoppingCartItemEntityArray" minOccurs="0"/> - <xsd:element name="payment" type="typens:shoppingCartPaymentEntity" minOccurs="0"/> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="shoppingCartTotalsEntity"> - <xsd:sequence> - <xsd:element name="title" type="xsd:string" minOccurs="0"/> - <xsd:element name="amount" type="xsd:double" minOccurs="0"/> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="shoppingCartTotalsEntityArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:shoppingCartTotalsEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="shoppingCartLicenseEntity"> - <xsd:sequence> - <xsd:element name="agreement_id" type="xsd:string" minOccurs="0"/> - <xsd:element name="name" type="xsd:string" minOccurs="0"/> - <xsd:element name="content" type="xsd:string" minOccurs="0"/> - <xsd:element name="is_active" type="xsd:int" minOccurs="0"/> - <xsd:element name="is_html" type="xsd:int" minOccurs="0"/> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="shoppingCartLicenseEntityArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:shoppingCartLicenseEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="shoppingCartProductEntity"> - <xsd:sequence> - <xsd:element name="product_id" type="xsd:string" minOccurs="0"/> - <xsd:element name="sku" type="xsd:string" minOccurs="0"/> - <xsd:element name="qty" type="xsd:double" minOccurs="0"/> - <xsd:element name="options" type="typens:associativeArray" minOccurs="0"/> - <xsd:element name="bundle_option" type="typens:associativeArray" minOccurs="0"/> - <xsd:element name="bundle_option_qty" type="typens:associativeArray" minOccurs="0"/> - <xsd:element name="links" type="typens:ArrayOfString" minOccurs="0"/> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="shoppingCartProductEntityArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:shoppingCartProductEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="shoppingCartProductResponseEntityArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:catalogProductEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="shoppingCartCustomerEntity"> - <xsd:sequence> - <xsd:element name="mode" type="xsd:string" minOccurs="0"/> - <xsd:element name="customer_id" type="xsd:int" minOccurs="0"/> - <xsd:element name="email" type="xsd:string" minOccurs="0"/> - <xsd:element name="firstname" type="xsd:string" minOccurs="0"/> - <xsd:element name="lastname" type="xsd:string" minOccurs="0"/> - <xsd:element name="password" type="xsd:string" minOccurs="0"/> - <xsd:element name="confirmation" type="xsd:string" minOccurs="0"/> - <xsd:element name="website_id" type="xsd:int" minOccurs="0"/> - <xsd:element name="store_id" type="xsd:int" minOccurs="0"/> - <xsd:element name="group_id" type="xsd:int" minOccurs="0"/> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="shoppingCartCustomerAddressEntity"> - <xsd:sequence> - <xsd:element name="mode" type="xsd:string" minOccurs="0"/> - <xsd:element name="address_id" type="xsd:string" minOccurs="0"/> - <xsd:element name="firstname" type="xsd:string" minOccurs="0"/> - <xsd:element name="lastname" type="xsd:string" minOccurs="0"/> - <xsd:element name="company" type="xsd:string" minOccurs="0"/> - <xsd:element name="street" type="xsd:string" minOccurs="0"/> - <xsd:element name="city" type="xsd:string" minOccurs="0"/> - <xsd:element name="region" type="xsd:string" minOccurs="0"/> - <xsd:element name="region_id" type="xsd:string" minOccurs="0"/> - <xsd:element name="postcode" type="xsd:string" minOccurs="0"/> - <xsd:element name="country_id" type="xsd:string" minOccurs="0"/> - <xsd:element name="telephone" type="xsd:string" minOccurs="0"/> - <xsd:element name="fax" type="xsd:string" minOccurs="0"/> - <xsd:element name="is_default_billing" type="xsd:int" minOccurs="0"/> - <xsd:element name="is_default_shipping" type="xsd:int" minOccurs="0"/> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="shoppingCartCustomerAddressEntityArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:shoppingCartCustomerAddressEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="shoppingCartShippingMethodEntity"> - <xsd:sequence> - <xsd:element name="code" type="xsd:string" minOccurs="0"/> - <xsd:element name="carrier" type="xsd:string" minOccurs="0"/> - <xsd:element name="carrier_title" type="xsd:string" minOccurs="0"/> - <xsd:element name="method" type="xsd:string" minOccurs="0"/> - <xsd:element name="method_title" type="xsd:string" minOccurs="0"/> - <xsd:element name="method_description" type="xsd:string" minOccurs="0"/> - <xsd:element name="price" type="xsd:double" minOccurs="0"/> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="shoppingCartShippingMethodEntityArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:shoppingCartShippingMethodEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="shoppingCartPaymentMethodEntity"> - <xsd:sequence> - <xsd:element name="po_number" type="xsd:string" minOccurs="0"/> - <xsd:element name="method" type="xsd:string" minOccurs="0"/> - <xsd:element name="cc_cid" type="xsd:string" minOccurs="0"/> - <xsd:element name="cc_owner" type="xsd:string" minOccurs="0"/> - <xsd:element name="cc_number" type="xsd:string" minOccurs="0"/> - <xsd:element name="cc_type" type="xsd:string" minOccurs="0"/> - <xsd:element name="cc_exp_year" type="xsd:string" minOccurs="0"/> - <xsd:element name="cc_exp_month" type="xsd:string" minOccurs="0"/> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="shoppingCartPaymentMethodResponseEntityArray"> - <xsd:sequence> - <xsd:element name="code" type="xsd:string"/> - <xsd:element name="title" type="xsd:string"/> - <xsd:element name="cc_types" type="typens:associativeArray"/> - </xsd:sequence> - </xsd:complexType> - - - <xsd:element name="shoppingCartCreateRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="shoppingCartCreateResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="shoppingCartOrderRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="quoteId" type="xsd:int" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="agreements" type="typens:ArrayOfString" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="shoppingCartOrderResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="shoppingCartInfoRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="quoteId" type="xsd:int" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="shoppingCartInfoResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:shoppingCartInfoEntity" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="shoppingCartTotalsRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="quoteId" type="xsd:int" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="shoppingCartTotalsResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:shoppingCartTotalsEntityArray" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="shoppingCartLicenseRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="quoteId" type="xsd:int" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="shoppingCartLicenseResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:shoppingCartLicenseEntityArray" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="shoppingCartProductAddRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="quoteId" type="xsd:int" /> - <xsd:element minOccurs="1" maxOccurs="1" name="productsData" type="typens:shoppingCartProductEntityArray" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="shoppingCartProductAddResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:boolean" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="shoppingCartProductUpdateRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="quoteId" type="xsd:int" /> - <xsd:element minOccurs="1" maxOccurs="1" name="productsData" type="typens:shoppingCartProductEntityArray" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="shoppingCartProductUpdateResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:boolean" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="shoppingCartProductRemoveRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="quoteId" type="xsd:int" /> - <xsd:element minOccurs="1" maxOccurs="1" name="productsData" type="typens:shoppingCartProductEntityArray" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="shoppingCartProductRemoveResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:boolean" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="shoppingCartProductListRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="quoteId" type="xsd:int" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="shoppingCartProductListResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:shoppingCartProductResponseEntityArray" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="shoppingCartProductMoveToCustomerQuoteRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="quoteId" type="xsd:int" /> - <xsd:element minOccurs="1" maxOccurs="1" name="productsData" type="typens:shoppingCartProductEntityArray" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="shoppingCartProductMoveToCustomerQuoteResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:boolean" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="shoppingCartCustomerSetRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="quoteId" type="xsd:int" /> - <xsd:element minOccurs="1" maxOccurs="1" name="customerData" type="typens:shoppingCartCustomerEntity" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="shoppingCartCustomerSetResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:boolean" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="shoppingCartCustomerAddressesRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="quoteId" type="xsd:int" /> - <xsd:element minOccurs="1" maxOccurs="1" name="customerAddressData" type="typens:shoppingCartCustomerAddressEntityArray" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="shoppingCartCustomerAddressesResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:boolean" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="shoppingCartShippingMethodRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="quoteId" type="xsd:int" /> - <xsd:element minOccurs="1" maxOccurs="1" name="shippingMethod" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="shoppingCartShippingMethodResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:boolean" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="shoppingCartShippingListRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="quoteId" type="xsd:int" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="shoppingCartShippingListResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:shoppingCartShippingMethodEntityArray" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="shoppingCartPaymentMethodRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="quoteId" type="xsd:int" /> - <xsd:element minOccurs="1" maxOccurs="1" name="paymentData" type="typens:shoppingCartPaymentMethodEntity" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="shoppingCartPaymentMethodResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:boolean" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="shoppingCartPaymentListRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="quoteId" type="xsd:int" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="shoppingCartPaymentListResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:shoppingCartPaymentMethodResponseEntityArray" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="shoppingCartCouponAddRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="quoteId" type="xsd:int" /> - <xsd:element minOccurs="1" maxOccurs="1" name="couponCode" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="shoppingCartCouponAddResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:boolean" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="shoppingCartCouponRemoveRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="quoteId" type="xsd:int" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="shoppingCartCouponRemoveResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:boolean" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - </xsd:schema> - </wsdl:types> - <wsdl:message name="shoppingCartCreateRequest"> - <wsdl:part name="parameters" element="typens:shoppingCartCreateRequestParam" /> - </wsdl:message> - <wsdl:message name="shoppingCartCreateResponse"> - <wsdl:part name="parameters" element="typens:shoppingCartCreateResponseParam" /> - </wsdl:message> - <wsdl:message name="shoppingCartOrderRequest"> - <wsdl:part name="parameters" element="typens:shoppingCartOrderRequestParam" /> - </wsdl:message> - <wsdl:message name="shoppingCartOrderResponse"> - <wsdl:part name="parameters" element="typens:shoppingCartOrderResponseParam" /> - </wsdl:message> - <wsdl:message name="shoppingCartInfoRequest"> - <wsdl:part name="parameters" element="typens:shoppingCartInfoRequestParam" /> - </wsdl:message> - <wsdl:message name="shoppingCartInfoResponse"> - <wsdl:part name="parameters" element="typens:shoppingCartInfoResponseParam" /> - </wsdl:message> - <wsdl:message name="shoppingCartTotalsRequest"> - <wsdl:part name="parameters" element="typens:shoppingCartTotalsRequestParam" /> - </wsdl:message> - <wsdl:message name="shoppingCartTotalsResponse"> - <wsdl:part name="parameters" element="typens:shoppingCartTotalsResponseParam" /> - </wsdl:message> - <wsdl:message name="shoppingCartLicenseRequest"> - <wsdl:part name="parameters" element="typens:shoppingCartLicenseRequestParam" /> - </wsdl:message> - <wsdl:message name="shoppingCartLicenseResponse"> - <wsdl:part name="parameters" element="typens:shoppingCartLicenseResponseParam" /> - </wsdl:message> - <wsdl:message name="shoppingCartProductAddRequest"> - <wsdl:part name="parameters" element="typens:shoppingCartProductAddRequestParam" /> - </wsdl:message> - <wsdl:message name="shoppingCartProductAddResponse"> - <wsdl:part name="parameters" element="typens:shoppingCartProductAddResponseParam" /> - </wsdl:message> - <wsdl:message name="shoppingCartProductUpdateRequest"> - <wsdl:part name="parameters" element="typens:shoppingCartProductUpdateRequestParam" /> - </wsdl:message> - <wsdl:message name="shoppingCartProductUpdateResponse"> - <wsdl:part name="parameters" element="typens:shoppingCartProductUpdateResponseParam" /> - </wsdl:message> - <wsdl:message name="shoppingCartProductRemoveRequest"> - <wsdl:part name="parameters" element="typens:shoppingCartProductRemoveRequestParam" /> - </wsdl:message> - <wsdl:message name="shoppingCartProductRemoveResponse"> - <wsdl:part name="parameters" element="typens:shoppingCartProductRemoveResponseParam" /> - </wsdl:message> - <wsdl:message name="shoppingCartProductListRequest"> - <wsdl:part name="parameters" element="typens:shoppingCartProductListRequestParam" /> - </wsdl:message> - <wsdl:message name="shoppingCartProductListResponse"> - <wsdl:part name="parameters" element="typens:shoppingCartProductListResponseParam" /> - </wsdl:message> - <wsdl:message name="shoppingCartProductMoveToCustomerQuoteRequest"> - <wsdl:part name="parameters" element="typens:shoppingCartProductMoveToCustomerQuoteRequestParam" /> - </wsdl:message> - <wsdl:message name="shoppingCartProductMoveToCustomerQuoteResponse"> - <wsdl:part name="parameters" element="typens:shoppingCartProductMoveToCustomerQuoteResponseParam" /> - </wsdl:message> - <wsdl:message name="shoppingCartCustomerSetRequest"> - <wsdl:part name="parameters" element="typens:shoppingCartCustomerSetRequestParam" /> - </wsdl:message> - <wsdl:message name="shoppingCartCustomerSetResponse"> - <wsdl:part name="parameters" element="typens:shoppingCartCustomerSetResponseParam" /> - </wsdl:message> - <wsdl:message name="shoppingCartCustomerAddressesRequest"> - <wsdl:part name="parameters" element="typens:shoppingCartCustomerAddressesRequestParam" /> - </wsdl:message> - <wsdl:message name="shoppingCartCustomerAddressesResponse"> - <wsdl:part name="parameters" element="typens:shoppingCartCustomerAddressesResponseParam" /> - </wsdl:message> - <wsdl:message name="shoppingCartShippingMethodRequest"> - <wsdl:part name="parameters" element="typens:shoppingCartShippingMethodRequestParam" /> - </wsdl:message> - <wsdl:message name="shoppingCartShippingMethodResponse"> - <wsdl:part name="parameters" element="typens:shoppingCartShippingMethodResponseParam" /> - </wsdl:message> - <wsdl:message name="shoppingCartShippingListRequest"> - <wsdl:part name="parameters" element="typens:shoppingCartShippingListRequestParam" /> - </wsdl:message> - <wsdl:message name="shoppingCartShippingListResponse"> - <wsdl:part name="parameters" element="typens:shoppingCartShippingListResponseParam" /> - </wsdl:message> - <wsdl:message name="shoppingCartPaymentMethodRequest"> - <wsdl:part name="parameters" element="typens:shoppingCartPaymentMethodRequestParam" /> - </wsdl:message> - <wsdl:message name="shoppingCartPaymentMethodResponse"> - <wsdl:part name="parameters" element="typens:shoppingCartPaymentMethodResponseParam" /> - </wsdl:message> - <wsdl:message name="shoppingCartPaymentListRequest"> - <wsdl:part name="parameters" element="typens:shoppingCartPaymentListRequestParam" /> - </wsdl:message> - <wsdl:message name="shoppingCartPaymentListResponse"> - <wsdl:part name="parameters" element="typens:shoppingCartPaymentListResponseParam" /> - </wsdl:message> - <wsdl:message name="shoppingCartCouponAddRequest"> - <wsdl:part name="parameters" element="typens:shoppingCartCouponAddRequestParam" /> - </wsdl:message> - <wsdl:message name="shoppingCartCouponAddResponse"> - <wsdl:part name="parameters" element="typens:shoppingCartCouponAddResponseParam" /> - </wsdl:message> - <wsdl:message name="shoppingCartCouponRemoveRequest"> - <wsdl:part name="parameters" element="typens:shoppingCartCouponRemoveRequestParam" /> - </wsdl:message> - <wsdl:message name="shoppingCartCouponRemoveResponse"> - <wsdl:part name="parameters" element="typens:shoppingCartCouponRemoveResponseParam" /> - </wsdl:message> - - <wsdl:portType name="{{var wsdl.handler}}PortType"> - <wsdl:operation name="shoppingCartCreate"> - <wsdl:documentation>Create shopping cart</wsdl:documentation> - <wsdl:input message="typens:shoppingCartCreateRequest"/> - <wsdl:output message="typens:shoppingCartCreateResponse"/> - </wsdl:operation> - <wsdl:operation name="shoppingCartInfo"> - <wsdl:documentation>Retrieve information about shopping cart</wsdl:documentation> - <wsdl:input message="typens:shoppingCartInfoRequest"/> - <wsdl:output message="typens:shoppingCartInfoResponse"/> - </wsdl:operation> - <wsdl:operation name="shoppingCartOrder"> - <wsdl:documentation>Create an order from shopping cart</wsdl:documentation> - <wsdl:input message="typens:shoppingCartOrderRequest"/> - <wsdl:output message="typens:shoppingCartOrderResponse"/> - </wsdl:operation> - <wsdl:operation name="shoppingCartTotals"> - <wsdl:documentation>Get total prices for shopping cart</wsdl:documentation> - <wsdl:input message="typens:shoppingCartTotalsRequest"/> - <wsdl:output message="typens:shoppingCartTotalsResponse"/> - </wsdl:operation> - <wsdl:operation name="shoppingCartLicense"> - <wsdl:documentation>Get terms and conditions</wsdl:documentation> - <wsdl:input message="typens:shoppingCartLicenseRequest"/> - <wsdl:output message="typens:shoppingCartLicenseResponse"/> - </wsdl:operation> - <wsdl:operation name="shoppingCartProductAdd"> - <wsdl:documentation>Add product(s) to shopping cart</wsdl:documentation> - <wsdl:input message="typens:shoppingCartProductAddRequest"/> - <wsdl:output message="typens:shoppingCartProductAddResponse"/> - </wsdl:operation> - <wsdl:operation name="shoppingCartProductUpdate"> - <wsdl:documentation>Update product(s) quantities in shopping cart</wsdl:documentation> - <wsdl:input message="typens:shoppingCartProductUpdateRequest"/> - <wsdl:output message="typens:shoppingCartProductUpdateResponse"/> - </wsdl:operation> - <wsdl:operation name="shoppingCartProductRemove"> - <wsdl:documentation>Remove product(s) from shopping cart</wsdl:documentation> - <wsdl:input message="typens:shoppingCartProductRemoveRequest"/> - <wsdl:output message="typens:shoppingCartProductRemoveResponse"/> - </wsdl:operation> - <wsdl:operation name="shoppingCartProductList"> - <wsdl:documentation>Get list of products in shopping cart</wsdl:documentation> - <wsdl:input message="typens:shoppingCartProductListRequest"/> - <wsdl:output message="typens:shoppingCartProductListResponse"/> - </wsdl:operation> - <wsdl:operation name="shoppingCartProductMoveToCustomerQuote"> - <wsdl:documentation>Move product(s) to customer quote</wsdl:documentation> - <wsdl:input message="typens:shoppingCartProductMoveToCustomerQuoteRequest"/> - <wsdl:output message="typens:shoppingCartProductMoveToCustomerQuoteResponse"/> - </wsdl:operation> - <wsdl:operation name="shoppingCartCustomerSet"> - <wsdl:documentation>Set customer for shopping cart</wsdl:documentation> - <wsdl:input message="typens:shoppingCartCustomerSetRequest"/> - <wsdl:output message="typens:shoppingCartCustomerSetResponse"/> - </wsdl:operation> - <wsdl:operation name="shoppingCartCustomerAddresses"> - <wsdl:documentation>Set customer's addresses in shopping cart</wsdl:documentation> - <wsdl:input message="typens:shoppingCartCustomerAddressesRequest"/> - <wsdl:output message="typens:shoppingCartCustomerAddressesResponse"/> - </wsdl:operation> - <wsdl:operation name="shoppingCartShippingMethod"> - <wsdl:documentation>Set shipping method</wsdl:documentation> - <wsdl:input message="typens:shoppingCartShippingMethodRequest"/> - <wsdl:output message="typens:shoppingCartShippingMethodResponse"/> - </wsdl:operation> - <wsdl:operation name="shoppingCartShippingList"> - <wsdl:documentation>Get list of available shipping methods</wsdl:documentation> - <wsdl:input message="typens:shoppingCartShippingListRequest"/> - <wsdl:output message="typens:shoppingCartShippingListResponse"/> - </wsdl:operation> - <wsdl:operation name="shoppingCartPaymentMethod"> - <wsdl:documentation>Set payment method</wsdl:documentation> - <wsdl:input message="typens:shoppingCartPaymentMethodRequest"/> - <wsdl:output message="typens:shoppingCartPaymentMethodResponse"/> - </wsdl:operation> - <wsdl:operation name="shoppingCartPaymentList"> - <wsdl:documentation>Get list of available payment methods</wsdl:documentation> - <wsdl:input message="typens:shoppingCartPaymentListRequest"/> - <wsdl:output message="typens:shoppingCartPaymentListResponse"/> - </wsdl:operation> - <wsdl:operation name="shoppingCartCouponAdd"> - <wsdl:documentation>Add coupon code for shopping cart</wsdl:documentation> - <wsdl:input message="typens:shoppingCartCouponAddRequest"/> - <wsdl:output message="typens:shoppingCartCouponAddResponse"/> - </wsdl:operation> - <wsdl:operation name="shoppingCartCouponRemove"> - <wsdl:documentation>Remove coupon code from shopping cart</wsdl:documentation> - <wsdl:input message="typens:shoppingCartCouponRemoveRequest"/> - <wsdl:output message="typens:shoppingCartCouponRemoveResponse"/> - </wsdl:operation> - </wsdl:portType> - <wsdl:binding name="{{var wsdl.handler}}Binding" type="typens:{{var wsdl.handler}}PortType"> - <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> - <wsdl:operation name="shoppingCartCreate"> - <soap:operation soapAction=""/> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="shoppingCartInfo"> - <soap:operation soapAction=""/> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="shoppingCartTotals"> - <soap:operation soapAction=""/> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="shoppingCartOrder"> - <soap:operation soapAction=""/> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="shoppingCartLicense"> - <soap:operation soapAction=""/> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="shoppingCartProductAdd"> - <soap:operation soapAction=""/> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="shoppingCartProductUpdate"> - <soap:operation soapAction=""/> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="shoppingCartProductRemove"> - <soap:operation soapAction=""/> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="shoppingCartProductList"> - <soap:operation soapAction=""/> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="shoppingCartProductMoveToCustomerQuote"> - <soap:operation soapAction=""/> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="shoppingCartCustomerSet"> - <soap:operation soapAction=""/> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="shoppingCartCustomerAddresses"> - <soap:operation soapAction=""/> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="shoppingCartShippingMethod"> - <soap:operation soapAction=""/> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="shoppingCartShippingList"> - <soap:operation soapAction=""/> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="shoppingCartPaymentMethod"> - <soap:operation soapAction=""/> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="shoppingCartPaymentList"> - <soap:operation soapAction=""/> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="shoppingCartCouponAdd"> - <soap:operation soapAction=""/> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="shoppingCartCouponRemove"> - <soap:operation soapAction=""/> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - </wsdl:binding> -</wsdl:definitions> diff --git a/app/code/core/Mage/Cms/etc/adminhtml/system.xml b/app/code/core/Mage/Cms/etc/adminhtml/system.xml index 788aa4573ef99ab60582f237e5c1109e6ce67a23..8a36287d24bdefde42608156dafe28d28592f5f5 100644 --- a/app/code/core/Mage/Cms/etc/adminhtml/system.xml +++ b/app/code/core/Mage/Cms/etc/adminhtml/system.xml @@ -46,6 +46,17 @@ <source_model>Mage_Backend_Model_Config_Source_Yesno</source_model> </field> </group> + <group id="browser_capabilities" translate="label" type="text" sortOrder="200" showInDefault="1" showInWebsite="1" showInStore="1"> + <label>Browser Capabilities Detection</label> + <field id="cookies" translate="label" module="Mage_Cms" type="select" sortOrder="100" showInDefault="1" showInWebsite="1" showInStore="1"> + <label>Redirect to CMS-page if Cookies are Disabled</label> + <source_model>Mage_Backend_Model_Config_Source_Yesno</source_model> + </field> + <field id="javascript" translate="label" module="Mage_Cms" type="select" sortOrder="200" showInDefault="1" showInWebsite="1" showInStore="1"> + <label>Show Notice if JavaScript is Disabled</label> + <source_model>Mage_Backend_Model_Config_Source_Yesno</source_model> + </field> + </group> </section> <section id="cms" translate="label" module="Mage_Cms" type="text" sortOrder="1001" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Content Management</label> diff --git a/app/code/core/Mage/Api/Model/Acl/Resource.php b/app/code/core/Mage/Core/Block.php similarity index 81% rename from app/code/core/Mage/Api/Model/Acl/Resource.php rename to app/code/core/Mage/Core/Block.php index f363df9cea88e8c13d111e331580fa2a8ffa8cc5..9cf6a062db5e8bd264367ce4365e190299d14498 100644 --- a/app/code/core/Mage/Api/Model/Acl/Resource.php +++ b/app/code/core/Mage/Core/Block.php @@ -19,20 +19,20 @@ * needs please refer to http://www.magentocommerce.com for more information. * * @category Mage - * @package Mage_Api + * @package Mage_Core * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ - /** - * Acl resource - * - * @category Mage - * @package Mage_Api - * @author Magento Core Team <core@magentocommerce.com> + * Magento Block interface */ -class Mage_Api_Model_Acl_Resource extends Zend_Acl_Resource +interface Mage_Core_Block { - + /** + * Produce and return block's html output + * + * @return string + */ + public function toHtml(); } diff --git a/app/code/core/Mage/Core/Block/Abstract.php b/app/code/core/Mage/Core/Block/Abstract.php index a00908ab3b14d2072729699289f561e78297457f..40754107bc3549f273a90e71f0777878dab5e93c 100644 --- a/app/code/core/Mage/Core/Block/Abstract.php +++ b/app/code/core/Mage/Core/Block/Abstract.php @@ -39,6 +39,7 @@ * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ abstract class Mage_Core_Block_Abstract extends Varien_Object + implements Mage_Core_Block { /** * @var Mage_Core_Model_Design_Package diff --git a/app/code/core/Mage/Core/Block/Template.php b/app/code/core/Mage/Core/Block/Template.php index acf5866862c92b5085c91985ffb9ccd155445894..aa2e4a3b1725c32fc988e8229aad911045c5c17a 100644 --- a/app/code/core/Mage/Core/Block/Template.php +++ b/app/code/core/Mage/Core/Block/Template.php @@ -340,7 +340,7 @@ HTML; protected function _getAllowSymlinks() { if (is_null($this->_allowSymlinks)) { - $this->_allowSymlinks = Mage::getStoreConfigFlag(self::XML_PATH_TEMPLATE_ALLOW_SYMLINK); + $this->_allowSymlinks = $this->_storeConfig->getConfigFlag(self::XML_PATH_TEMPLATE_ALLOW_SYMLINK); } return $this->_allowSymlinks; } diff --git a/app/code/core/Mage/Core/Controller/FrontInterface.php b/app/code/core/Mage/Core/Controller/FrontInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..b213d779092640116363cc8fbe5c45e9b1f6be8b --- /dev/null +++ b/app/code/core/Mage/Core/Controller/FrontInterface.php @@ -0,0 +1,42 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_Core + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +interface Mage_Core_Controller_FrontInterface +{ + /** + * Initialize front controller + * + * @return Mage_Core_Controller_FrontInterface + */ + public function init(); + + /** + * Dispatch request and send response + * + * @return Mage_Core_Controller_FrontInterface + */ + public function dispatch(); +} diff --git a/app/code/core/Mage/Core/Controller/Request/Http.php b/app/code/core/Mage/Core/Controller/Request/Http.php index e10263d71cadd928d7c72f5b6c8310ac19c39ff3..590a34a001b7b93942317ac27f2dcad5d50a17f4 100644 --- a/app/code/core/Mage/Core/Controller/Request/Http.php +++ b/app/code/core/Mage/Core/Controller/Request/Http.php @@ -530,4 +530,22 @@ class Mage_Core_Controller_Request_Http extends Zend_Controller_Request_Http } return false; } + + /** + * Retrieve a member of the $_FILES super global + * + * If no $key is passed, returns the entire $_FILES array. + * + * @param string $key + * @param mixed $default Default value to use if key not found + * @return mixed + */ + public function getFiles($key = null, $default = null) + { + if (null === $key) { + return $_FILES; + } + + return (isset($_FILES[$key])) ? $_FILES[$key] : $default; + } } diff --git a/app/code/core/Mage/Core/Controller/Varien/Front.php b/app/code/core/Mage/Core/Controller/Varien/Front.php index 99d732bf2e071b14d25c8034f87274ee443fb3ba..7c0ea7f9b93877b554e932b469954c8261ea9de3 100644 --- a/app/code/core/Mage/Core/Controller/Varien/Front.php +++ b/app/code/core/Mage/Core/Controller/Varien/Front.php @@ -25,7 +25,7 @@ */ -class Mage_Core_Controller_Varien_Front extends Varien_Object +class Mage_Core_Controller_Varien_Front extends Varien_Object implements Mage_Core_Controller_FrontInterface { protected $_defaults = array(); diff --git a/app/code/core/Mage/Core/Model/Acl/Config/ConfigInterface.php b/app/code/core/Mage/Core/Model/Acl/Config/ConfigInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..c883c278b504bf005a3c78f05df265ba85b08b6c --- /dev/null +++ b/app/code/core/Mage/Core/Model/Acl/Config/ConfigInterface.php @@ -0,0 +1,39 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_Core + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Object that implements this interface should give ACL resource list. + */ +interface Mage_Core_Model_Acl_Config_ConfigInterface +{ + /** + * Return ACL Resources loaded from anywhere + * + * @return DOMNodeList + */ + public function getAclResources(); + +} diff --git a/app/code/core/Mage/Core/Model/Acl/Loader/Resource/ResourceAbstract.php b/app/code/core/Mage/Core/Model/Acl/Loader/Resource/ResourceAbstract.php new file mode 100644 index 0000000000000000000000000000000000000000..7bb0605d16b9898f60b620a2fdcb82b97182b0bd --- /dev/null +++ b/app/code/core/Mage/Core/Model/Acl/Loader/Resource/ResourceAbstract.php @@ -0,0 +1,86 @@ +<?php +/** + * Abstraction of ACL Resource Loader + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +abstract class Mage_Core_Model_Acl_Loader_Resource_ResourceAbstract implements Magento_Acl_Loader +{ + /** + * Acl config + * + * @var Mage_Core_Model_Acl_Config_ConfigInterface + */ + protected $_config; + + /** + * Application object factory + * + * @var Magento_Acl_ResourceFactory + */ + protected $_resourceFactory; + + /** + * @param Mage_Core_Model_Acl_Config_ConfigInterface $configuration + * @param Magento_Acl_ResourceFactory $resourceFactory + */ + public function __construct(Mage_Core_Model_Acl_Config_ConfigInterface $configuration, + Magento_Acl_ResourceFactory $resourceFactory + ) { + $this->_config = $configuration; + $this->_resourceFactory = $resourceFactory; + } + + /** + * Populate ACL with resources from external storage + * + * @param Magento_Acl $acl + * @throws Mage_Core_Exception + */ + public function populateAcl(Magento_Acl $acl) + { + $this->_addResourceTree($acl, $this->_config->getAclResources(), null); + } + + /** + * Add list of nodes and their children to acl + * + * @param Magento_Acl $acl + * @param DOMNodeList $resources + * @param Magento_Acl_Resource $parent + */ + protected function _addResourceTree(Magento_Acl $acl, DOMNodeList $resources, Magento_Acl_Resource $parent = null) + { + /** @var $resourceConfig DOMElement */ + foreach ($resources as $resourceConfig) { + if (!($resourceConfig instanceof DOMElement)) { + continue; + } + /** @var $resource Magento_Acl_Resource */ + $resource = $this->_resourceFactory->createResource(array($resourceConfig->getAttribute('id'))); + $acl->addResource($resource, $parent); + if ($resourceConfig->hasChildNodes()) { + $this->_addResourceTree($acl, $resourceConfig->childNodes, $resource); + } + } + } +} diff --git a/app/code/core/Mage/Core/Model/App.php b/app/code/core/Mage/Core/Model/App.php index fe2f10aad37fcfee365fd0d5424b0db039689799..be2b550268d3fbeb26577f45c209c6145126189a 100644 --- a/app/code/core/Mage/Core/Model/App.php +++ b/app/code/core/Mage/Core/Model/App.php @@ -134,7 +134,7 @@ class Mage_Core_Model_App /** * Application front controller * - * @var Mage_Core_Controller_Varien_Front + * @var Mage_Core_Controller_FrontInterface */ protected $_frontController; @@ -260,10 +260,8 @@ class Mage_Core_Model_App /** * Constructor */ - public function __construct(Mage_Core_Controller_Varien_Front $frontController, - Magento_ObjectManager $objectManager - ) { - $this->_frontController = $frontController; + public function __construct(Magento_ObjectManager $objectManager) + { $this->_objectManager = $objectManager; } @@ -807,12 +805,45 @@ class Mage_Core_Model_App */ protected function _initFrontController() { + $this->_frontController = $this->_getFrontControllerByCurrentArea(); Magento_Profiler::start('init_front_controller'); $this->_frontController->init(); Magento_Profiler::stop('init_front_controller'); return $this; } + /** + * Instantiate proper front controller instance depending on current area + * + * @return Mage_Core_Controller_FrontInterface + */ + protected function _getFrontControllerByCurrentArea() + { + /** + * TODO: Temporary implementation for API. Must be reconsidered during implementation + * TODO: of ability to set different front controllers in different area. + * TODO: See also related changes in Mage_Core_Model_Config. + */ + // TODO: Assure that everything work fine work in areas without routers (e.g. URL generation) + /** Default front controller class */ + $frontControllerClass = 'Mage_Core_Controller_Varien_Front'; + $pathParts = explode('/', trim($this->getRequest()->getPathInfo(), '/')); + if ($pathParts) { + /** If area front name is used it is expected to be set on the first place in path info */ + $frontName = reset($pathParts); + foreach ($this->getConfig()->getAreas() as $areaCode => $areaInfo) { + if (isset($areaInfo['front_controller']) + && isset($areaInfo['frontName']) && ($frontName == $areaInfo['frontName']) + ) { + $this->getConfig()->setCurrentAreaCode($areaCode); + $frontControllerClass = $areaInfo['front_controller']; + break; + } + } + } + return $this->_objectManager->create($frontControllerClass); + } + /** * Re-declare custom error handler * @@ -1554,4 +1585,14 @@ class Mage_Core_Model_App unset($this->_websites[$website->getCode()]); } } + + /** + * Check if developer mode is enabled. + * + * @return bool + */ + public function isDeveloperMode() + { + return Mage::getIsDeveloperMode(); + } } diff --git a/app/code/core/Mage/Core/Model/Cache.php b/app/code/core/Mage/Core/Model/Cache.php index 2eab7ad05265a00ae6fa14ecca49e077726f9686..59a29f1b7ffd9ae9c0dafdc9801575322e7dbf2f 100644 --- a/app/code/core/Mage/Core/Model/Cache.php +++ b/app/code/core/Mage/Core/Model/Cache.php @@ -129,13 +129,22 @@ class Mage_Core_Model_Cache $this->_idPrefix = substr(md5($this->_config->getOptions()->getEtcDir()), 0, 3).'_'; } - $backend = $this->_getBackendOptions($options); - $frontend = $this->_getFrontendOptions($options); + $backend = $this->_getBackendOptions($options); + $frontend = $this->_getFrontendOptions($options); + // Start profiling + $profilerTags = $this->_generateProfilerTags('create', $backend['type'], $frontend['type']); + + Magento_Profiler::start('cache_frontend_create', $profilerTags); + + // create cache $this->_frontend = Zend_Cache::factory($frontend['type'], $backend['type'], $frontend, $backend['options'], true, true, true ); + // stop profiling + Magento_Profiler::stop('cache_frontend_create'); + if (isset($options['request_processors'])) { $this->_requestProcessors = $options['request_processors']; } @@ -350,6 +359,62 @@ class Mage_Core_Model_Cache return $tags; } + /** + * Generate Magento Profiler tags + * + * @param string $operation + * @param string $frontendType + * @param string $backendType + * @return array + */ + protected function _generateProfilerTags($operation, $frontendType = '', $backendType = '') + { + $profilerTags = array('group' => 'cache', + 'operation' => 'cache:' . $operation); + + if (!empty($frontendType)) { + $profilerTags['frontend_type'] = $frontendType; + } elseif ($this->_frontend) { + $profilerTags['frontend_type'] = get_class($this->_frontend); + } + + if (!empty($backendType)) { + $profilerTags['backend_type'] = $backendType; + } elseif ($this->_frontend) { + $parsedBackendType = $this->_getBackendType(); + if ($parsedBackendType) { + $profilerTags['backend_type'] = $parsedBackendType; + } + } + + return $profilerTags; + } + + /** + * Get cache backend type + * + * @return string + */ + protected function _getBackendType() + { + $backendType = ''; + + if ($this->_frontend) { + $backend = $this->_frontend->getBackend(); + $backendClass = get_class($backend); + + $possibleCacheBackends = array('Zend_Cache_Backend_', 'Varien_Cache_Backend_'); + foreach ($possibleCacheBackends as $backendClassStart) { + if (substr($backendClass, 0, strlen($backendClassStart)) == $backendClassStart) { + $backendType = substr($backendClass, strlen($backendClassStart)); + break; + } + } + } + + return $backendType; + } + /** * Get cache frontend API object * @@ -368,7 +433,11 @@ class Mage_Core_Model_Cache */ public function load($id) { - return $this->_frontend->load($this->_id($id)); + Magento_Profiler::start('cache_load', $this->_generateProfilerTags('load')); + $result = $this->_frontend->load($this->_id($id)); + Magento_Profiler::stop('cache_load'); + + return $result; } /** @@ -391,28 +460,39 @@ class Mage_Core_Model_Cache if ($this->_disallowSave) { return true; } - return $this->_frontend->save((string)$data, $this->_id($id), $this->_tags($tags), $lifeTime); + + Magento_Profiler::start('cache_save', $this->_generateProfilerTags('save')); + $result = $this->_frontend->save((string)$data, $this->_id($id), $this->_tags($tags), $lifeTime); + Magento_Profiler::stop('cache_save'); + + return $result; } /** * Remove cached data by identifier * - * @param string $id - * @return bool + * @param string $id + * @return bool */ public function remove($id) { - return $this->_frontend->remove($this->_id($id)); + Magento_Profiler::start('cache_remove', $this->_generateProfilerTags('remove')); + $result = $this->_frontend->remove($this->_id($id)); + Magento_Profiler::stop('cache_remove'); + + return $result; } /** * Clean cached data by specific tag * - * @param array $tags - * @return bool + * @param array $tags + * @return bool */ - public function clean($tags=array()) + public function clean($tags = array()) { + Magento_Profiler::start('cache_clean', $this->_generateProfilerTags('clean')); + $mode = Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG; if (!empty($tags)) { if (!is_array($tags)) { @@ -423,17 +503,23 @@ class Mage_Core_Model_Cache $res = $this->_frontend->clean($mode, array(Mage_Core_Model_App::CACHE_TAG)); $res = $res && $this->_frontend->clean($mode, array(Mage_Core_Model_Config::CACHE_TAG)); } + + Magento_Profiler::stop('cache_clean'); + return $res; } /** * Clean cached data by specific tag * - * @return bool + * @return bool */ public function flush() { + Magento_Profiler::start('cache_flush', $this->_generateProfilerTags('flush')); $res = $this->_frontend->clean(); + Magento_Profiler::stop('cache_flush'); + return $res; } diff --git a/app/code/core/Mage/Core/Model/Config.php b/app/code/core/Mage/Core/Model/Config.php index 8018c8e31f83163a7413f69145868a7af897927e..e8e3a6874ec73749fb127ef274fbf9b81472785c 100644 --- a/app/code/core/Mage/Core/Model/Config.php +++ b/app/code/core/Mage/Core/Model/Config.php @@ -1,5 +1,7 @@ <?php /** + * Core configuration class + * * Magento * * NOTICE OF LICENSE @@ -18,20 +20,9 @@ * versions in the future. If you wish to customize Magento for your * needs please refer to http://www.magentocommerce.com for more information. * - * @category Mage - * @package Mage_Core * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ - - -/** - * Core configuration class - * - * @category Mage - * @package Mage_Core - * @author Magento Core Team <core@magentocommerce.com> - */ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base { const CACHE_TAG = 'CONFIG'; @@ -1546,20 +1537,18 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base foreach ($nodeAreas->asArray() as $areaCode => $areaInfo) { if (empty($areaCode) || (!isset($areaInfo['base_controller']) || empty($areaInfo['base_controller'])) - || (!isset($areaInfo['routers']) || !is_array($areaInfo['routers'])) ) { continue; } - - foreach ($areaInfo['routers'] as $routerKey => $routerInfo) { - if (empty($routerKey) || !isset($routerInfo['class'])) { - unset($areaInfo[$routerKey]); - } - } - if (empty($areaInfo['routers'])) { - continue; - } - + /** + * TODO: Check of 'routers' nodes existance is excessive: + * TODO: 'routers' check is moved Mage_Core_Model_Config::getRouters() + */ + + /** + * TODO: Routers are not required in API. + * TODO: That is why Check for empty router class moved to Mage_Core_Model_Config::getRouters() + */ $this->_allowedAreas[$areaCode] = $areaInfo; } } @@ -1576,11 +1565,16 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base { $routers = array(); foreach ($this->getAreas() as $areaCode => $areaInfo) { - foreach ($areaInfo['routers'] as $routerKey => $routerInfo ) { - $routerInfo = array_merge($routerInfo, $areaInfo); - unset($routerInfo['routers']); - $routerInfo['area'] = $areaCode; - $routers[$routerKey] = $routerInfo; + if (isset($areaInfo['routers']) && is_array($areaInfo['routers'])) { + foreach ($areaInfo['routers'] as $routerKey => $routerInfo ) { + if (!isset($routerInfo['class']) || empty($routerInfo['class'])) { + continue; + } + $routerInfo = array_merge($routerInfo, $areaInfo); + unset($routerInfo['routers']); + $routerInfo['area'] = $areaCode; + $routers[$routerKey] = $routerInfo; + } } } return $routers; diff --git a/app/code/core/Mage/Api/Exception.php b/app/code/core/Mage/Core/Model/Config/Data/Factory.php similarity index 61% rename from app/code/core/Mage/Api/Exception.php rename to app/code/core/Mage/Core/Model/Config/Data/Factory.php index 1da500e010c5c5f5e8301a5b291653a68b923ff3..ee44791124385f619526b0d8b9c95e32dc9b4bb1 100644 --- a/app/code/core/Mage/Api/Exception.php +++ b/app/code/core/Mage/Core/Model/Config/Data/Factory.php @@ -19,35 +19,36 @@ * needs please refer to http://www.magentocommerce.com for more information. * * @category Mage - * @package Mage_Api + * @package Mage_Core * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -/** - * Api exception - * - * @category Mage - * @package Mage_Api - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api_Exception extends Mage_Core_Exception +class Mage_Core_Model_Config_Data_Factory { - protected $_customMessage = null; + /** + * Object manager + * + * @var Magento_ObjectManager + */ + protected $_objectManager; - public function __construct($faultCode, $customMessage=null) + /** + * @param Magento_ObjectManager $objectManager + */ + public function __construct(Magento_ObjectManager $objectManager) { - parent::__construct($faultCode); - $this->_customMessage = $customMessage; + $this->_objectManager = $objectManager; } /** - * Custom error message, if error is not in api. + * Create config data object * - * @return unknown + * @param array $arguments + * @return Mage_Core_Model_Config_Data */ - public function getCustomMessage() + public function create(array $arguments = array()) { - return $this->_customMessage; + return $this->_objectManager->create('Mage_Core_Model_Config_Data', $arguments); } -} // Class Mage_Api_Model_Resource_Exception End +} diff --git a/app/code/core/Mage/Core/Model/Magento/Api.php b/app/code/core/Mage/Core/Model/Magento/Api.php deleted file mode 100644 index 536286e63012d11d26f0a45de90f36b64d9b4098..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Core/Model/Magento/Api.php +++ /dev/null @@ -1,49 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Core - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Magento info API - * - * @category Mage - * @package Mage_Core - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Core_Model_Magento_Api extends Mage_Api_Model_Resource_Abstract -{ - /** - * Retrieve information about current Magento installation - * - * @return array - */ - public function info() - { - $result = array(); - $result['magento_edition'] = Mage::getEdition(); - $result['magento_version'] = Mage::getVersion(); - - return $result; - } -} diff --git a/app/code/core/Mage/Core/Model/Magento/Api/V2.php b/app/code/core/Mage/Core/Model/Magento/Api/V2.php deleted file mode 100644 index da41b5357161ca073cf3dd7f098c4dacb5af247b..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Core/Model/Magento/Api/V2.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Directory - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Magento info API V2 - * - * @category Mage - * @package Mage_Core - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Core_Model_Magento_Api_V2 extends Mage_Core_Model_Magento_Api -{ -} diff --git a/app/code/core/Mage/Core/Model/Resource.php b/app/code/core/Mage/Core/Model/Resource.php index a1d890ff3e6d5a5bddcf298c44e5165d16613b7e..d91487da8863f2d43e8d4fcd20cb0e971d8fbbda 100644 --- a/app/code/core/Mage/Core/Model/Resource.php +++ b/app/code/core/Mage/Core/Model/Resource.php @@ -1,5 +1,7 @@ <?php /** + * Resources and connections registry and factory + * * Magento * * NOTICE OF LICENSE @@ -18,17 +20,9 @@ * versions in the future. If you wish to customize Magento for your * needs please refer to http://www.magentocommerce.com for more information. * - * @category Mage - * @package Mage_Core * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ - - -/** - * Resources and connections registry and factory - * - */ class Mage_Core_Model_Resource { const AUTO_UPDATE_CACHE_KEY = 'DB_AUTOUPDATE'; @@ -159,11 +153,20 @@ class Mage_Core_Model_Resource // try to get adapter and create connection $className = $this->_getConnectionAdapterClassName($type); if ($className) { - // define profiler settings - $config['profiler'] = isset($config['profiler']) && $config['profiler'] != 'false'; - $connection = new $className($config); if ($connection instanceof Varien_Db_Adapter_Interface) { + /** @var Zend_Db_Adapter_Abstract $connection */ + + // Set additional params for Magento profiling tool + $profiler = $connection->getProfiler(); + if ($profiler instanceof Varien_Db_Profiler) { + /** @var Varien_Db_Profiler $profiler */ + $profiler->setType($type); + + $host = !empty($config['host']) ? $config['host'] : ''; + $profiler->setHost($host); + } + // run after initialization statements if (!empty($config['initStatements'])) { $connection->query($config['initStatements']); @@ -176,6 +179,7 @@ class Mage_Core_Model_Resource // try to get connection from type if (!$connection) { $typeInstance = $this->getConnectionTypeInstance($type); + /** @var Mage_Core_Model_Resource_Type_Abstract $typeInstance */ $connection = $typeInstance->getConnection($config); if (!$connection instanceof Varien_Db_Adapter_Interface) { $connection = false; @@ -217,7 +221,6 @@ class Mage_Core_Model_Resource return $this->_connectionTypes[$type]; } - /** * Get resource table name, validated by db adapter * diff --git a/app/code/core/Mage/Core/Model/Resource/Db/Profiler.php b/app/code/core/Mage/Core/Model/Resource/Db/Profiler.php new file mode 100644 index 0000000000000000000000000000000000000000..bdf3a57f7dc2e0e5444e188b7eb92ab78cb79912 --- /dev/null +++ b/app/code/core/Mage/Core/Model/Resource/Db/Profiler.php @@ -0,0 +1,146 @@ +<?php +/** + * Magento Core profiler for requests to database + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Core_Model_Resource_Db_Profiler extends Varien_Db_Profiler +{ + /** + * Default connection type for timer name creation + */ + const TIMER_PREFIX = 'DB_QUERY'; + + /** + * Default connection type for timer name creation + */ + const DEFAULT_CONNECTION_TYPE = 'database'; + + /** + * @var array Allowed query types + */ + protected $_queryTypes = array('select', 'insert', 'update', 'delete'); + + /** + * Form and return timer name + * + * @param string $operation + * @return string + */ + protected function _getTimerName($operation) + { + // default name of connection type + $timerName = Mage_Core_Model_Resource_Db_Profiler::DEFAULT_CONNECTION_TYPE; + + // connection type to database + if (!empty($this->_type)) { + $timerName = $this->_type; + } + + // sql operation + $timerName .= '_' . $operation; + + // database host + if (!empty($this->_host)) { + $timerName .= '_' . $this->_host; + } + + return Mage_Core_Model_Resource_Db_Profiler::TIMER_PREFIX . ':' . $timerName; + } + + /** + * Parse query type and return + * + * @param string $queryText + * @return string + */ + protected function _parseQueryType($queryText) + { + $queryTypeParsed = strtolower(substr(ltrim($queryText), 0, 6)); + + if (!in_array($queryTypeParsed, $this->_queryTypes)) { + $queryTypeParsed = 'query'; + } + + return $queryTypeParsed; + } + + /** + * Starts a query. Creates a new query profile object (Zend_Db_Profiler_Query) + * + * @param string $queryText SQL statement + * @param integer $queryType OPTIONAL Type of query, one of the Zend_Db_Profiler::* constants + * @return integer|null + */ + public function queryStart($queryText, $queryType = null) + { + $result = parent::queryStart($queryText, $queryType); + + if ($result !== null) { + $queryTypeParsed = $this->_parseQueryType($queryText); + $timerName = $this->_getTimerName($queryTypeParsed); + + $tags = array(); + + // connection type to database + $typePrefix = ''; + if ($this->_type) { + $tags['group'] = $this->_type; + $typePrefix = $this->_type . ':'; + } + + // sql operation + $tags['operation'] = $typePrefix . $queryTypeParsed; + + // database host + if ($this->_host) { + $tags['host'] = $this->_host; + } + + Magento_Profiler::start($timerName, $tags); + } + + return $result; + } + + /** + * Ends a query. Pass it the handle that was returned by queryStart(). + * + * @param int $queryId + * @return string|void + */ + public function queryEnd($queryId) + { + $result = parent::queryEnd($queryId); + + if ($result != self::IGNORED) { + /** @var Zend_Db_Profiler_Query $queryProfile */ + $queryProfile = $this->_queryProfiles[$queryId]; + $queryTypeParsed = $this->_parseQueryType($queryProfile->getQuery()); + $timerName = $this->_getTimerName($queryTypeParsed); + + Magento_Profiler::stop($timerName); + } + + return $result; + } +} diff --git a/app/code/core/Mage/Core/Model/Store.php b/app/code/core/Mage/Core/Model/Store.php index 7a24ef39afa1e368810e628e4b95ae93fa49e0e2..f1e6a4e5e17dd260765afb58a816ab9b8876728c 100644 --- a/app/code/core/Mage/Core/Model/Store.php +++ b/app/code/core/Mage/Core/Model/Store.php @@ -357,7 +357,7 @@ class Mage_Core_Model_Store extends Mage_Core_Model_Abstract public function initConfigCache() { /** - * Funtionality related with config separation + * Functionality related with config separation */ if ($this->_configCache === null) { $code = $this->getCode(); @@ -471,6 +471,10 @@ class Mage_Core_Model_Store extends Mage_Core_Model_Abstract if ($placeholder == 'unsecure_public_url' || $placeholder == 'secure_public_url') { $pubName = Mage_Core_Model_Config_Options::PUB_DIRECTORY; $url.= (substr(dirname($_SERVER['SCRIPT_FILENAME']), -4) == '/' . $pubName) ? '' : $pubName . '/'; + // @TODO: investigate how to build correct public URLs from API + if (Mage::registry('custom_entry_point')) { + $url .= $pubName . '/'; + } } if ($url) { diff --git a/app/code/core/Mage/Core/Model/Store/Api.php b/app/code/core/Mage/Core/Model/Store/Api.php deleted file mode 100644 index 23066597d4cc0e68b662453ce22002df32a9461b..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Core/Model/Store/Api.php +++ /dev/null @@ -1,96 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Core - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Store API - * - * @category Mage - * @package Mage_Core - * @author Magento Core Team <core@magentocommerce.com> - */ - -class Mage_Core_Model_Store_Api extends Mage_Api_Model_Resource_Abstract -{ - /** - * Retrieve stores list - * - * @return array - */ - public function items() - { - // Retrieve stores - $stores = Mage::app()->getStores(); - - // Make result array - $result = array(); - foreach ($stores as $store) { - $result[] = array( - 'store_id' => $store->getId(), - 'code' => $store->getCode(), - 'website_id' => $store->getWebsiteId(), - 'group_id' => $store->getGroupId(), - 'name' => $store->getName(), - 'sort_order' => $store->getSortOrder(), - 'is_active' => $store->getIsActive() - ); - } - - return $result; - } - - /** - * Retrieve store data - * - * @param string|int $storeId - * @return array - */ - public function info($storeId) - { - // Retrieve store info - try { - $store = Mage::app()->getStore($storeId); - } catch (Mage_Core_Model_Store_Exception $e) { - $this->_fault('store_not_exists'); - } - - if (!$store->getId()) { - $this->_fault('store_not_exists'); - } - - // Basic store data - $result = array(); - $result['store_id'] = $store->getId(); - $result['code'] = $store->getCode(); - $result['website_id'] = $store->getWebsiteId(); - $result['group_id'] = $store->getGroupId(); - $result['name'] = $store->getName(); - $result['sort_order'] = $store->getSortOrder(); - $result['is_active'] = $store->getIsActive(); - - return $result; - } - -} diff --git a/app/code/core/Mage/Core/Model/Store/Api/V2.php b/app/code/core/Mage/Core/Model/Store/Api/V2.php deleted file mode 100644 index 831eda528b2c625435b5d898123ec4893e0d04ec..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Core/Model/Store/Api/V2.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Directory - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Directory Country Api V2 - * - * @category Mage - * @package Mage_Core - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Core_Model_Store_Api_V2 extends Mage_Core_Model_Store_Api -{ -} diff --git a/app/code/core/Mage/Core/Model/Url.php b/app/code/core/Mage/Core/Model/Url.php index 70691419dd4cc2c9f4490e9a634239fa6f391513..518f7e7dc87cc3a4debe1a2059ec01f4acf10253 100644 --- a/app/code/core/Mage/Core/Model/Url.php +++ b/app/code/core/Mage/Core/Model/Url.php @@ -249,7 +249,7 @@ class Mage_Core_Model_Url extends Varien_Object public function getConfigData($key, $prefix = null) { if (is_null($prefix)) { - $prefix = 'web/' . ($this->getSecure() ? 'secure' : 'unsecure').'/'; + $prefix = 'web/' . ($this->isSecure() ? 'secure' : 'unsecure').'/'; } $path = $prefix . $key; @@ -305,7 +305,7 @@ class Mage_Core_Model_Url extends Varien_Object * * @return bool */ - public function getSecure() + public function isSecure() { if ($this->hasData('secure_is_forced')) { return (bool)$this->getData('secure'); @@ -382,7 +382,7 @@ class Mage_Core_Model_Url extends Varien_Object $this->setType(Mage_Core_Model_Store::URL_TYPE_DIRECT_LINK); } - return $this->getStore()->getBaseUrl($this->getType(), $this->getSecure()); + return $this->getStore()->getBaseUrl($this->getType(), $this->isSecure()); } /** @@ -538,11 +538,12 @@ class Mage_Core_Model_Url extends Varien_Object /** * Retrieve route name * + * @param mixed $default * @return string|null */ - public function getRouteName() + public function getRouteName($default = null) { - return $this->_getData('route_name'); + return $this->_getData('route_name') ? $this->_getData('route_name') : $default; } /** @@ -565,11 +566,12 @@ class Mage_Core_Model_Url extends Varien_Object /** * Retrieve controller name * + * @param mixed $default * @return string|null */ - public function getControllerName() + public function getControllerName($default = null) { - return $this->_getData('controller_name'); + return $this->_getData('controller_name') ? $this->_getData('controller_name') : null; } /** @@ -591,11 +593,12 @@ class Mage_Core_Model_Url extends Varien_Object /** * Retrieve action name * + * @param mixed $default * @return string|null */ - public function getActionName() + public function getActionName($default = null) { - return $this->_getData('action_name'); + return $this->_getData('action_name') ? $this->_getData('action_name') : $default; } /** @@ -1038,7 +1041,7 @@ class Mage_Core_Model_Url extends Varien_Object $sessionId = $session->getSessionIdForHost($url); if (Mage::app()->getUseSessionVar() && !$sessionId) { - $this->setQueryParam('___SID', $this->getSecure() ? 'S' : 'U'); // Secure/Unsecure + $this->setQueryParam('___SID', $this->isSecure() ? 'S' : 'U'); // Secure/Unsecure } else if ($sessionId) { $this->setQueryParam($session->getSessionIdQueryParam(), $sessionId); } diff --git a/app/code/core/Mage/Core/Model/Validator/Factory.php b/app/code/core/Mage/Core/Model/Validator/Factory.php new file mode 100644 index 0000000000000000000000000000000000000000..916db82685510a51b44a2495bc40161e4b38d81e --- /dev/null +++ b/app/code/core/Mage/Core/Model/Validator/Factory.php @@ -0,0 +1,129 @@ +<?php +/** + * Magento validator config factory + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Core_Model_Validator_Factory +{ + /** + * @var Magento_ObjectManager + */ + protected $_objectManager; + + /** + * @var Mage_Core_Model_Config + */ + protected $_config; + + /** + * @var Mage_Core_Model_Translate + */ + protected $_translator; + + /** + * Validator config files + * + * @var array + */ + protected $_configFiles = null; + + /** + * Initialize dependencies + * + * @param Magento_ObjectManager $objectManager + * @param Mage_Core_Model_Config $config + * @param Mage_Core_Model_Translate $translator + */ + public function __construct( + Magento_ObjectManager $objectManager, + Mage_Core_Model_Config $config, + Mage_Core_Model_Translate $translator + ) { + $this->_objectManager = $objectManager; + $this->_config = $config; + $this->_translator = $translator; + + $this->_configFiles = $this->_config->getModuleConfigurationFiles('validation.xml'); + $this->_initializeDefaultTranslator(); + } + + /** + * Create and set default translator to Magento_Validator_ValidatorAbstract. + */ + protected function _initializeDefaultTranslator() + { + $translateAdapter = $this->_translator; + $objectManager = $this->_objectManager; + // Pass translations to Mage_Core_Model_Translate from validators + $translatorCallback = function () use ($translateAdapter, $objectManager) { + /** @var Mage_Core_Model_Translate $translateAdapter */ + $args = func_get_args(); + $expr = $objectManager->create('Mage_Core_Model_Translate_Expr'); + $expr->setText($args[0]); + array_unshift($args, $expr); + return $translateAdapter->translate($args); + }; + /** @var Magento_Translate_Adapter $translator */ + $translator = $this->_objectManager->create('Magento_Translate_Adapter'); + $translator->setOptions(array('translator' => $translatorCallback)); + Magento_Validator_ValidatorAbstract::setDefaultTranslator($translator); + } + + /** + * Get validator config object. + * + * Will instantiate Magento_Validator_Config + * + * @return Magento_Validator_Config + */ + public function getValidatorConfig() + { + return $this->_objectManager->get('Magento_Validator_Config', array('configFiles' => $this->_configFiles)); + } + + /** + * Create validator builder instance based on entity and group. + * + * @param string $entityName + * @param string $groupName + * @param array|null $builderConfig + * @return Magento_Validator_Builder + */ + public function createValidatorBuilder($entityName, $groupName, array $builderConfig = null) + { + return $this->getValidatorConfig()->createValidatorBuilder($entityName, $groupName, $builderConfig); + } + + /** + * Create validator based on entity and group. + * + * @param string $entityName + * @param string $groupName + * @param array|null $builderConfig + * @return Magento_Validator + */ + public function createValidator($entityName, $groupName, array $builderConfig = null) + { + return $this->getValidatorConfig()->createValidator($entityName, $groupName, $builderConfig); + } +} diff --git a/app/code/core/Mage/Core/Service/ServiceAbstract.php b/app/code/core/Mage/Core/Service/ServiceAbstract.php new file mode 100644 index 0000000000000000000000000000000000000000..d82baa5160febe52a29828cd249136094c2b2480 --- /dev/null +++ b/app/code/core/Mage/Core/Service/ServiceAbstract.php @@ -0,0 +1,40 @@ +<?php +/** + * Abstract Service Layer + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +abstract class Mage_Core_Service_ServiceAbstract +{ + /** + * Sets each value from data to entity Varien_Object using setter method. + * + * @param Varien_Object $entity + * @param array $data + */ + protected function _setDataUsingMethods($entity, array $data) + { + foreach ($data as $property => $value) { + $entity->setDataUsingMethod($property, $value); + } + } +} diff --git a/app/code/core/Mage/Core/etc/api.xml b/app/code/core/Mage/Core/etc/api.xml deleted file mode 100644 index 03d5d44dd1afcfee8303aa587a1c9381fcd335e9..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Core/etc/api.xml +++ /dev/null @@ -1,103 +0,0 @@ -<?xml version="1.0"?> -<!-- -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Academic Free License (AFL 3.0) - * that is bundled with this package in the file LICENSE_AFL.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/afl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Core - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) - */ ---> -<config> - <api> - <resources> - <core_store translate="title" module="Mage_Core"> - <model>Mage_Core_Model_Store_Api</model> - <title>Store API</title> - <acl>core/store</acl> - <methods> - <list translate="title" module="Mage_Core"> - <title>Retrieve store list</title> - <method>items</method> - <acl>core/store/list</acl> - </list> - <info translate="title" module="Mage_Core"> - <title>Retrieve store data</title> - <acl>core/store/info</acl> - </info> - </methods> - <faults module="Mage_Core"> - <store_not_exists> - <code>100</code> - <message>Requested store view not found.</message> - </store_not_exists> - </faults> - </core_store> - <core_magento translate="title" module="Mage_Core"> - <model>Mage_Core_Model_Magento_Api</model> - <title>Magento info API</title> - <acl>core/magento</acl> - <methods> - <info translate="title" module="Mage_Core"> - <title>Get info about current Magento installation</title> - <acl>core/magento/info</acl> - </info> - </methods> - </core_magento> - </resources> - <resources_alias> - <store>core_store</store> - <magento>core_magento</magento> - </resources_alias> - <v2> - <resources_function_prefix> - <store>store</store> - <magento>magento</magento> - </resources_function_prefix> - </v2> - <rest> - <mapping> - </mapping> - </rest> - <acl> - <resources> - <core translate="title" module="Mage_Core"> - <title>Core</title> - <sort_order>1</sort_order> - <store translate="title" module="Mage_Core"> - <title>Store</title> - <info translate="title" module="Mage_Core"> - <title>Retrieve store data</title> - </info> - <list translate="title" module="Mage_Core"> - <title>List of stores</title> - </list> - </store> - <magento translate="title" module="Mage_Core"> - <title>Magento info</title> - <info translate="title" module="Mage_Core"> - <title>Retrieve info about current Magento installation</title> - </info> - </magento> - </core> - </resources> - </acl> - </api> -</config> diff --git a/app/code/core/Mage/Core/etc/wsdl.xml b/app/code/core/Mage/Core/etc/wsdl.xml deleted file mode 100644 index 8f3116b73f284e56afc606dc28181b2e8f867243..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Core/etc/wsdl.xml +++ /dev/null @@ -1,105 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<definitions xmlns:typens="urn:{{var wsdl.name}}" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" - xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns="http://schemas.xmlsoap.org/wsdl/" - name="{{var wsdl.name}}" targetNamespace="urn:{{var wsdl.name}}"> - <types> - <schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:Magento"> - <import namespace="http://schemas.xmlsoap.org/soap/encoding/" schemaLocation="http://schemas.xmlsoap.org/soap/encoding/" /> - <complexType name="storeEntity"> - <all> - <element name="store_id" type="xsd:int" /> - <element name="code" type="xsd:string" /> - <element name="website_id" type="xsd:int" /> - <element name="group_id" type="xsd:int" /> - <element name="name" type="xsd:string" /> - <element name="sort_order" type="xsd:int" /> - <element name="is_active" type="xsd:int" /> - </all> - </complexType> - <complexType name="storeEntityArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:storeEntity[]" /> - </restriction> - </complexContent> - </complexType> - <complexType name="magentoInfoEntity"> - <all> - <element name="magento_version" type="xsd:string" /> - <element name="magento_edition" type="xsd:string" /> - </all> - </complexType> - </schema> - </types> - <message name="storeListRequest"> - <part name="sessionId" type="xsd:string" /> - </message> - <message name="storeListResponse"> - <part name="stores" type="typens:storeEntityArray" /> - </message> - <message name="magentoInfoRequest"> - <part name="sessionId" type="xsd:string" /> - </message> - <message name="magentoInfoResponse"> - <part name="info" type="typens:magentoInfoEntity" /> - </message> - <message name="storeInfoRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="storeId" type="xsd:string" /> - </message> - <message name="storeInfoResponse"> - <part name="info" type="typens:storeEntity" /> - </message> - <portType name="{{var wsdl.handler}}PortType"> - <operation name="storeList"> - <documentation>List of stores</documentation> - <input message="typens:storeListRequest" /> - <output message="typens:storeListResponse" /> - </operation> - <operation name="storeInfo"> - <documentation>Store view info</documentation> - <input message="typens:storeInfoRequest" /> - <output message="typens:storeInfoResponse" /> - </operation> - <operation name="magentoInfo"> - <documentation>Info about current Magento installation</documentation> - <input message="typens:magentoInfoRequest" /> - <output message="typens:magentoInfoResponse" /> - </operation> - </portType> - <binding name="{{var wsdl.handler}}Binding" type="typens:{{var wsdl.handler}}PortType"> - <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" /> - <operation name="storeList"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="storeInfo"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="magentoInfo"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - </binding> - <service name="{{var wsdl.name}}Service"> - <port name="{{var wsdl.handler}}Port" binding="typens:{{var wsdl.handler}}Binding"> - <soap:address location="{{var wsdl.url}}" /> - </port> - </service> -</definitions> diff --git a/app/code/core/Mage/Core/etc/wsi.xml b/app/code/core/Mage/Core/etc/wsi.xml deleted file mode 100644 index 7e2b3b71557ff03904c7b6346420efebc878c86d..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Core/etc/wsi.xml +++ /dev/null @@ -1,148 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<wsdl:definitions xmlns:typens="urn:{{var wsdl.name}}" - xmlns:xsd="http://www.w3.org/2001/XMLSchema" - xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" - xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" - xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" - name="{{var wsdl.name}}" - targetNamespace="urn:{{var wsdl.name}}"> - <wsdl:types> - <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:{{var wsdl.name}}"> - <xsd:complexType name="storeEntity"> - <xsd:sequence> - <xsd:element name="store_id" type="xsd:int" /> - <xsd:element name="code" type="xsd:string" /> - <xsd:element name="website_id" type="xsd:int" /> - <xsd:element name="group_id" type="xsd:int" /> - <xsd:element name="name" type="xsd:string" /> - <xsd:element name="sort_order" type="xsd:int" /> - <xsd:element name="is_active" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="storeEntityArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:storeEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="magentoInfoEntity"> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="magento_version" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="magento_edition" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - <xsd:element name="storeListRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="storeListResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:storeEntityArray" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="storeInfoRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="storeId" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="storeInfoResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:storeEntity" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="magentoInfoRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="magentoInfoResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:magentoInfoEntity" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - </xsd:schema> - </wsdl:types> - <wsdl:message name="storeListRequest"> - <wsdl:part name="parameters" element="typens:storeListRequestParam" /> - </wsdl:message> - <wsdl:message name="storeListResponse"> - <wsdl:part name="parameters" element="typens:storeListResponseParam" /> - </wsdl:message> - <wsdl:message name="storeInfoRequest"> - <wsdl:part name="parameters" element="typens:storeInfoRequestParam" /> - </wsdl:message> - <wsdl:message name="storeInfoResponse"> - <wsdl:part name="parameters" element="typens:storeInfoResponseParam" /> - </wsdl:message> - <wsdl:message name="magentoInfoRequest"> - <wsdl:part name="parameters" element="typens:magentoInfoRequestParam" /> - </wsdl:message> - <wsdl:message name="magentoInfoResponse"> - <wsdl:part name="parameters" element="typens:magentoInfoResponseParam" /> - </wsdl:message> - <wsdl:portType name="{{var wsdl.handler}}PortType"> - <wsdl:operation name="storeList"> - <wsdl:documentation>List of stores</wsdl:documentation> - <wsdl:input message="typens:storeListRequest" /> - <wsdl:output message="typens:storeListResponse" /> - </wsdl:operation> - <wsdl:operation name="storeInfo"> - <wsdl:documentation>Store view info</wsdl:documentation> - <wsdl:input message="typens:storeInfoRequest" /> - <wsdl:output message="typens:storeInfoResponse" /> - </wsdl:operation> - <wsdl:operation name="magentoInfo"> - <wsdl:documentation>Info about current Magento installation</wsdl:documentation> - <wsdl:input message="typens:magentoInfoRequest" /> - <wsdl:output message="typens:magentoInfoResponse" /> - </wsdl:operation> - </wsdl:portType> - <wsdl:binding name="{{var wsdl.handler}}Binding" type="typens:{{var wsdl.handler}}PortType"> - <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" /> - <wsdl:operation name="storeList"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="storeInfo"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="magentoInfo"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - </wsdl:binding> - <wsdl:service name="{{var wsdl.name}}Service"> - <wsdl:port name="{{var wsdl.handler}}Port" binding="typens:{{var wsdl.handler}}Binding"> - <soap:address location="{{var wsdl.url}}" /> - </wsdl:port> - </wsdl:service> -</wsdl:definitions> diff --git a/app/code/core/Mage/Customer/Helper/Data.php b/app/code/core/Mage/Customer/Helper/Data.php index f0605cb8a27cb1fada4bdb37146996c0889b65d0..b6e1911d75f6736b627a66b6e8691f07bcc03fc0 100644 --- a/app/code/core/Mage/Customer/Helper/Data.php +++ b/app/code/core/Mage/Customer/Helper/Data.php @@ -618,4 +618,45 @@ class Mage_Customer_Helper_Data extends Mage_Core_Helper_Abstract { return new SoapClient(self::VAT_VALIDATION_WSDL_URL, array('trace' => $trace)); } + + /** + * Perform customer data filtration based on form code and form object + * + * @param Zend_Controller_Request_Http $request + * @param string $formCode The code of EAV form to take the list of attributes from + * @param Mage_Core_Model_Abstract $entity entity model for the form + * @param array $additionalAttributes The list of attribute codes to skip filtration for + * @param string $scope scope of the request + * @param Mage_Eav_Model_Form|null $eavForm EAV form model to use for extraction + * @return array Filtered customer data + */ + public function extractCustomerData(Zend_Controller_Request_Http $request, $formCode, $entity, + $additionalAttributes = array(), $scope = null, $eavForm = null + ) { + if (is_null($eavForm)) { + $eavForm = Mage::getModel('Mage_Customer_Model_Form'); + } + /** @var Mage_Eav_Model_Form $eavForm */ + $eavForm->setEntity($entity) + ->setFormCode($formCode) + ->ignoreInvisible(false); + $filteredData = $eavForm->extractData($request, $scope); + $requestData = $request->getPost($scope); + foreach ($additionalAttributes as $attributeCode) { + $filteredData[$attributeCode] = isset($requestData[$attributeCode]) + ? $requestData[$attributeCode] : false; + } + + $formAttributes = $eavForm->getAttributes(); + /** @var Mage_Customer_Model_Attribute $attribute */ + foreach ($formAttributes as $attribute) { + $attributeCode = $attribute->getAttributeCode(); + $frontendInput = $attribute->getFrontendInput(); + if ($frontendInput != 'boolean' && $filteredData[$attributeCode] === false) { + unset($filteredData[$attributeCode]); + } + } + + return $filteredData; + } } diff --git a/app/code/core/Mage/Customer/Model/Address.php b/app/code/core/Mage/Customer/Model/Address.php index ddc46aa0f33b471469311df6c773da60c896e97e..acf7f13727bf1393d806771382204e3f3d6ea755 100644 --- a/app/code/core/Mage/Customer/Model/Address.php +++ b/app/code/core/Mage/Customer/Model/Address.php @@ -36,6 +36,11 @@ */ class Mage_Customer_Model_Address extends Mage_Customer_Model_Address_Abstract { + /** + * Customer entity + * + * @var Mage_Customer_Model_Customer + */ protected $_customer; protected function _construct() diff --git a/app/code/core/Mage/Customer/Model/Address/Api.php b/app/code/core/Mage/Customer/Model/Address/Api.php deleted file mode 100644 index 0fa1085e02bbefafd453cb1998fd01db8d4bdf47..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Customer/Model/Address/Api.php +++ /dev/null @@ -1,237 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Customer - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Customer address api - * - * @category Mage - * @package Mage_Customer - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Customer_Model_Address_Api extends Mage_Customer_Model_Api_Resource -{ - protected $_mapAttributes = array( - 'customer_address_id' => 'entity_id' - ); - - public function __construct() - { - $this->_ignoredAttributeCodes[] = 'parent_id'; - } - - /** - * Retrive customer addresses list - * - * @param int $customerId - * @return array - */ - public function items($customerId) - { - $customer = Mage::getModel('Mage_Customer_Model_Customer') - ->load($customerId); - /* @var $customer Mage_Customer_Model_Customer */ - - if (!$customer->getId()) { - $this->_fault('customer_not_exists'); - } - - $result = array(); - foreach ($customer->getAddresses() as $address) { - $data = $address->toArray(); - $row = array(); - - foreach ($this->_mapAttributes as $attributeAlias => $attributeCode) { - $row[$attributeAlias] = isset($data[$attributeCode]) ? $data[$attributeCode] : null; - } - - foreach ($this->getAllowedAttributes($address) as $attributeCode => $attribute) { - if (isset($data[$attributeCode])) { - $row[$attributeCode] = $data[$attributeCode]; - } - } - - $row['is_default_billing'] = $customer->getDefaultBilling() == $address->getId(); - $row['is_default_shipping'] = $customer->getDefaultShipping() == $address->getId(); - - $result[] = $row; - - } - - return $result; - } - - /** - * Create new address for customer - * - * @param int $customerId - * @param array $addressData - * @return int - */ - public function create($customerId, $addressData) - { - $customer = Mage::getModel('Mage_Customer_Model_Customer') - ->load($customerId); - /* @var $customer Mage_Customer_Model_Customer */ - - if (!$customer->getId()) { - $this->_fault('customer_not_exists'); - } - - $address = Mage::getModel('Mage_Customer_Model_Address'); - - foreach ($this->getAllowedAttributes($address) as $attributeCode=>$attribute) { - if (isset($addressData[$attributeCode])) { - $address->setData($attributeCode, $addressData[$attributeCode]); - } - } - - if (isset($addressData['is_default_billing'])) { - $address->setIsDefaultBilling($addressData['is_default_billing']); - } - - if (isset($addressData['is_default_shipping'])) { - $address->setIsDefaultShipping($addressData['is_default_shipping']); - } - - $address->setCustomerId($customer->getId()); - - $valid = $address->validate(); - - if (is_array($valid)) { - $this->_fault('data_invalid', implode("\n", $valid)); - } - - try { - $address->save(); - } catch (Mage_Core_Exception $e) { - $this->_fault('data_invalid', $e->getMessage()); - } - - return $address->getId(); - } - - /** - * Retrieve address data - * - * @param int $addressId - * @return array - */ - public function info($addressId) - { - $address = Mage::getModel('Mage_Customer_Model_Address') - ->load($addressId); - - if (!$address->getId()) { - $this->_fault('not_exists'); - } - - $result = array(); - - foreach ($this->_mapAttributes as $attributeAlias => $attributeCode) { - $result[$attributeAlias] = $address->getData($attributeCode); - } - - foreach ($this->getAllowedAttributes($address) as $attributeCode => $attribute) { - $result[$attributeCode] = $address->getData($attributeCode); - } - - - if ($customer = $address->getCustomer()) { - $result['is_default_billing'] = $customer->getDefaultBilling() == $address->getId(); - $result['is_default_shipping'] = $customer->getDefaultShipping() == $address->getId(); - } - - return $result; - } - - /** - * Update address data - * - * @param int $addressId - * @param array $addressData - * @return boolean - */ - public function update($addressId, $addressData) - { - $address = Mage::getModel('Mage_Customer_Model_Address') - ->load($addressId); - - if (!$address->getId()) { - $this->_fault('not_exists'); - } - - foreach ($this->getAllowedAttributes($address) as $attributeCode=>$attribute) { - if (isset($addressData[$attributeCode])) { - $address->setData($attributeCode, $addressData[$attributeCode]); - } - } - - if (isset($addressData['is_default_billing'])) { - $address->setIsDefaultBilling($addressData['is_default_billing']); - } - - if (isset($addressData['is_default_shipping'])) { - $address->setIsDefaultShipping($addressData['is_default_shipping']); - } - - $valid = $address->validate(); - if (is_array($valid)) { - $this->_fault('data_invalid', implode("\n", $valid)); - } - - try { - $address->save(); - } catch (Mage_Core_Exception $e) { - $this->_fault('data_invalid', $e->getMessage()); - } - - return true; - } - - /** - * Delete address - * - * @param int $addressId - * @return boolean - */ - public function delete($addressId) - { - $address = Mage::getModel('Mage_Customer_Model_Address') - ->load($addressId); - - if (!$address->getId()) { - $this->_fault('not_exists'); - } - - try { - $address->delete(); - } catch (Mage_Core_Exception $e) { - $this->_fault('not_deleted', $e->getMessage()); - } - - return true; - } -} // Class Mage_Customer_Model_Address_Api End diff --git a/app/code/core/Mage/Customer/Model/Address/Api/V2.php b/app/code/core/Mage/Customer/Model/Address/Api/V2.php deleted file mode 100644 index a0330abc75adc4038a8ae5042d41c227d7039ed7..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Customer/Model/Address/Api/V2.php +++ /dev/null @@ -1,187 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Customer - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Customer address api V2 - * - * @category Mage - * @package Mage_Customer - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Customer_Model_Address_Api_V2 extends Mage_Customer_Model_Address_Api -{ - /** - * Create new address for customer - * - * @param int $customerId - * @param array $addressData - * @return int - */ - public function create($customerId, $addressData) - { - $customer = Mage::getModel('Mage_Customer_Model_Customer') - ->load($customerId); - /* @var $customer Mage_Customer_Model_Customer */ - - if (!$customer->getId()) { - $this->_fault('customer_not_exists'); - } - - $address = Mage::getModel('Mage_Customer_Model_Address'); - - foreach ($this->getAllowedAttributes($address) as $attributeCode=>$attribute) { - if (isset($addressData->$attributeCode)) { - $address->setData($attributeCode, $addressData->$attributeCode); - } - } - - if (isset($addressData->is_default_billing)) { - $address->setIsDefaultBilling($addressData->is_default_billing); - } - - if (isset($addressData->is_default_shipping)) { - $address->setIsDefaultShipping($addressData->is_default_shipping); - } - - $address->setCustomerId($customer->getId()); - - $valid = $address->validate(); - - if (is_array($valid)) { - $this->_fault('data_invalid', implode("\n", $valid)); - } - - try { - $address->save(); - } catch (Mage_Core_Exception $e) { - $this->_fault('data_invalid', $e->getMessage()); - } - - return $address->getId(); - } - - /** - * Retrieve address data - * - * @param int $addressId - * @return array - */ - public function info($addressId) - { - $address = Mage::getModel('Mage_Customer_Model_Address') - ->load($addressId); - - if (!$address->getId()) { - $this->_fault('not_exists'); - } - - $result = array(); - - foreach ($this->_mapAttributes as $attributeAlias => $attributeCode) { - $result[$attributeAlias] = $address->getData($attributeCode); - } - - foreach ($this->getAllowedAttributes($address) as $attributeCode => $attribute) { - $result[$attributeCode] = $address->getData($attributeCode); - } - - - if ($customer = $address->getCustomer()) { - $result['is_default_billing'] = $customer->getDefaultBilling() == $address->getId(); - $result['is_default_shipping'] = $customer->getDefaultShipping() == $address->getId(); - } - - return $result; - } - - /** - * Update address data - * - * @param int $addressId - * @param array $addressData - * @return boolean - */ - public function update($addressId, $addressData) - { - $address = Mage::getModel('Mage_Customer_Model_Address') - ->load($addressId); - - if (!$address->getId()) { - $this->_fault('not_exists'); - } - - foreach ($this->getAllowedAttributes($address) as $attributeCode=>$attribute) { - if (isset($addressData->$attributeCode)) { - $address->setData($attributeCode, $addressData->$attributeCode); - } - } - - if (isset($addressData->is_default_billing)) { - $address->setIsDefaultBilling($addressData->is_default_billing); - } - - if (isset($addressData->is_default_shipping)) { - $address->setIsDefaultShipping($addressData->is_default_shipping); - } - - $valid = $address->validate(); - if (is_array($valid)) { - $this->_fault('data_invalid', implode("\n", $valid)); - } - - try { - $address->save(); - } catch (Mage_Core_Exception $e) { - $this->_fault('data_invalid', $e->getMessage()); - } - - return true; - } - - /** - * Delete address - * - * @param int $addressId - * @return boolean - */ - public function delete($addressId) - { - $address = Mage::getModel('Mage_Customer_Model_Address') - ->load($addressId); - - if (!$address->getId()) { - $this->_fault('not_exists'); - } - - try { - $address->delete(); - } catch (Mage_Core_Exception $e) { - $this->_fault('not_deleted', $e->getMessage()); - } - - return true; - } -} // Class Mage_Customer_Model_Address_Api End diff --git a/app/code/core/Mage/Customer/Model/Address/Factory.php b/app/code/core/Mage/Customer/Model/Address/Factory.php new file mode 100644 index 0000000000000000000000000000000000000000..d865a254f9e556391eac05411cd0639baba6d89a --- /dev/null +++ b/app/code/core/Mage/Customer/Model/Address/Factory.php @@ -0,0 +1,53 @@ +<?php +/** + * Customer address factory + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Customer_Model_Address_Factory +{ + const ADDRESS_CLASS_NAME = 'Mage_Customer_Model_Address'; + + /** + * @var Magento_ObjectManager + */ + protected $_objectManager; + + /** + * @param Magento_ObjectManager $objectManager + */ + public function __construct(Magento_ObjectManager $objectManager) + { + $this->_objectManager = $objectManager; + } + + /** + * Create customer address model instance. + * + * @param array $arguments + * @return Mage_Customer_Model_Address + */ + public function create(array $arguments = array()) + { + return $this->_objectManager->create(self::ADDRESS_CLASS_NAME, $arguments, false); + } +} diff --git a/app/code/core/Mage/Checkout/Model/Cart/Api/V2.php b/app/code/core/Mage/Customer/Model/Address/Form.php similarity index 77% rename from app/code/core/Mage/Checkout/Model/Cart/Api/V2.php rename to app/code/core/Mage/Customer/Model/Address/Form.php index 30e62e5b42b4148728ea61c5f67b2f9188e45503..92b3e84390c5f3c3c15db8200f231b36d8fc83b9 100644 --- a/app/code/core/Mage/Checkout/Model/Cart/Api/V2.php +++ b/app/code/core/Mage/Customer/Model/Address/Form.php @@ -19,19 +19,24 @@ * needs please refer to http://www.magentocommerce.com for more information. * * @category Mage - * @package Mage_Checkout + * @package Mage_Customer * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ /** - * Shopping cart model + * Customer Address Form Model * * @category Mage - * @package Mage_Checkout + * @package Mage_Customer * @author Magento Core Team <core@magentocommerce.com> */ -class Mage_Checkout_Model_Cart_Api_V2 extends Mage_Checkout_Model_Cart_Api +class Mage_Customer_Model_Address_Form extends Mage_Customer_Model_Form { - + /** + * Current EAV entity type code + * + * @var string + */ + protected $_entityTypeCode = 'customer_address'; } diff --git a/app/code/core/Mage/Customer/Model/Api/Resource.php b/app/code/core/Mage/Customer/Model/Api/Resource.php deleted file mode 100644 index 1b88bd1658d5f765d1d2029113abd015b542ef2f..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Customer/Model/Api/Resource.php +++ /dev/null @@ -1,90 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Customer - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Customer abstract API resource - * - * @category Mage - * @package Mage_Customer - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Customer_Model_Api_Resource extends Mage_Api_Model_Resource_Abstract -{ - /** - * Default ignored attribute codes - * - * @var array - */ - protected $_ignoredAttributeCodes = array('entity_id', 'attribute_set_id', 'entity_type_id'); - - /** - * Default ignored attribute types - * - * @var array - */ - protected $_ignoredAttributeTypes = array(); - - /** - * Check is attribute allowed - * - * @param Mage_Eav_Model_Entity_Attribute_Abstract $attribute - * @param array $attributes - * @return boolean - */ - protected function _isAllowedAttribute($attribute, array $filter = null) - { - if (!is_null($filter) - && !( in_array($attribute->getAttributeCode(), $filter) - || in_array($attribute->getAttributeId(), $filter))) { - return false; - } - - return !in_array($attribute->getFrontendInput(), $this->_ignoredAttributeTypes) - && !in_array($attribute->getAttributeCode(), $this->_ignoredAttributeCodes); - } - - /** - * Return list of allowed attributes - * - * @param Mage_Eav_Model_Entity_Abstract $entity - * @param array $filter - * @return array - */ - public function getAllowedAttributes($entity, array $filter = null) - { - $attributes = $entity->getResource() - ->loadAllAttributes($entity) - ->getAttributesByCode(); - $result = array(); - foreach ($attributes as $attribute) { - if ($this->_isAllowedAttribute($attribute, $filter)) { - $result[$attribute->getAttributeCode()] = $attribute; - } - } - - return $result; - } -} // Class Mage_Customer_Model_Api_Resource End diff --git a/app/code/core/Mage/Customer/Model/Api2/Customer.php b/app/code/core/Mage/Customer/Model/Api2/Customer.php deleted file mode 100644 index d8469e5cbd276007fa53829aacb78e189a1aad45..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Customer/Model/Api2/Customer.php +++ /dev/null @@ -1,45 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Customer - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 class for customer - * - * @category Mage - * @package Mage_Customer - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Customer_Model_Api2_Customer extends Mage_Api2_Model_Resource -{ - /** - * Resource specific method to retrieve attributes' codes. May be overriden in child. - * - * @return array - */ - protected function _getResourceAttributes() - { - return $this->getEavAttributes(Mage_Api2_Model_Auth_User_Admin::USER_TYPE != $this->getUserType(), true); - } -} diff --git a/app/code/core/Mage/Customer/Model/Api2/Customer/Address.php b/app/code/core/Mage/Customer/Model/Api2/Customer/Address.php deleted file mode 100644 index 7aeb237b0371c0587c67d8132ea58f94b9464052..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Customer/Model/Api2/Customer/Address.php +++ /dev/null @@ -1,139 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Customer - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 class for customer address - * - * @category Mage - * @package Mage_Customer - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Customer_Model_Api2_Customer_Address extends Mage_Api2_Model_Resource -{ - /** - * Resource specific method to retrieve attributes' codes. May be overriden in child. - * - * @return array - */ - protected function _getResourceAttributes() - { - return $this->getEavAttributes(Mage_Api2_Model_Auth_User_Admin::USER_TYPE != $this->getUserType()); - } - - /** - * Get customer address resource validator instance - * - * @return Mage_Customer_Model_Api2_Customer_Address_Validator - */ - protected function _getValidator() - { - return Mage::getModel('Mage_Customer_Model_Api2_Customer_Address_Validator', - array('options' => array('resource' => $this))); - } - - /** - * Is specified address a default billing address? - * - * @param Mage_Customer_Model_Address $address - * @return bool - */ - protected function _isDefaultBillingAddress(Mage_Customer_Model_Address $address) - { - return $address->getCustomer()->getDefaultBilling() == $address->getId(); - } - - /** - * Is specified address a default shipping address? - * - * @param Mage_Customer_Model_Address $address - * @return bool - */ - protected function _isDefaultShippingAddress(Mage_Customer_Model_Address $address) - { - return $address->getCustomer()->getDefaultShipping() == $address->getId(); - } - - /** - * Get region id by name or code - * If id is not found then return passed $region - * - * @param string $region - * @param string $countryId - * @return int|string - */ - protected function _getRegionIdByNameOrCode($region, $countryId) - { - /** @var $collection Mage_Directory_Model_Resource_Region_Collection */ - $collection = Mage::getResourceModel('Mage_Directory_Model_Resource_Region_Collection'); - - $collection->getSelect() - ->reset() // to avoid locale usage - ->from(array('main_table' => $collection->getMainTable()), 'region_id'); - - $collection->addCountryFilter($countryId) - ->addFieldToFilter(array('default_name', 'code'), array($region, $region)); - - $id = $collection->getResource()->getReadConnection()->fetchOne($collection->getSelect()); - - return $id ? (int)$id : $region; - } - - /** - * Load customer address by id - * - * @param int $id - * @return Mage_Customer_Model_Address - */ - protected function _loadCustomerAddressById($id) - { - /* @var $address Mage_Customer_Model_Address */ - $address = Mage::getModel('Mage_Customer_Model_Address')->load($id); - - if (!$address->getId()) { - $this->_critical(self::RESOURCE_NOT_FOUND); - } - $address->addData($this->_getDefaultAddressesInfo($address)); - - return $address; - } - - /** - * Load customer by id - * - * @param int $id - * @throws Mage_Api2_Exception - * @return Mage_Customer_Model_Customer - */ - protected function _loadCustomerById($id) - { - /* @var $customer Mage_Customer_Model_Customer */ - $customer = Mage::getModel('Mage_Customer_Model_Customer')->load($id); - if (!$customer->getId()) { - $this->_critical(self::RESOURCE_NOT_FOUND); - } - return $customer; - } -} diff --git a/app/code/core/Mage/Customer/Model/Api2/Customer/Address/Rest.php b/app/code/core/Mage/Customer/Model/Api2/Customer/Address/Rest.php deleted file mode 100644 index 4732871f4e47c9f34b27e5597999b268e73d46ae..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Customer/Model/Api2/Customer/Address/Rest.php +++ /dev/null @@ -1,198 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Customer - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 class for customer address rest - * - * @category Mage - * @package Mage_Customer - * @author Magento Core Team <core@magentocommerce.com> - */ -abstract class Mage_Customer_Model_Api2_Customer_Address_Rest extends Mage_Customer_Model_Api2_Customer_Address -{ - /** - * Create customer address - * - * @param array $data - * @throws Mage_Api2_Exception - * @return string - */ - protected function _create(array $data) - { - /* @var $customer Mage_Customer_Model_Customer */ - $customer = $this->_loadCustomerById($this->getRequest()->getParam('customer_id')); - $validator = $this->_getValidator(); - - $data = $validator->filter($data); - if (!$validator->isValidData($data) || !$validator->isValidDataForCreateAssociationWithCountry($data)) { - foreach ($validator->getErrors() as $error) { - $this->_error($error, Mage_Api2_Model_Server::HTTP_BAD_REQUEST); - } - $this->_critical(self::RESOURCE_DATA_PRE_VALIDATION_ERROR); - } - - if (isset($data['region']) && isset($data['country_id'])) { - $data['region'] = $this->_getRegionIdByNameOrCode($data['region'], $data['country_id']); - } - - /* @var $address Mage_Customer_Model_Address */ - $address = Mage::getModel('Mage_Customer_Model_Address'); - $address->setData($data); - $address->setCustomer($customer); - - try { - $address->save(); - } catch (Mage_Core_Exception $e) { - $this->_error($e->getMessage(), Mage_Api2_Model_Server::HTTP_INTERNAL_ERROR); - } catch (Exception $e) { - $this->_critical(self::RESOURCE_INTERNAL_ERROR); - } - return $this->_getLocation($address); - } - - /** - * Retrieve information about specified customer address - * - * @throws Mage_Api2_Exception - * @return array - */ - protected function _retrieve() - { - /* @var $address Mage_Customer_Model_Address */ - $address = $this->_loadCustomerAddressById($this->getRequest()->getParam('id')); - $addressData = $address->getData(); - $addressData['street'] = $address->getStreet(); - return $addressData; - } - - /** - * Get customer addresses list - * - * @return array - */ - protected function _retrieveCollection() - { - $data = array(); - /* @var $address Mage_Customer_Model_Address */ - foreach ($this->_getCollectionForRetrieve() as $address) { - $addressData = $address->getData(); - $addressData['street'] = $address->getStreet(); - $data[] = array_merge($addressData, $this->_getDefaultAddressesInfo($address)); - } - return $data; - } - - /** - * Retrieve collection instances - * - * @return Mage_Customer_Model_Resource_Address_Collection - */ - protected function _getCollectionForRetrieve() - { - /* @var $customer Mage_Customer_Model_Customer */ - $customer = $this->_loadCustomerById($this->getRequest()->getParam('customer_id')); - - /* @var $collection Mage_Customer_Model_Resource_Address_Collection */ - $collection = $customer->getAddressesCollection(); - - $this->_applyCollectionModifiers($collection); - return $collection; - } - - /** - * Get array with default addresses information if possible - * - * @param Mage_Customer_Model_Address $address - * @return array - */ - protected function _getDefaultAddressesInfo(Mage_Customer_Model_Address $address) - { - return array( - 'is_default_billing' => (int)$this->_isDefaultBillingAddress($address), - 'is_default_shipping' => (int)$this->_isDefaultShippingAddress($address) - ); - } - - /** - * Update specified stock item - * - * @param array $data - * @throws Mage_Api2_Exception - */ - protected function _update(array $data) - { - /* @var $address Mage_Customer_Model_Address */ - $address = $this->_loadCustomerAddressById($this->getRequest()->getParam('id')); - $validator = $this->_getValidator(); - - $data = $validator->filter($data); - if (!$validator->isValidData($data, true) - || !$validator->isValidDataForChangeAssociationWithCountry($address, $data)) { - foreach ($validator->getErrors() as $error) { - $this->_error($error, Mage_Api2_Model_Server::HTTP_BAD_REQUEST); - } - $this->_critical(self::RESOURCE_DATA_PRE_VALIDATION_ERROR); - } - if (isset($data['region'])) { - $data['region'] = $this->_getRegionIdByNameOrCode( - $data['region'], isset($data['country_id']) ? $data['country_id'] : $address->getCountryId() - ); - $data['region_id'] = null; // to avoid overwrite region during update in address model _beforeSave() - } - $address->addData($data); - - try { - $address->save(); - } catch (Mage_Core_Exception $e) { - $this->_error($e->getMessage(), Mage_Api2_Model_Server::HTTP_INTERNAL_ERROR); - } catch (Exception $e) { - $this->_critical(self::RESOURCE_INTERNAL_ERROR); - } - } - - /** - * Delete customer - */ - protected function _delete() - { - /* @var $address Mage_Customer_Model_Address */ - $address = $this->_loadCustomerAddressById($this->getRequest()->getParam('id')); - - if ($this->_isDefaultBillingAddress($address) || $this->_isDefaultShippingAddress($address)) { - $this->_critical( - 'Address is default for customer so is not allowed to be deleted', - Mage_Api2_Model_Server::HTTP_BAD_REQUEST - ); - } - try { - $address->delete(); - } catch (Mage_Core_Exception $e) { - $this->_critical($e->getMessage(), Mage_Api2_Model_Server::HTTP_INTERNAL_ERROR); - } catch (Exception $e) { - $this->_critical(self::RESOURCE_INTERNAL_ERROR); - } - } -} diff --git a/app/code/core/Mage/Customer/Model/Api2/Customer/Address/Rest/Admin/V1.php b/app/code/core/Mage/Customer/Model/Api2/Customer/Address/Rest/Admin/V1.php deleted file mode 100644 index 91fdd7450a3670a93a8e8fc22684e048ae4c31c5..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Customer/Model/Api2/Customer/Address/Rest/Admin/V1.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Customer - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 class for customer address (admin) - * - * @category Mage - * @package Mage_Customer - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Customer_Model_Api2_Customer_Address_Rest_Admin_V1 extends Mage_Customer_Model_Api2_Customer_Address_Rest -{ -} diff --git a/app/code/core/Mage/Customer/Model/Api2/Customer/Address/Rest/Customer/V1.php b/app/code/core/Mage/Customer/Model/Api2/Customer/Address/Rest/Customer/V1.php deleted file mode 100644 index f1d1288ff5fa063b48c271e882bce69a3aa256e0..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Customer/Model/Api2/Customer/Address/Rest/Customer/V1.php +++ /dev/null @@ -1,71 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Customer - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 class for customer address (customer) - * - * @category Mage - * @package Mage_Customer - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Customer_Model_Api2_Customer_Address_Rest_Customer_V1 extends Mage_Customer_Model_Api2_Customer_Address_Rest -{ - /** - * Load customer address by id - * - * @param int $id - * @throws Mage_Api2_Exception - * @return Mage_Customer_Model_Address - */ - protected function _loadCustomerAddressById($id) - { - /* @var $customerAddress Mage_Customer_Model_Address */ - $customerAddress = parent::_loadCustomerAddressById($id); - // check owner - if ($this->getApiUser()->getUserId() != $customerAddress->getCustomerId()) { - $this->_critical(self::RESOURCE_NOT_FOUND); - } - return $customerAddress; - } - - /** - * Load customer by id - * - * @param int $id - * @throws Mage_Api2_Exception - * @return Mage_Customer_Model_Customer - */ - protected function _loadCustomerById($id) - { - /* @var $customer Mage_Customer_Model_Customer */ - $customer = parent::_loadCustomerById($id); - // check customer accaunt owner - if ($this->getApiUser()->getUserId() != $customer->getId()) { - $this->_critical(self::RESOURCE_NOT_FOUND); - } - return $customer; - } -} diff --git a/app/code/core/Mage/Customer/Model/Api2/Customer/Address/Validator.php b/app/code/core/Mage/Customer/Model/Api2/Customer/Address/Validator.php deleted file mode 100644 index 97dab4cd63740afb67ac77b63cf2851578f5dbd7..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Customer/Model/Api2/Customer/Address/Validator.php +++ /dev/null @@ -1,138 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Customer - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 class for customer address rest - * - * @category Mage - * @package Mage_Customer - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Customer_Model_Api2_Customer_Address_Validator extends Mage_Api2_Model_Resource_Validator_Eav -{ - /** - * Separator for multistreet - */ - const STREET_SEPARATOR = '; '; - - /** - * Filter request data. - * - * @param array $data - * @return array Filtered data - */ - public function filter(array $data) - { - $filteredData = parent::filter($data); - - // If the array contains more than two elements, then combine the extra elements in a string - if (isset($filteredData['street']) && is_array($filteredData['street']) && count($filteredData['street']) > 2) { - $filteredData['street'][1] .= self::STREET_SEPARATOR - . implode(self::STREET_SEPARATOR, array_slice($filteredData['street'], 2)); - $filteredData['street'] = array_slice($filteredData['street'], 0, 2); - } - // pass default addresses info - if (isset($data['is_default_billing'])) { - $filteredData['is_default_billing'] = $data['is_default_billing']; - } - if (isset($data['is_default_shipping'])) { - $filteredData['is_default_shipping'] = $data['is_default_shipping']; - } - return $filteredData; - } - - /** - * Validate data for create association with the country - * - * @param array $data - * @return bool - */ - public function isValidDataForCreateAssociationWithCountry(array $data) - { - return $this->_checkRegion($data, Mage::getModel('Mage_Directory_Model_Country')->loadByCode($data['country_id'])); - } - - /** - * Validate data for change association with the country - * - * @param Mage_Customer_Model_Address $address - * @param array $data - * @return bool - */ - public function isValidDataForChangeAssociationWithCountry(Mage_Customer_Model_Address $address, array $data) - { - if (!isset($data['country_id']) && !isset($data['region'])) { - return true; - } - // If country is in data - it has been already validated. If no - load current country. - if (isset($data['country_id'])) { - $country = Mage::getModel('Mage_Directory_Model_Country')->loadByCode($data['country_id']); - } else { - $country = $address->getCountryModel(); - } - return $this->_checkRegion($data, $country); - } - - /** - * Check region - * - * @param array $data - * @param Mage_Directory_Model_Country $country - * @return bool - */ - protected function _checkRegion($data, Mage_Directory_Model_Country $country) - { - /* @var $regions Mage_Directory_Model_Resource_Region_Collection */ - $regions = $country->getRegions(); - // Is it the country with predifined regions? - if ($regions->count()) { - if (!array_key_exists('region', $data) || empty($data['region'])) { - $this->_addError('"State/Province" is required.'); - return false; - } - - if (!is_string($data['region'])) { - $this->_addError('Invalid "State/Province" type.'); - return false; - } - - $count = $regions->addFieldToFilter(array('default_name', 'code'), array($data['region'], $data['region'])) - ->clear() - ->count(); - if (!$count) { - $this->_addError('State/Province does not exist.'); - return false; - } - } else { - if (array_key_exists('region', $data) && !is_string($data['region'])) { - $this->_addError('Invalid "State/Province" type.'); - return false; - } - } - - return true; - } -} diff --git a/app/code/core/Mage/Customer/Model/Api2/Customer/Rest.php b/app/code/core/Mage/Customer/Model/Api2/Customer/Rest.php deleted file mode 100644 index b7b455f8de79d8184294c04fe84d5848723c74ef..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Customer/Model/Api2/Customer/Rest.php +++ /dev/null @@ -1,166 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Customer - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Abstract API2 class for customer - * - * @category Mage - * @package Mage_Customer - * @author Magento Core Team <core@magentocommerce.com> - */ -abstract class Mage_Customer_Model_Api2_Customer_Rest extends Mage_Customer_Model_Api2_Customer -{ - /** - * Create customer - * - * @param array $data - * @return string - */ - protected function _create(array $data) - { - /** @var $validator Mage_Api2_Model_Resource_Validator_Eav */ - $validator = Mage::getResourceModel('Mage_Api2_Model_Resource_Validator_Eav', array( - 'options' => array('resource' => $this, 'operation' => self::OPERATION_CREATE) - )); - - $data = $validator->filter($data); - if (!$validator->isValidData($data)) { - foreach ($validator->getErrors() as $error) { - $this->_error($error, Mage_Api2_Model_Server::HTTP_BAD_REQUEST); - } - $this->_critical(self::RESOURCE_DATA_PRE_VALIDATION_ERROR); - } - - /** @var $customer Mage_Customer_Model_Customer */ - $customer = Mage::getModel('Mage_Customer_Model_Customer'); - $customer->setData($data); - - try { - $customer->save(); - } catch (Mage_Core_Exception $e) { - $this->_error($e->getMessage(), Mage_Api2_Model_Server::HTTP_INTERNAL_ERROR); - } catch (Exception $e) { - $this->_critical(self::RESOURCE_INTERNAL_ERROR); - } - - return $this->_getLocation($customer); - } - - /** - * Retrieve information about customer - * - * @throws Mage_Api2_Exception - * @return array - */ - protected function _retrieve() - { - /** @var $customer Mage_Customer_Model_Customer */ - $customer = $this->_loadCustomerById($this->getRequest()->getParam('id')); - return $customer->getData(); - } - - /** - * Get customers list - * - * @return array - */ - protected function _retrieveCollection() - { - $data = $this->_getCollectionForRetrieve()->load()->toArray(); - return isset($data['items']) ? $data['items'] : $data; - } - - /** - * Update customer - * - * @param array $data - * @throws Mage_Api2_Exception - */ - protected function _update(array $data) - { - /** @var $customer Mage_Customer_Model_Customer */ - $customer = $this->_loadCustomerById($this->getRequest()->getParam('id')); - /** @var $validator Mage_Api2_Model_Resource_Validator_Eav */ - $validator = Mage::getResourceModel('Mage_Api2_Model_Resource_Validator_Eav', array( - 'options' => array('resource' => $this, 'operation' => self::OPERATION_UPDATE) - )); - - $data = $validator->filter($data); - - unset($data['website_id']); // website is not allowed to change - - if (!$validator->isValidData($data, true)) { - foreach ($validator->getErrors() as $error) { - $this->_error($error, Mage_Api2_Model_Server::HTTP_BAD_REQUEST); - } - $this->_critical(self::RESOURCE_DATA_PRE_VALIDATION_ERROR); - } - - $customer->addData($data); - - try { - $customer->save(); - } catch (Mage_Core_Exception $e) { - $this->_error($e->getMessage(), Mage_Api2_Model_Server::HTTP_INTERNAL_ERROR); - } catch (Exception $e) { - $this->_critical(self::RESOURCE_INTERNAL_ERROR); - } - } - - /** - * Load customer by id - * - * @param int $id - * @throws Mage_Api2_Exception - * @return Mage_Customer_Model_Customer - */ - protected function _loadCustomerById($id) - { - /** @var $customer Mage_Customer_Model_Customer */ - $customer = Mage::getModel('Mage_Customer_Model_Customer')->load($id); - if (!$customer->getId()) { - $this->_critical(self::RESOURCE_NOT_FOUND); - } - return $customer; - } - - /** - * Retrieve collection instances - * - * @return Mage_Customer_Model_Resource_Customer_Collection - */ - protected function _getCollectionForRetrieve() - { - /** @var $collection Mage_Customer_Model_Resource_Customer_Collection */ - $collection = Mage::getResourceModel('Mage_Customer_Model_Resource_Customer_Collection'); - $collection->addAttributeToSelect(array_keys( - $this->getAvailableAttributes($this->getUserType(), Mage_Api2_Model_Resource::OPERATION_ATTRIBUTE_READ) - )); - - $this->_applyCollectionModifiers($collection); - return $collection; - } -} diff --git a/app/code/core/Mage/Customer/Model/Api2/Customer/Rest/Admin/V1.php b/app/code/core/Mage/Customer/Model/Api2/Customer/Rest/Admin/V1.php deleted file mode 100644 index 93492fb86661c8cc40846171f559901f971f7550..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Customer/Model/Api2/Customer/Rest/Admin/V1.php +++ /dev/null @@ -1,75 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Customer - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 class for customer (admin) - * - * @category Mage - * @package Mage_Customer - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Customer_Model_Api2_Customer_Rest_Admin_V1 extends Mage_Customer_Model_Api2_Customer_Rest -{ - /** - * Retrieve information about customer - * Add last logged in datetime - * - * @throws Mage_Api2_Exception - * @return array - */ - protected function _retrieve() - { - /** @var $log Mage_Log_Model_Customer */ - $log = Mage::getModel('Mage_Log_Model_Customer'); - $log->loadByCustomer($this->getRequest()->getParam('id')); - - $data = parent::_retrieve(); - $data['is_confirmed'] = (int) !(isset($data['confirmation']) && $data['confirmation']); - - $lastLoginAt = $log->getLoginAt(); - if (null !== $lastLoginAt) { - $data['last_logged_in'] = $lastLoginAt; - } - return $data; - } - - /** - * Delete customer - */ - protected function _delete() - { - /** @var $customer Mage_Customer_Model_Customer */ - $customer = parent::_loadCustomerById($this->getRequest()->getParam('id')); - - try { - $customer->delete(); - } catch (Mage_Core_Exception $e) { - $this->_critical($e->getMessage(), Mage_Api2_Model_Server::HTTP_INTERNAL_ERROR); - } catch (Exception $e) { - $this->_critical(self::RESOURCE_INTERNAL_ERROR); - } - } -} diff --git a/app/code/core/Mage/Customer/Model/Api2/Customer/Rest/Customer/V1.php b/app/code/core/Mage/Customer/Model/Api2/Customer/Rest/Customer/V1.php deleted file mode 100644 index cd9f2f6b943bacf26830f7b8f0f13e8b6691787e..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Customer/Model/Api2/Customer/Rest/Customer/V1.php +++ /dev/null @@ -1,97 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Customer - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 class for customer (customer) - * - * @category Mage - * @package Mage_Customer - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Customer_Model_Api2_Customer_Rest_Customer_V1 extends Mage_Customer_Model_Api2_Customer_Rest -{ - /** - * Is customer has rights to retrieve/update customer item - * - * @param int $customerId - * @throws Mage_Api2_Exception - * @return bool - */ - protected function _isOwner($customerId) - { - if ($this->getApiUser()->getUserId() !== $customerId) { - $this->_critical(self::RESOURCE_NOT_FOUND); - } - return true; - } - - /** - * Retrieve information about customer - * - * @throws Mage_Api2_Exception - * @return array - */ - protected function _retrieve() - { - if ($this->_isOwner($this->getRequest()->getParam('id'))) { - return parent::_retrieve(); - } - } - - /** - * Retrieve collection with only current customer instance - * - * @return Mage_Customer_Model_Resource_Customer_Collection - */ - protected function _getCollectionForRetrieve() - { - return parent::_getCollectionForRetrieve()->addAttributeToFilter('entity_id', $this->getApiUser()->getUserId()); - } - - /** - * Update customer - * - * @param array $data - * @throws Mage_Api2_Exception - */ - protected function _update(array $data) - { - if ($this->_isOwner($this->getRequest()->getParam('id'))) { - parent::_update($data); - } - } - - /** - * Update customers - * - * @param array $data - * @throws Mage_Api2_Exception - */ - protected function _multiUpdate(array $data) - { - $this->_critical(self::RESOURCE_METHOD_NOT_ALLOWED, Mage_Api2_Model_Server::HTTP_FORBIDDEN); - } -} diff --git a/app/code/core/Mage/Customer/Model/Customer.php b/app/code/core/Mage/Customer/Model/Customer.php index a5f0195f90d46d275e45cd168605b86aa0b4a3fb..783ff8d9dee2d1278ea1061eca9a75ad7a31d608 100644 --- a/app/code/core/Mage/Customer/Model/Customer.php +++ b/app/code/core/Mage/Customer/Model/Customer.php @@ -34,6 +34,7 @@ * @method int getWebsiteId() getWebsiteId() * @method int getStoreId() getStoreId() * @method string getEmail() getEmail() + * @method Mage_Customer_Model_Resource_Customer _getResource() */ class Mage_Customer_Model_Customer extends Mage_Core_Model_Abstract { @@ -608,7 +609,7 @@ class Mage_Customer_Model_Customer extends Mage_Core_Model_Abstract public function sendPasswordReminderEmail() { $storeId = $this->getStoreId(); - if (!$storeId) { + if (is_null($storeId)) { $storeId = $this->_getWebsiteStoreId(); } @@ -781,7 +782,7 @@ class Mage_Customer_Model_Customer extends Mage_Core_Model_Abstract * For existing customer password + confirmation will be validated only when password is set * (i.e. its change is requested) * - * @return bool + * @return bool|array */ public function validate() { @@ -884,45 +885,6 @@ class Mage_Customer_Model_Customer extends Mage_Core_Model_Abstract return $this; } - /** - * Validate address - * - * @param array $data - * @param string $type - * @return bool - */ - public function validateAddress(array $data, $type = 'billing') - { - $fields = array('city', 'country', 'postcode', 'telephone', 'street1'); - $usca = array('US', 'CA'); - $prefix = $type ? $type . '_' : ''; - - if ($data) { - foreach ($fields as $field) { - if (!isset($data[$prefix . $field])) { - return false; - } - if ($field == 'country' - && in_array(strtolower($data[$prefix . $field]), array('US', 'CA'))) { - - if (!isset($data[$prefix . 'region'])) { - return false; - } - - $region = Mage::getModel('Mage_Directory_Model_Region') - ->loadByName($data[$prefix . 'region']); - if (!$region->getId()) { - return false; - } - unset($region); - } - } - unset($data); - return true; - } - return false; - } - /** * Prepare customer for delete */ diff --git a/app/code/core/Mage/Customer/Model/Customer/Api.php b/app/code/core/Mage/Customer/Model/Customer/Api.php deleted file mode 100644 index bc77558ebb60b82edd1d8e9eb25c2e08b375a726..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Customer/Model/Customer/Api.php +++ /dev/null @@ -1,196 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Customer - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Customer api - * - * @category Mage - * @package Mage_Customer - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Customer_Model_Customer_Api extends Mage_Customer_Model_Api_Resource -{ - protected $_mapAttributes = array( - 'customer_id' => 'entity_id' - ); - /** - * Prepare data to insert/update. - * Creating array for stdClass Object - * - * @param stdClass $data - * @return array - */ - protected function _prepareData($data) - { - foreach ($this->_mapAttributes as $attributeAlias=>$attributeCode) { - if(isset($data[$attributeAlias])) - { - $data[$attributeCode] = $data[$attributeAlias]; - unset($data[$attributeAlias]); - } - } - return $data; - } - - /** - * Create new customer - * - * @param array $customerData - * @return int - */ - public function create($customerData) - { - $customerData = $this->_prepareData($customerData); - try { - $customer = Mage::getModel('Mage_Customer_Model_Customer') - ->setData($customerData) - ->save(); - } catch (Mage_Core_Exception $e) { - $this->_fault('data_invalid', $e->getMessage()); - } - return $customer->getId(); - } - - /** - * Retrieve customer data - * - * @param int $customerId - * @param array $attributes - * @return array - */ - public function info($customerId, $attributes = null) - { - $customer = Mage::getModel('Mage_Customer_Model_Customer')->load($customerId); - - if (!$customer->getId()) { - $this->_fault('not_exists'); - } - - if (!is_null($attributes) && !is_array($attributes)) { - $attributes = array($attributes); - } - - $result = array(); - - foreach ($this->_mapAttributes as $attributeAlias=>$attributeCode) { - $result[$attributeAlias] = $customer->getData($attributeCode); - } - - foreach ($this->getAllowedAttributes($customer, $attributes) as $attributeCode=>$attribute) { - $result[$attributeCode] = $customer->getData($attributeCode); - } - - return $result; - } - - /** - * Retrieve customers data - * - * @param object|array $filters - * @return array - */ - public function items($filters) - { - $collection = Mage::getModel('Mage_Customer_Model_Customer')->getCollection()->addAttributeToSelect('*'); - /** @var $apiHelper Mage_Api_Helper_Data */ - $apiHelper = Mage::helper('Mage_Api_Helper_Data'); - $filters = $apiHelper->parseFilters($filters, $this->_mapAttributes); - try { - foreach ($filters as $field => $value) { - $collection->addFieldToFilter($field, $value); - } - } catch (Mage_Core_Exception $e) { - $this->_fault('filters_invalid', $e->getMessage()); - } - $result = array(); - foreach ($collection as $customer) { - $data = $customer->toArray(); - $row = array(); - foreach ($this->_mapAttributes as $attributeAlias => $attributeCode) { - $row[$attributeAlias] = (isset($data[$attributeCode]) ? $data[$attributeCode] : null); - } - foreach ($this->getAllowedAttributes($customer) as $attributeCode => $attribute) { - if (isset($data[$attributeCode])) { - $row[$attributeCode] = $data[$attributeCode]; - } - } - $result[] = $row; - } - - return $result; - } - - /** - * Update customer data - * - * @param int $customerId - * @param array $customerData - * @return boolean - */ - public function update($customerId, $customerData) - { - $customerData = $this->_prepareData($customerData); - - $customer = Mage::getModel('Mage_Customer_Model_Customer')->load($customerId); - - if (!$customer->getId()) { - $this->_fault('not_exists'); - } - - foreach ($this->getAllowedAttributes($customer) as $attributeCode=>$attribute) { - if (isset($customerData[$attributeCode])) { - $customer->setData($attributeCode, $customerData[$attributeCode]); - } - } - - $customer->save(); - return true; - } - - /** - * Delete customer - * - * @param int $customerId - * @return boolean - */ - public function delete($customerId) - { - $customer = Mage::getModel('Mage_Customer_Model_Customer')->load($customerId); - - if (!$customer->getId()) { - $this->_fault('not_exists'); - } - - try { - $customer->delete(); - } catch (Mage_Core_Exception $e) { - $this->_fault('not_deleted', $e->getMessage()); - } - - return true; - } - -} // Class Mage_Customer_Model_Customer_Api End diff --git a/app/code/core/Mage/Customer/Model/Customer/Attribute/Backend/Password.php b/app/code/core/Mage/Customer/Model/Customer/Attribute/Backend/Password.php index 4a7094e0edc8b28c00f6d569c263c696eebd376d..8ed8432d7374a5433b0cc12047dbe2037d98d6f7 100644 --- a/app/code/core/Mage/Customer/Model/Customer/Attribute/Backend/Password.php +++ b/app/code/core/Mage/Customer/Model/Customer/Attribute/Backend/Password.php @@ -33,23 +33,42 @@ */ class Mage_Customer_Model_Customer_Attribute_Backend_Password extends Mage_Eav_Model_Entity_Attribute_Backend_Abstract { + const MIN_PASSWORD_LENGTH = 6; + /** * Special processing before attribute save: * a) check some rules for password * b) transform temporary attribute 'password' into real attribute 'password_hash' + * + * @param Varien_Object $object */ public function beforeSave($object) { - $password = trim($object->getPassword()); - $len = Mage::helper('Mage_Core_Helper_String')->strlen($password); - if ($len) { - if ($len < 6) { - Mage::throwException(Mage::helper('Mage_Customer_Helper_Data')->__('The password must have at least 6 characters. Leading or trailing spaces will be ignored.')); + $password = $object->getPassword(); + /** @var Mage_Core_Helper_String $stringHelper */ + $stringHelper = Mage::helper('Mage_Core_Helper_String'); + + $length = $stringHelper->strlen($password); + if ($length > 0) { + if ($length < self::MIN_PASSWORD_LENGTH) { + Mage::throwException(Mage::helper('Mage_Customer_Helper_Data')-> + __('The password must have at least %s characters.', self::MIN_PASSWORD_LENGTH)); + } + + if ($stringHelper->substr($password, 0, 1) == ' ' || + $stringHelper->substr($password, $length - 1, 1) == ' ') { + Mage::throwException(Mage::helper('Mage_Customer_Helper_Data')-> + __('The password can not begin or end with a space.')); } + $object->setPasswordHash($object->hashPassword($password)); } } + /** + * @param Varien_Object $object + * @return bool + */ public function validate($object) { if ($password = $object->getPassword()) { diff --git a/app/code/core/Mage/Customer/Model/Customer/Attribute/Backend/Store.php b/app/code/core/Mage/Customer/Model/Customer/Attribute/Backend/Store.php index bef96d81ac8d40650537e893d1f6440b8f613e7a..d30e3f21e7c242d1e1466060b85d7411c193b892 100644 --- a/app/code/core/Mage/Customer/Model/Customer/Attribute/Backend/Store.php +++ b/app/code/core/Mage/Customer/Model/Customer/Attribute/Backend/Store.php @@ -33,6 +33,12 @@ */ class Mage_Customer_Model_Customer_Attribute_Backend_Store extends Mage_Eav_Model_Entity_Attribute_Backend_Abstract { + /** + * Before save + * + * @param Varien_Object $object + * @return Mage_Customer_Model_Customer_Attribute_Backend_Store + */ public function beforeSave($object) { if ($object->getId()) { @@ -46,6 +52,7 @@ class Mage_Customer_Model_Customer_Attribute_Backend_Store extends Mage_Eav_Mode if (!$object->hasData('created_in')) { $object->setData('created_in', Mage::app()->getStore($object->getStoreId())->getName()); } + return $this; } } diff --git a/app/code/core/Mage/Customer/Model/Customer/Attribute/Backend/Website.php b/app/code/core/Mage/Customer/Model/Customer/Attribute/Backend/Website.php index 8d414bceb54ee3b696e318a7d6d7f58a7325881f..8d3ba16694dd383ff8485eaef4abe651e0330730 100644 --- a/app/code/core/Mage/Customer/Model/Customer/Attribute/Backend/Website.php +++ b/app/code/core/Mage/Customer/Model/Customer/Attribute/Backend/Website.php @@ -33,14 +33,22 @@ */ class Mage_Customer_Model_Customer_Attribute_Backend_Website extends Mage_Eav_Model_Entity_Attribute_Backend_Abstract { + /** + * Before save + * + * @param Varien_Object $object + * @return Mage_Customer_Model_Customer_Attribute_Backend_Website + */ public function beforeSave($object) { if ($object->getId()) { return $this; } + if (!$object->hasData('website_id')) { $object->setData('website_id', Mage::app()->getStore()->getWebsiteId()); } + return $this; } } diff --git a/app/code/core/Mage/Customer/Model/Customer/Factory.php b/app/code/core/Mage/Customer/Model/Customer/Factory.php new file mode 100644 index 0000000000000000000000000000000000000000..dd558d6089daf0ca10fb937de3cbea732714e492 --- /dev/null +++ b/app/code/core/Mage/Customer/Model/Customer/Factory.php @@ -0,0 +1,53 @@ +<?php +/** + * Customer factory + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Customer_Model_Customer_Factory +{ + const CUSTOMER_CLASS_NAME = 'Mage_Customer_Model_Customer'; + + /** + * @var Magento_ObjectManager + */ + protected $_objectManager; + + /** + * @param Magento_ObjectManager $objectManager + */ + public function __construct(Magento_ObjectManager $objectManager) + { + $this->_objectManager = $objectManager; + } + + /** + * Create customer model instance. + * + * @param array $arguments + * @return Mage_Customer_Model_Customer + */ + public function create(array $arguments = array()) + { + return $this->_objectManager->create(self::CUSTOMER_CLASS_NAME, $arguments, false); + } +} diff --git a/app/code/core/Mage/Customer/Model/Group/Api/V2.php b/app/code/core/Mage/Customer/Model/Group/Api/V2.php deleted file mode 100644 index 863840b2af88d9faa75cc96d31b163e7f6e716d5..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Customer/Model/Group/Api/V2.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Customer - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Customer groups api V2 - * - * @category Mage - * @package Mage_Customer - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Customer_Model_Group_Api_V2 extends Mage_Customer_Model_Group_Api -{ -} diff --git a/app/code/core/Mage/Customer/Model/Resource/Address.php b/app/code/core/Mage/Customer/Model/Resource/Address.php index ac374c8b9edc0df123939cd4f39e2930c575ba86..bfe1d3b71b41d29d6ac2bdbe93ddb797660f5f2a 100755 --- a/app/code/core/Mage/Customer/Model/Resource/Address.php +++ b/app/code/core/Mage/Customer/Model/Resource/Address.php @@ -1,5 +1,7 @@ <?php /** + * Customer address entity resource model + * * Magento * * NOTICE OF LICENSE @@ -18,24 +20,30 @@ * versions in the future. If you wish to customize Magento for your * needs please refer to http://www.magentocommerce.com for more information. * - * @category Mage - * @package Mage_Customer * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ - - -/** - * Customer address entity resource model - * - * @category Mage - * @package Mage_Customer - * @author Magento Core Team <core@magentocommerce.com> - */ class Mage_Customer_Model_Resource_Address extends Mage_Eav_Model_Entity_Abstract { /** - * Resource initialization + * @var Mage_Core_Model_Validator_Factory + */ + protected $_validatorFactory; + + /** + * Initialize object dependencies + * + * @param Mage_Core_Model_Validator_Factory $validatorFactory + * @param array $data + */ + public function __construct(Mage_Core_Model_Validator_Factory $validatorFactory, $data = array()) + { + $this->_validatorFactory = $validatorFactory; + parent::__construct($data); + } + + /** + * Resource initialization. */ protected function _construct() { @@ -71,4 +79,34 @@ class Mage_Customer_Model_Resource_Address extends Mage_Eav_Model_Entity_Abstrac } return $this; } + + /** + * Check customer address before saving + * + * @param Varien_Object $address + * @return Mage_Customer_Model_Resource_Address + */ + protected function _beforeSave(Varien_Object $address) + { + parent::_beforeSave($address); + + $this->_validate($address); + + return $this; + } + + /** + * Validate customer address entity + * + * @param Mage_Customer_Model_Customer $address + * @throws Magento_Validator_Exception when validation failed + */ + protected function _validate($address) + { + $validator = $this->_validatorFactory->createValidator('customer_address', 'save'); + + if (!$validator->isValid($address)) { + throw new Magento_Validator_Exception($validator->getMessages()); + } + } } diff --git a/app/code/core/Mage/Customer/Model/Resource/Customer.php b/app/code/core/Mage/Customer/Model/Resource/Customer.php index d897fe54e4c94b41792d146466047187f819500e..ef2ed2f2f4277d1b695a7e053ea6b3d11fefa819 100755 --- a/app/code/core/Mage/Customer/Model/Resource/Customer.php +++ b/app/code/core/Mage/Customer/Model/Resource/Customer.php @@ -1,5 +1,7 @@ <?php /** + * Customer entity resource model + * * Magento * * NOTICE OF LICENSE @@ -18,27 +20,24 @@ * versions in the future. If you wish to customize Magento for your * needs please refer to http://www.magentocommerce.com for more information. * - * @category Mage - * @package Mage_Customer * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ - - -/** - * Customer entity resource model - * - * @category Mage - * @package Mage_Customer - * @author Magento Core Team <core@magentocommerce.com> - */ class Mage_Customer_Model_Resource_Customer extends Mage_Eav_Model_Entity_Abstract { + /** + * @var Mage_Core_Model_Validator_Factory + */ + protected $_validatorFactory; + /** * Resource initialization + * + * @param Mage_Core_Model_Validator_Factory $validatorFactory */ - public function __construct() + public function __construct(Mage_Core_Model_Validator_Factory $validatorFactory) { + $this->_validatorFactory = $validatorFactory; $this->setType('customer'); $this->setConnection('customer_read', 'customer_write'); } @@ -64,16 +63,19 @@ class Mage_Customer_Model_Resource_Customer extends Mage_Eav_Model_Entity_Abstra /** * Check customer scope, email and confirmation key before saving * - * @param Mage_Customer_Model_Customer $customer + * @param Varien_Object $customer * @throws Mage_Customer_Exception + * @throws Mage_Core_Exception * @return Mage_Customer_Model_Resource_Customer */ protected function _beforeSave(Varien_Object $customer) { + /** @var Mage_Customer_Model_Customer $customer */ parent::_beforeSave($customer); if (!$customer->getEmail()) { - throw Mage::exception('Mage_Customer', Mage::helper('Mage_Customer_Helper_Data')->__('Customer email is required')); + throw Mage::exception('Mage_Customer', + Mage::helper('Mage_Customer_Helper_Data')->__('Customer email is required')); } $adapter = $this->_getWriteAdapter(); @@ -94,7 +96,8 @@ class Mage_Customer_Model_Resource_Customer extends Mage_Eav_Model_Entity_Abstra $result = $adapter->fetchOne($select, $bind); if ($result) { throw Mage::exception( - 'Mage_Customer', Mage::helper('Mage_Customer_Helper_Data')->__('This customer email already exists'), + 'Mage_Customer', + Mage::helper('Mage_Customer_Helper_Data')->__('Customer with the same email already exists.'), Mage_Customer_Model_Customer::EXCEPTION_EMAIL_EXISTS ); } @@ -110,9 +113,26 @@ class Mage_Customer_Model_Resource_Customer extends Mage_Eav_Model_Entity_Abstra $customer->setConfirmation(null); } + $this->_validate($customer); + return $this; } + /** + * Validate customer entity + * + * @param Mage_Customer_Model_Customer $customer + * @throws Magento_Validator_Exception when validation failed + */ + protected function _validate($customer) + { + $validator = $this->_validatorFactory->createValidator('customer', 'save'); + + if (!$validator->isValid($customer)) { + throw new Magento_Validator_Exception($validator->getMessages()); + } + } + /** * Save customer addresses and set default addresses in attributes backend * @@ -135,6 +155,7 @@ class Mage_Customer_Model_Resource_Customer extends Mage_Eav_Model_Entity_Abstra { $defaultBillingId = $customer->getData('default_billing'); $defaultShippingId = $customer->getData('default_shipping'); + /** @var Mage_Customer_Model_Address $address */ foreach ($customer->getAddresses() as $address) { if ($address->getData('_deleted')) { if ($address->getId() == $defaultBillingId) { @@ -143,7 +164,10 @@ class Mage_Customer_Model_Resource_Customer extends Mage_Eav_Model_Entity_Abstra if ($address->getId() == $defaultShippingId) { $customer->setData('default_shipping', null); } + $removedAddressId = $address->getId(); $address->delete(); + // Remove deleted address from customer address collection + $customer->getAddressesCollection()->removeItemByKey($removedAddressId); } else { $address->setParentId($customer->getId()) ->setStoreId($customer->getStoreId()) @@ -208,9 +232,8 @@ class Mage_Customer_Model_Resource_Customer extends Mage_Eav_Model_Entity_Abstra if ($customer->getSharingConfig()->isWebsiteScope()) { if (!$customer->hasData('website_id')) { - Mage::throwException( - Mage::helper('Mage_Customer_Helper_Data')->__('Customer website ID must be specified when using the website scope') - ); + Mage::throwException(Mage::helper('Mage_Customer_Helper_Data') + ->__('Customer website ID must be specified when using the website scope')); } $bind['website_id'] = (int)$customer->getWebsiteId(); $select->where('website_id = :website_id'); @@ -322,7 +345,8 @@ class Mage_Customer_Model_Resource_Customer extends Mage_Eav_Model_Entity_Abstra * @param string $newResetPasswordLinkToken * @return Mage_Customer_Model_Resource_Customer */ - public function changeResetPasswordLinkToken(Mage_Customer_Model_Customer $customer, $newResetPasswordLinkToken) { + public function changeResetPasswordLinkToken(Mage_Customer_Model_Customer $customer, $newResetPasswordLinkToken) + { if (is_string($newResetPasswordLinkToken) && !empty($newResetPasswordLinkToken)) { $customer->setRpToken($newResetPasswordLinkToken); $currentDate = Varien_Date::now(); diff --git a/app/code/core/Mage/Customer/Service/Customer.php b/app/code/core/Mage/Customer/Service/Customer.php new file mode 100644 index 0000000000000000000000000000000000000000..cd15ac8bfa1961f45c41f11c615bc7471ae6dacc --- /dev/null +++ b/app/code/core/Mage/Customer/Service/Customer.php @@ -0,0 +1,398 @@ +<?php +/** + * Customer service is responsible for customer business workflow encapsulation + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Customer_Service_Customer extends Mage_Core_Service_ServiceAbstract +{ + /** + * @var callable + */ + protected $_beforeSaveCallback = null; + + /** + * @var callable + */ + protected $_afterSaveCallback = null; + + /** + * @var Mage_Customer_Helper_Data + */ + protected $_translateHelper = null; + + /** + * @var Mage_Customer_Model_Customer_Factory + */ + protected $_customerFactory = null; + + /** + * @var Mage_Customer_Model_Address_Factory + */ + protected $_addressFactory = null; + + /** + * @var bool + */ + protected $_isAdminStore = true; + + /** + * @var bool + */ + protected $_sendRemainderEmail = true; + // todo: drop the parameter as soon as front controller of webapi will be able to return routers + + /** + * Constructor + * + * @param Mage_Customer_Helper_Data $helper + * @param Mage_Customer_Model_Customer_Factory $customerFactory + * @param Mage_Customer_Model_Address_Factory $addressFactory + * @param bool $isAdminStore + */ + public function __construct( + Mage_Customer_Helper_Data $helper, + Mage_Customer_Model_Customer_Factory $customerFactory, + Mage_Customer_Model_Address_Factory $addressFactory, + $isAdminStore = true + ) { + $this->_translateHelper = $helper; + $this->_customerFactory = $customerFactory; + $this->_addressFactory = $addressFactory; + $this->_isAdminStore = $isAdminStore; + } + + /** + * Set is admin store flag. + * + * @param bool $isAdminStore + * @return Mage_Customer_Service_Customer + */ + public function setIsAdminStore($isAdminStore) + { + $this->_isAdminStore = $isAdminStore; + return $this; + } + + /** + * Set flag if send remainder email + * + * @param bool $flag + * @return Mage_Customer_Service_Customer + */ + public function setSendRemainderEmail($flag) + { + // todo: drop next string as soon as front controller of webapi will be able to return routers + $this->_sendRemainderEmail = (bool)$flag; + return $this; + } + + /** + * Set before save callback. + * + * @param callable $callback + * @return Mage_Customer_Service_Customer + */ + public function setBeforeSaveCallback($callback) + { + $this->_beforeSaveCallback = $callback; + return $this; + } + + /** + * Set after save callback. + * + * @param callable $callback + * @return Mage_Customer_Service_Customer + */ + public function setAfterSaveCallback($callback) + { + $this->_afterSaveCallback = $callback; + return $this; + } + + /** + * Create customer with optional ability of adding addresses. + * + * @param array $customerData + * @param array|null $addressesData array of addresses + * @return Mage_Customer_Model_Customer + */ + public function create(array $customerData, array $addressesData = null) + { + $customer = $this->_customerFactory->create(); + $this->_preparePasswordForSave($customer, $customerData); + $this->_save($customer, $customerData, $addressesData); + + return $customer; + } + + /** + * Update customer entity. + * + * Update customer with optional ability to update customer addresses. + * Addresses that are not in $addressesData array but present in customer addresses collection will be removed. + * New address is created in case when no entity_id is present, otherwise corresponding address will be updated + * with data provided. + * + * @param string|int $customerId + * @param array $customerData + * @param array|null $addressesData array of addresses + * @return Mage_Customer_Model_Customer + */ + public function update($customerId, array $customerData, array $addressesData = null) + { + /** @var Mage_Customer_Model_Customer $customer */ + $customer = $this->_loadCustomerById($customerId); + + $this->_save($customer, $customerData, $addressesData); + if ($customerData) { + $this->_changePassword($customer, $customerData); + } + + return $customer; + } + + /** + * Save customer entity. Perform supplementary business workflow actions + * + * @param Mage_Customer_Model_Customer $customer + * @param array $customerData + * @param array|null $addressesData + * @return Mage_Customer_Service_Customer + */ + protected function _save($customer, array $customerData, array $addressesData = null) + { + if ($customerData) { + $this->_setDataUsingMethods($customer, $customerData); + } + $this->_beforeSave($customer, $customerData, $addressesData); + $customer->save(); + $this->_afterSave($customer, $customerData, $addressesData); + + return $this; + } + + /** + * Trigger before save logic + * + * @param Mage_Customer_Model_Customer $customer + * @param array $customerData + * @param array $addressesData + */ + protected function _beforeSave($customer, array $customerData, array $addressesData = null) + { + if (!is_null($addressesData)) { + $this->_prepareCustomerAddressesForSave($customer, $addressesData); + } + if (is_callable($this->_beforeSaveCallback)) { + call_user_func_array($this->_beforeSaveCallback, array($customer, $customerData, $addressesData)); + } + } + + /** + * Trigger before save logic + * + * @param Mage_Customer_Model_Customer $customer + * @param array $customerData + * @param array $addressesData + */ + protected function _afterSave($customer, array $customerData, array $addressesData = null) + { + if (is_callable($this->_afterSaveCallback)) { + call_user_func_array($this->_afterSaveCallback, array($customer, $customerData, $addressesData)); + } + $this->_sendWelcomeEmail($customer, $customerData); + } + + /** + * Set customer password + * + * @param Mage_Customer_Model_Customer $customer + * @param array $customerData + */ + protected function _preparePasswordForSave($customer, array $customerData) + { + $password = $this->_getCustomerPassword($customer, $customerData); + if (!is_null($password)) { + // 'force_confirmed' should be set in admin area only + if ($this->_isAdminStore) { + $customer->setForceConfirmed(true); + } + $customer->setPassword($password); + } + } + + /** + * Get customer password + * + * @param Mage_Customer_Model_Customer $customer + * @param array $customerData + * @return string|null + */ + protected function _getCustomerPassword($customer, array $customerData) + { + $password = null; + + if ($this->_isAutogeneratePassword($customerData)) { + $password = $customer->generatePassword(); + } elseif (isset($customerData['password'])) { + $password = $customerData['password']; + } + + return $password; + } + + /** + * Change customer password + * + * @param Mage_Customer_Model_Customer $customer + * @param array $customerData + * @return Mage_Customer_Service_Customer + */ + protected function _changePassword($customer, array $customerData) + { + if (!empty($customerData['password']) || $this->_isAutogeneratePassword($customerData)) { + $newPassword = $this->_getCustomerPassword($customer, $customerData); + $customer->changePassword($newPassword); + if ($this->_sendRemainderEmail) { + $customer->sendPasswordReminderEmail(); + } + } + + return $this; + } + + /** + * Check if password should be generated automatically + * + * @param array $customerData + * @return bool + */ + protected function _isAutogeneratePassword(array $customerData) + { + return isset($customerData['autogenerate_password']) && $customerData['autogenerate_password']; + } + + /** + * Retrieve send email flag + * + * @param array $customerData + * @return bool + */ + protected function _isSendEmail(array $customerData) + { + return isset($customerData['sendemail']) && $customerData['sendemail']; + } + + /** + * Send welcome email to customer + * + * @param Mage_Customer_Model_Customer $customer + * @param array $customerData + * @return Mage_Customer_Service_Customer + */ + protected function _sendWelcomeEmail($customer, array $customerData) + { + if ($customer->getWebsiteId() + && ($this->_isSendEmail($customerData) || $this->_isAutogeneratePassword($customerData)) + ) { + $isNewCustomer = !(bool)$customer->getOrigData($customer->getIdFieldName()); + $storeId = $customer->getSendemailStoreId(); + + if ($isNewCustomer) { + $customer->sendNewAccountEmail('registered', '', $storeId); + } elseif (!$customer->getConfirmation()) { + // Confirm not confirmed customer + $customer->sendNewAccountEmail('confirmed', '', $storeId); + } + } + return $this; + } + + /** + * Load customer by its ID + * + * @param int|string $customerId + * @return Mage_Customer_Model_Customer + * @throws Mage_Core_Exception + */ + protected function _loadCustomerById($customerId) + { + $customer = $this->_customerFactory->create(); + $customer->load($customerId); + if (!$customer->getId()) { + throw new Mage_Core_Exception($this->_translateHelper->__("The customer with the specified ID not found.")); + } + + return $customer; + } + + /** + * Save customer addresses. + * + * @param Mage_Customer_Model_Customer $customer + * @param array $addressesData + * @throws Mage_Core_Exception + */ + protected function _prepareCustomerAddressesForSave($customer, array $addressesData) + { + $hasChanges = $customer->hasDataChanges(); + $actualAddressesIds = array(); + foreach ($addressesData as $addressData) { + $addressId = null; + if (array_key_exists('entity_id', $addressData)) { + $addressId = $addressData['entity_id']; + unset($addressData['entity_id']); + } + + if (null !== $addressId) { + $address = $customer->getAddressItemById($addressId); + if (!$address || !$address->getId()) { + throw new Mage_Core_Exception( + $this->_translateHelper->__('The address with the specified ID not found.')); + } + } else { + $address = $this->_addressFactory->create(); + $address->setCustomerId($customer->getId()); + // Add customer address into addresses collection + $customer->addAddress($address); + } + $address->addData($addressData); + $hasChanges = $hasChanges || $address->hasDataChanges(); + + // Set post_index for detect default billing and shipping addresses + $address->setPostIndex($addressId); + + $actualAddressesIds[] = $address->getId(); + } + + /** @var Mage_Customer_Model_Address $address */ + foreach ($customer->getAddressesCollection() as $address) { + if (!in_array($address->getId(), $actualAddressesIds)) { + $address->setData('_deleted', true); + $hasChanges = true; + } + } + $customer->setDataChanges($hasChanges); + } +} diff --git a/app/code/core/Mage/Customer/controllers/AccountController.php b/app/code/core/Mage/Customer/controllers/AccountController.php index 51ad5c93a053c7214dd5627c582a1ae58ca229a7..6f746aa6dfe2e10a75a0b66fbd3609410acc9ae4 100644 --- a/app/code/core/Mage/Customer/controllers/AccountController.php +++ b/app/code/core/Mage/Customer/controllers/AccountController.php @@ -259,120 +259,137 @@ class Mage_Customer_AccountController extends Mage_Core_Controller_Front_Action return; } $session->setEscapeMessages(true); // prevent XSS injection in user input - if ($this->getRequest()->isPost()) { - $errors = array(); - - if (!$customer = Mage::registry('current_customer')) { - $customer = Mage::getModel('Mage_Customer_Model_Customer')->setId(null); - } - - /* @var $customerForm Mage_Customer_Model_Form */ - $customerForm = Mage::getModel('Mage_Customer_Model_Form'); - $customerForm->setFormCode('customer_account_create') - ->setEntity($customer); - $customerData = $customerForm->extractData($this->getRequest()); + if (!$this->getRequest()->isPost()) { + $this->_redirectError(Mage::getUrl('*/*/create', array('_secure' => true))); + return; + } - if ($this->getRequest()->getParam('is_subscribed', false)) { - $customer->setIsSubscribed(1); + try { + $customer = $this->_extractCustomer(); + $address = $this->_extractAddress($customer); + $this->_validateCustomer($customer, $address); + + $customer->save()->setOrigData(); + Mage::dispatchEvent('customer_register_success', + array('account_controller' => $this, 'customer' => $customer) + ); + + if ($customer->isConfirmationRequired()) { + $customer->sendNewAccountEmail( + 'confirmation', + $session->getBeforeAuthUrl(), + Mage::app()->getStore()->getId() + ); + $session->addSuccess($this->__('Account confirmation is required. Please, check your email for the confirmation link. To resend the confirmation email please <a href="%s">click here</a>.', Mage::helper('Mage_Customer_Helper_Data')->getEmailConfirmationUrl($customer->getEmail()))); + $this->_redirectSuccess(Mage::getUrl('*/*/index', array('_secure' => true))); + } else { + $session->setCustomerAsLoggedIn($customer); + $url = $this->_welcomeCustomer($customer); + $this->_redirectSuccess($url); } - - /** - * Initialize customer group id - */ - $customer->getGroupId(); - - if ($this->getRequest()->getPost('create_address')) { - /* @var $address Mage_Customer_Model_Address */ - $address = Mage::getModel('Mage_Customer_Model_Address'); - /* @var $addressForm Mage_Customer_Model_Form */ - $addressForm = Mage::getModel('Mage_Customer_Model_Form'); - $addressForm->setFormCode('customer_register_address') - ->setEntity($address); - - $addressData = $addressForm->extractData($this->getRequest(), 'address', false); - $addressErrors = $addressForm->validateData($addressData); - if ($addressErrors === true) { - $address->setId(null) - ->setIsDefaultBilling($this->getRequest()->getParam('default_billing', false)) - ->setIsDefaultShipping($this->getRequest()->getParam('default_shipping', false)); - $addressForm->compactData($addressData); - $customer->addAddress($address); - - $addressErrors = $address->validate(); - if (is_array($addressErrors)) { - $errors = array_merge($errors, $addressErrors); - } - } else { - $errors = array_merge($errors, $addressErrors); - } + return; + } catch (Mage_Core_Exception $e) { + if ($e->getCode() === Mage_Customer_Model_Customer::EXCEPTION_EMAIL_EXISTS) { + $url = Mage::getUrl('customer/account/forgotpassword'); + $message = $this->__('There is already an account with this email address. If you are sure that it is your email address, <a href="%s">click here</a> to get your password and access your account.', $url); + $session->setEscapeMessages(false); + } else { + $message = $e->getMessage(); } - - try { - $customerErrors = $customerForm->validateData($customerData); - if ($customerErrors !== true) { - $errors = array_merge($customerErrors, $errors); - } else { - $customerForm->compactData($customerData); - $customer->setPassword($this->getRequest()->getPost('password')); - $customer->setConfirmation($this->getRequest()->getPost('confirmation')); - $customerErrors = $customer->validate(); - if (is_array($customerErrors)) { - $errors = array_merge($customerErrors, $errors); - } + $session->addError($message); + } catch (Magento_Validator_Exception $e) { + foreach ($e->getMessages() as $messages) { + foreach ($messages as $message) { + $session->addError($message); } + } + } catch (Exception $e) { + $session->addException($e, $this->__('Cannot save the customer.')); + } - $validationResult = count($errors) == 0; - - if (true === $validationResult) { - $customer->save(); + $session->setCustomerFormData($this->getRequest()->getPost()); + $this->_redirectError(Mage::getUrl('*/*/create', array('_secure' => true))); + } - Mage::dispatchEvent('customer_register_success', - array('account_controller' => $this, 'customer' => $customer) - ); - - if ($customer->isConfirmationRequired()) { - $customer->sendNewAccountEmail( - 'confirmation', - $session->getBeforeAuthUrl(), - Mage::app()->getStore()->getId() - ); - $session->addSuccess($this->__('Account confirmation is required. Please, check your email for the confirmation link. To resend the confirmation email please <a href="%s">click here</a>.', Mage::helper('Mage_Customer_Helper_Data')->getEmailConfirmationUrl($customer->getEmail()))); - $this->_redirectSuccess(Mage::getUrl('*/*/index', array('_secure'=>true))); - return; - } else { - $session->setCustomerAsLoggedIn($customer); - $url = $this->_welcomeCustomer($customer); - $this->_redirectSuccess($url); - return; - } - } else { - $session->setCustomerFormData($this->getRequest()->getPost()); - if (is_array($errors)) { - foreach ($errors as $errorMessage) { - $session->addError($errorMessage); - } - } else { - $session->addError($this->__('Invalid customer data')); - } - } - } catch (Mage_Core_Exception $e) { - $session->setCustomerFormData($this->getRequest()->getPost()); - if ($e->getCode() === Mage_Customer_Model_Customer::EXCEPTION_EMAIL_EXISTS) { - $url = Mage::getUrl('customer/account/forgotpassword'); - $message = $this->__('There is already an account with this email address. If you are sure that it is your email address, <a href="%s">click here</a> to get your password and access your account.', $url); - $session->setEscapeMessages(false); - } else { - $message = $e->getMessage(); - } - $session->addError($message); - } catch (Exception $e) { - $session->setCustomerFormData($this->getRequest()->getPost()) - ->addException($e, $this->__('Cannot save the customer.')); + /** + * Do validation of customer and its address using validate methods in models + * + * @param Mage_Customer_Model_Customer $customer + * @param Mage_Customer_Model_Address|null $address + * @throws Magento_Validator_Exception + */ + protected function _validateCustomer($customer, $address = null) + { + $errors = array(); + if ($address) { + $addressErrors = $address->validate(); + if (is_array($addressErrors)) { + $errors = array_merge($errors, $addressErrors); } } + $customerErrors = $customer->validate(); + if (is_array($customerErrors)) { + $errors = array_merge($errors, $customerErrors); + } + if (count($errors) > 0) { + throw new Magento_Validator_Exception(array($errors)); + } + } - $this->_redirectError(Mage::getUrl('*/*/create', array('_secure' => true))); + /** + * Add address to customer during create account + * + * @param Mage_Customer_Model_Customer $customer + * @return Mage_Customer_Model_Address|null + */ + protected function _extractAddress($customer) + { + if (!$this->getRequest()->getPost('create_address')) { + return null; + } + /* @var Mage_Customer_Model_Address $address */ + $address = Mage::getModel('Mage_Customer_Model_Address'); + /* @var Mage_Customer_Model_Form $addressForm */ + $addressForm = Mage::getModel('Mage_Customer_Model_Form'); + $addressForm->setFormCode('customer_register_address') + ->setEntity($address); + + $addressData = $addressForm->extractData($this->getRequest(), 'address', false); + $address->setId(null) + ->setIsDefaultBilling($this->getRequest()->getParam('default_billing', false)) + ->setIsDefaultShipping($this->getRequest()->getParam('default_shipping', false)); + $addressForm->compactData($addressData); + $customer->addAddress($address); + return $address; + } + + /** + * Extract customer entity from request + * + * @return Mage_Customer_Model_Customer + */ + protected function _extractCustomer() + { + /** @var Mage_Customer_Model_Customer $customer */ + if (!$customer = Mage::registry('current_customer')) { + $customer = Mage::getModel('Mage_Customer_Model_Customer')->setId(null); + } + /* @var Mage_Customer_Model_Form $customerForm */ + $customerForm = Mage::getModel('Mage_Customer_Model_Form'); + $customerForm->setFormCode('customer_account_create') + ->setEntity($customer); + + $customerData = $customerForm->extractData($this->getRequest()); + // Initialize customer group id + $customer->getGroupId(); + $customerForm->compactData($customerData); + $customer->setPassword($this->getRequest()->getPost('password')); + $customer->setConfirmation($this->getRequest()->getPost('confirmation')); + if ($this->getRequest()->getParam('is_subscribed', false)) { + $customer->setIsSubscribed(1); + } + return $customer; } /** @@ -732,7 +749,8 @@ class Mage_Customer_AccountController extends Mage_Core_Controller_Front_Action public function editPostAction() { if (!$this->_validateFormKey()) { - return $this->_redirect('*/*/edit'); + $this->_redirect('*/*/edit'); + return; } if ($this->getRequest()->isPost()) { @@ -746,48 +764,42 @@ class Mage_Customer_AccountController extends Mage_Core_Controller_Front_Action $customerData = $customerForm->extractData($this->getRequest()); + $customerForm->compactData($customerData); $errors = array(); - $customerErrors = $customerForm->validateData($customerData); - if ($customerErrors !== true) { - $errors = array_merge($customerErrors, $errors); - } else { - $customerForm->compactData($customerData); - $errors = array(); - - // If password change was requested then add it to common validation scheme - if ($this->getRequest()->getParam('change_password')) { - $currPass = $this->getRequest()->getPost('current_password'); - $newPass = $this->getRequest()->getPost('password'); - $confPass = $this->getRequest()->getPost('confirmation'); - - $oldPass = $this->_getSession()->getCustomer()->getPasswordHash(); - if (Mage::helper('Mage_Core_Helper_String')->strpos($oldPass, ':')) { - list($_salt, $salt) = explode(':', $oldPass); - } else { - $salt = false; - } - if ($customer->hashPassword($currPass, $salt) == $oldPass) { - if (strlen($newPass)) { - /** - * Set entered password and its confirmation - they - * will be validated later to match each other and be of right length - */ - $customer->setPassword($newPass); - $customer->setConfirmation($confPass); - } else { - $errors[] = $this->__('New password field cannot be empty.'); - } + // If password change was requested then add it to common validation scheme + if ($this->getRequest()->getParam('change_password')) { + $currPass = $this->getRequest()->getPost('current_password'); + $newPass = $this->getRequest()->getPost('password'); + $confPass = $this->getRequest()->getPost('confirmation'); + + $oldPass = $this->_getSession()->getCustomer()->getPasswordHash(); + if (Mage::helper('Mage_Core_Helper_String')->strpos($oldPass, ':')) { + list($_salt, $salt) = explode(':', $oldPass); + } else { + $salt = false; + } + + if ($customer->hashPassword($currPass, $salt) == $oldPass) { + if (strlen($newPass)) { + /** + * Set entered password and its confirmation - they + * will be validated later to match each other and be of right length + */ + $customer->setPassword($newPass); + $customer->setConfirmation($confPass); } else { - $errors[] = $this->__('Invalid current password'); + $errors[] = $this->__('New password field cannot be empty.'); } + } else { + $errors[] = $this->__('Invalid current password'); } + } - // Validate account and compose list of errors if any - $customerErrors = $customer->validate(); - if (is_array($customerErrors)) { - $errors = array_merge($errors, $customerErrors); - } + // Validate account and compose list of errors if any + $customerErrors = $customer->validate(); + if (is_array($customerErrors)) { + $errors = array_merge($errors, $customerErrors); } if (!empty($errors)) { @@ -796,7 +808,7 @@ class Mage_Customer_AccountController extends Mage_Core_Controller_Front_Action $this->_getSession()->addError($message); } $this->_redirect('*/*/edit'); - return $this; + return; } try { diff --git a/app/code/core/Mage/Customer/controllers/AddressController.php b/app/code/core/Mage/Customer/controllers/AddressController.php index ebb6072f7627199b1771793d2b47372e5dfd1c9f..3dac1679cdb05a07b6bf2610affbebfb3d688bd4 100644 --- a/app/code/core/Mage/Customer/controllers/AddressController.php +++ b/app/code/core/Mage/Customer/controllers/AddressController.php @@ -24,7 +24,6 @@ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ - /** * Customer address controller * @@ -97,68 +96,85 @@ class Mage_Customer_AddressController extends Mage_Core_Controller_Front_Action $this->renderLayout(); } + /** + * Process address form save + */ public function formPostAction() { if (!$this->_validateFormKey()) { return $this->_redirect('*/*/'); } - // Save data - if ($this->getRequest()->isPost()) { - $customer = $this->_getSession()->getCustomer(); - /* @var $address Mage_Customer_Model_Address */ - $address = Mage::getModel('Mage_Customer_Model_Address'); - $addressId = $this->getRequest()->getParam('id'); - if ($addressId) { - $existsAddress = $customer->getAddressById($addressId); - if ($existsAddress->getId() && $existsAddress->getCustomerId() == $customer->getId()) { - $address->setId($existsAddress->getId()); - } - } - $errors = array(); + if (!$this->getRequest()->isPost()) { + $this->_getSession()->setAddressFormData($this->getRequest()->getPost()); + $this->_redirectError(Mage::getUrl('*/*/edit')); + return; + } - /* @var $addressForm Mage_Customer_Model_Form */ - $addressForm = Mage::getModel('Mage_Customer_Model_Form'); - $addressForm->setFormCode('customer_address_edit') - ->setEntity($address); - $addressData = $addressForm->extractData($this->getRequest()); - $addressErrors = $addressForm->validateData($addressData); - if ($addressErrors !== true) { - $errors = $addressErrors; + try { + $address = $this->_extractAddress(); + $this->_validateAddress($address); + $address->save(); + $this->_getSession()->addSuccess($this->__('The address has been saved.')); + $this->_redirectSuccess(Mage::getUrl('*/*/index', array('_secure'=>true))); + return; + } catch (Mage_Core_Exception $e) { + $this->_getSession()->addException($e, $e->getMessage()); + } catch (Magento_Validator_Exception $e) { + foreach ($e->getMessages() as $messages) { + foreach ($messages as $message) { + $this->_getSession()->addError($message); + } } + } catch (Exception $e) { + $this->_getSession()->addException($e, $this->__('Cannot save address.')); + } - try { - $addressForm->compactData($addressData); - $address->setCustomerId($customer->getId()) - ->setIsDefaultBilling($this->getRequest()->getParam('default_billing', false)) - ->setIsDefaultShipping($this->getRequest()->getParam('default_shipping', false)); - - $addressErrors = $address->validate(); - if ($addressErrors !== true) { - $errors = array_merge($errors, $addressErrors); - } + $this->_getSession()->setAddressFormData($this->getRequest()->getPost()); + $this->_redirectError(Mage::getUrl('*/*/edit', array('id' => $address->getId()))); + } - if (count($errors) === 0) { - $address->save(); - $this->_getSession()->addSuccess($this->__('The address has been saved.')); - $this->_redirectSuccess(Mage::getUrl('*/*/index', array('_secure'=>true))); - return; - } else { - $this->_getSession()->setAddressFormData($this->getRequest()->getPost()); - foreach ($errors as $errorMessage) { - $this->_getSession()->addError($errorMessage); - } - } - } catch (Mage_Core_Exception $e) { - $this->_getSession()->setAddressFormData($this->getRequest()->getPost()) - ->addException($e, $e->getMessage()); - } catch (Exception $e) { - $this->_getSession()->setAddressFormData($this->getRequest()->getPost()) - ->addException($e, $this->__('Cannot save address.')); - } + /** + * Do address validation using validate methods in models + * + * @param Mage_Customer_Model_Address $address + * @throws Magento_Validator_Exception + */ + protected function _validateAddress($address) + { + $addressErrors = $address->validate(); + if (is_array($addressErrors) && count($addressErrors) > 0) { + throw new Magento_Validator_Exception(array($addressErrors)); } + } - return $this->_redirectError(Mage::getUrl('*/*/edit', array('id' => $address->getId()))); + /** + * Extract address from request + * + * @return Mage_Customer_Model_Address + */ + protected function _extractAddress() + { + $customer = $this->_getSession()->getCustomer(); + /* @var Mage_Customer_Model_Address $address */ + $address = Mage::getModel('Mage_Customer_Model_Address'); + $addressId = $this->getRequest()->getParam('id'); + if ($addressId) { + $existsAddress = $customer->getAddressById($addressId); + if ($existsAddress->getId() && $existsAddress->getCustomerId() == $customer->getId()) { + $address->load($existsAddress->getId()); + } + } + /* @var Mage_Customer_Model_Form $addressForm */ + $addressForm = Mage::getModel('Mage_Customer_Model_Address_Form'); + $addressForm->setFormCode('customer_address_edit') + ->setEntity($address); + $addressData = $addressForm->extractData($this->getRequest()); + $addressForm->compactData($addressData); + $address->setCustomerId($customer->getId()) + ->setIsDefaultBilling($this->getRequest()->getParam('default_billing', false)) + ->setIsDefaultShipping($this->getRequest()->getParam('default_shipping', false)); + return $address; } public function deleteAction() diff --git a/app/code/core/Mage/Customer/etc/adminhtml/system.xml b/app/code/core/Mage/Customer/etc/adminhtml/system.xml index f1cb1e4f842faa078d288f25dd31d72f5e83dea4..2f19094b5d1b690c82dfd9f52ffa5e502c4d853c 100644 --- a/app/code/core/Mage/Customer/etc/adminhtml/system.xml +++ b/app/code/core/Mage/Customer/etc/adminhtml/system.xml @@ -245,7 +245,6 @@ <section id="general"> <group id="store_information"> <field id="validate_vat_number" translate="button_label" sortOrder="28" showInDefault="1" showInWebsite="1" showInStore="0"> - <label></label> <button_label>Validate VAT Number</button_label> <frontend_model>Mage_Adminhtml_Block_Customer_System_Config_Validatevat</frontend_model> </field> diff --git a/app/code/core/Mage/Customer/etc/api.xml b/app/code/core/Mage/Customer/etc/api.xml deleted file mode 100644 index be5868506372779e3ead5fc6836b9878bab23942..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Customer/etc/api.xml +++ /dev/null @@ -1,179 +0,0 @@ -<?xml version="1.0"?> -<!-- -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Academic Free License (AFL 3.0) - * that is bundled with this package in the file LICENSE_AFL.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/afl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Customer - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) - */ ---> -<config> - <api> - <resources> - <customer translate="title" module="Mage_Customer"> - <model>Mage_Customer_Model_Customer_Api</model> - <title>Customer API</title> - <acl>customer</acl> - <methods> - <list translate="title" module="Mage_Customer"> - <title>Retrieve customers</title> - <method>items</method> - <acl>customer/info</acl> - </list> - <create translate="title" module="Mage_Customer"> - <title>Create customer</title> - <acl>customer/create</acl> - </create> - <info translate="title" module="Mage_Customer"> - <title>Retrieve customer data</title> - <acl>customer/info</acl> - </info> - <update translate="title" module="Mage_Customer"> - <title>Update customer data</title> - <acl>customer/update</acl> - </update> - <delete translate="title" module="Mage_Customer"> - <title>Delete customer</title> - <acl>customer/delete</acl> - </delete> - </methods> - <faults module="Mage_Customer"> - <data_invalid> - <code>100</code> - <message>Invalid customer data. Details in error message.</message> - </data_invalid> - <filters_invalid> - <code>101</code> - <message>Invalid filters specified. Details in error message.</message> - </filters_invalid> - <not_exists> - <code>102</code> - <message>Customer not exists.</message> - </not_exists> - <not_deleted> - <code>103</code> - <message>Customer not deleted. Details in error message.</message> - </not_deleted> - </faults> - </customer> - <customer_group> - <model>Mage_Customer_Model_Group_Api</model> - <title>Customer's Groups API</title> - <acl>customer</acl> - <methods> - <list translate="title" module="Mage_Customer"> - <title>Retrieve customer groups</title> - <method>items</method> - </list> - </methods> - </customer_group> - <customer_address> - <model>Mage_Customer_Model_Address_Api</model> - <title>Customer Address API</title> - <acl>customer/address</acl> - <methods> - <list translate="title" module="Mage_Customer"> - <title>Retrieve customer addresses</title> - <method>items</method> - <acl>customer/address/info</acl> - </list> - <create translate="title" module="Mage_Customer"> - <title>Create customer address</title> - <acl>customer/address/create</acl> - </create> - <info translate="title" module="Mage_Customer"> - <title>Retrieve address data</title> - <acl>customer/address/info</acl> - </info> - <update translate="title" module="Mage_Customer"> - <title>Update customer address data</title> - <acl>customer/address/update</acl> - </update> - <delete translate="title" module="Mage_Customer"> - <title>Delete customer address</title> - <acl>customer/address/delete</acl> - </delete> - </methods> - <faults module="Mage_Customer"> - <data_invalid> - <code>100</code> - <message>Invalid address data. Details in error message.</message> - </data_invalid> - <customer_not_exists> - <code>101</code> - <message>Customer not exists.</message> - </customer_not_exists> - <not_exists> - <code>102</code> - <message>Address not exists.</message> - </not_exists> - <not_deleted> - <code>103</code> - <message>Address not deleted. Details in error message.</message> - </not_deleted> - </faults> - </customer_address> - </resources> - <v2> - <resources_function_prefix> - <customer>customerCustomer</customer> - <customer_group>customerGroup</customer_group> - <customer_address>customerAddress</customer_address> - </resources_function_prefix> - </v2> - <acl> - <resources> - <customer translate="title" module="Mage_Customer"> - <title>Customers</title> - <sort_order>3</sort_order> - <create translate="title" module="Mage_Customer"> - <title>Create</title> - </create> - <update translate="title" module="Mage_Customer"> - <title>Update</title> - </update> - <delete translate="title" module="Mage_Customer"> - <title>Delete</title> - </delete> - <info translate="title" module="Mage_Customer"> - <title>Retrieve customer info</title> - </info> - <address translate="title" module="Mage_Customer"> - <title>Addresses</title> - <sort_order>100</sort_order> - <create translate="title" module="Mage_Customer"> - <title>Create</title> - </create> - <update translate="title" module="Mage_Customer"> - <title>Update</title> - </update> - <delete translate="title" module="Mage_Customer"> - <title>Delete</title> - </delete> - <info translate="title" module="Mage_Customer"> - <title>Retrieve address info</title> - </info> - </address> - </customer> - </resources> - </acl> - </api> -</config> diff --git a/app/code/core/Mage/Customer/etc/api2.xml b/app/code/core/Mage/Customer/etc/api2.xml deleted file mode 100644 index cc7a97da884d2563271b26424019a31a8a15c01e..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Customer/etc/api2.xml +++ /dev/null @@ -1,213 +0,0 @@ -<?xml version="1.0"?> -<!-- -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Academic Free License (AFL 3.0) - * that is bundled with this package in the file LICENSE_AFL.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/afl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Customer - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) - */ ---> -<config> - <api2> - <resource_groups> - <customer translate="title" module="Mage_Api2"> - <title>Customer</title> - <sort_order>130</sort_order> - </customer> - </resource_groups> - <resources> - <customer translate="title" module="Mage_Api2"> - <group>customer</group> - <sort_order>90</sort_order> - <model>Mage_Customer_Model_Api2_Customer</model> - <working_model>Mage_Customer_Model_Customer</working_model> - <title>Customer</title> - <privileges> - <admin> - <retrieve>1</retrieve> - <update>1</update> - <delete>1</delete> - </admin> - <customer> - <retrieve>1</retrieve> - <update>1</update> - </customer> - </privileges> - <attributes translate="entity_id last_logged_in firstname lastname email website_id created_in group_id confirmation disable_auto_group_change" module="Mage_Api2"> - <entity_id>Customer ID</entity_id> - <last_logged_in>Last Logged In</last_logged_in> - <firstname>First Name</firstname> - <lastname>Last Name</lastname> - <email>Email</email> - <website_id>Associate to Website</website_id> - <created_in>Created From</created_in> - <group_id>Group</group_id> - <confirmation>Is Confirmed</confirmation> - <disable_auto_group_change>Disable automatic group change based on VAT ID</disable_auto_group_change> - </attributes> - <exclude_attributes> - <admin> - <write> - <entity_id>1</entity_id> - <created_at>1</created_at> - <created_in>1</created_in> - <last_logged_in>1</last_logged_in> - </write> - </admin> - <customer> - <read> - <entity_id>1</entity_id> - <last_logged_in>1</last_logged_in> - <website_id>1</website_id> - <created_in>1</created_in> - <group_id>1</group_id> - <disable_auto_group_change>1</disable_auto_group_change> - <confirmation>1</confirmation> - <created_at>1</created_at> - </read> - <write> - <entity_id>1</entity_id> - <last_logged_in>1</last_logged_in> - <website_id>1</website_id> - <created_in>1</created_in> - <group_id>1</group_id> - <disable_auto_group_change>1</disable_auto_group_change> - <confirmation>1</confirmation> - <created_at>1</created_at> - </write> - </customer> - </exclude_attributes> - <validators> - <eav> - <admin> - <entity_model>Mage_Customer_Model_Customer</entity_model> - <form_model>Mage_Customer_Model_Form</form_model> - <form_code> - <update>adminhtml_customer</update> - </form_code> - </admin> - <customer> - <entity_model>Mage_Customer_Model_Customer</entity_model> - <form_model>Mage_Customer_Model_Form</form_model> - <form_code> - <update>customer_account_edit</update> - </form_code> - </customer> - </eav> - </validators> - <routes> - <route_entity> - <route>/customers/:id</route> - <action_type>entity</action_type> - </route_entity> - <route_collection> - <route>/customers</route> - <action_type>collection</action_type> - </route_collection> - </routes> - <versions>1</versions> - </customer> - <customer_address translate="title" module="Mage_Api2"> - <group>customer</group> - <sort_order>110</sort_order> - <model>Mage_Customer_Model_Api2_Customer_Address</model> - <working_model>Mage_Customer_Model_Address</working_model> - <title>Customer Address</title> - <privileges> - <admin> - <create>1</create> - <retrieve>1</retrieve> - <update>1</update> - <delete>1</delete> - </admin> - <customer> - <create>1</create> - <retrieve>1</retrieve> - <update>1</update> - <delete>1</delete> - </customer> - </privileges> - <attributes translate="entity_id is_default_billing is_default_shipping" module="Mage_Api2"> - <entity_id>Customer Address ID</entity_id> - <is_default_billing>Is Default Billing Address</is_default_billing> - <is_default_shipping>Is Default Shipping Address</is_default_shipping> - </attributes> - <exclude_attributes> - <admin> - <read> - <region_id>1</region_id> - <vat_is_valid>1</vat_is_valid> - <vat_request_date>1</vat_request_date> - <vat_request_id>1</vat_request_id> - <vat_request_success>1</vat_request_success> - </read> - <write> - <entity_id>1</entity_id> - <region_id>1</region_id> - <vat_is_valid>1</vat_is_valid> - <vat_request_date>1</vat_request_date> - <vat_request_id>1</vat_request_id> - <vat_request_success>1</vat_request_success> - </write> - </admin> - <customer> - <read> - <region_id>1</region_id> - </read> - <write> - <entity_id>1</entity_id> - <region_id>1</region_id> - </write> - </customer> - </exclude_attributes> - <validators> - <eav> - <admin> - <entity_model>Mage_Customer_Model_Address</entity_model> - <form_model>Mage_Customer_Model_Form</form_model> - <form_code> - <update>adminhtml_customer_address</update> - </form_code> - </admin> - <customer> - <entity_model>Mage_Customer_Model_Address</entity_model> - <form_model>Mage_Customer_Model_Form</form_model> - <form_code> - <update>customer_address_edit</update> - </form_code> - </customer> - </eav> - </validators> - <routes> - <route_entity> - <route>/customers/addresses/:id</route> - <action_type>entity</action_type> - </route_entity> - <route_collection> - <route>/customers/:customer_id/addresses</route> - <action_type>collection</action_type> - </route_collection> - </routes> - <versions>1</versions> - </customer_address> - </resources> - </api2> -</config> diff --git a/app/code/core/Mage/Customer/etc/validation.xml b/app/code/core/Mage/Customer/etc/validation.xml new file mode 100644 index 0000000000000000000000000000000000000000..dfcdb97ace695ccd16b0c0aa8006dcbf170225c1 --- /dev/null +++ b/app/code/core/Mage/Customer/etc/validation.xml @@ -0,0 +1,64 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Academic Free License (AFL 3.0) + * that is bundled with this package in the file LICENSE_AFL.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/afl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_Customer + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ +--> +<validation> + <entity name="customer"> + <rules> + <rule name="check_eav"> + <entity_constraints> + <constraint alias="eav_data_validator" class="Mage_Eav_Model_Validator_Attribute_Data" /> + <constraint alias="eav_validator" class="Mage_Eav_Model_Validator_Attribute_Data"/> + </entity_constraints> + </rule> + </rules> + <groups> + <group name="save"> + <uses> + <use rule="check_eav"/> + </uses> + </group> + </groups> + </entity> + + <entity name="customer_address"> + <rules> + <rule name="check_eav"> + <entity_constraints> + <constraint alias="eav_data_validator" class="Mage_Eav_Model_Validator_Attribute_Data" /> + <constraint alias="eav_backend_validator" class="Mage_Eav_Model_Validator_Attribute_Backend" /> + </entity_constraints> + </rule> + </rules> + <groups> + <group name="save"> + <uses> + <use rule="check_eav"/> + </uses> + </group> + </groups> + </entity> +</validation> diff --git a/app/code/core/Mage/Customer/etc/wsdl.xml b/app/code/core/Mage/Customer/etc/wsdl.xml deleted file mode 100644 index 133b88763966f26f4a91ca65cdfe2aee87abc164..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Customer/etc/wsdl.xml +++ /dev/null @@ -1,354 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<definitions xmlns:typens="urn:{{var wsdl.name}}" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" - xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns="http://schemas.xmlsoap.org/wsdl/" - name="{{var wsdl.name}}" targetNamespace="urn:{{var wsdl.name}}"> - <types> - <schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:Magento"> - <import namespace="http://schemas.xmlsoap.org/soap/encoding/" schemaLocation="http://schemas.xmlsoap.org/soap/encoding/" /> - <complexType name="customerCustomerEntityToCreate"> - <all> - <element name="customer_id" type="xsd:int" minOccurs="0" /> - <element name="email" type="xsd:string" minOccurs="0" /> - <element name="firstname" type="xsd:string" minOccurs="0" /> - <element name="lastname" type="xsd:string" minOccurs="0" /> - <element name="password" type="xsd:string" minOccurs="0" /> - <element name="website_id" type="xsd:int" minOccurs="0" /> - <element name="store_id" type="xsd:int" minOccurs="0" /> - <element name="group_id" type="xsd:int" minOccurs="0" /> - </all> - </complexType> - <complexType name="customerCustomerEntity"> - <all> - <element name="customer_id" type="xsd:int" minOccurs="0" /> - <element name="created_at" type="xsd:string" minOccurs="0" /> - <element name="updated_at" type="xsd:string" minOccurs="0" /> - <element name="increment_id" type="xsd:string" minOccurs="0" /> - <element name="store_id" type="xsd:int" minOccurs="0" /> - <element name="website_id" type="xsd:int" minOccurs="0" /> - <element name="created_in" type="xsd:string" minOccurs="0" /> - <element name="email" type="xsd:string" minOccurs="0" /> - <element name="firstname" type="xsd:string" minOccurs="0" /> - <element name="middlename" type="xsd:string" minOccurs="0" /> - <element name="lastname" type="xsd:string" minOccurs="0" /> - <element name="group_id" type="xsd:int" minOccurs="0" /> - <element name="prefix" type="xsd:string" minOccurs="0" /> - <element name="suffix" type="xsd:string" minOccurs="0" /> - <element name="dob" type="xsd:string" minOccurs="0" /> - <element name="taxvat" type="xsd:string" minOccurs="0" /> - <element name="confirmation" type="xsd:boolean" minOccurs="0" /> - <element name="password_hash" type="xsd:string" minOccurs="0" /> - </all> - </complexType> - <complexType name="customerCustomerEntityArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:customerCustomerEntity[]" /> - </restriction> - </complexContent> - </complexType> - <complexType name="customerGroupEntity"> - <all> - <element name="customer_group_id" type="xsd:int" /> - <element name="customer_group_code" type="xsd:string" /> - </all> - </complexType> - <complexType name="customerGroupEntityArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:customerGroupEntity[]" /> - </restriction> - </complexContent> - </complexType> - <complexType name="customerAddressEntityCreate"> - <all> - <element name="city" type="xsd:string" minOccurs="0" /> - <element name="company" type="xsd:string" minOccurs="0" /> - <element name="country_id" type="xsd:string" minOccurs="0" /> - <element name="fax" type="xsd:string" minOccurs="0" /> - <element name="firstname" type="xsd:string" minOccurs="0" /> - <element name="lastname" type="xsd:string" minOccurs="0" /> - <element name="middlename" type="xsd:string" minOccurs="0" /> - <element name="postcode" type="xsd:string" minOccurs="0" /> - <element name="prefix" type="xsd:string" minOccurs="0" /> - <element name="region_id" type="xsd:int" minOccurs="0" /> - <element name="region" type="xsd:string" minOccurs="0" /> - <element name="street" type="typens:ArrayOfString" minOccurs="0" /> - <element name="suffix" type="xsd:string" minOccurs="0" /> - <element name="telephone" type="xsd:string" minOccurs="0" /> - <element name="is_default_billing" type="xsd:boolean" minOccurs="0" /> - <element name="is_default_shipping" type="xsd:boolean" minOccurs="0" /> - </all> - </complexType> - <complexType name="customerAddressEntityItem"> - <all> - <element name="customer_address_id" type="xsd:int" minOccurs="0" /> - <element name="created_at" type="xsd:string" minOccurs="0" /> - <element name="updated_at" type="xsd:string" minOccurs="0" /> - <element name="increment_id" type="xsd:string" minOccurs="0" /> - <element name="city" type="xsd:string" minOccurs="0" /> - <element name="company" type="xsd:string" minOccurs="0" /> - <element name="country_id" type="xsd:string" minOccurs="0" /> - <element name="fax" type="xsd:string" minOccurs="0" /> - <element name="firstname" type="xsd:string" minOccurs="0" /> - <element name="lastname" type="xsd:string" minOccurs="0" /> - <element name="middlename" type="xsd:string" minOccurs="0" /> - <element name="postcode" type="xsd:string" minOccurs="0" /> - <element name="prefix" type="xsd:string" minOccurs="0" /> - <element name="region" type="xsd:string" minOccurs="0" /> - <element name="region_id" type="xsd:int" minOccurs="0" /> - <element name="street" type="xsd:string" minOccurs="0" /> - <element name="suffix" type="xsd:string" minOccurs="0" /> - <element name="telephone" type="xsd:string" minOccurs="0" /> - <element name="is_default_billing" type="xsd:boolean" minOccurs="0" /> - <element name="is_default_shipping" type="xsd:boolean" minOccurs="0" /> - </all> - </complexType> - <complexType name="customerAddressEntityArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:customerAddressEntityItem[]" /> - </restriction> - </complexContent> - </complexType> - </schema> - </types> - <message name="customerCustomerListRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="filters" type="typens:filters" /> - </message> - <message name="customerCustomerListResponse"> - <part name="storeView" type="typens:customerCustomerEntityArray" /> - </message> - <message name="customerCustomerCreateRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="customerData" type="typens:customerCustomerEntityToCreate" /> - </message> - <message name="customerCustomerCreateResponse"> - <part name="result" type="xsd:int" /> - </message> - <message name="customerCustomerInfoRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="customerId" type="xsd:int" /> - <part name="attributes" type="typens:ArrayOfString" /> - </message> - <message name="customerCustomerInfoResponse"> - <part name="customerInfo" type="typens:customerCustomerEntity" /> - </message> - <message name="customerCustomerUpdateRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="customerId" type="xsd:int" /> - <part name="customerData" type="typens:customerCustomerEntityToCreate" /> - </message> - <message name="customerCustomerUpdateResponse"> - <part name="result" type="xsd:boolean" /> - </message> - <message name="customerCustomerDeleteRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="customerId" type="xsd:int" /> - </message> - <message name="customerCustomerDeleteResponse"> - <part name="result" type="xsd:boolean" /> - </message> - <message name="customerGroupListRequest"> - <part name="sessionId" type="xsd:string" /> - </message> - <message name="customerGroupListResponse"> - <part name="result" type="typens:customerGroupEntityArray" /> - </message> - <message name="customerAddressListRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="customerId" type="xsd:int" /> - </message> - <message name="customerAddressListResponse"> - <part name="result" type="typens:customerAddressEntityArray" /> - </message> - <message name="customerAddressCreateRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="customerId" type="xsd:int" /> - <part name="addressData" type="typens:customerAddressEntityCreate" /> - </message> - <message name="customerAddressCreateResponse"> - <part name="result" type="xsd:int" /> - </message> - <message name="customerAddressInfoRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="addressId" type="xsd:int" /> - </message> - <message name="customerAddressInfoResponse"> - <part name="info" type="typens:customerAddressEntityItem" /> - </message> - <message name="customerAddressUpdateRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="addressId" type="xsd:int" /> - <part name="addressData" type="typens:customerAddressEntityCreate" /> - </message> - <message name="customerAddressUpdateResponse"> - <part name="info" type="xsd:boolean" /> - </message> - <message name="customerAddressDeleteRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="addressId" type="xsd:int" /> - </message> - <message name="customerAddressDeleteResponse"> - <part name="info" type="xsd:boolean" /> - </message> - <portType name="{{var wsdl.handler}}PortType"> - <operation name="customerCustomerList"> - <documentation>Retrieve customers</documentation> - <input message="typens:customerCustomerListRequest" /> - <output message="typens:customerCustomerListResponse" /> - </operation> - <operation name="customerCustomerCreate"> - <documentation>Create customer</documentation> - <input message="typens:customerCustomerCreateRequest" /> - <output message="typens:customerCustomerCreateResponse" /> - </operation> - <operation name="customerCustomerInfo"> - <documentation>Retrieve customer data</documentation> - <input message="typens:customerCustomerInfoRequest" /> - <output message="typens:customerCustomerInfoResponse" /> - </operation> - <operation name="customerCustomerUpdate"> - <documentation>Update customer data</documentation> - <input message="typens:customerCustomerUpdateRequest" /> - <output message="typens:customerCustomerUpdateResponse" /> - </operation> - <operation name="customerCustomerDelete"> - <documentation>Delete customer</documentation> - <input message="typens:customerCustomerDeleteRequest" /> - <output message="typens:customerCustomerDeleteResponse" /> - </operation> - <operation name="customerGroupList"> - <documentation>Retrieve customer groups</documentation> - <input message="typens:customerGroupListRequest" /> - <output message="typens:customerGroupListResponse" /> - </operation> - <operation name="customerAddressList"> - <documentation>Retrieve customer addresses</documentation> - <input message="typens:customerAddressListRequest" /> - <output message="typens:customerAddressListResponse" /> - </operation> - <operation name="customerAddressCreate"> - <documentation>Create customer address</documentation> - <input message="typens:customerAddressCreateRequest" /> - <output message="typens:customerAddressCreateResponse" /> - </operation> - <operation name="customerAddressInfo"> - <documentation>Retrieve customer address data</documentation> - <input message="typens:customerAddressInfoRequest" /> - <output message="typens:customerAddressInfoResponse" /> - </operation> - <operation name="customerAddressUpdate"> - <documentation>Update customer address data</documentation> - <input message="typens:customerAddressUpdateRequest" /> - <output message="typens:customerAddressUpdateResponse" /> - </operation> - <operation name="customerAddressDelete"> - <documentation>Delete customer address</documentation> - <input message="typens:customerAddressDeleteRequest" /> - <output message="typens:customerAddressDeleteResponse" /> - </operation> - </portType> - <binding name="{{var wsdl.handler}}Binding" type="typens:{{var wsdl.handler}}PortType"> - <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" /> - <operation name="customerCustomerList"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="customerCustomerCreate"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="customerCustomerInfo"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="customerCustomerUpdate"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="customerCustomerDelete"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="customerGroupList"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="customerAddressList"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="customerAddressCreate"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="customerAddressInfo"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="customerAddressUpdate"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="customerAddressDelete"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - </binding> -</definitions> diff --git a/app/code/core/Mage/Customer/etc/wsi.xml b/app/code/core/Mage/Customer/etc/wsi.xml deleted file mode 100644 index abef413cafc44d055219580a1595c4604d89e2d7..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Customer/etc/wsi.xml +++ /dev/null @@ -1,507 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<wsdl:definitions xmlns:typens="urn:{{var wsdl.name}}" - xmlns:xsd="http://www.w3.org/2001/XMLSchema" - xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" - xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" - xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" - name="{{var wsdl.name}}" - targetNamespace="urn:{{var wsdl.name}}"> - <wsdl:types> - <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:{{var wsdl.name}}"> - <xsd:complexType name="customerCustomerEntityToCreate"> - <xsd:sequence> - <xsd:element name="customer_id" type="xsd:int" minOccurs="0" /> - <xsd:element name="email" type="xsd:string" minOccurs="0" /> - <xsd:element name="firstname" type="xsd:string" minOccurs="0" /> - <xsd:element name="lastname" type="xsd:string" minOccurs="0" /> - <xsd:element name="password" type="xsd:string" minOccurs="0" /> - <xsd:element name="website_id" type="xsd:int" minOccurs="0" /> - <xsd:element name="store_id" type="xsd:int" minOccurs="0" /> - <xsd:element name="group_id" type="xsd:int" minOccurs="0" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="customerCustomerEntity"> - <xsd:sequence> - <xsd:element name="customer_id" type="xsd:int" minOccurs="0" /> - <xsd:element name="created_at" type="xsd:string" minOccurs="0" /> - <xsd:element name="updated_at" type="xsd:string" minOccurs="0" /> - <xsd:element name="increment_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="store_id" type="xsd:int" minOccurs="0" /> - <xsd:element name="website_id" type="xsd:int" minOccurs="0" /> - <xsd:element name="created_in" type="xsd:string" minOccurs="0" /> - <xsd:element name="email" type="xsd:string" minOccurs="0" /> - <xsd:element name="firstname" type="xsd:string" minOccurs="0" /> - <xsd:element name="middlename" type="xsd:string" minOccurs="0" /> - <xsd:element name="lastname" type="xsd:string" minOccurs="0" /> - <xsd:element name="group_id" type="xsd:int" minOccurs="0" /> - <xsd:element name="prefix" type="xsd:string" minOccurs="0" /> - <xsd:element name="suffix" type="xsd:string" minOccurs="0" /> - <xsd:element name="dob" type="xsd:string" minOccurs="0" /> - <xsd:element name="taxvat" type="xsd:string" minOccurs="0" /> - <xsd:element name="confirmation" type="xsd:boolean" minOccurs="0" /> - <xsd:element name="password_hash" type="xsd:string" minOccurs="0" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="customerCustomerEntityArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:customerCustomerEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="customerGroupEntity"> - <xsd:sequence> - <xsd:element name="customer_group_id" type="xsd:int" /> - <xsd:element name="customer_group_code" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="customerGroupEntityArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:customerGroupEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="customerAddressEntityCreate"> - <xsd:sequence> - <xsd:element name="city" type="xsd:string" minOccurs="0" /> - <xsd:element name="company" type="xsd:string" minOccurs="0" /> - <xsd:element name="country_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="fax" type="xsd:string" minOccurs="0" /> - <xsd:element name="firstname" type="xsd:string" minOccurs="0" /> - <xsd:element name="lastname" type="xsd:string" minOccurs="0" /> - <xsd:element name="middlename" type="xsd:string" minOccurs="0" /> - <xsd:element name="postcode" type="xsd:string" minOccurs="0" /> - <xsd:element name="prefix" type="xsd:string" minOccurs="0" /> - <xsd:element name="region_id" type="xsd:int" minOccurs="0" /> - <xsd:element name="region" type="xsd:string" minOccurs="0" /> - <xsd:element name="street" type="typens:ArrayOfString" minOccurs="0" /> - <xsd:element name="suffix" type="xsd:string" minOccurs="0" /> - <xsd:element name="telephone" type="xsd:string" minOccurs="0" /> - <xsd:element name="is_default_billing" type="xsd:boolean" minOccurs="0" /> - <xsd:element name="is_default_shipping" type="xsd:boolean" minOccurs="0" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="customerAddressEntityItem"> - <xsd:sequence> - <xsd:element name="customer_address_id" type="xsd:int" minOccurs="0" /> - <xsd:element name="created_at" type="xsd:string" minOccurs="0" /> - <xsd:element name="updated_at" type="xsd:string" minOccurs="0" /> - <xsd:element name="increment_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="city" type="xsd:string" minOccurs="0" /> - <xsd:element name="company" type="xsd:string" minOccurs="0" /> - <xsd:element name="country_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="fax" type="xsd:string" minOccurs="0" /> - <xsd:element name="firstname" type="xsd:string" minOccurs="0" /> - <xsd:element name="lastname" type="xsd:string" minOccurs="0" /> - <xsd:element name="middlename" type="xsd:string" minOccurs="0" /> - <xsd:element name="postcode" type="xsd:string" minOccurs="0" /> - <xsd:element name="prefix" type="xsd:string" minOccurs="0" /> - <xsd:element name="region" type="xsd:string" minOccurs="0" /> - <xsd:element name="region_id" type="xsd:int" minOccurs="0" /> - <xsd:element name="street" type="xsd:string" minOccurs="0" /> - <xsd:element name="suffix" type="xsd:string" minOccurs="0" /> - <xsd:element name="telephone" type="xsd:string" minOccurs="0" /> - <xsd:element name="is_default_billing" type="xsd:boolean" minOccurs="0" /> - <xsd:element name="is_default_shipping" type="xsd:boolean" minOccurs="0" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="customerAddressEntityArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:customerAddressEntityItem" /> - </xsd:sequence> - </xsd:complexType> - - - <xsd:element name="customerCustomerListRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="filters" type="typens:filters" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="customerCustomerListResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:customerCustomerEntityArray" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="customerCustomerCreateRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="customerData" type="typens:customerCustomerEntityToCreate" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="customerCustomerCreateResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="customerCustomerInfoRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="customerId" type="xsd:int" /> - <xsd:element minOccurs="0" maxOccurs="1" name="attributes" type="typens:ArrayOfString" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="customerCustomerInfoResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:customerCustomerEntity" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="customerCustomerUpdateRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="customerId" type="xsd:int" /> - <xsd:element minOccurs="1" maxOccurs="1" name="customerData" type="typens:customerCustomerEntityToCreate" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="customerCustomerUpdateResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:boolean" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="customerCustomerDeleteRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="customerId" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="customerCustomerDeleteResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:boolean" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="customerGroupListRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="customerGroupListResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:customerGroupEntityArray" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="customerAddressListRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="customerId" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="customerAddressListResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:customerAddressEntityArray" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="customerAddressCreateRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="customerId" type="xsd:int" /> - <xsd:element minOccurs="1" maxOccurs="1" name="addressData" type="typens:customerAddressEntityCreate" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="customerAddressCreateResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="customerAddressInfoRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="addressId" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="customerAddressInfoResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:customerAddressEntityItem" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="customerAddressUpdateRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="addressId" type="xsd:int" /> - <xsd:element minOccurs="1" maxOccurs="1" name="addressData" type="typens:customerAddressEntityCreate" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="customerAddressUpdateResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:boolean" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="customerAddressDeleteRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="addressId" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="customerAddressDeleteResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:boolean" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - </xsd:schema> - </wsdl:types> - <wsdl:message name="customerCustomerListRequest"> - <wsdl:part name="parameters" element="typens:customerCustomerListRequestParam" /> - </wsdl:message> - <wsdl:message name="customerCustomerListResponse"> - <wsdl:part name="parameters" element="typens:customerCustomerListResponseParam" /> - </wsdl:message> - <wsdl:message name="customerCustomerCreateRequest"> - <wsdl:part name="parameters" element="typens:customerCustomerCreateRequestParam" /> - </wsdl:message> - <wsdl:message name="customerCustomerCreateResponse"> - <wsdl:part name="parameters" element="typens:customerCustomerCreateResponseParam" /> - </wsdl:message> - <wsdl:message name="customerCustomerInfoRequest"> - <wsdl:part name="parameters" element="typens:customerCustomerInfoRequestParam" /> - </wsdl:message> - <wsdl:message name="customerCustomerInfoResponse"> - <wsdl:part name="parameters" element="typens:customerCustomerInfoResponseParam" /> - </wsdl:message> - <wsdl:message name="customerCustomerUpdateRequest"> - <wsdl:part name="parameters" element="typens:customerCustomerUpdateRequestParam" /> - </wsdl:message> - <wsdl:message name="customerCustomerUpdateResponse"> - <wsdl:part name="parameters" element="typens:customerCustomerUpdateResponseParam" /> - </wsdl:message> - <wsdl:message name="customerCustomerDeleteRequest"> - <wsdl:part name="parameters" element="typens:customerCustomerDeleteRequestParam" /> - </wsdl:message> - <wsdl:message name="customerCustomerDeleteResponse"> - <wsdl:part name="parameters" element="typens:customerCustomerDeleteResponseParam" /> - </wsdl:message> - <wsdl:message name="customerGroupListRequest"> - <wsdl:part name="parameters" element="typens:customerGroupListRequestParam" /> - </wsdl:message> - <wsdl:message name="customerGroupListResponse"> - <wsdl:part name="parameters" element="typens:customerGroupListResponseParam" /> - </wsdl:message> - <wsdl:message name="customerAddressListRequest"> - <wsdl:part name="parameters" element="typens:customerAddressListRequestParam" /> - </wsdl:message> - <wsdl:message name="customerAddressListResponse"> - <wsdl:part name="parameters" element="typens:customerAddressListResponseParam" /> - </wsdl:message> - <wsdl:message name="customerAddressCreateRequest"> - <wsdl:part name="parameters" element="typens:customerAddressCreateRequestParam" /> - </wsdl:message> - <wsdl:message name="customerAddressCreateResponse"> - <wsdl:part name="parameters" element="typens:customerAddressCreateResponseParam" /> - </wsdl:message> - <wsdl:message name="customerAddressInfoRequest"> - <wsdl:part name="parameters" element="typens:customerAddressInfoRequestParam" /> - </wsdl:message> - <wsdl:message name="customerAddressInfoResponse"> - <wsdl:part name="parameters" element="typens:customerAddressInfoResponseParam" /> - </wsdl:message> - <wsdl:message name="customerAddressUpdateRequest"> - <wsdl:part name="parameters" element="typens:customerAddressUpdateRequestParam" /> - </wsdl:message> - <wsdl:message name="customerAddressUpdateResponse"> - <wsdl:part name="parameters" element="typens:customerAddressUpdateResponseParam" /> - </wsdl:message> - <wsdl:message name="customerAddressDeleteRequest"> - <wsdl:part name="parameters" element="typens:customerAddressDeleteRequestParam" /> - </wsdl:message> - <wsdl:message name="customerAddressDeleteResponse"> - <wsdl:part name="parameters" element="typens:customerAddressDeleteResponseParam" /> - </wsdl:message> - <wsdl:portType name="{{var wsdl.handler}}PortType"> - <wsdl:operation name="customerCustomerList"> - <wsdl:documentation>Retrieve customers</wsdl:documentation> - <wsdl:input message="typens:customerCustomerListRequest" /> - <wsdl:output message="typens:customerCustomerListResponse" /> - </wsdl:operation> - <wsdl:operation name="customerCustomerCreate"> - <wsdl:documentation>Create customer</wsdl:documentation> - <wsdl:input message="typens:customerCustomerCreateRequest" /> - <wsdl:output message="typens:customerCustomerCreateResponse" /> - </wsdl:operation> - <wsdl:operation name="customerCustomerInfo"> - <wsdl:documentation>Retrieve customer data</wsdl:documentation> - <wsdl:input message="typens:customerCustomerInfoRequest" /> - <wsdl:output message="typens:customerCustomerInfoResponse" /> - </wsdl:operation> - <wsdl:operation name="customerCustomerUpdate"> - <wsdl:documentation>Update customer data</wsdl:documentation> - <wsdl:input message="typens:customerCustomerUpdateRequest" /> - <wsdl:output message="typens:customerCustomerUpdateResponse" /> - </wsdl:operation> - <wsdl:operation name="customerCustomerDelete"> - <wsdl:documentation>Delete customer</wsdl:documentation> - <wsdl:input message="typens:customerCustomerDeleteRequest" /> - <wsdl:output message="typens:customerCustomerDeleteResponse" /> - </wsdl:operation> - <wsdl:operation name="customerGroupList"> - <wsdl:documentation>Retrieve customer groups</wsdl:documentation> - <wsdl:input message="typens:customerGroupListRequest" /> - <wsdl:output message="typens:customerGroupListResponse" /> - </wsdl:operation> - <wsdl:operation name="customerAddressList"> - <wsdl:documentation>Retrieve customer addresses</wsdl:documentation> - <wsdl:input message="typens:customerAddressListRequest" /> - <wsdl:output message="typens:customerAddressListResponse" /> - </wsdl:operation> - <wsdl:operation name="customerAddressCreate"> - <wsdl:documentation>Create customer address</wsdl:documentation> - <wsdl:input message="typens:customerAddressCreateRequest" /> - <wsdl:output message="typens:customerAddressCreateResponse" /> - </wsdl:operation> - <wsdl:operation name="customerAddressInfo"> - <wsdl:documentation>Retrieve customer address data</wsdl:documentation> - <wsdl:input message="typens:customerAddressInfoRequest" /> - <wsdl:output message="typens:customerAddressInfoResponse" /> - </wsdl:operation> - <wsdl:operation name="customerAddressUpdate"> - <wsdl:documentation>Update customer address data</wsdl:documentation> - <wsdl:input message="typens:customerAddressUpdateRequest" /> - <wsdl:output message="typens:customerAddressUpdateResponse" /> - </wsdl:operation> - <wsdl:operation name="customerAddressDelete"> - <wsdl:documentation>Delete customer address</wsdl:documentation> - <wsdl:input message="typens:customerAddressDeleteRequest" /> - <wsdl:output message="typens:customerAddressDeleteResponse" /> - </wsdl:operation> - </wsdl:portType> - <wsdl:binding name="{{var wsdl.handler}}Binding" type="typens:{{var wsdl.handler}}PortType"> - <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" /> - <wsdl:operation name="customerCustomerList"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="customerCustomerCreate"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="customerCustomerInfo"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="customerCustomerUpdate"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="customerCustomerDelete"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="customerGroupList"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="customerAddressList"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="customerAddressCreate"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="customerAddressInfo"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="customerAddressUpdate"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="customerAddressDelete"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - </wsdl:binding> -</wsdl:definitions> diff --git a/app/code/core/Mage/Directory/Model/Country/Api.php b/app/code/core/Mage/Directory/Model/Country/Api.php deleted file mode 100644 index 3a945c3d822f74f2872c300d0f6fec76a65385b3..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Directory/Model/Country/Api.php +++ /dev/null @@ -1,54 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Directory - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Directory Country Api - * - * @category Mage - * @package Mage_Directory - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Directory_Model_Country_Api extends Mage_Api_Model_Resource_Abstract -{ - /** - * Retrieve countries list - * - * @return array - */ - public function items() - { - $collection = Mage::getModel('Mage_Directory_Model_Country')->getCollection(); - - $result = array(); - foreach ($collection as $country) { - /* @var $country Mage_Directory_Model_Country */ - $country->getName(); // Loading name in default locale - $result[] = $country->toArray(array('country_id', 'iso2_code', 'iso3_code', 'name')); - } - - return $result; - } -} // Class Mage_Directory_Model_Country_Api End diff --git a/app/code/core/Mage/Directory/Model/Country/Api/V2.php b/app/code/core/Mage/Directory/Model/Country/Api/V2.php deleted file mode 100644 index b705b4de884218abc67b92a2f41bdebe566682ec..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Directory/Model/Country/Api/V2.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Directory - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Directory Country Api V2 - * - * @category Mage - * @package Mage_Directory - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Directory_Model_Country_Api_V2 extends Mage_Directory_Model_Country_Api -{ -} diff --git a/app/code/core/Mage/Directory/Model/Region/Api.php b/app/code/core/Mage/Directory/Model/Region/Api.php deleted file mode 100644 index 855bd92ad09484ce69255a7dde974fa4091db09a..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Directory/Model/Region/Api.php +++ /dev/null @@ -1,62 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Directory - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Directory Region Api - * - * @category Mage - * @package Mage_Directory - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Directory_Model_Region_Api extends Mage_Api_Model_Resource_Abstract -{ - /** - * Retrieve regions list - * - * @param string $country - * @return array - */ - public function items($country) - { - try { - $country = Mage::getModel('Mage_Directory_Model_Country')->loadByCode($country); - } catch (Mage_Core_Exception $e) { - $this->_fault('country_not_exists', $e->getMessage()); - } - - if (!$country->getId()) { - $this->_fault('country_not_exists'); - } - - $result = array(); - foreach ($country->getRegions() as $region) { - $region->getName(); - $result[] = $region->toArray(array('region_id', 'code', 'name')); - } - - return $result; - } -} // Class Mage_Directory_Model_Region_Api End diff --git a/app/code/core/Mage/Directory/Model/Region/Api/V2.php b/app/code/core/Mage/Directory/Model/Region/Api/V2.php deleted file mode 100644 index f3d898779b128a87bb6c585a66e1686e5b5aad29..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Directory/Model/Region/Api/V2.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Directory - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Directory Region Api V2 - * - * @category Mage - * @package Mage_Directory - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Directory_Model_Region_Api_V2 extends Mage_Directory_Model_Region_Api -{ -} diff --git a/app/code/core/Mage/Directory/etc/api.xml b/app/code/core/Mage/Directory/etc/api.xml deleted file mode 100644 index 07901e78d05d1305f08644c68b31e9fa9487f08a..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Directory/etc/api.xml +++ /dev/null @@ -1,85 +0,0 @@ -<?xml version="1.0"?> -<!-- -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Academic Free License (AFL 3.0) - * that is bundled with this package in the file LICENSE_AFL.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/afl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Directory - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) - */ ---> -<config> - <api> - <resources> - <directory_country translate="title" module="Mage_Directory"> - <model>Mage_Directory_Model_Country_Api</model> - <title>Country API</title> - <acl>directory/country</acl> - <methods> - <list translate="title" module="Mage_Directory"> - <title>List of countries</title> - <method>items</method> - </list> - </methods> - </directory_country> - <directory_region translate="title" module="Mage_Directory"> - <model>Mage_Directory_Model_Region_Api</model> - <title>Region API</title> - <acl>directory/region</acl> - <methods> - <list translate="title" module="Mage_Directory"> - <title>List of regions in specified country</title> - <method>items</method> - </list> - </methods> - <faults module="Mage_Directory"> - <country_not_exists> - <code>101</code> - <message>Country not exists.</message> - </country_not_exists> - </faults> - </directory_region> - </resources> - <resources_alias> - <country>directory_country</country> - <region>directory_region</region> - </resources_alias> - <v2> - <resources_function_prefix> - <country>directoryCountry</country> - <region>directoryRegion</region> - </resources_function_prefix> - </v2> - <acl> - <resources> - <directory translate="title" module="Mage_Directory"> - <title>Directory</title> - <sort_order>5</sort_order> - <country translate="title" module="Mage_Directory"> - <title>Country</title> - </country> - <region translate="title" module="Mage_Directory"> - <title>Region</title> - </region> - </directory> - </resources> - </acl> - </api> -</config> diff --git a/app/code/core/Mage/Directory/etc/wsdl.xml b/app/code/core/Mage/Directory/etc/wsdl.xml deleted file mode 100644 index 5ace22429397ca334693a189d9465247e805a672..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Directory/etc/wsdl.xml +++ /dev/null @@ -1,90 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<definitions xmlns:typens="urn:{{var wsdl.name}}" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" - xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns="http://schemas.xmlsoap.org/wsdl/" - name="{{var wsdl.name}}" targetNamespace="urn:{{var wsdl.name}}"> - <types> - <schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:Magento"> - <import namespace="http://schemas.xmlsoap.org/soap/encoding/" schemaLocation="http://schemas.xmlsoap.org/soap/encoding/" /> - <complexType name="directoryCountryEntity"> - <all> - <element name="country_id" type="xsd:string" /> - <element name="iso2_code" type="xsd:string" /> - <element name="iso3_code" type="xsd:string" /> - <element name="name" type="xsd:string" /> - </all> - </complexType> - <complexType name="directoryCountryEntityArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:directoryCountryEntity[]" /> - </restriction> - </complexContent> - </complexType> - <complexType name="directoryRegionEntity"> - <all> - <element name="region_id" type="xsd:string" /> - <element name="code" type="xsd:string" /> - <element name="name" type="xsd:string" /> - </all> - </complexType> - <complexType name="directoryRegionEntityArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:directoryRegionEntity[]" /> - </restriction> - </complexContent> - </complexType> - </schema> - </types> - <message name="directoryCountryListRequest"> - <part name="sessionId" type="xsd:string" /> - </message> - <message name="directoryCountryListResponse"> - <part name="countries" type="typens:directoryCountryEntityArray" /> - </message> - <message name="directoryRegionListRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="country" type="xsd:string" /> - </message> - <message name="directoryRegionListResponse"> - <part name="countries" type="typens:directoryRegionEntityArray" /> - </message> - <portType name="{{var wsdl.handler}}PortType"> - <operation name="directoryCountryList"> - <documentation>List of countries</documentation> - <input message="typens:directoryCountryListRequest" /> - <output message="typens:directoryCountryListResponse" /> - </operation> - <operation name="directoryRegionList"> - <documentation>List of regions in specified country</documentation> - <input message="typens:directoryRegionListRequest" /> - <output message="typens:directoryRegionListResponse" /> - </operation> - </portType> - <binding name="{{var wsdl.handler}}Binding" type="typens:{{var wsdl.handler}}PortType"> - <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" /> - <operation name="directoryCountryList"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="directoryRegionList"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - </binding> - <service name="{{var wsdl.name}}Service"> - <port name="{{var wsdl.handler}}Port" binding="typens:{{var wsdl.handler}}Binding"> - <soap:address location="{{var wsdl.url}}" /> - </port> - </service> -</definitions> diff --git a/app/code/core/Mage/Directory/etc/wsi.xml b/app/code/core/Mage/Directory/etc/wsi.xml deleted file mode 100644 index eca62b5d0cbd050761c81af2b389c9199329c569..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Directory/etc/wsi.xml +++ /dev/null @@ -1,119 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<wsdl:definitions xmlns:typens="urn:{{var wsdl.name}}" - xmlns:xsd="http://www.w3.org/2001/XMLSchema" - xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" - xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" - xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" - name="{{var wsdl.name}}" - targetNamespace="urn:{{var wsdl.name}}"> - <wsdl:types> - <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:{{var wsdl.name}}"> - <xsd:complexType name="directoryCountryEntity"> - <xsd:sequence> - <xsd:element name="country_id" type="xsd:string" /> - <xsd:element name="iso2_code" type="xsd:string" /> - <xsd:element name="iso3_code" type="xsd:string" /> - <xsd:element name="name" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="directoryCountryEntityArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:directoryCountryEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="directoryRegionEntity"> - <xsd:sequence> - <xsd:element name="region_id" type="xsd:string" /> - <xsd:element name="code" type="xsd:string" /> - <xsd:element name="name" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="directoryRegionEntityArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:directoryRegionEntity" /> - </xsd:sequence> - </xsd:complexType> - - - <xsd:element name="directoryCountryListRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="directoryCountryListResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:directoryCountryEntityArray" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="directoryRegionListRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="country" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="directoryRegionListResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:directoryRegionEntityArray" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - </xsd:schema> - </wsdl:types> - <wsdl:message name="directoryCountryListRequest"> - <wsdl:part name="parameters" element="typens:directoryCountryListRequestParam" /> - </wsdl:message> - <wsdl:message name="directoryCountryListResponse"> - <wsdl:part name="parameters" element="typens:directoryCountryListResponseParam" /> - </wsdl:message> - <wsdl:message name="directoryRegionListRequest"> - <wsdl:part name="parameters" element="typens:directoryRegionListRequestParam" /> - </wsdl:message> - <wsdl:message name="directoryRegionListResponse"> - <wsdl:part name="parameters" element="typens:directoryRegionListResponseParam" /> - </wsdl:message> - <wsdl:portType name="{{var wsdl.handler}}PortType"> - <wsdl:operation name="directoryCountryList"> - <wsdl:documentation>List of countries</wsdl:documentation> - <wsdl:input message="typens:directoryCountryListRequest" /> - <wsdl:output message="typens:directoryCountryListResponse" /> - </wsdl:operation> - <wsdl:operation name="directoryRegionList"> - <wsdl:documentation>List of regions in specified country</wsdl:documentation> - <wsdl:input message="typens:directoryRegionListRequest" /> - <wsdl:output message="typens:directoryRegionListResponse" /> - </wsdl:operation> - </wsdl:portType> - <wsdl:binding name="{{var wsdl.handler}}Binding" type="typens:{{var wsdl.handler}}PortType"> - <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" /> - <wsdl:operation name="directoryCountryList"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="directoryRegionList"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - </wsdl:binding> - <wsdl:service name="{{var wsdl.name}}Service"> - <wsdl:port name="{{var wsdl.handler}}Port" binding="typens:{{var wsdl.handler}}Binding"> - <soap:address location="{{var wsdl.url}}" /> - </wsdl:port> - </wsdl:service> -</wsdl:definitions> diff --git a/app/code/core/Mage/Downloadable/Model/Link/Api.php b/app/code/core/Mage/Downloadable/Model/Link/Api.php deleted file mode 100644 index 12b361113a4dd54b57395ddc82a2516ab07ba75d..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Downloadable/Model/Link/Api.php +++ /dev/null @@ -1,277 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Downloadable - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Downloadable links API model - * - * @category Mage - * @package Mage_Downloadable - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Downloadable_Model_Link_Api extends Mage_Catalog_Model_Api_Resource -{ - /** - * Return validator instance - * - * @return Mage_Downloadable_Model_Link_Api_Validator - */ - protected function _getValidator() - { - return Mage::getSingleton('Mage_Downloadable_Model_Link_Api_Validator'); - } - - /** - * Decode file from base64 and upload it to donwloadable 'tmp' folder - * - * @param array $fileInfo - * @param string $type - * @return string - */ - protected function _uploadFile($fileInfo, $type) - { - $tmpPath = ''; - if ($type == 'sample') { - $tmpPath = Mage_Downloadable_Model_Sample::getBaseTmpPath(); - } elseif ($type == 'link') { - $tmpPath = Mage_Downloadable_Model_Link::getBaseTmpPath(); - } elseif ($type == 'link_samples') { - $tmpPath = Mage_Downloadable_Model_Link::getBaseSampleTmpPath(); - } - - $result = array(); - try { - $uploader = Mage::getModel('Mage_Downloadable_Model_Link_Api_Uploader', array('file' => $fileInfo)); - $uploader->setAllowRenameFiles(true); - $uploader->setFilesDispersion(true); - $result = $uploader->save($tmpPath); - - if (isset($result['file'])) { - $fullPath = rtrim($tmpPath, DS) . DS . ltrim($result['file'], DS); - Mage::helper('Mage_Core_Helper_File_Storage_Database')->saveFile($fullPath); - } - } catch (Exception $e) { - if ($e->getMessage() != '') { - $this->_fault('upload_failed', $e->getMessage()); - } else { - $this->_fault($e->getCode()); - } - } - - $result['status'] = 'new'; - $result['name'] = substr($result['file'], strrpos($result['file'], '/')+1); - return Mage::helper('Mage_Core_Helper_Data')->jsonEncode(array($result)); - } - - /** - * Add downloadable content to product - * - * @param int|string $productId - * @param array $resource - * @param string $resourceType - * @param string|int|null $store - * @param string|null $identifierType ('sku'|'id') - * @return boolean - */ - public function add($productId, $resource, $resourceType, $store = null, $identifierType = null) - { - try { - $this->_getValidator()->validateType($resourceType); - $this->_getValidator()->validateAttributes($resource, $resourceType); - } catch (Exception $e) { - $this->_fault('validation_error', $e->getMessage()); - } - - $resource['is_delete'] = 0; - if ($resourceType == 'link') { - $resource['link_id'] = 0; - } elseif ($resourceType == 'sample') { - $resource['sample_id'] = 0; - } - - if ($resource['type'] == 'file') { - if (isset($resource['file'])) { - $resource['file'] = $this->_uploadFile($resource['file'], $resourceType); - } - unset($resource[$resourceType.'_url']); - } elseif ($resource['type'] == 'url') { - unset($resource['file']); - } - - if ($resourceType == 'link' && $resource['sample']['type'] == 'file') { - if (isset($resource['sample']['file'])) { - $resource['sample']['file'] = $this->_uploadFile($resource['sample']['file'], 'link_samples'); - } - unset($resource['sample']['url']); - } elseif ($resourceType == 'link' && $resource['sample']['type'] == 'url') { - $resource['sample']['file'] = null; - } - - $product = $this->_getProduct($productId, $store, $identifierType); - try { - $downloadable = array($resourceType => array($resource)); - $product->setDownloadableData($downloadable); - $product->save(); - } catch (Exception $e) { - $this->_fault('save_error', $e->getMessage()); - } - - return true; - } - - /** - * Retrieve downloadable product links - * - * @param int|string $productId - * @param string|int $store - * @param string $identifierType ('sku'|'id') - * @return array - */ - public function items($productId, $store = null, $identifierType = null) - { - $product = $this->_getProduct($productId, $store, $identifierType); - - $linkArr = array(); - $links = $product->getTypeInstance()->getLinks($product); - $fileHelper = Mage::helper('Mage_Downloadable_Helper_File'); - foreach ($links as $item) { - $tmpLinkItem = array( - 'link_id' => $item->getId(), - 'title' => $item->getTitle(), - 'price' => $item->getPrice(), - 'number_of_downloads' => $item->getNumberOfDownloads(), - 'is_shareable' => $item->getIsShareable(), - 'link_url' => $item->getLinkUrl(), - 'link_type' => $item->getLinkType(), - 'sample_file' => $item->getSampleFile(), - 'sample_url' => $item->getSampleUrl(), - 'sample_type' => $item->getSampleType(), - 'sort_order' => $item->getSortOrder() - ); - $file = $fileHelper->getFilePath( - Mage_Downloadable_Model_Link::getBasePath(), $item->getLinkFile() - ); - - if ($item->getLinkFile() && !is_file($file)) { - Mage::helper('Mage_Core_Helper_File_Storage_Database')->saveFileToFilesystem($file); - } - - if ($item->getLinkFile() && is_file($file)) { - $name = $fileHelper->getFileFromPathFile($item->getLinkFile()); - $tmpLinkItem['file_save'] = array( - array( - 'file' => $item->getLinkFile(), - 'name' => $name, - 'size' => filesize($file), - 'status' => 'old' - )); - } - $sampleFile = $fileHelper->getFilePath( - Mage_Downloadable_Model_Link::getBaseSamplePath(), $item->getSampleFile() - ); - if ($item->getSampleFile() && is_file($sampleFile)) { - $tmpLinkItem['sample_file_save'] = array( - array( - 'file' => $item->getSampleFile(), - 'name' => $fileHelper->getFileFromPathFile($item->getSampleFile()), - 'size' => filesize($sampleFile), - 'status' => 'old' - )); - } - if ($item->getNumberOfDownloads() == '0') { - $tmpLinkItem['is_unlimited'] = 1; - } - if ($product->getStoreId() && $item->getStoreTitle()) { - $tmpLinkItem['store_title'] = $item->getStoreTitle(); - } - if ($product->getStoreId() && Mage::helper('Mage_Downloadable_Helper_Data')->getIsPriceWebsiteScope()) { - $tmpLinkItem['website_price'] = $item->getWebsitePrice(); - } - $linkArr[] = $tmpLinkItem; - } - unset($item); - unset($tmpLinkItem); - unset($links); - - $samples = $product->getTypeInstance()->getSamples($product)->getData(); - return array('links' => $linkArr, 'samples' => $samples); - } - - /** - * Remove downloadable product link - * @param string $linkId - * @param string $resourceType - * @return bool - */ - public function remove($linkId, $resourceType) - { - try { - $this->_getValidator()->validateType($resourceType); - } catch (Exception $e) { - $this->_fault('validation_error', $e->getMessage()); - } - - switch($resourceType) { - case 'link': - $downloadableModel = Mage::getSingleton('Mage_Downloadable_Model_Link'); - break; - case 'sample': - $downloadableModel = Mage::getSingleton('Mage_Downloadable_Model_Sample'); - break; - } - - $downloadableModel->load($linkId); - if (is_null($downloadableModel->getId())) { - $this->_fault('link_was_not_found'); - } - - try { - $downloadableModel->delete(); - } catch (Exception $e) { - $this->_fault('remove_error', $e->getMessage()); - } - - return true; - } - - /** - * Return loaded downloadable product instance - * - * @param int|string $productId (SKU or ID) - * @param int|string $store - * @param string $identifierType - * @return Mage_Catalog_Model_Product - */ - protected function _getProduct($productId, $store = null, $identifierType = null) - { - $product = parent::_getProduct($productId, $store, $identifierType); - - if ($product->getTypeId() !== Mage_Downloadable_Model_Product_Type::TYPE_DOWNLOADABLE) { - $this->_fault('product_not_downloadable'); - } - - return $product; - } -} diff --git a/app/code/core/Mage/Downloadable/Model/Link/Api/Uploader.php b/app/code/core/Mage/Downloadable/Model/Link/Api/Uploader.php deleted file mode 100644 index e9eeadbc5ff90a2c496e9a438d76dbbcac4703b6..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Downloadable/Model/Link/Api/Uploader.php +++ /dev/null @@ -1,129 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Downloadable - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * File uploader for API - * - * @category Mage - * @package Mage_Downloadable - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Downloadable_Model_Link_Api_Uploader extends Mage_Core_Model_File_Uploader -{ - /** - * Filename prefix - * - * @var string - */ - protected $_filePrefix = 'Api'; - - /** - * Default file type - */ - const DEFAULT_FILE_TYPE = 'application/octet-stream'; - - /** - * Check if the uploaded file exists - * - * @throws Exception - * @param array $file - */ - public function __construct($file) - { - $this->_setUploadFile($file); - if( !file_exists($this->_file['tmp_name']) ) { - throw new Exception('', 'file_not_uploaded'); - } else { - $this->_fileExists = true; - } - } - - /** - * Sets uploaded file info and decodes the file - * - * @throws Exception - * @param array $fileInfo - * @return void - */ - private function _setUploadFile($fileInfo) - { - if (!is_array($fileInfo)) { - throw new Exception('', 'file_data_not_correct'); - } - - $this->_file = $this->_decodeFile($fileInfo); - $this->_uploadType = self::SINGLE_STYLE; - } - - /** - * Decode uploaded file base64 encoded content - * - * @param array $fileInfo - * @return array - */ - private function _decodeFile($fileInfo) - { - $tmpFileName = $this->_getTmpFilePath(); - - $file = new Varien_Io_File(); - $file->open(array('path' => sys_get_temp_dir())); - $file->streamOpen($tmpFileName); - $file->streamWrite(base64_decode($fileInfo['base64_content'])); - $file->streamClose(); - - return array( - 'name' => $fileInfo['name'], - 'type' => isset($fileInfo['type'])? $fileInfo['type'] : self::DEFAULT_FILE_TYPE, - 'tmp_name' => $tmpFileName, - 'error' => 0, - 'size' => filesize($tmpFileName) - ); - } - - /** - * Generate temporary file name - * - * @return string - */ - private function _getTmpFilePath() - { - return tempnam(sys_get_temp_dir(), $this->_filePrefix); - - } - - /** - * Moves a file - * - * @param string $sourceFile - * @param string $destinationFile - * @return bool - */ - protected function _moveFile($sourceFile, $destinationFile) - { - return rename($sourceFile, $destinationFile); - } - -} diff --git a/app/code/core/Mage/Downloadable/Model/Link/Api/V2.php b/app/code/core/Mage/Downloadable/Model/Link/Api/V2.php deleted file mode 100644 index ef7e2da06a1ba6602a8d1851e89b2a30d28d921b..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Downloadable/Model/Link/Api/V2.php +++ /dev/null @@ -1,67 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Downloadable - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Downloadable links API model - * - * @category Mage - * @package Mage_Downloadable - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Downloadable_Model_Link_Api_V2 extends Mage_Downloadable_Model_Link_Api -{ - /** - * Clean the object, leave only property values - * - * @param object $var - * @return void - */ - protected function _prepareData(&$var) - { - if (is_object($var)) { - $var = get_object_vars($var); - foreach ($var as $key => &$value) { - $this->_prepareData($value); - } - } - } - - /** - * Add downloadable content to product - * - * @param int|string $productId - * @param object $resource - * @param string $resourceType - * @param string|int $store - * @param string $identifierType ('sku'|'id') - * @return type - */ - public function add($productId, $resource, $resourceType, $store = null, $identifierType = null) - { - $this->_prepareData($resource); - return parent::add($productId, $resource, $resourceType, $store, $identifierType); - } -} diff --git a/app/code/core/Mage/Downloadable/Model/Link/Api/Validator.php b/app/code/core/Mage/Downloadable/Model/Link/Api/Validator.php deleted file mode 100644 index 79f7fc4b6a97fb107f39aaf89e405787e14ae8eb..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Downloadable/Model/Link/Api/Validator.php +++ /dev/null @@ -1,286 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Downloadable - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Downloadable links validator - * - * @category Mage - * @package Mage_Downloadable - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Downloadable_Model_Link_Api_Validator //extends Mage_Api_Model_Resource_Abstract -{ - /** - * Acceptable resourceTypes array - * @var array - */ - protected $_types = array('link', 'sample'); - - /** - * Acceptable upload types array - * @var array - */ - protected $_uploadTypes = array('file', 'url'); - - /** - * List of all attributes and names endings of validation functions - * - * @var array - */ - protected $_defaultAttributes = array( - 'link' => array( - 'title' => 'Title', // $1 - 'price' => 'Price', // $2 - 'number_of_downloads' => 'NumOfDownloads', // if no set is_unlimited to 1 $3 - 'is_unlimited' => 'Unlimited', // 1|0 $4 - 'is_shareable' => 'Shareable', // 1|0|2 (2) $5 - 'type' => 'UploadType', // file|url (file) $6 - 'file' => 'File', // array(name, base64_content) $7 - 'link_url' => 'Url', // URL $8 - 'sort_order' => 'Order', // int (0) $9 - 'sample' => array( - 'type' => 'UploadType', // file|url (file) $6 - 'file' => 'File', // array(name, base64_content) $7 - 'url' => 'Url' // URL $8 - ) - ), - 'sample' => array( - 'title' => 'Title', // $1 - 'type' => 'UploadType', // file|url (file) $6 - 'file' => 'File', // array(name, base64_content) $7 - 'sample_url' => 'Url', // URL $8 - 'sort_order' => 'Order' // int (0) $9 - ) - ); - - /** - * Get resource types - * - * @return array - */ - public function getResourceTypes() - { - return $this->_types; - } - - /** - * Validate resourceType, it should be one of (links|samples|link_samples) - * - * @param string $type - * @return boolean - */ - public function validateType($type) - { - if (!in_array($type, $this->getResourceTypes())) { - throw new Exception('unknown_resource_type'); - } - return true; - } - - /** - * Validate all parameters and loads default values for omitted parameters. - * - * @param array $resource - * @param string $resourceType - */ - public function validateAttributes(&$resource, $resourceType) - { - $fields = $this->_defaultAttributes[$resourceType]; - $this->_dispatch($resource, $fields); - - $this->completeCheck($resource, $resourceType); - } - - /** - * Final check - * - * @param array $resource - * @param string $resourceType - */ - public function completeCheck(&$resource, $resourceType) - { - if ($resourceType == 'link') { - if ($resource['type'] == 'file') { - $this->validateFileDetails($resource['file']); - } - if ($resource['type'] == 'url' && empty($resource['link_url'])) { - throw new Exception('empty_url'); - } - // sample - if ($resource['sample']['type'] == 'file') { - $this->validateFileDetails($resource['sample']['file']); - } - if ($resource['sample']['type'] == 'url' && empty($resource['sample']['url'])) { - throw new Exception('empty_url'); - } - } - if ($resourceType == 'sample') { - if ($resource['type'] == 'file') { - $this->validateFileDetails($resource['file']); - } - if ($resource['type'] == 'url' && empty($resource['sample_url'])) { - throw new Exception('empty_url'); - } - } - } - - /** - * Validate variable, in case of fault throw exception - * - * @param mixed $var - */ - public function validateFileDetails(&$var) - { - if (!isset ($var['name']) || !is_string($var['name']) || strlen($var['name']) === 0) { - throw new Exception('no_filename'); - } - if (!isset ($var['base64_content']) - || !is_string($var['base64_content']) - || strlen($var['base64_content']) === 0 - ) { - throw new Exception('no_file_base64_content'); - } - } - - /** - * Runs all checks. - * - * @param array $resource - * @param array $fields - */ - protected function _dispatch(&$resource, $fields) - { - foreach ($fields as $name => $validator) { - if (is_string($validator) && strlen($validator) > 0 && array_key_exists($name, $resource)) { - $call = 'validate' . $validator; - $this->$call($resource[$name]); - } - if (is_array($validator)) { - $this->_dispatch($resource[$name], $validator); - } - } - } - - /** - * Validate variable, in case of fault loads default entity. - * - * @param string $var - */ - public function validateTitle(&$var) - { - if (!is_string($var) || strlen($var) === 0) { - throw new Exception('no_title'); - } - } - - /** - * Validate variable, in case of fault loads default entity. - * - * @param float $var - */ - public function validatePrice(&$var) - { - $var = is_numeric($var)? floatval($var) : floatval(0); - } - - /** - * Validate variable, in case of fault loads default entity. - * - * @param int $var - */ - public function validateNumOfDownloads(&$var) - { - $var = is_numeric($var)? intval($var) : 0; - } - - /** - * Validate variable, in case of fault loads default entity. - * - * @param int|boolean $var - */ - public function validateUnlimited(&$var) - { - $var = ((is_numeric($var) && $var >= 0 && $var <= 1) || (is_bool($var)))? intval($var) : 0; - } - - /** - * Validate variable, in case of fault loads default entity. - * - * @param int $var - */ - public function validateShareable(&$var) - { - $var = (is_numeric($var) && $var >= 0 && $var <= 2)? intval($var) : 2; - } - - /** - * Validate variable, in case of fault loads default entity. - * - * @param array $var - */ - public function validateFile(&$var) - { - $var = is_array($var)? $var : null; - } - - /** - * Validate variable, in case of fault loads default entity. - * - * @param string $var - */ - public function validateUrl(&$var) - { - - if (is_string($var) && strlen($var) > 0) { - $urlregex = "/^(https?|ftp)\:\/\/([a-z0-9+\!\*\(\)\,\;\?\&\=\$\_\.\-]+(\:[a-z0-9+\!\*\(\)\,\;\?\&\=\$\_\.\-]+)?@)?[a-z0-9\+\$\_\-]+(\.[a-z0-9+\$\_\-]+)*(\:[0-9]{2,5})?(\/([a-z0-9+\$\_\-]\.?)+)*\/?(\?[a-z\+\&\$\_\.\-][a-z0-9\;\:\@\/\&\%\=\+\$\_\.\-]*)?(#[a-z\_\.\-][a-z0-9\+\$\_\.\-]*)?$/i"; - if (!preg_match($urlregex, $var)) { - throw new Exception('url_not_valid'); - } - } else { - $var = ''; - } - } - - /** - * Validate variable, in case of fault loads default entity. - * - * @param int $var - */ - public function validateOrder(&$var) - { - $var = is_numeric($var)? intval($var) : 0; - } - - /** - * Validate variable, in case of fault loads default entity. - * - * @param string $var - */ - public function validateUploadType(&$var) - { - $var = in_array($var, $this->_uploadTypes)? $var : 'file'; - } -} diff --git a/app/code/core/Mage/Downloadable/etc/api.xml b/app/code/core/Mage/Downloadable/etc/api.xml deleted file mode 100644 index 90076a165234be3c1c4959fc7c28b19819759c1d..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Downloadable/etc/api.xml +++ /dev/null @@ -1,156 +0,0 @@ -<?xml version="1.0"?> -<!-- -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Academic Free License (AFL 3.0) - * that is bundled with this package in the file LICENSE_AFL.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/afl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Downloadable - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) - */ ---> -<config> - <api> - <resources> - <catalog_product_downloadable_link translate="title" module="Mage_Downloadable"> - <model>Mage_Downloadable_Model_Link_Api</model> - <title>Category API</title> - <acl>downloadable/link</acl> - <methods> - <add translate="title" module="Mage_Downloadable"> - <title>Add links and samples to downloadable product</title> - <method>add</method> - <acl>downloadable/link/add</acl> - </add> - <list translate="title" module="Mage_Downloadable"> - <title>Retrieve links and samples list from downloadable product</title> - <method>items</method> - <acl>downloadable/link/list</acl> - </list> - <remove translate="title" module="Mage_Downloadable"> - <title>Remove links and samples from downloadable product</title> - <acl>downloadable/link/remove</acl> - </remove> - </methods> - <faults module="Mage_Downloadable"> - <store_not_exists> - <code>100</code> - <message>Store with requested code/id does not exist.</message> - </store_not_exists> - <product_not_exists> - <code>101</code> - <message>Product with requested id does not exist.</message> - </product_not_exists> - <links_and_samples_allowed> - <code>401</code> - <message>Incorrect resourceType, only "links" and "samples" allowed.</message> - </links_and_samples_allowed> - <empty_url> - <code>402</code> - <message>URL cannot be empty.</message> - </empty_url> - <no_filename> - <code>403</code> - <message>Filename was omitted, or contains unallowed characters.</message> - </no_filename> - <no_file_base64_content> - <code>404</code> - <message>File content should be passed as base64 string. For details, please see http://en.wikipedia.org/wiki/Base64</message> - </no_file_base64_content> - <no_title> - <code>405</code> - <message>Title cannot be empty.</message> - </no_title> - <unknown_resource_type> - <code>406</code> - <message>Incorrect content type only "link", "link_samples" and "sample" allowed.</message> - </unknown_resource_type> - <product_not_downloadable> - <code>408</code> - <message>Incorrect product type. Downloadable content, can be added only to "downloadable" products.</message> - </product_not_downloadable> - <incorect_file_extension> - <code>409</code> - <message>Incorrect extension of filename.</message> - </incorect_file_extension> - <file_size_is_to_big> - <code>410</code> - <message>Uploaded file is too big.</message> - </file_size_is_to_big> - <tmp_dir_is_not_writeable> - <code>411</code> - <message>Has no permissions for writing to temporary folder.</message> - </tmp_dir_is_not_writeable> - <can_not_create_sub_tmp_folder> - <code>411</code> - <message>Cannot create sub folder in temporary folder.</message> - </can_not_create_sub_tmp_folder> - <link_was_not_found> - <code>412</code> - <message>Link or sample with specified ID was not found.</message> - </link_was_not_found> - <incorrect_resource_type> - <code>413</code> - <message>An allowed resource type values for remove method is: "links" and "samples".</message> - </incorrect_resource_type> - <save_error> - <code>414</code> - <message>Unable to save action. Details in error message.</message> - </save_error> - <validation_error> - <code>415</code> - <message>Validation error has occurred.</message> - </validation_error> - <remove_error> - <code>416</code> - <message>Unable to remove link. Details in error message.</message> - </remove_error> - </faults> - </catalog_product_downloadable_link> - </resources> - <resources_alias> - <product_downloadable_link>catalog_product_downloadable_link</product_downloadable_link> - </resources_alias> - <v2> - <resources_function_prefix> - <product_downloadable_link>catalogProductDownloadableLink</product_downloadable_link> - </resources_function_prefix> - </v2> - <acl> - <resources> - <catalog> - <product> - <downloadable_link translate="title" module="Mage_Downloadable"> - <title>Product downloadable links</title> - <add translate="title" module="Mage_Downloadable"> - <title>Add</title> - </add> - <list translate="title" module="Mage_Downloadable"> - <title>List</title> - </list> - <remove translate="title" module="Mage_Downloadable"> - <title>Remove</title> - </remove> - </downloadable_link> - </product> - </catalog> - </resources> - </acl> - </api> -</config> diff --git a/app/code/core/Mage/Downloadable/etc/wsdl.xml b/app/code/core/Mage/Downloadable/etc/wsdl.xml deleted file mode 100644 index b463be954b204538fc2aea20471058543a29a52d..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Downloadable/etc/wsdl.xml +++ /dev/null @@ -1,193 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<definitions xmlns:typens="urn:{{var wsdl.name}}" xmlns:xsd="http://www.w3.org/2001/XMLSchema" - xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" - xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" - xmlns="http://schemas.xmlsoap.org/wsdl/" - name="{{var wsdl.name}}" targetNamespace="urn:{{var wsdl.name}}"> - <types> - <schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:Magento"> - <import namespace="http://schemas.xmlsoap.org/soap/encoding/" - schemaLocation="http://schemas.xmlsoap.org/soap/encoding/"/> - <complexType name="catalogProductDownloadableLinkFileEntity"> - <all> - <element name="name" type="xsd:string" minOccurs="0" /> - <element name="base64_content" type="xsd:string" minOccurs="0" /> - </all> - </complexType> - <complexType name="catalogProductDownloadableLinkAddSampleEntity"> - <all> - <element name="type" type="xsd:string" minOccurs="0" /> - <element name="file" type="typens:catalogProductDownloadableLinkFileEntity" minOccurs="0" /> - <element name="url" type="xsd:string" minOccurs="0" /> - </all> - </complexType> - <complexType name="catalogProductDownloadableLinkAddEntity"> - <all> - <element name="title" type="xsd:string" minOccurs="1" /> - <element name="price" type="xsd:string" minOccurs="0" /> - <element name="is_unlimited" type="xsd:int" minOccurs="0" /> - <element name="number_of_downloads" type="xsd:int" minOccurs="0" /> - <element name="is_shareable" type="xsd:int" minOccurs="0" /> - <element name="sample" type="typens:catalogProductDownloadableLinkAddSampleEntity" minOccurs="0" /> - <element name="type" type="xsd:string" minOccurs="0" /> - <element name="file" type="typens:catalogProductDownloadableLinkFileEntity" minOccurs="0" /> - <element name="link_url" type="xsd:string" minOccurs="0" /> - <element name="sample_url" type="xsd:string" minOccurs="0" /> - <element name="sort_order" type="xsd:int" minOccurs="0" /> - </all> - </complexType> - <complexType name="catalogProductDownloadableLinkFileInfoEntity"> - <all> - <element name="file" type="xsd:string" /> - <element name="name" type="xsd:string" /> - <element name="size" type="xsd:int" /> - <element name="status" type="xsd:string" /> - </all> - </complexType> - <complexType name="catalogProductDownloadableLinkFileInfoEntityArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:catalogProductDownloadableLinkFileInfoEntity[]"/> - </restriction> - </complexContent> - </complexType> - <complexType name="catalogProductDownloadableLinkEntity"> - <all> - <element name="link_id" type="xsd:string" /> - <element name="title" type="xsd:string" /> - <element name="price" type="xsd:string" /> - <element name="number_of_downloads" type="xsd:int" minOccurs="0" /> - <element name="is_unlimited" type="xsd:int" minOccurs="0" /> - <element name="is_shareable" type="xsd:int" /> - <element name="link_url" type="xsd:string" /> - <element name="link_type" type="xsd:string" /> - <element name="sample_file" type="xsd:string" minOccurs="0" /> - <element name="sample_url" type="xsd:string" minOccurs="0" /> - <element name="sample_type" type="xsd:string" /> - <element name="sort_order" type="xsd:int" /> - <element name="file_save" type="typens:catalogProductDownloadableLinkFileInfoEntityArray" minOccurs="0" /> - <element name="sample_file_save" type="typens:catalogProductDownloadableLinkFileInfoEntityArray" minOccurs="0" /> - </all> - </complexType> - <complexType name="catalogProductDownloadableLinkEntityArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:catalogProductDownloadableLinkEntity[]"/> - </restriction> - </complexContent> - </complexType> - <complexType name="catalogProductDownloadableLinkSampleEntity"> - <all> - <element name="sample_id" type="xsd:string" /> - <element name="product_id" type="xsd:string" /> - <element name="sample_file" type="xsd:string" minOccurs="0" /> - <element name="sample_url" type="xsd:string" minOccurs="0" /> - <element name="sample_type" type="xsd:string" /> - <element name="sort_order" type="xsd:string" /> - <element name="default_title" type="xsd:string" /> - <element name="store_title" type="xsd:string" /> - <element name="title" type="xsd:string" /> - </all> - </complexType> - <complexType name="catalogProductDownloadableLinkSampleEntityArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:catalogProductDownloadableLinkSampleEntity[]"/> - </restriction> - </complexContent> - </complexType> - <complexType name="catalogProductDownloadableLinkInfoEntity"> - <all> - <element name="links" type="typens:catalogProductDownloadableLinkEntityArray" /> - <element name="samples" type="typens:catalogProductDownloadableLinkSampleEntityArray" /> - </all> - </complexType> - </schema> - </types> - <message name="catalogProductDownloadableLinkAddRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="productId" type="xsd:string"/> - <part name="resource" type="typens:catalogProductDownloadableLinkAddEntity"/> - <part name="resourceType" type="xsd:string"/> - <part name="store" type="xsd:string"/> - <part name="identifierType" type="xsd:string"/> - </message> - <message name="catalogProductDownloadableLinkAddResponse"> - <part name="respons" type="xsd:int"/> - </message> - <message name="catalogProductDownloadableLinkListRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="productId" type="xsd:string"/> - <part name="store" type="xsd:string"/> - <part name="identifierType" type="xsd:string"/> - </message> - <message name="catalogProductDownloadableLinkListResponse"> - <part name="respons" type="typens:catalogProductDownloadableLinkInfoEntity"/> - </message> - <message name="catalogProductDownloadableLinkRemoveRequest"> - <part name="sessionId" type="xsd:string"/> - <part name="linkId" type="xsd:string"/> - <part name="resourceType" type="xsd:string"/> - </message> - <message name="catalogProductDownloadableLinkRemoveResponse"> - <part name="respons" type="xsd:boolean"/> - </message> - <portType name="{{var wsdl.handler}}PortType"> - <operation name="catalogProductDownloadableLinkAdd"> - <documentation>Add links to downloadable product</documentation> - <input message="typens:catalogProductDownloadableLinkAddRequest"/> - <output message="typens:catalogProductDownloadableLinkAddResponse"/> - </operation> - <operation name="catalogProductDownloadableLinkList"> - <documentation>Retrieve list of links and samples for downloadable product</documentation> - <input message="typens:catalogProductDownloadableLinkListRequest"/> - <output message="typens:catalogProductDownloadableLinkListResponse"/> - </operation> - <operation name="catalogProductDownloadableLinkRemove"> - <documentation>Remove links and samples from downloadable product</documentation> - <input message="typens:catalogProductDownloadableLinkRemoveRequest"/> - <output message="typens:catalogProductDownloadableLinkRemoveResponse"/> - </operation> - </portType> - <binding name="{{var wsdl.handler}}Binding" type="typens:{{var wsdl.handler}}PortType"> - <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/> - <operation name="catalogProductDownloadableLinkAdd"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductDownloadableLinkList"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - <operation name="catalogProductDownloadableLinkRemove"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" - encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> - </output> - </operation> - </binding> - <service name="{{var wsdl.name}}Service"> - <port name="{{var wsdl.handler}}Port" binding="typens:{{var wsdl.handler}}Binding"> - <soap:address location="{{var wsdl.url}}"/> - </port> - </service> -</definitions> diff --git a/app/code/core/Mage/Downloadable/etc/wsi.xml b/app/code/core/Mage/Downloadable/etc/wsi.xml deleted file mode 100644 index 498eb427f3c4f82f34ca20e78805cdf45dd01d85..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Downloadable/etc/wsi.xml +++ /dev/null @@ -1,220 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<wsdl:definitions xmlns:typens="urn:{{var wsdl.name}}" - xmlns:xsd="http://www.w3.org/2001/XMLSchema" - xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" - xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" - xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" - name="{{var wsdl.name}}" - targetNamespace="urn:{{var wsdl.name}}"> - <wsdl:types> - <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:{{var wsdl.name}}"> - <xsd:complexType name="catalogProductDownloadableLinkFileEntity"> - <xsd:sequence> - <xsd:element name="name" type="xsd:string" minOccurs="0" /> - <xsd:element name="base64_content" type="xsd:string" minOccurs="0" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductDownloadableLinkAddSampleEntity"> - <xsd:sequence> - <xsd:element name="type" type="xsd:string" minOccurs="0" /> - <xsd:element name="file" type="typens:catalogProductDownloadableLinkFileEntity" minOccurs="0" /> - <xsd:element name="url" type="xsd:string" minOccurs="0" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductDownloadableLinkAddEntity"> - <xsd:sequence> - <xsd:element name="title" type="xsd:string" minOccurs="1" /> - <xsd:element name="price" type="xsd:string" minOccurs="0" /> - <xsd:element name="is_unlimited" type="xsd:int" minOccurs="0" /> - <xsd:element name="number_of_downloads" type="xsd:int" minOccurs="0" /> - <xsd:element name="is_shareable" type="xsd:int" minOccurs="0" /> - <xsd:element name="sample" type="typens:catalogProductDownloadableLinkAddSampleEntity" minOccurs="0" /> - <xsd:element name="type" type="xsd:string" minOccurs="0" /> - <xsd:element name="file" type="typens:catalogProductDownloadableLinkFileEntity" minOccurs="0" /> - <xsd:element name="link_url" type="xsd:string" minOccurs="0" /> - <xsd:element name="sample_url" type="xsd:string" minOccurs="0" /> - <xsd:element name="sort_order" type="xsd:int" minOccurs="0" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductDownloadableLinkFileInfoEntity"> - <xsd:sequence> - <xsd:element name="file" type="xsd:string" /> - <xsd:element name="name" type="xsd:string" /> - <xsd:element name="size" type="xsd:int" /> - <xsd:element name="status" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductDownloadableLinkFileInfoEntityArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:catalogProductDownloadableLinkFileInfoEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductDownloadableLinkEntity"> - <xsd:sequence> - <xsd:element name="link_id" type="xsd:string" /> - <xsd:element name="title" type="xsd:string" /> - <xsd:element name="price" type="xsd:string" /> - <xsd:element name="number_of_downloads" type="xsd:int" minOccurs="0" /> - <xsd:element name="is_unlimited" type="xsd:int" minOccurs="0" /> - <xsd:element name="is_shareable" type="xsd:int" /> - <xsd:element name="link_url" type="xsd:string" /> - <xsd:element name="link_type" type="xsd:string" /> - <xsd:element name="sample_file" type="xsd:string" minOccurs="0" /> - <xsd:element name="sample_url" type="xsd:string" minOccurs="0" /> - <xsd:element name="sample_type" type="xsd:string" /> - <xsd:element name="sort_order" type="xsd:int" /> - <xsd:element name="file_save" type="typens:catalogProductDownloadableLinkFileInfoEntityArray" minOccurs="0" /> - <xsd:element name="sample_file_save" type="typens:catalogProductDownloadableLinkFileInfoEntityArray" minOccurs="0" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductDownloadableLinkEntityArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:catalogProductDownloadableLinkEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductDownloadableLinkSampleEntity"> - <xsd:sequence> - <xsd:element name="sample_id" type="xsd:string" /> - <xsd:element name="product_id" type="xsd:string" /> - <xsd:element name="sample_file" type="xsd:string" minOccurs="0" /> - <xsd:element name="sample_url" type="xsd:string" minOccurs="0" /> - <xsd:element name="sample_type" type="xsd:string" /> - <xsd:element name="sort_order" type="xsd:string" /> - <xsd:element name="default_title" type="xsd:string" /> - <xsd:element name="store_title" type="xsd:string" /> - <xsd:element name="title" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductDownloadableLinkSampleEntityArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:catalogProductDownloadableLinkSampleEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductDownloadableLinkListEntity"> - <xsd:sequence> - <xsd:element name="links" type="typens:catalogProductDownloadableLinkEntityArray" /> - <xsd:element name="samples" type="typens:catalogProductDownloadableLinkSampleEntityArray" /> - </xsd:sequence> - </xsd:complexType> - - - <xsd:element name="catalogProductDownloadableLinkAddRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="productId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="resource" type="typens:catalogProductDownloadableLinkAddEntity" /> - <xsd:element minOccurs="1" maxOccurs="1" name="resourceType" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="identifierType" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductDownloadableLinkAddResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductDownloadableLinkListRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="productId" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="identifierType" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductDownloadableLinkListResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:catalogProductDownloadableLinkListEntity" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductDownloadableLinkRemoveRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="linkId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="resourceType" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductDownloadableLinkRemoveResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - </xsd:schema> - </wsdl:types> - <wsdl:message name="catalogProductDownloadableLinkAddRequest"> - <wsdl:part name="parameters" element="typens:catalogProductDownloadableLinkAddRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductDownloadableLinkAddResponse"> - <wsdl:part name="parameters" element="typens:catalogProductDownloadableLinkAddResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductDownloadableLinkListRequest"> - <wsdl:part name="parameters" element="typens:catalogProductDownloadableLinkListRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductDownloadableLinkListResponse"> - <wsdl:part name="parameters" element="typens:catalogProductDownloadableLinkListResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductDownloadableLinkRemoveRequest"> - <wsdl:part name="parameters" element="typens:catalogProductDownloadableLinkRemoveRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductDownloadableLinkRemoveResponse"> - <wsdl:part name="parameters" element="typens:catalogProductDownloadableLinkRemoveResponseParam" /> - </wsdl:message> - <wsdl:portType name="{{var wsdl.handler}}PortType"> - <wsdl:operation name="catalogProductDownloadableLinkAdd"> - <wsdl:documentation>Add links to downloadable product</wsdl:documentation> - <wsdl:input message="typens:catalogProductDownloadableLinkAddRequest" /> - <wsdl:output message="typens:catalogProductDownloadableLinkAddResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductDownloadableLinkList"> - <wsdl:documentation>Retrieve list of links and samples for downloadable product</wsdl:documentation> - <wsdl:input message="typens:catalogProductDownloadableLinkListRequest" /> - <wsdl:output message="typens:catalogProductDownloadableLinkListResponse" /> - </wsdl:operation> - <wsdl:operation name="catalogProductDownloadableLinkRemove"> - <wsdl:documentation>Remove links and samples from downloadable product</wsdl:documentation> - <wsdl:input message="typens:catalogProductDownloadableLinkRemoveRequest" /> - <wsdl:output message="typens:catalogProductDownloadableLinkRemoveResponse" /> - </wsdl:operation> - </wsdl:portType> - <wsdl:binding name="{{var wsdl.handler}}Binding" type="typens:{{var wsdl.handler}}PortType"> - <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" /> - <wsdl:operation name="catalogProductDownloadableLinkAdd"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductDownloadableLinkList"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="catalogProductDownloadableLinkRemove"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - </wsdl:binding> -</wsdl:definitions> diff --git a/app/code/core/Mage/Eav/Model/Attribute.php b/app/code/core/Mage/Eav/Model/Attribute.php index b4041324d405e40346b392ca348801dcef156d92..4373a527d8bd8d8e86f398e3c4d2e87164280542 100644 --- a/app/code/core/Mage/Eav/Model/Attribute.php +++ b/app/code/core/Mage/Eav/Model/Attribute.php @@ -27,6 +27,9 @@ /** * EAV attribute resource model (Using Forms) * + * @method Mage_Eav_Model_Attribute_Data_Abstract|null getDataModel() Get data model linked to attribute or null. + * @method string|null getFrontendInput() Get attribute type for user interface form or null + * * @category Mage * @package Mage_Eav * @author Magento Core Team <core@magentocommerce.com> diff --git a/app/code/core/Mage/Eav/Model/Entity/Attribute.php b/app/code/core/Mage/Eav/Model/Entity/Attribute.php index 8cb9b1c13d010a8be3230a75e25d5c1da83abef6..aa1a32b32ce82f0cbaf81eb1b552559955dce883 100644 --- a/app/code/core/Mage/Eav/Model/Entity/Attribute.php +++ b/app/code/core/Mage/Eav/Model/Entity/Attribute.php @@ -114,6 +114,25 @@ class Mage_Eav_Model_Entity_Attribute extends Mage_Eav_Model_Entity_Attribute_Ab return $this->_getResource()->deleteEntity($this); } + /** + * Load entity_attribute_id into $this by $this->attribute_set_id + * + * @return Mage_Core_Model_Abstract + */ + public function loadEntityAttributeIdBySet() + { + // load attributes collection filtered by attribute_id and attribute_set_id + $filteredAttributes = $this->getResourceCollection() + ->setAttributeSetFilter($this->getAttributeSetId()) + ->addFieldToFilter('entity_attribute.attribute_id', $this->getId()) + ->load(); + if (count($filteredAttributes) > 0) { + // getFirstItem() can be used as we can have one or zero records in the collection + $this->setEntityAttributeId($filteredAttributes->getFirstItem()->getEntityAttributeId()); + } + return $this; + } + /** * Prepare data for save * diff --git a/app/code/core/Mage/Eav/Model/Form.php b/app/code/core/Mage/Eav/Model/Form.php index 1bc6d3bfbea1544d665b1f89cdbcdb8e6f5f10cf..36c4ca365ac456ac94cfbc6a8512b3a75defbc55 100644 --- a/app/code/core/Mage/Eav/Model/Form.php +++ b/app/code/core/Mage/Eav/Model/Form.php @@ -24,7 +24,6 @@ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ - /** * EAV Entity Form Model * @@ -35,7 +34,7 @@ abstract class Mage_Eav_Model_Form { /** - * Current module pathname + * Current module path name * * @var string */ @@ -97,6 +96,13 @@ abstract class Mage_Eav_Model_Form */ protected $_userAttributes; + /** + * Array of form attributes that is not omitted + * + * @var array + */ + protected $_allowedAttributes = null; + /** * Is AJAX request flag * @@ -111,6 +117,11 @@ abstract class Mage_Eav_Model_Form */ protected $_ignoreInvisible = true; + /** + * @var Magento_Validator + */ + protected $_validator = null; + /** * Checks correct module choice * @@ -136,6 +147,20 @@ abstract class Mage_Eav_Model_Form return Mage::getResourceModel($this->_moduleName . '_Model_Resource_Form_Attribute_Collection'); } + /** + * Get EAV Entity Form Attribute Collection with applied filters + * + * @return Mage_Eav_Model_Resource_Form_Attribute_Collection|mixed + */ + protected function _getFilteredFormAttributeCollection() + { + return $this->_getFormAttributeCollection() + ->setStore($this->getStore()) + ->setEntityType($this->getEntityType()) + ->addFormCodeFilter($this->getFormCode()) + ->setSortOrder(); + } + /** * Set current store * @@ -250,24 +275,19 @@ abstract class Mage_Eav_Model_Form public function getAttributes() { if (is_null($this->_attributes)) { - /* @var $collection Mage_Eav_Model_Resource_Form_Attribute_Collection */ - $collection = $this->_getFormAttributeCollection(); - - $collection->setStore($this->getStore()) - ->setEntityType($this->getEntityType()) - ->addFormCodeFilter($this->getFormCode()) - ->setSortOrder(); - $this->_attributes = array(); $this->_userAttributes = array(); - foreach ($collection as $attribute) { - /* @var $attribute Mage_Eav_Model_Entity_Attribute */ + /** @var $attribute Mage_Eav_Model_Attribute */ + foreach ($this->_getFilteredFormAttributeCollection() as $attribute) { $this->_attributes[$attribute->getAttributeCode()] = $attribute; if ($attribute->getIsUserDefined()) { $this->_userAttributes[$attribute->getAttributeCode()] = $attribute; } else { $this->_systemAttributes[$attribute->getAttributeCode()] = $attribute; } + if (!$this->_isAttributeOmitted($attribute)) { + $this->_allowedAttributes[$attribute->getAttributeCode()] = $attribute; + } } } return $this->_attributes; @@ -277,7 +297,7 @@ abstract class Mage_Eav_Model_Form * Return attribute instance by code or false * * @param string $attributeCode - * @return Mage_Eav_Model_Entity_Attribute|false + * @return Mage_Eav_Model_Entity_Attribute|bool */ public function getAttribute($attributeCode) { @@ -316,6 +336,20 @@ abstract class Mage_Eav_Model_Form return $this->_systemAttributes; } + /** + * Get not omitted attributes + * + * @return array + */ + public function getAllowedAttributes() + { + if (is_null($this->_allowedAttributes)) { + // load attributes + $this->getAttributes(); + } + return $this->_allowedAttributes; + } + /** * Return attribute data model by attribute * @@ -357,10 +391,8 @@ abstract class Mage_Eav_Model_Form public function extractData(Zend_Controller_Request_Http $request, $scope = null, $scopeOnly = true) { $data = array(); - foreach ($this->getAttributes() as $attribute) { - if ($this->_isAttributeOmitted($attribute)) { - continue; - } + /** @var $attribute Mage_Eav_Model_Attribute */ + foreach ($this->getAllowedAttributes() as $attribute) { $dataModel = $this->_getAttributeDataModel($attribute); $dataModel->setRequestScope($scope); $dataModel->setRequestScopeOnly($scopeOnly); @@ -369,6 +401,32 @@ abstract class Mage_Eav_Model_Form return $data; } + /** + * Get validator + * + * @param array $data + * @return Magento_Validator + */ + protected function _getValidator(array $data) + { + if (is_null($this->_validator)) { + $configFiles = Mage::getConfig()->getModuleConfigurationFiles('validation.xml'); + $validatorFactory = new Magento_Validator_Config($configFiles); + $builder = $validatorFactory->createValidatorBuilder('eav_entity', 'form'); + + $builder->addConfiguration('eav_data_validator', array( + 'method' => 'setAttributes', + 'arguments' => array($this->getAllowedAttributes()) + )); + $builder->addConfiguration('eav_data_validator', array( + 'method' => 'setData', + 'arguments' => array($data) + )); + $this->_validator = $builder->createValidator(); + } + return $this->_validator; + } + /** * Validate data array and return true or array of errors * @@ -377,27 +435,15 @@ abstract class Mage_Eav_Model_Form */ public function validateData(array $data) { - $errors = array(); - foreach ($this->getAttributes() as $attribute) { - if ($this->_isAttributeOmitted($attribute)) { - continue; + $validator = $this->_getValidator($data); + if (!$validator->isValid($this->getEntity())) { + $messages = array(); + foreach ($validator->getMessages() as $errorMessages) { + $messages = array_merge($messages, (array)$errorMessages); } - $dataModel = $this->_getAttributeDataModel($attribute); - $dataModel->setExtractedData($data); - if (!isset($data[$attribute->getAttributeCode()])) { - $data[$attribute->getAttributeCode()] = null; - } - $result = $dataModel->validateValue($data[$attribute->getAttributeCode()]); - if ($result !== true) { - $errors = array_merge($errors, $result); - } - } - - if (count($errors) == 0) { - return true; + return $messages; } - - return $errors; + return true; } /** @@ -408,10 +454,8 @@ abstract class Mage_Eav_Model_Form */ public function compactData(array $data) { - foreach ($this->getAttributes() as $attribute) { - if ($this->_isAttributeOmitted($attribute)) { - continue; - } + /** @var $attribute Mage_Eav_Model_Attribute */ + foreach ($this->getAllowedAttributes() as $attribute) { $dataModel = $this->_getAttributeDataModel($attribute); $dataModel->setExtractedData($data); if (!isset($data[$attribute->getAttributeCode()])) { @@ -431,10 +475,8 @@ abstract class Mage_Eav_Model_Form */ public function restoreData(array $data) { - foreach ($this->getAttributes() as $attribute) { - if ($this->_isAttributeOmitted($attribute)) { - continue; - } + /** @var $attribute Mage_Eav_Model_Attribute */ + foreach ($this->getAllowedAttributes() as $attribute) { $dataModel = $this->_getAttributeDataModel($attribute); $dataModel->setExtractedData($data); if (!isset($data[$attribute->getAttributeCode()])) { @@ -446,7 +488,7 @@ abstract class Mage_Eav_Model_Form } /** - * Return array of entity formated values + * Return array of entity formatted values * * @param string $format * @return array @@ -454,10 +496,8 @@ abstract class Mage_Eav_Model_Form public function outputData($format = Mage_Eav_Model_Attribute_Data::OUTPUT_FORMAT_TEXT) { $data = array(); - foreach ($this->getAttributes() as $attribute) { - if ($this->_isAttributeOmitted($attribute)) { - continue; - } + /** @var $attribute Mage_Eav_Model_Attribute */ + foreach ($this->getAllowedAttributes() as $attribute) { $dataModel = $this->_getAttributeDataModel($attribute); $dataModel->setExtractedData($data); $data[$attribute->getAttributeCode()] = $dataModel->outputValue($format); @@ -472,10 +512,8 @@ abstract class Mage_Eav_Model_Form */ public function resetEntityData() { - foreach ($this->getAttributes() as $attribute) { - if ($this->_isAttributeOmitted($attribute)) { - continue; - } + /** @var $attribute Mage_Eav_Model_Attribute */ + foreach ($this->getAllowedAttributes() as $attribute) { $value = $this->getEntity()->getOrigData($attribute->getAttributeCode()); $this->getEntity()->setData($attribute->getAttributeCode(), $value); } @@ -512,6 +550,7 @@ abstract class Mage_Eav_Model_Form public function initDefaultValues() { if (!$this->getEntity()->getId()) { + /** @var $attribute Mage_Eav_Model_Attribute */ foreach ($this->getAttributes() as $attribute) { $default = $attribute->getDefaultValue(); if ($default != '') { diff --git a/app/code/core/Mage/Eav/Model/Resource/Attribute/Collection.php b/app/code/core/Mage/Eav/Model/Resource/Attribute/Collection.php index 8dfca8d581ad91b7af63c5e242652c26a5c1bb75..539e7b9762b757c9bec7a3bc046fd58fc9c96fac 100755 --- a/app/code/core/Mage/Eav/Model/Resource/Attribute/Collection.php +++ b/app/code/core/Mage/Eav/Model/Resource/Attribute/Collection.php @@ -226,8 +226,11 @@ abstract class Mage_Eav_Model_Resource_Attribute_Collection */ public function addSystemHiddenFilter() { - $field = '(CASE WHEN additional_table.is_system = 1 AND additional_table.is_visible = 0 THEN 1 ELSE 0 END)'; - return $this->addFieldToFilter($field, 0); + $connection = $this->getConnection(); + $expression = $connection->getCheckSql('additional_table.is_system = 1 AND additional_table.is_visible = 0', + '1', '0'); + $this->getSelect()->where($connection->quoteInto($expression . ' = ?', 0)); + return $this; } /** diff --git a/app/code/core/Mage/Eav/Model/Validator/Attribute/Backend.php b/app/code/core/Mage/Eav/Model/Validator/Attribute/Backend.php new file mode 100644 index 0000000000000000000000000000000000000000..92d14e062d836f2f7adfd6720ff8f01f26d3108c --- /dev/null +++ b/app/code/core/Mage/Eav/Model/Validator/Attribute/Backend.php @@ -0,0 +1,92 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_Eav + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Validation EAV entity via EAV attributes' backend models + * + * @category Mage + * @package Mage_Eav + * @author Magento Core Team <core@magentocommerce.com> + */ +class Mage_Eav_Model_Validator_Attribute_Backend extends Magento_Validator_ValidatorAbstract +{ + /** + * @var array + */ + protected $_messages; + + /** + * Returns true if and only if $value meets the validation requirements. + * + * @param Mage_Core_Model_Abstract $entity + * @return boolean + * @throws InvalidArgumentException + */ + public function isValid($entity) + { + $this->_messages = array(); + if (!($entity instanceof Mage_Core_Model_Abstract)) { + throw new InvalidArgumentException('Model must be extended from Mage_Core_Model_Abstract'); + } + /** @var Mage_Eav_Model_Entity_Abstract $resource */ + $resource = $entity->getResource(); + if (!($resource instanceof Mage_Eav_Model_Entity_Abstract)) { + throw new InvalidArgumentException('Model resource must be extended from Mage_Eav_Model_Entity_Abstract'); + } + $resource->loadAllAttributes($entity); + $attributes = $resource->getAttributesByCode(); + /** @var Mage_Eav_Model_Entity_Attribute $attribute */ + foreach ($attributes as $attribute) { + $backend = $attribute->getBackend(); + if (!method_exists($backend, 'validate')) { + continue; + } + try { + $result = $backend->validate($entity); + if (false === $result) { + $this->_messages[$attribute->getAttributeCode()][] = + Mage::helper('Mage_Eav_Helper_Data')->__('The value of attribute "%s" is invalid', + $attribute->getAttributeCode()); + } elseif (is_string($result)) { + $this->_messages[$attribute->getAttributeCode()][] = $result; + } + } catch (Mage_Core_Exception $e) { + $this->_messages[$attribute->getAttributeCode()][] = $e->getMessage(); + } + } + return 0 == count($this->_messages); + } + + /** + * Returns an array of messages that explain why the most recent isValid() call returned false. + * + * @return array + */ + public function getMessages() + { + return $this->_messages; + } +} diff --git a/app/code/core/Mage/Eav/Model/Validator/Attribute/Data.php b/app/code/core/Mage/Eav/Model/Validator/Attribute/Data.php new file mode 100644 index 0000000000000000000000000000000000000000..e26190cc69a9d5781ee877eaeb0764f9abdaf5d9 --- /dev/null +++ b/app/code/core/Mage/Eav/Model/Validator/Attribute/Data.php @@ -0,0 +1,248 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_Eav + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * EAV attribute data validator + * + * @category Mage + * @package Mage_Eav + * @author Magento Core Team <core@magentocommerce.com> + */ +class Mage_Eav_Model_Validator_Attribute_Data extends Magento_Validator_ValidatorAbstract +{ + /** + * @var array + */ + protected $_messages = array(); + + /** + * @var array + */ + protected $_attributes = array(); + + /** + * @var array + */ + protected $_attributesWhiteList = array(); + + /** + * @var array + */ + protected $_attributesBlackList = array(); + + /** + * @var array + */ + protected $_data = array(); + + /** + * @var Mage_Eav_Model_Attribute_Data + */ + protected $_dataModelFactory; + + /** + * Set list of attributes for validation in isValid method. + * + * @param Mage_Eav_Model_Attribute[] $attributes + * @return Mage_Eav_Model_Validator_Attribute_Data + */ + public function setAttributes(array $attributes) + { + $this->_attributes = $attributes; + return $this; + } + + /** + * Set codes of attributes that should be filtered in validation process. + * + * All attributes not in this list 't be involved in validation. + * + * @param array $attributesCodes + * @return Mage_Eav_Model_Validator_Attribute_Data + */ + public function setAttributesWhiteList(array $attributesCodes) + { + $this->_attributesWhiteList = $attributesCodes; + return $this; + } + + /** + * Set codes of attributes that should be excluded in validation process. + * + * All attributes in this list won't be involved in validation. + * + * @param array $attributesCodes + * @return Mage_Eav_Model_Validator_Attribute_Data + */ + public function setAttributesBlackList(array $attributesCodes) + { + $this->_attributesBlackList = $attributesCodes; + return $this; + } + + /** + * Set data for validation in isValid method. + * + * @param array $data + * @return Mage_Eav_Model_Validator_Attribute_Data + */ + public function setData(array $data) + { + $this->_data = $data; + return $this; + } + + /** + * Validate EAV model attributes with data models + * + * @param Mage_Core_Model_Abstract $entity + * @return bool + */ + public function isValid($entity) + { + /** @var $attributes Mage_Eav_Model_Attribute[] */ + $attributes = $this->_getAttributes($entity); + + $data = array(); + if ($this->_data) { + $data = $this->_data; + } elseif ($entity instanceof Varien_Object) { + $data = $entity->getData(); + } + + foreach ($attributes as $attribute) { + $attributeCode = $attribute->getAttributeCode(); + if (!$attribute->getDataModel() && !$attribute->getFrontendInput()) { + continue; + } + $dataModel = $this->getAttributeDataModelFactory()->factory($attribute, $entity); + $dataModel->setExtractedData($data); + if (!isset($data[$attributeCode])) { + $data[$attributeCode] = null; + } + $result = $dataModel->validateValue($data[$attributeCode]); + if (true !== $result) { + $this->_addErrorMessages($attributeCode, (array)$result); + } + } + return count($this->_messages) == 0; + } + + /** + * Get attributes involved in validation. + * + * This method return specified $_attributes if they defined by setAttributes method, otherwise if $entity + * is EAV-model it returns it's all available attributes, otherwise it return empty array. + * + * @param mixed $entity + * @return array + */ + protected function _getAttributes($entity) + { + /** @var Mage_Customer_Model_Attribute[] $attributes */ + $attributes = array(); + + if ($this->_attributes) { + $attributes = $this->_attributes; + } elseif ($entity instanceof Mage_Core_Model_Abstract + && $entity->getResource() instanceof Mage_Eav_Model_Entity_Abstract + ) { // $entity is EAV-model + $attributes = $entity->getEntityType()->getAttributeCollection()->getItems(); + } + + $attributesByCode = array(); + $attributesCodes = array(); + foreach ($attributes as $attribute) { + $attributeCode = $attribute->getAttributeCode(); + $attributesByCode[$attributeCode] = $attribute; + $attributesCodes[] = $attributeCode; + } + + $ignoreAttributes = $this->_attributesBlackList; + if ($this->_attributesWhiteList) { + $ignoreAttributes = array_merge( + $ignoreAttributes, + array_diff($attributesCodes, $this->_attributesWhiteList) + ); + } + + foreach ($ignoreAttributes as $attributeCode) { + unset($attributesByCode[$attributeCode]); + } + + return $attributesByCode; + } + + /** + * Get factory object for creating Attribute Data Model + * + * @return Mage_Eav_Model_Attribute_Data + */ + public function getAttributeDataModelFactory() + { + if (!$this->_dataModelFactory) { + $this->_dataModelFactory = new Mage_Eav_Model_Attribute_Data; + } + return $this->_dataModelFactory; + } + + /** + * Set factory object for creating Attribute Data Model + * + * @param Mage_Eav_Model_Attribute_Data $factory + * @return Mage_Eav_Model_Validator_Attribute_Data + */ + public function setAttributeDataModelFactory($factory) + { + $this->_dataModelFactory = $factory; + return $this; + } + + /** + * Add error messages + * + * @param string $code + * @param array $messages + */ + protected function _addErrorMessages($code, array $messages) + { + if (!array_key_exists($code, $this->_messages)) { + $this->_messages[$code] = $messages; + } else { + $this->_messages[$code] = array_merge($this->_messages[$code], $messages); + } + } + + /** + * Get validation messages + * + * @return array + */ + public function getMessages() + { + return $this->_messages; + } +} diff --git a/app/code/core/Mage/Api2/etc/adminhtml/menu.xml b/app/code/core/Mage/Eav/etc/validation.xml similarity index 60% rename from app/code/core/Mage/Api2/etc/adminhtml/menu.xml rename to app/code/core/Mage/Eav/etc/validation.xml index bd0a5ead5b7049ce841a618d24e674802ebe0da0..13572efe140262513c6d1a6b204ad3cb8d3725fe 100644 --- a/app/code/core/Mage/Api2/etc/adminhtml/menu.xml +++ b/app/code/core/Mage/Eav/etc/validation.xml @@ -1,4 +1,4 @@ -<?xml version="1.0"?> +<?xml version="1.0" encoding="UTF-8"?> <!-- /** * Magento @@ -20,14 +20,26 @@ * needs please refer to http://www.magentocommerce.com for more information. * * @category Mage - * @package Mage_Api2 + * @package Mage_Eav * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) */ --> -<config> - <menu> - <add id="Mage_Api2::system_api_rest_roles" title="REST - Roles" module="Mage_Api2" sortOrder="30" parent="Mage_Api::system_api" action="adminhtml/api2_role" resource="Mage_Api2::rest_roles"/> - <add id="Mage_Api2::system_api_rest_attributes" title="REST - Attributes" module="Mage_Api2" sortOrder="40" parent="Mage_Api::system_api" action="adminhtml/api2_attribute" resource="Mage_Api2::rest_attributes"/> - </menu> -</config> +<validation> + <entity name="eav_entity"> + <rules> + <rule name="eav_attribute_data"> + <entity_constraints> + <constraint alias="eav_data_validator" class="Mage_Eav_Model_Validator_Attribute_Data" /> + </entity_constraints> + </rule> + </rules> + <groups> + <group name="form"> + <uses> + <use rule="eav_attribute_data"/> + </uses> + </group> + </groups> + </entity> +</validation> diff --git a/app/code/core/Mage/GiftMessage/Model/Api.php b/app/code/core/Mage/GiftMessage/Model/Api.php deleted file mode 100644 index 62c5cd4113bab64054542c511fb875dbdbb40155..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/GiftMessage/Model/Api.php +++ /dev/null @@ -1,185 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_GiftMessage - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * GiftMessage api - * - * @category Mage - * @package Mage_GiftMessage - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_GiftMessage_Model_Api extends Mage_Checkout_Model_Api_Resource_Product -{ - /** - * Return an Array of attributes. - * - * @param Array $obj - * @return Array - */ - protected function _prepareData($arr) - { - if (is_array($arr)) { - return $arr; - } - return array(); - } - - /** - * Raise event for setting a giftMessage. - * - * @param String $entityId - * @param Mage_Core_Controller_Request_Http $request - * @param Mage_Sales_Model_Quote $quote - * @return AssociativeArray - */ - protected function _setGiftMessage($entityId, $request, $quote) - { - - /** - * Below code will catch exceptions only in DeveloperMode - * @see Mage_Core_Model_App::_callObserverMethod($object, $method, $observer) - * And result of Mage::dispatchEvent will always return an Object of Mage_Core_Model_App. - */ - try { - Mage::dispatchEvent( - 'checkout_controller_onepage_save_shipping_method', - array('request' => $request, 'quote' => $quote) - ); - return array('entityId' => $entityId, 'result' => true, 'error' => ''); - } catch (Exception $e) { - return array('entityId' => $entityId, 'result' => false, 'error' => $e->getMessage()); - } - } - - /** - * Set GiftMessage for a Quote. - * - * @param String $quoteId - * @param AssociativeArray $giftMessage - * @param String $store - * @return AssociativeArray - */ - public function setForQuote($quoteId, $giftMessage, $store = null) - { - /** @var $quote Mage_Sales_Model_Quote */ - $quote = $this->_getQuote($quoteId, $store); - - $giftMessage = $this->_prepareData($giftMessage); - if (empty($giftMessage)) { - $this->_fault('giftmessage_invalid_data'); - } - - $giftMessage['type'] = 'quote'; - $giftMessages = array($quoteId => $giftMessage); - $request = new Mage_Core_Controller_Request_Http(); - $request->setParam("giftmessage", $giftMessages); - - return $this->_setGiftMessage($quote->getId(), $request, $quote); - } - - /** - * Set a GiftMessage to QuoteItem by product - * - * @param String $quoteId - * @param Array $productsAndMessages - * @param String $store - * @return array - */ - public function setForQuoteProduct($quoteId, $productsAndMessages, $store = null) - { - /** @var $quote Mage_Sales_Model_Quote */ - $quote = $this->_getQuote($quoteId, $store); - - $productsAndMessages = $this->_prepareData($productsAndMessages); - if (empty($productsAndMessages)) { - $this->_fault('invalid_data'); - } - - if (count($productsAndMessages) == 2 - && isset($productsAndMessages['product']) - && isset($productsAndMessages['message'])) { - $productsAndMessages = array($productsAndMessages); - } - - $results = array(); - foreach ($productsAndMessages as $productAndMessage) { - if (isset($productAndMessage['product']) && isset($productAndMessage['message'])) { - $product = $this->_prepareData($productAndMessage['product']); - if (empty($product)) { - $this->_fault('product_invalid_data'); - } - $message = $this->_prepareData($productAndMessage['message']); - if (empty($message)) { - $this->_fault('giftmessage_invalid_data'); - } - - if (isset($product['product_id'])) { - $productByItem = $this->_getProduct($product['product_id'], $store, "id"); - } elseif (isset($product['sku'])) { - $productByItem = $this->_getProduct($product['sku'], $store, "sku"); - } else { - continue; - } - - $productObj = $this->_getProductRequest($product); - $quoteItem = $this->_getQuoteItemByProduct($quote, $productByItem, $productObj); - $results[] = $this->setForQuoteItem($quoteItem->getId(), $message, $store); - } - } - - return $results; - } - - /** - * Set GiftMessage for a QuoteItem by its Id. - * - * @param String $quoteItemId - * @param AssociativeArray $giftMessage - * @param String $store - * @return AssociativeArray - */ - public function setForQuoteItem($quoteItemId, $giftMessage, $store = null) - { - /** @var $quote Mage_Sales_Model_Quote_Item */ - $quoteItem = Mage::getModel('Mage_Sales_Model_Quote_Item')->load($quoteItemId); - if (is_null($quoteItem->getId())) { - $this->_fault("quote_item_not_exists"); - } - - /** @var $quote Mage_Sales_Model_Quote */ - $quote = $this->_getQuote($quoteItem->getQuoteId(), $store); - - $giftMessage = $this->_prepareData($giftMessage); - $giftMessage['type'] = 'quote_item'; - - $giftMessages = array($quoteItem->getId() => $giftMessage); - - $request = new Mage_Core_Controller_Request_Http(); - $request->setParam("giftmessage", $giftMessages); - - return $this->_setGiftMessage($quoteItemId, $request, $quote); - } -} diff --git a/app/code/core/Mage/GiftMessage/Model/Api/V2.php b/app/code/core/Mage/GiftMessage/Model/Api/V2.php deleted file mode 100644 index b03a60a072bbf1fd324705ea51f59b1cf344647b..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/GiftMessage/Model/Api/V2.php +++ /dev/null @@ -1,105 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_GiftMessage - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * GiftMessage api - * - * @category Mage - * @package Mage_GiftMessage - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_GiftMessage_Model_Api_V2 extends Mage_GiftMessage_Model_Api -{ - - /** - * Return an Array of Object attributes. - * - * @param Mixed $data - * @return Array - */ - protected function _prepareData($data){ - if (is_object($data)) { - $arr = get_object_vars($data); - foreach ($arr as $key => $value) { - $assocArr = array(); - if (is_array($value)) { - foreach ($value as $v) { - if (is_object($v) && count(get_object_vars($v))==2 - && isset($v->key) && isset($v->value)) { - $assocArr[$v->key] = $v->value; - } - } - } - if (!empty($assocArr)) { - $arr[$key] = $assocArr; - } - } - $arr = $this->_prepareData($arr); - return parent::_prepareData($arr); - } - if (is_array($data)) { - foreach ($data as $key => $value) { - if (is_object($value) || is_array($value)) { - $data[$key] = $this->_prepareData($value); - } else { - $data[$key] = $value; - } - } - return parent::_prepareData($data); - } - return $data; - } - - /** - * Raise event for setting a giftMessage. - * - * @param String $entityId - * @param Mage_Core_Controller_Request_Http $request - * @param Mage_Sales_Model_Quote $quote - * @return stdClass - */ - protected function _setGiftMessage($entityId, $request, $quote) { - $response = new stdClass(); - $response->entityId = $entityId; - - /** - * Below code will catch exceptions only in DeveloperMode - * @see Mage_Core_Model_App::_callObserverMethod($object, $method, $observer) - * And result of Mage::dispatchEvent will always return an Object of Mage_Core_Model_App. - */ - try { - Mage::dispatchEvent('checkout_controller_onepage_save_shipping_method', array('request'=>$request, 'quote'=>$quote)); - $response->result = true; - $response->error = ''; - } catch (Exception $e) { - $response->result = false; - $response->error = $e->getMessage(); - } - return $response; - } - -} -?> diff --git a/app/code/core/Mage/GiftMessage/etc/api.xml b/app/code/core/Mage/GiftMessage/etc/api.xml deleted file mode 100644 index 638d29ec6ef0161a2e4dc25fc52f241ac6852841..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/GiftMessage/etc/api.xml +++ /dev/null @@ -1,92 +0,0 @@ -<?xml version="1.0"?> -<!-- -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Academic Free License (AFL 3.0) - * that is bundled with this package in the file LICENSE_AFL.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/afl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_GiftMessage - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) - */ ---> -<config> - <api> - <resources> - <giftmessage translate="title" module="Mage_GiftMessage"> - <model>Mage_GiftMessage_Model_Api</model> - <title>Gift Message API</title> - <acl>giftmessage/set</acl> - <methods> - <setForQuote translate="title" module="Mage_GiftMessage"> - <title>Add gift message for shopping cart</title> - <method>setForQuote</method> - <acl>giftmessage/set</acl> - </setForQuote> - <setForQuoteItem translate="title" module="Mage_GiftMessage"> - <title>Add gift messages for quote item of shopping cart</title> - <method>setForQuoteItem</method> - <acl>giftmessage/set</acl> - </setForQuoteItem> - <setForQuoteProduct translate="title" module="Mage_GiftMessage"> - <title>Add gift messages to products of shopping cart</title> - <method>setForQuoteProduct</method> - <acl>giftmessage/set</acl> - </setForQuoteProduct> - </methods> - <faults module="Mage_GiftMessage"> - <store_not_exists> - <code>1001</code> - <message>Can not make operation because store is not exists</message> - </store_not_exists> - <quote_not_exists> - <code>1002</code> - <message>Can not make operation because quote is not exists</message> - </quote_not_exists> - <giftmessage_invalid_data> - <code>1101</code> - <message>Gift message data is not valid.</message> - </giftmessage_invalid_data> - <product_invalid_data> - <code>1102</code> - <message>Product's data is not valid.</message> - </product_invalid_data> - <quote_item_not_exists> - <code>1103</code> - <message>Quote item is not exists</message> - </quote_item_not_exists> - </faults> - </giftmessage> - </resources> - <acl> - <resources> - <giftmessage translate="title" module="Mage_Checkout"> - <title>Gift Message</title> - <set translate="title" module="Mage_Checkout"> - <title>Add gift messages to shopping cart</title> - </set> - </giftmessage> - </resources> - </acl> - <v2> - <resources_function_prefix> - <giftmessage>giftMessage</giftmessage> - </resources_function_prefix> - </v2> - </api> -</config> diff --git a/app/code/core/Mage/GiftMessage/etc/wsdl.xml b/app/code/core/Mage/GiftMessage/etc/wsdl.xml deleted file mode 100644 index 9fd677d2cac069bc12d3fb493c5a14cf52bc143e..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/GiftMessage/etc/wsdl.xml +++ /dev/null @@ -1,123 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<definitions xmlns:typens="urn:{{var wsdl.name}}" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" - xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns="http://schemas.xmlsoap.org/wsdl/" - name="{{var wsdl.name}}" targetNamespace="urn:{{var wsdl.name}}"> - <types> - <schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:Magento"> - <import namespace="http://schemas.xmlsoap.org/soap/encoding/" schemaLocation="http://schemas.xmlsoap.org/soap/encoding/" /> - <complexType name="giftMessageEntity"> - <sequence> - <element name="from" type="xsd:string" minOccurs="0" /> - <element name="to" type="xsd:string" minOccurs="0" /> - <element name="message" type="xsd:string" minOccurs="0" /> - </sequence> - </complexType> - <complexType name="giftMessageResponse"> - <sequence> - <element name="entityId" type="xsd:string" minOccurs="0" /> - <element name="result" type="xsd:boolean" minOccurs="0" /> - <element name="error" type="xsd:string" minOccurs="0" /> - </sequence> - </complexType> - <complexType name="giftMessageResponseArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:giftMessageResponse[]" /> - </restriction> - </complexContent> - </complexType> - <complexType name="giftMessageAssociativeProductsEntity"> - <sequence> - <element name="product" type="typens:shoppingCartProductEntity" /> - <element name="message" type="typens:giftMessageEntity" /> - </sequence> - </complexType> - <complexType name="giftMessageAssociativeProductsEntityArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:giftMessageAssociativeProductsEntity[]" /> - </restriction> - </complexContent> - </complexType> - </schema> - </types> - <message name="giftMessageForQuoteRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="quoteId" type="xsd:string" /> - <part name="giftMessage" type="typens:giftMessageEntity" /> - <part name="storeId" type="xsd:string" /> - </message> - <message name="giftMessageForQuoteResponse"> - <part name="result" type="typens:giftMessageResponse" /> - </message> - <message name="giftMessageForQuoteItemRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="quoteItemId" type="xsd:string" /> - <part name="giftMessage" type="typens:giftMessageEntity" /> - <part name="storeId" type="xsd:string" /> - </message> - <message name="giftMessageForQuoteItemResponse"> - <part name="result" type="typens:giftMessageResponse" /> - </message> - <message name="giftMessageForQuoteProductRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="quoteId" type="xsd:string" /> - <part name="productsAndMessages" type="typens:giftMessageAssociativeProductsEntityArray" /> - <part name="storeId" type="xsd:string" /> - </message> - <message name="giftMessageForQuoteProductResponse"> - <part name="result" type="typens:giftMessageResponseArray" /> - </message> - <portType name="{{var wsdl.handler}}PortType"> - <operation name="giftMessageSetForQuote"> - <documentation>Set a gift message to the cart</documentation> - <input message="typens:giftMessageForQuoteRequest" /> - <output message="typens:giftMessageForQuoteResponse" /> - </operation> - <operation name="giftMessageSetForQuoteItem"> - <documentation>Setting a gift messages to the quote item</documentation> - <input message="typens:giftMessageForQuoteItemRequest" /> - <output message="typens:giftMessageForQuoteItemResponse" /> - </operation> - <operation name="giftMessageSetForQuoteProduct"> - <documentation>Setting a gift messages to the quote items by products</documentation> - <input message="typens:giftMessageForQuoteProductRequest" /> - <output message="typens:giftMessageForQuoteProductResponse" /> - </operation> - </portType> - <binding name="{{var wsdl.handler}}Binding" type="typens:{{var wsdl.handler}}PortType"> - <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" /> - <operation name="giftMessageSetForQuote"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="giftMessageSetForQuoteItem"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="giftMessageSetForQuoteProduct"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - </binding> - <service name="{{var wsdl.name}}Service"> - <port name="{{var wsdl.handler}}Port" binding="typens:{{var wsdl.handler}}Binding"> - <soap:address location="{{var wsdl.url}}" /> - </port> - </service> -</definitions> diff --git a/app/code/core/Mage/GiftMessage/etc/wsi.xml b/app/code/core/Mage/GiftMessage/etc/wsi.xml deleted file mode 100644 index 155d52646b593e66d09b48c8291db937494ecda4..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/GiftMessage/etc/wsi.xml +++ /dev/null @@ -1,161 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<wsdl:definitions xmlns:typens="urn:{{var wsdl.name}}" - xmlns:xsd="http://www.w3.org/2001/XMLSchema" - xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" - xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" - xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" - name="{{var wsdl.name}}" - targetNamespace="urn:{{var wsdl.name}}"> - <wsdl:types> - <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:{{var wsdl.name}}"> - <xsd:complexType name="giftMessageEntity"> - <xsd:sequence> - <xsd:element name="from" type="xsd:string" minOccurs="0" /> - <xsd:element name="to" type="xsd:string" minOccurs="0" /> - <xsd:element name="message" type="xsd:string" minOccurs="0" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="giftMessageResponse"> - <xsd:sequence> - <xsd:element name="entityId" type="xsd:string" minOccurs="0" /> - <xsd:element name="result" type="xsd:boolean" minOccurs="0" /> - <xsd:element name="error" type="xsd:string" minOccurs="0" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="giftMessageResponseArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:giftMessageResponse" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="giftMessageAssociativeProductsEntity"> - <xsd:sequence> - <xsd:element name="product" type="typens:shoppingCartProductEntity" /> - <xsd:element name="message" type="typens:giftMessageEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="giftMessageAssociativeProductsEntityArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:giftMessageAssociativeProductsEntity" /> - </xsd:sequence> - </xsd:complexType> - - - <xsd:element name="giftMessageForQuoteRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="quoteId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="giftMessage" type="typens:giftMessageEntity" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="giftMessageForQuoteResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:giftMessageResponse" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="giftMessageForQuoteItemRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="quoteItemId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="giftMessage" type="typens:giftMessageEntity" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="giftMessageForQuoteItemResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:giftMessageResponse" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="giftMessageForQuoteProductRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="quoteId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="productsAndMessages" type="typens:giftMessageAssociativeProductsEntityArray" /> - <xsd:element minOccurs="0" maxOccurs="1" name="store" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="giftMessageForQuoteProductResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:giftMessageResponseArray" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - </xsd:schema> - </wsdl:types> - <wsdl:message name="giftMessageForQuoteRequest"> - <wsdl:part name="parameters" element="typens:giftMessageForQuoteRequestParam" /> - </wsdl:message> - <wsdl:message name="giftMessageForQuoteResponse"> - <wsdl:part name="parameters" element="typens:giftMessageForQuoteResponseParam" /> - </wsdl:message> - <wsdl:message name="giftMessageForQuoteItemRequest"> - <wsdl:part name="parameters" element="typens:giftMessageForQuoteItemRequestParam" /> - </wsdl:message> - <wsdl:message name="giftMessageForQuoteItemResponse"> - <wsdl:part name="parameters" element="typens:giftMessageForQuoteItemResponseParam" /> - </wsdl:message> - <wsdl:message name="giftMessageForQuoteProductRequest"> - <wsdl:part name="parameters" element="typens:giftMessageForQuoteProductRequestParam" /> - </wsdl:message> - <wsdl:message name="giftMessageForQuoteProductResponse"> - <wsdl:part name="parameters" element="typens:giftMessageForQuoteProductResponseParam" /> - </wsdl:message> - <wsdl:portType name="{{var wsdl.handler}}PortType"> - <wsdl:operation name="giftMessageSetForQuote"> - <wsdl:documentation>Set a gift message to the cart</wsdl:documentation> - <wsdl:input message="typens:giftMessageForQuoteRequest" /> - <wsdl:output message="typens:giftMessageForQuoteResponse" /> - </wsdl:operation> - <wsdl:operation name="giftMessageSetForQuoteItem"> - <wsdl:documentation>Setting a gift messages to the quote item</wsdl:documentation> - <wsdl:input message="typens:giftMessageForQuoteItemRequest" /> - <wsdl:output message="typens:giftMessageForQuoteItemResponse" /> - </wsdl:operation> - <wsdl:operation name="giftMessageSetForQuoteProduct"> - <wsdl:documentation>Setting a gift messages to the quote items by products</wsdl:documentation> - <wsdl:input message="typens:giftMessageForQuoteProductRequest" /> - <wsdl:output message="typens:giftMessageForQuoteProductResponse" /> - </wsdl:operation> - </wsdl:portType> - <wsdl:binding name="{{var wsdl.handler}}Binding" type="typens:{{var wsdl.handler}}PortType"> - <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" /> - <wsdl:operation name="giftMessageSetForQuote"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="giftMessageSetForQuoteItem"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="giftMessageSetForQuoteProduct"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - </wsdl:binding> -</wsdl:definitions> diff --git a/app/code/core/Mage/Oauth/Model/Consumer.php b/app/code/core/Mage/Oauth/Model/Consumer.php index 82a19f70e0e4ea27137f33f0294275a31e173712..a011c21309d46d46c1b3b78aad24fb17c182708a 100644 --- a/app/code/core/Mage/Oauth/Model/Consumer.php +++ b/app/code/core/Mage/Oauth/Model/Consumer.php @@ -38,9 +38,7 @@ * @method Mage_Oauth_Model_Consumer setName() setName(string $name) * @method string getKey() * @method Mage_Oauth_Model_Consumer setKey() setKey(string $key) - * @method string getSecret() * @method Mage_Oauth_Model_Consumer setSecret() setSecret(string $secret) - * @method string getCallbackUrl() * @method Mage_Oauth_Model_Consumer setCallbackUrl() setCallbackUrl(string $url) * @method string getCreatedAt() * @method Mage_Oauth_Model_Consumer setCreatedAt() setCreatedAt(string $date) @@ -49,7 +47,7 @@ * @method string getRejectedCallbackUrl() * @method Mage_Oauth_Model_Consumer setRejectedCallbackUrl() setRejectedCallbackUrl(string $rejectedCallbackUrl) */ -class Mage_Oauth_Model_Consumer extends Mage_Core_Model_Abstract +abstract class Mage_Oauth_Model_Consumer extends Mage_Core_Model_Abstract implements Mage_Oauth_Model_ConsumerInterface { /** * Key hash length @@ -129,4 +127,35 @@ class Mage_Oauth_Model_Consumer extends Mage_Core_Model_Abstract } return true; } + + /** + * Load consumer by key. + * + * @param string $key + * @return Mage_Oauth_Model_Consumer + */ + public function loadByKey($key) + { + return $this->load($key, 'key'); + } + + /** + * Get consumer key. + * + * @return string + */ + public function getSecret() + { + return $this->getData('secret'); + } + + /** + * Get consumer callback URL. + * + * @return string + */ + public function getCallBackUrl() + { + return $this->getData('callback_url'); + } } diff --git a/app/code/core/Mage/Oauth/Model/Consumer/Factory.php b/app/code/core/Mage/Oauth/Model/Consumer/Factory.php new file mode 100644 index 0000000000000000000000000000000000000000..3322315024d2569650088608cd0296f37358fa08 --- /dev/null +++ b/app/code/core/Mage/Oauth/Model/Consumer/Factory.php @@ -0,0 +1,51 @@ +<?php +/** + * Consumer builder factory. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Oauth_Model_Consumer_Factory +{ + /** + * @var Magento_ObjectManager + */ + protected $_objectManager; + + /** + * @param Magento_ObjectManager $objectManager + */ + public function __construct(Magento_ObjectManager $objectManager) + { + $this->_objectManager = $objectManager; + } + + /** + * Create consumer model. + * + * @param array $arguments + * @return Mage_Oauth_Model_Consumer + */ + public function create(array $arguments = array()) + { + return $this->_objectManager->create('Mage_Oauth_Model_Consumer', $arguments); + } +} diff --git a/app/code/core/Mage/Oauth/Model/ConsumerInterface.php b/app/code/core/Mage/Oauth/Model/ConsumerInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..9576f85b9cc688ea480fb2f9208b020817e24939 --- /dev/null +++ b/app/code/core/Mage/Oauth/Model/ConsumerInterface.php @@ -0,0 +1,56 @@ +<?php +/** + * oAuth consumer interface. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +interface Mage_Oauth_Model_ConsumerInterface +{ + /** + * Load consumer by key. + * + * @param string $key + * @return Mage_Oauth_Model_ConsumerInterface + */ + public function loadByKey($key); + + /** + * Get consumer ID. + * + * @return int + */ + public function getId(); + + /** + * Get consumer key. + * + * @return string + */ + public function getSecret(); + + /** + * Get consumer callback URL. + * + * @return string + */ + public function getCallBackUrl(); +} diff --git a/app/code/core/Mage/Oauth/Model/Nonce/Factory.php b/app/code/core/Mage/Oauth/Model/Nonce/Factory.php new file mode 100644 index 0000000000000000000000000000000000000000..6929958e8eb6ab16b15a9644513109124f478f4e --- /dev/null +++ b/app/code/core/Mage/Oauth/Model/Nonce/Factory.php @@ -0,0 +1,32 @@ +<?php +/** + * Nonce builder factory. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + */ +class Mage_Oauth_Model_Nonce_Factory +{ + /** + * @var Magento_ObjectManager + */ + protected $_objectManager; + + /** + * @param Magento_ObjectManager $objectManager + */ + public function __construct(Magento_ObjectManager $objectManager) + { + $this->_objectManager = $objectManager; + } + + /** + * Create nonce model. + * + * @param array $arguments + * @return Mage_Oauth_Model_Nonce + */ + public function create($arguments = array()) + { + return $this->_objectManager->create('Mage_Oauth_Model_Nonce', $arguments); + } +} diff --git a/app/code/core/Mage/Oauth/Model/Server.php b/app/code/core/Mage/Oauth/Model/Server.php index 86c5b96e350e583345cce70cbde9360afd4fad80..4b4c1d9fc1cbaae328d35772572303dd1eb4d9ae 100644 --- a/app/code/core/Mage/Oauth/Model/Server.php +++ b/app/code/core/Mage/Oauth/Model/Server.php @@ -86,7 +86,7 @@ class Mage_Oauth_Model_Server const TIME_DEVIATION = 600; /** - * Value of callback URL when it is established or if cliaent is unable to receive callbacks + * Value of callback URL when it is established or if the client is unable to receive callbacks * * @link http://tools.ietf.org/html/rfc5849#section-2.1 Requirement in RFC-5849 */ @@ -95,7 +95,7 @@ class Mage_Oauth_Model_Server /** * Consumer object * - * @var Mage_Oauth_Model_Consumer + * @var Mage_Oauth_Model_ConsumerInterface */ protected $_consumer; @@ -162,7 +162,7 @@ class Mage_Oauth_Model_Server /** * Request object * - * @var Mage_Core_Controller_Request_Http + * @var Zend_Controller_Request_Http */ protected $_request; @@ -187,33 +187,48 @@ class Mage_Oauth_Model_Server */ protected $_token; + /** @var Mage_Oauth_Model_Token_Factory */ + protected $_tokenFactory; + + /** @var Mage_Oauth_Model_Consumer_Factory */ + protected $_consumerFactory; + + /** @var Mage_Oauth_Model_Nonce_Factory */ + protected $_nonceFactory; + /** * Internal constructor not depended on params * * @param Zend_Controller_Request_Http $request OPTIONAL Request object (If not specified - use singleton) + * @param Mage_Oauth_Model_Token_Factory $tokenFactory + * @param Mage_Oauth_Model_Consumer_Factory $consumerFactory + * @param Mage_Oauth_Model_Nonce_Factory $nonceFactory * @throws Exception */ - public function __construct($request = null) - { - if (is_object($request)) { - if (!$request instanceof Zend_Controller_Request_Http) { - throw new Exception('Invalid request object passed'); - } - $this->_request = $request; - } else { - $this->_request = Mage::app()->getRequest(); - } + public function __construct( + Zend_Controller_Request_Http $request, + Mage_Oauth_Model_Token_Factory $tokenFactory, + Mage_Oauth_Model_Consumer_Factory $consumerFactory, + Mage_Oauth_Model_Nonce_Factory $nonceFactory + ) { + $this->_request = $request; + $this->_tokenFactory = $tokenFactory; + $this->_consumerFactory = $consumerFactory; + $this->_nonceFactory = $nonceFactory; } /** * Retrieve protocol and request parameters from request object * + * @param string $authHeaderValue * @link http://tools.ietf.org/html/rfc5849#section-3.5 * @return Mage_Oauth_Model_Server */ - protected function _fetchParams() + protected function _fetchParams($authHeaderValue = null) { - $authHeaderValue = $this->_request->getHeader('Authorization'); + if (is_null($authHeaderValue)) { + $authHeaderValue = $this->_request->getHeader('Authorization'); + } if ($authHeaderValue && 'oauth' === strtolower(substr($authHeaderValue, 0, 5))) { $authHeaderValue = substr($authHeaderValue, 6); // ignore 'OAuth ' at the beginning @@ -298,9 +313,8 @@ class Mage_Oauth_Model_Server */ protected function _initConsumer() { - $this->_consumer = Mage::getModel('Mage_Oauth_Model_Consumer'); - - $this->_consumer->load($this->_protocolParams['oauth_consumer_key'], 'key'); + $this->_consumer = $this->_consumerFactory->create(); + $this->_consumer->loadByKey($this->_protocolParams['oauth_consumer_key']); if (!$this->_consumer->getId()) { $this->_throwException('', self::ERR_CONSUMER_KEY_REJECTED); @@ -315,7 +329,7 @@ class Mage_Oauth_Model_Server */ protected function _initToken() { - $this->_token = Mage::getModel('Mage_Oauth_Model_Token'); + $this->_token = $this->_tokenFactory->create(); if (self::REQUEST_INITIATE != $this->_requestType) { $this->_validateTokenParam(); @@ -467,9 +481,7 @@ class Mage_Oauth_Model_Server if ($timestamp <= 0 || $timestamp > (time() + self::TIME_DEVIATION)) { $this->_throwException('', self::ERR_TIMESTAMP_REFUSED); } - /** @var $nonceObj Mage_Oauth_Model_Nonce */ - $nonceObj = Mage::getModel('Mage_Oauth_Model_Nonce'); - + $nonceObj = $this->_nonceFactory->create(); $nonceObj->load($nonce, 'nonce'); if ($nonceObj->getTimestamp() == $timestamp) { @@ -503,10 +515,6 @@ class Mage_Oauth_Model_Server $this->_throwException($paramName, self::ERR_PARAMETER_REJECTED); } } - // validate consumer key length - if (strlen($this->_protocolParams['oauth_consumer_key']) != Mage_Oauth_Model_Consumer::KEY_LENGTH) { - $this->_throwException('', self::ERR_CONSUMER_KEY_REJECTED); - } // validate signature method if (!in_array($this->_protocolParams['oauth_signature_method'], self::getSupportedSignatureMethods())) { $this->_throwException('', self::ERR_SIGNATURE_METHOD_REJECTED); @@ -536,13 +544,13 @@ class Mage_Oauth_Model_Server array_merge($this->_params, $this->_protocolParams), $this->_protocolParams['oauth_signature_method'], $this->_consumer->getSecret(), - $this->_token->getSecret(), + !is_null($this->_token) ? $this->_token->getSecret() : null, $this->_request->getMethod(), $this->_request->getScheme() . '://' . $this->_request->getHttpHost() . $this->_request->getRequestUri() ); if ($calculatedSign != $this->_protocolParams['oauth_signature']) { - $this->_throwException($calculatedSign, self::ERR_SIGNATURE_INVALID); + $this->_throwException('Invalid signature.', self::ERR_SIGNATURE_INVALID); } } @@ -687,8 +695,6 @@ class Mage_Oauth_Model_Server } if (self::ERR_PARAMETER_ABSENT == $eCode) { $errorMsg .= '&oauth_parameters_absent=' . $eMsg; - } elseif (self::ERR_SIGNATURE_INVALID == $eCode) { - $errorMsg .= '&debug_sbs=' . $eMsg; } elseif ($eMsg) { $errorMsg .= '&message=' . $eMsg; } diff --git a/app/code/core/Mage/Oauth/Model/Token/Factory.php b/app/code/core/Mage/Oauth/Model/Token/Factory.php new file mode 100644 index 0000000000000000000000000000000000000000..606eabeabfdf112cca2a47be475dbe7be35ae1c4 --- /dev/null +++ b/app/code/core/Mage/Oauth/Model/Token/Factory.php @@ -0,0 +1,32 @@ +<?php +/** + * Token builder factory. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + */ +class Mage_Oauth_Model_Token_Factory +{ + /** + * @var Magento_ObjectManager + */ + protected $_objectManager; + + /** + * @param Magento_ObjectManager $objectManager + */ + public function __construct(Magento_ObjectManager $objectManager) + { + $this->_objectManager = $objectManager; + } + + /** + * Create token model. + * + * @param array $arguments + * @return Mage_Oauth_Model_Token + */ + public function create($arguments = array()) + { + return $this->_objectManager->create('Mage_Oauth_Model_Token', $arguments); + } +} diff --git a/app/code/core/Mage/Oauth/controllers/Adminhtml/Oauth/AuthorizeController.php b/app/code/core/Mage/Oauth/controllers/Adminhtml/Oauth/AuthorizeController.php index 7ff62ba9a4739ea01c3f01025cf0101a0450629b..1cf892b88ca7664421effcdb4a726d14a75f78f2 100644 --- a/app/code/core/Mage/Oauth/controllers/Adminhtml/Oauth/AuthorizeController.php +++ b/app/code/core/Mage/Oauth/controllers/Adminhtml/Oauth/AuthorizeController.php @@ -38,14 +38,14 @@ class Mage_Oauth_Adminhtml_Oauth_AuthorizeController extends Mage_Adminhtml_Cont * * @var string */ - protected $_sessionName = 'admin/session'; + protected $_sessionName = 'Mage_Backend_Model_Auth_Session'; /** * Array of actions which can be processed without secret key validation * * @var array */ - public $_publicActions = array('index', 'simple', 'confirm', 'confirmSimple','reject', 'rejectSimple'); + protected $_publicActions = array('index', 'simple', 'confirm', 'confirmSimple','reject', 'rejectSimple'); /** * Disable showing of login form @@ -172,7 +172,7 @@ class Mage_Oauth_Adminhtml_Oauth_AuthorizeController extends Mage_Adminhtml_Cont $this->loadLayout(); /** @var $block Mage_Oauth_Block_Adminhtml_Oauth_Authorize */ - $block = $this->getLayout()->getBlock('content')->getChildBlock('oauth.authorize.confirm'); + $block = $this->getLayout()->getBlock('oauth.authorize.confirm'); $block->setIsSimple($simple); try { diff --git a/app/code/core/Mage/Oauth/etc/adminhtml/acl.xml b/app/code/core/Mage/Oauth/etc/adminhtml/acl.xml deleted file mode 100644 index 90aadee66d77645b51f3525fc3ee6239eb738842..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Oauth/etc/adminhtml/acl.xml +++ /dev/null @@ -1,48 +0,0 @@ -<?xml version="1.0"?> -<!-- -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Academic Free License (AFL 3.0) - * that is bundled with this package in the file LICENSE_AFL.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/afl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Oauth - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) - */ ---> -<config> - <acl> - <resources> - <resource id="Mage_Adminhtml::admin"> - <resource id="Mage_Adminhtml::system"> - <resource id="Mage_Api::api"> - <resource id="Mage_Oauth::consumer" module="Mage_Oauth" title="OAuth Consumers" sortOrder="20"> - <resource id="Mage_Oauth::consumer_edit" title="Edit" sortOrder="30" /> - <resource id="Mage_Oauth::consumer_delete" title="Delete" sortOrder="40" /> - </resource> - <resource id="Mage_Oauth::authorizedTokens" module="Mage_Oauth" title="OAuth Authorized Tokens" sortOrder="30" /> - <resource id="Mage_Oauth::oauth_admin_token" module="Mage_Oauth" title="OAuth Admin My Apps" sortOrder="40" /> - </resource> - <resource id="Mage_Adminhtml::config"> - <resource id="Mage_Oauth::oauth" title="OAuth" sortOrder="20" /> - </resource> - </resource> - </resource> - </resources> - </acl> -</config> diff --git a/app/code/core/Mage/Oauth/etc/adminhtml/menu.xml b/app/code/core/Mage/Oauth/etc/adminhtml/menu.xml index 64c880aa8d4c1cb8b60a1b780a3ba85d20b7e541..380e7b1364a50324086fb11f1d801991fdbed4da 100644 --- a/app/code/core/Mage/Oauth/etc/adminhtml/menu.xml +++ b/app/code/core/Mage/Oauth/etc/adminhtml/menu.xml @@ -27,8 +27,9 @@ --> <config> <menu> - <add id="Mage_Oauth::system_api_oauth_consumer" title="REST - OAuth Consumers" module="Mage_Oauth" sortOrder="50" parent="Mage_Api::system_api" action="adminhtml/oauth_consumer" resource="Mage_Oauth::consumer"/> - <add id="Mage_Oauth::system_api_oauth_authorized_tokens" title="REST - OAuth Authorized Tokens" module="Mage_Oauth" sortOrder="60" parent="Mage_Api::system_api" action="adminhtml/oauth_authorizedTokens" resource="Mage_Oauth::authorizedTokens"/> - <add id="Mage_Oauth::system_api_oauth_admin_token" title="REST - My Apps" module="Mage_Oauth" sortOrder="70" parent="Mage_Api::system_api" action="adminhtml/oauth_admin_token" resource="Mage_Oauth::oauth_admin_token"/> + <!-- Menu elements has been disabled untill 3-legged oAuth functionality is needed. --> + <!--<add id="Mage_Oauth::system_api_oauth_consumer" title="REST - OAuth Consumers" module="Mage_Oauth" sortOrder="50" parent="Mage_Api::system_api" action="adminhtml/oauth_consumer" resource="Mage_Oauth::consumer"/>--> + <!--<add id="Mage_Oauth::system_api_oauth_authorized_tokens" title="REST - OAuth Authorized Tokens" module="Mage_Oauth" sortOrder="60" parent="Mage_Api::system_api" action="adminhtml/oauth_authorizedTokens" resource="Mage_Oauth::authorizedTokens"/>--> + <!--<add id="Mage_Oauth::system_api_oauth_admin_token" title="REST - My Apps" module="Mage_Oauth" sortOrder="70" parent="Mage_Api::system_api" action="adminhtml/oauth_admin_token" resource="Mage_Oauth::oauth_admin_token"/>--> </menu> </config> diff --git a/app/code/core/Mage/Page/Block/Html/Header.php b/app/code/core/Mage/Page/Block/Html/Header.php index a2e62fe848bcf762c32b3bb336a6e7bcabaccb28..5c03555887ca51f9277113f283490b6a6e1d310f 100644 --- a/app/code/core/Mage/Page/Block/Html/Header.php +++ b/app/code/core/Mage/Page/Block/Html/Header.php @@ -33,6 +33,43 @@ */ class Mage_Page_Block_Html_Header extends Mage_Core_Block_Template { + /** + * @var Mage_Core_Model_Config_Options + */ + protected $_configOptions; + + public function __construct( + Mage_Core_Controller_Request_Http $request, + Mage_Core_Model_Layout $layout, + Mage_Core_Model_Event_Manager $eventManager, + Mage_Core_Model_Url $urlBuilder, + Mage_Core_Model_Translate $translator, + Mage_Core_Model_Cache $cache, + Mage_Core_Model_Design_Package $designPackage, + Mage_Core_Model_Session $session, + Mage_Core_Model_Store_Config $storeConfig, + Mage_Core_Controller_Varien_Front $frontController, + Mage_Core_Model_Factory_Helper $helperFactory, + Mage_Core_Model_Config_Options $configOptions, + array $data = array() + ) { + parent::__construct( + $request, + $layout, + $eventManager, + $urlBuilder, + $translator, + $cache, + $designPackage, + $session, + $storeConfig, + $frontController, + $helperFactory, + $data + ); + $this->_configOptions = $configOptions; + } + public function _construct() { $this->setTemplate('html/header.phtml'); @@ -55,12 +92,17 @@ class Mage_Page_Block_Html_Header extends Mage_Core_Block_Template return $this; } + /** + * Get logo image URL + * + * @return string + */ public function getLogoSrc() { if (empty($this->_data['logo_src'])) { - $this->_data['logo_src'] = Mage::getStoreConfig('design/header/logo_src'); + $this->_data['logo_src'] = $this->_getLogoUrl(); } - return $this->getViewFileUrl($this->_data['logo_src']); + return $this->_data['logo_src']; } public function getLogoAlt() @@ -83,4 +125,43 @@ class Mage_Page_Block_Html_Header extends Mage_Core_Block_Template return $this->_data['welcome']; } + + /** + * Retrieve logo image URL + * + * @return string + */ + protected function _getLogoUrl() + { + $folderName = Mage_Backend_Model_Config_Backend_Image_Logo::UPLOAD_DIR; + $storeLogoPath = $this->_storeConfig->getConfig('design/header/logo_src'); + $logoUrl = $this->_urlBuilder->getBaseUrl(array('_type' => 'media')) . $folderName . '/' . $storeLogoPath; + $absolutePath = $this->_configOptions->getDir('media') . DIRECTORY_SEPARATOR + . $folderName . DIRECTORY_SEPARATOR . $storeLogoPath; + + if (!is_null($storeLogoPath) && $this->_isFile($absolutePath)) { + $url = $logoUrl; + } else { + $url = $this->getViewFileUrl('images::logo.gif'); + } + + return $url; + } + + /** + * If DB file storage is on - find there, otherwise - just file_exists + * + * @param string $filename + * @return bool + */ + protected function _isFile($filename) + { + $helper = $this->_helperFactory->get('Mage_Core_Helper_File_Storage_Database'); + + if ($helper->checkDbUsage() && !is_file($filename)) { + $helper->saveFileToFilesystem($filename); + } + + return is_file($filename); + } } diff --git a/app/code/core/Mage/Page/etc/adminhtml/system.xml b/app/code/core/Mage/Page/etc/adminhtml/system.xml index a99454cd5dc5c68773e0f579828b1acdbb46f3e9..f62c61a9ee55133d45abd248b89bffe42db24f77 100644 --- a/app/code/core/Mage/Page/etc/adminhtml/system.xml +++ b/app/code/core/Mage/Page/etc/adminhtml/system.xml @@ -77,10 +77,13 @@ <comment>This action will delete your custom instructions and reset robots.txt file to system's default settings.</comment> </field> </group> - <group id="header" translate="label" type="text" sortOrder="30" showInDefault="1" showInWebsite="1" showInStore="1"> + <group id="header" translate="label comment" type="text" sortOrder="30" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Header</label> - <field id="logo_src" translate="label" type="text" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1"> - <label>Logo Image Src</label> + <field id="logo_src" translate="label" type="image" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1"> + <label>Logo Image</label> + <comment>Allowed file types:PNG, GIF, JPG, JPEG.</comment> + <backend_model>Mage_Backend_Model_Config_Backend_Image_Logo</backend_model> + <base_url type="media" scope_info="1">logo</base_url> </field> <field id="logo_alt" translate="label" type="text" sortOrder="20" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Logo Image Alt</label> diff --git a/app/code/core/Mage/Page/etc/config.xml b/app/code/core/Mage/Page/etc/config.xml index 4b192e93c8ddacd12ccc71e69ffb462a3a81aec6..f60e32f7fff3bf921b7f19752b6dd2429d4ea588 100644 --- a/app/code/core/Mage/Page/etc/config.xml +++ b/app/code/core/Mage/Page/etc/config.xml @@ -147,7 +147,6 @@ Disallow: /*SID= </default_custom_instructions> </search_engine_robots> <header translate="welcome" module="Mage_Page"> - <logo_src>images/logo.gif</logo_src> <logo_alt>Magento Commerce</logo_alt> <welcome>Default welcome msg!</welcome> </header> diff --git a/app/code/core/Mage/Sales/Model/Api/Resource.php b/app/code/core/Mage/Sales/Model/Api/Resource.php deleted file mode 100644 index 35079fb3732ad9e7a05d550ab36ac563c43fa31e..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Sales/Model/Api/Resource.php +++ /dev/null @@ -1,136 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Sales - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Sale api resource abstract - * - * @category Mage - * @package Mage_Sales - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Sales_Model_Api_Resource extends Mage_Api_Model_Resource_Abstract -{ - /** - * Default ignored attribute codes per entity type - * - * @var array - */ - protected $_ignoredAttributeCodes = array( - 'global' => array('entity_id', 'attribute_set_id', 'entity_type_id') - ); - - /** - * Attributes map array per entity type - * - * @var google - */ - protected $_attributesMap = array( - 'global' => array() - ); - - /** - * Update attributes for entity - * - * @param array $data - * @param Mage_Core_Model_Abstract $object - * @param array $attributes - * @return Mage_Sales_Model_Api_Resource - */ - protected function _updateAttributes($data, $object, $type, array $attributes = null) - { - - foreach ($data as $attribute=>$value) { - if ($this->_isAllowedAttribute($attribute, $type, $attributes)) { - $object->setData($attribute, $value); - } - } - - return $this; - } - - /** - * Retrieve entity attributes values - * - * @param Mage_Core_Model_Abstract $object - * @param array $attributes - * @return Mage_Sales_Model_Api_Resource - */ - protected function _getAttributes($object, $type, array $attributes = null) - { - $result = array(); - - if (!is_object($object)) { - return $result; - } - - foreach ($object->getData() as $attribute=>$value) { - if ($this->_isAllowedAttribute($attribute, $type, $attributes)) { - $result[$attribute] = $value; - } - } - - if (isset($this->_attributesMap['global'])) { - foreach ($this->_attributesMap['global'] as $alias=>$attributeCode) { - $result[$alias] = $object->getData($attributeCode); - } - } - - if (isset($this->_attributesMap[$type])) { - foreach ($this->_attributesMap[$type] as $alias=>$attributeCode) { - $result[$alias] = $object->getData($attributeCode); - } - } - - return $result; - } - - /** - * Check is attribute allowed to usage - * - * @param Mage_Eav_Model_Entity_Attribute_Abstract $attribute - * @param string $entityType - * @param array $attributes - * @return boolean - */ - protected function _isAllowedAttribute($attributeCode, $type, array $attributes = null) - { - if (!empty($attributes) - && !(in_array($attributeCode, $attributes))) { - return false; - } - - if (in_array($attributeCode, $this->_ignoredAttributeCodes['global'])) { - return false; - } - - if (isset($this->_ignoredAttributeCodes[$type]) - && in_array($attributeCode, $this->_ignoredAttributeCodes[$type])) { - return false; - } - - return true; - } -} // Class Mage_Sales_Model_Api_Resource End diff --git a/app/code/core/Mage/Sales/Model/Api2/Order.php b/app/code/core/Mage/Sales/Model/Api2/Order.php deleted file mode 100644 index 8a99da257ea1b3e9900a65c363dd768a1775cdfa..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Sales/Model/Api2/Order.php +++ /dev/null @@ -1,318 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Sales - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 class for orders - * - * @category Mage - * @package Mage_Sales - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Sales_Model_Api2_Order extends Mage_Api2_Model_Resource -{ - /**#@+ - * Parameters' names in config with special ACL meaning - */ - const PARAM_GIFT_MESSAGE = '_gift_message'; - const PARAM_ORDER_COMMENTS = '_order_comments'; - const PARAM_PAYMENT_METHOD = '_payment_method'; - const PARAM_TAX_NAME = '_tax_name'; - const PARAM_TAX_RATE = '_tax_rate'; - /**#@-*/ - - /** - * Add gift message info to select - * - * @param Mage_Sales_Model_Resource_Order_Collection $collection - * @return Mage_Sales_Model_Api2_Order - */ - protected function _addGiftMessageInfo(Mage_Sales_Model_Resource_Order_Collection $collection) - { - $collection->getSelect()->joinLeft( - array('gift_message' => $collection->getTable('gift_message')), - 'main_table.gift_message_id = gift_message.gift_message_id', - array( - 'gift_message_from' => 'gift_message.sender', - 'gift_message_to' => 'gift_message.recipient', - 'gift_message_body' => 'gift_message.message' - ) - ); - - return $this; - } - - /** - * Add order payment method field to select - * - * @param Mage_Sales_Model_Resource_Order_Collection $collection - * @return Mage_Sales_Model_Api2_Order - */ - protected function _addPaymentMethodInfo(Mage_Sales_Model_Resource_Order_Collection $collection) - { - $collection->getSelect()->joinLeft( - array('payment_method' => $collection->getTable('sales_flat_order_payment')), - 'main_table.entity_id = payment_method.parent_id', - array('payment_method' => 'payment_method.method') - ); - - return $this; - } - - /** - * Add order tax information to select - * - * @param Mage_Sales_Model_Resource_Order_Collection $collection - * @return Mage_Sales_Model_Api2_Order - */ - protected function _addTaxInfo(Mage_Sales_Model_Resource_Order_Collection $collection) - { - $taxInfoFields = array(); - - if ($this->_isTaxNameAllowed()) { - $taxInfoFields['tax_name'] = 'order_tax.title'; - } - if ($this->_isTaxRateAllowed()) { - $taxInfoFields['tax_rate'] = 'order_tax.percent'; - } - if ($taxInfoFields) { - $collection->getSelect()->joinLeft( - array('order_tax' => $collection->getTable('sales_order_tax')), - 'main_table.entity_id = order_tax.order_id', - $taxInfoFields - ); - } - return $this; - } - - /** - * Retrieve a list or orders' addresses in a form of [order ID => array of addresses, ...] - * - * @param array $orderIds Orders identifiers - * @return array - */ - protected function _getAddresses(array $orderIds) - { - $addresses = array(); - - if ($this->_isSubCallAllowed('order_address')) { - /** @var $addressesFilter Mage_Api2_Model_Acl_Filter */ - $addressesFilter = $this->_getSubModel('order_address', array())->getFilter(); - // do addresses request if at least one attribute allowed - if ($addressesFilter->getAllowedAttributes()) { - /* @var $collection Mage_Sales_Model_Resource_Order_Address_Collection */ - $collection = Mage::getResourceModel('Mage_Sales_Model_Resource_Order_Address_Collection'); - - $collection->addAttributeToFilter('parent_id', $orderIds); - - foreach ($collection->getItems() as $item) { - $addresses[$item->getParentId()][] = $addressesFilter->out($item->toArray()); - } - } - } - return $addresses; - } - - /** - * Retrieve collection instance for orders list - * - * @return Mage_Sales_Model_Resource_Order_Collection - */ - protected function _getCollectionForRetrieve() - { - /** @var $collection Mage_Sales_Model_Resource_Order_Collection */ - $collection = Mage::getResourceModel('Mage_Sales_Model_Resource_Order_Collection'); - - $this->_applyCollectionModifiers($collection); - - return $collection; - } - - /** - * Retrieve collection instance for single order - * - * @param int $orderId Order identifier - * @return Mage_Sales_Model_Resource_Order_Collection - */ - protected function _getCollectionForSingleRetrieve($orderId) - { - /** @var $collection Mage_Sales_Model_Resource_Order_Collection */ - $collection = Mage::getResourceModel('Mage_Sales_Model_Resource_Order_Collection'); - - return $collection->addFieldToFilter($collection->getResource()->getIdFieldName(), $orderId); - } - - /** - * Retrieve a list or orders' comments in a form of [order ID => array of comments, ...] - * - * @param array $orderIds Orders' identifiers - * @return array - */ - protected function _getComments(array $orderIds) - { - $comments = array(); - - if ($this->_isOrderCommentsAllowed() && $this->_isSubCallAllowed('order_comment')) { - /** @var $commentsFilter Mage_Api2_Model_Acl_Filter */ - $commentsFilter = $this->_getSubModel('order_comment', array())->getFilter(); - // do comments request if at least one attribute allowed - if ($commentsFilter->getAllowedAttributes()) { - foreach ($this->_getCommentsCollection($orderIds)->getItems() as $item) { - $comments[$item->getParentId()][] = $commentsFilter->out($item->toArray()); - } - } - } - return $comments; - } - - /** - * Prepare and return order comments collection - * - * @param array $orderIds Orders' identifiers - * @return Mage_Sales_Model_Resource_Order_Status_History_Collection|Object - */ - protected function _getCommentsCollection(array $orderIds) - { - /* @var $collection Mage_Sales_Model_Resource_Order_Status_History_Collection */ - $collection = Mage::getResourceModel('Mage_Sales_Model_Resource_Order_Status_History_Collection'); - $collection->setOrderFilter($orderIds); - - return $collection; - } - - /** - * Retrieve a list or orders' items in a form of [order ID => array of items, ...] - * - * @param array $orderIds Orders identifiers - * @return array - */ - protected function _getItems(array $orderIds) - { - $items = array(); - - if ($this->_isSubCallAllowed('order_item')) { - /** @var $itemsFilter Mage_Api2_Model_Acl_Filter */ - $itemsFilter = $this->_getSubModel('order_item', array())->getFilter(); - // do items request if at least one attribute allowed - if ($itemsFilter->getAllowedAttributes()) { - /* @var $collection Mage_Sales_Model_Resource_Order_Item_Collection */ - $collection = Mage::getResourceModel('Mage_Sales_Model_Resource_Order_Item_Collection'); - - $collection->addAttributeToFilter('order_id', $orderIds); - - foreach ($collection->getItems() as $item) { - $items[$item->getOrderId()][] = $itemsFilter->out($item->toArray()); - } - } - } - return $items; - } - - /** - * Check gift messages information is allowed - * - * @return bool - */ - public function _isGiftMessageAllowed() - { - return in_array(self::PARAM_GIFT_MESSAGE, $this->getFilter()->getAllowedAttributes()); - } - - /** - * Check order comments information is allowed - * - * @return bool - */ - public function _isOrderCommentsAllowed() - { - return in_array(self::PARAM_ORDER_COMMENTS, $this->getFilter()->getAllowedAttributes()); - } - - /** - * Check payment method information is allowed - * - * @return bool - */ - public function _isPaymentMethodAllowed() - { - return in_array(self::PARAM_PAYMENT_METHOD, $this->getFilter()->getAllowedAttributes()); - } - - /** - * Check tax name information is allowed - * - * @return bool - */ - public function _isTaxNameAllowed() - { - return in_array(self::PARAM_TAX_NAME, $this->getFilter()->getAllowedAttributes()); - } - - /** - * Check tax rate information is allowed - * - * @return bool - */ - public function _isTaxRateAllowed() - { - return in_array(self::PARAM_TAX_RATE, $this->getFilter()->getAllowedAttributes()); - } - - /** - * Get orders list - * - * @return array - */ - protected function _retrieveCollection() - { - $collection = $this->_getCollectionForRetrieve(); - - if ($this->_isPaymentMethodAllowed()) { - $this->_addPaymentMethodInfo($collection); - } - if ($this->_isGiftMessageAllowed()) { - $this->_addGiftMessageInfo($collection); - } - $this->_addTaxInfo($collection); - - $ordersData = array(); - - foreach ($collection->getItems() as $order) { - $ordersData[$order->getId()] = $order->toArray(); - } - if ($ordersData) { - foreach ($this->_getAddresses(array_keys($ordersData)) as $orderId => $addresses) { - $ordersData[$orderId]['addresses'] = $addresses; - } - foreach ($this->_getItems(array_keys($ordersData)) as $orderId => $items) { - $ordersData[$orderId]['order_items'] = $items; - } - foreach ($this->_getComments(array_keys($ordersData)) as $orderId => $comments) { - $ordersData[$orderId]['order_comments'] = $comments; - } - } - return $ordersData; - } -} diff --git a/app/code/core/Mage/Sales/Model/Api2/Order/Address.php b/app/code/core/Mage/Sales/Model/Api2/Order/Address.php deleted file mode 100644 index 52eefedc8c14d3ef88c7ce5a76b717f6732de323..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Sales/Model/Api2/Order/Address.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Sales - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 class for order address - * - * @category Mage - * @package Mage_Sales - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Sales_Model_Api2_Order_Address extends Mage_Api2_Model_Resource -{ -} diff --git a/app/code/core/Mage/Sales/Model/Api2/Order/Address/Rest.php b/app/code/core/Mage/Sales/Model/Api2/Order/Address/Rest.php deleted file mode 100644 index 9df350aa6c8a082679374c129b8aefd82239c70d..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Sales/Model/Api2/Order/Address/Rest.php +++ /dev/null @@ -1,92 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Sales - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Abstract API2 class for order address - * - * @category Mage - * @package Mage_Sales - * @author Magento Core Team <core@magentocommerce.com> - */ -abstract class Mage_Sales_Model_Api2_Order_Address_Rest extends Mage_Sales_Model_Api2_Order_Address -{ - /**#@+ - * Parameters in request used in model (usually specified in route mask) - */ - const PARAM_ORDER_ID = 'order_id'; - const PARAM_ADDRESS_TYPE = 'address_type'; - /**#@-*/ - - /** - * Retrieve order address - * - * @return array - */ - protected function _retrieve() - { - /** @var $address Mage_Sales_Model_Order_Address */ - $address = $this->_getCollectionForRetrieve() - ->addAttributeToFilter('address_type', $this->getRequest()->getParam(self::PARAM_ADDRESS_TYPE)) - ->getFirstItem(); - if (!$address->getId()) { - $this->_critical(self::RESOURCE_NOT_FOUND); - } - return $address->getData(); - } - - /** - * Retrieve order addresses - * - * @return array - */ - protected function _retrieveCollection() - { - $collection = $this->_getCollectionForRetrieve(); - - $this->_applyCollectionModifiers($collection); - $data = $collection->load()->toArray(); - - if (0 == count($data['items'])) { - $this->_critical(self::RESOURCE_NOT_FOUND); - } - - return $data['items']; - } - - /** - * Retrieve collection instances - * - * @return Mage_Sales_Model_Resource_Order_Address_Collection - */ - protected function _getCollectionForRetrieve() - { - /* @var $collection Mage_Sales_Model_Resource_Order_Address_Collection */ - $collection = Mage::getResourceModel('Mage_Sales_Model_Resource_Order_Address_Collection'); - $collection->addAttributeToFilter('parent_id', $this->getRequest()->getParam(self::PARAM_ORDER_ID)); - - return $collection; - } -} diff --git a/app/code/core/Mage/Sales/Model/Api2/Order/Address/Rest/Admin/V1.php b/app/code/core/Mage/Sales/Model/Api2/Order/Address/Rest/Admin/V1.php deleted file mode 100644 index 6ce971d1991f41b3e83797d4f5c45633efc4e472..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Sales/Model/Api2/Order/Address/Rest/Admin/V1.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Sales - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 class for order address (admin) - * - * @category Mage - * @package Mage_Sales - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Sales_Model_Api2_Order_Address_Rest_Admin_V1 extends Mage_Sales_Model_Api2_Order_Address_Rest -{ -} diff --git a/app/code/core/Mage/Sales/Model/Api2/Order/Address/Rest/Customer/V1.php b/app/code/core/Mage/Sales/Model/Api2/Order/Address/Rest/Customer/V1.php deleted file mode 100644 index a43b48692c1c08c1b485021d08aee0b1e791d8d1..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Sales/Model/Api2/Order/Address/Rest/Customer/V1.php +++ /dev/null @@ -1,48 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Sales - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 class for order address (customer) - * - * @category Mage - * @package Mage_Sales - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Sales_Model_Api2_Order_Address_Rest_Customer_V1 extends Mage_Sales_Model_Api2_Order_Address_Rest -{ - /** - * Retrieve collection instances - * - * @return Mage_Sales_Model_Resource_Order_Address_Collection - */ - protected function _getCollectionForRetrieve() - { - $collection = parent::_getCollectionForRetrieve(); - $collection->addAttributeToFilter('customer_id', $this->getApiUser()->getUserId()); - - return $collection; - } -} diff --git a/app/code/core/Mage/Sales/Model/Api2/Order/Comment.php b/app/code/core/Mage/Sales/Model/Api2/Order/Comment.php deleted file mode 100644 index f7f9f79cdff40b9393618b824296c9278a1209d0..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Sales/Model/Api2/Order/Comment.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Sales - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 class for sales order comments - * - * @category Mage - * @package Mage_Sales - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Sales_Model_Api2_Order_Comment extends Mage_Api2_Model_Resource -{ -} diff --git a/app/code/core/Mage/Sales/Model/Api2/Order/Comment/Rest.php b/app/code/core/Mage/Sales/Model/Api2/Order/Comment/Rest.php deleted file mode 100644 index 17296516a05dca394dba23c4bc69245fb54cf161..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Sales/Model/Api2/Order/Comment/Rest.php +++ /dev/null @@ -1,89 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Sales - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Abstract API2 class for sales order comments - * - * @category Mage - * @package Mage_Sales - * @author Magento Core Team <core@magentocommerce.com> - */ -abstract class Mage_Sales_Model_Api2_Order_Comment_Rest extends Mage_Sales_Model_Api2_Order_Comment -{ - /**#@+ - * Parameters in request used in model (usually specified in route mask) - */ - const PARAM_ORDER_ID = 'id'; - /**#@-*/ - - /** - * Get sales order comments - * - * @return array - */ - protected function _retrieveCollection() - { - $collection = $this->_getCollectionForRetrieve(); - $collection->addFieldToSelect($this->getForcedAttributes()); - - $this->_applyCollectionModifiers($collection); - - $data = $collection->load()->toArray(); - return isset($data['items']) ? $data['items'] : $data; - } - - /** - * Retrieve collection instances - * - * @return Mage_Sales_Model_Resource_Order_Status_History_Collection - */ - protected function _getCollectionForRetrieve() - { - /* @var $collection Mage_Sales_Model_Resource_Order_Status_History_Collection */ - $collection = Mage::getResourceModel('Mage_Sales_Model_Resource_Order_Status_History_Collection'); - $collection->setOrderFilter($this->_loadOrderById($this->getRequest()->getParam(self::PARAM_ORDER_ID))); - - return $collection; - } - - /** - * Load order by id - * - * @param int $id - * @throws Mage_Api2_Exception - * @return Mage_Sales_Model_Order - */ - protected function _loadOrderById($id) - { - /* @var $order Mage_Sales_Model_Order */ - $order = Mage::getModel('Mage_Sales_Model_Order')->load($id); - if (!$order->getId()) { - $this->_critical(self::RESOURCE_NOT_FOUND); - } - - return $order; - } -} diff --git a/app/code/core/Mage/Sales/Model/Api2/Order/Comment/Rest/Admin/V1.php b/app/code/core/Mage/Sales/Model/Api2/Order/Comment/Rest/Admin/V1.php deleted file mode 100644 index 31166da3995c63594157d8346afe58e37e684e57..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Sales/Model/Api2/Order/Comment/Rest/Admin/V1.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Sales - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 class for sales order comments (admin) - * - * @category Mage - * @package Mage_Sales - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Sales_Model_Api2_Order_Comment_Rest_Admin_V1 extends Mage_Sales_Model_Api2_Order_Comment_Rest -{ -} diff --git a/app/code/core/Mage/Sales/Model/Api2/Order/Comment/Rest/Customer/V1.php b/app/code/core/Mage/Sales/Model/Api2/Order/Comment/Rest/Customer/V1.php deleted file mode 100644 index fc162b98f5598de77246909563ab65910789fe03..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Sales/Model/Api2/Order/Comment/Rest/Customer/V1.php +++ /dev/null @@ -1,66 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Sales - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 class for sales order comments (customer) - * - * @category Mage - * @package Mage_Sales - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Sales_Model_Api2_Order_Comment_Rest_Customer_V1 extends Mage_Sales_Model_Api2_Order_Comment_Rest -{ - /** - * Load order by id - * - * @param int $id - * @throws Mage_Api2_Exception - * @return Mage_Sales_Model_Order - */ - protected function _loadOrderById($id) - { - $order = parent::_loadOrderById($id); - - // Check sales order's owner - if ($this->getApiUser()->getUserId() !== $order->getCustomerId()) { - $this->_critical(self::RESOURCE_NOT_FOUND); - } - return $order; - } - - /** - * Retrieve collection instances - * - * @return Mage_Sales_Model_Resource_Order_Status_History_Collection - */ - protected function _getCollectionForRetrieve() - { - $collection = parent::_getCollectionForRetrieve(); - $collection->addFieldToFilter('is_visible_on_front', 1); - - return $collection; - } -} diff --git a/app/code/core/Mage/Sales/Model/Api2/Order/Item.php b/app/code/core/Mage/Sales/Model/Api2/Order/Item.php deleted file mode 100644 index 0ef7978cfa500f6dfa627d91166d464374ea692f..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Sales/Model/Api2/Order/Item.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Sales - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 class for order items - * - * @category Mage - * @package Mage_Sales - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Sales_Model_Api2_Order_Item extends Mage_Api2_Model_Resource -{ -} diff --git a/app/code/core/Mage/Sales/Model/Api2/Order/Item/Rest.php b/app/code/core/Mage/Sales/Model/Api2/Order/Item/Rest.php deleted file mode 100644 index 526d17606dd501b10364ef427036da6c54b14145..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Sales/Model/Api2/Order/Item/Rest.php +++ /dev/null @@ -1,93 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Sales - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Abstract API2 class for order items rest - * - * @category Mage - * @package Mage_Sales - * @author Magento Core Team <core@magentocommerce.com> - */ -abstract class Mage_Sales_Model_Api2_Order_Item_Rest extends Mage_Sales_Model_Api2_Order_Item -{ - /**#@+ - * Parameters in request used in model (usually specified in route) - */ - const PARAM_ORDER_ID = 'id'; - /**#@-*/ - - /** - * Get order items list - * - * @return array - */ - protected function _retrieveCollection() - { - $data = array(); - /* @var $item Mage_Sales_Model_Order_Item */ - foreach ($this->_getCollectionForRetrieve() as $item) { - $itemData = $item->getData(); - $itemData['status'] = $item->getStatus(); - $data[] = $itemData; - } - return $data; - } - /** - * Retrieve order items collection - * - * @return Mage_Sales_Model_Resource_Order_Item_Collection - */ - protected function _getCollectionForRetrieve() - { - /* @var $order Mage_Sales_Model_Order */ - $order = $this->_loadOrderById( - $this->getRequest()->getParam(self::PARAM_ORDER_ID) - ); - - /* @var $collection Mage_Sales_Model_Resource_Order_Item_Collection */ - $collection = Mage::getResourceModel('Mage_Sales_Model_Resource_Order_Item_Collection'); - $collection->setOrderFilter($order->getId()); - $this->_applyCollectionModifiers($collection); - return $collection; - } - - /** - * Load order by id - * - * @param int $id - * @throws Mage_Api2_Exception - * @return Mage_Sales_Model_Order - */ - protected function _loadOrderById($id) - { - /* @var $order Mage_Sales_Model_Order */ - $order = Mage::getModel('Mage_Sales_Model_Order')->load($id); - if (!$order->getId()) { - $this->_critical(self::RESOURCE_NOT_FOUND); - } - return $order; - } -} diff --git a/app/code/core/Mage/Sales/Model/Api2/Order/Item/Rest/Admin/V1.php b/app/code/core/Mage/Sales/Model/Api2/Order/Item/Rest/Admin/V1.php deleted file mode 100644 index 68a647c01f67970983ba8d2f1477428970c7e191..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Sales/Model/Api2/Order/Item/Rest/Admin/V1.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 class for order items (admin) - * - * @category Mage - * @package Mage_Sales - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Sales_Model_Api2_Order_Item_Rest_Admin_V1 extends Mage_Sales_Model_Api2_Order_Item_Rest -{ -} diff --git a/app/code/core/Mage/Sales/Model/Api2/Order/Item/Rest/Customer/V1.php b/app/code/core/Mage/Sales/Model/Api2/Order/Item/Rest/Customer/V1.php deleted file mode 100644 index 6b2cbf659ea3213c165baf9e261658981c1e3e7d..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Sales/Model/Api2/Order/Item/Rest/Customer/V1.php +++ /dev/null @@ -1,56 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 class for order items (customer) - * - * @category Mage - * @package Mage_Sales - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Sales_Model_Api2_Order_Item_Rest_Customer_V1 extends Mage_Sales_Model_Api2_Order_Item_Rest -{ - /** - * Load order by id - * - * @param int $id - * @throws Mage_Api2_Exception - * @return Mage_Sales_Model_Order - */ - protected function _loadOrderById($id) - { - /* @var $order Mage_Sales_Model_Order */ - $order = Mage::getModel('Mage_Sales_Model_Order')->load($id); - if (!$order->getId()) { - $this->_critical(self::RESOURCE_NOT_FOUND); - } - // check order owner - if ($this->getApiUser()->getUserId() != $order->getCustomerId()) { - $this->_critical(self::RESOURCE_NOT_FOUND); - } - return $order; - } -} diff --git a/app/code/core/Mage/Sales/Model/Api2/Order/Rest.php b/app/code/core/Mage/Sales/Model/Api2/Order/Rest.php deleted file mode 100644 index c3ce9d0e717a9a117de67af7e649365e3f495735..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Sales/Model/Api2/Order/Rest.php +++ /dev/null @@ -1,76 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Sales - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Abstract API2 class for order item - * - * @category Mage - * @package Mage_Sales - * @author Magento Core Team <core@magentocommerce.com> - */ -abstract class Mage_Sales_Model_Api2_Order_Rest extends Mage_Sales_Model_Api2_Order -{ - /** - * Retrieve information about specified order item - * - * @throws Mage_Api2_Exception - * @return array - */ - protected function _retrieve() - { - $orderId = $this->getRequest()->getParam('id'); - $collection = $this->_getCollectionForSingleRetrieve($orderId); - - if ($this->_isPaymentMethodAllowed()) { - $this->_addPaymentMethodInfo($collection); - } - if ($this->_isGiftMessageAllowed()) { - $this->_addGiftMessageInfo($collection); - } - $this->_addTaxInfo($collection); - - $order = $collection->getItemById($orderId); - - if (!$order) { - $this->_critical(self::RESOURCE_NOT_FOUND); - } - $orderData = $order->getData(); - $addresses = $this->_getAddresses(array($orderId)); - $items = $this->_getItems(array($orderId)); - $comments = $this->_getComments(array($orderId)); - - if ($addresses) { - $orderData['addresses'] = $addresses[$orderId]; - } - if ($items) { - $orderData['order_items'] = $items[$orderId]; - } - if ($comments) { - $orderData['order_comments'] = $comments[$orderId]; - } - return $orderData; - } -} diff --git a/app/code/core/Mage/Sales/Model/Api2/Order/Rest/Admin/V1.php b/app/code/core/Mage/Sales/Model/Api2/Order/Rest/Admin/V1.php deleted file mode 100644 index 789526995b39967fe3a358e00fdd0a1d4d2e3159..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Sales/Model/Api2/Order/Rest/Admin/V1.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 class for orders (admin) - * - * @category Mage - * @package Mage_Sales - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Sales_Model_Api2_Order_Rest_Admin_V1 extends Mage_Sales_Model_Api2_Order_Rest -{ -} diff --git a/app/code/core/Mage/Sales/Model/Api2/Order/Rest/Customer/V1.php b/app/code/core/Mage/Sales/Model/Api2/Order/Rest/Customer/V1.php deleted file mode 100644 index a8d68b414de6ac84058c29b420d1f90832ce4c28..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Sales/Model/Api2/Order/Rest/Customer/V1.php +++ /dev/null @@ -1,71 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Sales - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API2 class for orders (customer) - * - * @category Mage - * @package Mage_Sales - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Sales_Model_Api2_Order_Rest_Customer_V1 extends Mage_Sales_Model_Api2_Order_Rest -{ - /** - * Retrieve collection instance for orders - * - * @return Mage_Sales_Model_Resource_Order_Collection - */ - protected function _getCollectionForRetrieve() - { - return parent::_getCollectionForRetrieve()->addAttributeToFilter( - 'customer_id', array('eq' => $this->getApiUser()->getUserId()) - ); - } - - /** - * Retrieve collection instance for single order - * - * @param int $orderId Order identifier - * @return Mage_Sales_Model_Resource_Order_Collection - */ - protected function _getCollectionForSingleRetrieve($orderId) - { - return parent::_getCollectionForSingleRetrieve($orderId)->addAttributeToFilter( - 'customer_id', array('eq' => $this->getApiUser()->getUserId()) - ); - } - - /** - * Prepare and return order comments collection - * - * @param array $orderIds Orders' identifiers - * @return Mage_Sales_Model_Resource_Order_Status_History_Collection|Object - */ - protected function _getCommentsCollection(array $orderIds) - { - return parent::_getCommentsCollection($orderIds)->addFieldToFilter('is_visible_on_front', 1); - } -} diff --git a/app/code/core/Mage/Sales/Model/Order/Api.php b/app/code/core/Mage/Sales/Model/Order/Api.php deleted file mode 100644 index 029369339bae3627d9f1d4e08be80bc2a1f65a2a..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Sales/Model/Order/Api.php +++ /dev/null @@ -1,255 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Sales - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Order API - * - * @category Mage - * @package Mage_Sales - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Sales_Model_Order_Api extends Mage_Sales_Model_Api_Resource -{ - /** - * Initialize attributes map - */ - public function __construct() - { - $this->_attributesMap = array( - 'order' => array('order_id' => 'entity_id'), - 'order_address' => array('address_id' => 'entity_id'), - 'order_payment' => array('payment_id' => 'entity_id') - ); - } - - /** - * Initialize basic order model - * - * @param mixed $orderIncrementId - * @return Mage_Sales_Model_Order - */ - protected function _initOrder($orderIncrementId) - { - $order = Mage::getModel('Mage_Sales_Model_Order'); - - /* @var $order Mage_Sales_Model_Order */ - - $order->loadByIncrementId($orderIncrementId); - - if (!$order->getId()) { - $this->_fault('not_exists'); - } - - return $order; - } - - /** - * Retrieve list of orders. Filtration could be applied - * - * @param null|object|array $filters - * @return array - */ - public function items($filters = null) - { - $orders = array(); - - //TODO: add full name logic - $billingAliasName = 'billing_o_a'; - $shippingAliasName = 'shipping_o_a'; - - /** @var $orderCollection Mage_Sales_Model_Resource_Order_Collection */ - $orderCollection = Mage::getModel('Mage_Sales_Model_Order')->getCollection(); - $billingFirstnameField = "$billingAliasName.firstname"; - $billingLastnameField = "$billingAliasName.lastname"; - $shippingFirstnameField = "$shippingAliasName.firstname"; - $shippingLastnameField = "$shippingAliasName.lastname"; - $orderCollection->addAttributeToSelect('*') - ->addAddressFields() - ->addExpressionFieldToSelect('billing_firstname', "{{billing_firstname}}", - array('billing_firstname' => $billingFirstnameField)) - ->addExpressionFieldToSelect('billing_lastname', "{{billing_lastname}}", - array('billing_lastname' => $billingLastnameField)) - ->addExpressionFieldToSelect('shipping_firstname', "{{shipping_firstname}}", - array('shipping_firstname' => $shippingFirstnameField)) - ->addExpressionFieldToSelect('shipping_lastname', "{{shipping_lastname}}", - array('shipping_lastname' => $shippingLastnameField)) - ->addExpressionFieldToSelect('billing_name', "CONCAT({{billing_firstname}}, ' ', {{billing_lastname}})", - array('billing_firstname' => $billingFirstnameField, 'billing_lastname' => $billingLastnameField)) - ->addExpressionFieldToSelect('shipping_name', 'CONCAT({{shipping_firstname}}, " ", {{shipping_lastname}})', - array('shipping_firstname' => $shippingFirstnameField, 'shipping_lastname' => $shippingLastnameField) - ); - - /** @var $apiHelper Mage_Api_Helper_Data */ - $apiHelper = Mage::helper('Mage_Api_Helper_Data'); - $filters = $apiHelper->parseFilters($filters, $this->_attributesMap['order']); - try { - foreach ($filters as $field => $value) { - $orderCollection->addFieldToFilter($field, $value); - } - } catch (Mage_Core_Exception $e) { - $this->_fault('filters_invalid', $e->getMessage()); - } - foreach ($orderCollection as $order) { - $orders[] = $this->_getAttributes($order, 'order'); - } - return $orders; - } - - /** - * Retrieve full order information - * - * @param string $orderIncrementId - * @return array - */ - public function info($orderIncrementId) - { - $order = $this->_initOrder($orderIncrementId); - - if ($order->getGiftMessageId() > 0) { - $order->setGiftMessage( - Mage::getSingleton('Mage_GiftMessage_Model_Message')->load($order->getGiftMessageId())->getMessage() - ); - } - - $result = $this->_getAttributes($order, 'order'); - - $result['shipping_address'] = $this->_getAttributes($order->getShippingAddress(), 'order_address'); - $result['billing_address'] = $this->_getAttributes($order->getBillingAddress(), 'order_address'); - $result['items'] = array(); - - foreach ($order->getAllItems() as $item) { - if ($item->getGiftMessageId() > 0) { - $item->setGiftMessage( - Mage::getSingleton('Mage_GiftMessage_Model_Message')->load($item->getGiftMessageId())->getMessage() - ); - } - - $result['items'][] = $this->_getAttributes($item, 'order_item'); - } - - $result['payment'] = $this->_getAttributes($order->getPayment(), 'order_payment'); - - $result['status_history'] = array(); - - foreach ($order->getAllStatusHistory() as $history) { - $result['status_history'][] = $this->_getAttributes($history, 'order_status_history'); - } - - return $result; - } - - /** - * Add comment to order - * - * @param string $orderIncrementId - * @param string $status - * @param string $comment - * @param boolean $notify - * @return boolean - */ - public function addComment($orderIncrementId, $status, $comment = null, $notify = false) - { - $order = $this->_initOrder($orderIncrementId); - - $order->addStatusToHistory($status, $comment, $notify); - - - try { - $order->save(); - $order->sendOrderUpdateEmail($notify, $comment); - } catch (Mage_Core_Exception $e) { - $this->_fault('status_not_changed', $e->getMessage()); - } - - return true; - } - - /** - * Hold order - * - * @param string $orderIncrementId - * @return boolean - */ - public function hold($orderIncrementId) - { - $order = $this->_initOrder($orderIncrementId); - - try { - $order->hold(); - $order->save(); - } catch (Mage_Core_Exception $e) { - $this->_fault('status_not_changed', $e->getMessage()); - } - - return true; - } - - /** - * Unhold order - * - * @param string $orderIncrementId - * @return boolean - */ - public function unhold($orderIncrementId) - { - $order = $this->_initOrder($orderIncrementId); - - try { - $order->unhold(); - $order->save(); - } catch (Mage_Core_Exception $e) { - $this->_fault('status_not_changed', $e->getMessage()); - } - - return true; - } - - /** - * Cancel order - * - * @param string $orderIncrementId - * @return boolean - */ - public function cancel($orderIncrementId) - { - $order = $this->_initOrder($orderIncrementId); - - if (Mage_Sales_Model_Order::STATE_CANCELED == $order->getState()) { - $this->_fault('status_not_changed'); - } - try { - $order->cancel(); - $order->save(); - } catch (Mage_Core_Exception $e) { - $this->_fault('status_not_changed', $e->getMessage()); - } - if (Mage_Sales_Model_Order::STATE_CANCELED != $order->getState()) { - $this->_fault('status_not_changed'); - } - return true; - } - -} // Class Mage_Sales_Model_Order_Api End diff --git a/app/code/core/Mage/Sales/Model/Order/Creditmemo.php b/app/code/core/Mage/Sales/Model/Order/Creditmemo.php index de6aa75a0508522799c0bd2769dd428eff3329e0..889c43d05db3d23001b4d0d975389199e86a44ca 100644 --- a/app/code/core/Mage/Sales/Model/Order/Creditmemo.php +++ b/app/code/core/Mage/Sales/Model/Order/Creditmemo.php @@ -619,7 +619,7 @@ class Mage_Sales_Model_Order_Creditmemo extends Mage_Sales_Model_Abstract $this->setData('base_adjustment_positive', $amount); $amount = $this->getStore()->roundPrice( - $amount*$this->getOrder()->getStoreToOrderRate() + $amount*$this->getOrder()->getBaseToOrderRate() ); $this->setData('adjustment_positive', $amount); return $this; @@ -637,7 +637,7 @@ class Mage_Sales_Model_Order_Creditmemo extends Mage_Sales_Model_Abstract $this->setData('base_adjustment_negative', $amount); $amount = $this->getStore()->roundPrice( - $amount*$this->getOrder()->getStoreToOrderRate() + $amount*$this->getOrder()->getBaseToOrderRate() ); $this->setData('adjustment_negative', $amount); return $this; @@ -647,10 +647,11 @@ class Mage_Sales_Model_Order_Creditmemo extends Mage_Sales_Model_Abstract * Adds comment to credit memo with additional possibility to send it to customer via email * and show it in customer account * + * @param Mage_Sales_Model_Order_Creditmemo_Comment|string $comment * @param bool $notify * @param bool $visibleOnFront * - * @return Mage_Sales_Model_Order_Creditmemo + * @return Mage_Sales_Model_Order_Creditmemo_Comment */ public function addComment($comment, $notify=false, $visibleOnFront=false) { @@ -666,8 +667,8 @@ class Mage_Sales_Model_Order_Creditmemo extends Mage_Sales_Model_Abstract if (!$comment->getId()) { $this->getCommentsCollection()->addItem($comment); } - $this->_hasDataChanges = true; - return $this; + + return $comment; } public function getCommentsCollection($reload=false) diff --git a/app/code/core/Mage/Sales/Model/Order/Creditmemo/Api.php b/app/code/core/Mage/Sales/Model/Order/Creditmemo/Api.php deleted file mode 100644 index 538d68a38c4c6eb4eb2fe956386ba3368c28f0d6..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Sales/Model/Order/Creditmemo/Api.php +++ /dev/null @@ -1,278 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Sales - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Credit memo API - * - * @category Mage - * @package Mage_Sales - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Sales_Model_Order_Creditmemo_Api extends Mage_Sales_Model_Api_Resource -{ - - /** - * Initialize attributes mapping - */ - public function __construct() - { - $this->_attributesMap = array( - 'creditmemo' => array('creditmemo_id' => 'entity_id'), - 'creditmemo_item' => array('item_id' => 'entity_id'), - 'creditmemo_comment' => array('comment_id' => 'entity_id') - ); - } - - /** - * Retrieve credit memos list. Filtration could be applied - * - * @param null|object|array $filters - * @return array - */ - public function items($filters = null) - { - $creditmemos = array(); - /** @var $apiHelper Mage_Api_Helper_Data */ - $apiHelper = Mage::helper('Mage_Api_Helper_Data'); - $filters = $apiHelper->parseFilters($filters, $this->_attributesMap['creditmemo']); - /** @var $creditmemoModel Mage_Sales_Model_Order_Creditmemo */ - $creditmemoModel = Mage::getModel('Mage_Sales_Model_Order_Creditmemo'); - try { - $creditMemoCollection = $creditmemoModel->getFilteredCollectionItems($filters); - foreach ($creditMemoCollection as $creditmemo) { - $creditmemos[] = $this->_getAttributes($creditmemo, 'creditmemo'); - } - } catch (Exception $e) { - $this->_fault('invalid_filter', $e->getMessage()); - } - return $creditmemos; - } - - /** - * Make filter of appropriate format for list method - * - * @deprecated since 1.7.0.1 - * @param array|null $filter - * @return array|null - */ - protected function _prepareListFilter($filter = null) - { - // prepare filter, map field creditmemo_id to entity_id - if (is_array($filter)) { - foreach ($filter as $field => $value) { - if (isset($this->_attributesMap['creditmemo'][$field])) { - $filter[$this->_attributesMap['creditmemo'][$field]] = $value; - unset($filter[$field]); - } - } - } - return $filter; - } - - /** - * Retrieve credit memo information - * - * @param string $creditmemoIncrementId - * @return array - */ - public function info($creditmemoIncrementId) - { - $creditmemo = $this->_getCreditmemo($creditmemoIncrementId); - // get credit memo attributes with entity_id' => 'creditmemo_id' mapping - $result = $this->_getAttributes($creditmemo, 'creditmemo'); - $result['order_increment_id'] = $creditmemo->getOrder()->load($creditmemo->getOrderId())->getIncrementId(); - // items refunded - $result['items'] = array(); - foreach ($creditmemo->getAllItems() as $item) { - $result['items'][] = $this->_getAttributes($item, 'creditmemo_item'); - } - // credit memo comments - $result['comments'] = array(); - foreach ($creditmemo->getCommentsCollection() as $comment) { - $result['comments'][] = $this->_getAttributes($comment, 'creditmemo_comment'); - } - - return $result; - } - - /** - * Create new credit memo for order - * - * @param string $creditmemoIncrementId - * @param array $creditmemoData array('qtys' => array('sku1' => qty1, ... , 'skuN' => qtyN), - * 'shipping_amount' => value, 'adjustment_positive' => value, 'adjustment_negative' => value) - * @param string|null $comment - * @param bool $notifyCustomer - * @param bool $includeComment - * @param string $refundToStoreCreditAmount - * @return string $creditmemoIncrementId - */ - public function create($creditmemoIncrementId, $creditmemoData = null, $comment = null, $notifyCustomer = false, - $includeComment = false, $refundToStoreCreditAmount = null) - { - /** @var $order Mage_Sales_Model_Order */ - $order = Mage::getModel('Mage_Sales_Model_Order')->load($creditmemoIncrementId, 'increment_id'); - if (!$order->getId()) { - $this->_fault('order_not_exists'); - } - if (!$order->canCreditmemo()) { - $this->_fault('cannot_create_creditmemo'); - } - $creditmemoData = $this->_prepareCreateData($creditmemoData); - - /** @var $service Mage_Sales_Model_Service_Order */ - $service = Mage::getModel('Mage_Sales_Model_Service_Order', array('order' => $order)); - /** @var $creditmemo Mage_Sales_Model_Order_Creditmemo */ - $creditmemo = $service->prepareCreditmemo($creditmemoData); - - // refund to Store Credit - if ($refundToStoreCreditAmount) { - // check if refund to Store Credit is available - if ($order->getCustomerIsGuest()) { - $this->_fault('cannot_refund_to_storecredit'); - } - $refundToStoreCreditAmount = max( - 0, - min($creditmemo->getBaseCustomerBalanceReturnMax(), $refundToStoreCreditAmount) - ); - if ($refundToStoreCreditAmount) { - $refundToStoreCreditAmount = $creditmemo->getStore()->roundPrice($refundToStoreCreditAmount); - $creditmemo->setBaseCustomerBalanceTotalRefunded($refundToStoreCreditAmount); - $refundToStoreCreditAmount = $creditmemo->getStore()->roundPrice( - $refundToStoreCreditAmount*$order->getStoreToOrderRate() - ); - // this field can be used by customer balance observer - $creditmemo->setBsCustomerBalTotalRefunded($refundToStoreCreditAmount); - // setting flag to make actual refund to customer balance after credit memo save - $creditmemo->setCustomerBalanceRefundFlag(true); - } - } - $creditmemo->setPaymentRefundDisallowed(true)->register(); - // add comment to creditmemo - if (!empty($comment)) { - $creditmemo->addComment($comment, $notifyCustomer); - } - try { - Mage::getModel('Mage_Core_Model_Resource_Transaction') - ->addObject($creditmemo) - ->addObject($order) - ->save(); - // send email notification - $creditmemo->sendEmail($notifyCustomer, ($includeComment ? $comment : '')); - } catch (Mage_Core_Exception $e) { - $this->_fault('data_invalid', $e->getMessage()); - } - return $creditmemo->getIncrementId(); - } - - /** - * Add comment to credit memo - * - * @param string $creditmemoIncrementId - * @param string $comment - * @param boolean $notifyCustomer - * @param boolean $includeComment - * @return boolean - */ - public function addComment($creditmemoIncrementId, $comment, $notifyCustomer = false, $includeComment = false) - { - $creditmemo = $this->_getCreditmemo($creditmemoIncrementId); - try { - $creditmemo->addComment($comment, $notifyCustomer)->save(); - $creditmemo->sendUpdateEmail($notifyCustomer, ($includeComment ? $comment : '')); - } catch (Mage_Core_Exception $e) { - $this->_fault('data_invalid', $e->getMessage()); - } - - return true; - } - - /** - * Cancel credit memo - * - * @param string $creditmemoIncrementId - * @return boolean - */ - public function cancel($creditmemoIncrementId) - { - $creditmemo = $this->_getCreditmemo($creditmemoIncrementId); - - if (!$creditmemo->canCancel()) { - $this->_fault('status_not_changed', Mage::helper('Mage_Sales_Helper_Data')->__('Credit memo cannot be canceled.')); - } - try { - $creditmemo->cancel()->save(); - } catch (Exception $e) { - $this->_fault('status_not_changed', Mage::helper('Mage_Sales_Helper_Data')->__('Credit memo canceling problem.')); - } - - return true; - } - - /** - * Hook method, could be replaced in derived classes - * - * @param array $data - * @return array - */ - protected function _prepareCreateData($data) - { - $data = isset($data) ? $data : array(); - - if (isset($data['qtys']) && count($data['qtys'])) { - $qtysArray = array(); - foreach ($data['qtys'] as $qKey => $qVal) { - // Save backward compatibility - if (is_array($qVal)) { - if (isset($qVal['order_item_id']) && isset($qVal['qty'])) { - $qtysArray[$qVal['order_item_id']] = $qVal['qty']; - } - } else { - $qtysArray[$qKey] = $qVal; - } - } - $data['qtys'] = $qtysArray; - } - return $data; - } - - /** - * Load CreditMemo by IncrementId - * - * @param mixed $incrementId - * @return Mage_Core_Model_Abstract|Mage_Sales_Model_Order_Creditmemo - */ - protected function _getCreditmemo($incrementId) - { - /** @var $creditmemo Mage_Sales_Model_Order_Creditmemo */ - $creditmemo = Mage::getModel('Mage_Sales_Model_Order_Creditmemo')->load($incrementId, 'increment_id'); - if (!$creditmemo->getId()) { - $this->_fault('not_exists'); - } - return $creditmemo; - } - -} diff --git a/app/code/core/Mage/Sales/Model/Order/Creditmemo/Api/V2.php b/app/code/core/Mage/Sales/Model/Order/Creditmemo/Api/V2.php deleted file mode 100644 index c885e7f5bd1939debb493ff8bbd161dc5e69fe6e..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Sales/Model/Order/Creditmemo/Api/V2.php +++ /dev/null @@ -1,91 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Sales - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Credit memo API - * - * @category Mage - * @package Mage_Sales - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Sales_Model_Order_Creditmemo_Api_V2 extends Mage_Sales_Model_Order_Creditmemo_Api -{ - - /** - * Prepare filters - * - * @deprecated since 1.7.0.1 - * @param null|object $filters - * @return array - */ - protected function _prepareListFilter($filters = null) - { - $preparedFilters = array(); - $helper = Mage::helper('Mage_Api_Helper_Data'); - if (isset($filters->filter)) { - $helper->associativeArrayUnpack($filters->filter); - $preparedFilters += $filters->filter; - } - if (isset($filters->complex_filter)) { - $helper->associativeArrayUnpack($filters->complex_filter); - foreach ($filters->complex_filter as &$filter) { - $helper->associativeArrayUnpack($filter); - } - $preparedFilters += $filters->complex_filter; - } - foreach ($preparedFilters as $field => $value) { - if (isset($this->_attributesMap['creditmemo'][$field])) { - $preparedFilters[$this->_attributesMap['creditmemo'][$field]] = $value; - unset($preparedFilters[$field]); - } - } - - return $preparedFilters; - } - - /** - * Prepare data - * - * @param null|object $data - * @return array - */ - protected function _prepareCreateData($data) - { - // convert data object to array, if it's null turn it into empty array - $data = (isset($data) and is_object($data)) ? get_object_vars($data) : array(); - // convert qtys object to array - if (isset($data['qtys']) && count($data['qtys'])) { - $qtysArray = array(); - foreach ($data['qtys'] as &$item) { - if (isset($item->order_item_id) && isset($item->qty)) { - $qtysArray[$item->order_item_id] = $item->qty; - } - } - $data['qtys'] = $qtysArray; - } - return $data; - } -} diff --git a/app/code/core/Mage/Sales/Model/Order/Invoice/Api.php b/app/code/core/Mage/Sales/Model/Order/Invoice/Api.php deleted file mode 100644 index d156aa37b3562388f533701cbd1a907a20db2364..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Sales/Model/Order/Invoice/Api.php +++ /dev/null @@ -1,309 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Sales - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Invoice API - * - * @category Mage - * @package Mage_Sales - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Sales_Model_Order_Invoice_Api extends Mage_Sales_Model_Api_Resource -{ - /** - * Initialize attributes map - */ - public function __construct() - { - $this->_attributesMap = array( - 'invoice' => array('invoice_id' => 'entity_id'), - 'invoice_item' => array('item_id' => 'entity_id'), - 'invoice_comment' => array('comment_id' => 'entity_id')); - } - - /** - * Retrive invoices list. Filtration could be applied - * - * @param null|object|array $filters - * @return array - */ - public function items($filters = null) - { - $invoices = array(); - /** @var $invoiceCollection Mage_Sales_Model_Resource_Order_Invoice_Collection */ - $invoiceCollection = Mage::getResourceModel('Mage_Sales_Model_Resource_Order_Invoice_Collection'); - $invoiceCollection->addAttributeToSelect('entity_id') - ->addAttributeToSelect('order_id') - ->addAttributeToSelect('increment_id') - ->addAttributeToSelect('created_at') - ->addAttributeToSelect('state') - ->addAttributeToSelect('grand_total') - ->addAttributeToSelect('order_currency_code'); - - /** @var $apiHelper Mage_Api_Helper_Data */ - $apiHelper = Mage::helper('Mage_Api_Helper_Data'); - try { - $filters = $apiHelper->parseFilters($filters, $this->_attributesMap['invoice']); - foreach ($filters as $field => $value) { - $invoiceCollection->addFieldToFilter($field, $value); - } - } catch (Mage_Core_Exception $e) { - $this->_fault('filters_invalid', $e->getMessage()); - } - foreach ($invoiceCollection as $invoice) { - $invoices[] = $this->_getAttributes($invoice, 'invoice'); - } - return $invoices; - } - - /** - * Retrieve invoice information - * - * @param string $invoiceIncrementId - * @return array - */ - public function info($invoiceIncrementId) - { - $invoice = Mage::getModel('Mage_Sales_Model_Order_Invoice')->loadByIncrementId($invoiceIncrementId); - - /* @var Mage_Sales_Model_Order_Invoice $invoice */ - - if (!$invoice->getId()) { - $this->_fault('not_exists'); - } - - $result = $this->_getAttributes($invoice, 'invoice'); - $result['order_increment_id'] = $invoice->getOrderIncrementId(); - - $result['items'] = array(); - foreach ($invoice->getAllItems() as $item) { - $result['items'][] = $this->_getAttributes($item, 'invoice_item'); - } - - $result['comments'] = array(); - foreach ($invoice->getCommentsCollection() as $comment) { - $result['comments'][] = $this->_getAttributes($comment, 'invoice_comment'); - } - - return $result; - } - - /** - * Create new invoice for order - * - * @param string $orderIncrementId - * @param array $itemsQty - * @param string $comment - * @param booleam $email - * @param boolean $includeComment - * @return string - */ - public function create($orderIncrementId, $itemsQty, $comment = null, $email = false, $includeComment = false) - { - $order = Mage::getModel('Mage_Sales_Model_Order')->loadByIncrementId($orderIncrementId); - - /* @var $order Mage_Sales_Model_Order */ - /** - * Check order existing - */ - if (!$order->getId()) { - $this->_fault('order_not_exists'); - } - - /** - * Check invoice create availability - */ - if (!$order->canInvoice()) { - $this->_fault('data_invalid', Mage::helper('Mage_Sales_Helper_Data')->__('Cannot do invoice for order.')); - } - - $invoice = $order->prepareInvoice($itemsQty); - - $invoice->register(); - - if ($comment !== null) { - $invoice->addComment($comment, $email); - } - - if ($email) { - $invoice->setEmailSent(true); - } - - $invoice->getOrder()->setIsInProcess(true); - - try { - $transactionSave = Mage::getModel('Mage_Core_Model_Resource_Transaction') - ->addObject($invoice) - ->addObject($invoice->getOrder()) - ->save(); - - $invoice->sendEmail($email, ($includeComment ? $comment : '')); - } catch (Mage_Core_Exception $e) { - $this->_fault('data_invalid', $e->getMessage()); - } - - return $invoice->getIncrementId(); - } - - /** - * Add comment to invoice - * - * @param string $invoiceIncrementId - * @param string $comment - * @param boolean $email - * @param boolean $includeComment - * @return boolean - */ - public function addComment($invoiceIncrementId, $comment, $email = false, $includeComment = false) - { - $invoice = Mage::getModel('Mage_Sales_Model_Order_Invoice')->loadByIncrementId($invoiceIncrementId); - - /* @var $invoice Mage_Sales_Model_Order_Invoice */ - - if (!$invoice->getId()) { - $this->_fault('not_exists'); - } - - - try { - $invoice->addComment($comment, $email); - $invoice->sendUpdateEmail($email, ($includeComment ? $comment : '')); - $invoice->save(); - } catch (Mage_Core_Exception $e) { - $this->_fault('data_invalid', $e->getMessage()); - } - - return true; - } - - /** - * Capture invoice - * - * @param string $invoiceIncrementId - * @return boolean - */ - public function capture($invoiceIncrementId) - { - $invoice = Mage::getModel('Mage_Sales_Model_Order_Invoice')->loadByIncrementId($invoiceIncrementId); - - /* @var $invoice Mage_Sales_Model_Order_Invoice */ - - if (!$invoice->getId()) { - $this->_fault('not_exists'); - } - - if (!$invoice->canCapture()) { - $this->_fault('status_not_changed', Mage::helper('Mage_Sales_Helper_Data')->__('Invoice cannot be captured.')); - } - - try { - $invoice->capture(); - $invoice->getOrder()->setIsInProcess(true); - $transactionSave = Mage::getModel('Mage_Core_Model_Resource_Transaction') - ->addObject($invoice) - ->addObject($invoice->getOrder()) - ->save(); - } catch (Mage_Core_Exception $e) { - $this->_fault('status_not_changed', $e->getMessage()); - } catch (Exception $e) { - $this->_fault('status_not_changed', Mage::helper('Mage_Sales_Helper_Data')->__('Invoice capturing problem.')); - } - - return true; - } - - /** - * Void invoice - * - * @param unknown_type $invoiceIncrementId - * @return unknown - */ - public function void($invoiceIncrementId) - { - $invoice = Mage::getModel('Mage_Sales_Model_Order_Invoice')->loadByIncrementId($invoiceIncrementId); - - /* @var $invoice Mage_Sales_Model_Order_Invoice */ - - if (!$invoice->getId()) { - $this->_fault('not_exists'); - } - - if (!$invoice->canVoid()) { - $this->_fault('status_not_changed', Mage::helper('Mage_Sales_Helper_Data')->__('Invoice cannot be voided.')); - } - - try { - $invoice->void(); - $invoice->getOrder()->setIsInProcess(true); - $transactionSave = Mage::getModel('Mage_Core_Model_Resource_Transaction') - ->addObject($invoice) - ->addObject($invoice->getOrder()) - ->save(); - } catch (Mage_Core_Exception $e) { - $this->_fault('status_not_changed', $e->getMessage()); - } catch (Exception $e) { - $this->_fault('status_not_changed', Mage::helper('Mage_Sales_Helper_Data')->__('Invoice void problem')); - } - - return true; - } - - /** - * Cancel invoice - * - * @param string $invoiceIncrementId - * @return boolean - */ - public function cancel($invoiceIncrementId) - { - $invoice = Mage::getModel('Mage_Sales_Model_Order_Invoice')->loadByIncrementId($invoiceIncrementId); - - /* @var $invoice Mage_Sales_Model_Order_Invoice */ - - if (!$invoice->getId()) { - $this->_fault('not_exists'); - } - - if (!$invoice->canCancel()) { - $this->_fault('status_not_changed', Mage::helper('Mage_Sales_Helper_Data')->__('Invoice cannot be canceled.')); - } - - try { - $invoice->cancel(); - $invoice->getOrder()->setIsInProcess(true); - $transactionSave = Mage::getModel('Mage_Core_Model_Resource_Transaction') - ->addObject($invoice) - ->addObject($invoice->getOrder()) - ->save(); - } catch (Mage_Core_Exception $e) { - $this->_fault('status_not_changed', $e->getMessage()); - } catch (Exception $e) { - $this->_fault('status_not_changed', Mage::helper('Mage_Sales_Helper_Data')->__('Invoice canceling problem.')); - } - - return true; - } -} diff --git a/app/code/core/Mage/Sales/Model/Order/Invoice/Api/V2.php b/app/code/core/Mage/Sales/Model/Order/Invoice/Api/V2.php deleted file mode 100644 index 518dfaf984d0a64f153b5aadc9058ec49e7eaf2e..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Sales/Model/Order/Invoice/Api/V2.php +++ /dev/null @@ -1,105 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Sales - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Invoice API V2 - * - * @category Mage - * @package Mage_Sales - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Sales_Model_Order_Invoice_Api_V2 extends Mage_Sales_Model_Order_Invoice_Api -{ - /** - * Create new invoice for order - * - * @param string $invoiceIncrementId - * @param array $itemsQty - * @param string $comment - * @param bool $email - * @param bool $includeComment - * @return string - */ - public function create($invoiceIncrementId, $itemsQty, $comment = null, $email = false, $includeComment = false) - { - $order = Mage::getModel('Mage_Sales_Model_Order')->loadByIncrementId($invoiceIncrementId); - $itemsQty = $this->_prepareItemQtyData($itemsQty); - /* @var $order Mage_Sales_Model_Order */ - /** - * Check order existing - */ - if (!$order->getId()) { - $this->_fault('order_not_exists'); - } - - /** - * Check invoice create availability - */ - if (!$order->canInvoice()) { - $this->_fault('data_invalid', Mage::helper('Mage_Sales_Helper_Data')->__('Cannot do invoice for order.')); - } - - $invoice = $order->prepareInvoice($itemsQty); - - $invoice->register(); - - if ($comment !== null) { - $invoice->addComment($comment, $email); - } - - if ($email) { - $invoice->setEmailSent(true); - } - - $invoice->getOrder()->setIsInProcess(true); - - try { - Mage::getModel('Mage_Core_Model_Resource_Transaction')->addObject($invoice)->addObject($invoice->getOrder())->save(); - $invoice->sendEmail($email, ($includeComment ? $comment : '')); - } catch (Mage_Core_Exception $e) { - $this->_fault('data_invalid', $e->getMessage()); - } - - return $invoice->getIncrementId(); - } - - /** - * Prepare items quantity data - * - * @param array $data - * @return array - */ - protected function _prepareItemQtyData($data) - { - $quantity = array(); - foreach ($data as $item) { - if (isset($item->order_item_id) && isset($item->qty)) { - $quantity[$item->order_item_id] = $item->qty; - } - } - return $quantity; - } -} diff --git a/app/code/core/Mage/Sales/Model/Order/Shipment/Api.php b/app/code/core/Mage/Sales/Model/Order/Shipment/Api.php deleted file mode 100644 index 65d0830b36bd6e899f03dbc30431bd6d1fd0a82b..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Sales/Model/Order/Shipment/Api.php +++ /dev/null @@ -1,381 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Sales - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Sales order shippment API - * - * @category Mage - * @package Mage_Sales - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Sales_Model_Order_Shipment_Api extends Mage_Sales_Model_Api_Resource -{ - public function __construct() - { - $this->_attributesMap['shipment'] = array('shipment_id' => 'entity_id'); - - $this->_attributesMap['shipment_item'] = array('item_id' => 'entity_id'); - - $this->_attributesMap['shipment_comment'] = array('comment_id' => 'entity_id'); - - $this->_attributesMap['shipment_track'] = array('track_id' => 'entity_id'); - } - - /** - * Retrieve shipments by filters - * - * @param null|object|array $filters - * @return array - */ - public function items($filters = null) - { - $shipments = array(); - //TODO: add full name logic - $shipmentCollection = Mage::getResourceModel('Mage_Sales_Model_Resource_Order_Shipment_Collection') - ->addAttributeToSelect('increment_id') - ->addAttributeToSelect('created_at') - ->addAttributeToSelect('total_qty') - ->joinAttribute('shipping_firstname', 'order_address/firstname', 'shipping_address_id', null, 'left') - ->joinAttribute('shipping_lastname', 'order_address/lastname', 'shipping_address_id', null, 'left') - ->joinAttribute('order_increment_id', 'order/increment_id', 'order_id', null, 'left') - ->joinAttribute('order_created_at', 'order/created_at', 'order_id', null, 'left'); - - /** @var $apiHelper Mage_Api_Helper_Data */ - $apiHelper = Mage::helper('Mage_Api_Helper_Data'); - try { - $filters = $apiHelper->parseFilters($filters, $this->_attributesMap['shipment']); - foreach ($filters as $field => $value) { - $shipmentCollection->addFieldToFilter($field, $value); - } - } catch (Mage_Core_Exception $e) { - $this->_fault('filters_invalid', $e->getMessage()); - } - foreach ($shipmentCollection as $shipment) { - $shipments[] = $this->_getAttributes($shipment, 'shipment'); - } - - return $shipments; - } - - /** - * Retrieve shipment information - * - * @param string $shipmentIncrementId - * @return array - */ - public function info($shipmentIncrementId) - { - $shipment = Mage::getModel('Mage_Sales_Model_Order_Shipment')->loadByIncrementId($shipmentIncrementId); - - /* @var $shipment Mage_Sales_Model_Order_Shipment */ - - if (!$shipment->getId()) { - $this->_fault('not_exists'); - } - - $result = $this->_getAttributes($shipment, 'shipment'); - - $result['items'] = array(); - foreach ($shipment->getAllItems() as $item) { - $result['items'][] = $this->_getAttributes($item, 'shipment_item'); - } - - $result['tracks'] = array(); - foreach ($shipment->getAllTracks() as $track) { - $result['tracks'][] = $this->_getAttributes($track, 'shipment_track'); - } - - $result['comments'] = array(); - foreach ($shipment->getCommentsCollection() as $comment) { - $result['comments'][] = $this->_getAttributes($comment, 'shipment_comment'); - } - - return $result; - } - - /** - * Create new shipment for order - * - * @param string $orderIncrementId - * @param array $itemsQty - * @param string $comment - * @param booleam $email - * @param boolean $includeComment - * @return string - */ - public function create($orderIncrementId, $itemsQty = array(), $comment = null, $email = false, - $includeComment = false - ) { - $order = Mage::getModel('Mage_Sales_Model_Order')->loadByIncrementId($orderIncrementId); - - /** - * Check order existing - */ - if (!$order->getId()) { - $this->_fault('order_not_exists'); - } - - /** - * Check shipment create availability - */ - if (!$order->canShip()) { - $this->_fault('data_invalid', Mage::helper('Mage_Sales_Helper_Data')->__('Cannot do shipment for order.')); - } - - /* @var $shipment Mage_Sales_Model_Order_Shipment */ - $shipment = $order->prepareShipment($itemsQty); - if ($shipment) { - $shipment->register(); - $shipment->addComment($comment, $email && $includeComment); - if ($email) { - $shipment->setEmailSent(true); - } - $shipment->getOrder()->setIsInProcess(true); - try { - $transactionSave = Mage::getModel('Mage_Core_Model_Resource_Transaction') - ->addObject($shipment) - ->addObject($shipment->getOrder()) - ->save(); - $shipment->sendEmail($email, ($includeComment ? $comment : '')); - } catch (Mage_Core_Exception $e) { - $this->_fault('data_invalid', $e->getMessage()); - } - return $shipment->getIncrementId(); - } - return null; - } - - /** - * Add tracking number to order - * - * @param string $shipmentIncrementId - * @param string $carrier - * @param string $title - * @param string $trackNumber - * @return int - */ - public function addTrack($shipmentIncrementId, $carrier, $title, $trackNumber) - { - $shipment = Mage::getModel('Mage_Sales_Model_Order_Shipment')->loadByIncrementId($shipmentIncrementId); - - /* @var $shipment Mage_Sales_Model_Order_Shipment */ - - if (!$shipment->getId()) { - $this->_fault('not_exists'); - } - - $carriers = $this->_getCarriers($shipment); - - if (!isset($carriers[$carrier])) { - $this->_fault('data_invalid', Mage::helper('Mage_Sales_Helper_Data')->__('Invalid carrier specified.')); - } - - $track = Mage::getModel('Mage_Sales_Model_Order_Shipment_Track') - ->setNumber($trackNumber) - ->setCarrierCode($carrier) - ->setTitle($title); - - $shipment->addTrack($track); - - try { - $shipment->save(); - $track->save(); - } catch (Mage_Core_Exception $e) { - $this->_fault('data_invalid', $e->getMessage()); - } - - return $track->getId(); - } - - /** - * Remove tracking number - * - * @param string $shipmentIncrementId - * @param int $trackId - * @return boolean - */ - public function removeTrack($shipmentIncrementId, $trackId) - { - $shipment = Mage::getModel('Mage_Sales_Model_Order_Shipment')->loadByIncrementId($shipmentIncrementId); - - /* @var $shipment Mage_Sales_Model_Order_Shipment */ - - if (!$shipment->getId()) { - $this->_fault('not_exists'); - } - - if(!$track = $shipment->getTrackById($trackId)) { - $this->_fault('track_not_exists'); - } - - try { - $track->delete(); - } catch (Mage_Core_Exception $e) { - $this->_fault('track_not_deleted', $e->getMessage()); - } - - return true; - } - - /** - * Send email with shipment data to customer - * - * @param string $shipmentIncrementId - * @param string $comment - * @return bool - */ - public function sendInfo($shipmentIncrementId, $comment = '') - { - /* @var $shipment Mage_Sales_Model_Order_Shipment */ - $shipment = Mage::getModel('Mage_Sales_Model_Order_Shipment')->loadByIncrementId($shipmentIncrementId); - - if (!$shipment->getId()) { - $this->_fault('not_exists'); - } - - try { - $shipment->sendEmail(true, $comment) - ->setEmailSent(true) - ->save(); - $historyItem = Mage::getResourceModel('Mage_Sales_Model_Resource_Order_Status_History_Collection') - ->getUnnotifiedForInstance($shipment, Mage_Sales_Model_Order_Shipment::HISTORY_ENTITY_NAME); - if ($historyItem) { - $historyItem->setIsCustomerNotified(1); - $historyItem->save(); - } - } catch (Mage_Core_Exception $e) { - $this->_fault('data_invalid', $e->getMessage()); - } - - return true; - } - - /** - * Retrieve tracking number info - * - * @param string $shipmentIncrementId - * @param int $trackId - * @return mixed - */ - public function infoTrack($shipmentIncrementId, $trackId) - { - $shipment = Mage::getModel('Mage_Sales_Model_Order_Shipment')->loadByIncrementId($shipmentIncrementId); - - /* @var $shipment Mage_Sales_Model_Order_Shipment */ - - if (!$shipment->getId()) { - $this->_fault('not_exists'); - } - - if(!$track = $shipment->getTrackById($trackId)) { - $this->_fault('track_not_exists'); - } - - /* @var $track Mage_Sales_Model_Order_Shipment_Track */ - $info = $track->getNumberDetail(); - - if (is_object($info)) { - $info = $info->toArray(); - } - - return $info; - } - - /** - * Add comment to shipment - * - * @param string $shipmentIncrementId - * @param string $comment - * @param boolean $email - * @param boolean $includeInEmail - * @return boolean - */ - public function addComment($shipmentIncrementId, $comment, $email = false, $includeInEmail = false) - { - $shipment = Mage::getModel('Mage_Sales_Model_Order_Shipment')->loadByIncrementId($shipmentIncrementId); - - /* @var $shipment Mage_Sales_Model_Order_Shipment */ - - if (!$shipment->getId()) { - $this->_fault('not_exists'); - } - - - try { - $shipment->addComment($comment, $email); - $shipment->sendUpdateEmail($email, ($includeInEmail ? $comment : '')); - $shipment->save(); - } catch (Mage_Core_Exception $e) { - $this->_fault('data_invalid', $e->getMessage()); - } - - return true; - } - - /** - * Retrieve allowed shipping carriers for specified order - * - * @param string $orderIncrementId - * @return array - */ - public function getCarriers($orderIncrementId) - { - $order = Mage::getModel('Mage_Sales_Model_Order')->loadByIncrementId($orderIncrementId); - - /** - * Check order existing - */ - if (!$order->getId()) { - $this->_fault('order_not_exists'); - } - - return $this->_getCarriers($order); - } - - /** - * Retrieve shipping carriers for specified order - * - * @param Mage_Eav_Model_Entity_Abstract $object - * @return array - */ - protected function _getCarriers($object) - { - $carriers = array(); - $carrierInstances = Mage::getSingleton('Mage_Shipping_Model_Config')->getAllCarriers( - $object->getStoreId() - ); - - $carriers['custom'] = Mage::helper('Mage_Sales_Helper_Data')->__('Custom Value'); - foreach ($carrierInstances as $code => $carrier) { - if ($carrier->isTrackingAvailable()) { - $carriers[$code] = $carrier->getConfigData('title'); - } - } - - return $carriers; - } - -} // Class Mage_Sales_Model_Order_Shipment_Api End diff --git a/app/code/core/Mage/Sales/Model/Order/Shipment/Api/V2.php b/app/code/core/Mage/Sales/Model/Order/Shipment/Api/V2.php deleted file mode 100644 index 798ab9582fd8f7a463a446004d2f20ab3a22ae01..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Sales/Model/Order/Shipment/Api/V2.php +++ /dev/null @@ -1,122 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Sales - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Sales order shippment API V2 - * - * @category Mage - * @package Mage_Sales - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Sales_Model_Order_Shipment_Api_V2 extends Mage_Sales_Model_Order_Shipment_Api -{ - protected function _prepareItemQtyData($data) - { - $_data = array(); - foreach ($data as $item) { - if (isset($item->order_item_id) && isset($item->qty)) { - $_data[$item->order_item_id] = $item->qty; - } - } - return $_data; - } - - /** - * Create new shipment for order - * - * @param string $orderIncrementId - * @param array $itemsQty - * @param string $comment - * @param boolean $email - * @param boolean $includeComment - * @return string - */ - public function create($orderIncrementId, $itemsQty = array(), $comment = null, $email = false, - $includeComment = false - ) { - $order = Mage::getModel('Mage_Sales_Model_Order')->loadByIncrementId($orderIncrementId); - $itemsQty = $this->_prepareItemQtyData($itemsQty); - /** - * Check order existing - */ - if (!$order->getId()) { - $this->_fault('order_not_exists'); - } - - /** - * Check shipment create availability - */ - if (!$order->canShip()) { - $this->_fault('data_invalid', Mage::helper('Mage_Sales_Helper_Data')->__('Cannot do shipment for order.')); - } - - /* @var $shipment Mage_Sales_Model_Order_Shipment */ - $shipment = $order->prepareShipment($itemsQty); - if ($shipment) { - $shipment->register(); - $shipment->addComment($comment, $email && $includeComment); - if ($email) { - $shipment->setEmailSent(true); - } - $shipment->getOrder()->setIsInProcess(true); - try { - $transactionSave = Mage::getModel('Mage_Core_Model_Resource_Transaction') - ->addObject($shipment) - ->addObject($shipment->getOrder()) - ->save(); - $shipment->sendEmail($email, ($includeComment ? $comment : '')); - } catch (Mage_Core_Exception $e) { - $this->_fault('data_invalid', $e->getMessage()); - } - return $shipment->getIncrementId(); - } - return null; - } - - /** - * Retrieve allowed shipping carriers for specified order - * - * @param string $orderIncrementId - * @return array - */ - public function getCarriers($orderIncrementId) - { - $order = Mage::getModel('Mage_Sales_Model_Order')->loadByIncrementId($orderIncrementId); - - /** - * Check order existing - */ - if (!$order->getId()) { - $this->_fault('order_not_exists'); - } - $carriers = array(); - foreach ($this->_getCarriers($order) as $key => $value) { - $carriers[] = array('key' => $key, 'value' => $value); - } - - return $carriers; - } -} diff --git a/app/code/core/Mage/Sales/etc/api.xml b/app/code/core/Mage/Sales/etc/api.xml deleted file mode 100644 index 20e0a9fc46e96bff32a7c64e997f220ec23d1abe..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Sales/etc/api.xml +++ /dev/null @@ -1,375 +0,0 @@ -<?xml version="1.0"?> -<!-- -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Academic Free License (AFL 3.0) - * that is bundled with this package in the file LICENSE_AFL.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/afl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Sales - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) - */ ---> -<config> - <api> - <resources> - <sales_order translate="title" module="Mage_Sales"> - <model>Mage_Sales_Model_Order_Api</model> - <title>Order API</title> - <acl>sales/order</acl> - <methods> - <list translate="title" module="Mage_Sales"> - <title>Retrieve list of orders by filters</title> - <method>items</method> - <acl>sales/order/info</acl> - </list> - <info translate="title" module="Mage_Sales"> - <title>Retrieve order information</title> - <acl>sales/order/info</acl> - </info> - <addComment translate="title" module="Mage_Sales"> - <title>Add comment to order</title> - <acl>sales/order/change</acl> - </addComment> - <hold translate="title" module="Mage_Sales"> - <title>Hold order</title> - <acl>sales/order/change</acl> - </hold> - <unhold translate="title" module="Mage_Sales"> - <title>Unhold order</title> - <acl>sales/order/change</acl> - </unhold> - <cancel translate="title" module="Mage_Sales"> - <title>Cancel order</title> - <acl>sales/order/change</acl> - </cancel> - </methods> - <faults module="Mage_Sales"> - <not_exists> - <code>100</code> - <message>Requested order not exists.</message> - </not_exists> - <filters_invalid> - <code>101</code> - <message>Invalid filters given. Details in error message.</message> - </filters_invalid> - <data_invalid> - <code>102</code> - <message>Invalid data given. Details in error message.</message> - </data_invalid> - <status_not_changed> - <code>103</code> - <message>Order status not changed. Details in error message.</message> - </status_not_changed> - </faults> - </sales_order> - <sales_order_shipment> - <title>Shipment API</title> - <model>Mage_Sales_Model_Order_Shipment_Api</model> - <acl>sales/order/shipment</acl> - <methods> - <list translate="title" module="Mage_Sales"> - <title>Retrieve list of shipments by filters</title> - <method>items</method> - <acl>sales/order/shipment/info</acl> - </list> - <info translate="title" module="Mage_Sales"> - <title>Retrieve shipment information</title> - <acl>sales/order/shipment/info</acl> - </info> - <sendInfo translate="title" module="Mage_Sales"> - <title>Send shipment info</title> - <acl>sales/order/shipment/send</acl> - </sendInfo> - <create translate="title" module="Mage_Sales"> - <title>Create new shipment for order</title> - <acl>sales/order/shipment/create</acl> - </create> - <addComment translate="title" module="Mage_Sales"> - <title>Add new comment to shipment</title> - <acl>sales/order/shipment/comment</acl> - </addComment> - <addTrack translate="title" module="Mage_Sales"> - <title>Add new tracking number</title> - <acl>sales/order/shipment/track</acl> - </addTrack> - <removeTrack translate="title" module="Mage_Sales"> - <title>Remove tracking number</title> - <acl>sales/order/shipment/track</acl> - </removeTrack> - <getCarriers> - <title>Retrieve list of allowed carriers for order</title> - </getCarriers> - </methods> - <faults module="Mage_Sales"> - <not_exists> - <code>100</code> - <message>Requested shipment not exists.</message> - </not_exists> - <filters_invalid> - <code>101</code> - <message>Invalid filters given. Details in error message.</message> - </filters_invalid> - <data_invalid> - <code>102</code> - <message>Invalid data given. Details in error message.</message> - </data_invalid> - <order_not_exists> - <code>103</code> - <message>Requested order not exists.</message> - </order_not_exists> - <track_not_exists> - <code>104</code> - <message>Requested tracking not exists.</message> - </track_not_exists> - <track_not_deleted> - <code>105</code> - <message>Tracking not deleted. Details in error message.</message> - </track_not_deleted> - </faults> - </sales_order_shipment> - <sales_order_invoice> - <title>Invoice API</title> - <model>Mage_Sales_Model_Order_Invoice_Api</model> - <acl>sales/order/invoice</acl> - <methods> - <list translate="title" module="Mage_Sales"> - <title>Retrieve list of invoices by filters</title> - <method>items</method> - <acl>sales/order/invoice/info</acl> - </list> - <info translate="title" module="Mage_Sales"> - <title>Retrieve invoice information</title> - <acl>sales/order/invoice/info</acl> - </info> - <create translate="title" module="Mage_Sales"> - <title>Create new invoice for order</title> - <acl>sales/order/invoice/create</acl> - </create> - <addComment translate="title" module="Mage_Sales"> - <title>Add new comment to shipment</title> - <acl>sales/order/invoice/comment</acl> - </addComment> - <capture translate="title" module="Mage_Sales"> - <title>Capture invoice</title> - <acl>sales/order/invoice/capture</acl> - </capture> - <void translate="title" module="Mage_Sales"> - <title>Void invoice</title> - <acl>sales/order/invoice/void</acl> - </void> - <cancel translate="title" module="Mage_Sales"> - <title>Cancel invoice</title> - <acl>sales/order/invoice/cancel</acl> - </cancel> - </methods> - <faults module="Mage_Sales"> - <not_exists> - <code>100</code> - <message>Requested invoice does not exist.</message> - </not_exists> - <invalid_filter> - <code>101</code> - <message>Invalid filter given. Details in error message.</message> - </invalid_filter> - <data_invalid> - <code>102</code> - <message>Invalid data given. Details in error message.</message> - </data_invalid> - <order_not_exists> - <code>103</code> - <message>Requested order not exists.</message> - </order_not_exists> - <status_not_changed> - <code>104</code> - <message>Invoice status not changed</message> - </status_not_changed> - </faults> - </sales_order_invoice> - <sales_order_creditmemo> - <title>Credit memo API</title> - <model>Mage_Sales_Model_Order_Creditmemo_Api</model> - <acl>sales/order/creditmemo</acl> - <methods> - <list translate="title" module="Mage_Sales"> - <title>Retrieve list of credit memos by filters</title> - <method>items</method> - <acl>sales/order/creditmemo/list</acl> - </list> - <info translate="title" module="Mage_Sales"> - <title>Retrieve credit memo information</title> - <acl>sales/order/creditmemo/info</acl> - </info> - <create translate="title" module="Mage_Sales"> - <title>Create new credit memo for order</title> - <acl>sales/order/creditmemo/create</acl> - </create> - <addComment translate="title" module="Mage_Sales"> - <title>Add new comment to credit memo</title> - <acl>sales/order/creditmemo/comment</acl> - </addComment> - <cancel translate="title" module="Mage_Sales"> - <title>Cancel credit memo</title> - <acl>sales/order/creditmemo/cancel</acl> - </cancel> - </methods> - <faults module="Mage_Sales"> - <not_exists> - <code>100</code> - <message>Requested credit memo does not exist</message> - </not_exists> - <invalid_filter> - <code>101</code> - <message>Invalid filter given. Details in error message</message> - </invalid_filter> - <data_invalid> - <code>102</code> - <message>Invalid data given. Details in error message</message> - </data_invalid> - <order_not_exists> - <code>103</code> - <message>Requested order does not exist</message> - </order_not_exists> - <status_not_changed> - <code>104</code> - <message>Credit memo status not changed</message> - </status_not_changed> - <cannot_refund_to_storecredit> - <code>105</code> - <message>Money can not be refunded to the store credit account as order was created by guest</message> - </cannot_refund_to_storecredit> - <cannot_create_creditmemo> - <code>106</code> - <message>Credit memo for requested order can not be created.</message> - </cannot_create_creditmemo> - </faults> - </sales_order_creditmemo> - </resources> - <resources_alias> - <order>sales_order</order> - <order_shipment>sales_order_shipment</order_shipment> - <order_invoice>sales_order_invoice</order_invoice> - <order_creditmemo>sales_order_creditmemo</order_creditmemo> - </resources_alias> - <v2> - <resources_function_prefix> - <order>salesOrder</order> - <order_shipment>salesOrderShipment</order_shipment> - <order_invoice>salesOrderInvoice</order_invoice> - <order_creditmemo>salesOrderCreditmemo</order_creditmemo> - </resources_function_prefix> - </v2> - <rest> - <mapping> - <sales_order> - <delete> - <method>cancel</method> - </delete> - <post> - <resource>cart</resource> - <method>order</method> - </post> - </sales_order> - <sales_order_invoice> - <delete> - <method>cancel</method> - </delete> - </sales_order_invoice> - <sales_order_creditmemo> - <delete> - <method>cancel</method> - </delete> - </sales_order_creditmemo> - </mapping> - </rest> - <acl> - <resources> - <sales translate="title" module="Mage_Sales"> - <title>Sales</title> - <sort_order>2</sort_order> - <order translate="title" module="Mage_Sales"> - <title>Order</title> - <change translate="title" module="Mage_Sales"> - <title>Change status, add comments</title> - </change> - <info translate="title" module="Mage_Sales"> - <title>Retrieve orders info</title> - </info> - <shipment translate="title" module="Mage_Sales"> - <title>Order shipments</title> - <create translate="title" module="Mage_Sales"> - <title>Create</title> - </create> - <comment translate="title" module="Mage_Sales"> - <title>Comments</title> - </comment> - <track translate="title" module="Mage_Sales"> - <title>Tracking</title> - </track> - <info translate="title" module="Mage_Sales"> - <title>Retrieve shipment info</title> - </info> - <send translate="title" module="Mage_Sales"> - <title>Send shipment info</title> - </send> - </shipment> - <invoice translate="title" module="Mage_Sales"> - <title>Order invoice</title> - <create translate="title" module="Mage_Sales"> - <title>Create</title> - </create> - <comment translate="title" module="Mage_Sales"> - <title>Comments</title> - </comment> - <capture translate="title" module="Mage_Sales"> - <title>Capture</title> - </capture> - <void translate="title" module="Mage_Sales"> - <title>Void</title> - </void> - <cancel translate="title" module="Mage_Sales"> - <title>Cancel</title> - </cancel> - <info translate="title" module="Mage_Sales"> - <title>Retrieve invoice info</title> - </info> - </invoice> - <creditmemo translate="title" module="Mage_Sales"> - <title>Order credit memo</title> - <create translate="title" module="Mage_Sales"> - <title>Create</title> - </create> - <comment translate="title" module="Mage_Sales"> - <title>Comments</title> - </comment> - <cancel translate="title" module="Mage_Sales"> - <title>Cancel</title> - </cancel> - <info translate="title" module="Mage_Sales"> - <title>Retrieve credit memo info</title> - </info> - <list translate="title" module="Mage_Sales"> - <title>Retrieve credit memo list</title> - </list> - </creditmemo> - </order> - </sales> - </resources> - </acl> - </api> -</config> diff --git a/app/code/core/Mage/Sales/etc/api2.xml b/app/code/core/Mage/Sales/etc/api2.xml deleted file mode 100644 index 9e96f69fb65aabd1bf90d864eea12ccd9207183d..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Sales/etc/api2.xml +++ /dev/null @@ -1,310 +0,0 @@ -<?xml version="1.0"?> -<!-- -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Academic Free License (AFL 3.0) - * that is bundled with this package in the file LICENSE_AFL.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/afl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Sales - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) - */ ---> -<config> - <api2> - <resource_groups> - <sales translate="title" module="Mage_Api2"> - <title>Sales</title> - <sort_order>130</sort_order> - <children> - <sales_order translate="title" module="Mage_Api2"> - <title>Order</title> - <sort_order>150</sort_order> - </sales_order> - </children> - </sales> - </resource_groups> - <resources> - <order translate="title" module="Mage_Api2"> - <group>sales</group> - <sort_order>10</sort_order> - <model>Mage_Sales_Model_Api2_Order</model> - <title>Orders</title> - <privileges> - <admin> - <retrieve>1</retrieve> - </admin> - <customer> - <retrieve>1</retrieve> - </customer> - </privileges> - <routes> - <route_entity> - <route>/orders/:id</route> - <action_type>entity</action_type> - </route_entity> - <route_collection> - <route>/orders</route> - <action_type>collection</action_type> - </route_collection> - </routes> - <attributes translate="entity_id increment_id created_at status shipping_description _payment_method base_currency_code store_currency_code store_name remote_ip store_to_order_rate subtotal subtotal_incl_tax discount_amount base_grand_total grand_total shipping_amount shipping_tax_amount shipping_incl_tax tax_amount _tax_name _tax_rate coupon_code base_discount_amount base_subtotal base_shipping_amount base_shipping_tax_amount base_tax_amount total_paid base_total_paid total_refunded base_total_refunded base_subtotal_incl_tax base_total_due total_due shipping_discount_amount base_shipping_discount_amount discount_description customer_balance_amount base_customer_balance_amount base_customer_balance_amount _gift_message _order_comments customer_id" module="Mage_Api2"> - <entity_id>Order ID (internal)</entity_id> - <increment_id>Order ID</increment_id> - <created_at>Order Date</created_at> - <status>Order Status</status> - <shipping_description>Shipping Method</shipping_description> - <_payment_method>Payment Method</_payment_method> - <base_currency_code>Base Currency</base_currency_code> - <store_currency_code>Order Currency</store_currency_code> - <store_name>Store Name</store_name> - <remote_ip>Placed from IP</remote_ip> - <store_to_order_rate>Store Currency to Order Currency Rate</store_to_order_rate> - <subtotal>Subtotal</subtotal> - <subtotal_incl_tax>Subtotal Including Tax</subtotal_incl_tax> - <discount_amount>Discount</discount_amount> - <base_grand_total>Grand Total to Be Charged</base_grand_total> - <grand_total>Grand Total</grand_total> - <shipping_amount>Shipping Amount</shipping_amount> - <shipping_tax_amount>Shipping Including Tax</shipping_tax_amount> - <shipping_incl_tax>Shipping Tax</shipping_incl_tax> - <tax_amount>Tax Amount</tax_amount> - <_tax_name>Tax Name</_tax_name> - <_tax_rate>Tax Rate</_tax_rate> - <coupon_code>Coupon Code</coupon_code> - <base_discount_amount>Base Discount</base_discount_amount> - <base_subtotal>Base Subtotal</base_subtotal> - <base_shipping_amount>Base Shipping</base_shipping_amount> - <base_shipping_tax_amount>Base Shipping Tax</base_shipping_tax_amount> - <base_tax_amount>Base Tax Amount</base_tax_amount> - <total_paid>Total Paid</total_paid> - <base_total_paid>Base Total Paid</base_total_paid> - <total_refunded>Total Refunded</total_refunded> - <base_total_refunded>Base Total Refunded</base_total_refunded> - <base_subtotal_incl_tax>Base Subtotal Including Tax</base_subtotal_incl_tax> - <base_total_due>Base Total Due</base_total_due> - <total_due>Total Due</total_due> - <shipping_discount_amount>Shipping Discount</shipping_discount_amount> - <base_shipping_discount_amount>Base Shipping Discount</base_shipping_discount_amount> - <discount_description>Discount Description</discount_description> - <customer_balance_amount>Customer Balance</customer_balance_amount> - <base_customer_balance_amount>Base Customer Balance</base_customer_balance_amount> - <_gift_message>Gift Message</_gift_message> - <_order_comments>Order Comments</_order_comments> - <customer_id>Customer ID</customer_id> - </attributes> - <include_attributes> - <customer> - <read> - <entity_id>1</entity_id> - <increment_id>1</increment_id> - <created_at>1</created_at> - <status>1</status> - <shipping_description>1</shipping_description> - <_payment_method>1</_payment_method> - <base_currency_code>1</base_currency_code> - <store_currency_code>1</store_currency_code> - <subtotal>1</subtotal> - <subtotal_incl_tax>1</subtotal_incl_tax> - <discount_amount>1</discount_amount> - <base_grand_total>1</base_grand_total> - <grand_total>1</grand_total> - <shipping_amount>1</shipping_amount> - <shipping_tax_amount>1</shipping_tax_amount> - <shipping_incl_tax>1</shipping_incl_tax> - <tax_amount>1</tax_amount> - <_tax_name>1</_tax_name> - <_tax_rate>1</_tax_rate> - <_gift_message>1</_gift_message> - <_order_comments>1</_order_comments> - </read> - </customer> - </include_attributes> - <force_attributes> - <customer> - <payment_method>1</payment_method> - <addresses>1</addresses> - <order_items>1</order_items> - <gift_message_from>1</gift_message_from> - <gift_message_to>1</gift_message_to> - <gift_message_body>1</gift_message_body> - <order_comments>1</order_comments> - <tax_name>1</tax_name> - <tax_rate>1</tax_rate> - </customer> - <admin> - <payment_method>1</payment_method> - <addresses>1</addresses> - <order_items>1</order_items> - <gift_message_from>1</gift_message_from> - <gift_message_to>1</gift_message_to> - <gift_message_body>1</gift_message_body> - <order_comments>1</order_comments> - <tax_name>1</tax_name> - <tax_rate>1</tax_rate> - </admin> - </force_attributes> - <versions>1</versions> - </order> - <order_item translate="title" module="Mage_Api2"> - <group>sales_order</group> - <sort_order>30</sort_order> - <model>Mage_Sales_Model_Api2_Order_Item</model> - <working_model>Mage_Sales_Model_Order_Item</working_model> - <title>Order Items</title> - <privileges> - <admin> - <retrieve>1</retrieve> - </admin> - <customer> - <retrieve>1</retrieve> - </customer> - </privileges> - <attributes translate="item_id name parent_item_id sku price price_incl_tax qty_ordered qty_invoiced qty_shipped qty_canceled qty_refunded row_total row_total_incl_tax base_price original_price base_original_price base_price_incl_tax tax_percent tax_amount base_tax_amount discount_amount base_discount_amount base_row_total base_row_total_incl_tax" module="Mage_Api2"> - <item_id>Order Item ID</item_id> - <name>Product and Custom Options Name</name> - <parent_item_id>Parent Order Item ID</parent_item_id> - <sku>SKU</sku> - <price>Price</price> - <price_incl_tax>Price Including Tax</price_incl_tax> - <qty_ordered>Ordered Qty</qty_ordered> - <qty_invoiced>Invoiced Qty</qty_invoiced> - <qty_shipped>Shipped Qty</qty_shipped> - <qty_canceled>Canceled Qty</qty_canceled> - <qty_refunded>Refunded Qty</qty_refunded> - <row_total>Item Subtotal</row_total> - <row_total_incl_tax>Item Subtotal Including Tax</row_total_incl_tax> - <base_price>Base Price</base_price> - <original_price>Original Price</original_price> - <base_original_price>Base Original Price</base_original_price> - <base_price_incl_tax>Base Price Including Tax</base_price_incl_tax> - <tax_percent>Tax Percent</tax_percent> - <tax_amount>Tax Amount</tax_amount> - <base_tax_amount>Base Tax Amount</base_tax_amount> - <discount_amount>Discount Amount</discount_amount> - <base_discount_amount>Base Discount Amount</base_discount_amount> - <base_row_total>Base Item Subtotal</base_row_total> - <base_row_total_incl_tax>Base Item Subtotal Including Tax</base_row_total_incl_tax> - </attributes> - <include_attributes> - <customer> - <read> - <item_id>1</item_id> - <name>1</name> - <parent_item_id>1</parent_item_id> - <sku>1</sku> - <price>1</price> - <price_incl_tax>1</price_incl_tax> - <qty_ordered>1</qty_ordered> - <qty_invoiced>1</qty_invoiced> - <qty_shipped>1</qty_shipped> - <qty_canceled>1</qty_canceled> - <qty_refunded>1</qty_refunded> - <row_total>1</row_total> - <row_total_incl_tax>1</row_total_incl_tax> - </read> - </customer> - </include_attributes> - <routes> - <route_collection> - <route>/orders/:id/items</route> - <action_type>collection</action_type> - </route_collection> - </routes> - <versions>1</versions> - </order_item> - <order_address translate="title" module="Mage_Api2"> - <group>sales_order</group> - <sort_order>40</sort_order> - <model>Mage_Sales_Model_Api2_Order_Address</model> - <working_model>Mage_Sales_Model_Order_Address</working_model> - <title>Order Addresses</title> - <privileges> - <admin> - <retrieve>1</retrieve> - </admin> - <customer> - <retrieve>1</retrieve> - </customer> - </privileges> - <routes> - <route_entity> - <route>/orders/:order_id/addresses/:address_type</route> - <action_type>entity</action_type> - </route_entity> - <route_collection> - <route>/orders/:order_id/addresses</route> - <action_type>collection</action_type> - </route_collection> - </routes> - <versions>1</versions> - <attributes translate="lastname firstname middlename prefix suffix company street city region postcode country_id telephone address_type email" module="Mage_Api2"> - <lastname>Customer Last Name</lastname> - <firstname>Customer First Name</firstname> - <middlename>Customer Middle Name</middlename> - <prefix>Customer Prefix</prefix> - <suffix>Customer Suffix</suffix> - <company>Company</company> - <street>Street</street> - <city>City</city> - <region>State</region> - <postcode>ZIP/Postal Code</postcode> - <country_id>Country</country_id> - <telephone>Phone Number</telephone> - <address_type>Address Type</address_type> - <email>Email</email> - </attributes> - </order_address> - <order_comment translate="title" module="Mage_Api2"> - <group>sales_order</group> - <sort_order>60</sort_order> - <model>Mage_Sales_Model_Api2_Order_Comment</model> - <working_model>Mage_Sales_Model_Order_Status_History</working_model> - <title>Order Comments</title> - <privileges> - <admin> - <retrieve>1</retrieve> - </admin> - <customer> - <retrieve>1</retrieve> - </customer> - </privileges> - <force_attributes> - <admin> - <created_at>1</created_at> - <comment>1</comment> - <is_customer_notified>1</is_customer_notified> - <is_visible_on_front>1</is_visible_on_front> - <status>1</status> - </admin> - <customer> - <created_at>1</created_at> - <comment>1</comment> - </customer> - </force_attributes> - <routes> - <route_collection> - <route>/orders/:id/comments</route> - <action_type>collection</action_type> - </route_collection> - </routes> - <versions>1</versions> - </order_comment> - </resources> - </api2> -</config> diff --git a/app/code/core/Mage/Sales/etc/wsdl.xml b/app/code/core/Mage/Sales/etc/wsdl.xml deleted file mode 100644 index a691e32e2ac8f86f9f62298e2e05546404602aaf..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Sales/etc/wsdl.xml +++ /dev/null @@ -1,1346 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<definitions xmlns:typens="urn:{{var wsdl.name}}" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" - xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns="http://schemas.xmlsoap.org/wsdl/" - name="{{var wsdl.name}}" targetNamespace="urn:{{var wsdl.name}}"> - <types> - <schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:Magento"> - <import namespace="http://schemas.xmlsoap.org/soap/encoding/" schemaLocation="http://schemas.xmlsoap.org/soap/encoding/" /> - <complexType name="salesOrderEntity"> - <all> - <element name="increment_id" type="xsd:string" minOccurs="0" /> - <element name="parent_id" type="xsd:string" minOccurs="0" /> - <element name="store_id" type="xsd:string" minOccurs="0" /> - <element name="created_at" type="xsd:string" minOccurs="0" /> - <element name="updated_at" type="xsd:string" minOccurs="0" /> - <element name="is_active" type="xsd:string" minOccurs="0" /> - <element name="customer_id" type="xsd:string" minOccurs="0" /> - <element name="tax_amount" type="xsd:string" minOccurs="0" /> - <element name="shipping_amount" type="xsd:string" minOccurs="0" /> - <element name="discount_amount" type="xsd:string" minOccurs="0" /> - <element name="subtotal" type="xsd:string" minOccurs="0" /> - <element name="grand_total" type="xsd:string" minOccurs="0" /> - <element name="total_paid" type="xsd:string" minOccurs="0" /> - <element name="total_refunded" type="xsd:string" minOccurs="0" /> - <element name="total_qty_ordered" type="xsd:string" minOccurs="0" /> - <element name="total_canceled" type="xsd:string" minOccurs="0" /> - <element name="total_invoiced" type="xsd:string" minOccurs="0" /> - <element name="total_online_refunded" type="xsd:string" minOccurs="0" /> - <element name="total_offline_refunded" type="xsd:string" minOccurs="0" /> - <element name="base_tax_amount" type="xsd:string" minOccurs="0" /> - <element name="base_shipping_amount" type="xsd:string" minOccurs="0" /> - <element name="base_discount_amount" type="xsd:string" minOccurs="0" /> - <element name="base_subtotal" type="xsd:string" minOccurs="0" /> - <element name="base_grand_total" type="xsd:string" minOccurs="0" /> - <element name="base_total_paid" type="xsd:string" minOccurs="0" /> - <element name="base_total_refunded" type="xsd:string" minOccurs="0" /> - <element name="base_total_qty_ordered" type="xsd:string" minOccurs="0" /> - <element name="base_total_canceled" type="xsd:string" minOccurs="0" /> - <element name="base_total_invoiced" type="xsd:string" minOccurs="0" /> - <element name="base_total_online_refunded" type="xsd:string" minOccurs="0" /> - <element name="base_total_offline_refunded" type="xsd:string" minOccurs="0" /> - <element name="billing_address_id" type="xsd:string" minOccurs="0" /> - <element name="billing_firstname" type="xsd:string" minOccurs="0" /> - <element name="billing_lastname" type="xsd:string" minOccurs="0" /> - <element name="shipping_address_id" type="xsd:string" minOccurs="0" /> - <element name="shipping_firstname" type="xsd:string" minOccurs="0" /> - <element name="shipping_lastname" type="xsd:string" minOccurs="0" /> - <element name="billing_name" type="xsd:string" minOccurs="0" /> - <element name="shipping_name" type="xsd:string" minOccurs="0" /> - <element name="store_to_base_rate" type="xsd:string" minOccurs="0" /> - <element name="store_to_order_rate" type="xsd:string" minOccurs="0" /> - <element name="base_to_global_rate" type="xsd:string" minOccurs="0" /> - <element name="base_to_order_rate" type="xsd:string" minOccurs="0" /> - <element name="weight" type="xsd:string" minOccurs="0" /> - <element name="store_name" type="xsd:string" minOccurs="0" /> - <element name="remote_ip" type="xsd:string" minOccurs="0" /> - <element name="status" type="xsd:string" minOccurs="0" /> - <element name="state" type="xsd:string" minOccurs="0" /> - <element name="applied_rule_ids" type="xsd:string" minOccurs="0" /> - <element name="global_currency_code" type="xsd:string" minOccurs="0" /> - <element name="base_currency_code" type="xsd:string" minOccurs="0" /> - <element name="store_currency_code" type="xsd:string" minOccurs="0" /> - <element name="order_currency_code" type="xsd:string" minOccurs="0" /> - <element name="shipping_method" type="xsd:string" minOccurs="0" /> - <element name="shipping_description" type="xsd:string" minOccurs="0" /> - <element name="customer_email" type="xsd:string" minOccurs="0" /> - <element name="customer_firstname" type="xsd:string" minOccurs="0" /> - <element name="customer_lastname" type="xsd:string" minOccurs="0" /> - <element name="quote_id" type="xsd:string" minOccurs="0" /> - <element name="is_virtual" type="xsd:string" minOccurs="0" /> - <element name="customer_group_id" type="xsd:string" minOccurs="0" /> - <element name="customer_note_notify" type="xsd:string" minOccurs="0" /> - <element name="customer_is_guest" type="xsd:string" minOccurs="0" /> - <element name="email_sent" type="xsd:string" minOccurs="0" /> - <element name="order_id" type="xsd:string" minOccurs="0" /> - <element name="gift_message_id" type="xsd:string" minOccurs="0" /> - <element name="gift_message" type="xsd:string" minOccurs="0" /> - <element name="shipping_address" type="typens:salesOrderAddressEntity" minOccurs="0" /> - <element name="billing_address" type="typens:salesOrderAddressEntity" minOccurs="0" /> - <element name="items" type="typens:salesOrderItemEntityArray" minOccurs="0" /> - <element name="payment" type="typens:salesOrderPaymentEntity" minOccurs="0" /> - <element name="status_history" type="typens:salesOrderStatusHistoryEntityArray" minOccurs="0" /> - </all> - </complexType> - <complexType name="salesOrderListEntity"> - <all> - <element name="increment_id" type="xsd:string" minOccurs="0" /> - <element name="store_id" type="xsd:string" minOccurs="0" /> - <element name="created_at" type="xsd:string" minOccurs="0" /> - <element name="updated_at" type="xsd:string" minOccurs="0" /> - <element name="customer_id" type="xsd:string" minOccurs="0" /> - <element name="tax_amount" type="xsd:string" minOccurs="0" /> - <element name="shipping_amount" type="xsd:string" minOccurs="0" /> - <element name="discount_amount" type="xsd:string" minOccurs="0" /> - <element name="subtotal" type="xsd:string" minOccurs="0" /> - <element name="grand_total" type="xsd:string" minOccurs="0" /> - <element name="total_paid" type="xsd:string" minOccurs="0" /> - <element name="total_refunded" type="xsd:string" minOccurs="0" /> - <element name="total_qty_ordered" type="xsd:string" minOccurs="0" /> - <element name="total_canceled" type="xsd:string" minOccurs="0" /> - <element name="total_invoiced" type="xsd:string" minOccurs="0" /> - <element name="total_online_refunded" type="xsd:string" minOccurs="0" /> - <element name="total_offline_refunded" type="xsd:string" minOccurs="0" /> - <element name="base_tax_amount" type="xsd:string" minOccurs="0" /> - <element name="base_shipping_amount" type="xsd:string" minOccurs="0" /> - <element name="base_discount_amount" type="xsd:string" minOccurs="0" /> - <element name="base_subtotal" type="xsd:string" minOccurs="0" /> - <element name="base_grand_total" type="xsd:string" minOccurs="0" /> - <element name="base_total_paid" type="xsd:string" minOccurs="0" /> - <element name="base_total_refunded" type="xsd:string" minOccurs="0" /> - <element name="base_total_qty_ordered" type="xsd:string" minOccurs="0" /> - <element name="base_total_canceled" type="xsd:string" minOccurs="0" /> - <element name="base_total_invoiced" type="xsd:string" minOccurs="0" /> - <element name="base_total_online_refunded" type="xsd:string" minOccurs="0" /> - <element name="base_total_offline_refunded" type="xsd:string" minOccurs="0" /> - <element name="billing_address_id" type="xsd:string" minOccurs="0" /> - <element name="billing_firstname" type="xsd:string" minOccurs="0" /> - <element name="billing_lastname" type="xsd:string" minOccurs="0" /> - <element name="shipping_address_id" type="xsd:string" minOccurs="0" /> - <element name="shipping_firstname" type="xsd:string" minOccurs="0" /> - <element name="shipping_lastname" type="xsd:string" minOccurs="0" /> - <element name="billing_name" type="xsd:string" minOccurs="0" /> - <element name="shipping_name" type="xsd:string" minOccurs="0" /> - <element name="store_to_base_rate" type="xsd:string" minOccurs="0" /> - <element name="store_to_order_rate" type="xsd:string" minOccurs="0" /> - <element name="base_to_global_rate" type="xsd:string" minOccurs="0" /> - <element name="base_to_order_rate" type="xsd:string" minOccurs="0" /> - <element name="weight" type="xsd:string" minOccurs="0" /> - <element name="store_name" type="xsd:string" minOccurs="0" /> - <element name="remote_ip" type="xsd:string" minOccurs="0" /> - <element name="status" type="xsd:string" minOccurs="0" /> - <element name="state" type="xsd:string" minOccurs="0" /> - <element name="applied_rule_ids" type="xsd:string" minOccurs="0" /> - <element name="global_currency_code" type="xsd:string" minOccurs="0" /> - <element name="base_currency_code" type="xsd:string" minOccurs="0" /> - <element name="store_currency_code" type="xsd:string" minOccurs="0" /> - <element name="order_currency_code" type="xsd:string" minOccurs="0" /> - <element name="shipping_method" type="xsd:string" minOccurs="0" /> - <element name="shipping_description" type="xsd:string" minOccurs="0" /> - <element name="customer_email" type="xsd:string" minOccurs="0" /> - <element name="customer_firstname" type="xsd:string" minOccurs="0" /> - <element name="customer_lastname" type="xsd:string" minOccurs="0" /> - <element name="quote_id" type="xsd:string" minOccurs="0" /> - <element name="is_virtual" type="xsd:string" minOccurs="0" /> - <element name="customer_group_id" type="xsd:string" minOccurs="0" /> - <element name="customer_note_notify" type="xsd:string" minOccurs="0" /> - <element name="customer_is_guest" type="xsd:string" minOccurs="0" /> - <element name="email_sent" type="xsd:string" minOccurs="0" /> - <element name="order_id" type="xsd:string" minOccurs="0" /> - <element name="gift_message_id" type="xsd:string" minOccurs="0" /> - <element name="coupon_code" type="xsd:string" minOccurs="0" /> - <element name="protect_code" type="xsd:string" minOccurs="0" /> - <element name="base_discount_canceled" type="xsd:string" minOccurs="0" /> - <element name="base_discount_invoiced" type="xsd:string" minOccurs="0" /> - <element name="base_discount_refunded" type="xsd:string" minOccurs="0" /> - <element name="base_shipping_canceled" type="xsd:string" minOccurs="0" /> - <element name="base_shipping_invoiced" type="xsd:string" minOccurs="0" /> - <element name="base_shipping_refunded" type="xsd:string" minOccurs="0" /> - <element name="base_shipping_tax_amount" type="xsd:string" minOccurs="0" /> - <element name="base_shipping_tax_refunded" type="xsd:string" minOccurs="0" /> - <element name="base_subtotal_canceled" type="xsd:string" minOccurs="0" /> - <element name="base_subtotal_invoiced" type="xsd:string" minOccurs="0" /> - <element name="base_subtotal_refunded" type="xsd:string" minOccurs="0" /> - <element name="base_tax_canceled" type="xsd:string" minOccurs="0" /> - <element name="base_tax_invoiced" type="xsd:string" minOccurs="0" /> - <element name="base_tax_refunded" type="xsd:string" minOccurs="0" /> - <element name="base_total_invoiced_cost" type="xsd:string" minOccurs="0" /> - <element name="discount_canceled" type="xsd:string" minOccurs="0" /> - <element name="discount_invoiced" type="xsd:string" minOccurs="0" /> - <element name="discount_refunded" type="xsd:string" minOccurs="0" /> - <element name="shipping_canceled" type="xsd:string" minOccurs="0" /> - <element name="shipping_invoiced" type="xsd:string" minOccurs="0" /> - <element name="shipping_refunded" type="xsd:string" minOccurs="0" /> - <element name="shipping_tax_amount" type="xsd:string" minOccurs="0" /> - <element name="shipping_tax_refunded" type="xsd:string" minOccurs="0" /> - <element name="subtotal_canceled" type="xsd:string" minOccurs="0" /> - <element name="subtotal_invoiced" type="xsd:string" minOccurs="0" /> - <element name="subtotal_refunded" type="xsd:string" minOccurs="0" /> - <element name="tax_canceled" type="xsd:string" minOccurs="0" /> - <element name="tax_invoiced" type="xsd:string" minOccurs="0" /> - <element name="tax_refunded" type="xsd:string" minOccurs="0" /> - <element name="can_ship_partially" type="xsd:string" minOccurs="0" /> - <element name="can_ship_partially_item" type="xsd:string" minOccurs="0" /> - <element name="edit_increment" type="xsd:string" minOccurs="0" /> - <element name="forced_do_shipment_with_invoice" type="xsd:string" minOccurs="0" /> - <element name="payment_authorization_expiration" type="xsd:string" minOccurs="0" /> - <element name="paypal_ipn_customer_notified" type="xsd:string" minOccurs="0" /> - <element name="quote_address_id" type="xsd:string" minOccurs="0" /> - <element name="adjustment_negative" type="xsd:string" minOccurs="0" /> - <element name="adjustment_positive" type="xsd:string" minOccurs="0" /> - <element name="base_adjustment_negative" type="xsd:string" minOccurs="0" /> - <element name="base_adjustment_positive" type="xsd:string" minOccurs="0" /> - <element name="base_shipping_discount_amount" type="xsd:string" minOccurs="0" /> - <element name="base_subtotal_incl_tax" type="xsd:string" minOccurs="0" /> - <element name="base_total_due" type="xsd:string" minOccurs="0" /> - <element name="payment_authorization_amount" type="xsd:string" minOccurs="0" /> - <element name="shipping_discount_amount" type="xsd:string" minOccurs="0" /> - <element name="subtotal_incl_tax" type="xsd:string" minOccurs="0" /> - <element name="total_due" type="xsd:string" minOccurs="0" /> - <element name="customer_dob" type="xsd:string" minOccurs="0" /> - <element name="customer_middlename" type="xsd:string" minOccurs="0" /> - <element name="customer_prefix" type="xsd:string" minOccurs="0" /> - <element name="customer_suffix" type="xsd:string" minOccurs="0" /> - <element name="customer_taxvat" type="xsd:string" minOccurs="0" /> - <element name="discount_description" type="xsd:string" minOccurs="0" /> - <element name="ext_customer_id" type="xsd:string" minOccurs="0" /> - <element name="ext_order_id" type="xsd:string" minOccurs="0" /> - <element name="hold_before_state" type="xsd:string" minOccurs="0" /> - <element name="hold_before_status" type="xsd:string" minOccurs="0" /> - <element name="original_increment_id" type="xsd:string" minOccurs="0" /> - <element name="relation_child_id" type="xsd:string" minOccurs="0" /> - <element name="relation_child_real_id" type="xsd:string" minOccurs="0" /> - <element name="relation_parent_id" type="xsd:string" minOccurs="0" /> - <element name="relation_parent_real_id" type="xsd:string" minOccurs="0" /> - <element name="x_forwarded_for" type="xsd:string" minOccurs="0" /> - <element name="customer_note" type="xsd:string" minOccurs="0" /> - <element name="total_item_count" type="xsd:string" minOccurs="0" /> - <element name="customer_gender" type="xsd:string" minOccurs="0" /> - <element name="hidden_tax_amount" type="xsd:string" minOccurs="0" /> - <element name="base_hidden_tax_amount" type="xsd:string" minOccurs="0" /> - <element name="shipping_hidden_tax_amount" type="xsd:string" minOccurs="0" /> - <element name="base_shipping_hidden_tax_amount" type="xsd:string" minOccurs="0" /> - <element name="hidden_tax_invoiced" type="xsd:string" minOccurs="0" /> - <element name="base_hidden_tax_invoiced" type="xsd:string" minOccurs="0" /> - <element name="hidden_tax_refunded" type="xsd:string" minOccurs="0" /> - <element name="base_hidden_tax_refunded" type="xsd:string" minOccurs="0" /> - <element name="shipping_incl_tax" type="xsd:string" minOccurs="0" /> - <element name="base_shipping_incl_tax" type="xsd:string" minOccurs="0" /> - <element name="base_customer_balance_amount" type="xsd:string" minOccurs="0" /> - <element name="customer_balance_amount" type="xsd:string" minOccurs="0" /> - <element name="base_customer_balance_invoiced" type="xsd:string" minOccurs="0" /> - <element name="customer_balance_invoiced" type="xsd:string" minOccurs="0" /> - <element name="base_customer_balance_refunded" type="xsd:string" minOccurs="0" /> - <element name="customer_balance_refunded" type="xsd:string" minOccurs="0" /> - <element name="bs_customer_bal_total_refunded" type="xsd:string" minOccurs="0" /> - <element name="customer_bal_total_refunded" type="xsd:string" minOccurs="0" /> - <element name="gift_cards" type="xsd:string" minOccurs="0" /> - <element name="base_gift_cards_amount" type="xsd:string" minOccurs="0" /> - <element name="gift_cards_amount" type="xsd:string" minOccurs="0" /> - <element name="base_gift_cards_invoiced" type="xsd:string" minOccurs="0" /> - <element name="gift_cards_invoiced" type="xsd:string" minOccurs="0" /> - <element name="base_gift_cards_refunded" type="xsd:string" minOccurs="0" /> - <element name="gift_cards_refunded" type="xsd:string" minOccurs="0" /> - <element name="reward_points_balance" type="xsd:string" minOccurs="0" /> - <element name="base_reward_currency_amount" type="xsd:string" minOccurs="0" /> - <element name="reward_currency_amount" type="xsd:string" minOccurs="0" /> - <element name="base_rwrd_crrncy_amt_invoiced" type="xsd:string" minOccurs="0" /> - <element name="rwrd_currency_amount_invoiced" type="xsd:string" minOccurs="0" /> - <element name="base_rwrd_crrncy_amnt_refnded" type="xsd:string" minOccurs="0" /> - <element name="rwrd_crrncy_amnt_refunded" type="xsd:string" minOccurs="0" /> - <element name="reward_points_balance_refunded" type="xsd:string" minOccurs="0" /> - <element name="reward_points_balance_refund" type="xsd:string" minOccurs="0" /> - <element name="reward_salesrule_points" type="xsd:string" minOccurs="0" /> - <element name="firstname" type="xsd:string" minOccurs="0" /> - <element name="lastname" type="xsd:string" minOccurs="0" /> - <element name="telephone" type="xsd:string" minOccurs="0" /> - <element name="postcode" type="xsd:string" minOccurs="0" /> - </all> - </complexType> - <complexType name="salesOrderListEntityArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:salesOrderListEntity[]" /> - </restriction> - </complexContent> - </complexType> - <complexType name="salesOrderAddressEntity"> - <all> - <element name="increment_id" type="xsd:string" minOccurs="0" /> - <element name="parent_id" type="xsd:string" minOccurs="0" /> - <element name="created_at" type="xsd:string" minOccurs="0" /> - <element name="updated_at" type="xsd:string" minOccurs="0" /> - <element name="is_active" type="xsd:string" minOccurs="0" /> - <element name="address_type" type="xsd:string" minOccurs="0" /> - <element name="firstname" type="xsd:string" minOccurs="0" /> - <element name="lastname" type="xsd:string" minOccurs="0" /> - <element name="company" type="xsd:string" minOccurs="0" /> - <element name="street" type="xsd:string" minOccurs="0" /> - <element name="city" type="xsd:string" minOccurs="0" /> - <element name="region" type="xsd:string" minOccurs="0" /> - <element name="postcode" type="xsd:string" minOccurs="0" /> - <element name="country_id" type="xsd:string" minOccurs="0" /> - <element name="telephone" type="xsd:string" minOccurs="0" /> - <element name="fax" type="xsd:string" minOccurs="0" /> - <element name="region_id" type="xsd:string" minOccurs="0" /> - <element name="address_id" type="xsd:string" minOccurs="0" /> - </all> - </complexType> - <complexType name="salesOrderItemEntity"> - <all> - <element name="item_id" type="xsd:string" minOccurs="0" /> - <element name="order_id" type="xsd:string" minOccurs="0" /> - <element name="quote_item_id" type="xsd:string" minOccurs="0" /> - <element name="created_at" type="xsd:string" minOccurs="0" /> - <element name="updated_at" type="xsd:string" minOccurs="0" /> - <element name="product_id" type="xsd:string" minOccurs="0" /> - <element name="product_type" type="xsd:string" minOccurs="0" /> - <element name="product_options" type="xsd:string" minOccurs="0" /> - <element name="weight" type="xsd:string" minOccurs="0" /> - <element name="is_virtual" type="xsd:string" minOccurs="0" /> - <element name="sku" type="xsd:string" minOccurs="0" /> - <element name="name" type="xsd:string" minOccurs="0" /> - <element name="applied_rule_ids" type="xsd:string" minOccurs="0" /> - <element name="free_shipping" type="xsd:string" minOccurs="0" /> - <element name="is_qty_decimal" type="xsd:string" minOccurs="0" /> - <element name="no_discount" type="xsd:string" minOccurs="0" /> - <element name="qty_canceled" type="xsd:string" minOccurs="0" /> - <element name="qty_invoiced" type="xsd:string" minOccurs="0" /> - <element name="qty_ordered" type="xsd:string" minOccurs="0" /> - <element name="qty_refunded" type="xsd:string" minOccurs="0" /> - <element name="qty_shipped" type="xsd:string" minOccurs="0" /> - <element name="cost" type="xsd:string" minOccurs="0" /> - <element name="price" type="xsd:string" minOccurs="0" /> - <element name="base_price" type="xsd:string" minOccurs="0" /> - <element name="original_price" type="xsd:string" minOccurs="0" /> - <element name="base_original_price" type="xsd:string" minOccurs="0" /> - <element name="tax_percent" type="xsd:string" minOccurs="0" /> - <element name="tax_amount" type="xsd:string" minOccurs="0" /> - <element name="base_tax_amount" type="xsd:string" minOccurs="0" /> - <element name="tax_invoiced" type="xsd:string" minOccurs="0" /> - <element name="base_tax_invoiced" type="xsd:string" minOccurs="0" /> - <element name="discount_percent" type="xsd:string" minOccurs="0" /> - <element name="discount_amount" type="xsd:string" minOccurs="0" /> - <element name="base_discount_amount" type="xsd:string" minOccurs="0" /> - <element name="discount_invoiced" type="xsd:string" minOccurs="0" /> - <element name="base_discount_invoiced" type="xsd:string" minOccurs="0" /> - <element name="amount_refunded" type="xsd:string" minOccurs="0" /> - <element name="base_amount_refunded" type="xsd:string" minOccurs="0" /> - <element name="row_total" type="xsd:string" minOccurs="0" /> - <element name="base_row_total" type="xsd:string" minOccurs="0" /> - <element name="row_invoiced" type="xsd:string" minOccurs="0" /> - <element name="base_row_invoiced" type="xsd:string" minOccurs="0" /> - <element name="row_weight" type="xsd:string" minOccurs="0" /> - <element name="gift_message_id" type="xsd:string" minOccurs="0" /> - <element name="gift_message" type="xsd:string" minOccurs="0" /> - <element name="gift_message_available" type="xsd:string" minOccurs="0" /> - <element name="base_tax_before_discount" type="xsd:string" minOccurs="0" /> - <element name="tax_before_discount" type="xsd:string" minOccurs="0" /> - <element name="weee_tax_applied" type="xsd:string" minOccurs="0" /> - <element name="weee_tax_applied_amount" type="xsd:string" minOccurs="0" /> - <element name="weee_tax_applied_row_amount" type="xsd:string" minOccurs="0" /> - <element name="base_weee_tax_applied_amount" type="xsd:string" minOccurs="0" /> - <element name="base_weee_tax_applied_row_amnt" type="xsd:string" minOccurs="0" /> - <element name="weee_tax_disposition" type="xsd:string" minOccurs="0" /> - <element name="weee_tax_row_disposition" type="xsd:string" minOccurs="0" /> - <element name="base_weee_tax_disposition" type="xsd:string" minOccurs="0" /> - <element name="base_weee_tax_row_disposition" type="xsd:string" minOccurs="0" /> - </all> - </complexType> - <complexType name="salesOrderItemEntityArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:salesOrderItemEntity[]" /> - </restriction> - </complexContent> - </complexType> - <complexType name="orderItemIdQty"> - <all> - <element name="order_item_id" type="xsd:int" /> - <element name="qty" type="xsd:double" /> - </all> - </complexType> - <complexType name="orderItemIdQtyArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:orderItemIdQty[]" /> - </restriction> - </complexContent> - </complexType> - <complexType name="salesOrderPaymentEntity"> - <all> - <element name="increment_id" type="xsd:string" minOccurs="0" /> - <element name="parent_id" type="xsd:string" minOccurs="0" /> - <element name="created_at" type="xsd:string" minOccurs="0" /> - <element name="updated_at" type="xsd:string" minOccurs="0" /> - <element name="is_active" type="xsd:string" minOccurs="0" /> - <element name="amount_ordered" type="xsd:string" minOccurs="0" /> - <element name="shipping_amount" type="xsd:string" minOccurs="0" /> - <element name="base_amount_ordered" type="xsd:string" minOccurs="0" /> - <element name="base_shipping_amount" type="xsd:string" minOccurs="0" /> - <element name="method" type="xsd:string" minOccurs="0" /> - <element name="po_number" type="xsd:string" minOccurs="0" /> - <element name="cc_type" type="xsd:string" minOccurs="0" /> - <element name="cc_number_enc" type="xsd:string" minOccurs="0" /> - <element name="cc_last4" type="xsd:string" minOccurs="0" /> - <element name="cc_owner" type="xsd:string" minOccurs="0" /> - <element name="cc_exp_month" type="xsd:string" minOccurs="0" /> - <element name="cc_exp_year" type="xsd:string" minOccurs="0" /> - <element name="cc_ss_start_month" type="xsd:string" minOccurs="0" /> - <element name="cc_ss_start_year" type="xsd:string" minOccurs="0" /> - <element name="payment_id" type="xsd:string" minOccurs="0" /> - </all> - </complexType> - <complexType name="salesOrderStatusHistoryEntity"> - <all> - <element name="increment_id" type="xsd:string" minOccurs="0" /> - <element name="parent_id" type="xsd:string" minOccurs="0" /> - <element name="created_at" type="xsd:string" minOccurs="0" /> - <element name="updated_at" type="xsd:string" minOccurs="0" /> - <element name="is_active" type="xsd:string" minOccurs="0" /> - <element name="is_customer_notified" type="xsd:string" minOccurs="0" /> - <element name="status" type="xsd:string" minOccurs="0" /> - <element name="comment" type="xsd:string" minOccurs="0" /> - </all> - </complexType> - <complexType name="salesOrderStatusHistoryEntityArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:salesOrderStatusHistoryEntity[]" /> - </restriction> - </complexContent> - </complexType> - <complexType name="salesOrderShipmentEntity"> - <all> - <element name="increment_id" type="xsd:string" minOccurs="0" /> - <element name="parent_id" type="xsd:string" minOccurs="0" /> - <element name="store_id" type="xsd:string" minOccurs="0" /> - <element name="created_at" type="xsd:string" minOccurs="0" /> - <element name="updated_at" type="xsd:string" minOccurs="0" /> - <element name="is_active" type="xsd:string" minOccurs="0" /> - <element name="shipping_address_id" type="xsd:string" minOccurs="0" /> - <element name="shipping_firstname" type="xsd:string" minOccurs="0" /> - <element name="shipping_lastname" type="xsd:string" minOccurs="0" /> - <element name="order_id" type="xsd:string" minOccurs="0" /> - <element name="order_increment_id" type="xsd:string" minOccurs="0" /> - <element name="order_created_at" type="xsd:string" minOccurs="0" /> - <element name="total_qty" type="xsd:string" minOccurs="0" /> - <element name="shipment_id" type="xsd:string" minOccurs="0" /> - <element name="items" type="typens:salesOrderShipmentItemEntityArray" minOccurs="0" /> - <element name="tracks" type="typens:salesOrderShipmentTrackEntityArray" minOccurs="0" /> - <element name="comments" type="typens:salesOrderShipmentCommentEntityArray" minOccurs="0" /> - </all> - </complexType> - <complexType name="salesOrderShipmentEntityArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:salesOrderShipmentEntity[]" /> - </restriction> - </complexContent> - </complexType> - <complexType name="salesOrderShipmentCommentEntity"> - <all> - <element name="increment_id" type="xsd:string" minOccurs="0" /> - <element name="parent_id" type="xsd:string" minOccurs="0" /> - <element name="created_at" type="xsd:string" minOccurs="0" /> - <element name="updated_at" type="xsd:string" minOccurs="0" /> - <element name="is_active" type="xsd:string" minOccurs="0" /> - <element name="comment" type="xsd:string" minOccurs="0" /> - <element name="is_customer_notified" type="xsd:string" minOccurs="0" /> - <element name="comment_id" type="xsd:string" minOccurs="0" /> - </all> - </complexType> - <complexType name="salesOrderShipmentCommentEntityArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:salesOrderShipmentCommentEntity[]" /> - </restriction> - </complexContent> - </complexType> - <complexType name="salesOrderShipmentTrackEntity"> - <all> - <element name="increment_id" type="xsd:string" minOccurs="0" /> - <element name="parent_id" type="xsd:string" minOccurs="0" /> - <element name="created_at" type="xsd:string" minOccurs="0" /> - <element name="updated_at" type="xsd:string" minOccurs="0" /> - <element name="is_active" type="xsd:string" minOccurs="0" /> - <element name="carrier_code" type="xsd:string" minOccurs="0" /> - <element name="title" type="xsd:string" minOccurs="0" /> - <element name="number" type="xsd:string" minOccurs="0" /> - <element name="order_id" type="xsd:string" minOccurs="0" /> - <element name="track_id" type="xsd:string" minOccurs="0" /> - </all> - </complexType> - <complexType name="salesOrderShipmentTrackEntityArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:salesOrderShipmentTrackEntity[]" /> - </restriction> - </complexContent> - </complexType> - <complexType name="salesOrderShipmentItemEntity"> - <all> - <element name="increment_id" type="xsd:string" minOccurs="0" /> - <element name="parent_id" type="xsd:string" minOccurs="0" /> - <element name="created_at" type="xsd:string" minOccurs="0" /> - <element name="updated_at" type="xsd:string" minOccurs="0" /> - <element name="is_active" type="xsd:string" minOccurs="0" /> - <element name="sku" type="xsd:string" minOccurs="0" /> - <element name="name" type="xsd:string" minOccurs="0" /> - <element name="order_item_id" type="xsd:string" minOccurs="0" /> - <element name="product_id" type="xsd:string" minOccurs="0" /> - <element name="weight" type="xsd:string" minOccurs="0" /> - <element name="price" type="xsd:string" minOccurs="0" /> - <element name="qty" type="xsd:string" minOccurs="0" /> - <element name="item_id" type="xsd:string" minOccurs="0" /> - </all> - </complexType> - <complexType name="salesOrderShipmentItemEntityArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:salesOrderShipmentItemEntity[]" /> - </restriction> - </complexContent> - </complexType> - <complexType name="salesOrderInvoiceEntity"> - <all> - <element name="increment_id" type="xsd:string" minOccurs="0" /> - <element name="parent_id" type="xsd:string" minOccurs="0" /> - <element name="store_id" type="xsd:string" minOccurs="0" /> - <element name="created_at" type="xsd:string" minOccurs="0" /> - <element name="updated_at" type="xsd:string" minOccurs="0" /> - <element name="is_active" type="xsd:string" minOccurs="0" /> - <element name="global_currency_code" type="xsd:string" minOccurs="0" /> - <element name="base_currency_code" type="xsd:string" minOccurs="0" /> - <element name="store_currency_code" type="xsd:string" minOccurs="0" /> - <element name="order_currency_code" type="xsd:string" minOccurs="0" /> - <element name="store_to_base_rate" type="xsd:string" minOccurs="0" /> - <element name="store_to_order_rate" type="xsd:string" minOccurs="0" /> - <element name="base_to_global_rate" type="xsd:string" minOccurs="0" /> - <element name="base_to_order_rate" type="xsd:string" minOccurs="0" /> - <element name="subtotal" type="xsd:string" minOccurs="0" /> - <element name="base_subtotal" type="xsd:string" minOccurs="0" /> - <element name="base_grand_total" type="xsd:string" minOccurs="0" /> - <element name="discount_amount" type="xsd:string" minOccurs="0" /> - <element name="base_discount_amount" type="xsd:string" minOccurs="0" /> - <element name="shipping_amount" type="xsd:string" minOccurs="0" /> - <element name="base_shipping_amount" type="xsd:string" minOccurs="0" /> - <element name="tax_amount" type="xsd:string" minOccurs="0" /> - <element name="base_tax_amount" type="xsd:string" minOccurs="0" /> - <element name="billing_address_id" type="xsd:string" minOccurs="0" /> - <element name="billing_firstname" type="xsd:string" minOccurs="0" /> - <element name="billing_lastname" type="xsd:string" minOccurs="0" /> - <element name="order_id" type="xsd:string" minOccurs="0" /> - <element name="order_increment_id" type="xsd:string" minOccurs="0" /> - <element name="order_created_at" type="xsd:string" minOccurs="0" /> - <element name="state" type="xsd:string" minOccurs="0" /> - <element name="grand_total" type="xsd:string" minOccurs="0" /> - <element name="invoice_id" type="xsd:string" minOccurs="0" /> - <element name="items" type="typens:salesOrderInvoiceItemEntityArray" minOccurs="0" /> - <element name="comments" type="typens:salesOrderInvoiceCommentEntityArray" minOccurs="0" /> - </all> - </complexType> - <complexType name="salesOrderInvoiceEntityArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:salesOrderInvoiceEntity[]" /> - </restriction> - </complexContent> - </complexType> - <complexType name="salesOrderInvoiceItemEntity"> - <all> - <element name="increment_id" type="xsd:string" minOccurs="0" /> - <element name="parent_id" type="xsd:string" minOccurs="0" /> - <element name="created_at" type="xsd:string" minOccurs="0" /> - <element name="updated_at" type="xsd:string" minOccurs="0" /> - <element name="is_active" type="xsd:string" minOccurs="0" /> - <element name="weee_tax_applied" type="xsd:string" minOccurs="0" /> - <element name="qty" type="xsd:string" minOccurs="0" /> - <element name="cost" type="xsd:string" minOccurs="0" /> - <element name="price" type="xsd:string" minOccurs="0" /> - <element name="tax_amount" type="xsd:string" minOccurs="0" /> - <element name="row_total" type="xsd:string" minOccurs="0" /> - <element name="base_price" type="xsd:string" minOccurs="0" /> - <element name="base_tax_amount" type="xsd:string" minOccurs="0" /> - <element name="base_row_total" type="xsd:string" minOccurs="0" /> - <element name="base_weee_tax_applied_amount" type="xsd:string" minOccurs="0" /> - <element name="base_weee_tax_applied_row_amnt" type="xsd:string" minOccurs="0" /> - <element name="weee_tax_applied_amount" type="xsd:string" minOccurs="0" /> - <element name="weee_tax_applied_row_amount" type="xsd:string" minOccurs="0" /> - <element name="weee_tax_disposition" type="xsd:string" minOccurs="0" /> - <element name="weee_tax_row_disposition" type="xsd:string" minOccurs="0" /> - <element name="base_weee_tax_disposition" type="xsd:string" minOccurs="0" /> - <element name="base_weee_tax_row_disposition" type="xsd:string" minOccurs="0" /> - <element name="sku" type="xsd:string" minOccurs="0" /> - <element name="name" type="xsd:string" minOccurs="0" /> - <element name="order_item_id" type="xsd:string" minOccurs="0" /> - <element name="product_id" type="xsd:string" minOccurs="0" /> - <element name="item_id" type="xsd:string" minOccurs="0" /> - </all> - </complexType> - <complexType name="salesOrderInvoiceItemEntityArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:salesOrderInvoiceItemEntity[]" /> - </restriction> - </complexContent> - </complexType> - <complexType name="salesOrderInvoiceCommentEntity"> - <all> - <element name="increment_id" type="xsd:string" minOccurs="0" /> - <element name="parent_id" type="xsd:string" minOccurs="0" /> - <element name="created_at" type="xsd:string" minOccurs="0" /> - <element name="updated_at" type="xsd:string" minOccurs="0" /> - <element name="is_active" type="xsd:string" minOccurs="0" /> - <element name="comment" type="xsd:string" minOccurs="0" /> - <element name="is_customer_notified" type="xsd:string" minOccurs="0" /> - <element name="comment_id" type="xsd:string" minOccurs="0" /> - </all> - </complexType> - <complexType name="salesOrderInvoiceCommentEntityArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:salesOrderInvoiceCommentEntity[]" /> - </restriction> - </complexContent> - </complexType> - <complexType name="salesOrderCreditmemoEntity"> - <all> - <element name="updated_at" type="xsd:string" minOccurs="0" /> - <element name="created_at" type="xsd:string" minOccurs="0" /> - <element name="increment_id" type="xsd:string" minOccurs="0" /> - <element name="transaction_id" type="xsd:string" minOccurs="0" /> - <element name="global_currency_code" type="xsd:string" minOccurs="0" /> - <element name="base_currency_code" type="xsd:string" minOccurs="0" /> - <element name="order_currency_code" type="xsd:string" minOccurs="0" /> - <element name="store_currency_code" type="xsd:string" minOccurs="0" /> - <element name="cybersource_token" type="xsd:string" minOccurs="0" /> - <element name="invoice_id" type="xsd:string" minOccurs="0" /> - <element name="billing_address_id" type="xsd:string" minOccurs="0" /> - <element name="shipping_address_id" type="xsd:string" minOccurs="0" /> - <element name="state" type="xsd:string" minOccurs="0" /> - <element name="creditmemo_status" type="xsd:string" minOccurs="0" /> - <element name="email_sent" type="xsd:string" minOccurs="0" /> - <element name="order_id" type="xsd:string" minOccurs="0" /> - <element name="tax_amount" type="xsd:string" minOccurs="0" /> - <element name="shipping_tax_amount" type="xsd:string" minOccurs="0" /> - <element name="base_tax_amount" type="xsd:string" minOccurs="0" /> - <element name="base_adjustment_positive" type="xsd:string" minOccurs="0" /> - <element name="base_grand_total" type="xsd:string" minOccurs="0" /> - <element name="adjustment" type="xsd:string" minOccurs="0" /> - <element name="subtotal" type="xsd:string" minOccurs="0" /> - <element name="discount_amount" type="xsd:string" minOccurs="0" /> - <element name="base_subtotal" type="xsd:string" minOccurs="0" /> - <element name="base_adjustment" type="xsd:string" minOccurs="0" /> - <element name="base_to_global_rate" type="xsd:string" minOccurs="0" /> - <element name="store_to_base_rate" type="xsd:string" minOccurs="0" /> - <element name="base_shipping_amount" type="xsd:string" minOccurs="0" /> - <element name="adjustment_negative" type="xsd:string" minOccurs="0" /> - <element name="subtotal_incl_tax" type="xsd:string" minOccurs="0" /> - <element name="shipping_amount" type="xsd:string" minOccurs="0" /> - <element name="base_subtotal_incl_tax" type="xsd:string" minOccurs="0" /> - <element name="base_adjustment_negative" type="xsd:string" minOccurs="0" /> - <element name="grand_total" type="xsd:string" minOccurs="0" /> - <element name="base_discount_amount" type="xsd:string" minOccurs="0" /> - <element name="base_to_order_rate" type="xsd:string" minOccurs="0" /> - <element name="store_to_order_rate" type="xsd:string" minOccurs="0" /> - <element name="base_shipping_tax_amount" type="xsd:string" minOccurs="0" /> - <element name="adjustment_positive" type="xsd:string" minOccurs="0" /> - <element name="store_id" type="xsd:string" minOccurs="0" /> - <element name="hidden_tax_amount" type="xsd:string" minOccurs="0" /> - <element name="base_hidden_tax_amount" type="xsd:string" minOccurs="0" /> - <element name="shipping_hidden_tax_amount" type="xsd:string" minOccurs="0" /> - <element name="base_shipping_hidden_tax_amnt" type="xsd:string" minOccurs="0" /> - <element name="shipping_incl_tax" type="xsd:string" minOccurs="0" /> - <element name="base_shipping_incl_tax" type="xsd:string" minOccurs="0" /> - <element name="base_customer_balance_amount" type="xsd:string" minOccurs="0" /> - <element name="customer_balance_amount" type="xsd:string" minOccurs="0" /> - <element name="bs_customer_bal_total_refunded" type="xsd:string" minOccurs="0" /> - <element name="customer_bal_total_refunded" type="xsd:string" minOccurs="0" /> - <element name="base_gift_cards_amount" type="xsd:string" minOccurs="0" /> - <element name="gift_cards_amount" type="xsd:string" minOccurs="0" /> - <element name="gw_base_price" type="xsd:string" minOccurs="0" /> - <element name="gw_price" type="xsd:string" minOccurs="0" /> - <element name="gw_items_base_price" type="xsd:string" minOccurs="0" /> - <element name="gw_items_price" type="xsd:string" minOccurs="0" /> - <element name="gw_card_base_price" type="xsd:string" minOccurs="0" /> - <element name="gw_card_price" type="xsd:string" minOccurs="0" /> - <element name="gw_base_tax_amount" type="xsd:string" minOccurs="0" /> - <element name="gw_tax_amount" type="xsd:string" minOccurs="0" /> - <element name="gw_items_base_tax_amount" type="xsd:string" minOccurs="0" /> - <element name="gw_items_tax_amount" type="xsd:string" minOccurs="0" /> - <element name="gw_card_base_tax_amount" type="xsd:string" minOccurs="0" /> - <element name="gw_card_tax_amount" type="xsd:string" minOccurs="0" /> - <element name="base_reward_currency_amount" type="xsd:string" minOccurs="0" /> - <element name="reward_currency_amount" type="xsd:string" minOccurs="0" /> - <element name="reward_points_balance" type="xsd:string" minOccurs="0" /> - <element name="reward_points_balance_refund" type="xsd:string" minOccurs="0" /> - <element name="creditmemo_id" type="xsd:string" minOccurs="0" /> - <element name="items" type="typens:salesOrderCreditmemoItemEntityArray" minOccurs="0" /> - <element name="comments" type="typens:salesOrderCreditmemoCommentEntityArray" minOccurs="0" /> - </all> - </complexType> - <complexType name="salesOrderCreditmemoEntityArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:salesOrderCreditmemoEntity[]" /> - </restriction> - </complexContent> - </complexType> - <complexType name="salesOrderCreditmemoItemEntity"> - <all> - <element name="item_id" type="xsd:string" minOccurs="0" /> - <element name="parent_id" type="xsd:string" minOccurs="0" /> - <element name="weee_tax_applied_row_amount" type="xsd:string" minOccurs="0" /> - <element name="base_price" type="xsd:string" minOccurs="0" /> - <element name="base_weee_tax_row_disposition" type="xsd:string" minOccurs="0" /> - <element name="tax_amount" type="xsd:string" minOccurs="0" /> - <element name="base_weee_tax_applied_amount" type="xsd:string" minOccurs="0" /> - <element name="weee_tax_row_disposition" type="xsd:string" minOccurs="0" /> - <element name="base_row_total" type="xsd:string" minOccurs="0" /> - <element name="discount_amount" type="xsd:string" minOccurs="0" /> - <element name="row_total" type="xsd:string" minOccurs="0" /> - <element name="weee_tax_applied_amount" type="xsd:string" minOccurs="0" /> - <element name="base_discount_amount" type="xsd:string" minOccurs="0" /> - <element name="base_weee_tax_disposition" type="xsd:string" minOccurs="0" /> - <element name="price_incl_tax" type="xsd:string" minOccurs="0" /> - <element name="base_tax_amount" type="xsd:string" minOccurs="0" /> - <element name="weee_tax_disposition" type="xsd:string" minOccurs="0" /> - <element name="base_price_incl_tax" type="xsd:string" minOccurs="0" /> - <element name="qty" type="xsd:string" minOccurs="0" /> - <element name="base_cost" type="xsd:string" minOccurs="0" /> - <element name="base_weee_tax_applied_row_amount" type="xsd:string" minOccurs="0" /> - <element name="price" type="xsd:string" minOccurs="0" /> - <element name="base_row_total_incl_tax" type="xsd:string" minOccurs="0" /> - <element name="row_total_incl_tax" type="xsd:string" minOccurs="0" /> - <element name="product_id" type="xsd:string" minOccurs="0" /> - <element name="order_item_id" type="xsd:string" minOccurs="0" /> - <element name="additional_data" type="xsd:string" minOccurs="0" /> - <element name="description" type="xsd:string" minOccurs="0" /> - <element name="weee_tax_applied" type="xsd:string" minOccurs="0" /> - <element name="sku" type="xsd:string" minOccurs="0" /> - <element name="name" type="xsd:string" minOccurs="0" /> - <element name="hidden_tax_amount" type="xsd:string" minOccurs="0"/> - <element name="base_hidden_tax_amount" type="xsd:string" minOccurs="0"/> - </all> - </complexType> - <complexType name="salesOrderCreditmemoItemEntityArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:salesOrderCreditmemoItemEntity[]" /> - </restriction> - </complexContent> - </complexType> - <complexType name="salesOrderCreditmemoCommentEntity"> - <all> - <element name="parent_id" type="xsd:string" minOccurs="0" /> - <element name="created_at" type="xsd:string" minOccurs="0" /> - <element name="comment" type="xsd:string" minOccurs="0" /> - <element name="is_customer_notified" type="xsd:string" minOccurs="0" /> - <element name="comment_id" type="xsd:string" minOccurs="0" /> - <element name="is_visible_on_front" type="xsd:string" minOccurs="0"/> - </all> - </complexType> - <complexType name="salesOrderCreditmemoCommentEntityArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:salesOrderCreditmemoCommentEntity[]" /> - </restriction> - </complexContent> - </complexType> - <complexType name="salesOrderCreditmemoData"> - <all> - <element name="qtys" type="typens:orderItemIdQtyArray" minOccurs="0"/> - <element name="shipping_amount" type="xsd:double" minOccurs="0"/> - <element name="adjustment_positive" type="xsd:double" minOccurs="0"/> - <element name="adjustment_negative" type="xsd:double" minOccurs="0"/> - </all> - </complexType> - </schema> - </types> - <message name="salesOrderListRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="filters" type="typens:filters" /> - </message> - <message name="salesOrderListResponse"> - <part name="result" type="typens:salesOrderListEntityArray" /> - </message> - <message name="salesOrderInfoRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="orderIncrementId" type="xsd:string" /> - </message> - <message name="salesOrderInfoResponse"> - <part name="result" type="typens:salesOrderEntity" /> - </message> - <message name="salesOrderAddCommentRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="orderIncrementId" type="xsd:string" /> - <part name="status" type="xsd:string" /> - <part name="comment" type="xsd:string" /> - <part name="notify" type="xsd:string" /> - </message> - <message name="salesOrderAddCommentResponse"> - <part name="result" type="xsd:boolean" /> - </message> - <message name="salesOrderHoldRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="orderIncrementId" type="xsd:string" /> - </message> - <message name="salesOrderHoldResponse"> - <part name="result" type="xsd:boolean" /> - </message> - <message name="salesOrderUnholdRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="orderIncrementId" type="xsd:string" /> - </message> - <message name="salesOrderUnholdResponse"> - <part name="result" type="xsd:boolean" /> - </message> - <message name="salesOrderCancelRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="orderIncrementId" type="xsd:string" /> - </message> - <message name="salesOrderCancelResponse"> - <part name="result" type="xsd:boolean" /> - </message> - <message name="salesOrderShipmentListRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="filters" type="typens:filters" /> - </message> - <message name="salesOrderShipmentListResponse"> - <part name="result" type="typens:salesOrderShipmentEntityArray" /> - </message> - <message name="salesOrderShipmentInfoRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="shipmentIncrementId" type="xsd:string" /> - </message> - <message name="salesOrderShipmentInfoResponse"> - <part name="result" type="typens:salesOrderShipmentEntity" /> - </message> - <message name="salesOrderShipmentCreateRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="orderIncrementId" type="xsd:string" /> - <part name="itemsQty" type="typens:orderItemIdQtyArray" /> - <part name="comment" type="xsd:string" /> - <part name="email" type="xsd:int" /> - <part name="includeComment" type="xsd:int" /> - </message> - <message name="salesOrderShipmentCreateResponse"> - <part name="shipmentIncrementId" type="xsd:string" /> - </message> - <message name="salesOrderShipmentAddCommentRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="shipmentIncrementId" type="xsd:string" /> - <part name="comment" type="xsd:string" /> - <part name="email" type="xsd:string" /> - <part name="includeInEmail" type="xsd:string" /> - </message> - <message name="salesOrderShipmentAddCommentResponse"> - <part name="shipmentIncrementId" type="xsd:boolean" /> - </message> - <message name="salesOrderShipmentAddTrackRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="shipmentIncrementId" type="xsd:string" /> - <part name="carrier" type="xsd:string" /> - <part name="title" type="xsd:string" /> - <part name="trackNumber" type="xsd:string" /> - </message> - <message name="salesOrderShipmentAddTrackResponse"> - <part name="result" type="xsd:int" /> - </message> - <message name="salesOrderShipmentSendInfoRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="shipmentIncrementId" type="xsd:string" /> - <part name="comment" type="xsd:string" /> - </message> - <message name="salesOrderShipmentSendInfoResponse"> - <part name="result" type="xsd:boolean" /> - </message> - <message name="salesOrderShipmentRemoveTrackRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="shipmentIncrementId" type="xsd:string" /> - <part name="trackId" type="xsd:string" /> - </message> - <message name="salesOrderShipmentRemoveTrackResponse"> - <part name="result" type="xsd:boolean" /> - </message> - <message name="salesOrderShipmentGetCarriersRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="orderIncrementId" type="xsd:string" /> - </message> - <message name="salesOrderShipmentGetCarriersResponse"> - <part name="result" type="typens:associativeArray" /> - </message> - <message name="salesOrderInvoiceListRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="filters" type="typens:filters" /> - </message> - <message name="salesOrderInvoiceListResponse"> - <part name="result" type="typens:salesOrderInvoiceEntityArray" /> - </message> - <message name="salesOrderInvoiceInfoRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="invoiceIncrementId" type="xsd:string" /> - </message> - <message name="salesOrderInvoiceInfoResponse"> - <part name="result" type="typens:salesOrderInvoiceEntity" /> - </message> - <message name="salesOrderInvoiceCreateRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="invoiceIncrementId" type="xsd:string" /> - <part name="itemsQty" type="typens:orderItemIdQtyArray" /> - <part name="comment" type="xsd:string" /> - <part name="email" type="xsd:string" /> - <part name="includeComment" type="xsd:string" /> - </message> - <message name="salesOrderInvoiceCreateResponse"> - <part name="result" type="xsd:string" /> - </message> - <message name="salesOrderInvoiceAddCommentRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="invoiceIncrementId" type="xsd:string" /> - <part name="comment" type="xsd:string" /> - <part name="email" type="xsd:string" /> - <part name="includeComment" type="xsd:string" /> - </message> - <message name="salesOrderInvoiceAddCommentResponse"> - <part name="result" type="xsd:boolean" /> - </message> - <message name="salesOrderCreditmemoListRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="filters" type="typens:filters" /> - </message> - <message name="salesOrderCreditmemoListResponse"> - <part name="result" type="typens:salesOrderCreditmemoEntityArray" /> - </message> - <message name="salesOrderCreditmemoInfoRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="creditmemoIncrementId" type="xsd:string" /> - </message> - <message name="salesOrderCreditmemoInfoResponse"> - <part name="result" type="typens:salesOrderCreditmemoEntity" /> - </message> - <message name="salesOrderCreditmemoCreateRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="creditmemoIncrementId" type="xsd:string" /> - <part name="creditmemoData" type="typens:salesOrderCreditmemoData" /> - <part name="comment" type="xsd:string" /> - <part name="notifyCustomer" type="xsd:int" /> - <part name="includeComment" type="xsd:int" /> - <part name="refundToStoreCreditAmount" type="xsd:string" /> - </message> - <message name="salesOrderCreditmemoCreateResponse"> - <part name="result" type="xsd:string" /> - </message> - <message name="salesOrderCreditmemoAddCommentRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="creditmemoIncrementId" type="xsd:string" /> - <part name="comment" type="xsd:string" /> - <part name="notifyCustomer" type="xsd:int" /> - <part name="includeComment" type="xsd:int" /> - </message> - <message name="salesOrderCreditmemoAddCommentResponse"> - <part name="result" type="xsd:boolean" /> - </message> - <message name="salesOrderCreditmemoCancelRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="creditmemoIncrementId" type="xsd:string" /> - </message> - <message name="salesOrderCreditmemoCancelResponse"> - <part name="result" type="xsd:boolean" /> - </message> - <message name="salesOrderInvoiceCaptureRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="invoiceIncrementId" type="xsd:string" /> - </message> - <message name="salesOrderInvoiceCaptureResponse"> - <part name="result" type="xsd:boolean" /> - </message> - <message name="salesOrderInvoiceVoidRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="invoiceIncrementId" type="xsd:string" /> - </message> - <message name="salesOrderInvoiceVoidResponse"> - <part name="result" type="xsd:boolean" /> - </message> - <message name="salesOrderInvoiceCancelRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="invoiceIncrementId" type="xsd:string" /> - </message> - <message name="salesOrderInvoiceCancelResponse"> - <part name="result" type="xsd:boolean" /> - </message> - <portType name="{{var wsdl.handler}}PortType"> - <operation name="salesOrderList"> - <documentation>Retrieve list of orders by filters</documentation> - <input message="typens:salesOrderListRequest" /> - <output message="typens:salesOrderListResponse" /> - </operation> - <operation name="salesOrderInfo"> - <documentation>Retrieve order information</documentation> - <input message="typens:salesOrderInfoRequest" /> - <output message="typens:salesOrderInfoResponse" /> - </operation> - <operation name="salesOrderAddComment"> - <documentation>Add comment to order</documentation> - <input message="typens:salesOrderAddCommentRequest" /> - <output message="typens:salesOrderAddCommentResponse" /> - </operation> - <operation name="salesOrderHold"> - <documentation>Hold order</documentation> - <input message="typens:salesOrderHoldRequest" /> - <output message="typens:salesOrderHoldResponse" /> - </operation> - <operation name="salesOrderUnhold"> - <documentation>Unhold order</documentation> - <input message="typens:salesOrderUnholdRequest" /> - <output message="typens:salesOrderUnholdResponse" /> - </operation> - <operation name="salesOrderCancel"> - <documentation>Cancel order</documentation> - <input message="typens:salesOrderCancelRequest" /> - <output message="typens:salesOrderCancelResponse" /> - </operation> - <operation name="salesOrderShipmentList"> - <documentation>Retrieve list of shipments by filters</documentation> - <input message="typens:salesOrderShipmentListRequest" /> - <output message="typens:salesOrderShipmentListResponse" /> - </operation> - <operation name="salesOrderShipmentInfo"> - <documentation>Retrieve shipment information</documentation> - <input message="typens:salesOrderShipmentInfoRequest" /> - <output message="typens:salesOrderShipmentInfoResponse" /> - </operation> - <operation name="salesOrderShipmentCreate"> - <documentation>Create new shipment for order</documentation> - <input message="typens:salesOrderShipmentCreateRequest" /> - <output message="typens:salesOrderShipmentCreateResponse" /> - </operation> - <operation name="salesOrderShipmentAddComment"> - <documentation>Add new comment to shipment</documentation> - <input message="typens:salesOrderShipmentAddCommentRequest" /> - <output message="typens:salesOrderShipmentAddCommentResponse" /> - </operation> - <operation name="salesOrderShipmentAddTrack"> - <documentation>Add new tracking number</documentation> - <input message="typens:salesOrderShipmentAddTrackRequest" /> - <output message="typens:salesOrderShipmentAddTrackResponse" /> - </operation> - <operation name="salesOrderShipmentSendInfo"> - <documentation>Send shipment info</documentation> - <input message="typens:salesOrderShipmentSendInfoRequest" /> - <output message="typens:salesOrderShipmentSendInfoResponse" /> - </operation> - <operation name="salesOrderShipmentRemoveTrack"> - <documentation>Remove tracking number</documentation> - <input message="typens:salesOrderShipmentRemoveTrackRequest" /> - <output message="typens:salesOrderShipmentRemoveTrackResponse" /> - </operation> - <operation name="salesOrderShipmentGetCarriers"> - <documentation>Retrieve list of allowed carriers for order</documentation> - <input message="typens:salesOrderShipmentGetCarriersRequest" /> - <output message="typens:salesOrderShipmentGetCarriersResponse" /> - </operation> - <operation name="salesOrderInvoiceList"> - <documentation>Retrieve list of invoices by filters</documentation> - <input message="typens:salesOrderInvoiceListRequest" /> - <output message="typens:salesOrderInvoiceListResponse" /> - </operation> - <operation name="salesOrderInvoiceInfo"> - <documentation>Retrieve invoice information</documentation> - <input message="typens:salesOrderInvoiceInfoRequest" /> - <output message="typens:salesOrderInvoiceInfoResponse" /> - </operation> - <operation name="salesOrderInvoiceCreate"> - <documentation>Create new invoice for order</documentation> - <input message="typens:salesOrderInvoiceCreateRequest" /> - <output message="typens:salesOrderInvoiceCreateResponse" /> - </operation> - <operation name="salesOrderInvoiceAddComment"> - <documentation>Add new comment to shipment</documentation> - <input message="typens:salesOrderInvoiceAddCommentRequest" /> - <output message="typens:salesOrderInvoiceAddCommentResponse" /> - </operation> - <operation name="salesOrderInvoiceCapture"> - <documentation>Capture invoice</documentation> - <input message="typens:salesOrderInvoiceCaptureRequest" /> - <output message="typens:salesOrderInvoiceCaptureResponse" /> - </operation> - <operation name="salesOrderInvoiceVoid"> - <documentation>Void invoice</documentation> - <input message="typens:salesOrderInvoiceVoidRequest" /> - <output message="typens:salesOrderInvoiceVoidResponse" /> - </operation> - <operation name="salesOrderInvoiceCancel"> - <documentation>Cancel invoice</documentation> - <input message="typens:salesOrderInvoiceCancelRequest" /> - <output message="typens:salesOrderInvoiceCancelResponse" /> - </operation> - <operation name="salesOrderCreditmemoList"> - <documentation>Retrieve list of creditmemos by filters</documentation> - <input message="typens:salesOrderCreditmemoListRequest" /> - <output message="typens:salesOrderCreditmemoListResponse" /> - </operation> - <operation name="salesOrderCreditmemoInfo"> - <documentation>Retrieve creditmemo information</documentation> - <input message="typens:salesOrderCreditmemoInfoRequest" /> - <output message="typens:salesOrderCreditmemoInfoResponse" /> - </operation> - <operation name="salesOrderCreditmemoCreate"> - <documentation>Create new creditmemo for order</documentation> - <input message="typens:salesOrderCreditmemoCreateRequest" /> - <output message="typens:salesOrderCreditmemoCreateResponse" /> - </operation> - <operation name="salesOrderCreditmemoAddComment"> - <documentation>Add new comment to shipment</documentation> - <input message="typens:salesOrderCreditmemoAddCommentRequest" /> - <output message="typens:salesOrderCreditmemoAddCommentResponse" /> - </operation> - <operation name="salesOrderCreditmemoCancel"> - <documentation>Cancel creditmemo</documentation> - <input message="typens:salesOrderCreditmemoCancelRequest" /> - <output message="typens:salesOrderCreditmemoCancelResponse" /> - </operation> - </portType> - <binding name="{{var wsdl.handler}}Binding" type="typens:{{var wsdl.handler}}PortType"> - <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" /> - <operation name="salesOrderList"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="salesOrderInfo"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="salesOrderAddComment"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="salesOrderHold"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="salesOrderUnhold"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="salesOrderCancel"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="salesOrderShipmentList"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="salesOrderShipmentInfo"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="salesOrderShipmentCreate"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="salesOrderShipmentAddComment"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="salesOrderShipmentAddTrack"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="salesOrderShipmentSendInfo"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="salesOrderShipmentRemoveTrack"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="salesOrderShipmentGetCarriers"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="salesOrderInvoiceList"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="salesOrderInvoiceInfo"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="salesOrderInvoiceCreate"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="salesOrderInvoiceAddComment"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="salesOrderInvoiceCapture"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="salesOrderInvoiceVoid"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="salesOrderInvoiceCancel"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="salesOrderCreditmemoList"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="salesOrderCreditmemoInfo"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="salesOrderCreditmemoCreate"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="salesOrderCreditmemoAddComment"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - <operation name="salesOrderCreditmemoCancel"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - </binding> - <service name="{{var wsdl.name}}Service"> - <port name="{{var wsdl.handler}}Port" binding="typens:{{var wsdl.handler}}Binding"> - <soap:address location="{{var wsdl.url}}" /> - </port> - </service> -</definitions> diff --git a/app/code/core/Mage/Sales/etc/wsi.xml b/app/code/core/Mage/Sales/etc/wsi.xml deleted file mode 100644 index 8493b7af831b13c1657f22b74627f1278665b715..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Sales/etc/wsi.xml +++ /dev/null @@ -1,1686 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<wsdl:definitions xmlns:typens="urn:{{var wsdl.name}}" - xmlns:xsd="http://www.w3.org/2001/XMLSchema" - xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" - xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" - xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" - name="{{var wsdl.name}}" - targetNamespace="urn:{{var wsdl.name}}"> - <wsdl:types> - <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:{{var wsdl.name}}"> - <xsd:complexType name="salesOrderEntity"> - <xsd:sequence> - <xsd:element name="increment_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="parent_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="store_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="created_at" type="xsd:string" minOccurs="0" /> - <xsd:element name="updated_at" type="xsd:string" minOccurs="0" /> - <xsd:element name="is_active" type="xsd:string" minOccurs="0" /> - <xsd:element name="customer_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="tax_amount" type="xsd:string" minOccurs="0" /> - <xsd:element name="shipping_amount" type="xsd:string" minOccurs="0" /> - <xsd:element name="discount_amount" type="xsd:string" minOccurs="0" /> - <xsd:element name="subtotal" type="xsd:string" minOccurs="0" /> - <xsd:element name="grand_total" type="xsd:string" minOccurs="0" /> - <xsd:element name="total_paid" type="xsd:string" minOccurs="0" /> - <xsd:element name="total_refunded" type="xsd:string" minOccurs="0" /> - <xsd:element name="total_qty_ordered" type="xsd:string" minOccurs="0" /> - <xsd:element name="total_canceled" type="xsd:string" minOccurs="0" /> - <xsd:element name="total_invoiced" type="xsd:string" minOccurs="0" /> - <xsd:element name="total_online_refunded" type="xsd:string" minOccurs="0" /> - <xsd:element name="total_offline_refunded" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_tax_amount" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_shipping_amount" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_discount_amount" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_subtotal" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_grand_total" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_total_paid" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_total_refunded" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_total_qty_ordered" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_total_canceled" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_total_invoiced" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_total_online_refunded" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_total_offline_refunded" type="xsd:string" minOccurs="0" /> - <xsd:element name="billing_address_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="billing_firstname" type="xsd:string" minOccurs="0" /> - <xsd:element name="billing_lastname" type="xsd:string" minOccurs="0" /> - <xsd:element name="shipping_address_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="shipping_firstname" type="xsd:string" minOccurs="0" /> - <xsd:element name="shipping_lastname" type="xsd:string" minOccurs="0" /> - <xsd:element name="billing_name" type="xsd:string" minOccurs="0" /> - <xsd:element name="shipping_name" type="xsd:string" minOccurs="0" /> - <xsd:element name="store_to_base_rate" type="xsd:string" minOccurs="0" /> - <xsd:element name="store_to_order_rate" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_to_global_rate" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_to_order_rate" type="xsd:string" minOccurs="0" /> - <xsd:element name="weight" type="xsd:string" minOccurs="0" /> - <xsd:element name="store_name" type="xsd:string" minOccurs="0" /> - <xsd:element name="remote_ip" type="xsd:string" minOccurs="0" /> - <xsd:element name="status" type="xsd:string" minOccurs="0" /> - <xsd:element name="state" type="xsd:string" minOccurs="0" /> - <xsd:element name="applied_rule_ids" type="xsd:string" minOccurs="0" /> - <xsd:element name="global_currency_code" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_currency_code" type="xsd:string" minOccurs="0" /> - <xsd:element name="store_currency_code" type="xsd:string" minOccurs="0" /> - <xsd:element name="order_currency_code" type="xsd:string" minOccurs="0" /> - <xsd:element name="shipping_method" type="xsd:string" minOccurs="0" /> - <xsd:element name="shipping_description" type="xsd:string" minOccurs="0" /> - <xsd:element name="customer_email" type="xsd:string" minOccurs="0" /> - <xsd:element name="customer_firstname" type="xsd:string" minOccurs="0" /> - <xsd:element name="customer_lastname" type="xsd:string" minOccurs="0" /> - <xsd:element name="quote_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="is_virtual" type="xsd:string" minOccurs="0" /> - <xsd:element name="customer_group_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="customer_note_notify" type="xsd:string" minOccurs="0" /> - <xsd:element name="customer_is_guest" type="xsd:string" minOccurs="0" /> - <xsd:element name="email_sent" type="xsd:string" minOccurs="0" /> - <xsd:element name="order_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="gift_message_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="gift_message" type="xsd:string" minOccurs="0" /> - <xsd:element name="shipping_address" type="typens:salesOrderAddressEntity" minOccurs="0" /> - <xsd:element name="billing_address" type="typens:salesOrderAddressEntity" minOccurs="0" /> - <xsd:element name="items" type="typens:salesOrderItemEntityArray" minOccurs="0" /> - <xsd:element name="payment" type="typens:salesOrderPaymentEntity" minOccurs="0" /> - <xsd:element name="status_history" type="typens:salesOrderStatusHistoryEntityArray" minOccurs="0" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="salesOrderListEntity"> - <xsd:sequence> - <xsd:element name="increment_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="store_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="created_at" type="xsd:string" minOccurs="0" /> - <xsd:element name="updated_at" type="xsd:string" minOccurs="0" /> - <xsd:element name="customer_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="tax_amount" type="xsd:string" minOccurs="0" /> - <xsd:element name="shipping_amount" type="xsd:string" minOccurs="0" /> - <xsd:element name="discount_amount" type="xsd:string" minOccurs="0" /> - <xsd:element name="subtotal" type="xsd:string" minOccurs="0" /> - <xsd:element name="grand_total" type="xsd:string" minOccurs="0" /> - <xsd:element name="total_paid" type="xsd:string" minOccurs="0" /> - <xsd:element name="total_refunded" type="xsd:string" minOccurs="0" /> - <xsd:element name="total_qty_ordered" type="xsd:string" minOccurs="0" /> - <xsd:element name="total_canceled" type="xsd:string" minOccurs="0" /> - <xsd:element name="total_invoiced" type="xsd:string" minOccurs="0" /> - <xsd:element name="total_online_refunded" type="xsd:string" minOccurs="0" /> - <xsd:element name="total_offline_refunded" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_tax_amount" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_shipping_amount" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_discount_amount" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_subtotal" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_grand_total" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_total_paid" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_total_refunded" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_total_qty_ordered" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_total_canceled" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_total_invoiced" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_total_online_refunded" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_total_offline_refunded" type="xsd:string" minOccurs="0" /> - <xsd:element name="billing_address_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="billing_firstname" type="xsd:string" minOccurs="0" /> - <xsd:element name="billing_lastname" type="xsd:string" minOccurs="0" /> - <xsd:element name="shipping_address_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="shipping_firstname" type="xsd:string" minOccurs="0" /> - <xsd:element name="shipping_lastname" type="xsd:string" minOccurs="0" /> - <xsd:element name="billing_name" type="xsd:string" minOccurs="0" /> - <xsd:element name="shipping_name" type="xsd:string" minOccurs="0" /> - <xsd:element name="store_to_base_rate" type="xsd:string" minOccurs="0" /> - <xsd:element name="store_to_order_rate" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_to_global_rate" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_to_order_rate" type="xsd:string" minOccurs="0" /> - <xsd:element name="weight" type="xsd:string" minOccurs="0" /> - <xsd:element name="store_name" type="xsd:string" minOccurs="0" /> - <xsd:element name="remote_ip" type="xsd:string" minOccurs="0" /> - <xsd:element name="status" type="xsd:string" minOccurs="0" /> - <xsd:element name="state" type="xsd:string" minOccurs="0" /> - <xsd:element name="applied_rule_ids" type="xsd:string" minOccurs="0" /> - <xsd:element name="global_currency_code" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_currency_code" type="xsd:string" minOccurs="0" /> - <xsd:element name="store_currency_code" type="xsd:string" minOccurs="0" /> - <xsd:element name="order_currency_code" type="xsd:string" minOccurs="0" /> - <xsd:element name="shipping_method" type="xsd:string" minOccurs="0" /> - <xsd:element name="shipping_description" type="xsd:string" minOccurs="0" /> - <xsd:element name="customer_email" type="xsd:string" minOccurs="0" /> - <xsd:element name="customer_firstname" type="xsd:string" minOccurs="0" /> - <xsd:element name="customer_lastname" type="xsd:string" minOccurs="0" /> - <xsd:element name="quote_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="is_virtual" type="xsd:string" minOccurs="0" /> - <xsd:element name="customer_group_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="customer_note_notify" type="xsd:string" minOccurs="0" /> - <xsd:element name="customer_is_guest" type="xsd:string" minOccurs="0" /> - <xsd:element name="email_sent" type="xsd:string" minOccurs="0" /> - <xsd:element name="order_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="gift_message_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="coupon_code" type="xsd:string" minOccurs="0" /> - <xsd:element name="protect_code" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_discount_canceled" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_discount_invoiced" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_discount_refunded" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_shipping_canceled" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_shipping_invoiced" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_shipping_refunded" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_shipping_tax_amount" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_shipping_tax_refunded" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_subtotal_canceled" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_subtotal_invoiced" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_subtotal_refunded" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_tax_canceled" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_tax_invoiced" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_tax_refunded" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_total_invoiced_cost" type="xsd:string" minOccurs="0" /> - <xsd:element name="discount_canceled" type="xsd:string" minOccurs="0" /> - <xsd:element name="discount_invoiced" type="xsd:string" minOccurs="0" /> - <xsd:element name="discount_refunded" type="xsd:string" minOccurs="0" /> - <xsd:element name="shipping_canceled" type="xsd:string" minOccurs="0" /> - <xsd:element name="shipping_invoiced" type="xsd:string" minOccurs="0" /> - <xsd:element name="shipping_refunded" type="xsd:string" minOccurs="0" /> - <xsd:element name="shipping_tax_amount" type="xsd:string" minOccurs="0" /> - <xsd:element name="shipping_tax_refunded" type="xsd:string" minOccurs="0" /> - <xsd:element name="subtotal_canceled" type="xsd:string" minOccurs="0" /> - <xsd:element name="subtotal_invoiced" type="xsd:string" minOccurs="0" /> - <xsd:element name="subtotal_refunded" type="xsd:string" minOccurs="0" /> - <xsd:element name="tax_canceled" type="xsd:string" minOccurs="0" /> - <xsd:element name="tax_invoiced" type="xsd:string" minOccurs="0" /> - <xsd:element name="tax_refunded" type="xsd:string" minOccurs="0" /> - <xsd:element name="can_ship_partially" type="xsd:string" minOccurs="0" /> - <xsd:element name="can_ship_partially_item" type="xsd:string" minOccurs="0" /> - <xsd:element name="edit_increment" type="xsd:string" minOccurs="0" /> - <xsd:element name="forced_do_shipment_with_invoice" type="xsd:string" minOccurs="0" /> - <xsd:element name="payment_authorization_expiration" type="xsd:string" minOccurs="0" /> - <xsd:element name="paypal_ipn_customer_notified" type="xsd:string" minOccurs="0" /> - <xsd:element name="quote_address_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="adjustment_negative" type="xsd:string" minOccurs="0" /> - <xsd:element name="adjustment_positive" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_adjustment_negative" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_adjustment_positive" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_shipping_discount_amount" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_subtotal_incl_tax" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_total_due" type="xsd:string" minOccurs="0" /> - <xsd:element name="payment_authorization_amount" type="xsd:string" minOccurs="0" /> - <xsd:element name="shipping_discount_amount" type="xsd:string" minOccurs="0" /> - <xsd:element name="subtotal_incl_tax" type="xsd:string" minOccurs="0" /> - <xsd:element name="total_due" type="xsd:string" minOccurs="0" /> - <xsd:element name="customer_dob" type="xsd:string" minOccurs="0" /> - <xsd:element name="customer_middlename" type="xsd:string" minOccurs="0" /> - <xsd:element name="customer_prefix" type="xsd:string" minOccurs="0" /> - <xsd:element name="customer_suffix" type="xsd:string" minOccurs="0" /> - <xsd:element name="customer_taxvat" type="xsd:string" minOccurs="0" /> - <xsd:element name="discount_description" type="xsd:string" minOccurs="0" /> - <xsd:element name="ext_customer_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="ext_order_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="hold_before_state" type="xsd:string" minOccurs="0" /> - <xsd:element name="hold_before_status" type="xsd:string" minOccurs="0" /> - <xsd:element name="original_increment_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="relation_child_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="relation_child_real_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="relation_parent_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="relation_parent_real_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="x_forwarded_for" type="xsd:string" minOccurs="0" /> - <xsd:element name="customer_note" type="xsd:string" minOccurs="0" /> - <xsd:element name="total_item_count" type="xsd:string" minOccurs="0" /> - <xsd:element name="customer_gender" type="xsd:string" minOccurs="0" /> - <xsd:element name="hidden_tax_amount" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_hidden_tax_amount" type="xsd:string" minOccurs="0" /> - <xsd:element name="shipping_hidden_tax_amount" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_shipping_hidden_tax_amount" type="xsd:string" minOccurs="0" /> - <xsd:element name="hidden_tax_invoiced" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_hidden_tax_invoiced" type="xsd:string" minOccurs="0" /> - <xsd:element name="hidden_tax_refunded" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_hidden_tax_refunded" type="xsd:string" minOccurs="0" /> - <xsd:element name="shipping_incl_tax" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_shipping_incl_tax" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_customer_balance_amount" type="xsd:string" minOccurs="0" /> - <xsd:element name="customer_balance_amount" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_customer_balance_invoiced" type="xsd:string" minOccurs="0" /> - <xsd:element name="customer_balance_invoiced" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_customer_balance_refunded" type="xsd:string" minOccurs="0" /> - <xsd:element name="customer_balance_refunded" type="xsd:string" minOccurs="0" /> - <xsd:element name="bs_customer_bal_total_refunded" type="xsd:string" minOccurs="0" /> - <xsd:element name="customer_bal_total_refunded" type="xsd:string" minOccurs="0" /> - <xsd:element name="gift_cards" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_gift_cards_amount" type="xsd:string" minOccurs="0" /> - <xsd:element name="gift_cards_amount" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_gift_cards_invoiced" type="xsd:string" minOccurs="0" /> - <xsd:element name="gift_cards_invoiced" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_gift_cards_refunded" type="xsd:string" minOccurs="0" /> - <xsd:element name="gift_cards_refunded" type="xsd:string" minOccurs="0" /> - <xsd:element name="reward_points_balance" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_reward_currency_amount" type="xsd:string" minOccurs="0" /> - <xsd:element name="reward_currency_amount" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_rwrd_crrncy_amt_invoiced" type="xsd:string" minOccurs="0" /> - <xsd:element name="rwrd_currency_amount_invoiced" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_rwrd_crrncy_amnt_refnded" type="xsd:string" minOccurs="0" /> - <xsd:element name="rwrd_crrncy_amnt_refunded" type="xsd:string" minOccurs="0" /> - <xsd:element name="reward_points_balance_refunded" type="xsd:string" minOccurs="0" /> - <xsd:element name="reward_points_balance_refund" type="xsd:string" minOccurs="0" /> - <xsd:element name="reward_salesrule_points" type="xsd:string" minOccurs="0" /> - <xsd:element name="firstname" type="xsd:string" minOccurs="0" /> - <xsd:element name="lastname" type="xsd:string" minOccurs="0" /> - <xsd:element name="telephone" type="xsd:string" minOccurs="0" /> - <xsd:element name="postcode" type="xsd:string" minOccurs="0" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="salesOrderListEntityArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:salesOrderListEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="salesOrderAddressEntity"> - <xsd:sequence> - <xsd:element name="increment_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="parent_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="created_at" type="xsd:string" minOccurs="0" /> - <xsd:element name="updated_at" type="xsd:string" minOccurs="0" /> - <xsd:element name="is_active" type="xsd:string" minOccurs="0" /> - <xsd:element name="address_type" type="xsd:string" minOccurs="0" /> - <xsd:element name="firstname" type="xsd:string" minOccurs="0" /> - <xsd:element name="lastname" type="xsd:string" minOccurs="0" /> - <xsd:element name="company" type="xsd:string" minOccurs="0" /> - <xsd:element name="street" type="xsd:string" minOccurs="0" /> - <xsd:element name="city" type="xsd:string" minOccurs="0" /> - <xsd:element name="region" type="xsd:string" minOccurs="0" /> - <xsd:element name="postcode" type="xsd:string" minOccurs="0" /> - <xsd:element name="country_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="telephone" type="xsd:string" minOccurs="0" /> - <xsd:element name="fax" type="xsd:string" minOccurs="0" /> - <xsd:element name="region_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="address_id" type="xsd:string" minOccurs="0" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="salesOrderItemEntity"> - <xsd:sequence> - <xsd:element name="item_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="order_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="quote_item_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="created_at" type="xsd:string" minOccurs="0" /> - <xsd:element name="updated_at" type="xsd:string" minOccurs="0" /> - <xsd:element name="product_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="product_type" type="xsd:string" minOccurs="0" /> - <xsd:element name="product_options" type="xsd:string" minOccurs="0" /> - <xsd:element name="weight" type="xsd:string" minOccurs="0" /> - <xsd:element name="is_virtual" type="xsd:string" minOccurs="0" /> - <xsd:element name="sku" type="xsd:string" minOccurs="0" /> - <xsd:element name="name" type="xsd:string" minOccurs="0" /> - <xsd:element name="applied_rule_ids" type="xsd:string" minOccurs="0" /> - <xsd:element name="free_shipping" type="xsd:string" minOccurs="0" /> - <xsd:element name="is_qty_decimal" type="xsd:string" minOccurs="0" /> - <xsd:element name="no_discount" type="xsd:string" minOccurs="0" /> - <xsd:element name="qty_canceled" type="xsd:string" minOccurs="0" /> - <xsd:element name="qty_invoiced" type="xsd:string" minOccurs="0" /> - <xsd:element name="qty_ordered" type="xsd:string" minOccurs="0" /> - <xsd:element name="qty_refunded" type="xsd:string" minOccurs="0" /> - <xsd:element name="qty_shipped" type="xsd:string" minOccurs="0" /> - <xsd:element name="cost" type="xsd:string" minOccurs="0" /> - <xsd:element name="price" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_price" type="xsd:string" minOccurs="0" /> - <xsd:element name="original_price" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_original_price" type="xsd:string" minOccurs="0" /> - <xsd:element name="tax_percent" type="xsd:string" minOccurs="0" /> - <xsd:element name="tax_amount" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_tax_amount" type="xsd:string" minOccurs="0" /> - <xsd:element name="tax_invoiced" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_tax_invoiced" type="xsd:string" minOccurs="0" /> - <xsd:element name="discount_percent" type="xsd:string" minOccurs="0" /> - <xsd:element name="discount_amount" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_discount_amount" type="xsd:string" minOccurs="0" /> - <xsd:element name="discount_invoiced" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_discount_invoiced" type="xsd:string" minOccurs="0" /> - <xsd:element name="amount_refunded" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_amount_refunded" type="xsd:string" minOccurs="0" /> - <xsd:element name="row_total" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_row_total" type="xsd:string" minOccurs="0" /> - <xsd:element name="row_invoiced" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_row_invoiced" type="xsd:string" minOccurs="0" /> - <xsd:element name="row_weight" type="xsd:string" minOccurs="0" /> - <xsd:element name="gift_message_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="gift_message" type="xsd:string" minOccurs="0" /> - <xsd:element name="gift_message_available" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_tax_before_discount" type="xsd:string" minOccurs="0" /> - <xsd:element name="tax_before_discount" type="xsd:string" minOccurs="0" /> - <xsd:element name="weee_tax_applied" type="xsd:string" minOccurs="0" /> - <xsd:element name="weee_tax_applied_amount" type="xsd:string" minOccurs="0" /> - <xsd:element name="weee_tax_applied_row_amount" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_weee_tax_applied_amount" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_weee_tax_applied_row_amnt" type="xsd:string" minOccurs="0" /> - <xsd:element name="weee_tax_disposition" type="xsd:string" minOccurs="0" /> - <xsd:element name="weee_tax_row_disposition" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_weee_tax_disposition" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_weee_tax_row_disposition" type="xsd:string" minOccurs="0" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="salesOrderItemEntityArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:salesOrderItemEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="orderItemIdQty"> - <xsd:sequence> - <xsd:element name="order_item_id" type="xsd:int" /> - <xsd:element name="qty" type="xsd:double" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="orderItemIdQtyArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:orderItemIdQty" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="salesOrderPaymentEntity"> - <xsd:sequence> - <xsd:element name="increment_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="parent_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="created_at" type="xsd:string" minOccurs="0" /> - <xsd:element name="updated_at" type="xsd:string" minOccurs="0" /> - <xsd:element name="is_active" type="xsd:string" minOccurs="0" /> - <xsd:element name="amount_ordered" type="xsd:string" minOccurs="0" /> - <xsd:element name="shipping_amount" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_amount_ordered" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_shipping_amount" type="xsd:string" minOccurs="0" /> - <xsd:element name="method" type="xsd:string" minOccurs="0" /> - <xsd:element name="po_number" type="xsd:string" minOccurs="0" /> - <xsd:element name="cc_type" type="xsd:string" minOccurs="0" /> - <xsd:element name="cc_number_enc" type="xsd:string" minOccurs="0" /> - <xsd:element name="cc_last4" type="xsd:string" minOccurs="0" /> - <xsd:element name="cc_owner" type="xsd:string" minOccurs="0" /> - <xsd:element name="cc_exp_month" type="xsd:string" minOccurs="0" /> - <xsd:element name="cc_exp_year" type="xsd:string" minOccurs="0" /> - <xsd:element name="cc_ss_start_month" type="xsd:string" minOccurs="0" /> - <xsd:element name="cc_ss_start_year" type="xsd:string" minOccurs="0" /> - <xsd:element name="payment_id" type="xsd:string" minOccurs="0" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="salesOrderStatusHistoryEntity"> - <xsd:sequence> - <xsd:element name="increment_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="parent_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="created_at" type="xsd:string" minOccurs="0" /> - <xsd:element name="updated_at" type="xsd:string" minOccurs="0" /> - <xsd:element name="is_active" type="xsd:string" minOccurs="0" /> - <xsd:element name="is_customer_notified" type="xsd:string" minOccurs="0" /> - <xsd:element name="status" type="xsd:string" minOccurs="0" /> - <xsd:element name="comment" type="xsd:string" minOccurs="0" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="salesOrderStatusHistoryEntityArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:salesOrderStatusHistoryEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="salesOrderShipmentEntity"> - <xsd:sequence> - <xsd:element name="increment_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="parent_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="store_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="created_at" type="xsd:string" minOccurs="0" /> - <xsd:element name="updated_at" type="xsd:string" minOccurs="0" /> - <xsd:element name="is_active" type="xsd:string" minOccurs="0" /> - <xsd:element name="shipping_address_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="shipping_firstname" type="xsd:string" minOccurs="0" /> - <xsd:element name="shipping_lastname" type="xsd:string" minOccurs="0" /> - <xsd:element name="order_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="order_increment_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="order_created_at" type="xsd:string" minOccurs="0" /> - <xsd:element name="total_qty" type="xsd:string" minOccurs="0" /> - <xsd:element name="shipment_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="items" type="typens:salesOrderShipmentItemEntityArray" minOccurs="0" /> - <xsd:element name="tracks" type="typens:salesOrderShipmentTrackEntityArray" minOccurs="0" /> - <xsd:element name="comments" type="typens:salesOrderShipmentCommentEntityArray" minOccurs="0" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="salesOrderShipmentEntityArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:salesOrderShipmentEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="salesOrderShipmentCommentEntity"> - <xsd:sequence> - <xsd:element name="increment_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="parent_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="created_at" type="xsd:string" minOccurs="0" /> - <xsd:element name="updated_at" type="xsd:string" minOccurs="0" /> - <xsd:element name="is_active" type="xsd:string" minOccurs="0" /> - <xsd:element name="comment" type="xsd:string" minOccurs="0" /> - <xsd:element name="is_customer_notified" type="xsd:string" minOccurs="0" /> - <xsd:element name="comment_id" type="xsd:string" minOccurs="0" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="salesOrderShipmentCommentEntityArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:salesOrderShipmentCommentEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="salesOrderShipmentTrackEntity"> - <xsd:sequence> - <xsd:element name="increment_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="parent_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="created_at" type="xsd:string" minOccurs="0" /> - <xsd:element name="updated_at" type="xsd:string" minOccurs="0" /> - <xsd:element name="is_active" type="xsd:string" minOccurs="0" /> - <xsd:element name="carrier_code" type="xsd:string" minOccurs="0" /> - <xsd:element name="title" type="xsd:string" minOccurs="0" /> - <xsd:element name="number" type="xsd:string" minOccurs="0" /> - <xsd:element name="order_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="track_id" type="xsd:string" minOccurs="0" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="salesOrderShipmentTrackEntityArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:salesOrderShipmentTrackEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="salesOrderShipmentItemEntity"> - <xsd:sequence> - <xsd:element name="increment_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="parent_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="created_at" type="xsd:string" minOccurs="0" /> - <xsd:element name="updated_at" type="xsd:string" minOccurs="0" /> - <xsd:element name="is_active" type="xsd:string" minOccurs="0" /> - <xsd:element name="sku" type="xsd:string" minOccurs="0" /> - <xsd:element name="name" type="xsd:string" minOccurs="0" /> - <xsd:element name="order_item_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="product_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="weight" type="xsd:string" minOccurs="0" /> - <xsd:element name="price" type="xsd:string" minOccurs="0" /> - <xsd:element name="qty" type="xsd:string" minOccurs="0" /> - <xsd:element name="item_id" type="xsd:string" minOccurs="0" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="salesOrderShipmentItemEntityArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:salesOrderShipmentItemEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="salesOrderInvoiceEntity"> - <xsd:sequence> - <xsd:element name="increment_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="parent_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="store_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="created_at" type="xsd:string" minOccurs="0" /> - <xsd:element name="updated_at" type="xsd:string" minOccurs="0" /> - <xsd:element name="is_active" type="xsd:string" minOccurs="0" /> - <xsd:element name="global_currency_code" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_currency_code" type="xsd:string" minOccurs="0" /> - <xsd:element name="store_currency_code" type="xsd:string" minOccurs="0" /> - <xsd:element name="order_currency_code" type="xsd:string" minOccurs="0" /> - <xsd:element name="store_to_base_rate" type="xsd:string" minOccurs="0" /> - <xsd:element name="store_to_order_rate" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_to_global_rate" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_to_order_rate" type="xsd:string" minOccurs="0" /> - <xsd:element name="subtotal" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_subtotal" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_grand_total" type="xsd:string" minOccurs="0" /> - <xsd:element name="discount_amount" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_discount_amount" type="xsd:string" minOccurs="0" /> - <xsd:element name="shipping_amount" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_shipping_amount" type="xsd:string" minOccurs="0" /> - <xsd:element name="tax_amount" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_tax_amount" type="xsd:string" minOccurs="0" /> - <xsd:element name="billing_address_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="billing_firstname" type="xsd:string" minOccurs="0" /> - <xsd:element name="billing_lastname" type="xsd:string" minOccurs="0" /> - <xsd:element name="order_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="order_increment_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="order_created_at" type="xsd:string" minOccurs="0" /> - <xsd:element name="state" type="xsd:string" minOccurs="0" /> - <xsd:element name="grand_total" type="xsd:string" minOccurs="0" /> - <xsd:element name="invoice_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="items" type="typens:salesOrderInvoiceItemEntityArray" minOccurs="0" /> - <xsd:element name="comments" type="typens:salesOrderInvoiceCommentEntityArray" minOccurs="0" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="salesOrderInvoiceEntityArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:salesOrderInvoiceEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="salesOrderInvoiceItemEntity"> - <xsd:sequence> - <xsd:element name="increment_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="parent_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="created_at" type="xsd:string" minOccurs="0" /> - <xsd:element name="updated_at" type="xsd:string" minOccurs="0" /> - <xsd:element name="is_active" type="xsd:string" minOccurs="0" /> - <xsd:element name="weee_tax_applied" type="xsd:string" minOccurs="0" /> - <xsd:element name="qty" type="xsd:string" minOccurs="0" /> - <xsd:element name="cost" type="xsd:string" minOccurs="0" /> - <xsd:element name="price" type="xsd:string" minOccurs="0" /> - <xsd:element name="tax_amount" type="xsd:string" minOccurs="0" /> - <xsd:element name="row_total" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_price" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_tax_amount" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_row_total" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_weee_tax_applied_amount" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_weee_tax_applied_row_amnt" type="xsd:string" minOccurs="0" /> - <xsd:element name="weee_tax_applied_amount" type="xsd:string" minOccurs="0" /> - <xsd:element name="weee_tax_applied_row_amount" type="xsd:string" minOccurs="0" /> - <xsd:element name="weee_tax_disposition" type="xsd:string" minOccurs="0" /> - <xsd:element name="weee_tax_row_disposition" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_weee_tax_disposition" type="xsd:string" minOccurs="0" /> - <xsd:element name="base_weee_tax_row_disposition" type="xsd:string" minOccurs="0" /> - <xsd:element name="sku" type="xsd:string" minOccurs="0" /> - <xsd:element name="name" type="xsd:string" minOccurs="0" /> - <xsd:element name="order_item_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="product_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="item_id" type="xsd:string" minOccurs="0" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="salesOrderInvoiceItemEntityArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:salesOrderInvoiceItemEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="salesOrderInvoiceCommentEntity"> - <xsd:sequence> - <xsd:element name="increment_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="parent_id" type="xsd:string" minOccurs="0" /> - <xsd:element name="created_at" type="xsd:string" minOccurs="0" /> - <xsd:element name="updated_at" type="xsd:string" minOccurs="0" /> - <xsd:element name="is_active" type="xsd:string" minOccurs="0" /> - <xsd:element name="comment" type="xsd:string" minOccurs="0" /> - <xsd:element name="is_customer_notified" type="xsd:string" minOccurs="0" /> - <xsd:element name="comment_id" type="xsd:string" minOccurs="0" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="salesOrderInvoiceCommentEntityArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:salesOrderInvoiceCommentEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="salesOrderCreditmemoEntity"> - <xsd:sequence> - <xsd:element name="updated_at" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="created_at" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="increment_id" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="transaction_id" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="global_currency_code" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="base_currency_code" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="order_currency_code" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="store_currency_code" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="cybersource_token" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="invoice_id" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="billing_address_id" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="shipping_address_id" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="state" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="creditmemo_status" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="email_sent" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="order_id" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="tax_amount" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="shipping_tax_amount" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="base_tax_amount" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="base_adjustment_positive" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="base_grand_total" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="adjustment" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="subtotal" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="discount_amount" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="base_subtotal" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="base_adjustment" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="base_to_global_rate" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="store_to_base_rate" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="base_shipping_amount" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="adjustment_negative" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="subtotal_incl_tax" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="shipping_amount" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="base_subtotal_incl_tax" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="base_adjustment_negative" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="grand_total" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="base_discount_amount" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="base_to_order_rate" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="store_to_order_rate" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="base_shipping_tax_amount" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="adjustment_positive" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="store_id" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="hidden_tax_amount" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="base_hidden_tax_amount" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="shipping_hidden_tax_amount" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="base_shipping_hidden_tax_amnt" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="shipping_incl_tax" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="base_shipping_incl_tax" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="base_customer_balance_amount" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="customer_balance_amount" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="bs_customer_bal_total_refunded" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="customer_bal_total_refunded" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="base_gift_cards_amount" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="gift_cards_amount" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="gw_base_price" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="gw_price" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="gw_items_base_price" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="gw_items_price" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="gw_card_base_price" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="gw_card_price" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="gw_base_tax_amount" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="gw_tax_amount" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="gw_items_base_tax_amount" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="gw_items_tax_amount" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="gw_card_base_tax_amount" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="gw_card_tax_amount" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="base_reward_currency_amount" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="reward_currency_amount" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="reward_points_balance" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="reward_points_balance_refund" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="creditmemo_id" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="items" type="typens:salesOrderCreditmemoItemEntityArray" minOccurs="0" maxOccurs="1" /> - <xsd:element name="comments" type="typens:salesOrderCreditmemoCommentEntityArray" minOccurs="0" maxOccurs="1" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="salesOrderCreditmemoEntityArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:salesOrderCreditmemoEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="salesOrderCreditmemoItemEntity"> - <xsd:sequence> - <xsd:element name="item_id" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="parent_id" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="weee_tax_applied_row_amount" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="base_price" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="base_weee_tax_row_disposition" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="tax_amount" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="base_weee_tax_applied_amount" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="weee_tax_row_disposition" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="base_row_total" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="discount_amount" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="row_total" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="weee_tax_applied_amount" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="base_discount_amount" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="base_weee_tax_disposition" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="price_incl_tax" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="base_tax_amount" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="weee_tax_disposition" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="base_price_incl_tax" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="qty" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="base_cost" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="base_weee_tax_applied_row_amount" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="price" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="base_row_total_incl_tax" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="row_total_incl_tax" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="product_id" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="order_item_id" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="additional_data" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="description" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="weee_tax_applied" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="sku" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="name" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="hidden_tax_amount" type="xsd:string" minOccurs="0" maxOccurs="1"/> - <xsd:element name="base_hidden_tax_amount" type="xsd:string" minOccurs="0" maxOccurs="1"/> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="salesOrderCreditmemoItemEntityArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:salesOrderCreditmemoItemEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="salesOrderCreditmemoCommentEntity"> - <xsd:sequence> - <xsd:element name="parent_id" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="created_at" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="comment" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="is_customer_notified" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="comment_id" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="is_visible_on_front" type="xsd:string" minOccurs="0" maxOccurs="1"/> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="salesOrderCreditmemoCommentEntityArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:salesOrderCreditmemoCommentEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="salesOrderCreditmemoData"> - <xsd:sequence> - <xsd:element name="qtys" type="typens:orderItemIdQtyArray" minOccurs="0" maxOccurs="1"/> - <xsd:element name="shipping_amount" type="xsd:double" minOccurs="0" maxOccurs="1"/> - <xsd:element name="adjustment_positive" type="xsd:double" minOccurs="0" maxOccurs="1"/> - <xsd:element name="adjustment_negative" type="xsd:double" minOccurs="0" maxOccurs="1"/> - </xsd:sequence> - </xsd:complexType> - - <xsd:element name="salesOrderListRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="filters" type="typens:filters" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderListResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:salesOrderListEntityArray" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderInfoRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="orderIncrementId" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderInfoResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:salesOrderEntity" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderAddCommentRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="orderIncrementId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="status" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="comment" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="notify" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderAddCommentResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderHoldRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="orderIncrementId" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderHoldResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderUnholdRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="orderIncrementId" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderUnholdResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderCancelRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="orderIncrementId" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderCancelResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderShipmentListRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="filters" type="typens:filters" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderShipmentListResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:salesOrderShipmentEntityArray" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderShipmentInfoRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="shipmentIncrementId" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderShipmentInfoResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:salesOrderShipmentEntity" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderShipmentCreateRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="orderIncrementId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="itemsQty" type="typens:orderItemIdQtyArray" /> - <xsd:element minOccurs="0" maxOccurs="1" name="comment" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="email" type="xsd:int" /> - <xsd:element minOccurs="1" maxOccurs="1" name="includeComment" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderShipmentCreateResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderShipmentAddTrackRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="shipmentIncrementId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="carrier" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="title" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="trackNumber" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderShipmentAddTrackResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderShipmentRemoveTrackRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="shipmentIncrementId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="trackId" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderShipmentRemoveTrackResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderShipmentSendInfoRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="shipmentIncrementId" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="comment" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderShipmentSendInfoResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderShipmentAddCommentRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="shipmentIncrementId" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="comment" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="email" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="includeInEmail" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderShipmentAddCommentResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderShipmentGetCarriersRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="orderIncrementId" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderShipmentGetCarriersResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:associativeArray" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderInvoiceListRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="filters" type="typens:filters" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderInvoiceListResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:salesOrderInvoiceEntityArray" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderInvoiceInfoRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="invoiceIncrementId" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderInvoiceInfoResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:salesOrderInvoiceEntity" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderInvoiceCreateRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="invoiceIncrementId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="itemsQty" type="typens:orderItemIdQtyArray" /> - <xsd:element minOccurs="0" maxOccurs="1" name="comment" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="email" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="includeComment" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderInvoiceCreateResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderInvoiceAddCommentRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="invoiceIncrementId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="comment" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="email" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="includeComment" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderInvoiceAddCommentResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderInvoiceCaptureRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="invoiceIncrementId" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderInvoiceCaptureResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderInvoiceVoidRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="invoiceIncrementId" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderInvoiceVoidResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderInvoiceCancelRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="invoiceIncrementId" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderInvoiceCancelResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderCreditmemoListRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="filters" type="typens:filters" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderCreditmemoListResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:salesOrderCreditmemoEntityArray" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderCreditmemoInfoRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="creditmemoIncrementId" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderCreditmemoInfoResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:salesOrderCreditmemoEntity" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderCreditmemoCreateRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="creditmemoIncrementId" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="creditmemoData" type="typens:salesOrderCreditmemoData" /> - <xsd:element minOccurs="0" maxOccurs="1" name="comment" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="notifyCustomer" type="xsd:int" /> - <xsd:element minOccurs="0" maxOccurs="1" name="includeComment" type="xsd:int" /> - <xsd:element minOccurs="0" maxOccurs="1" name="refundToStoreCreditAmount" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderCreditmemoCreateResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderCreditmemoAddCommentRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="creditmemoIncrementId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="comment" type="xsd:string" /> - <xsd:element minOccurs="0" maxOccurs="1" name="notifyCustomer" type="xsd:int" /> - <xsd:element minOccurs="0" maxOccurs="1" name="includeComment" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderCreditmemoAddCommentResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:int" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderCreditmemoCancelRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" /> - <xsd:element minOccurs="1" maxOccurs="1" name="creditmemoIncrementId" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="salesOrderCreditmemoCancelResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element minOccurs="1" maxOccurs="1" name="result" type="xsd:string" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - </xsd:schema> - </wsdl:types> - <wsdl:message name="salesOrderListRequest"> - <wsdl:part name="parameters" element="typens:salesOrderListRequestParam" /> - </wsdl:message> - <wsdl:message name="salesOrderListResponse"> - <wsdl:part name="parameters" element="typens:salesOrderListResponseParam" /> - </wsdl:message> - <wsdl:message name="salesOrderInfoRequest"> - <wsdl:part name="parameters" element="typens:salesOrderInfoRequestParam" /> - </wsdl:message> - <wsdl:message name="salesOrderInfoResponse"> - <wsdl:part name="parameters" element="typens:salesOrderInfoResponseParam" /> - </wsdl:message> - <wsdl:message name="salesOrderAddCommentRequest"> - <wsdl:part name="parameters" element="typens:salesOrderAddCommentRequestParam" /> - </wsdl:message> - <wsdl:message name="salesOrderAddCommentResponse"> - <wsdl:part name="parameters" element="typens:salesOrderAddCommentResponseParam" /> - </wsdl:message> - <wsdl:message name="salesOrderHoldRequest"> - <wsdl:part name="parameters" element="typens:salesOrderHoldRequestParam" /> - </wsdl:message> - <wsdl:message name="salesOrderHoldResponse"> - <wsdl:part name="parameters" element="typens:salesOrderHoldResponseParam" /> - </wsdl:message> - <wsdl:message name="salesOrderUnholdRequest"> - <wsdl:part name="parameters" element="typens:salesOrderUnholdRequestParam" /> - </wsdl:message> - <wsdl:message name="salesOrderUnholdResponse"> - <wsdl:part name="parameters" element="typens:salesOrderUnholdResponseParam" /> - </wsdl:message> - <wsdl:message name="salesOrderCancelRequest"> - <wsdl:part name="parameters" element="typens:salesOrderCancelRequestParam" /> - </wsdl:message> - <wsdl:message name="salesOrderCancelResponse"> - <wsdl:part name="parameters" element="typens:salesOrderCancelResponseParam" /> - </wsdl:message> - <wsdl:message name="salesOrderShipmentListRequest"> - <wsdl:part name="parameters" element="typens:salesOrderShipmentListRequestParam" /> - </wsdl:message> - <wsdl:message name="salesOrderShipmentListResponse"> - <wsdl:part name="parameters" element="typens:salesOrderShipmentListResponseParam" /> - </wsdl:message> - <wsdl:message name="salesOrderShipmentInfoRequest"> - <wsdl:part name="parameters" element="typens:salesOrderShipmentInfoRequestParam" /> - </wsdl:message> - <wsdl:message name="salesOrderShipmentInfoResponse"> - <wsdl:part name="parameters" element="typens:salesOrderShipmentInfoResponseParam" /> - </wsdl:message> - <wsdl:message name="salesOrderShipmentCreateRequest"> - <wsdl:part name="parameters" element="typens:salesOrderShipmentCreateRequestParam" /> - </wsdl:message> - <wsdl:message name="salesOrderShipmentCreateResponse"> - <wsdl:part name="parameters" element="typens:salesOrderShipmentCreateResponseParam" /> - </wsdl:message> - <wsdl:message name="salesOrderShipmentAddCommentRequest"> - <wsdl:part name="parameters" element="typens:salesOrderShipmentAddCommentRequestParam" /> - </wsdl:message> - <wsdl:message name="salesOrderShipmentAddCommentResponse"> - <wsdl:part name="parameters" element="typens:salesOrderShipmentAddCommentResponseParam" /> - </wsdl:message> - <wsdl:message name="salesOrderShipmentAddTrackRequest"> - <wsdl:part name="parameters" element="typens:salesOrderShipmentAddTrackRequestParam" /> - </wsdl:message> - <wsdl:message name="salesOrderShipmentAddTrackResponse"> - <wsdl:part name="parameters" element="typens:salesOrderShipmentAddTrackResponseParam" /> - </wsdl:message> - <wsdl:message name="salesOrderShipmentRemoveTrackRequest"> - <wsdl:part name="parameters" element="typens:salesOrderShipmentRemoveTrackRequestParam" /> - </wsdl:message> - <wsdl:message name="salesOrderShipmentRemoveTrackResponse"> - <wsdl:part name="parameters" element="typens:salesOrderShipmentRemoveTrackResponseParam" /> - </wsdl:message> - <wsdl:message name="salesOrderShipmentSendInfoRequest"> - <wsdl:part name="parameters" element="typens:salesOrderShipmentSendInfoRequestParam" /> - </wsdl:message> - <wsdl:message name="salesOrderShipmentSendInfoResponse"> - <wsdl:part name="parameters" element="typens:salesOrderShipmentSendInfoResponseParam" /> - </wsdl:message> - <wsdl:message name="salesOrderShipmentGetCarriersRequest"> - <wsdl:part name="parameters" element="typens:salesOrderShipmentGetCarriersRequestParam" /> - </wsdl:message> - <wsdl:message name="salesOrderShipmentGetCarriersResponse"> - <wsdl:part name="parameters" element="typens:salesOrderShipmentGetCarriersResponseParam" /> - </wsdl:message> - <wsdl:message name="salesOrderInvoiceListRequest"> - <wsdl:part name="parameters" element="typens:salesOrderInvoiceListRequestParam" /> - </wsdl:message> - <wsdl:message name="salesOrderInvoiceListResponse"> - <wsdl:part name="parameters" element="typens:salesOrderInvoiceListResponseParam" /> - </wsdl:message> - <wsdl:message name="salesOrderInvoiceInfoRequest"> - <wsdl:part name="parameters" element="typens:salesOrderInvoiceInfoRequestParam" /> - </wsdl:message> - <wsdl:message name="salesOrderInvoiceInfoResponse"> - <wsdl:part name="parameters" element="typens:salesOrderInvoiceInfoResponseParam" /> - </wsdl:message> - <wsdl:message name="salesOrderInvoiceCreateRequest"> - <wsdl:part name="parameters" element="typens:salesOrderInvoiceCreateRequestParam" /> - </wsdl:message> - <wsdl:message name="salesOrderInvoiceCreateResponse"> - <wsdl:part name="parameters" element="typens:salesOrderInvoiceCreateResponseParam" /> - </wsdl:message> - <wsdl:message name="salesOrderInvoiceAddCommentRequest"> - <wsdl:part name="parameters" element="typens:salesOrderInvoiceAddCommentRequestParam" /> - </wsdl:message> - <wsdl:message name="salesOrderInvoiceAddCommentResponse"> - <wsdl:part name="parameters" element="typens:salesOrderInvoiceAddCommentResponseParam" /> - </wsdl:message> - <wsdl:message name="salesOrderInvoiceCaptureRequest"> - <wsdl:part name="parameters" element="typens:salesOrderInvoiceCaptureRequestParam" /> - </wsdl:message> - <wsdl:message name="salesOrderInvoiceCaptureResponse"> - <wsdl:part name="parameters" element="typens:salesOrderInvoiceCaptureResponseParam" /> - </wsdl:message> - <wsdl:message name="salesOrderInvoiceVoidRequest"> - <wsdl:part name="parameters" element="typens:salesOrderInvoiceVoidRequestParam" /> - </wsdl:message> - <wsdl:message name="salesOrderInvoiceVoidResponse"> - <wsdl:part name="parameters" element="typens:salesOrderInvoiceVoidResponseParam" /> - </wsdl:message> - <wsdl:message name="salesOrderInvoiceCancelRequest"> - <wsdl:part name="parameters" element="typens:salesOrderInvoiceCancelRequestParam" /> - </wsdl:message> - <wsdl:message name="salesOrderInvoiceCancelResponse"> - <wsdl:part name="parameters" element="typens:salesOrderInvoiceCancelResponseParam" /> - </wsdl:message> - <wsdl:message name="salesOrderCreditmemoListRequest"> - <wsdl:part name="parameters" element="typens:salesOrderCreditmemoListRequestParam" /> - </wsdl:message> - <wsdl:message name="salesOrderCreditmemoListResponse"> - <wsdl:part name="parameters" element="typens:salesOrderCreditmemoListResponseParam" /> - </wsdl:message> - <wsdl:message name="salesOrderCreditmemoInfoRequest"> - <wsdl:part name="parameters" element="typens:salesOrderCreditmemoInfoRequestParam" /> - </wsdl:message> - <wsdl:message name="salesOrderCreditmemoInfoResponse"> - <wsdl:part name="parameters" element="typens:salesOrderCreditmemoInfoResponseParam" /> - </wsdl:message> - <wsdl:message name="salesOrderCreditmemoCreateRequest"> - <wsdl:part name="parameters" element="typens:salesOrderCreditmemoCreateRequestParam" /> - </wsdl:message> - <wsdl:message name="salesOrderCreditmemoCreateResponse"> - <wsdl:part name="parameters" element="typens:salesOrderCreditmemoCreateResponseParam" /> - </wsdl:message> - <wsdl:message name="salesOrderCreditmemoAddCommentRequest"> - <wsdl:part name="parameters" element="typens:salesOrderCreditmemoAddCommentRequestParam" /> - </wsdl:message> - <wsdl:message name="salesOrderCreditmemoAddCommentResponse"> - <wsdl:part name="parameters" element="typens:salesOrderCreditmemoAddCommentResponseParam" /> - </wsdl:message> - <wsdl:message name="salesOrderCreditmemoCancelRequest"> - <wsdl:part name="parameters" element="typens:salesOrderCreditmemoCancelRequestParam" /> - </wsdl:message> - <wsdl:message name="salesOrderCreditmemoCancelResponse"> - <wsdl:part name="parameters" element="typens:salesOrderCreditmemoCancelResponseParam" /> - </wsdl:message> - <wsdl:portType name="{{var wsdl.handler}}PortType"> - <wsdl:operation name="salesOrderList"> - <wsdl:documentation>Retrieve list of orders by filters</wsdl:documentation> - <wsdl:input message="typens:salesOrderListRequest" /> - <wsdl:output message="typens:salesOrderListResponse" /> - </wsdl:operation> - <wsdl:operation name="salesOrderInfo"> - <wsdl:documentation>Retrieve order information</wsdl:documentation> - <wsdl:input message="typens:salesOrderInfoRequest" /> - <wsdl:output message="typens:salesOrderInfoResponse" /> - </wsdl:operation> - <wsdl:operation name="salesOrderAddComment"> - <wsdl:documentation>Add comment to order</wsdl:documentation> - <wsdl:input message="typens:salesOrderAddCommentRequest" /> - <wsdl:output message="typens:salesOrderAddCommentResponse" /> - </wsdl:operation> - <wsdl:operation name="salesOrderHold"> - <wsdl:documentation>Hold order</wsdl:documentation> - <wsdl:input message="typens:salesOrderHoldRequest" /> - <wsdl:output message="typens:salesOrderHoldResponse" /> - </wsdl:operation> - <wsdl:operation name="salesOrderUnhold"> - <wsdl:documentation>Unhold order</wsdl:documentation> - <wsdl:input message="typens:salesOrderUnholdRequest" /> - <wsdl:output message="typens:salesOrderUnholdResponse" /> - </wsdl:operation> - <wsdl:operation name="salesOrderCancel"> - <wsdl:documentation>Cancel order</wsdl:documentation> - <wsdl:input message="typens:salesOrderCancelRequest" /> - <wsdl:output message="typens:salesOrderCancelResponse" /> - </wsdl:operation> - <wsdl:operation name="salesOrderShipmentList"> - <wsdl:documentation>Retrieve list of shipments by filters</wsdl:documentation> - <wsdl:input message="typens:salesOrderShipmentListRequest" /> - <wsdl:output message="typens:salesOrderShipmentListResponse" /> - </wsdl:operation> - <wsdl:operation name="salesOrderShipmentInfo"> - <wsdl:documentation>Retrieve shipment information</wsdl:documentation> - <wsdl:input message="typens:salesOrderShipmentInfoRequest" /> - <wsdl:output message="typens:salesOrderShipmentInfoResponse" /> - </wsdl:operation> - <wsdl:operation name="salesOrderShipmentCreate"> - <wsdl:documentation>Create new shipment for order</wsdl:documentation> - <wsdl:input message="typens:salesOrderShipmentCreateRequest" /> - <wsdl:output message="typens:salesOrderShipmentCreateResponse" /> - </wsdl:operation> - <wsdl:operation name="salesOrderShipmentAddComment"> - <wsdl:documentation>Add new comment to shipment</wsdl:documentation> - <wsdl:input message="typens:salesOrderShipmentAddCommentRequest" /> - <wsdl:output message="typens:salesOrderShipmentAddCommentResponse" /> - </wsdl:operation> - <wsdl:operation name="salesOrderShipmentAddTrack"> - <wsdl:documentation>Add new tracking number</wsdl:documentation> - <wsdl:input message="typens:salesOrderShipmentAddTrackRequest" /> - <wsdl:output message="typens:salesOrderShipmentAddTrackResponse" /> - </wsdl:operation> - <wsdl:operation name="salesOrderShipmentRemoveTrack"> - <wsdl:documentation>Remove tracking number</wsdl:documentation> - <wsdl:input message="typens:salesOrderShipmentRemoveTrackRequest" /> - <wsdl:output message="typens:salesOrderShipmentRemoveTrackResponse" /> - </wsdl:operation> - <wsdl:operation name="salesOrderShipmentSendInfo"> - <wsdl:documentation>Send shipment info</wsdl:documentation> - <wsdl:input message="typens:salesOrderShipmentSendInfoRequest" /> - <wsdl:output message="typens:salesOrderShipmentSendInfoResponse" /> - </wsdl:operation> - <wsdl:operation name="salesOrderShipmentGetCarriers"> - <wsdl:documentation>Retrieve list of allowed carriers for order</wsdl:documentation> - <wsdl:input message="typens:salesOrderShipmentGetCarriersRequest" /> - <wsdl:output message="typens:salesOrderShipmentGetCarriersResponse" /> - </wsdl:operation> - <wsdl:operation name="salesOrderInvoiceList"> - <wsdl:documentation>Retrieve list of invoices by filters</wsdl:documentation> - <wsdl:input message="typens:salesOrderInvoiceListRequest" /> - <wsdl:output message="typens:salesOrderInvoiceListResponse" /> - </wsdl:operation> - <wsdl:operation name="salesOrderInvoiceInfo"> - <wsdl:documentation>Retrieve invoice information</wsdl:documentation> - <wsdl:input message="typens:salesOrderInvoiceInfoRequest" /> - <wsdl:output message="typens:salesOrderInvoiceInfoResponse" /> - </wsdl:operation> - <wsdl:operation name="salesOrderInvoiceCreate"> - <wsdl:documentation>Create new invoice for order</wsdl:documentation> - <wsdl:input message="typens:salesOrderInvoiceCreateRequest" /> - <wsdl:output message="typens:salesOrderInvoiceCreateResponse" /> - </wsdl:operation> - <wsdl:operation name="salesOrderInvoiceAddComment"> - <wsdl:documentation>Add new comment to shipment</wsdl:documentation> - <wsdl:input message="typens:salesOrderInvoiceAddCommentRequest" /> - <wsdl:output message="typens:salesOrderInvoiceAddCommentResponse" /> - </wsdl:operation> - <wsdl:operation name="salesOrderInvoiceCapture"> - <wsdl:documentation>Capture invoice</wsdl:documentation> - <wsdl:input message="typens:salesOrderInvoiceCaptureRequest" /> - <wsdl:output message="typens:salesOrderInvoiceCaptureResponse" /> - </wsdl:operation> - <wsdl:operation name="salesOrderInvoiceVoid"> - <wsdl:documentation>Void invoice</wsdl:documentation> - <wsdl:input message="typens:salesOrderInvoiceVoidRequest" /> - <wsdl:output message="typens:salesOrderInvoiceVoidResponse" /> - </wsdl:operation> - <wsdl:operation name="salesOrderInvoiceCancel"> - <wsdl:documentation>Cancel invoice</wsdl:documentation> - <wsdl:input message="typens:salesOrderInvoiceCancelRequest" /> - <wsdl:output message="typens:salesOrderInvoiceCancelResponse" /> - </wsdl:operation> - <wsdl:operation name="salesOrderCreditmemoList"> - <wsdl:documentation>Retrieve list of creditmemos by filters</wsdl:documentation> - <wsdl:input message="typens:salesOrderCreditmemoListRequest" /> - <wsdl:output message="typens:salesOrderCreditmemoListResponse" /> - </wsdl:operation> - <wsdl:operation name="salesOrderCreditmemoInfo"> - <wsdl:documentation>Retrieve creditmemo information</wsdl:documentation> - <wsdl:input message="typens:salesOrderCreditmemoInfoRequest" /> - <wsdl:output message="typens:salesOrderCreditmemoInfoResponse" /> - </wsdl:operation> - <wsdl:operation name="salesOrderCreditmemoCreate"> - <wsdl:documentation>Create new creditmemo for order</wsdl:documentation> - <wsdl:input message="typens:salesOrderCreditmemoCreateRequest" /> - <wsdl:output message="typens:salesOrderCreditmemoCreateResponse" /> - </wsdl:operation> - <wsdl:operation name="salesOrderCreditmemoAddComment"> - <wsdl:documentation>Add new comment to creditmemo</wsdl:documentation> - <wsdl:input message="typens:salesOrderCreditmemoAddCommentRequest" /> - <wsdl:output message="typens:salesOrderCreditmemoAddCommentResponse" /> - </wsdl:operation> - <wsdl:operation name="salesOrderCreditmemoCancel"> - <wsdl:documentation>Cancel creditmemo</wsdl:documentation> - <wsdl:input message="typens:salesOrderCreditmemoCancelRequest" /> - <wsdl:output message="typens:salesOrderCreditmemoCancelResponse" /> - </wsdl:operation> - </wsdl:portType> - <wsdl:binding name="{{var wsdl.handler}}Binding" type="typens:{{var wsdl.handler}}PortType"> - <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" /> - <wsdl:operation name="salesOrderList"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="salesOrderInfo"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="salesOrderAddComment"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="salesOrderHold"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="salesOrderUnhold"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="salesOrderCancel"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="salesOrderShipmentList"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="salesOrderShipmentInfo"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="salesOrderShipmentCreate"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="salesOrderShipmentAddComment"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="salesOrderShipmentAddTrack"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="salesOrderShipmentRemoveTrack"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="salesOrderShipmentSendInfo"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="salesOrderShipmentGetCarriers"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="salesOrderInvoiceList"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="salesOrderInvoiceInfo"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="salesOrderInvoiceCreate"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="salesOrderInvoiceAddComment"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="salesOrderInvoiceCapture"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="salesOrderInvoiceVoid"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="salesOrderInvoiceCancel"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="salesOrderCreditmemoList"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="salesOrderCreditmemoInfo"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="salesOrderCreditmemoCreate"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="salesOrderCreditmemoAddComment"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - <wsdl:operation name="salesOrderCreditmemoCancel"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - </wsdl:binding> - <wsdl:service name="{{var wsdl.name}}Service"> - <wsdl:port name="{{var wsdl.handler}}Port" binding="typens:{{var wsdl.handler}}Binding"> - <soap:address location="{{var wsdl.url}}" /> - </wsdl:port> - </wsdl:service> -</wsdl:definitions> diff --git a/app/code/core/Mage/SalesRule/Model/Resource/Coupon/Collection.php b/app/code/core/Mage/SalesRule/Model/Resource/Coupon/Collection.php index fc5e167431db0b961ff42477d7ac9c508d6b1366..e579ef2f9fa8d2f59f321d8133414cd7c413df28 100755 --- a/app/code/core/Mage/SalesRule/Model/Resource/Coupon/Collection.php +++ b/app/code/core/Mage/SalesRule/Model/Resource/Coupon/Collection.php @@ -97,9 +97,9 @@ class Mage_SalesRule_Model_Resource_Coupon_Collection extends Mage_Core_Model_Re public function addIsUsedFilterCallback($collection, $column) { $filterValue = $column->getFilter()->getCondition(); - $collection->addFieldToFilter( - $this->getConnection()->getCheckSql('main_table.times_used > 0', 1, 0), - array('eq' => $filterValue) - ); + + $expression = $this->getConnection()->getCheckSql('main_table.times_used > 0', 1, 0); + $conditionSql = $this->_getConditionSql($expression, $filterValue); + $collection->getSelect()->where($conditionSql); } } diff --git a/app/code/core/Mage/Tag/Model/Api.php b/app/code/core/Mage/Tag/Model/Api.php deleted file mode 100644 index 1080659bd658cebcbaa3de2fd9f10ef0f5aba52d..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Tag/Model/Api.php +++ /dev/null @@ -1,245 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Tag - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Product Tag API - * - * @category Mage - * @package Mage_Tag - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Tag_Model_Api extends Mage_Catalog_Model_Api_Resource -{ - /** - * Retrieve list of tags for specified product - * - * @param int $productId - * @param string|int $store - * @return array - */ - public function items($productId, $store = null) - { - $result = array(); - // fields list to return - $fieldsForResult = array('tag_id', 'name'); - - /** @var $product Mage_Catalog_Model_Product */ - $product = Mage::getModel('Mage_Catalog_Model_Product')->load($productId); - if (!$product->getId()) { - $this->_fault('product_not_exists'); - } - - /** @var $tags Mage_Tag_Model_Resource_Tag_Collection */ - $tags = Mage::getModel('Mage_Tag_Model_Tag')->getCollection()->joinRel()->addProductFilter($productId); - if ($store) { - $tags->addStoreFilter($this->_getStoreId($store)); - } - - /** @var $tag Mage_Tag_Model_Tag */ - foreach ($tags as $tag) { - $result[$tag->getId()] = $tag->toArray($fieldsForResult); - } - - return $result; - } - - /** - * Retrieve tag info as array('name'-> .., 'status' => .., - * 'base_popularity' => .., 'products' => array($productId => $popularity, ...)) - * - * @param int $tagId - * @param string|int $store - * @return array - */ - public function info($tagId, $store) - { - $result = array(); - $storeId = $this->_getStoreId($store); - /** @var $tag Mage_Tag_Model_Tag */ - $tag = Mage::getModel('Mage_Tag_Model_Tag')->setStoreId($storeId)->setAddBasePopularity()->load($tagId); - if (!$tag->getId()) { - $this->_fault('tag_not_exists'); - } - $result['status'] = $tag->getStatus(); - $result['name'] = $tag->getName(); - $result['base_popularity'] = (is_numeric($tag->getBasePopularity())) ? $tag->getBasePopularity() : 0; - // retrieve array($productId => $popularity, ...) - $result['products'] = array(); - $relatedProductsCollection = $tag->getEntityCollection()->addTagFilter($tagId) - ->addStoreFilter($storeId)->addPopularity($tagId); - foreach ($relatedProductsCollection as $product) { - $result['products'][$product->getId()] = $product->getPopularity(); - } - - return $result; - } - - /** - * Add tag(s) to product. - * Return array of added/updated tags as array($tagName => $tagId, ...) - * - * @param array $data - * @return array - */ - public function add($data) - { - $data = $this->_prepareDataForAdd($data); - /** @var $product Mage_Catalog_Model_Product */ - $product = Mage::getModel('Mage_Catalog_Model_Product')->load($data['product_id']); - if (!$product->getId()) { - $this->_fault('product_not_exists'); - } - /** @var $customer Mage_Customer_Model_Customer */ - $customer = Mage::getModel('Mage_Customer_Model_Customer')->load($data['customer_id']); - if (!$customer->getId()) { - $this->_fault('customer_not_exists'); - } - $storeId = $this->_getStoreId($data['store']); - - try { - /** @var $tag Mage_Tag_Model_Tag */ - $tag = Mage::getModel('Mage_Tag_Model_Tag'); - $tagHelper = Mage::helper('Mage_Tag_Helper_Data'); - $tagNamesArr = $tagHelper->cleanTags($tagHelper->extractTags($data['tag'])); - foreach ($tagNamesArr as $tagName) { - // unset previously added tag data - $tag->unsetData(); - $tag->loadByName($tagName); - if (!$tag->getId()) { - $tag->setName($tagName) - ->setFirstCustomerId($customer->getId()) - ->setFirstStoreId($storeId) - ->setStatus($tag->getPendingStatus()) - ->save(); - } - $tag->saveRelation($product->getId(), $customer->getId(), $storeId); - $result[$tagName] = $tag->getId(); - } - } catch (Mage_Core_Exception $e) { - $this->_fault('save_error', $e->getMessage()); - } - - return $result; - } - - /** - * Change existing tag information - * - * @param int $tagId - * @param array $data - * @param string|int $store - * @return bool - */ - public function update($tagId, $data, $store) - { - $data = $this->_prepareDataForUpdate($data); - $storeId = $this->_getStoreId($store); - /** @var $tag Mage_Tag_Model_Tag */ - $tag = Mage::getModel('Mage_Tag_Model_Tag')->setStoreId($storeId)->setAddBasePopularity()->load($tagId); - if (!$tag->getId()) { - $this->_fault('tag_not_exists'); - } - - // store should be set for 'base_popularity' to be saved in Mage_Tag_Model_Resource_Tag::_afterSave() - $tag->setStore($storeId); - if (isset($data['base_popularity'])) { - $tag->setBasePopularity($data['base_popularity']); - } - if (isset($data['name'])) { - $tag->setName(trim($data['name'])); - } - if (isset($data['status'])) { - // validate tag status - if (!in_array($data['status'], array( - $tag->getApprovedStatus(), $tag->getPendingStatus(), $tag->getDisabledStatus()))) { - $this->_fault('invalid_data'); - } - $tag->setStatus($data['status']); - } - - try { - $tag->save(); - } catch (Mage_Core_Exception $e) { - $this->_fault('save_error', $e->getMessage()); - } - - return true; - } - - /** - * Remove existing tag - * - * @param int $tagId - * @return bool - */ - public function remove($tagId) - { - /** @var $tag Mage_Tag_Model_Tag */ - $tag = Mage::getModel('Mage_Tag_Model_Tag')->load($tagId); - if (!$tag->getId()) { - $this->_fault('tag_not_exists'); - } - try { - $tag->delete(); - } catch (Mage_Core_Exception $e) { - $this->_fault('remove_error', $e->getMessage()); - } - - return true; - } - - /** - * Check data before add - * - * @param array $data - * @return array - */ - protected function _prepareDataForAdd($data) - { - if (!isset($data['product_id']) or !isset($data['tag']) - or !isset($data['customer_id']) or !isset($data['store'])) { - $this->_fault('invalid_data'); - } - - return $data; - } - - /** - * Check data before update - * - * @param $data - * @return - */ - protected function _prepareDataForUpdate($data) - { - // $data should contain at least one field to change - if ( !(isset($data['name']) or isset($data['status']) or isset($data['base_popularity']))) { - $this->_fault('invalid_data'); - } - - return $data; - } -} diff --git a/app/code/core/Mage/Tag/Model/Api/V2.php b/app/code/core/Mage/Tag/Model/Api/V2.php deleted file mode 100644 index 720a18f2507aa9e724c816e27def020e05ba6ba2..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Tag/Model/Api/V2.php +++ /dev/null @@ -1,109 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Tag - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Product Tag API - * - * @category Mage - * @package Mage_Tag - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Tag_Model_Api_V2 extends Mage_Tag_Model_Api -{ - /** - * Retrieve list of tags for specified product as array of objects - * - * @param int $productId - * @param string|int $store - * @return array - */ - public function items($productId, $store = null) - { - $result = parent::items($productId, $store); - foreach ($result as $key => $tag) { - $result[$key] = Mage::helper('Mage_Api_Helper_Data')->wsiArrayPacker($tag); - } - return array_values($result); - } - - /** - * Add tag(s) to product. - * Return array of objects - * - * @param array $data - * @return array - */ - public function add($data) - { - $result = array(); - foreach (parent::add($data) as $key => $value) { - $result[] = array('key' => $key, 'value' => $value); - } - - return $result; - } - - /** - * Retrieve tag info as object - * - * @param int $tagId - * @param string|int $store - * @return object - */ - public function info($tagId, $store) - { - $result = parent::info($tagId, $store); - $result = Mage::helper('Mage_Api_Helper_Data')->wsiArrayPacker($result); - foreach ($result->products as $key => $value) { - $result->products[$key] = array('key' => $key, 'value' => $value); - } - return $result; - } - - /** - * Convert data from object to array before add - * - * @param object $data - * @return array - */ - protected function _prepareDataForAdd($data) - { - Mage::helper('Mage_Api_Helper_Data')->toArray($data); - return parent::_prepareDataForAdd($data); - } - - /** - * Convert data from object to array before update - * - * @param object $data - * @return array - */ - protected function _prepareDataForUpdate($data) - { - Mage::helper('Mage_Api_Helper_Data')->toArray($data); - return parent::_prepareDataForUpdate($data); - } -} diff --git a/app/code/core/Mage/Tag/etc/api.xml b/app/code/core/Mage/Tag/etc/api.xml deleted file mode 100644 index d883b3d26d75c468629c62e333b0ab9ce806048f..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Tag/etc/api.xml +++ /dev/null @@ -1,138 +0,0 @@ -<?xml version="1.0"?> -<!-- -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Academic Free License (AFL 3.0) - * that is bundled with this package in the file LICENSE_AFL.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/afl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Tag - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) - */ ---> -<config> - <api> - <resources> - <catalog_product_tag translate="title" module="Mage_Tag"> - <title>Product Tag API</title> - <model>Mage_Tag_Model_Api</model> - <acl>catalog/product/tag</acl> - <methods> - <list translate="title" module="Mage_Tag"> - <title>Retrieve list of tags by product</title> - <method>items</method> - <acl>catalog/product/tag/list</acl> - </list> - <info translate="title" module="Mage_Tag"> - <title>Retrieve product tag info</title> - <acl>catalog/product/tag/info</acl> - </info> - <add translate="title" module="Mage_Tag"> - <title>Add tag(s) to product</title> - <acl>catalog/product/tag/add</acl> - </add> - <update translate="title" module="Mage_Tag"> - <title>Update product tag</title> - <acl>catalog/product/tag/update</acl> - </update> - <remove translate="title" module="Mage_Tag"> - <title>Remove product tag</title> - <acl>catalog/product/tag/remove</acl> - </remove> - </methods> - <faults module="Mage_Tag"> - <store_not_exists> - <code>101</code> - <message>Requested store does not exist.</message> - </store_not_exists> - <product_not_exists> - <code>102</code> - <message>Requested product does not exist.</message> - </product_not_exists> - <customer_not_exists> - <code>103</code> - <message>Requested customer does not exist.</message> - </customer_not_exists> - <tag_not_exists> - <code>104</code> - <message>Requested tag does not exist.</message> - </tag_not_exists> - <invalid_data> - <code>105</code> - <message>Provided data is invalid.</message> - </invalid_data> - <save_error> - <code>106</code> - <message>Error while saving tag. Details in error message.</message> - </save_error> - <remove_error> - <code>107</code> - <message>Error while removing tag. Details in error message.</message> - </remove_error> - </faults> - </catalog_product_tag> - </resources> - <resources_alias> - <product_tag>catalog_product_tag</product_tag> - </resources_alias> - <v2> - <resources_function_prefix> - <product_tag>catalogProductTag</product_tag> - </resources_function_prefix> - </v2> - <rest> - <mapping> - <product_tag> - <post> - <method>add</method> - </post> - <delete> - <method>remove</method> - </delete> - </product_tag> - </mapping> - </rest> - <acl> - <resources> - <catalog> - <product> - <tag translate="title" module="Mage_Tag"> - <title>Tag</title> - <sort_order>103</sort_order> - <list translate="title" module="Mage_Tag"> - <title>List</title> - </list> - <info translate="title" module="Mage_Tag"> - <title>Info</title> - </info> - <add translate="title" module="Mage_Tag"> - <title>Add</title> - </add> - <update translate="title" module="Mage_Tag"> - <title>Update</title> - </update> - <remove translate="title" module="Mage_Tag"> - <title>Remove</title> - </remove> - </tag> - </product> - </catalog> - </resources> - </acl> - </api> -</config> diff --git a/app/code/core/Mage/Tag/etc/wsdl.xml b/app/code/core/Mage/Tag/etc/wsdl.xml deleted file mode 100644 index c7d114736c7e619cd3fced5dec2f2ec49caabb45..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Tag/etc/wsdl.xml +++ /dev/null @@ -1,189 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<definitions xmlns:typens="urn:{{var wsdl.name}}" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" - xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns="http://schemas.xmlsoap.org/wsdl/" - name="{{var wsdl.name}}" targetNamespace="urn:{{var wsdl.name}}"> - <types> - <schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:Magento"> - <import namespace="http://schemas.xmlsoap.org/soap/encoding/" schemaLocation="http://schemas.xmlsoap.org/soap/encoding/" /> - <complexType name="catalogProductTagListEntity"> - <all> - <element name="tag_id" type="xsd:string" minOccurs="1" /> - <element name="name" type="xsd:string" minOccurs="1" /> - </all> - </complexType> - <complexType name="catalogProductTagListEntityArray"> - <complexContent> - <restriction base="soapenc:Array"> - <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:catalogProductTagListEntity[]" /> - </restriction> - </complexContent> - </complexType> - <complexType name="catalogProductTagAddEntity"> - <all> - <element name="tag" type="xsd:string" minOccurs="1" /> - <element name="product_id" type="xsd:string" minOccurs="1" /> - <element name="customer_id" type="xsd:string" minOccurs="1" /> - <element name="store" type="xsd:string" minOccurs="1" /> - </all> - </complexType> - <complexType name="catalogProductTagUpdateEntity"> - <all> - <element name="name" type="xsd:string" minOccurs="0" /> - <element name="status" type="xsd:string" minOccurs="0" /> - <element name="base_popularity" type="xsd:string" minOccurs="0" /> - </all> - </complexType> - <complexType name="catalogProductTagInfoEntity"> - <all> - <element name="name" type="xsd:string" minOccurs="1" /> - <element name="status" type="xsd:string" minOccurs="1" /> - <element name="base_popularity" type="xsd:string" minOccurs="1" /> - <element name="products" type="typens:associativeArray" minOccurs="1" /> - </all> - </complexType> - </schema> - </types> - - <message name="catalogProductTagListRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="productId" type="xsd:string" /> - <part name="store" type="xsd:string" /> - </message> - <message name="catalogProductTagListResponse"> - <part name="result" type="typens:catalogProductTagListEntityArray" /> - </message> - <message name="catalogProductTagInfoRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="tagId" type="xsd:string" /> - <part name="store" type="xsd:string" /> - </message> - <message name="catalogProductTagInfoResponse"> - <part name="result" type="typens:catalogProductTagInfoEntity" /> - </message> - <message name="catalogProductTagAddRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="data" type="typens:catalogProductTagAddEntity" /> - </message> - <message name="catalogProductTagAddResponse"> - <part name="result" type="typens:associativeArray" /> - </message> - <message name="catalogProductTagUpdateRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="tagId" type="xsd:string" /> - <part name="data" type="typens:catalogProductTagUpdateEntity" /> - <part name="store" type="xsd:string" /> - </message> - <message name="catalogProductTagUpdateResponse"> - <part name="result" type="xsd:boolean" /> - </message> - <message name="catalogProductTagRemoveRequest"> - <part name="sessionId" type="xsd:string" /> - <part name="tagId" type="xsd:string" /> - </message> - <message name="catalogProductTagRemoveResponse"> - <part name="result" type="xsd:boolean" /> - </message> - - <portType name="{{var wsdl.handler}}PortType"> - <operation name="catalogProductTagList"> - <documentation>Retrieve list of tags by product</documentation> - <input message="typens:catalogProductTagListRequest" /> - <output message="typens:catalogProductTagListResponse" /> - </operation> - </portType> - <portType name="{{var wsdl.handler}}PortType"> - <operation name="catalogProductTagInfo"> - <documentation>Retrieve product tag info</documentation> - <input message="typens:catalogProductTagInfoRequest" /> - <output message="typens:catalogProductTagInfoResponse" /> - </operation> - </portType> - <portType name="{{var wsdl.handler}}PortType"> - <operation name="catalogProductTagAdd"> - <documentation>Add tag(s) to product</documentation> - <input message="typens:catalogProductTagAddRequest" /> - <output message="typens:catalogProductTagAddResponse" /> - </operation> - </portType> - <portType name="{{var wsdl.handler}}PortType"> - <operation name="catalogProductTagUpdate"> - <documentation>Update product tag</documentation> - <input message="typens:catalogProductTagUpdateRequest" /> - <output message="typens:catalogProductTagUpdateResponse" /> - </operation> - </portType> - <portType name="{{var wsdl.handler}}PortType"> - <operation name="catalogProductTagRemove"> - <documentation>Remove product tag</documentation> - <input message="typens:catalogProductTagRemoveRequest" /> - <output message="typens:catalogProductTagRemoveResponse" /> - </operation> - </portType> - - <binding name="{{var wsdl.handler}}Binding" type="typens:{{var wsdl.handler}}PortType"> - <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" /> - <operation name="catalogProductTagList"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - </binding> - <binding name="{{var wsdl.handler}}Binding" type="typens:{{var wsdl.handler}}PortType"> - <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" /> - <operation name="catalogProductTagInfo"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - </binding> - <binding name="{{var wsdl.handler}}Binding" type="typens:{{var wsdl.handler}}PortType"> - <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" /> - <operation name="catalogProductTagAdd"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - </binding> - <binding name="{{var wsdl.handler}}Binding" type="typens:{{var wsdl.handler}}PortType"> - <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" /> - <operation name="catalogProductTagUpdate"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - </binding> - <binding name="{{var wsdl.handler}}Binding" type="typens:{{var wsdl.handler}}PortType"> - <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" /> - <operation name="catalogProductTagRemove"> - <soap:operation soapAction="urn:{{var wsdl.handler}}Action" /> - <input> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </input> - <output> - <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> - </output> - </operation> - </binding> - - <service name="{{var wsdl.name}}Service"> - <port name="{{var wsdl.handler}}Port" binding="typens:{{var wsdl.handler}}Binding"> - <soap:address location="{{var wsdl.url}}" /> - </port> - </service> -</definitions> diff --git a/app/code/core/Mage/Tag/etc/wsi.xml b/app/code/core/Mage/Tag/etc/wsi.xml deleted file mode 100644 index 615e2a445837df5510209229f77d988c3c9491e4..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Tag/etc/wsi.xml +++ /dev/null @@ -1,262 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<wsdl:definitions xmlns:typens="urn:{{var wsdl.name}}" - xmlns:xsd="http://www.w3.org/2001/XMLSchema" - xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" - xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" - xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" - name="{{var wsdl.name}}" - targetNamespace="urn:{{var wsdl.name}}"> - - <wsdl:types> - <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:{{var wsdl.name}}"> - <xsd:complexType name="catalogProductTagListEntity"> - <xsd:sequence> - <xsd:element name="tag_id" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="name" type="xsd:string" minOccurs="1" maxOccurs="1" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductTagListEntityArray"> - <xsd:sequence> - <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:catalogProductTagListEntity" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductTagAddEntity"> - <xsd:sequence> - <xsd:element name="tag" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="product_id" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="customer_id" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="store" type="xsd:string" minOccurs="1" maxOccurs="1" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductTagUpdateEntity"> - <xsd:sequence> - <xsd:element name="name" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="status" type="xsd:string" minOccurs="0" maxOccurs="1" /> - <xsd:element name="base_popularity" type="xsd:string" minOccurs="0" maxOccurs="1" /> - </xsd:sequence> - </xsd:complexType> - <xsd:complexType name="catalogProductTagInfoEntity"> - <xsd:sequence> - <xsd:element name="name" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="status" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="base_popularity" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="products" type="typens:associativeArray" minOccurs="1" maxOccurs="1" /> - </xsd:sequence> - </xsd:complexType> - - <xsd:element name="catalogProductTagListRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element name="sessionId" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="productId" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="store" type="xsd:string" minOccurs="1" maxOccurs="1" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductTagListResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element name="result" type="typens:catalogProductTagListEntityArray" minOccurs="1" maxOccurs="1" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductTagInfoRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element name="sessionId" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="tagId" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="store" type="xsd:string" minOccurs="1" maxOccurs="1" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductTagInfoResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element name="result" type="typens:catalogProductTagInfoEntity" minOccurs="1" maxOccurs="1" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductTagAddRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element name="sessionId" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="data" type="typens:catalogProductTagAddEntity" minOccurs="1" maxOccurs="1" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductTagAddResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element name="result" type="typens:associativeArray" minOccurs="1" maxOccurs="1" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductTagUpdateRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element name="sessionId" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="tagId" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="data" type="typens:catalogProductTagUpdateEntity" minOccurs="1" maxOccurs="1" /> - <xsd:element name="store" type="xsd:string" minOccurs="1" maxOccurs="1" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductTagUpdateResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element name="result" type="xsd:int" minOccurs="1" maxOccurs="1" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductTagRemoveRequestParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element name="sessionId" type="xsd:string" minOccurs="1" maxOccurs="1" /> - <xsd:element name="tagId" type="xsd:string" minOccurs="1" maxOccurs="1" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - <xsd:element name="catalogProductTagRemoveResponseParam"> - <xsd:complexType> - <xsd:sequence> - <xsd:element name="result" type="xsd:int" minOccurs="1" maxOccurs="1" /> - </xsd:sequence> - </xsd:complexType> - </xsd:element> - </xsd:schema> - </wsdl:types> - - <wsdl:message name="catalogProductTagListRequest"> - <wsdl:part name="parameters" element="typens:catalogProductTagListRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductTagListResponse"> - <wsdl:part name="parameters" element="typens:catalogProductTagListResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductTagInfoRequest"> - <wsdl:part name="parameters" element="typens:catalogProductTagInfoRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductTagInfoResponse"> - <wsdl:part name="parameters" element="typens:catalogProductTagInfoResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductTagAddRequest"> - <wsdl:part name="parameters" element="typens:catalogProductTagAddRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductTagAddResponse"> - <wsdl:part name="parameters" element="typens:catalogProductTagAddResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductTagUpdateRequest"> - <wsdl:part name="parameters" element="typens:catalogProductTagUpdateRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductTagUpdateResponse"> - <wsdl:part name="parameters" element="typens:catalogProductTagUpdateResponseParam" /> - </wsdl:message> - <wsdl:message name="catalogProductTagRemoveRequest"> - <wsdl:part name="parameters" element="typens:catalogProductTagRemoveRequestParam" /> - </wsdl:message> - <wsdl:message name="catalogProductTagRemoveResponse"> - <wsdl:part name="parameters" element="typens:catalogProductTagRemoveResponseParam" /> - </wsdl:message> - - <wsdl:portType name="{{var wsdl.handler}}PortType"> - <wsdl:operation name="catalogProductTagList"> - <wsdl:documentation>Retrieve list of tags by product</wsdl:documentation> - <wsdl:input message="typens:catalogProductTagListRequest" /> - <wsdl:output message="typens:catalogProductTagListResponse" /> - </wsdl:operation> - </wsdl:portType> - <wsdl:portType name="{{var wsdl.handler}}PortType"> - <wsdl:operation name="catalogProductTagInfo"> - <wsdl:documentation>Retrieve product tag info</wsdl:documentation> - <wsdl:input message="typens:catalogProductTagInfoRequest" /> - <wsdl:output message="typens:catalogProductTagInfoResponse" /> - </wsdl:operation> - </wsdl:portType> - <wsdl:portType name="{{var wsdl.handler}}PortType"> - <wsdl:operation name="catalogProductTagAdd"> - <wsdl:documentation>Add tag(s) to product</wsdl:documentation> - <wsdl:input message="typens:catalogProductTagAddRequest" /> - <wsdl:output message="typens:catalogProductTagAddResponse" /> - </wsdl:operation> - </wsdl:portType> - <wsdl:portType name="{{var wsdl.handler}}PortType"> - <wsdl:operation name="catalogProductTagUpdate"> - <wsdl:documentation>Update product tag</wsdl:documentation> - <wsdl:input message="typens:catalogProductTagUpdateRequest" /> - <wsdl:output message="typens:catalogProductTagUpdateResponse" /> - </wsdl:operation> - </wsdl:portType> - <wsdl:portType name="{{var wsdl.handler}}PortType"> - <wsdl:operation name="catalogProductTagRemove"> - <wsdl:documentation>Remove product tag</wsdl:documentation> - <wsdl:input message="typens:catalogProductTagRemoveRequest" /> - <wsdl:output message="typens:catalogProductTagRemoveResponse" /> - </wsdl:operation> - </wsdl:portType> - - <wsdl:binding name="{{var wsdl.handler}}Binding" type="typens:{{var wsdl.handler}}PortType"> - <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" /> - <wsdl:operation name="catalogProductTagList"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - </wsdl:binding> - <wsdl:binding name="{{var wsdl.handler}}Binding" type="typens:{{var wsdl.handler}}PortType"> - <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" /> - <wsdl:operation name="catalogProductTagInfo"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - </wsdl:binding> - <wsdl:binding name="{{var wsdl.handler}}Binding" type="typens:{{var wsdl.handler}}PortType"> - <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" /> - <wsdl:operation name="catalogProductTagAdd"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - </wsdl:binding> - <wsdl:binding name="{{var wsdl.handler}}Binding" type="typens:{{var wsdl.handler}}PortType"> - <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" /> - <wsdl:operation name="catalogProductTagUpdate"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - </wsdl:binding> - <wsdl:binding name="{{var wsdl.handler}}Binding" type="typens:{{var wsdl.handler}}PortType"> - <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" /> - <wsdl:operation name="catalogProductTagRemove"> - <soap:operation soapAction="" /> - <wsdl:input> - <soap:body use="literal" /> - </wsdl:input> - <wsdl:output> - <soap:body use="literal" /> - </wsdl:output> - </wsdl:operation> - </wsdl:binding> - - <wsdl:service name="{{var wsdl.name}}Service"> - <wsdl:port name="{{var wsdl.handler}}Port" binding="typens:{{var wsdl.handler}}Binding"> - <soap:address location="{{var wsdl.url}}" /> - </wsdl:port> - </wsdl:service> -</wsdl:definitions> diff --git a/app/code/core/Mage/Tax/Model/Resource/Calculation.php b/app/code/core/Mage/Tax/Model/Resource/Calculation.php index 7a331c2f4db3171e25912571e898043c1985ed72..86c5eac1812eef60cadbd2f963f10c7d04d0f3f8 100755 --- a/app/code/core/Mage/Tax/Model/Resource/Calculation.php +++ b/app/code/core/Mage/Tax/Model/Resource/Calculation.php @@ -338,7 +338,16 @@ class Mage_Tax_Model_Resource_Calculation extends Mage_Core_Model_Resource_Db_Ab ->order('tax_postcode ' . Varien_Db_Select::SQL_DESC) ->order('value ' . Varien_Db_Select::SQL_DESC); - $this->_ratesCache[$cacheKey] = $this->_getReadAdapter()->fetchAll($select); + $fetchResult = $this->_getReadAdapter()->fetchAll($select); + $filteredRates = array(); + if ($fetchResult) { + foreach ($fetchResult as $rate) { + if (!isset($filteredRates[$rate['tax_calculation_rate_id']])) { + $filteredRates[$rate['tax_calculation_rate_id']] = $rate; + } + } + } + $this->_ratesCache[$cacheKey] = array_values($filteredRates); } return $this->_ratesCache[$cacheKey]; diff --git a/app/code/core/Mage/Usa/Model/Shipping/Carrier/Dhl.php b/app/code/core/Mage/Usa/Model/Shipping/Carrier/Dhl.php index 257d1f6d3fb2e6d15b5727031c8265b14c1d9467..07487e07b14a1ffc73f299c51b38339ffbf1c5bd 100644 --- a/app/code/core/Mage/Usa/Model/Shipping/Carrier/Dhl.php +++ b/app/code/core/Mage/Usa/Model/Shipping/Carrier/Dhl.php @@ -568,7 +568,7 @@ class Mage_Usa_Model_Shipping_Carrier_Dhl $ch = curl_init(); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_URL, $url); - curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($ch, CURLOPT_POSTFIELDS, $request); $responseBody = curl_exec($ch); @@ -1072,7 +1072,7 @@ class Mage_Usa_Model_Shipping_Carrier_Dhl $ch = curl_init(); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_URL, $url); - curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($ch, CURLOPT_POSTFIELDS, $request); $responseBody = curl_exec($ch); diff --git a/app/code/core/Mage/Usa/Model/Shipping/Carrier/Fedex.php b/app/code/core/Mage/Usa/Model/Shipping/Carrier/Fedex.php index fc425dd7ad859d6ffe40111068f1ef41de3b7572..ec16a3902d31755fd23c3ff938c82a6c7f9a87ee 100644 --- a/app/code/core/Mage/Usa/Model/Shipping/Carrier/Fedex.php +++ b/app/code/core/Mage/Usa/Model/Shipping/Carrier/Fedex.php @@ -622,7 +622,7 @@ class Mage_Usa_Model_Shipping_Carrier_Fedex $ch = curl_init(); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_URL, $url); - curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($ch, CURLOPT_POSTFIELDS, $request); $responseBody = curl_exec($ch); diff --git a/app/code/core/Mage/User/Block/Role/Grid/User.php b/app/code/core/Mage/User/Block/Role/Grid/User.php index fe66215191d69dbb2ee7021fe859428f8dba0c53..dac3795b8c0e5819ceaa20f0d83a488547192f6c 100644 --- a/app/code/core/Mage/User/Block/Role/Grid/User.php +++ b/app/code/core/Mage/User/Block/Role/Grid/User.php @@ -25,7 +25,7 @@ */ /** - * Acl role user grid + * Acl role user grid. * * @category Mage * @package Mage_User diff --git a/app/code/core/Mage/User/data/user_setup/data-upgrade-1.6.1.1-1.6.1.2.php b/app/code/core/Mage/User/data/user_setup/data-upgrade-1.6.1.1-1.6.1.2.php index 96de456269f18901ea0fd238f6c218852e46c35e..62fdd352967839d27ca4df7dca4c33ebabf8e106 100644 --- a/app/code/core/Mage/User/data/user_setup/data-upgrade-1.6.1.1-1.6.1.2.php +++ b/app/code/core/Mage/User/data/user_setup/data-upgrade-1.6.1.1-1.6.1.2.php @@ -68,12 +68,6 @@ $map = array( 'admin/system/config/trans_email' => 'Mage_Adminhtml::trans_email', 'admin/system/variable' => 'Mage_Adminhtml::variable', 'admin/system/config/web' => 'Mage_Adminhtml::web', - 'admin/system/api/rest_roles/delete' => 'Mage_Api2::delete', - 'admin/system/api/rest_attributes' => 'Mage_Api2::rest_attributes', - 'admin/system/api/rest_attributes/edit' => 'Mage_Api2::rest_attributes_edit', - 'admin/system/api/rest_roles' => 'Mage_Api2::rest_roles', - 'admin/system/api/rest_roles/add' => 'Mage_Api2::rest_roles_add', - 'admin/system/api/rest_roles/edit' => 'Mage_Api2::rest_roles_edit', 'admin/system/api' => 'Mage_Api::api', 'admin/system/config/api' => 'Mage_Api::config_api', 'admin/system/api/roles' => 'Mage_Api::roles', diff --git a/app/code/core/Mage/Adminhtml/Block/Api/Role.php b/app/code/core/Mage/Webapi/Block/Adminhtml/Role.php similarity index 62% rename from app/code/core/Mage/Adminhtml/Block/Api/Role.php rename to app/code/core/Mage/Webapi/Block/Adminhtml/Role.php index e502929902224ccdef11298ef4693ff26d091c4b..b47b60ffa944ddebb9875c8acc89cc8633de094a 100644 --- a/app/code/core/Mage/Adminhtml/Block/Api/Role.php +++ b/app/code/core/Mage/Webapi/Block/Adminhtml/Role.php @@ -1,5 +1,7 @@ <?php /** + * Web API Adminhtml role block. + * * Magento * * NOTICE OF LICENSE @@ -18,29 +20,39 @@ * versions in the future. If you wish to customize Magento for your * needs please refer to http://www.magentocommerce.com for more information. * - * @category Mage - * @package Mage_Adminhtml * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ - -/** - * Adminhtml permissioms role block - * - * @category Mage - * @package Mage_Adminhtml - * @author Magento Core Team <core@magentocommerce.com> - */ - -class Mage_Adminhtml_Block_Api_Role extends Mage_Adminhtml_Block_Widget_Grid_Container +class Mage_Webapi_Block_Adminhtml_Role extends Mage_Backend_Block_Widget_Grid_Container { + /** + * @var string + */ + protected $_blockGroup = 'Mage_Webapi'; + + /** + * @var string + */ + protected $_controller = 'adminhtml_role'; + /** + * Internal constructor. + */ protected function _construct() { - $this->_controller = 'api_role'; - $this->_headerText = Mage::helper('Mage_Adminhtml_Helper_Data')->__('Roles'); - $this->_addButtonLabel = Mage::helper('Mage_Adminhtml_Helper_Data')->__('Add New Role'); parent::_construct(); + + $this->_headerText = $this->__('API Roles'); + $this->_updateButton('add', 'label', $this->__('Add New API Role')); } + /** + * Get create URL. + * + * @return string + */ + public function getCreateUrl() + { + return $this->getUrl('*/*/edit'); + } } diff --git a/app/code/core/Mage/Webapi/Block/Adminhtml/Role/Edit.php b/app/code/core/Mage/Webapi/Block/Adminhtml/Role/Edit.php new file mode 100644 index 0000000000000000000000000000000000000000..110e51edabcfb6ca01b6eb1b57a97fa3e89bd4ae --- /dev/null +++ b/app/code/core/Mage/Webapi/Block/Adminhtml/Role/Edit.php @@ -0,0 +1,89 @@ +<?php +/** + * Web API role edit page. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * + * @method Mage_Webapi_Block_Adminhtml_Role_Edit setApiRole() setApiRole(Mage_Webapi_Model_Acl_Role $role) + * @method Mage_Webapi_Model_Acl_Role getApiRole() getApiRole() + */ +class Mage_Webapi_Block_Adminhtml_Role_Edit extends Mage_Backend_Block_Widget_Form_Container +{ + /** + * @var string + */ + protected $_blockGroup = 'Mage_Webapi'; + + /** + * @var string + */ + protected $_controller = 'adminhtml_role'; + + /** + * @var string + */ + protected $_objectId = 'role_id'; + + /** + * Internal Constructor. + */ + protected function _construct() + { + parent::_construct(); + + $this->_formScripts[] = "function saveAndContinueEdit(url)" . + "{var tagForm = new varienForm('edit_form'); tagForm.submit(url);}"; + + $this->_addButton('save_and_continue', array( + 'label' => $this->__('Save and Continue Edit'), + 'onclick' => "saveAndContinueEdit('" . $this->getSaveAndContinueUrl() . "')", + 'class' => 'save' + ), 100); + + $this->_updateButton('save', 'label', $this->__('Save API Role')); + $this->_updateButton('delete', 'label', $this->__('Delete API Role')); + } + + /** + * Retrieve role SaveAndContinue URL. + * + * @return string + */ + public function getSaveAndContinueUrl() + { + return $this->getUrl('*/*/save', array('_current' => true, 'continue' => true)); + } + + /** + * Get header text. + * + * @return string + */ + public function getHeaderText() + { + if ($this->getApiRole()->getId()) { + return $this->__("Edit API Role '%s'", $this->escapeHtml($this->getApiRole()->getRoleName())); + } else { + return $this->__('New API Role'); + } + } +} diff --git a/app/code/core/Mage/Adminhtml/Block/Api/User/Edit/Form.php b/app/code/core/Mage/Webapi/Block/Adminhtml/Role/Edit/Form.php similarity index 71% rename from app/code/core/Mage/Adminhtml/Block/Api/User/Edit/Form.php rename to app/code/core/Mage/Webapi/Block/Adminhtml/Role/Edit/Form.php index 700381d5e43194b3b183f05c7f19f4fce31bf855..52298ac02c5540fd443384b748eee12f469263fa 100644 --- a/app/code/core/Mage/Adminhtml/Block/Api/User/Edit/Form.php +++ b/app/code/core/Mage/Webapi/Block/Adminhtml/Role/Edit/Form.php @@ -1,5 +1,7 @@ <?php /** + * Web API Role edit form. + * * Magento * * NOTICE OF LICENSE @@ -18,28 +20,26 @@ * versions in the future. If you wish to customize Magento for your * needs please refer to http://www.magentocommerce.com for more information. * - * @category Mage - * @package Mage_Adminhtml * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ - -/** - * Adminhtml permissions user edit form - * - * @category Mage - * @package Mage_Adminhtml - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Adminhtml_Block_Api_User_Edit_Form extends Mage_Adminhtml_Block_Widget_Form +class Mage_Webapi_Block_Adminhtml_Role_Edit_Form extends Mage_Backend_Block_Widget_Form { - + /** + * Prepare form container. + * + * @return Mage_Webapi_Block_Adminhtml_Role_Edit_Form + */ protected function _prepareForm() { - $form = new Varien_Data_Form(array('id' => 'edit_form', 'action' => $this->getData('action'), 'method' => 'post')); + $form = new Varien_Data_Form(array( + 'action' => $this->getUrl('*/*/save'), + 'id' => 'edit_form', + 'method' => 'post' + )); $form->setUseContainer(true); $this->setForm($form); + return parent::_prepareForm(); } - } diff --git a/app/code/core/Mage/Webapi/Block/Adminhtml/Role/Edit/Tab/Main.php b/app/code/core/Mage/Webapi/Block/Adminhtml/Role/Edit/Tab/Main.php new file mode 100644 index 0000000000000000000000000000000000000000..e3f5298c96d07dca39d994a4845f416cb380ec65 --- /dev/null +++ b/app/code/core/Mage/Webapi/Block/Adminhtml/Role/Edit/Tab/Main.php @@ -0,0 +1,81 @@ +<?php +/** + * Web API Role tab with main information. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * + * @method Mage_Webapi_Block_Adminhtml_Role_Edit_Tab_Main setApiRole() setApiRole(Mage_Webapi_Model_Acl_Role $role) + * @method Mage_Webapi_Model_Acl_Role getApiRole() getApiRole() + */ +class Mage_Webapi_Block_Adminhtml_Role_Edit_Tab_Main extends Mage_Backend_Block_Widget_Form +{ + /** + * Prepare Form. + * + * @return Mage_Backend_Block_Widget_Form + */ + protected function _prepareForm() + { + $form = new Varien_Data_Form(); + + $fieldset = $form->addFieldset('base_fieldset', array( + 'legend' => $this->__('Role Information')) + ); + + $role = $this->getApiRole(); + if ($role && $role->getId()) { + $fieldset->addField('role_id', 'hidden', array( + 'name' => 'role_id', + 'value' => $role->getId() + )); + } + + $fieldset->addField('role_name', 'text', array( + 'name' => 'role_name', + 'id' => 'role_name', + 'class' => 'required-entry', + 'required' => true, + 'label' => $this->__('Role Name'), + 'title' => $this->__('Role Name'), + )); + + $fieldset->addField('in_role_user', 'hidden', + array( + 'name' => 'in_role_user', + 'id' => 'in_role_user', + ) + ); + + $fieldset->addField('in_role_user_old', 'hidden', + array( + 'name' => 'in_role_user_old' + ) + ); + + if ($role) { + $form->setValues($role->getData()); + } + $this->setForm($form); + + return parent::_prepareForm(); + } +} diff --git a/app/code/core/Mage/Webapi/Block/Adminhtml/Role/Edit/Tab/Resource.php b/app/code/core/Mage/Webapi/Block/Adminhtml/Role/Edit/Tab/Resource.php new file mode 100644 index 0000000000000000000000000000000000000000..0a37f94910efe4b92d1a493cc19199841d2c2a75 --- /dev/null +++ b/app/code/core/Mage/Webapi/Block/Adminhtml/Role/Edit/Tab/Resource.php @@ -0,0 +1,154 @@ +<?php +/** + * Web API role resource tab. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * + * @method Mage_Webapi_Block_Adminhtml_Role_Edit_Tab_Resource setApiRole() setApiRole(Mage_Webapi_Model_Acl_Role $role) + * @method Mage_Webapi_Model_Acl_Role getApiRole() getApiRole() + * @method Mage_Webapi_Block_Adminhtml_Role_Edit_Tab_Resource setSelectedResources() setSelectedResources(array $srIds) + * @method array getSelectedResources() getSelectedResources() + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class Mage_Webapi_Block_Adminhtml_Role_Edit_Tab_Resource extends Mage_Backend_Block_Widget_Form +{ + /** + * @var Mage_Webapi_Model_Authorization_Config + */ + protected $_authorizationConfig; + + /** + * @var Mage_Webapi_Model_Resource_Acl_Rule + */ + protected $_ruleResource; + + /** + * @var array + */ + protected $_aclResourcesTree; + + /** + * @var array + */ + protected $_selResourcesIds; + + /** + * @param Mage_Core_Controller_Request_Http $request + * @param Mage_Core_Model_Layout $layout + * @param Mage_Core_Model_Event_Manager $eventManager + * @param Mage_Backend_Model_Url $urlBuilder + * @param Mage_Core_Model_Translate $translator + * @param Mage_Core_Model_Cache $cache + * @param Mage_Core_Model_Design_Package $designPackage + * @param Mage_Core_Model_Session $session + * @param Mage_Core_Model_Store_Config $storeConfig + * @param Mage_Core_Controller_Varien_Front $frontController + * @param Mage_Core_Model_Factory_Helper $helperFactory + * @param Mage_Webapi_Model_Authorization_Config $authorizationConfig + * @param Mage_Webapi_Model_Resource_Acl_Rule $ruleResource + * @param array $data + * + * @SuppressWarnings(PHPMD.ExcessiveParameterList) + */ + public function __construct( + Mage_Core_Controller_Request_Http $request, + Mage_Core_Model_Layout $layout, + Mage_Core_Model_Event_Manager $eventManager, + Mage_Backend_Model_Url $urlBuilder, + Mage_Core_Model_Translate $translator, + Mage_Core_Model_Cache $cache, + Mage_Core_Model_Design_Package $designPackage, + Mage_Core_Model_Session $session, + Mage_Core_Model_Store_Config $storeConfig, + Mage_Core_Controller_Varien_Front $frontController, + Mage_Core_Model_Factory_Helper $helperFactory, + Mage_Webapi_Model_Authorization_Config $authorizationConfig, + Mage_Webapi_Model_Resource_Acl_Rule $ruleResource, + array $data = array() + ) { + parent::__construct($request, $layout, $eventManager, $urlBuilder, $translator, $cache, $designPackage, + $session, $storeConfig, $frontController, $helperFactory, $data + ); + $this->_authorizationConfig = $authorizationConfig; + $this->_ruleResource = $ruleResource; + } + + /** + * Prepare Form. + * + * @return Mage_Webapi_Block_Adminhtml_Role_Edit_Tab_Resource + */ + protected function _prepareForm() + { + $this->_aclResourcesTree = $this->_authorizationConfig->getAclResourcesAsArray(false); + $selectedResources = $this->_getSelectedResourcesIds(); + + if ($selectedResources) { + $selResourcesCallback = function (&$resourceItem) use ($selectedResources, &$selResourcesCallback) { + if (in_array($resourceItem['id'], $selectedResources)) { + $resourceItem['checked'] = true; + } + if (!empty($resourceItem['children'])) { + array_walk($resourceItem['children'], $selResourcesCallback); + } + }; + array_walk($this->_aclResourcesTree, $selResourcesCallback); + } + + return parent::_prepareForm(); + } + + /** + * Check whether resource access is set to "All". + * + * @return bool + */ + public function isEverythingAllowed() + { + return in_array(Mage_Webapi_Model_Authorization::API_ACL_RESOURCES_ROOT_ID, $this->_getSelectedResourcesIds()); + } + + /** + * Get ACL resources tree. + * + * @return string + */ + public function getResourcesTree() + { + return $this->_aclResourcesTree; + } + + /** + * Get selected ACL resources of given API role. + * + * @return array + */ + protected function _getSelectedResourcesIds() + { + $apiRole = $this->getApiRole(); + if (null === $this->_selResourcesIds && $apiRole && $apiRole->getId()) { + $this->_selResourcesIds = $this->_ruleResource->getResourceIdsByRole($apiRole->getRoleId()); + } + return (array)$this->_selResourcesIds; + } +} diff --git a/app/code/core/Mage/Webapi/Block/Adminhtml/Role/Edit/Tabs.php b/app/code/core/Mage/Webapi/Block/Adminhtml/Role/Edit/Tabs.php new file mode 100644 index 0000000000000000000000000000000000000000..8715196b386a570384fc043271dd24ac0fb8242e --- /dev/null +++ b/app/code/core/Mage/Webapi/Block/Adminhtml/Role/Edit/Tabs.php @@ -0,0 +1,81 @@ +<?php +/** + * Web API Role edit page tabs. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * + * @method Mage_Webapi_Block_Adminhtml_Role_Edit_Tabs setApiRole() setApiRole(Mage_Webapi_Model_Acl_Role $role) + * @method Mage_Webapi_Model_Acl_Role getApiRole() getApiRole() + */ +class Mage_Webapi_Block_Adminhtml_Role_Edit_Tabs extends Mage_Backend_Block_Widget_Tabs +{ + /** + * Internal Constructor. + */ + protected function _construct() + { + parent::_construct(); + + $this->setId('page_tabs'); + $this->setDestElementId('edit_form'); + $this->setTitle($this->__('Role Information')); + } + + /** + * Prepare child blocks. + * + * @return Mage_Core_Block_Abstract + */ + protected function _beforeToHtml() + { + /** @var Mage_Webapi_Block_Adminhtml_Role_Edit_Tab_Main $mainBlock */ + $mainBlock = $this->getLayout()->getBlock('webapi.role.edit.tab.main'); + $mainBlock->setApiRole($this->getApiRole()); + $this->addTab('main_section', array( + 'label' => $this->__('Role Info'), + 'title' => $this->__('Role Info'), + 'content' => $mainBlock->toHtml(), + 'active' => true + )); + + /** @var Mage_Webapi_Block_Adminhtml_Role_Edit_Tab_Resource $resourceBlock */ + $resourceBlock = $this->getLayout()->getBlock('webapi.role.edit.tab.resource'); + $resourceBlock->setApiRole($this->getApiRole()); + $this->addTab('resource_section', array( + 'label' => $this->__('Resources'), + 'title' => $this->__('Resources'), + 'content' => $resourceBlock->toHtml() + )); + + if ($this->getApiRole() && $this->getApiRole()->getRoleId() > 0) { + $usersGrid = $this->getLayout()->getBlock('webapi.role.edit.tab.users.grid'); + $this->addTab('user_section', array( + 'label' => $this->__('Users'), + 'title' => $this->__('Users'), + 'content' => $usersGrid->toHtml() + )); + } + + return parent::_beforeToHtml(); + } + +} diff --git a/app/code/core/Mage/Api/Model/Resource/Permissions/Collection.php b/app/code/core/Mage/Webapi/Block/Adminhtml/User.php old mode 100755 new mode 100644 similarity index 67% rename from app/code/core/Mage/Api/Model/Resource/Permissions/Collection.php rename to app/code/core/Mage/Webapi/Block/Adminhtml/User.php index ef76c92a93bc1c7ff600ad702148ce10cc035357..bc40788dd63d8da306dc507b73333e2052fcc285 --- a/app/code/core/Mage/Api/Model/Resource/Permissions/Collection.php +++ b/app/code/core/Mage/Webapi/Block/Adminhtml/User.php @@ -1,5 +1,7 @@ <?php /** + * Web API adminhtml user block. + * * Magento * * NOTICE OF LICENSE @@ -18,28 +20,29 @@ * versions in the future. If you wish to customize Magento for your * needs please refer to http://www.magentocommerce.com for more information. * - * @category Mage - * @package Mage_Api * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ +class Mage_Webapi_Block_Adminhtml_User extends Mage_Backend_Block_Widget_Grid_Container +{ + /** + * @var string + */ + protected $_blockGroup = 'Mage_Webapi'; + /** + * @var string + */ + protected $_controller = 'adminhtml_user'; -/** - * Permissions Resource Collection - * - * @category Mage - * @package Mage_Api - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api_Model_Resource_Permissions_Collection extends Mage_Core_Model_Resource_Db_Collection_Abstract -{ /** - * Resource collection initialization - * + * Internal constructor. */ protected function _construct() { - $this->_init('Mage_Api_Model_Rules', 'Mage_Api_Model_Resource_Rules'); + parent::_construct(); + + $this->_headerText = $this->__('API Users'); + $this->_updateButton('add', 'label', $this->__('Add New API User')); } } diff --git a/app/code/core/Mage/Webapi/Block/Adminhtml/User/Edit.php b/app/code/core/Mage/Webapi/Block/Adminhtml/User/Edit.php new file mode 100644 index 0000000000000000000000000000000000000000..c5b9edd8b401927b9340b5ff49f51fb5a7264b10 --- /dev/null +++ b/app/code/core/Mage/Webapi/Block/Adminhtml/User/Edit.php @@ -0,0 +1,93 @@ +<?php +/** + * Web API user edit page. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * + * @method Varien_Object getApiUser() getApiUser() + * @method Mage_Webapi_Block_Adminhtml_User_Edit setApiUser() setApiUser(Varien_Object $apiUser) + */ +class Mage_Webapi_Block_Adminhtml_User_Edit extends Mage_Backend_Block_Widget_Form_Container +{ + /** + * @var string + */ + protected $_blockGroup = 'Mage_Webapi'; + + /** + * @var string + */ + protected $_controller = 'adminhtml_user'; + + /** + * @var string + */ + protected $_objectId = 'user_id'; + + /** + * Internal constructor. + */ + protected function _construct() + { + parent::_construct(); + + $this->_addButton('save_and_continue', array( + 'label' => $this->__('Save and Continue Edit'), + 'onclick' => 'saveAndContinueEdit()', + 'class' => 'save' + ), 100); + + $this->_formScripts[] = "function saveAndContinueEdit()" + . "{editForm.submit($('edit_form').action + 'back/edit/')}"; + + $this->_updateButton('save', 'label', $this->__('Save API User')); + $this->_updateButton('save', 'id', 'save_button'); + $this->_updateButton('delete', 'label', $this->__('Delete API User')); + } + + /** + * Set Web API user to child form block. + * + * @return Mage_Webapi_Block_Adminhtml_User_Edit + */ + protected function _beforeToHtml() + { + /** @var $formBlock Mage_Webapi_Block_Adminhtml_User_Edit_Form */ + $formBlock = $this->getChildBlock('form'); + $formBlock->setApiUser($this->getApiUser()); + return parent::_beforeToHtml(); + } + + /** + * Get header text. + * + * @return string + */ + public function getHeaderText() + { + if ($this->getApiUser()->getId()) { + return $this->__("Edit API User '%s'", $this->escapeHtml($this->getApiUser()->getApiKey())); + } else { + return $this->__('New API User'); + } + } +} diff --git a/app/code/core/Mage/Webapi/Block/Adminhtml/User/Edit/Form.php b/app/code/core/Mage/Webapi/Block/Adminhtml/User/Edit/Form.php new file mode 100644 index 0000000000000000000000000000000000000000..f9adf16367e214ea7db618d35af1fb185904a0ea --- /dev/null +++ b/app/code/core/Mage/Webapi/Block/Adminhtml/User/Edit/Form.php @@ -0,0 +1,47 @@ +<?php +/** + * Web API user edit form. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * + * @method Mage_Webapi_Block_Adminhtml_User_Edit setApiUser() setApiUser(Mage_Webapi_Model_Acl_User $user) + * @method Mage_Webapi_Model_Acl_User getApiUser() getApiUser() + */ +class Mage_Webapi_Block_Adminhtml_User_Edit_Form extends Mage_Backend_Block_Widget_Form +{ + /** + * Prepare Form. + * + * @return Mage_Webapi_Block_Adminhtml_User_Edit_Form + */ + protected function _prepareForm() + { + $form = new Varien_Data_Form(); + $form->setId('edit_form'); + $form->setAction($this->getUrl('*/*/save')); + $form->setMethod('post'); + $form->setUseContainer(true); + $this->setForm($form); + + return parent::_prepareForm(); + } +} diff --git a/app/code/core/Mage/Webapi/Block/Adminhtml/User/Edit/Tab/Main.php b/app/code/core/Mage/Webapi/Block/Adminhtml/User/Edit/Tab/Main.php new file mode 100644 index 0000000000000000000000000000000000000000..3a2e3aea96e381179b101e2d7e93ed8adfadf7c1 --- /dev/null +++ b/app/code/core/Mage/Webapi/Block/Adminhtml/User/Edit/Tab/Main.php @@ -0,0 +1,92 @@ +<?php +/** + * Web API user edit form. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * + * @method Mage_Webapi_Block_Adminhtml_User_Edit setApiUser() setApiUser(Mage_Webapi_Model_Acl_User $user) + * @method Mage_Webapi_Model_Acl_User getApiUser() getApiUser() + */ +class Mage_Webapi_Block_Adminhtml_User_Edit_Tab_Main extends Mage_Backend_Block_Widget_Form +{ + /** + * Prepare Form. + * + * @return Mage_Webapi_Block_Adminhtml_User_Edit_Tab_Main + */ + protected function _prepareForm() + { + $form = new Varien_Data_Form(); + + $fieldset = $form->addFieldset('base_fieldset', array( + 'legend' => $this->__('Account Information')) + ); + + $user = $this->getApiUser(); + if ($user->getId()) { + $fieldset->addField('user_id', 'hidden', array( + 'name' => 'user_id', + 'value' => $user->getId() + )); + } + + $fieldset->addField('company_name', 'text', array( + 'name' => 'company_name', + 'id' => 'company_name', + 'required' => false, + 'label' => $this->__('Company Name'), + 'title' => $this->__('Company Name'), + )); + + $fieldset->addField('contact_email', 'text', array( + 'name' => 'contact_email', + 'id' => 'contact_email', + 'class' => 'validate-email', + 'required' => true, + 'label' => $this->__('Contact Email'), + 'title' => $this->__('Contact Email'), + )); + + $fieldset->addField('api_key', 'text', array( + 'name' => 'api_key', + 'id' => 'api_key', + 'required' => true, + 'label' => $this->__('API Key'), + 'title' => $this->__('API Key'), + )); + + $fieldset->addField('secret', 'text', array( + 'name' => 'secret', + 'id' => 'secret', + 'required' => true, + 'label' => $this->__('API Secret'), + 'title' => $this->__('API Secret'), + )); + + if ($user) { + $form->setValues($user->getData()); + } + $this->setForm($form); + + return parent::_prepareForm(); + } +} diff --git a/app/code/core/Mage/Adminhtml/Block/Api/User/Edit/Tabs.php b/app/code/core/Mage/Webapi/Block/Adminhtml/User/Edit/Tabs.php similarity index 54% rename from app/code/core/Mage/Adminhtml/Block/Api/User/Edit/Tabs.php rename to app/code/core/Mage/Webapi/Block/Adminhtml/User/Edit/Tabs.php index 4c36e7166640dc73d2c020bdc34922277091bce5..dab4a354121126f5a983383c8cec184cfa5ab7c1 100644 --- a/app/code/core/Mage/Adminhtml/Block/Api/User/Edit/Tabs.php +++ b/app/code/core/Mage/Webapi/Block/Adminhtml/User/Edit/Tabs.php @@ -1,5 +1,7 @@ <?php /** + * Web API user edit page tabs. + * * Magento * * NOTICE OF LICENSE @@ -18,48 +20,49 @@ * versions in the future. If you wish to customize Magento for your * needs please refer to http://www.magentocommerce.com for more information. * - * @category Mage - * @package Mage_Adminhtml * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Admin page left menu * - * @category Mage - * @package Mage_Adminhtml - * @author Magento Core Team <core@magentocommerce.com> + * @method Varien_Object getApiUser() getApiUser() + * @method Mage_Webapi_Block_Adminhtml_User_Edit_Tabs setApiUser() setApiUser(Varien_Object $apiUser) */ -class Mage_Adminhtml_Block_Api_User_Edit_Tabs extends Mage_Adminhtml_Block_Widget_Tabs +class Mage_Webapi_Block_Adminhtml_User_Edit_Tabs extends Mage_Backend_Block_Widget_Tabs { - + /** + * Internal constructor. + */ protected function _construct() { parent::_construct(); + $this->setId('page_tabs'); $this->setDestElementId('edit_form'); - $this->setTitle(Mage::helper('Mage_Adminhtml_Helper_Data')->__('User Information')); + $this->setTitle($this->__('User Information')); } + /** + * Before to HTML. + * + * @return Mage_Core_Block_Abstract + */ protected function _beforeToHtml() { + /** @var Mage_Webapi_Block_Adminhtml_User_Edit_Tab_Main $mainTab */ + $mainTab = $this->getLayout()->getBlock('webapi.user.edit.tab.main'); + $mainTab->setApiUser($this->getApiUser()); $this->addTab('main_section', array( - 'label' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('User Info'), - 'title' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('User Info'), - 'content' => $this->getLayout()->createBlock('Mage_Adminhtml_Block_Api_User_Edit_Tab_Main')->toHtml(), - 'active' => true + 'label' => $this->__('User Info'), + 'title' => $this->__('User Info'), + 'content' => $mainTab->toHtml(), + 'active' => true )); + $rolesGrid = $this->getLayout()->getBlock('webapi.user.edit.tab.roles.grid'); $this->addTab('roles_section', array( - 'label' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('User Role'), - 'title' => Mage::helper('Mage_Adminhtml_Helper_Data')->__('User Role'), - 'content' => $this->getLayout()->createBlock( - 'Mage_Adminhtml_Block_Api_User_Edit_Tab_Roles', - 'user.roles.grid' - )->toHtml(), + 'label' => $this->__('User Role'), + 'title' => $this->__('User Role'), + 'content' => $rolesGrid->toHtml(), )); return parent::_beforeToHtml(); } - } diff --git a/app/code/core/Mage/Api/Model/Server/V2/Handler.php b/app/code/core/Mage/Webapi/Controller/Action/Factory.php similarity index 52% rename from app/code/core/Mage/Api/Model/Server/V2/Handler.php rename to app/code/core/Mage/Webapi/Controller/Action/Factory.php index 6a1d563d204cca031491237c89cbb38e83842fe5..c1503bccea1263d95575b3a753b36225bb0b4569 100644 --- a/app/code/core/Mage/Api/Model/Server/V2/Handler.php +++ b/app/code/core/Mage/Webapi/Controller/Action/Factory.php @@ -1,5 +1,7 @@ <?php /** + * Factory of web API action controllers (resources). + * * Magento * * NOTICE OF LICENSE @@ -18,42 +20,39 @@ * versions in the future. If you wish to customize Magento for your * needs please refer to http://www.magentocommerce.com for more information. * - * @category Mage - * @package Mage_Api * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ - -/** - * Webservices server handler v2 - * - * @category Mage - * @package Mage_Api - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api_Model_Server_V2_Handler extends Mage_Api_Model_Server_Handler_Abstract +class Mage_Webapi_Controller_Action_Factory { - protected $_resourceSuffix = '_v2'; + /** + * @var Magento_ObjectManager + */ + protected $_objectManager; /** - * Interceptor for all interfaces - * - * @param sttring $function - * @param array $args + * @param Magento_ObjectManager $objectManager */ + public function __construct(Magento_ObjectManager $objectManager) + { + $this->_objectManager = $objectManager; + } - public function __call( $function, $args ) + /** + * Create front controller instance. + * + * @param string $className + * @param Mage_Webapi_Controller_Request $request + * @return Mage_Webapi_Controller_ActionAbstract + * @throws InvalidArgumentException + */ + public function createActionController($className, $request) { - $sessionId = array_shift( $args ); - $apiKey = ''; - $nodes = Mage::getSingleton('Mage_Api_Model_Config')->getNode('v2/resources_function_prefix')->children(); - foreach ($nodes as $resource => $prefix) { - $prefix = $prefix->asArray(); - if (false !== strpos($function, $prefix)) { - $method = substr($function, strlen($prefix)); - $apiKey = $resource . '.' . strtolower($method[0]).substr($method, 1); - } + $actionController = $this->_objectManager->create($className, array('request' => $request)); + if (!$actionController instanceof Mage_Webapi_Controller_ActionAbstract) { + throw new InvalidArgumentException( + 'The specified class is not a valid API action controller.'); } - return $this->call($sessionId, $apiKey, $args); + return $actionController; } } diff --git a/app/code/core/Mage/Webapi/Controller/ActionAbstract.php b/app/code/core/Mage/Webapi/Controller/ActionAbstract.php new file mode 100644 index 0000000000000000000000000000000000000000..081da582300a39f90e705022be52f250dd40f847 --- /dev/null +++ b/app/code/core/Mage/Webapi/Controller/ActionAbstract.php @@ -0,0 +1,171 @@ +<?php +/** + * Generic action controller for all resources available via web API. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +abstract class Mage_Webapi_Controller_ActionAbstract +{ + /**#@+ + * Collection page sizes. + */ + const PAGE_SIZE_DEFAULT = 10; + const PAGE_SIZE_MAX = 100; + /**#@-*/ + + /**#@+ + * Allowed API resource methods. + */ + const METHOD_CREATE = 'create'; + const METHOD_GET = 'get'; + const METHOD_LIST = 'list'; + const METHOD_UPDATE = 'update'; + const METHOD_DELETE = 'delete'; + const METHOD_MULTI_UPDATE = 'multiUpdate'; + const METHOD_MULTI_DELETE = 'multiDelete'; + const METHOD_MULTI_CREATE = 'multiCreate'; + /**#@-*/ + + /** @var Mage_Webapi_Controller_Request */ + protected $_request; + + /** @var Mage_Webapi_Controller_Response */ + protected $_response; + + /** @var Mage_Webapi_Helper_Data */ + protected $_translationHelper; + + /** @var Mage_Core_Model_Factory_Helper */ + protected $_helperFactory; + + /** + * Initialize dependencies. + * + * @param Mage_Webapi_Controller_Request_Factory $requestFactory + * @param Mage_Webapi_Controller_Response_Factory $responseFactory + * @param Mage_Core_Model_Factory_Helper $helperFactory + */ + public function __construct( + Mage_Webapi_Controller_Request_Factory $requestFactory, + Mage_Webapi_Controller_Response_Factory $responseFactory, + Mage_Core_Model_Factory_Helper $helperFactory + ) { + $this->_helperFactory = $helperFactory; + $this->_translationHelper = $this->_helperFactory->get('Mage_Webapi_Helper_Data'); + $this->_request = $requestFactory->get(); + $this->_response = $responseFactory->get(); + } + + /** + * Retrieve request. + * + * @return Mage_Webapi_Controller_Request + */ + public function getRequest() + { + return $this->_request; + } + + /** + * Retrieve response. + * + * @return Mage_Webapi_Controller_Response + */ + public function getResponse() + { + return $this->_response; + } + + /** + * Set navigation parameters and apply filters from URL params. + * + * @param Varien_Data_Collection_Db $collection + * @return Varien_Data_Collection_Db + * @throws Mage_Webapi_Exception + */ + // TODO: Check and finish this method (the implementation was migrated from Magento 1) + final protected function _applyCollectionModifiers(Varien_Data_Collection_Db $collection) + { + $pageNumber = $this->getRequest()->getPageNumber(); + if ($pageNumber != abs($pageNumber)) { + throw new Mage_Webapi_Exception( + $this->_translationHelper->__("Page number is invalid."), + Mage_Webapi_Exception::HTTP_BAD_REQUEST + ); + } + $pageSize = $this->getRequest()->getPageSize(); + if (null == $pageSize) { + $pageSize = self::PAGE_SIZE_DEFAULT; + } else { + if ($pageSize != abs($pageSize) || $pageSize > self::PAGE_SIZE_MAX) { + throw new Mage_Webapi_Exception( + $this->_translationHelper->__('The paging limit exceeds the allowed number.'), + Mage_Webapi_Exception::HTTP_BAD_REQUEST + ); + } + } + $orderField = $this->getRequest()->getOrderField(); + if (null !== $orderField) { + if (!is_string($orderField) + // TODO: Check if order field is allowed for specified entity + ) { + throw new Mage_Webapi_Exception( + $this->_translationHelper->__('Collection "order" value is invalid.'), + Mage_Webapi_Exception::HTTP_BAD_REQUEST + ); + } + $collection->setOrder($orderField, $this->getRequest()->getOrderDirection()); + } + $collection->setCurPage($pageNumber)->setPageSize($pageSize); + return $collection; + } + + /** + * Check if specified action is defined in current controller. + * + * @param string $actionName + * @return bool + */ + public function hasAction($actionName) + { + return method_exists($this, $actionName); + } + + /** + * Retrieve list of allowed method names in action controllers. + * + * @return array + */ + public static function getAllowedMethods() + { + return array( + self::METHOD_CREATE, + self::METHOD_GET, + self::METHOD_LIST, + self::METHOD_UPDATE, + self::METHOD_MULTI_UPDATE, + self::METHOD_DELETE, + self::METHOD_MULTI_DELETE, + self::METHOD_MULTI_CREATE, + ); + } +} diff --git a/app/code/core/Mage/Webapi/Controller/Dispatcher/ErrorProcessor.php b/app/code/core/Mage/Webapi/Controller/Dispatcher/ErrorProcessor.php new file mode 100644 index 0000000000000000000000000000000000000000..4651d2cf480b23da168a122318dd8e143b2fc944 --- /dev/null +++ b/app/code/core/Mage/Webapi/Controller/Dispatcher/ErrorProcessor.php @@ -0,0 +1,288 @@ +<?php +/** + * Helper for errors processing. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Controller_Dispatcher_ErrorProcessor +{ + const DEFAULT_SHUTDOWN_FUNCTION = 'apiShutdownFunction'; + + const DEFAULT_ERROR_HTTP_CODE = 500; + const DEFAULT_RESPONSE_CHARSET = 'UTF-8'; + + /**#@+ + * Error data representation formats. + */ + const DATA_FORMAT_JSON = 'json'; + const DATA_FORMAT_XML = 'xml'; + /**#@-*/ + + /** @var Mage_Webapi_Helper_Data */ + protected $_apiHelper; + + /** @var Mage_Core_Helper_Data */ + protected $_coreHelper; + + /** @var Mage_Core_Model_App */ + protected $_app; + + /** @var Mage_Core_Model_Logger */ + protected $_logger; + + /** + * Initialize dependencies. Register custom shutdown function. + * + * @param Mage_Core_Model_Factory_Helper $helperFactory + * @param Mage_Core_Model_App $app + * @param Mage_Core_Model_Logger $logger + */ + public function __construct( + Mage_Core_Model_Factory_Helper $helperFactory, + Mage_Core_Model_App $app, + Mage_Core_Model_Logger $logger + ) { + $this->_apiHelper = $helperFactory->get('Mage_Webapi_Helper_Data'); + $this->_coreHelper = $helperFactory->get('Mage_Core_Helper_Data'); + $this->_app = $app; + $this->_logger = $logger; + $this->registerShutdownFunction(); + } + + /** + * Mask actual exception for security reasons in case when it should not be exposed to API clients. + * + * @param Exception $exception + * @return Exception + */ + public function maskException(Exception $exception) + { + if (!($exception instanceof Mage_Webapi_Exception) && !$this->_app->isDeveloperMode()) { + /** Log information about actual exception. */ + $reportId = $this->_logException($exception); + /** Create exception with masked message. */ + return new Mage_Webapi_Exception( + $this->_apiHelper + ->__('Internal Error. Details are available in Magento log file. Report ID: "%s"', $reportId), + Mage_Webapi_Exception::HTTP_INTERNAL_ERROR + ); + } else { + return $exception; + } + } + + /** + * Process API exception. + * + * Create report if not in developer mode and render error to send correct API response. + * + * @param Exception $exception + * @param int $httpCode + * @SuppressWarnings(PHPMD.ExitExpression) + */ + public function renderException(Exception $exception, $httpCode = self::DEFAULT_ERROR_HTTP_CODE) + { + if ($this->_app->isDeveloperMode() || $exception instanceof Mage_Webapi_Exception) { + $this->render($exception->getMessage(), $exception->getTraceAsString(), $exception->getCode()); + } else { + $reportId = $this->_logException($exception); + $this->render( + $this->_apiHelper + ->__('Internal Error. Details are available in Magento log file. Report ID: "%s"', $reportId), + 'Trace is not available.', + $httpCode + ); + } + // TODO: Move die() call to render() method when it will be covered with functional tests. + die(); + } + + /** + * Log information about exception to exception log. + * + * @param Exception $exception + * @return string $reportId + */ + protected function _logException(Exception $exception) + { + $exceptionClass = get_class($exception); + $reportId = uniqid("webapi-"); + $exceptionForLog = new $exceptionClass( + /** Trace is added separately by logException. */ + "Report ID: $reportId; Message: {$exception->getMessage()}", + $exception->getCode() + ); + $this->_logger->logException($exceptionForLog); + return $reportId; + } + + /** + * Render error according to mime type. + * + * @param string $errorMessage + * @param string $trace + * @param int $httpCode + */ + public function render( + $errorMessage, + $trace = 'Trace is not available.', + $httpCode = self::DEFAULT_ERROR_HTTP_CODE + ) { + if (strstr($_SERVER['HTTP_ACCEPT'], 'json')) { + $output = $this->_formatError($errorMessage, $trace, $httpCode, self::DATA_FORMAT_JSON); + $mimeType = 'application/json'; + } elseif (strstr($_SERVER['HTTP_ACCEPT'], 'xml')) { + $output = $this->_formatError($errorMessage, $trace, $httpCode, self::DATA_FORMAT_XML); + $mimeType = 'application/xml'; + } else { + /** Default format is JSON */ + $output = $this->_formatError($errorMessage, $trace, $httpCode, self::DATA_FORMAT_JSON); + $mimeType = 'application/json'; + } + if (!headers_sent()) { + header('HTTP/1.1 ' . ($httpCode ? $httpCode : self::DEFAULT_ERROR_HTTP_CODE)); + header('Content-Type: ' . $mimeType . '; charset=' . self::DEFAULT_RESPONSE_CHARSET); + } + echo $output; + } + + /** + * Format error data according to required format. + * + * @param string $errorMessage + * @param string $trace + * @param string $format + * @param int $httpCode + * @return array + */ + protected function _formatError($errorMessage, $trace, $httpCode, $format) + { + $errorData = array(); + $message = array('code' => $httpCode, 'message' => $errorMessage); + if ($this->_app->isDeveloperMode()) { + $message['trace'] = $trace; + } + $errorData['messages']['error'][] = $message; + switch ($format) { + case self::DATA_FORMAT_JSON: + $errorData = $this->_coreHelper->jsonEncode($errorData); + break; + case self::DATA_FORMAT_XML: + $errorData = '<?xml version="1.0"?>' + . '<error>' + . '<messages>' + . '<error>' + . '<data_item>' + . '<code>' . $httpCode . '</code>' + . '<message>' . $errorMessage . '</message>' + . ($this->_app->isDeveloperMode() ? '<trace><![CDATA[' . $trace . ']]></trace>' : '') + . '</data_item>' + . '</error>' + . '</messages>' + . '</error>'; + break; + } + return $errorData; + } + + /** + * Declare web API-specific shutdown function. + * + * @return Mage_Webapi_Controller_Dispatcher_ErrorProcessor + */ + public function registerShutdownFunction() + { + register_shutdown_function(array($this, self::DEFAULT_SHUTDOWN_FUNCTION)); + return $this; + } + + /** + * Function to catch errors, that has not been caught by the user error dispatcher function. + * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + */ + // TODO: Check if this function is useful (it was migrated from M1) + public function apiShutdownFunction() + { + $fatalErrorFlag = E_ERROR | E_USER_ERROR | E_PARSE | E_CORE_ERROR | E_COMPILE_ERROR | E_RECOVERABLE_ERROR; + $error = error_get_last(); + if ($error && ($error['type'] & $fatalErrorFlag)) { + $errorMessage = ''; + switch ($error['type']) { + case E_ERROR: + $errorMessage .= "Fatal Error"; + break; + case E_PARSE: + $errorMessage .= "Parse Error"; + break; + case E_CORE_ERROR: + $errorMessage .= "Core Error"; + break; + case E_COMPILE_ERROR: + $errorMessage .= "Compile Error"; + break; + case E_USER_ERROR: + $errorMessage .= "User Error"; + break; + case E_RECOVERABLE_ERROR: + $errorMessage .= "Recoverable Error"; + break; + default: + $errorMessage .= "Unknown error ({$error['type']})"; + break; + } + $errorMessage .= ": {$error['message']} in {$error['file']} on line {$error['line']}"; + try { + // call registered error dispatcher + trigger_error("'$errorMessage'", E_USER_ERROR); + } catch (Exception $e) { + $errorMessage = $e->getMessage(); + } + if (!$this->_app->isDeveloperMode()) { + $this->_saveFatalErrorReport($errorMessage); + } + $this->render($errorMessage); + } + } + + /** + * Log information about fatal error. + * + * @param string $reportData + * @return Mage_Webapi_Controller_Dispatcher_ErrorProcessor + */ + protected function _saveFatalErrorReport($reportData) + { + // TODO refactor method using Varien_Io_File class functions. + /** Directory for API related reports. */ + /** @see Error_Processor::__construct() */ + $reportDir = BP . DS . 'var' . DS . 'report' . DS . 'api'; + if (!file_exists($reportDir)) { + @mkdir($reportDir, 0777, true); + } + $reportId = abs(intval(microtime(true) * rand(100, 1000))); + $reportFile = $reportDir . DS . $reportId; + @file_put_contents($reportFile, serialize($reportData)); + @chmod($reportFile, 0777); + return $this; + } +} diff --git a/app/code/core/Mage/Webapi/Controller/Dispatcher/Factory.php b/app/code/core/Mage/Webapi/Controller/Dispatcher/Factory.php new file mode 100644 index 0000000000000000000000000000000000000000..cb820684050ab7c215c23daee242f32b413e3c41 --- /dev/null +++ b/app/code/core/Mage/Webapi/Controller/Dispatcher/Factory.php @@ -0,0 +1,72 @@ +<?php +/** + * Factory of web API dispatchers. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Controller_Dispatcher_Factory +{ + /** + * List of available web API dispatchers. + * + * @var array array({api type} => {API dispatcher class}) + */ + protected $_apiDispatcherMap = array( + Mage_Webapi_Controller_Front::API_TYPE_REST => 'Mage_Webapi_Controller_Dispatcher_Rest', + Mage_Webapi_Controller_Front::API_TYPE_SOAP => 'Mage_Webapi_Controller_Dispatcher_Soap', + ); + + /** + * @var Magento_ObjectManager + */ + protected $_objectManager; + + /** + * Initialize dependencies. + * + * @param Magento_ObjectManager $objectManager + */ + public function __construct(Magento_ObjectManager $objectManager) + { + $this->_objectManager = $objectManager; + } + + /** + * Create front controller instance. + * + * Use current API type to define proper request class. + * + * @param string $apiType + * @return Mage_Webapi_Controller_DispatcherInterface + * @throws LogicException If there is no corresponding dispatcher class for current API type. + */ + public function get($apiType) + { + if (!isset($this->_apiDispatcherMap[$apiType])) { + throw new LogicException( + sprintf('There is no corresponding dispatcher class for the "%s" API type.', $apiType) + ); + } + $dispatcherClass = $this->_apiDispatcherMap[$apiType]; + return $this->_objectManager->get($dispatcherClass); + } +} diff --git a/app/code/core/Mage/Webapi/Controller/Dispatcher/Rest.php b/app/code/core/Mage/Webapi/Controller/Dispatcher/Rest.php new file mode 100644 index 0000000000000000000000000000000000000000..ca5597e76c9c1a6ea485a0b7703adb3c497bfd98 --- /dev/null +++ b/app/code/core/Mage/Webapi/Controller/Dispatcher/Rest.php @@ -0,0 +1,133 @@ +<?php +/** + * Dispatcher for REST API calls. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Controller_Dispatcher_Rest implements Mage_Webapi_Controller_DispatcherInterface +{ + /** @var Mage_Webapi_Model_Config_Rest */ + protected $_apiConfig; + + /** @var Mage_Webapi_Controller_Dispatcher_Rest_Presentation */ + protected $_restPresentation; + + /** @var Mage_Webapi_Controller_Router_Rest */ + protected $_router; + + /** @var Mage_Webapi_Controller_Dispatcher_Rest_Authentication */ + protected $_authentication; + + /** @var Mage_Webapi_Controller_Request_Rest */ + protected $_request; + + /** + * Action controller factory. + * + * @var Mage_Webapi_Controller_Action_Factory + */ + protected $_controllerFactory; + + /** @var Mage_Webapi_Model_Authorization */ + protected $_authorization; + + /** @var Mage_Webapi_Controller_Response_Rest */ + protected $_response; + + /** + * Initialize dependencies. + * + * @param Mage_Webapi_Model_Config_Rest $apiConfig + * @param Mage_Webapi_Controller_Request_Rest $request + * @param Mage_Webapi_Controller_Response_Rest $response + * @param Mage_Webapi_Controller_Action_Factory $controllerFactory + * @param Mage_Webapi_Controller_Dispatcher_Rest_Presentation $restPresentation + * @param Mage_Webapi_Controller_Router_Rest $router + * @param Mage_Webapi_Model_Authorization $authorization + * @param Mage_Webapi_Controller_Dispatcher_Rest_Authentication $authentication + */ + public function __construct( + Mage_Webapi_Model_Config_Rest $apiConfig, + Mage_Webapi_Controller_Request_Rest $request, + Mage_Webapi_Controller_Response_Rest $response, + Mage_Webapi_Controller_Action_Factory $controllerFactory, + Mage_Webapi_Controller_Dispatcher_Rest_Presentation $restPresentation, + Mage_Webapi_Controller_Router_Rest $router, + Mage_Webapi_Model_Authorization $authorization, + Mage_Webapi_Controller_Dispatcher_Rest_Authentication $authentication + ) { + $this->_apiConfig = $apiConfig; + $this->_restPresentation = $restPresentation; + $this->_router = $router; + $this->_authentication = $authentication; + $this->_request = $request; + $this->_controllerFactory = $controllerFactory; + $this->_authorization = $authorization; + $this->_response = $response; + } + + /** + * Handle REST request. + * + * @return Mage_Webapi_Controller_Dispatcher_Rest + */ + public function dispatch() + { + try { + $this->_authentication->authenticate(); + $route = $this->_router->match($this->_request); + + $operation = $this->_request->getOperationName(); + $resourceVersion = $this->_request->getResourceVersion(); + $this->_apiConfig->validateVersionNumber($resourceVersion, $this->_request->getResourceName()); + $method = $this->_apiConfig->getMethodNameByOperation($operation, $resourceVersion); + $controllerClassName = $this->_apiConfig->getControllerClassByOperationName($operation); + $controllerInstance = $this->_controllerFactory->createActionController( + $controllerClassName, + $this->_request + ); + $versionAfterFallback = $this->_apiConfig->identifyVersionSuffix( + $operation, + $resourceVersion, + $controllerInstance + ); + /** + * Route check has two stages: + * The first is performed against full list of routes that is merged from all resources. + * The second stage of route check can be performed only when actual version to be executed is known. + */ + $this->_router->checkRoute($this->_request, $method, $versionAfterFallback); + $this->_apiConfig->checkDeprecationPolicy($route->getResourceName(), $method, $versionAfterFallback); + $action = $method . $versionAfterFallback; + + $this->_authorization->checkResourceAcl($route->getResourceName(), $method); + + $inputData = $this->_restPresentation->fetchRequestData($controllerInstance, $action); + $outputData = call_user_func_array(array($controllerInstance, $action), $inputData); + $this->_restPresentation->prepareResponse($method, $outputData); + } catch (Exception $e) { + $this->_response->setException($e); + } + $this->_response->sendResponse(); + return $this; + } +} diff --git a/app/code/core/Mage/Webapi/Controller/Dispatcher/Rest/Authentication.php b/app/code/core/Mage/Webapi/Controller/Dispatcher/Rest/Authentication.php new file mode 100644 index 0000000000000000000000000000000000000000..614b1a9466b3177816cec1e164a3643099bddb21 --- /dev/null +++ b/app/code/core/Mage/Webapi/Controller/Dispatcher/Rest/Authentication.php @@ -0,0 +1,65 @@ +<?php +/** + * REST web API authentication model. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Controller_Dispatcher_Rest_Authentication +{ + /** @var Mage_Webapi_Model_Authorization_RoleLocator */ + protected $_roleLocator; + + /** @var Mage_Webapi_Model_Rest_Oauth_Server */ + protected $_oauthServer; + + /** + * Initialize dependencies. + * + * @param Mage_Webapi_Model_Rest_Oauth_Server $oauthServer + * @param Mage_Webapi_Model_Authorization_RoleLocator $roleLocator + */ + public function __construct( + Mage_Webapi_Model_Rest_Oauth_Server $oauthServer, + Mage_Webapi_Model_Authorization_RoleLocator $roleLocator + ) { + $this->_oauthServer = $oauthServer; + $this->_roleLocator = $roleLocator; + } + + /** + * Authenticate user. + * + * @throws Mage_Webapi_Exception If authentication failed + */ + public function authenticate() + { + try { + $consumer = $this->_oauthServer->authenticateTwoLegged(); + $this->_roleLocator->setRoleId($consumer->getRoleId()); + } catch (Exception $e) { + throw new Mage_Webapi_Exception( + $this->_oauthServer->reportProblem($e), + Mage_Webapi_Exception::HTTP_UNAUTHORIZED + ); + } + } +} diff --git a/app/code/core/Mage/Webapi/Controller/Dispatcher/Rest/Presentation.php b/app/code/core/Mage/Webapi/Controller/Dispatcher/Rest/Presentation.php new file mode 100644 index 0000000000000000000000000000000000000000..796040ca5e06bbd257770d9f1d4cf8e83b534f4c --- /dev/null +++ b/app/code/core/Mage/Webapi/Controller/Dispatcher/Rest/Presentation.php @@ -0,0 +1,234 @@ +<?php +/** + * Helper for data processing according to REST presentation. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Controller_Dispatcher_Rest_Presentation +{ + /** @var Mage_Webapi_Model_Config_Rest */ + protected $_apiConfig; + + /** @var Mage_Webapi_Helper_Data */ + protected $_apiHelper; + + /** @var Mage_Webapi_Helper_Config */ + protected $_configHelper; + + /** @var Mage_Webapi_Controller_Request_Rest */ + protected $_request; + + /** @var Mage_Webapi_Controller_Response_Rest */ + protected $_response; + + /** @var Magento_Controller_Router_Route_Factory */ + protected $_routeFactory; + + /** @var Mage_Webapi_Controller_Response_Rest_RendererInterface */ + protected $_renderer; + + /** + * Initialize dependencies. + * + * @param Mage_Webapi_Model_Config_Rest $apiConfig + * @param Mage_Webapi_Helper_Data $helper + * @param Mage_Webapi_Helper_Config $configHelper + * @param Mage_Webapi_Controller_Request_Factory $requestFactory + * @param Mage_Webapi_Controller_Response_Rest $response + * @param Mage_Webapi_Controller_Response_Rest_Renderer_Factory $rendererFactory + * @param Magento_Controller_Router_Route_Factory $routeFactory + */ + public function __construct( + Mage_Webapi_Model_Config_Rest $apiConfig, + Mage_Webapi_Helper_Data $helper, + Mage_Webapi_Helper_Config $configHelper, + Mage_Webapi_Controller_Request_Factory $requestFactory, + Mage_Webapi_Controller_Response_Rest $response, + Mage_Webapi_Controller_Response_Rest_Renderer_Factory $rendererFactory, + Magento_Controller_Router_Route_Factory $routeFactory + ) { + $this->_apiConfig = $apiConfig; + $this->_apiHelper = $helper; + $this->_configHelper = $configHelper; + $this->_request = $requestFactory->get(); + $this->_response = $response; + $this->_routeFactory = $routeFactory; + $this->_renderer = $rendererFactory->get(); + } + + /** + * Fetch data from request and prepare it for passing to specified action. + * + * @param object $controllerInstance + * @param string $action + * @return array + */ + public function fetchRequestData($controllerInstance, $action) + { + $methodReflection = Mage_Webapi_Helper_Data::createMethodReflection($controllerInstance, $action); + $methodName = $this->_configHelper->getMethodNameWithoutVersionSuffix($methodReflection); + $bodyParamName = $this->_configHelper->getOperationBodyParamName($methodReflection); + $requestParams = array_merge( + $this->_request->getParams(), + array($bodyParamName => $this->_getRequestBody($methodName)) + ); + /** Convert names of ID and Parent ID params in request to those which are used in method interface. */ + $idArgumentName = $this->_configHelper->getOperationIdParamName($methodReflection); + $parentIdParamName = Mage_Webapi_Controller_Router_Route_Rest::PARAM_PARENT_ID; + $idParamName = Mage_Webapi_Controller_Router_Route_Rest::PARAM_ID; + if (isset($requestParams[$parentIdParamName]) && ($idArgumentName != $parentIdParamName)) { + $requestParams[$idArgumentName] = $requestParams[$parentIdParamName]; + unset($requestParams[$parentIdParamName]); + } elseif (isset($requestParams[$idParamName]) && ($idArgumentName != $idParamName)) { + $requestParams[$idArgumentName] = $requestParams[$idParamName]; + unset($requestParams[$idParamName]); + } + + return $this->_apiHelper->prepareMethodParams($controllerInstance, $action, $requestParams, $this->_apiConfig); + } + + /** + * Perform rendering of action results. + * + * @param string $method + * @param array|null $outputData + */ + public function prepareResponse($method, $outputData = null) + { + switch ($method) { + case Mage_Webapi_Controller_ActionAbstract::METHOD_CREATE: + /** @var $createdItem Mage_Core_Model_Abstract */ + $createdItem = $outputData; + $this->_response->setHeader('Location', $this->_getCreatedItemLocation($createdItem)); + break; + case Mage_Webapi_Controller_ActionAbstract::METHOD_GET: + // TODO: Implement fields filtration + $filteredData = $outputData; + $this->_render($filteredData); + break; + case Mage_Webapi_Controller_ActionAbstract::METHOD_LIST: + // TODO: Implement fields filtration + $filteredData = $outputData; + $this->_render($filteredData); + break; + case Mage_Webapi_Controller_ActionAbstract::METHOD_MULTI_UPDATE: + // break is intentionally omitted + case Mage_Webapi_Controller_ActionAbstract::METHOD_MULTI_CREATE: + // break is intentionally omitted + case Mage_Webapi_Controller_ActionAbstract::METHOD_MULTI_DELETE: + $this->_response->setHttpResponseCode(Mage_Webapi_Controller_Response_Rest::HTTP_MULTI_STATUS); + break; + case Mage_Webapi_Controller_ActionAbstract::METHOD_UPDATE: + // break is intentionally omitted + case Mage_Webapi_Controller_ActionAbstract::METHOD_DELETE: + break; + } + $this->_renderMessages(); + } + + /** + * Render error and success messages. + */ + protected function _renderMessages() + { + if ($this->_response->getMessages()) { + $this->_render(array('messages' => $this->_response->getMessages())); + } + } + + /** + * Generate resource location. + * + * @param Mage_Core_Model_Abstract $createdItem + * @return string URL + */ + protected function _getCreatedItemLocation($createdItem) + { + $apiTypeRoute = $this->_routeFactory->createRoute( + 'Mage_Webapi_Controller_Router_Route_Webapi', + Mage_Webapi_Controller_Router_Route_Webapi::getApiRoute() + ); + $resourceName = $this->_request->getResourceName(); + $routeToItem = $this->_routeFactory->createRoute( + 'Zend_Controller_Router_Route', + $this->_apiConfig->getRestRouteToItem($resourceName) + ); + $chain = $apiTypeRoute->chain($routeToItem); + $params = array( + Mage_Webapi_Controller_Router_Route_Webapi::PARAM_API_TYPE => $this->_request->getApiType(), + Mage_Webapi_Controller_Router_Route_Rest::PARAM_ID => $createdItem->getId(), + Mage_Webapi_Controller_Router_Route_Rest::PARAM_VERSION => $this->_request->getResourceVersion() + ); + $uri = $chain->assemble($params); + + return '/' . $uri; + } + + /** + * Retrieve request data. Ensure that data is not empty. + * + * @param string $method + * @return array + */ + protected function _getRequestBody($method) + { + $processedInputData = null; + switch ($method) { + case Mage_Webapi_Controller_ActionAbstract::METHOD_CREATE: + $processedInputData = $this->_request->getBodyParams(); + // TODO: Implement data filtration of item + break; + case Mage_Webapi_Controller_ActionAbstract::METHOD_MULTI_CREATE: + $processedInputData = $this->_request->getBodyParams(); + break; + case Mage_Webapi_Controller_ActionAbstract::METHOD_UPDATE: + $processedInputData = $this->_request->getBodyParams(); + // TODO: Implement data filtration + break; + case Mage_Webapi_Controller_ActionAbstract::METHOD_MULTI_UPDATE: + $processedInputData = $this->_request->getBodyParams(); + // TODO: Implement fields filtration + break; + case Mage_Webapi_Controller_ActionAbstract::METHOD_MULTI_DELETE: + // break is intentionally omitted + case Mage_Webapi_Controller_ActionAbstract::METHOD_GET: + // break is intentionally omitted + case Mage_Webapi_Controller_ActionAbstract::METHOD_DELETE: + // break is intentionally omitted + case Mage_Webapi_Controller_ActionAbstract::METHOD_LIST: + break; + } + return $processedInputData; + } + + /** + * Render data using registered Renderer. + * + * @param mixed $data + */ + protected function _render($data) + { + $mimeType = $this->_renderer->getMimeType(); + $body = $this->_renderer->render($data); + $this->_response->setMimeType($mimeType)->setBody($body); + } +} diff --git a/app/code/core/Mage/Webapi/Controller/Dispatcher/Soap.php b/app/code/core/Mage/Webapi/Controller/Dispatcher/Soap.php new file mode 100644 index 0000000000000000000000000000000000000000..6513f65b65f37fab21c239ae37b154ea9c4ed5b3 --- /dev/null +++ b/app/code/core/Mage/Webapi/Controller/Dispatcher/Soap.php @@ -0,0 +1,193 @@ +<?php +/** + * Dispatcher for SOAP API calls. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Controller_Dispatcher_Soap implements Mage_Webapi_Controller_DispatcherInterface +{ + /** @var Mage_Webapi_Model_Config_Soap */ + protected $_apiConfig; + + /** @var Mage_Webapi_Model_Soap_Server */ + protected $_soapServer; + + /** @var Mage_Webapi_Model_Soap_AutoDiscover */ + protected $_autoDiscover; + + /** @var Mage_Webapi_Controller_Request_Soap */ + protected $_request; + + /** @var Mage_Webapi_Model_Soap_Fault */ + protected $_soapFault; + + /** @var Mage_Webapi_Controller_Response */ + protected $_response; + + /** @var Mage_Webapi_Controller_Dispatcher_ErrorProcessor */ + protected $_errorProcessor; + + /** @var Mage_Webapi_Controller_Dispatcher_Soap_Handler */ + protected $_soapHandler; + + /** + * Initialize dependencies. + * + * @param Mage_Webapi_Model_Config_Soap $apiConfig + * @param Mage_Webapi_Controller_Request_Soap $request + * @param Mage_Webapi_Controller_Response $response + * @param Mage_Webapi_Model_Soap_AutoDiscover $autoDiscover + * @param Mage_Webapi_Model_Soap_Server $soapServer + * @param Mage_Webapi_Model_Soap_Fault $soapFault + * @param Mage_Webapi_Controller_Dispatcher_ErrorProcessor $errorProcessor + * @param Mage_Webapi_Controller_Dispatcher_Soap_Handler $soapHandler + */ + public function __construct( + Mage_Webapi_Model_Config_Soap $apiConfig, + Mage_Webapi_Controller_Request_Soap $request, + Mage_Webapi_Controller_Response $response, + Mage_Webapi_Model_Soap_AutoDiscover $autoDiscover, + Mage_Webapi_Model_Soap_Server $soapServer, + Mage_Webapi_Model_Soap_Fault $soapFault, + Mage_Webapi_Controller_Dispatcher_ErrorProcessor $errorProcessor, + Mage_Webapi_Controller_Dispatcher_Soap_Handler $soapHandler + ) { + $this->_apiConfig = $apiConfig; + $this->_autoDiscover = $autoDiscover; + $this->_soapServer = $soapServer; + $this->_request = $request; + $this->_soapFault = $soapFault; + $this->_response = $response; + $this->_errorProcessor = $errorProcessor; + $this->_soapHandler = $soapHandler; + } + + /** + * Dispatch request to SOAP endpoint. + * + * @return Mage_Webapi_Controller_Dispatcher_Soap + */ + public function dispatch() + { + try { + if ($this->_request->getParam(Mage_Webapi_Model_Soap_Server::REQUEST_PARAM_WSDL) !== null) { + $responseBody = $this->_autoDiscover->handle( + $this->_request->getRequestedResources(), + $this->_soapServer->generateUri() + ); + $this->_setResponseContentType('text/xml'); + } else { + $responseBody = $this->_initSoapServer()->handle(); + $this->_setResponseContentType('application/soap+xml'); + } + $this->_setResponseBody($responseBody); + } catch (Exception $e) { + $maskedException = $this->_errorProcessor->maskException($e); + $this->_processBadRequest($maskedException->getMessage()); + } + + $this->_response->sendResponse(); + return $this; + } + + /** + * Process request as HTTP 400 and set error message. + * + * @param string $message + */ + protected function _processBadRequest($message) + { + $this->_setResponseContentType('text/xml'); + $this->_response->setHttpResponseCode(400); + $details = array(); + foreach ($this->_apiConfig->getAllResourcesVersions() as $resourceName => $versions) { + foreach ($versions as $version) { + $details['availableResources'][$resourceName][$version] = sprintf( + '%s?wsdl&resources[%s]=%s', + $this->_soapServer->getEndpointUri(), + $resourceName, + $version + ); + } + } + + $this->_setResponseBody( + $this->_soapFault->getSoapFaultMessage( + $message, + Mage_Webapi_Model_Soap_Fault::FAULT_CODE_SENDER, + 'en', + $details + ) + ); + } + + /** + * Set content type to response object. + * + * @param string $contentType + * @return Mage_Webapi_Controller_Dispatcher_Soap + */ + protected function _setResponseContentType($contentType = 'text/xml') + { + $this->_response->clearHeaders() + ->setHeader('Content-Type', "$contentType; charset={$this->_soapServer->getApiCharset()}"); + return $this; + } + + /** + * Set body to response object. + * + * @param string $responseBody + * @return Mage_Webapi_Controller_Dispatcher_Soap + */ + protected function _setResponseBody($responseBody) + { + $this->_response->setBody( + preg_replace( + '/<\?xml version="([^\"]+)"([^\>]+)>/i', + '<?xml version="$1" encoding="' . $this->_soapServer->getApiCharset() . '"?>', + $responseBody + ) + ); + return $this; + } + + /** + * Initialize SOAP Server. + * + * @return Mage_Webapi_Model_Soap_Server + */ + protected function _initSoapServer() + { + $this->_soapServer->initWsdlCache(); + $this->_soapServer->setWSDL($this->_soapServer->generateUri(true)) + ->setEncoding($this->_soapServer->getApiCharset()) + ->setSoapVersion(SOAP_1_2) + ->setClassmap($this->_apiConfig->getTypeToClassMap()); + use_soap_error_handler(false); + // TODO: Headers are not available at this point. + // $this->_soapHandler->setRequestHeaders($this->_getRequestHeaders()); + $this->_soapServer->setReturnResponse(true)->setObject($this->_soapHandler); + + return $this->_soapServer; + } +} diff --git a/app/code/core/Mage/Webapi/Controller/Dispatcher/Soap/Authentication.php b/app/code/core/Mage/Webapi/Controller/Dispatcher/Soap/Authentication.php new file mode 100644 index 0000000000000000000000000000000000000000..f69da14401403fc1145ec2dfc98e4ee49aec0121 --- /dev/null +++ b/app/code/core/Mage/Webapi/Controller/Dispatcher/Soap/Authentication.php @@ -0,0 +1,95 @@ +<?php +/** + * SOAP web API authentication model. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Controller_Dispatcher_Soap_Authentication +{ + /** @var Mage_Webapi_Helper_Data */ + protected $_helper; + + /** + * Username token factory. + * + * @var Mage_Webapi_Model_Soap_Security_UsernameToken_Factory + */ + protected $_tokenFactory; + + /** @var Mage_Webapi_Model_Authorization_RoleLocator */ + protected $_roleLocator; + + /** + * Initialize dependencies. + * + * @param Mage_Webapi_Helper_Data $helper + * @param Mage_Webapi_Model_Soap_Security_UsernameToken_Factory $usernameTokenFactory + * @param Mage_Webapi_Model_Authorization_RoleLocator $roleLocator + */ + public function __construct( + Mage_Webapi_Helper_Data $helper, + Mage_Webapi_Model_Soap_Security_UsernameToken_Factory $usernameTokenFactory, + Mage_Webapi_Model_Authorization_RoleLocator $roleLocator + ) { + $this->_helper = $helper; + $this->_tokenFactory = $usernameTokenFactory; + $this->_roleLocator = $roleLocator; + } + + /** + * Authenticate user. + * + * @param stdClass $usernameToken WS-Security UsernameToken object + * @throws Mage_Webapi_Exception If authentication failed + */ + public function authenticate($usernameToken) + { + try { + $token = $this->_tokenFactory->createFromArray(); + $request = $usernameToken; + // @codingStandardsIgnoreStart + $user = $token->authenticate($request->Username, $request->Password, $request->Created, $request->Nonce); + // @codingStandardsIgnoreEnd + $this->_roleLocator->setRoleId($user->getRoleId()); + } catch (Mage_Webapi_Model_Soap_Security_UsernameToken_NonceUsedException $e) { + throw new Mage_Webapi_Exception( + $this->_helper->__('WS-Security UsernameToken Nonce is already used.'), + Mage_Webapi_Exception::HTTP_BAD_REQUEST + ); + } catch (Mage_Webapi_Model_Soap_Security_UsernameToken_TimestampRefusedException $e) { + throw new Mage_Webapi_Exception( + $this->_helper->__('WS-Security UsernameToken Created timestamp is refused.'), + Mage_Webapi_Exception::HTTP_BAD_REQUEST + ); + } catch (Mage_Webapi_Model_Soap_Security_UsernameToken_InvalidCredentialException $e) { + throw new Mage_Webapi_Exception( + $this->_helper->__('Invalid Username or Password.'), + Mage_Webapi_Exception::HTTP_BAD_REQUEST + ); + } catch (Mage_Webapi_Model_Soap_Security_UsernameToken_InvalidDateException $e) { + throw new Mage_Webapi_Exception( + $this->_helper->__('Invalid UsernameToken Created date.'), + Mage_Webapi_Exception::HTTP_BAD_REQUEST + ); + } + } +} diff --git a/app/code/core/Mage/Webapi/Controller/Dispatcher/Soap/Handler.php b/app/code/core/Mage/Webapi/Controller/Dispatcher/Soap/Handler.php new file mode 100644 index 0000000000000000000000000000000000000000..a774c174353f1d6884cb53bac0414b6141152597 --- /dev/null +++ b/app/code/core/Mage/Webapi/Controller/Dispatcher/Soap/Handler.php @@ -0,0 +1,226 @@ +<?php +/** + * Handler of requests to SOAP server. + * + * The main responsibility is to instantiate proper action controller (resource) and execute requested method on it. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Controller_Dispatcher_Soap_Handler +{ + const HEADER_SECURITY = 'Security'; + const RESULT_NODE_NAME = 'result'; + + /** @var Mage_Webapi_Model_Config_Soap */ + protected $_apiConfig; + + /** + * WS-Security UsernameToken object from request. + * + * @var stdClass + */ + protected $_usernameToken; + + /** @var Mage_Webapi_Helper_Data */ + protected $_helper; + + /** @var Mage_Webapi_Controller_Dispatcher_Soap_Authentication */ + protected $_authentication; + + /** + * Action controller factory. + * + * @var Mage_Webapi_Controller_Action_Factory + */ + protected $_controllerFactory; + + /** @var Mage_Webapi_Model_Authorization */ + protected $_authorization; + + /** @var Mage_Webapi_Controller_Request_Soap */ + protected $_request; + + /** @var Mage_Webapi_Controller_Dispatcher_ErrorProcessor */ + protected $_errorProcessor; + + /** + * List of headers passed in the request + * + * @var array + */ + protected $_requestHeaders = array(self::HEADER_SECURITY); + + /** + * Initialize dependencies. + * + * @param Mage_Webapi_Model_Config_Soap $apiConfig + * @param Mage_Webapi_Helper_Data $helper + * @param Mage_Webapi_Controller_Dispatcher_Soap_Authentication $authentication + * @param Mage_Webapi_Controller_Action_Factory $controllerFactory + * @param Mage_Webapi_Model_Authorization $authorization + * @param Mage_Webapi_Controller_Request_Soap $request + * @param Mage_Webapi_Controller_Dispatcher_ErrorProcessor $errorProcessor + */ + public function __construct( + Mage_Webapi_Model_Config_Soap $apiConfig, + Mage_Webapi_Helper_Data $helper, + Mage_Webapi_Controller_Dispatcher_Soap_Authentication $authentication, + Mage_Webapi_Controller_Action_Factory $controllerFactory, + Mage_Webapi_Model_Authorization $authorization, + Mage_Webapi_Controller_Request_Soap $request, + Mage_Webapi_Controller_Dispatcher_ErrorProcessor $errorProcessor + ) { + $this->_apiConfig = $apiConfig; + $this->_helper = $helper; + $this->_authentication = $authentication; + $this->_controllerFactory = $controllerFactory; + $this->_authorization = $authorization; + $this->_request = $request; + $this->_errorProcessor = $errorProcessor; + } + + /** + * Handler for all SOAP operations. + * + * @param string $operation + * @param array $arguments + * @return stdClass + * @throws Mage_Webapi_Model_Soap_Fault + * @throws Mage_Webapi_Exception + */ + public function __call($operation, $arguments) + { + if (in_array($operation, $this->_requestHeaders)) { + $this->_processSoapHeader($operation, $arguments); + } else { + try { + if (is_null($this->_usernameToken)) { + throw new Mage_Webapi_Exception( + $this->_helper->__('WS-Security UsernameToken is not found in SOAP-request.'), + Mage_Webapi_Exception::HTTP_UNAUTHORIZED + ); + } + $this->_authentication->authenticate($this->_usernameToken); + $resourceVersion = $this->_getOperationVersion($operation); + $resourceName = $this->_apiConfig->getResourceNameByOperation($operation, $resourceVersion); + if (!$resourceName) { + throw new Mage_Webapi_Exception( + $this->_helper->__('Method "%s" is not found.', $operation), + Mage_Webapi_Exception::HTTP_NOT_FOUND + ); + } + $controllerClass = $this->_apiConfig->getControllerClassByOperationName($operation); + $controllerInstance = $this->_controllerFactory->createActionController( + $controllerClass, + $this->_request + ); + $method = $this->_apiConfig->getMethodNameByOperation($operation, $resourceVersion); + + $this->_authorization->checkResourceAcl($resourceName, $method); + + $arguments = reset($arguments); + $arguments = get_object_vars($arguments); + $versionAfterFallback = $this->_apiConfig->identifyVersionSuffix( + $operation, + $resourceVersion, + $controllerInstance + ); + $this->_apiConfig->checkDeprecationPolicy($resourceName, $method, $versionAfterFallback); + $action = $method . $versionAfterFallback; + $arguments = $this->_helper->prepareMethodParams( + $controllerClass, + $action, + $arguments, + $this->_apiConfig + ); + $outputData = call_user_func_array(array($controllerInstance, $action), $arguments); + return (object)array(self::RESULT_NODE_NAME => $outputData); + } catch (Mage_Webapi_Exception $e) { + throw new Mage_Webapi_Model_Soap_Fault($e->getMessage(), $e->getOriginator(), $e); + } catch (Exception $e) { + $maskedException = $this->_errorProcessor->maskException($e); + throw new Mage_Webapi_Model_Soap_Fault( + $maskedException->getMessage(), + Mage_Webapi_Model_Soap_Fault::FAULT_CODE_RECEIVER, + $maskedException + ); + } + } + } + + /** + * Set request headers + * + * @param array $requestHeaders + */ + public function setRequestHeaders(array $requestHeaders) + { + $this->_requestHeaders = $requestHeaders; + } + + /** + * Handle SOAP headers. + * + * @param string $header + * @param array $arguments + */ + protected function _processSoapHeader($header, $arguments) + { + switch ($header) { + case self::HEADER_SECURITY: + foreach ($arguments as $argument) { + // @codingStandardsIgnoreStart + if (is_object($argument) && isset($argument->UsernameToken)) { + $this->_usernameToken = $argument->UsernameToken; + } + // @codingStandardsIgnoreEnd + } + break; + } + } + + /** + * Identify version of requested operation. + * + * This method is required when there are two or more resource versions specified in request: + * http://magento.host/api/soap?wsdl&resources[resource_a]=v1&resources[resource_b]=v2 <br/> + * In this case it is not obvious what version of requested operation should be used. + * + * @param string $operationName + * @return int + * @throws Mage_Webapi_Exception + */ + protected function _getOperationVersion($operationName) + { + $requestedResources = $this->_request->getRequestedResources(); + $resourceName = $this->_apiConfig->getResourceNameByOperation($operationName); + if (!isset($requestedResources[$resourceName])) { + throw new Mage_Webapi_Exception( + $this->_helper->__('The version of "%s" operation cannot be identified.', $operationName), + Mage_Webapi_Exception::HTTP_NOT_FOUND + ); + } + $version = (int)str_replace('V', '', ucfirst($requestedResources[$resourceName])); + $this->_apiConfig->validateVersionNumber($version, $resourceName); + return $version; + } +} diff --git a/app/code/core/Mage/Webapi/Controller/DispatcherInterface.php b/app/code/core/Mage/Webapi/Controller/DispatcherInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..bb9730ec8058a1e65e308288f42b8de06db28a99 --- /dev/null +++ b/app/code/core/Mage/Webapi/Controller/DispatcherInterface.php @@ -0,0 +1,34 @@ +<?php +/** + * Abstract dispatcher for web API requests. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +interface Mage_Webapi_Controller_DispatcherInterface +{ + /** + * Dispatch request. + * + * @return Mage_Webapi_Controller_DispatcherInterface + */ + public function dispatch(); +} diff --git a/app/code/core/Mage/Webapi/Controller/Front.php b/app/code/core/Mage/Webapi/Controller/Front.php new file mode 100644 index 0000000000000000000000000000000000000000..be07a91dadf2603fe94f05ce2ba5485c20a7ece9 --- /dev/null +++ b/app/code/core/Mage/Webapi/Controller/Front.php @@ -0,0 +1,169 @@ +<?php +/** + * Front controller associated with API area. + * + * The main responsibility of this class is to identify requested API type and instantiate correct dispatcher for it. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Controller_Front implements Mage_Core_Controller_FrontInterface +{ + /**#@+ + * API types + */ + const API_TYPE_REST = 'rest'; + const API_TYPE_SOAP = 'soap'; + /**#@-*/ + + /** + * Specific front controller for current API type. + * + * @var Mage_Webapi_Controller_DispatcherInterface + */ + protected $_dispatcher; + + /** @var Mage_Core_Model_App */ + protected $_application; + + /** @var Mage_Webapi_Helper_Data */ + protected $_helper; + + /** @var string */ + protected $_apiType; + + /** @var Mage_Webapi_Controller_Dispatcher_Factory */ + protected $_dispatcherFactory; + + /** @var Magento_Controller_Router_Route_Factory */ + protected $_routeFactory; + + /** @var Mage_Webapi_Controller_Dispatcher_ErrorProcessor */ + protected $_errorProcessor; + + /** + * Initialize dependencies. + * + * @param Mage_Core_Model_Factory_Helper $helperFactory + * @param Mage_Webapi_Controller_Dispatcher_Factory $dispatcherFactory + * @param Mage_Core_Model_App $application + * @param Magento_Controller_Router_Route_Factory $routeFactory + * @param Mage_Webapi_Controller_Dispatcher_ErrorProcessor $errorProcessor + */ + public function __construct( + Mage_Core_Model_Factory_Helper $helperFactory, + Mage_Webapi_Controller_Dispatcher_Factory $dispatcherFactory, + Mage_Core_Model_App $application, + Magento_Controller_Router_Route_Factory $routeFactory, + Mage_Webapi_Controller_Dispatcher_ErrorProcessor $errorProcessor + ) { + $this->_helper = $helperFactory->get('Mage_Webapi_Helper_Data'); + $this->_dispatcherFactory = $dispatcherFactory; + $this->_application = $application; + $this->_routeFactory = $routeFactory; + $this->_errorProcessor = $errorProcessor; + } + + /** + * Prepare environment, initialize dispatcher. + * + * @return Mage_Webapi_Controller_Front + */ + public function init() + { + ini_set('display_startup_errors', 0); + ini_set('display_errors', 0); + + return $this; + } + + /** + * Dispatch request and send response. + * + * @return Mage_Webapi_Controller_Front + */ + public function dispatch() + { + try { + $this->_getDispatcher()->dispatch(); + } catch (Exception $e) { + $this->_errorProcessor->renderException($e); + } + return $this; + } + + /** + * Retrieve front controller for concrete API type (factory method). + * + * @return Mage_Webapi_Controller_DispatcherInterface + * @throws Mage_Core_Exception + */ + protected function _getDispatcher() + { + if (is_null($this->_dispatcher)) { + $this->_dispatcher = $this->_dispatcherFactory->get($this->determineApiType()); + } + return $this->_dispatcher; + } + + /** + * Return the list of defined API types. + * + * @return array + */ + public function getListOfAvailableApiTypes() + { + return array( + self::API_TYPE_REST, + self::API_TYPE_SOAP + ); + } + + /** + * Determine current API type using application request (not web API request). + * + * @return string + * @throws Mage_Core_Exception + * @throws Mage_Webapi_Exception If requested API type is invalid. + */ + public function determineApiType() + { + if (is_null($this->_apiType)) { + $request = $this->_application->getRequest(); + $apiRoute = $this->_routeFactory->createRoute( + 'Mage_Webapi_Controller_Router_Route_Webapi', + Mage_Webapi_Controller_Router_Route_Webapi::getApiRoute() + ); + if (!($apiTypeMatch = $apiRoute->match($request, true))) { + throw new Mage_Webapi_Exception($this->_helper->__('Request does not match any API type route.'), + Mage_Webapi_Exception::HTTP_BAD_REQUEST); + } + + $apiType = $apiTypeMatch[Mage_Webapi_Controller_Router_Route_Webapi::PARAM_API_TYPE]; + if (!in_array($apiType, $this->getListOfAvailableApiTypes())) { + throw new Mage_Webapi_Exception($this->_helper->__('The "%s" API type is not defined.', $apiType), + Mage_Webapi_Exception::HTTP_BAD_REQUEST); + } + $this->_apiType = $apiType; + } + return $this->_apiType; + } +} diff --git a/app/code/core/Mage/Webapi/Controller/Request.php b/app/code/core/Mage/Webapi/Controller/Request.php new file mode 100644 index 0000000000000000000000000000000000000000..3ba729543731e096c9d415478f1ca1c0e7740e68 --- /dev/null +++ b/app/code/core/Mage/Webapi/Controller/Request.php @@ -0,0 +1,139 @@ +<?php +/** + * Web API request. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Controller_Request extends Zend_Controller_Request_Http +{ + /**#@+ + * Name of query ($_GET) parameters to use in navigation and so on. + */ + const QUERY_PARAM_REQ_ATTRS = 'attrs'; + const QUERY_PARAM_PAGE_NUM = 'page'; + const QUERY_PARAM_PAGE_SIZE = 'limit'; + const QUERY_PARAM_ORDER_FIELD = 'order'; + const QUERY_PARAM_ORDER_DIR = 'dir'; + const QUERY_PARAM_FILTER = 'filter'; + /**#@-*/ + + /** @var string */ + protected $_apiType; + + /** + * Set current API type. + * + * @param string $apiType + * @param null|string|Zend_Uri $uri + */ + public function __construct($apiType, $uri = null) + { + $this->setApiType($apiType); + parent::__construct($uri); + } + + /** + * Get current API type. + * + * @return string + */ + public function getApiType() + { + return $this->_apiType; + } + + /** + * Set current API type. + * + * @param string $apiType + */ + public function setApiType($apiType) + { + $this->_apiType = $apiType; + } + + /** + * Get filter settings passed by API user. + * + * @return mixed + */ + public function getFilter() + { + return $this->getQuery(self::QUERY_PARAM_FILTER); + } + + /** + * Get sort order direction requested by API user. + * + * @return mixed + */ + public function getOrderDirection() + { + return $this->getQuery(self::QUERY_PARAM_ORDER_DIR); + } + + /** + * Get sort order field requested by API user. + * + * @return mixed + */ + public function getOrderField() + { + return $this->getQuery(self::QUERY_PARAM_ORDER_FIELD); + } + + /** + * Retrieve page number requested by API user. + * + * @return mixed + */ + public function getPageNumber() + { + return $this->getQuery(self::QUERY_PARAM_PAGE_NUM); + } + + /** + * Retrieve page size requested by API user. + * + * @return mixed + */ + public function getPageSize() + { + return $this->getQuery(self::QUERY_PARAM_PAGE_SIZE); + } + + /** + * Get an array of attribute codes requested by API user. + * + * @return array + */ + public function getRequestedAttributes() + { + $include = $this->getQuery(self::QUERY_PARAM_REQ_ATTRS, array()); + + //transform comma-separated list + if (!is_array($include)) { + $include = explode(',', $include); + } + return array_map('trim', $include); + } +} diff --git a/app/code/core/Mage/Webapi/Controller/Request/Factory.php b/app/code/core/Mage/Webapi/Controller/Request/Factory.php new file mode 100644 index 0000000000000000000000000000000000000000..1fd912b9541b9a57e279adbbf984451ee7a99727 --- /dev/null +++ b/app/code/core/Mage/Webapi/Controller/Request/Factory.php @@ -0,0 +1,77 @@ +<?php +/** + * Factory of web API requests. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Controller_Request_Factory +{ + /** + * List of request classes corresponding to API types. + * + * @var array + */ + protected $_apiTypeToRequestMap = array( + Mage_Webapi_Controller_Front::API_TYPE_REST => 'Mage_Webapi_Controller_Request_Rest', + Mage_Webapi_Controller_Front::API_TYPE_SOAP => 'Mage_Webapi_Controller_Request_Soap', + ); + + /** @var Magento_ObjectManager */ + protected $_objectManager; + + /** @var Mage_Webapi_Controller_Front */ + protected $_apiFrontController; + + /** + * Initialize dependencies. + * + * @param Mage_Webapi_Controller_Front $apiFrontController + * @param Magento_ObjectManager $objectManager + */ + public function __construct( + Mage_Webapi_Controller_Front $apiFrontController, + Magento_ObjectManager $objectManager + ) { + $this->_apiFrontController = $apiFrontController; + $this->_objectManager = $objectManager; + } + + /** + * Create request object. + * + * Use current API type to define proper request class. + * + * @return Mage_Webapi_Controller_Request + * @throws LogicException If there is no corresponding request class for current API type. + */ + public function get() + { + $apiType = $this->_apiFrontController->determineApiType(); + if (!isset($this->_apiTypeToRequestMap[$apiType])) { + throw new LogicException( + sprintf('There is no corresponding request class for the "%s" API type.', $apiType) + ); + } + $requestClass = $this->_apiTypeToRequestMap[$apiType]; + return $this->_objectManager->get($requestClass); + } +} diff --git a/app/code/core/Mage/Webapi/Controller/Request/Rest.php b/app/code/core/Mage/Webapi/Controller/Request/Rest.php new file mode 100644 index 0000000000000000000000000000000000000000..a70d533696c035d4a9bf5f448621406cca159f89 --- /dev/null +++ b/app/code/core/Mage/Webapi/Controller/Request/Rest.php @@ -0,0 +1,344 @@ +<?php +/** + * REST API request. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Controller_Request_Rest extends Mage_Webapi_Controller_Request +{ + /** + * Character set which must be used in request. + */ + const REQUEST_CHARSET = 'utf-8'; + + /**#@+ + * HTTP methods supported by REST. + */ + const HTTP_METHOD_CREATE = 'create'; + const HTTP_METHOD_GET = 'get'; + const HTTP_METHOD_UPDATE = 'update'; + const HTTP_METHOD_DELETE = 'delete'; + /**#@-*/ + + /**#@+ + * Resource types. + */ + const ACTION_TYPE_ITEM = 'item'; + const ACTION_TYPE_COLLECTION = 'collection'; + /**#@-*/ + + /** @var string */ + protected $_resourceName; + + /** @var string */ + protected $_resourceType; + + /** @var string */ + protected $_resourceVersion; + + /** + * @var Mage_Webapi_Controller_Request_Rest_InterpreterInterface + */ + protected $_interpreter; + + /** @var array */ + protected $_bodyParams; + + /** @var Mage_Webapi_Helper_Data */ + protected $_helper; + + /** @var Mage_Webapi_Controller_Request_Rest_Interpreter_Factory */ + protected $_interpreterFactory; + + /** + * Initialize dependencies. + * + * @param Mage_Webapi_Controller_Request_Rest_Interpreter_Factory $interpreterFactory + * @param Mage_Webapi_Helper_Data $helper + * @param string|null $uri + */ + public function __construct( + Mage_Webapi_Controller_Request_Rest_Interpreter_Factory $interpreterFactory, + Mage_Webapi_Helper_Data $helper, + $uri = null + ) { + parent::__construct(Mage_Webapi_Controller_Front::API_TYPE_REST, $uri); + $this->_helper = $helper; + $this->_interpreterFactory = $interpreterFactory; + } + + /** + * Get request interpreter. + * + * @return Mage_Webapi_Controller_Request_Rest_InterpreterInterface + */ + protected function _getInterpreter() + { + if (null === $this->_interpreter) { + $this->_interpreter = $this->_interpreterFactory->get($this->getContentType()); + } + return $this->_interpreter; + } + + /** + * Retrieve accept types understandable by requester in a form of array sorted by quality in descending order. + * + * @return array + */ + public function getAcceptTypes() + { + $qualityToTypes = array(); + $orderedTypes = array(); + + foreach (preg_split('/,\s*/', $this->getHeader('Accept')) as $definition) { + $typeWithQ = explode(';', $definition); + $mimeType = trim(array_shift($typeWithQ)); + + // check MIME type validity + if (!preg_match('~^([0-9a-z*+\-]+)(?:/([0-9a-z*+\-\.]+))?$~i', $mimeType)) { + continue; + } + $quality = '1.0'; // default value for quality + + if ($typeWithQ) { + $qAndValue = explode('=', $typeWithQ[0]); + + if (2 == count($qAndValue)) { + $quality = $qAndValue[1]; + } + } + $qualityToTypes[$quality][$mimeType] = true; + } + krsort($qualityToTypes); + + foreach ($qualityToTypes as $typeList) { + $orderedTypes += $typeList; + } + return array_keys($orderedTypes); + } + + /** + * Fetch data from HTTP Request body. + * + * @return array + */ + public function getBodyParams() + { + if (null == $this->_bodyParams) { + $this->_bodyParams = $this->_getInterpreter()->interpret((string)$this->getRawBody()); + } + return $this->_bodyParams; + } + + /** + * Get Content-Type of request. + * + * @return string + * @throws Mage_Webapi_Exception + */ + public function getContentType() + { + $headerValue = $this->getHeader('Content-Type'); + + if (!$headerValue) { + throw new Mage_Webapi_Exception($this->_helper->__('Content-Type header is empty'), + Mage_Webapi_Exception::HTTP_BAD_REQUEST); + } + if (!preg_match('~^([a-z\d/\-+.]+)(?:; *charset=(.+))?$~Ui', $headerValue, $matches)) { + throw new Mage_Webapi_Exception($this->_helper->__('Invalid Content-Type header'), + Mage_Webapi_Exception::HTTP_BAD_REQUEST); + } + // request encoding check if it is specified in header + if (isset($matches[2]) && self::REQUEST_CHARSET != strtolower($matches[2])) { + throw new Mage_Webapi_Exception($this->_helper->__('UTF-8 is the only supported charset'), + Mage_Webapi_Exception::HTTP_BAD_REQUEST); + } + + return $matches[1]; + } + + /** + * Retrieve one of CRUD operations depending on HTTP method. + * + * @return string + * @throws Mage_Webapi_Exception + */ + public function getHttpMethod() + { + if (!$this->isGet() && !$this->isPost() && !$this->isPut() && !$this->isDelete()) { + throw new Mage_Webapi_Exception($this->_helper->__('Invalid request method'), + Mage_Webapi_Exception::HTTP_BAD_REQUEST); + } + // Map HTTP methods to classic CRUD verbs + $operationByMethod = array( + 'GET' => self::HTTP_METHOD_GET, + 'POST' => self::HTTP_METHOD_CREATE, + 'PUT' => self::HTTP_METHOD_UPDATE, + 'DELETE' => self::HTTP_METHOD_DELETE + ); + + return $operationByMethod[$this->getMethod()]; + } + + /** + * Retrieve resource type. + * + * @return string + */ + public function getResourceName() + { + return $this->_resourceName; + } + + /** + * Set resource type. + * + * @param string $resourceName + */ + public function setResourceName($resourceName) + { + $this->_resourceName = $resourceName; + } + + /** + * Retrieve action type. + * + * @return string|null + */ + public function getResourceType() + { + return $this->_resourceType; + } + + /** + * Set resource type. + * + * @param string $resourceType + */ + public function setResourceType($resourceType) + { + $this->_resourceType = $resourceType; + } + + /** + * Retrieve action version. + * + * @return int + * @throws LogicException If resource version cannot be identified. + */ + public function getResourceVersion() + { + if (!$this->_resourceVersion) { + $this->setResourceVersion($this->getParam(Mage_Webapi_Controller_Router_Route_Rest::PARAM_VERSION)); + } + return $this->_resourceVersion; + } + + /** + * Set resource version. + * + * @param string|int $resourceVersion Version number either with prefix or without it + * @throws Mage_Webapi_Exception + * @return Mage_Webapi_Controller_Request_Rest + */ + public function setResourceVersion($resourceVersion) + { + $versionPrefix = Mage_Webapi_Model_ConfigAbstract::VERSION_NUMBER_PREFIX; + if (preg_match("/^{$versionPrefix}?(\d+)$/i", $resourceVersion, $matches)) { + $versionNumber = (int)$matches[1]; + } else { + throw new Mage_Webapi_Exception( + $this->_helper->__("Resource version is not specified or invalid one is specified."), + Mage_Webapi_Exception::HTTP_BAD_REQUEST + ); + } + $this->_resourceVersion = $versionNumber; + return $this; + } + + /** + * Identify operation name according to HTTP request parameters. + * + * @return string + * @throws Mage_Webapi_Exception + */ + public function getOperationName() + { + $restMethodsMap = array( + self::ACTION_TYPE_COLLECTION . self::HTTP_METHOD_CREATE => + Mage_Webapi_Controller_ActionAbstract::METHOD_CREATE, + self::ACTION_TYPE_COLLECTION . self::HTTP_METHOD_GET => + Mage_Webapi_Controller_ActionAbstract::METHOD_LIST, + self::ACTION_TYPE_COLLECTION . self::HTTP_METHOD_UPDATE => + Mage_Webapi_Controller_ActionAbstract::METHOD_MULTI_UPDATE, + self::ACTION_TYPE_COLLECTION . self::HTTP_METHOD_DELETE => + Mage_Webapi_Controller_ActionAbstract::METHOD_MULTI_DELETE, + self::ACTION_TYPE_ITEM . self::HTTP_METHOD_GET => Mage_Webapi_Controller_ActionAbstract::METHOD_GET, + self::ACTION_TYPE_ITEM . self::HTTP_METHOD_UPDATE => Mage_Webapi_Controller_ActionAbstract::METHOD_UPDATE, + self::ACTION_TYPE_ITEM . self::HTTP_METHOD_DELETE => Mage_Webapi_Controller_ActionAbstract::METHOD_DELETE, + ); + $httpMethod = $this->getHttpMethod(); + $resourceType = $this->getResourceType(); + if (!isset($restMethodsMap[$resourceType . $httpMethod])) { + throw new Mage_Webapi_Exception($this->_helper->__('Requested method does not exist.'), + Mage_Webapi_Exception::HTTP_NOT_FOUND); + } + $methodName = $restMethodsMap[$resourceType . $httpMethod]; + if ($methodName == self::HTTP_METHOD_CREATE) { + /** If request is numeric array, multi create operation must be used. */ + $params = $this->getBodyParams(); + if (count($params)) { + $keys = array_keys($params); + if (is_numeric($keys[0])) { + $methodName = Mage_Webapi_Controller_ActionAbstract::METHOD_MULTI_CREATE; + } + } + } + $operationName = $this->getResourceName() . ucfirst($methodName); + return $operationName; + } + + /** + * Identify resource type by operation name. + * + * @param string $operation + * @return string 'collection' or 'item' + * @throws InvalidArgumentException When method does not match the list of allowed methods + */ + public static function getActionTypeByOperation($operation) + { + $actionTypeMap = array( + Mage_Webapi_Controller_ActionAbstract::METHOD_CREATE => self::ACTION_TYPE_COLLECTION, + Mage_Webapi_Controller_ActionAbstract::METHOD_MULTI_CREATE => self::ACTION_TYPE_COLLECTION, + Mage_Webapi_Controller_ActionAbstract::METHOD_GET => self::ACTION_TYPE_ITEM, + Mage_Webapi_Controller_ActionAbstract::METHOD_LIST => self::ACTION_TYPE_COLLECTION, + Mage_Webapi_Controller_ActionAbstract::METHOD_UPDATE => self::ACTION_TYPE_ITEM, + Mage_Webapi_Controller_ActionAbstract::METHOD_MULTI_UPDATE => self::ACTION_TYPE_COLLECTION, + Mage_Webapi_Controller_ActionAbstract::METHOD_DELETE => self::ACTION_TYPE_ITEM, + Mage_Webapi_Controller_ActionAbstract::METHOD_MULTI_DELETE => self::ACTION_TYPE_COLLECTION, + ); + if (!isset($actionTypeMap[$operation])) { + throw new InvalidArgumentException(sprintf('The "%s" method is not a valid resource method.', $operation)); + } + return $actionTypeMap[$operation]; + } +} diff --git a/app/code/core/Mage/Webapi/Controller/Request/Rest/Interpreter/Factory.php b/app/code/core/Mage/Webapi/Controller/Request/Rest/Interpreter/Factory.php new file mode 100644 index 0000000000000000000000000000000000000000..6d12ad8434b266ea520493c9500fd11d1291d416 --- /dev/null +++ b/app/code/core/Mage/Webapi/Controller/Request/Rest/Interpreter/Factory.php @@ -0,0 +1,98 @@ +<?php +/** + * Factory of REST request interpreters. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Controller_Request_Rest_Interpreter_Factory +{ + /** + * Request interpret adapters. + */ + const XML_PATH_WEBAPI_REQUEST_INTERPRETERS = 'global/webapi/rest/request/interpreters'; + + /** + * @var Magento_ObjectManager + */ + protected $_objectManager; + + /** @var Mage_Core_Model_Config */ + protected $_applicationConfig; + + /** @var Mage_Webapi_Helper_Data */ + protected $_helper; + + /** @var Mage_Core_Model_Factory_Helper */ + protected $_helperFactory; + + /** + * @param Magento_ObjectManager $objectManager + * @param Mage_Core_Model_Config $applicationConfig + * @param Mage_Core_Model_Factory_Helper $helperFactory + */ + public function __construct( + Magento_ObjectManager $objectManager, + Mage_Core_Model_Config $applicationConfig, + Mage_Core_Model_Factory_Helper $helperFactory + ) { + $this->_objectManager = $objectManager; + $this->_applicationConfig = $applicationConfig; + $this->_helperFactory = $helperFactory; + $this->_helper = $this->_helperFactory->get('Mage_Webapi_Helper_Data'); + } + + /** + * Retrieve proper interpreter for the specified content type. + * + * @param string $contentType + * @return Mage_Webapi_Controller_Request_Rest_InterpreterInterface + * @throws LogicException|Mage_Webapi_Exception + */ + public function get($contentType) + { + $interpretersMetadata = (array)$this->_applicationConfig->getNode(self::XML_PATH_WEBAPI_REQUEST_INTERPRETERS); + if (empty($interpretersMetadata) || !is_array($interpretersMetadata)) { + throw new LogicException('Request interpreter adapter is not set.'); + } + foreach ($interpretersMetadata as $interpreterMetadata) { + $interpreterType = (string)$interpreterMetadata->type; + if ($interpreterType == $contentType) { + $interpreterClass = (string)$interpreterMetadata->model; + break; + } + } + + if (!isset($interpreterClass) || empty($interpreterClass)) { + throw new Mage_Webapi_Exception( + $this->_helper->__('Server cannot understand Content-Type HTTP header media type "%s"', $contentType), + Mage_Webapi_Exception::HTTP_BAD_REQUEST + ); + } + + $interpreter = $this->_objectManager->get($interpreterClass); + if (!$interpreter instanceof Mage_Webapi_Controller_Request_Rest_InterpreterInterface) { + throw new LogicException( + 'The interpreter must implement "Mage_Webapi_Controller_Request_Rest_InterpreterInterface".'); + } + return $interpreter; + } +} diff --git a/app/code/core/Mage/Webapi/Controller/Request/Rest/Interpreter/Json.php b/app/code/core/Mage/Webapi/Controller/Request/Rest/Interpreter/Json.php new file mode 100644 index 0000000000000000000000000000000000000000..f9cf4946caf9fcac7b1f8355ac867929a95fd3e0 --- /dev/null +++ b/app/code/core/Mage/Webapi/Controller/Request/Rest/Interpreter/Json.php @@ -0,0 +1,83 @@ +<?php +/** + * JSON interpreter of REST request content. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Controller_Request_Rest_Interpreter_Json implements + Mage_Webapi_Controller_Request_Rest_InterpreterInterface +{ + /** @var Mage_Webapi_Helper_Data */ + protected $_helper; + + /** @var Mage_Core_Model_Factory_Helper */ + protected $_helperFactory; + + /** @var Mage_Core_Model_App */ + protected $_app; + + /** + * @param Mage_Core_Model_Factory_Helper $helperFactory + * @param Mage_Core_Model_App $app + */ + public function __construct(Mage_Core_Model_Factory_Helper $helperFactory, Mage_Core_Model_App $app) + { + $this->_helperFactory = $helperFactory; + $this->_helper = $this->_helperFactory->get('Mage_Webapi_Helper_Data'); + $this->_app = $app; + } + + /** + * Parse Request body into array of params. + * + * @param string $encodedBody Posted content from request. + * @return array|null Return NULL if content is invalid. + * @throws InvalidArgumentException + * @throws Mage_Webapi_Exception If decoding error was encountered. + */ + public function interpret($encodedBody) + { + if (!is_string($encodedBody)) { + throw new InvalidArgumentException(sprintf( + 'Invalid data type "%s". String is expected.', + gettype($encodedBody) + )); + } + try { + /** @var Mage_Core_Helper_Data $jsonHelper */ + $jsonHelper = $this->_helperFactory->get('Mage_Core_Helper_Data'); + $decodedBody = $jsonHelper->jsonDecode($encodedBody); + } catch (Zend_Json_Exception $e) { + if (!$this->_app->isDeveloperMode()) { + throw new Mage_Webapi_Exception($this->_helper->__('Decoding error.'), + Mage_Webapi_Exception::HTTP_BAD_REQUEST); + } else { + throw new Mage_Webapi_Exception( + 'Decoding error: ' . PHP_EOL . $e->getMessage() . PHP_EOL . $e->getTraceAsString(), + Mage_Webapi_Exception::HTTP_BAD_REQUEST + ); + } + + } + return $decodedBody; + } +} diff --git a/app/code/core/Mage/Webapi/Controller/Request/Rest/Interpreter/Xml.php b/app/code/core/Mage/Webapi/Controller/Request/Rest/Interpreter/Xml.php new file mode 100644 index 0000000000000000000000000000000000000000..f1f50ba936ddbfab2674d48ef28a2ed1ca27b065 --- /dev/null +++ b/app/code/core/Mage/Webapi/Controller/Request/Rest/Interpreter/Xml.php @@ -0,0 +1,123 @@ +<?php +/** + * XML interpreter of REST request content. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Controller_Request_Rest_Interpreter_Xml implements + Mage_Webapi_Controller_Request_Rest_InterpreterInterface +{ + /** @var Mage_Webapi_Helper_Data */ + protected $_helper; + + /** @var Mage_Core_Model_Factory_Helper */ + protected $_helperFactory; + + /** @var Mage_Xml_Parser */ + protected $_xmlParser; + + /** @var Mage_Core_Model_App */ + protected $_app; + + /** + * Initialize dependencies. + * + * @param Mage_Xml_Parser $xmlParser + * @param Mage_Core_Model_Factory_Helper $helperFactory + * @param Mage_Core_Model_App $app + */ + public function __construct( + Mage_Xml_Parser $xmlParser, + Mage_Core_Model_Factory_Helper $helperFactory, + Mage_Core_Model_App $app + ) { + $this->_xmlParser = $xmlParser; + $this->_helperFactory = $helperFactory; + $this->_helper = $this->_helperFactory->get('Mage_Webapi_Helper_Data'); + $this->_app = $app; + } + + /** + * Load error string. + * + * Is null if there was no error while loading + * + * @var string + */ + protected $_errorMessage = null; + + /** + * Convert XML document into array. + * + * @param string $xmlRequestBody XML document + * @return array Data converted from XML document to array. Root node is excluded from response. + * @throws InvalidArgumentException In case of invalid argument type. + * @throws Mage_Webapi_Exception If decoding error occurs. + */ + public function interpret($xmlRequestBody) + { + if (!is_string($xmlRequestBody)) { + throw new InvalidArgumentException( + sprintf('Invalid data type "%s". String is expected.', gettype($xmlRequestBody)) + ); + } + /** Disable external entity loading to prevent possible vulnerability */ + $previousLoaderState = libxml_disable_entity_loader(true); + set_error_handler(array($this, 'handleErrors')); + + $this->_xmlParser->loadXML($xmlRequestBody); + + restore_error_handler(); + libxml_disable_entity_loader($previousLoaderState); + + /** Process errors during XML parsing. */ + if ($this->_errorMessage !== null) { + if (!$this->_app->isDeveloperMode()) { + $exceptionMessage = $this->_helper->__('Decoding error.'); + } else { + $exceptionMessage = 'Decoding Error: ' . $this->_errorMessage; + } + throw new Mage_Webapi_Exception($exceptionMessage, Mage_Webapi_Exception::HTTP_BAD_REQUEST); + } + $data = $this->_xmlParser->xmlToArray(); + /** Data will always have exactly one element so it is safe to call reset here. */ + return reset($data); + } + + /** + * Handle any errors during XML loading. + * + * @param integer $errorNumber + * @param string $errorMessage + * @param string $errorFile + * @param integer $errorLine + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function handleErrors($errorNumber, $errorMessage, $errorFile, $errorLine) + { + if (is_null($this->_errorMessage)) { + $this->_errorMessage = $errorMessage; + } else { + $this->_errorMessage .= $errorMessage; + } + } +} diff --git a/app/code/core/Mage/Webapi/Controller/Request/Rest/InterpreterInterface.php b/app/code/core/Mage/Webapi/Controller/Request/Rest/InterpreterInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..e8807e21ff14fd6b0b27d7be307f65cece34e7a9 --- /dev/null +++ b/app/code/core/Mage/Webapi/Controller/Request/Rest/InterpreterInterface.php @@ -0,0 +1,35 @@ +<?php +/** + * Interface of REST request content interpreter. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +interface Mage_Webapi_Controller_Request_Rest_InterpreterInterface +{ + /** + * Parse request body into array of params. + * + * @param string $body Posted content from request + * @return array|null Return NULL if content is invalid + */ + public function interpret($body); +} diff --git a/app/code/core/Mage/Webapi/Controller/Request/Soap.php b/app/code/core/Mage/Webapi/Controller/Request/Soap.php new file mode 100644 index 0000000000000000000000000000000000000000..241d7856cf76e2e20384b4ab2479ab5a7c583f9b --- /dev/null +++ b/app/code/core/Mage/Webapi/Controller/Request/Soap.php @@ -0,0 +1,69 @@ +<?php +/** + * Soap API request. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Controller_Request_Soap extends Mage_Webapi_Controller_Request +{ + /** @var Mage_Webapi_Helper_Data */ + protected $_helper; + + /** + * Initialize dependencies. + * + * @param Mage_Webapi_Helper_Data $helper + * @param string|null $uri + */ + public function __construct(Mage_Webapi_Helper_Data $helper, $uri = null) + { + parent::__construct(Mage_Webapi_Controller_Front::API_TYPE_SOAP, $uri); + $this->_helper = $helper; + } + + /** + * Identify versions of resources that should be used for API configuration generation. + * + * @return array + * @throws Mage_Webapi_Exception When GET parameters are invalid + */ + public function getRequestedResources() + { + $wsdlParam = Mage_Webapi_Model_Soap_Server::REQUEST_PARAM_WSDL; + $resourcesParam = Mage_Webapi_Model_Soap_Server::REQUEST_PARAM_RESOURCES; + $requestParams = array_keys($this->getParams()); + $allowedParams = array(Mage_Webapi_Controller_Router_Route_Webapi::PARAM_API_TYPE, $wsdlParam, $resourcesParam); + $notAllowedParameters = array_diff($requestParams, $allowedParams); + if (count($notAllowedParameters)) { + $message = $this->_helper->__('Not allowed parameters: %s. ', implode(', ', $notAllowedParameters)) + . $this->_helper->__('Please use only "%s" and "%s".', $wsdlParam, $resourcesParam); + throw new Mage_Webapi_Exception($message, Mage_Webapi_Exception::HTTP_BAD_REQUEST); + } + + $requestedResources = $this->getParam($resourcesParam); + if (empty($requestedResources) || !is_array($requestedResources)) { + $message = $this->_helper->__('Requested resources are missing.'); + throw new Mage_Webapi_Exception($message, Mage_Webapi_Exception::HTTP_BAD_REQUEST); + } + return $requestedResources; + } +} diff --git a/app/code/core/Mage/Api2/Model/Response.php b/app/code/core/Mage/Webapi/Controller/Response.php similarity index 70% rename from app/code/core/Mage/Api2/Model/Response.php rename to app/code/core/Mage/Webapi/Controller/Response.php index b6d15674fe9671a4d280345067525dd4ecbccdf4..7ff56abd8482f732254f788c2e12cb9da8ade63b 100644 --- a/app/code/core/Mage/Api2/Model/Response.php +++ b/app/code/core/Mage/Webapi/Controller/Response.php @@ -1,5 +1,7 @@ <?php /** + * Web API response. + * * Magento * * NOTICE OF LICENSE @@ -18,46 +20,36 @@ * versions in the future. If you wish to customize Magento for your * needs please refer to http://www.magentocommerce.com for more information. * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * API Response model - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -class Mage_Api2_Model_Response extends Zend_Controller_Response_Http +class Mage_Webapi_Controller_Response extends Zend_Controller_Response_Http { /** - * Character set which must be used in response + * Character set which must be used in response. */ const RESPONSE_CHARSET = 'utf-8'; /**#@+ - * Default message types + * Default message types. */ const MESSAGE_TYPE_SUCCESS = 'success'; - const MESSAGE_TYPE_ERROR = 'error'; + const MESSAGE_TYPE_ERROR = 'error'; const MESSAGE_TYPE_WARNING = 'warning'; /**#@- */ /** - * Messages + * Messages. * * @var array */ protected $_messages = array(); /** - * Set header appropriate to specified MIME type + * Set header appropriate to specified MIME type. * * @param string $mimeType MIME type - * @return Mage_Api2_Model_Response + * @return Mage_Webapi_Controller_Response */ public function setMimeType($mimeType) { @@ -65,13 +57,13 @@ class Mage_Api2_Model_Response extends Zend_Controller_Response_Http } /** - * Add message to responce + * Add message to response. * * @param string $message * @param string $code * @param array $params * @param string $type - * return Mage_Api2_Model_Response + * @return Mage_Webapi_Controller_Response */ public function addMessage($message, $code, $params = array(), $type = self::MESSAGE_TYPE_ERROR) { @@ -82,7 +74,7 @@ class Mage_Api2_Model_Response extends Zend_Controller_Response_Http } /** - * Has messages + * Has messages. * * @return bool */ @@ -92,7 +84,7 @@ class Mage_Api2_Model_Response extends Zend_Controller_Response_Http } /** - * Return messages + * Return messages. * * @return array */ @@ -102,9 +94,9 @@ class Mage_Api2_Model_Response extends Zend_Controller_Response_Http } /** - * Clear messages + * Clear messages. * - * return Mage_Api2_Model_Response + * @return Mage_Webapi_Controller_Response */ public function clearMessages() { diff --git a/app/code/core/Mage/Webapi/Controller/Response/Factory.php b/app/code/core/Mage/Webapi/Controller/Response/Factory.php new file mode 100644 index 0000000000000000000000000000000000000000..08947050ea66bf4cda4dceba47bfde29144be960 --- /dev/null +++ b/app/code/core/Mage/Webapi/Controller/Response/Factory.php @@ -0,0 +1,77 @@ +<?php +/** + * Factory of web API requests. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Controller_Response_Factory +{ + /** + * List of response classes corresponding to API types. + * + * @var array + */ + protected $_apiResponseMap = array( + Mage_Webapi_Controller_Front::API_TYPE_REST => 'Mage_Webapi_Controller_Response_Rest', + Mage_Webapi_Controller_Front::API_TYPE_SOAP => 'Mage_Webapi_Controller_Response', + ); + + /** @var Magento_ObjectManager */ + protected $_objectManager; + + /** @var Mage_Webapi_Controller_Front */ + protected $_apiFrontController; + + /** + * Initialize dependencies. + * + * @param Mage_Webapi_Controller_Front $apiFrontController + * @param Magento_ObjectManager $objectManager + */ + public function __construct( + Mage_Webapi_Controller_Front $apiFrontController, + Magento_ObjectManager $objectManager + ) { + $this->_apiFrontController = $apiFrontController; + $this->_objectManager = $objectManager; + } + + /** + * Create response object. + * + * Use current API type to define proper response class. + * + * @return Mage_Webapi_Controller_Response + * @throws LogicException If there is no corresponding response class for current API type. + */ + public function get() + { + $apiType = $this->_apiFrontController->determineApiType(); + if (!isset($this->_apiResponseMap[$apiType])) { + throw new LogicException( + sprintf('There is no corresponding response class for the "%s" API type.', $apiType) + ); + } + $requestClass = $this->_apiResponseMap[$apiType]; + return $this->_objectManager->get($requestClass); + } +} diff --git a/app/code/core/Mage/Webapi/Controller/Response/Rest.php b/app/code/core/Mage/Webapi/Controller/Response/Rest.php new file mode 100644 index 0000000000000000000000000000000000000000..e3a2670b470cc68e2c646dc372148e60c39d4f69 --- /dev/null +++ b/app/code/core/Mage/Webapi/Controller/Response/Rest.php @@ -0,0 +1,129 @@ +<?php +/** + * Web API REST response. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Controller_Response_Rest extends Mage_Webapi_Controller_Response +{ + /**#@+ + * Success HTTP response codes. + */ + const HTTP_OK = 200; + const HTTP_CREATED = 201; + const HTTP_MULTI_STATUS = 207; + /**#@-*/ + + /** @var Mage_Webapi_Controller_Dispatcher_ErrorProcessor */ + protected $_errorProcessor; + + /** @var Mage_Webapi_Controller_Response_Rest_RendererInterface */ + protected $_renderer; + + /** @var Mage_Webapi_Helper_Data */ + protected $_helper; + + /** @var Mage_Core_Model_App */ + protected $_app; + + /** + * Initialize dependencies. + * + * @param Mage_Webapi_Controller_Response_Rest_Renderer_Factory $rendererFactory + * @param Mage_Webapi_Controller_Dispatcher_ErrorProcessor $errorProcessor + * @param Mage_Webapi_Helper_Data $helper + * @param Mage_Core_Model_App $app + */ + public function __construct( + Mage_Webapi_Controller_Response_Rest_Renderer_Factory $rendererFactory, + Mage_Webapi_Controller_Dispatcher_ErrorProcessor $errorProcessor, + Mage_Webapi_Helper_Data $helper, + Mage_Core_Model_App $app + ) { + $this->_renderer = $rendererFactory->get(); + $this->_errorProcessor = $errorProcessor; + $this->_helper = $helper; + $this->_app = $app; + } + + /** + * Add exception to the list of exceptions. + * + * Replace real error message of untrusted exceptions to prevent potential vulnerability. + * + * @param Exception $exception + * @return Mage_Webapi_Controller_Response_Rest + */ + public function setException(Exception $exception) + { + return parent::setException($this->_errorProcessor->maskException($exception)); + } + + /** + * Send response to the client, render exceptions if they are present. + */ + public function sendResponse() + { + try { + if ($this->isException()) { + $this->_renderMessages(); + } + parent::sendResponse(); + } catch (Exception $e) { + // If the server does not support all MIME types accepted by the client it SHOULD send 406 (not acceptable). + $httpCode = $e->getCode() == Mage_Webapi_Exception::HTTP_NOT_ACCEPTABLE + ? Mage_Webapi_Exception::HTTP_NOT_ACCEPTABLE + : Mage_Webapi_Exception::HTTP_INTERNAL_ERROR; + + /** If error was encountered during "error rendering" process then use error renderer. */ + $this->_errorProcessor->renderException($e, $httpCode); + } + } + + /** + * Generate and set HTTP response code, error messages to Response object. + */ + protected function _renderMessages() + { + $formattedMessages = array(); + $formattedMessages['messages'] = $this->getMessages(); + $responseHttpCode = null; + /** @var Exception $exception */ + foreach ($this->getException() as $exception) { + $code = ($exception instanceof Mage_Webapi_Exception) + ? $exception->getCode() + : Mage_Webapi_Exception::HTTP_INTERNAL_ERROR; + $messageData = array('code' => $code, 'message' => $exception->getMessage()); + if ($this->_app->isDeveloperMode()) { + $messageData['trace'] = $exception->getTraceAsString(); + } + $formattedMessages['messages']['error'][] = $messageData; + // keep HTTP code for response + $responseHttpCode = $code; + } + // set HTTP code of the last error, Content-Type, and all rendered error messages to body + $this->setHttpResponseCode($responseHttpCode); + $this->setMimeType($this->_renderer->getMimeType()); + $this->setBody($this->_renderer->render($formattedMessages)); + return $this; + } +} diff --git a/app/code/core/Mage/Webapi/Controller/Response/Rest/Renderer/Factory.php b/app/code/core/Mage/Webapi/Controller/Response/Rest/Renderer/Factory.php new file mode 100644 index 0000000000000000000000000000000000000000..5e955059899a03d1cd65f353184c0bb63aee45c3 --- /dev/null +++ b/app/code/core/Mage/Webapi/Controller/Response/Rest/Renderer/Factory.php @@ -0,0 +1,107 @@ +<?php +/** + * Factory of REST renderers. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Controller_Response_Rest_Renderer_Factory +{ + /** + * Response render adapters. + */ + const XML_PATH_WEBAPI_RESPONSE_RENDERS = 'global/webapi/rest/response/renders'; + + /** + * @var Magento_ObjectManager + */ + protected $_objectManager; + + /** @var Mage_Core_Model_Config */ + protected $_applicationConfig; + + /** @var Mage_Webapi_Helper_Data */ + protected $_helper; + + /** @var Mage_Webapi_Controller_Request_Rest */ + protected $_request; + + /** + * Initialize dependencies. + * + * @param Magento_ObjectManager $objectManager + * @param Mage_Core_Model_Config $applicationConfig + * @param Mage_Core_Model_Factory_Helper $helperFactory + * @param Mage_Webapi_Controller_Request_Rest $request + */ + public function __construct( + Magento_ObjectManager $objectManager, + Mage_Core_Model_Config $applicationConfig, + Mage_Core_Model_Factory_Helper $helperFactory, + Mage_Webapi_Controller_Request_Rest $request + ) { + $this->_objectManager = $objectManager; + $this->_applicationConfig = $applicationConfig; + $this->_helper = $helperFactory->get('Mage_Webapi_Helper_Data'); + $this->_request = $request; + } + + /** + * Get renderer for Mime-Type specified in Accept header of request. + * + * @return Mage_Webapi_Controller_Response_Rest_RendererInterface + * @throws Mage_Webapi_Exception + * @throws LogicException + */ + public function get() + { + $acceptTypes = $this->_request->getAcceptTypes(); + $availableRenderers = (array)$this->_applicationConfig->getNode(self::XML_PATH_WEBAPI_RESPONSE_RENDERS); + if (!is_array($acceptTypes)) { + $acceptTypes = array($acceptTypes); + } + foreach ($acceptTypes as $acceptType) { + foreach ($availableRenderers as $rendererConfig) { + $rendererType = (string)$rendererConfig->type; + if ($acceptType == $rendererType + || ($acceptType == current(explode('/', $rendererType)) . '/*') + || $acceptType == '*/*' + ) { + $rendererClass = (string)$rendererConfig->model; + break 2; + } + } + } + if (!isset($rendererClass)) { + /** If server does not have renderer for any of the accepted types it SHOULD send 406 (not acceptable). */ + throw new Mage_Webapi_Exception( + $this->_helper->__('Server cannot understand Accept HTTP header media type.'), + Mage_Webapi_Exception::HTTP_NOT_ACCEPTABLE + ); + } + $renderer = $this->_objectManager->get($rendererClass); + if (!$renderer instanceof Mage_Webapi_Controller_Response_Rest_RendererInterface) { + throw new LogicException( + 'The renderer must implement "Mage_Webapi_Controller_Response_Rest_RendererInterface".'); + } + return $renderer; + } +} diff --git a/app/code/core/Mage/Api2/Model/Renderer/Json.php b/app/code/core/Mage/Webapi/Controller/Response/Rest/Renderer/Json.php similarity index 54% rename from app/code/core/Mage/Api2/Model/Renderer/Json.php rename to app/code/core/Mage/Webapi/Controller/Response/Rest/Renderer/Json.php index 848790390cf70f7b773680080a4c79b2bb9aec67..4e60de9f3a9c3144e59d1ae6277c556a0071ff9b 100644 --- a/app/code/core/Mage/Api2/Model/Renderer/Json.php +++ b/app/code/core/Mage/Webapi/Controller/Response/Rest/Renderer/Json.php @@ -1,5 +1,7 @@ <?php /** + * JSON Renderer allows to format array or object as JSON document. + * * Magento * * NOTICE OF LICENSE @@ -18,39 +20,44 @@ * versions in the future. If you wish to customize Magento for your * needs please refer to http://www.magentocommerce.com for more information. * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Webservice API2 renderer of JSON type model - * - * @category Mage - * @package Mage_Api2 - * @author Magento Core Team <core@magentocommerce.com> + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -class Mage_Api2_Model_Renderer_Json implements Mage_Api2_Model_Renderer_Interface +class Mage_Webapi_Controller_Response_Rest_Renderer_Json implements + Mage_Webapi_Controller_Response_Rest_RendererInterface { /** - * Adapter mime type + * Adapter mime type. */ const MIME_TYPE = 'application/json'; + /** @var Mage_Core_Helper_Data */ + protected $_helper; + + /** + * Initialize dependencies. + * + * @param Mage_Core_Model_Factory_Helper $helperFactory + */ + public function __construct( + Mage_Core_Model_Factory_Helper $helperFactory + ) { + $this->_helper = $helperFactory->get('Mage_Core_Helper_Data'); + } + /** - * Convert Array to JSON + * Convert data to JSON. * * @param array|object $data * @return string */ public function render($data) { - return Zend_Json::encode($data); + return $this->_helper->jsonEncode($data); } /** - * Get MIME type generated by renderer + * Get JSON renderer MIME type. * * @return string */ diff --git a/app/code/core/Mage/Webapi/Controller/Response/Rest/Renderer/Xml.php b/app/code/core/Mage/Webapi/Controller/Response/Rest/Renderer/Xml.php new file mode 100644 index 0000000000000000000000000000000000000000..23a6898d82518a65b7768cb52fcd2b598019489b --- /dev/null +++ b/app/code/core/Mage/Webapi/Controller/Response/Rest/Renderer/Xml.php @@ -0,0 +1,179 @@ +<?php +/** + * XML Renderer allows to format array or object as valid XML document. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Controller_Response_Rest_Renderer_Xml implements + Mage_Webapi_Controller_Response_Rest_RendererInterface +{ + /** + * Renderer mime type. + */ + const MIME_TYPE = 'application/xml'; + + /** + * Root node in XML output. + */ + const XML_ROOT_NODE = 'response'; + + /** + * This value is used to replace numeric keys while formatting data for XML output. + */ + const DEFAULT_ENTITY_ITEM_NAME = 'item'; + + /** @var Mage_Xml_Generator */ + protected $_xmlGenerator; + + /** + * Initialize dependencies. + * + * @param Mage_Xml_Generator $xmlGenerator + */ + public function __construct(Mage_Xml_Generator $xmlGenerator) + { + $this->_xmlGenerator = $xmlGenerator; + } + + /** + * Get XML renderer MIME type. + * + * @return string + */ + public function getMimeType() + { + return self::MIME_TYPE; + } + + /** + * Format object|array to valid XML. + * + * @param array|Varien_Object $data + * @return string + */ + public function render($data) + { + $formattedData = $this->_formatData($data, true); + /** Wrap response in a single node. */ + $formattedData = array(self::XML_ROOT_NODE => $formattedData); + $this->_xmlGenerator->setIndexedArrayItemName(self::DEFAULT_ENTITY_ITEM_NAME)->arrayToXml($formattedData); + return $this->_xmlGenerator->getDom()->saveXML(); + } + + /** + * Reformat mixed data to multidimensional array. + * + * This method is recursive. + * + * @param array|Varien_Object $data + * @param bool $isRoot + * @return array + * @throws InvalidArgumentException + */ + protected function _formatData($data, $isRoot = false) + { + if (!is_array($data) && !is_object($data)) { + if ($isRoot) { + $data = array($data); + } + } elseif ($data instanceof Varien_Object) { + $data = $data->toArray(); + } else { + $data = (array)$data; + } + $isAssoc = !preg_match('/^\d+$/', implode(array_keys($data), '')); + + $formattedData = array(); + foreach ($data as $key => $value) { + $value = is_array($value) || is_object($value) ? $this->_formatData($value) : $this->_formatValue($value); + if ($isAssoc) { + $formattedData[$this->_prepareKey($key)] = $value; + } else { + $formattedData[] = $value; + } + } + return $formattedData; + } + + /** + * Prepare value in contrast with key. + * + * @param string $value + * @return string + */ + protected function _formatValue($value) + { + $replacementMap = array('&' => '&'); + return str_replace(array_keys($replacementMap), array_values($replacementMap), $value); + } + + /** + * Format array key or field name to be valid array key name. + * + * Replaces characters that are invalid in array key names. + * + * @param string $key + * @return string + */ + protected function _prepareKey($key) + { + $replacementMap = array( + '!' => '', + '"' => '', + '#' => '', + '$' => '', + '%' => '', + '&' => '', + '\'' => '', + '(' => '', + ')' => '', + '*' => '', + '+' => '', + ',' => '', + '/' => '', + ';' => '', + '<' => '', + '=' => '', + '>' => '', + '?' => '', + '@' => '', + '[' => '', + '\\' => '', + ']' => '', + '^' => '', + '`' => '', + '{' => '', + '|' => '', + '}' => '', + '~' => '', + ' ' => '_', + ':' => '_' + ); + $key = str_replace(array_keys($replacementMap), array_values($replacementMap), $key); + $key = trim($key, '_'); + $prohibitedTagPattern = '/^[0-9,.-]/'; + if (preg_match($prohibitedTagPattern, $key)) { + $key = self::DEFAULT_ENTITY_ITEM_NAME . '_' . $key; + } + return $key; + } +} diff --git a/app/code/core/Mage/Webapi/Controller/Response/Rest/RendererInterface.php b/app/code/core/Mage/Webapi/Controller/Response/Rest/RendererInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..b3ab1b4d34cdb812d25039e64e2988847aa45a6c --- /dev/null +++ b/app/code/core/Mage/Webapi/Controller/Response/Rest/RendererInterface.php @@ -0,0 +1,42 @@ +<?php +/** + * Interface of REST response renderers. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +interface Mage_Webapi_Controller_Response_Rest_RendererInterface +{ + /** + * Render content in a certain format. + * + * @param array|object $data + * @return string + */ + public function render($data); + + /** + * Get MIME type generated by renderer. + * + * @return string + */ + public function getMimeType(); +} diff --git a/app/code/core/Mage/Webapi/Controller/Router/Rest.php b/app/code/core/Mage/Webapi/Controller/Router/Rest.php new file mode 100644 index 0000000000000000000000000000000000000000..dcd7522d315eb8e947517a1804b3640b9a5b207c --- /dev/null +++ b/app/code/core/Mage/Webapi/Controller/Router/Rest.php @@ -0,0 +1,97 @@ +<?php +/** + * Router for Magento web API. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Controller_Router_Rest +{ + /** @var array */ + protected $_routes = array(); + + /** @var Mage_Webapi_Helper_Data */ + protected $_helper; + + /** @var Mage_Webapi_Model_Config_Rest */ + protected $_apiConfig; + + /** + * Initialize dependencies. + * + * @param Mage_Webapi_Helper_Data $helper + * @param Mage_Webapi_Model_Config_Rest $apiConfig + */ + public function __construct( + Mage_Webapi_Helper_Data $helper, + Mage_Webapi_Model_Config_Rest $apiConfig + ) { + $this->_helper = $helper; + $this->_apiConfig = $apiConfig; + } + + /** + * Route the Request, the only responsibility of the class. + * Find route that matches current URL, set parameters of the route to Request object. + * + * @param Mage_Webapi_Controller_Request_Rest $request + * @return Mage_Webapi_Controller_Router_Route_Rest + * @throws Mage_Webapi_Exception + */ + public function match(Mage_Webapi_Controller_Request_Rest $request) + { + /** @var Mage_Webapi_Controller_Router_Route_Rest[] $routes */ + $routes = $this->_apiConfig->getAllRestRoutes(); + foreach ($routes as $route) { + $params = $route->match($request); + if ($params !== false) { + $request->setParams($params); + /** Initialize additional request parameters using data from route */ + $request->setResourceName($route->getResourceName()); + $request->setResourceType($route->getResourceType()); + return $route; + } + } + throw new Mage_Webapi_Exception($this->_helper->__('Request does not match any route.'), + Mage_Webapi_Exception::HTTP_NOT_FOUND); + } + + /** + * Check whether current request matches any route of specified method or not. Method version is taken into account. + * + * @param Mage_Webapi_Controller_Request_Rest $request + * @param string $methodName + * @param string $version + * @throws Mage_Webapi_Exception In case when request does not match any route of specified method. + */ + public function checkRoute(Mage_Webapi_Controller_Request_Rest $request, $methodName, $version) + { + $resourceName = $request->getResourceName(); + $routes = $this->_apiConfig->getMethodRestRoutes($resourceName, $methodName, $version); + foreach ($routes as $route) { + if ($route->match($request)) { + return; + } + } + throw new Mage_Webapi_Exception($this->_helper->__('Request does not match any route.'), + Mage_Webapi_Exception::HTTP_NOT_FOUND); + } +} diff --git a/app/code/core/Mage/Webapi/Controller/Router/Route/Rest.php b/app/code/core/Mage/Webapi/Controller/Router/Route/Rest.php new file mode 100644 index 0000000000000000000000000000000000000000..72c37bc866c8686716a97be045cd706a0fd290c9 --- /dev/null +++ b/app/code/core/Mage/Webapi/Controller/Router/Route/Rest.php @@ -0,0 +1,85 @@ +<?php +/** + * Route to resources available via REST API. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Controller_Router_Route_Rest extends Mage_Webapi_Controller_Router_RouteAbstract +{ + /**#@+ + * Names of special parameters in routes. + */ + const PARAM_VERSION = 'resourceVersion'; + const PARAM_ID = 'id'; + const PARAM_PARENT_ID = 'parentId'; + /**#@-*/ + + /** @var string */ + protected $_resourceName; + + /** @var string */ + protected $_resourceType; + + /** + * Set route resource. + * + * @param string $resourceName + * @return Mage_Webapi_Controller_Router_Route_Rest + */ + public function setResourceName($resourceName) + { + $this->_resourceName = $resourceName; + return $this; + } + + /** + * Get route resource. + * + * @return string + */ + public function getResourceName() + { + return $this->_resourceName; + } + + /** + * Set route resource type. + * + * @param string $resourceType + * @return Mage_Webapi_Controller_Router_Route_Rest + */ + public function setResourceType($resourceType) + { + $this->_resourceType = $resourceType; + return $this; + } + + /** + * Get route resource type. + * + * @return string + */ + public function getResourceType() + { + return $this->_resourceType; + } +} diff --git a/app/code/core/Mage/Webapi/Controller/Router/Route/Webapi.php b/app/code/core/Mage/Webapi/Controller/Router/Route/Webapi.php new file mode 100644 index 0000000000000000000000000000000000000000..4412ab90dc1a82df2f2b68c9529549f1fa2cb237 --- /dev/null +++ b/app/code/core/Mage/Webapi/Controller/Router/Route/Webapi.php @@ -0,0 +1,40 @@ +<?php +/** + * Route to Magento web API. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Controller_Router_Route_Webapi extends Mage_Webapi_Controller_Router_RouteAbstract +{ + const PARAM_API_TYPE = 'api_type'; + const API_AREA_NAME = 'api'; + + /** + * Retrieve API route. + * + * @return string + */ + public static function getApiRoute() + { + return self::API_AREA_NAME . '/:' . self::PARAM_API_TYPE; + } +} diff --git a/app/code/core/Mage/Webapi/Controller/Router/RouteAbstract.php b/app/code/core/Mage/Webapi/Controller/Router/RouteAbstract.php new file mode 100644 index 0000000000000000000000000000000000000000..a330a9eee4dc49120a5ee9aa52268498f88e5fe1 --- /dev/null +++ b/app/code/core/Mage/Webapi/Controller/Router/RouteAbstract.php @@ -0,0 +1,40 @@ +<?php +/** + * Abstract route for Magento web API. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +abstract class Mage_Webapi_Controller_Router_RouteAbstract extends Zend_Controller_Router_Route +{ + /** + * Matches a Request with parts defined by a map. Assigns and + * returns an array of variables on a successful match. + * + * @param Mage_Webapi_Controller_Request $request + * @param boolean $partial Partial path matching + * @return array|bool An array of assigned values or a boolean false on a mismatch + */ + public function match($request, $partial = false) + { + return parent::match(ltrim($request->getPathInfo(), $this->_urlDelimiter), $partial); + } +} diff --git a/app/code/core/Mage/Webapi/Exception.php b/app/code/core/Mage/Webapi/Exception.php new file mode 100644 index 0000000000000000000000000000000000000000..0cc4835d8497ac97036b744ea61211b1a13c39e7 --- /dev/null +++ b/app/code/core/Mage/Webapi/Exception.php @@ -0,0 +1,68 @@ +<?php +/** + * Webapi module exception. Should be used in web API resources implementation. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Exception extends RuntimeException +{ + /**#@+ + * Error HTTP response codes. + */ + const HTTP_BAD_REQUEST = 400; + const HTTP_UNAUTHORIZED = 401; + const HTTP_FORBIDDEN = 403; + const HTTP_NOT_FOUND = 404; + const HTTP_METHOD_NOT_ALLOWED = 405; + const HTTP_NOT_ACCEPTABLE = 406; + const HTTP_INTERNAL_ERROR = 500; + /**#@-*/ + + const ORIGINATOR_SENDER = 'Sender'; + const ORIGINATOR_RECEIVER = 'Receiver'; + + /** + * Initialize exception with HTTP code. + * + * @param string $message + * @param int $code + * @throws InvalidArgumentException + */ + public function __construct($message, $code) + { + /** Only HTTP error codes are allowed. No success or redirect codes must be used. */ + if ($code < 400 || $code > 599) { + throw new InvalidArgumentException(sprintf('The specified code "%d" is invalid.', $code)); + } + parent::__construct($message, $code); + } + + /** + * Identify exception originator: sender or receiver. + * + * @return string + */ + public function getOriginator() + { + return ($this->getCode() < 500) ? self::ORIGINATOR_SENDER : self::ORIGINATOR_RECEIVER; + } +} diff --git a/app/code/core/Mage/Webapi/Helper/Config.php b/app/code/core/Mage/Webapi/Helper/Config.php new file mode 100644 index 0000000000000000000000000000000000000000..d740e0fddbcf7df2a5b8588265fac83278f3a213 --- /dev/null +++ b/app/code/core/Mage/Webapi/Helper/Config.php @@ -0,0 +1,365 @@ +<?php +use Zend\Server\Reflection\ReflectionMethod; + +/** + * Webapi config helper. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Helper_Config extends Mage_Core_Helper_Abstract +{ + /** + * Convert singular form of word to plural. + * + * @param string $singular + * @return string + */ + public function convertSingularToPlural($singular) + { + $plural = $singular; + $conversionMatrix = array( + '/(x|ch|ss|sh)$/i' => "$1es", + '/([^aeiouy]|qu)y$/i' => "$1ies", + '/s$/i' => "s", + /** Add 's' to any string longer than 0 characters */ + '/(.+)$/' => "$1s" + ); + foreach ($conversionMatrix as $singularPattern => $pluralPattern) { + if (preg_match($singularPattern, $singular)) { + $plural = preg_replace($singularPattern, $pluralPattern, $singular); + break; + } + } + return $plural; + } + + /** + * Normalize short type names to full type names. + * + * @param string $type + * @return string + */ + public function normalizeType($type) + { + $normalizationMap = array( + 'str' => 'string', + 'integer' => 'int', + 'bool' => 'boolean', + ); + + return isset($normalizationMap[$type]) ? $normalizationMap[$type] : $type; + } + + /** + * Check if given type is a simple type. + * + * @param string $type + * @return bool + */ + public function isTypeSimple($type) + { + if ($this->isArrayType($type)) { + $type = $this->getArrayItemType($type); + } + + return in_array($type, array('string', 'int', 'float', 'double', 'boolean')); + } + + /** + * Check if given type is an array of type items. + * Example: + * <pre> + * ComplexType[] -> array of ComplexType items + * string[] -> array of strings + * </pre> + * + * @param string $type + * @return bool + */ + public function isArrayType($type) + { + return (bool)preg_match('/(\[\]$|^ArrayOf)/', $type); + } + + /** + * Get item type of the array. + * Example: + * <pre> + * ComplexType[] => ComplexType + * string[] => string + * int[] => integer + * </pre> + * + * @param string $arrayType + * @return string + */ + public function getArrayItemType($arrayType) + { + return $this->normalizeType(str_replace('[]', '', $arrayType)); + } + + /** + * Translate complex type class name into type name. + * + * Example: + * <pre> + * Mage_Customer_Model_Webapi_CustomerData => CustomerData + * Mage_Catalog_Model_Webapi_ProductData => CatalogProductData + * </pre> + * + * @param string $class + * @return string + * @throws InvalidArgumentException + */ + public function translateTypeName($class) + { + if (preg_match('/(.*)_(.*)_Model_Webapi_\2?(.*)/', $class, $matches)) { + $moduleNamespace = $matches[1] == 'Mage' ? '' : $matches[1]; + $moduleName = $matches[2]; + $typeNameParts = explode('_', $matches[3]); + + return ucfirst($moduleNamespace . $moduleName . implode('', $typeNameParts)); + } + throw new InvalidArgumentException(sprintf('Invalid parameter type "%s".', $class)); + } + + /** + * Translate array complex type name. + * + * Example: + * <pre> + * ComplexTypeName[] => ArrayOfComplexTypeName + * string[] => ArrayOfString + * </pre> + * + * @param string $type + * @return string + */ + public function translateArrayTypeName($type) + { + return 'ArrayOf' . ucfirst($this->getArrayItemType($type)); + } + + /** + * Translate controller class name into resource name. + * Example: + * <pre> + * Mage_Customer_Controller_Webapi_CustomerController => customer + * Mage_Customer_Controller_Webapi_Customer_AddressController => customerAddress + * Mage_Catalog_Controller_Webapi_ProductController => catalogProduct + * Mage_Catalog_Controller_Webapi_Product_ImagesController => catalogProductImages + * Mage_Catalog_Controller_Webapi_CategoryController => catalogCategory + * </pre> + * + * @param string $class + * @return string + * @throws InvalidArgumentException + */ + public function translateResourceName($class) + { + $resourceNameParts = $this->getResourceNameParts($class); + return lcfirst(implode('', $resourceNameParts)); + } + + /** + * Identify the list of resource name parts including subresources using class name. + * + * Examples of input/output pairs: <br/> + * - 'Mage_Customer_Controller_Webapi_Customer_Address' => array('Customer', 'Address') <br/> + * - 'Vendor_Customer_Controller_Webapi_Customer_Address' => array('VendorCustomer', 'Address') <br/> + * - 'Mage_Catalog_Controller_Webapi_Product' => array('Catalog', 'Product') + * + * @param string $className + * @return array + * @throws InvalidArgumentException When class is not valid API resource. + */ + public function getResourceNameParts($className) + { + if (preg_match(Mage_Webapi_Model_Config_ReaderAbstract::RESOURCE_CLASS_PATTERN, $className, $matches)) { + $moduleNamespace = $matches[1]; + $moduleName = $matches[2]; + $moduleNamespace = ($moduleNamespace == 'Mage') ? '' : $moduleNamespace; + $resourceNameParts = explode('_', trim($matches[3], '_')); + if ($moduleName == $resourceNameParts[0]) { + /** Avoid duplication of words in resource name */ + $moduleName = ''; + } + $parentResourceName = $moduleNamespace . $moduleName . array_shift($resourceNameParts); + array_unshift($resourceNameParts, $parentResourceName); + return $resourceNameParts; + } + throw new InvalidArgumentException(sprintf('The controller class name "%s" is invalid.', $className)); + } + + /** + * Identify API method name without version suffix by its reflection. + * + * @param ReflectionMethod|string $method Method name or method reflection. + * @return string Method name without version suffix on success. + * @throws InvalidArgumentException When method name is invalid API resource method. + */ + public function getMethodNameWithoutVersionSuffix($method) + { + if ($method instanceof ReflectionMethod) { + $methodNameWithSuffix = $method->getName(); + } else { + $methodNameWithSuffix = $method; + } + $regularExpression = $this->getMethodNameRegularExpression(); + if (preg_match($regularExpression, $methodNameWithSuffix, $methodMatches)) { + $methodName = $methodMatches[1]; + return $methodName; + } + throw new InvalidArgumentException(sprintf('"%s" is an invalid API resource method.', $methodNameWithSuffix)); + } + + /** + * Get regular expression to be used for method name separation into name itself and version. + * + * @return string + */ + public function getMethodNameRegularExpression() + { + return sprintf('/(%s)(V\d+)/', implode('|', Mage_Webapi_Controller_ActionAbstract::getAllowedMethods())); + } + + /** + * Identify request body param name, if it is expected by method. + * + * @param ReflectionMethod $methodReflection + * @return bool|string Return body param name if body is expected, false otherwise + * @throws LogicException + */ + public function getOperationBodyParamName(ReflectionMethod $methodReflection) + { + $bodyParamName = false; + /**#@+ + * Body param position in case of top level resources. + */ + $bodyPosCreate = 1; + $bodyPosMultiCreate = 1; + $bodyPosUpdate = 2; + $bodyPosMultiUpdate = 1; + $bodyPosMultiDelete = 1; + /**#@-*/ + $bodyParamPositions = array( + Mage_Webapi_Controller_ActionAbstract::METHOD_CREATE => $bodyPosCreate, + Mage_Webapi_Controller_ActionAbstract::METHOD_MULTI_CREATE => $bodyPosMultiCreate, + Mage_Webapi_Controller_ActionAbstract::METHOD_UPDATE => $bodyPosUpdate, + Mage_Webapi_Controller_ActionAbstract::METHOD_MULTI_UPDATE => $bodyPosMultiUpdate, + Mage_Webapi_Controller_ActionAbstract::METHOD_MULTI_DELETE => $bodyPosMultiDelete + ); + $methodName = $this->getMethodNameWithoutVersionSuffix($methodReflection); + $isBodyExpected = isset($bodyParamPositions[$methodName]); + if ($isBodyExpected) { + $bodyParamPosition = $bodyParamPositions[$methodName]; + if ($this->isSubresource($methodReflection) + && $methodName != Mage_Webapi_Controller_ActionAbstract::METHOD_UPDATE + ) { + /** For subresources parent ID param must precede request body param. */ + $bodyParamPosition++; + } + $methodInterfaces = $methodReflection->getPrototypes(); + /** @var \Zend\Server\Reflection\Prototype $methodInterface */ + $methodInterface = reset($methodInterfaces); + $methodParams = $methodInterface->getParameters(); + if (empty($methodParams) || (count($methodParams) < $bodyParamPosition)) { + throw new LogicException(sprintf( + 'Method "%s" must have parameter for passing request body. ' + . 'Its position must be "%s" in method interface.', + $methodReflection->getName(), + $bodyParamPosition + )); + } + /** @var $bodyParamReflection \Zend\Code\Reflection\ParameterReflection */ + /** Param position in the array should be counted from 0. */ + $bodyParamReflection = $methodParams[$bodyParamPosition - 1]; + $bodyParamName = $bodyParamReflection->getName(); + } + return $bodyParamName; + } + + /** + * Identify ID param name if it is expected for the specified method. + * + * @param ReflectionMethod $methodReflection + * @return bool|string Return ID param name if it is expected; false otherwise. + * @throws LogicException If resource method interface does not contain required ID parameter. + */ + public function getOperationIdParamName(ReflectionMethod $methodReflection) + { + $idParamName = false; + $isIdFieldExpected = false; + if (!$this->isSubresource($methodReflection)) { + /** Top level resource, not subresource */ + $methodsWithId = array( + Mage_Webapi_Controller_ActionAbstract::METHOD_GET, + Mage_Webapi_Controller_ActionAbstract::METHOD_UPDATE, + Mage_Webapi_Controller_ActionAbstract::METHOD_DELETE, + ); + $methodName = $this->getMethodNameWithoutVersionSuffix($methodReflection); + if (in_array($methodName, $methodsWithId)) { + $isIdFieldExpected = true; + } + } else { + /** + * All subresources must have ID field: + * either subresource ID (for item operations) or parent resource ID (for collection operations) + */ + $isIdFieldExpected = true; + } + + if ($isIdFieldExpected) { + /** ID field must always be the first parameter of resource method */ + $methodInterfaces = $methodReflection->getPrototypes(); + /** @var \Zend\Server\Reflection\Prototype $methodInterface */ + $methodInterface = reset($methodInterfaces); + $methodParams = $methodInterface->getParameters(); + if (empty($methodParams)) { + throw new LogicException(sprintf( + 'The "%s" method must have at least one parameter: resource ID.', + $methodReflection->getName() + )); + } + /** @var ReflectionParameter $idParam */ + $idParam = reset($methodParams); + $idParamName = $idParam->getName(); + } + return $idParamName; + } + + /** + * Identify if API resource is top level resource or subresource. + * + * @param ReflectionMethod $methodReflection + * @return bool + * @throws InvalidArgumentException In case when class name is not valid API resource class. + */ + public function isSubresource(ReflectionMethod $methodReflection) + { + $className = $methodReflection->getDeclaringClass()->getName(); + if (preg_match(Mage_Webapi_Model_Config_ReaderAbstract::RESOURCE_CLASS_PATTERN, $className, $matches)) { + return count(explode('_', trim($matches[3], '_'))) > 1; + } + throw new InvalidArgumentException(sprintf('"%s" is not a valid resource class.', $className)); + } +} diff --git a/app/code/core/Mage/Webapi/Helper/Data.php b/app/code/core/Mage/Webapi/Helper/Data.php new file mode 100644 index 0000000000000000000000000000000000000000..85a2b37b1b84f5741c72b9713affd195ee0378e4 --- /dev/null +++ b/app/code/core/Mage/Webapi/Helper/Data.php @@ -0,0 +1,202 @@ +<?php +use Zend\Server\Reflection\ReflectionMethod; + +/** + * Webapi module helper. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Helper_Data extends Mage_Core_Helper_Abstract +{ + /** @var Mage_Webapi_Helper_Config */ + protected $_configHelper; + + /** + * Initialize dependencies. + * + * @param Mage_Webapi_Helper_Config $configHelper + */ + public function __construct(Mage_Webapi_Helper_Config $configHelper) + { + $this->_configHelper = $configHelper; + } + + /** + * Web API ACL resources tree root ID. + */ + const RESOURCES_TREE_ROOT_ID = '__root__'; + + /** + * Reformat request data to be compatible with method specified interface: <br/> + * - sort arguments in correct order <br/> + * - set default values for omitted arguments + * - instantiate objects of necessary classes + * + * @param string|object $classOrObject Resource class name + * @param string $methodName Resource method name + * @param array $requestData Data to be passed to method + * @param Mage_Webapi_Model_ConfigAbstract $apiConfig + * @return array Array of prepared method arguments + * @throws Mage_Webapi_Exception + */ + public function prepareMethodParams( + $classOrObject, + $methodName, + $requestData, + Mage_Webapi_Model_ConfigAbstract $apiConfig + ) { + $methodReflection = self::createMethodReflection($classOrObject, $methodName); + $methodData = $apiConfig->getMethodMetadata($methodReflection); + $methodArguments = array(); + if (isset($methodData['interface']['in']['parameters']) + && is_array($methodData['interface']['in']['parameters']) + ) { + foreach ($methodData['interface']['in']['parameters'] as $paramName => $paramData) { + if (isset($requestData[$paramName])) { + $methodArguments[$paramName] = $this->_formatParamData( + $requestData[$paramName], + $paramData['type'], + $apiConfig + ); + } elseif (!$paramData['required']) { + $methodArguments[$paramName] = $paramData['default']; + } else { + throw new Mage_Webapi_Exception($this->__('Required parameter "%s" is missing.', $paramName), + Mage_Webapi_Exception::HTTP_BAD_REQUEST); + } + } + } + return $methodArguments; + } + + /** + * Format $data according to specified $dataType recursively. + * + * Instantiate objects of proper classes and set data to its fields. + * + * @param mixed $data + * @param string $dataType + * @param Mage_Webapi_Model_ConfigAbstract $apiConfig + * @return mixed + * @throws LogicException If specified $dataType is invalid + * @throws Mage_Webapi_Exception If required fields do not have values specified in $data + */ + protected function _formatParamData($data, $dataType, Mage_Webapi_Model_ConfigAbstract $apiConfig) + { + if ($this->_configHelper->isTypeSimple($dataType) || is_null($data)) { + $formattedData = $data; + } elseif ($this->_configHelper->isArrayType($dataType)) { + $formattedData = $this->_formatArrayData($data, $dataType, $apiConfig); + } else { + $formattedData = $this->_formatComplexObjectData($data, $dataType, $apiConfig); + } + return $formattedData; + } + + /** + * Format data of array type. + * + * @param array $data + * @param string $dataType + * @param Mage_Webapi_Model_ConfigAbstract $apiConfig + * @return array + * @throws Mage_Webapi_Exception If passed data is not an array + */ + protected function _formatArrayData($data, $dataType, $apiConfig) + { + $itemDataType = $this->_configHelper->getArrayItemType($dataType); + $formattedData = array(); + if (!is_array($data)) { + throw new Mage_Webapi_Exception( + $this->__('Data corresponding to "%s" type is expected to be an array.', $dataType), + Mage_Webapi_Exception::HTTP_BAD_REQUEST + ); + } + foreach ($data as $itemData) { + $formattedData[] = $this->_formatParamData($itemData, $itemDataType, $apiConfig); + } + return $formattedData; + } + + /** + * Format data as object of the specified class. + * + * @param array|object $data + * @param string $dataType + * @param Mage_Webapi_Model_ConfigAbstract $apiConfig + * @return object Object of required data type + * @throws LogicException If specified $dataType is invalid + * @throws Mage_Webapi_Exception If required fields does not have values specified in $data + */ + protected function _formatComplexObjectData($data, $dataType, $apiConfig) + { + $dataTypeMetadata = $apiConfig->getTypeData($dataType); + $typeToClassMap = $apiConfig->getTypeToClassMap(); + if (!isset($typeToClassMap[$dataType])) { + throw new LogicException(sprintf('Specified data type "%s" does not match any class.', $dataType)); + } + $complexTypeClass = $typeToClassMap[$dataType]; + if (is_object($data) && (get_class($data) == $complexTypeClass)) { + /** In case of SOAP the object creation is performed by soap server. */ + return $data; + } + $complexDataObject = new $complexTypeClass(); + if (!is_array($data)) { + throw new Mage_Webapi_Exception( + $this->__('Data corresponding to "%s" type is expected to be an array.', $dataType), + Mage_Webapi_Exception::HTTP_BAD_REQUEST + ); + } + foreach ($dataTypeMetadata['parameters'] as $fieldName => $fieldMetadata) { + if (isset($data[$fieldName])) { + $fieldValue = $data[$fieldName]; + } elseif (($fieldMetadata['required'] == false)) { + $fieldValue = $fieldMetadata['default']; + } else { + throw new Mage_Webapi_Exception($this->__('Value of "%s" attribute is required.', $fieldName), + Mage_Webapi_Exception::HTTP_BAD_REQUEST); + } + $complexDataObject->$fieldName = $this->_formatParamData( + $fieldValue, + $fieldMetadata['type'], + $apiConfig + ); + } + return $complexDataObject; + } + + /** + * Create Zend method reflection object. + * + * @param string|object $classOrObject + * @param string $methodName + * @return Zend\Server\Reflection\ReflectionMethod + */ + public static function createMethodReflection($classOrObject, $methodName) + { + $methodReflection = new \ReflectionMethod($classOrObject, $methodName); + $classReflection = new \ReflectionClass($classOrObject); + $zendClassReflection = new Zend\Server\Reflection\ReflectionClass($classReflection); + $zendMethodReflection = new Zend\Server\Reflection\ReflectionMethod($zendClassReflection, $methodReflection); + return $zendMethodReflection; + } +} diff --git a/app/code/core/Mage/Webapi/Model/Acl/Role.php b/app/code/core/Mage/Webapi/Model/Acl/Role.php new file mode 100644 index 0000000000000000000000000000000000000000..c70aadb9070f62cf377dc1e59ea49125dff6c66a --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Acl/Role.php @@ -0,0 +1,35 @@ +<?php +/** + * Role item model. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Acl_Role extends Mage_Core_Model_Abstract +{ + /** + * Initialize resource. + */ + protected function _construct() + { + $this->_init('Mage_Webapi_Model_Resource_Acl_Role'); + } +} diff --git a/app/code/core/Mage/Webapi/Model/Acl/Role/Factory.php b/app/code/core/Mage/Webapi/Model/Acl/Role/Factory.php new file mode 100644 index 0000000000000000000000000000000000000000..e191b48108ab35813df1a41a2de66f81c671aea3 --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Acl/Role/Factory.php @@ -0,0 +1,53 @@ +<?php +/** + * ACL Role factory. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Acl_Role_Factory +{ + const CLASS_NAME = 'Mage_Webapi_Model_Acl_Role'; + + /** + * @var Magento_ObjectManager + */ + protected $_objectManager; + + /** + * @param Magento_ObjectManager $objectManager + */ + public function __construct(Magento_ObjectManager $objectManager) + { + $this->_objectManager = $objectManager; + } + + /** + * Create ACL role model. + * + * @param array $arguments + * @return Mage_Webapi_Model_Acl_Role + */ + public function create(array $arguments = array()) + { + return $this->_objectManager->create(self::CLASS_NAME, $arguments); + } +} diff --git a/app/code/core/Mage/Webapi/Model/Acl/Role/InRoleUserUpdater.php b/app/code/core/Mage/Webapi/Model/Acl/Role/InRoleUserUpdater.php new file mode 100644 index 0000000000000000000000000000000000000000..ab33555a9257595dabf023caad126c5ae4a2efc9 --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Acl/Role/InRoleUserUpdater.php @@ -0,0 +1,65 @@ +<?php +/** + * Users in role grid "In Role User" column with checkbox updater. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Acl_Role_InRoleUserUpdater implements Mage_Core_Model_Layout_Argument_UpdaterInterface +{ + /** + * @var int + */ + protected $_roleId; + + /** + * @var Mage_Webapi_Model_Resource_Acl_User + */ + protected $_userResource; + + /** + * Constructor. + * + * @param Mage_Core_Controller_Request_Http $request + * @param Mage_Webapi_Model_Resource_Acl_User $userResource + */ + public function __construct( + Mage_Core_Controller_Request_Http $request, + Mage_Webapi_Model_Resource_Acl_User $userResource + ) { + $this->_roleId = (int)$request->getParam('role_id'); + $this->_userResource = $userResource; + } + + /** + * Init values with users assigned to role. + * + * @param array|null $values + * @return array|null + */ + public function update($values) + { + if ($this->_roleId) { + $values = $this->_userResource->getRoleUsers($this->_roleId); + } + return $values; + } +} diff --git a/app/code/core/Mage/Webapi/Model/Acl/Role/UsersUpdater.php b/app/code/core/Mage/Webapi/Model/Acl/Role/UsersUpdater.php new file mode 100644 index 0000000000000000000000000000000000000000..6f26d30c827aea513f024e01b88bd9087f365fd6 --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Acl/Role/UsersUpdater.php @@ -0,0 +1,107 @@ +<?php +/** + * Users in role grid items updater. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Acl_Role_UsersUpdater implements Mage_Core_Model_Layout_Argument_UpdaterInterface +{ + /** + * Filter name for users by role. + */ + const IN_ROLE_USERS_PARAMETER = 'in_role_users'; + + /**#@+ + * Supported values of filtering users by role. + */ + const IN_ROLE_USERS_ANY = 1; + const IN_ROLE_USERS_YES = 2; + const IN_ROLE_USERS_NO = 3; + /**#@-*/ + + /** + * @var int + */ + protected $_roleId; + + /** + * @var Mage_Core_Controller_Request_Http + */ + protected $_inRoleUsersFilter; + + /** + * Constructor. + * + * @param Mage_Core_Controller_Request_Http $request + * @param Mage_Backend_Helper_Data $backendHelper + */ + public function __construct(Mage_Core_Controller_Request_Http $request, Mage_Backend_Helper_Data $backendHelper) + { + $this->_roleId = (int)$request->getParam('role_id'); + $this->_inRoleUsersFilter = $this->_parseInRoleUsersFilter($request, $backendHelper); + } + + /** + * Parse $_inRoleUsersFilter value from request + * + * @param Mage_Core_Controller_Request_Http $request + * @param Mage_Backend_Helper_Data $backendHelper + * @return int + */ + protected function _parseInRoleUsersFilter( + Mage_Core_Controller_Request_Http $request, + Mage_Backend_Helper_Data $backendHelper + ) { + $result = self::IN_ROLE_USERS_ANY; + $filter = $backendHelper->prepareFilterString($request->getParam('filter', '')); + if (isset($filter[self::IN_ROLE_USERS_PARAMETER])) { + $result = $filter[self::IN_ROLE_USERS_PARAMETER] ? self::IN_ROLE_USERS_YES : self::IN_ROLE_USERS_NO; + } elseif (!$request->isAjax()) { + $result = self::IN_ROLE_USERS_YES; + } + return $result; + } + + /** + * Add filtering users by role. + * + * @param Mage_Webapi_Model_Resource_Acl_User_Collection $collection + * @return Mage_Webapi_Model_Resource_Acl_User_Collection + */ + public function update($collection) + { + if ($this->_roleId) { + switch ($this->_inRoleUsersFilter) { + case self::IN_ROLE_USERS_YES: + $collection->addFieldToFilter('role_id', $this->_roleId); + break; + case self::IN_ROLE_USERS_NO: + $collection->addFieldToFilter('role_id', array( + array('neq' => $this->_roleId), + array('is' => new Zend_Db_Expr('NULL')) + )); + break; + } + } + return $collection; + } +} diff --git a/app/code/core/Mage/Webapi/Model/Acl/Rule.php b/app/code/core/Mage/Webapi/Model/Acl/Rule.php new file mode 100644 index 0000000000000000000000000000000000000000..61e6cd817f1e13b3d950ecad58245a121908e298 --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Acl/Rule.php @@ -0,0 +1,65 @@ +<?php +/** + * Web API ACL Rules. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * + * @method int getRoleId() getRoleId() + * @method Mage_Webapi_Model_Acl_Rule setRoleId() setRoleId(int $value) + * @method string getResourceId() getResourceId() + * @method Mage_Webapi_Model_Resource_Acl_Rule getResource() getResource() + * @method Mage_Webapi_Model_Resource_Acl_Rule_Collection getCollection() getCollection() + * @method Mage_Webapi_Model_Acl_Rule setResourceId() setResourceId(string $value) + * @method Mage_Webapi_Model_Acl_Rule setResources() setResources(array $resources) + * @method array getResources() getResources() + */ +class Mage_Webapi_Model_Acl_Rule extends Mage_Core_Model_Abstract +{ + /** + * Web API ACL config's resources root ID. + */ + const API_ACL_RESOURCES_ROOT_ID = 'Mage_Webapi'; + + /** + * Web API ACL resource separator. + */ + const RESOURCE_SEPARATOR = '/'; + + /** + * Constructor. + */ + protected function _construct() + { + $this->_init('Mage_Webapi_Model_Resource_Acl_Rule'); + } + + /** + * Save role resources. + * + * @return Mage_Webapi_Model_Acl_Rule + */ + public function saveResources() + { + $this->getResource()->saveResources($this); + return $this; + } +} diff --git a/app/code/core/Mage/Webapi/Model/Acl/User.php b/app/code/core/Mage/Webapi/Model/Acl/User.php new file mode 100644 index 0000000000000000000000000000000000000000..a9d8045ae5ab721f57769a76fa2d6be31c4201d9 --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Acl/User.php @@ -0,0 +1,94 @@ +<?php +/** + * Web API User model. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * + * @method Mage_Webapi_Model_Acl_User setRoleId() setRoleId(int $id) + * @method int getRoleId() getRoleId() + * @method Mage_Webapi_Model_Acl_User setApiKey() setApiKey(string $apiKey) + * @method string getApiKey() getApiKey() + * @method Mage_Webapi_Model_Acl_User setContactEmail() setContactEmail(string $contactEmail) + * @method string getContactEmail() getContactEmail() + * @method Mage_Webapi_Model_Acl_User setSecret() setSecret(string $secret) + * @method Mage_Webapi_Model_Acl_User setCompanyName() setCompanyName(string $companyName) + * @method string getCompanyName() getCompanyName() + */ +class Mage_Webapi_Model_Acl_User extends Mage_Core_Model_Abstract implements Mage_Oauth_Model_ConsumerInterface +{ + /** + * Prefix of model events names. + * + * @var string + */ + protected $_eventPrefix = 'webapi_user'; + + /** + * Initialize resource model. + */ + protected function _construct() + { + $this->_init('Mage_Webapi_Model_Resource_Acl_User'); + } + + /** + * Get role users. + * + * @param integer $roleId + * @return array + */ + public function getRoleUsers($roleId) + { + return $this->getResource()->getRoleUsers($roleId); + } + + /** + * Load user by key. + * + * @param string $key + * @return Mage_Webapi_Model_Acl_User + */ + public function loadByKey($key) + { + return $this->load($key, 'api_key'); + } + + /** + * Get consumer key. + * + * @return string + */ + public function getSecret() + { + return $this->getData('secret'); + } + + /** + * Get consumer callback URL. + * + * @return string + */ + public function getCallBackUrl() + { + return ''; + } +} diff --git a/app/code/core/Mage/Webapi/Model/Acl/User/Factory.php b/app/code/core/Mage/Webapi/Model/Acl/User/Factory.php new file mode 100644 index 0000000000000000000000000000000000000000..b2eecc3b79d76745ce9cb45d9336f4f367d472f3 --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Acl/User/Factory.php @@ -0,0 +1,53 @@ +<?php +/** + * ACL User factory. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Acl_User_Factory extends Mage_Oauth_Model_Consumer_Factory +{ + const CLASS_NAME = 'Mage_Webapi_Model_Acl_User'; + + /** + * @var Magento_ObjectManager + */ + protected $_objectManager; + + /** + * @param Magento_ObjectManager $objectManager + */ + public function __construct(Magento_ObjectManager $objectManager) + { + $this->_objectManager = $objectManager; + } + + /** + * Create ACL user model. + * + * @param array $arguments + * @return Mage_Webapi_Model_Acl_User + */ + public function create(array $arguments = array()) + { + return $this->_objectManager->create(self::CLASS_NAME, $arguments); + } +} diff --git a/app/code/core/Mage/Webapi/Model/Acl/User/RoleUpdater.php b/app/code/core/Mage/Webapi/Model/Acl/User/RoleUpdater.php new file mode 100644 index 0000000000000000000000000000000000000000..0721df457522e2caeef36a4fab8a219983b02f7b --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Acl/User/RoleUpdater.php @@ -0,0 +1,65 @@ +<?php +/** + * User role in role grid items updater. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Acl_User_RoleUpdater implements Mage_Core_Model_Layout_Argument_UpdaterInterface +{ + /** + * @var int + */ + protected $_userId; + + /** + * @var Mage_Webapi_Model_Acl_User_Factory + */ + protected $_userFactory; + + /** + * Constructor. + * + * @param Mage_Core_Controller_Request_Http $request + * @param Mage_Webapi_Model_Acl_User_Factory $userFactory + */ + public function __construct( + Mage_Core_Controller_Request_Http $request, + Mage_Webapi_Model_Acl_User_Factory $userFactory + ) { + $this->_userId = (int)$request->getParam('user_id'); + $this->_userFactory = $userFactory; + } + + /** + * Initialize value with role assigned to user. + * + * @param int|null $value + * @return int|null + */ + public function update($value) + { + if ($this->_userId) { + $value = $this->_userFactory->create()->load($this->_userId)->getRoleId(); + } + return $value; + } +} diff --git a/app/code/core/Mage/Webapi/Model/Authorization.php b/app/code/core/Mage/Webapi/Model/Authorization.php new file mode 100644 index 0000000000000000000000000000000000000000..81a53cab7812957584b1a2c0056d743d59a38774 --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Authorization.php @@ -0,0 +1,72 @@ +<?php +/** + * Web API authorization model. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Authorization +{ + /** + * Web API ACL config's resources root ID. + */ + const API_ACL_RESOURCES_ROOT_ID = 'Mage_Webapi'; + + /** @var Mage_Core_Model_Authorization */ + protected $_coreAuthorization; + + /** @var Mage_Webapi_Helper_Data */ + protected $_helper; + + /** + * Initialize dependencies. + * + * @param Mage_Webapi_Helper_Data $helper + * @param Mage_Core_Model_Authorization $coreAuthorization + */ + public function __construct( + Mage_Webapi_Helper_Data $helper, + Mage_Core_Model_Authorization $coreAuthorization + ) { + $this->_helper = $helper; + $this->_coreAuthorization = $coreAuthorization; + } + + /** + * Check permissions on specific resource in ACL. + * + * @param string $resource + * @param string $method + * @throws Mage_Webapi_Exception + */ + public function checkResourceAcl($resource, $method) + { + $coreAuthorization = $this->_coreAuthorization; + if (!$coreAuthorization->isAllowed($resource . Mage_Webapi_Model_Acl_Rule::RESOURCE_SEPARATOR . $method) + && !$coreAuthorization->isAllowed(Mage_Webapi_Model_Authorization::API_ACL_RESOURCES_ROOT_ID) + ) { + throw new Mage_Webapi_Exception( + $this->_helper->__('Access to resource is forbidden.'), + Mage_Webapi_Exception::HTTP_FORBIDDEN + ); + } + } +} diff --git a/app/code/core/Mage/Webapi/Model/Authorization/Config.php b/app/code/core/Mage/Webapi/Model/Authorization/Config.php new file mode 100644 index 0000000000000000000000000000000000000000..4fb805d888067d08fe5db12ad898a96e2fb2f871 --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Authorization/Config.php @@ -0,0 +1,200 @@ +<?php +/** + * API ACL Config model + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Authorization_Config implements Mage_Core_Model_Acl_Config_ConfigInterface +{ + + const ACL_RESOURCES_XPATH = '/config/acl/resources/*'; + + const ACL_VIRTUAL_RESOURCES_XPATH = '/config/mapping/*'; + + /** + * @var Mage_Core_Model_Config + */ + protected $_config; + + /** + * @var Magento_Acl_Config_Reader + */ + protected $_reader; + + /** + * @var Mage_Webapi_Model_Authorization_Config_Reader_Factory + */ + protected $_readerFactory; + + /** + * @param Mage_Core_Model_Config $config + * @param Mage_Webapi_Model_Authorization_Config_Reader_Factory $readerFactory + */ + public function __construct(Mage_Core_Model_Config $config, + Mage_Webapi_Model_Authorization_Config_Reader_Factory $readerFactory + ) { + $this->_config = $config; + $this->_readerFactory = $readerFactory; + } + + /** + * Retrieve list of ACL files from each module. + * + * @return array + */ + protected function _getAclResourceFiles() + { + $files = $this->_config->getModuleConfigurationFiles('webapi' . DIRECTORY_SEPARATOR . 'acl.xml'); + return (array)$files; + } + + /** + * Reader object initialization. + * + * @return Magento_Acl_Config_Reader + */ + protected function _getReader() + { + if (is_null($this->_reader)) { + $aclResourceFiles = $this->_getAclResourceFiles(); + $this->_reader = $this->_readerFactory->createReader(array($aclResourceFiles)); + } + return $this->_reader; + } + + /** + * Get DOMXPath with loaded resources inside. + * + * @return DOMXPath + */ + protected function _getXPathResources() + { + $aclResources = $this->_getReader()->getAclResources(); + return new DOMXPath($aclResources); + } + + /** + * Return ACL Resources. + * + * @return DOMNodeList + */ + public function getAclResources() + { + return $this->_getXPathResources()->query(self::ACL_RESOURCES_XPATH); + } + + /** + * Return array representation of ACL resources. + * + * @param bool $includeRoot If FALSE then only children of root element will be returned + * @return array + */ + public function getAclResourcesAsArray($includeRoot = true) + { + $result = array(); + $rootResource = null; + $resources = $this->getAclResources(); + + if ($resources && $resources->length == 1) { + $rootResource = $resources->item(0); + } + + if ($rootResource && $rootResource->childNodes + && (string)$rootResource->getAttribute('id') == Mage_Webapi_Model_Authorization::API_ACL_RESOURCES_ROOT_ID + ) { + $result = $this->_parseAclResourceDOMElement($rootResource); + } + + if (!$includeRoot) { + $result = isset($result['children']) ? $result['children'] : array(); + } + return $result; + } + + /** + * Parse DOMElement of ACL resource in config and return its array representation. + * + * @param DOMElement $node + * @return array + */ + protected function _parseAclResourceDOMElement(DOMElement $node) + { + $result = array(); + + $result['id'] = (string)$node->getAttribute('id'); + $result['text'] = (string)$node->getAttribute('title'); + $sortOrder = (string)$node->getAttribute('sortOrder'); + if (!empty($sortOrder)) { + $result['sortOrder']= $sortOrder; + } + + $result['children'] = array(); + foreach ($node->childNodes as $child) { + if ($child instanceof DOMElement) { + $result['children'][] = $this->_parseAclResourceDOMElement($child); + } + } + + if (!empty($result['children'])) { + $result['children'] = $this->_getSortedBySortOrder($result['children']); + } + + return $result; + } + + /** + * Get array elements sorted by sortOrder key + * + * @param array $elements + * @return array + */ + protected function _getSortedBySortOrder(array $elements) + { + $sortable = array(); + $unsortable = array(); + foreach ($elements as $element) { + if (isset($element['sortOrder'])) { + $sortable[] = $element; + } else { + $unsortable[] = $element; + } + } + usort($sortable, function ($firstItem, $secondItem) { + // To preserve the original order in the array, return 1 when $firstItem == $secondItem instead of 0 + return $firstItem['sortOrder'] < $secondItem['sortOrder'] ? -1 : 1; + }); + // Move un-sortable elements to the end of array to preserve their original order between each other + return array_merge($sortable, $unsortable); + } + + /** + * Return ACL Virtual Resources. + * + * Virtual resources are not shown in resource list, they use existing resource to check permission. + * + * @return DOMNodeList + */ + public function getAclVirtualResources() + { + return $this->_getXPathResources()->query(self::ACL_VIRTUAL_RESOURCES_XPATH); + } +} diff --git a/app/code/core/Mage/Webapi/Model/Authorization/Config/Reader.php b/app/code/core/Mage/Webapi/Model/Authorization/Config/Reader.php new file mode 100644 index 0000000000000000000000000000000000000000..15c3edcbe61e41b197582d91c399951b6bad51e0 --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Authorization/Config/Reader.php @@ -0,0 +1,47 @@ +<?php +/** + * API ACL Config Reader model. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Authorization_Config_Reader extends Magento_Acl_Config_Reader +{ + /** + * Get absolute path to the XML-schema file. + * + * @return string + */ + public function getSchemaFile() + { + return __DIR__ . DIRECTORY_SEPARATOR . 'acl.xsd'; + } + + /** + * Get XML-contents, initial for merging. + * + * @return string + */ + protected function _getInitialXml() + { + return '<?xml version="1.0" encoding="utf-8"?><config><acl></acl><mapping></mapping></config>'; + } +} diff --git a/app/code/core/Mage/Webapi/Model/Authorization/Config/Reader/Factory.php b/app/code/core/Mage/Webapi/Model/Authorization/Config/Reader/Factory.php new file mode 100644 index 0000000000000000000000000000000000000000..6c37970523fbd85e40b6eb0ff9f796464b68c271 --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Authorization/Config/Reader/Factory.php @@ -0,0 +1,53 @@ +<?php +/** + * Factory for Mage_Webapi_Model_Authorization_Config_Reader + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Authorization_Config_Reader_Factory +{ + const READER_CLASS_NAME = 'Mage_Webapi_Model_Authorization_Config_Reader'; + + /** + * @var Magento_ObjectManager + */ + protected $_objectManager; + + /** + * @param Magento_ObjectManager $objectManager + */ + public function __construct(Magento_ObjectManager $objectManager) + { + $this->_objectManager = $objectManager; + } + + /** + * Return new Mage_Webapi_Model_Authorization_Config_Reader + * + * @param array $arguments + * @return Mage_Webapi_Model_Authorization_Config_Reader + */ + public function createReader(array $arguments = array()) + { + return $this->_objectManager->create(self::READER_CLASS_NAME, $arguments, false); + } +} diff --git a/app/code/core/Mage/Webapi/Model/Authorization/Config/acl.xsd b/app/code/core/Mage/Webapi/Model/Authorization/Config/acl.xsd new file mode 100644 index 0000000000000000000000000000000000000000..5416737be4174827017ab4067080ed52258e253f --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Authorization/Config/acl.xsd @@ -0,0 +1,140 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Structure description for acl.xml ACL resource files. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Academic Free License (AFL 3.0) + * that is bundled with this package in the file LICENSE_AFL.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/afl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ +--> +<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> + <xs:element name="config"> + <xs:complexType> + <xs:sequence> + <xs:element name="acl"> + <xs:complexType> + <xs:sequence> + <xs:element name="resources"> + <xs:complexType> + <xs:sequence> + <xs:element minOccurs="0" maxOccurs="unbounded" name="resource" type="aclResource" /> + </xs:sequence> + </xs:complexType> + + <xs:unique name="uniqueResourceId"> + <xs:annotation> + <xs:documentation> + Attribute ID is unique under all ACL resources + </xs:documentation> + </xs:annotation> + <xs:selector xpath=".//*"/> + <xs:field xpath="@id"/> + </xs:unique> + </xs:element> + </xs:sequence> + </xs:complexType> + </xs:element> + + <xs:element name="mapping"> + <xs:complexType> + <xs:sequence> + <xs:element minOccurs="0" maxOccurs="unbounded" name="resource" type="aclMapping"> + <xs:unique name="uniqueMappedResourceId"> + <xs:annotation> + <xs:documentation> + Attribute ID is unique under all mapped ACL resources + </xs:documentation> + </xs:annotation> + <xs:selector xpath=".//*"/> + <xs:field xpath="@id"/> + </xs:unique> + </xs:element> + </xs:sequence> + </xs:complexType> + </xs:element> + </xs:sequence> + </xs:complexType> + </xs:element> + + <xs:complexType name="aclResource"> + <xs:annotation> + <xs:documentation> + ACL Resource. Recursive complex type + </xs:documentation> + </xs:annotation> + + <xs:sequence> + <xs:element minOccurs="0" maxOccurs="unbounded" name="resource" type="aclResource" /> + </xs:sequence> + + <xs:attribute name="id" type="typeId" use="required" /> + <xs:attribute name="module" type="typeModule" use="optional" /> + <xs:attribute name="title" type="typeTitle" use="optional" /> + <xs:attribute name="sortOrder" type="xs:int" use="optional" /> + </xs:complexType> + + <xs:complexType name="aclMapping"> + <xs:annotation> + <xs:documentation> + ACL Resource mapping. + </xs:documentation> + </xs:annotation> + + <xs:attribute name="id" type="typeId" use="required" /> + <xs:attribute name="parent" type="typeId" use="required" /> + </xs:complexType> + + <xs:simpleType name="typeId"> + <xs:annotation> + <xs:documentation> + Item ID attribute can have only [A-Za-z0-9_]/[A-Za-z0-9_]. Minimal length is 3 symbols. Case insensitive. + </xs:documentation> + </xs:annotation> + + <xs:restriction base="xs:string"> + <xs:pattern value="[A-Za-z_0-9]+/?[A-Za-z_0-9]+" /> + </xs:restriction> + </xs:simpleType> + + <xs:simpleType name="typeTitle"> + <xs:annotation> + <xs:documentation> + Item title attribute minimal length is 3 symbols + </xs:documentation> + </xs:annotation> + + <xs:restriction base="xs:string"> + <xs:minLength value="3" /> + <xs:maxLength value="50" /> + </xs:restriction> + </xs:simpleType> + + <xs:simpleType name="typeModule"> + <xs:annotation> + <xs:documentation> + Item module attribute can have only [a-z0-9_]. Minimal length is 3 symbols. Case insensitive. + </xs:documentation> + </xs:annotation> + <xs:restriction base="xs:string"> + <xs:pattern value="[A-Z]+[a-z0-9]{1,}_[A-Z]+[A-Z0-9a-z]{1,}" /> + </xs:restriction> + </xs:simpleType> +</xs:schema> diff --git a/app/code/core/Mage/Webapi/Model/Authorization/Loader/Resource.php b/app/code/core/Mage/Webapi/Model/Authorization/Loader/Resource.php new file mode 100644 index 0000000000000000000000000000000000000000..a834985714b2b2ba6dc95fc7ada4f4315ed86c7a --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Authorization/Loader/Resource.php @@ -0,0 +1,75 @@ +<?php +/** + * API ACL Resource Loader. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Authorization_Loader_Resource extends Mage_Core_Model_Acl_Loader_Resource_ResourceAbstract +{ + /** + * Deny each resource for all roles. + * + * @param Magento_Acl $acl + */ + protected function _denyResources(Magento_Acl $acl) + { + foreach ($acl->getResources() as $aclResource) { + $acl->deny(null, $aclResource); + } + } + + /** + * Load virtual resources as sub-resources of existing one. + * + * @param Magento_Acl $acl + */ + protected function _loadVirtualResources(Magento_Acl $acl) + { + $virtualResources = $this->_config->getAclVirtualResources(); + /** @var $resourceConfig DOMElement */ + foreach ($virtualResources as $resourceConfig) { + if (!($resourceConfig instanceof DOMElement)) { + continue; + } + $parent = $resourceConfig->getAttribute('parent'); + $resourceId = $resourceConfig->getAttribute('id'); + if ($acl->has($parent) && !$acl->has($resourceId)) { + /** @var $resource Magento_Acl_Resource */ + $resource = $this->_resourceFactory->createResource(array($resourceId)); + $acl->addResource($resource, $parent); + } + } + } + + /** + * Populate ACL with resources from external storage. + * + * @param Magento_Acl $acl + * @throws Mage_Core_Exception + */ + public function populateAcl(Magento_Acl $acl) + { + parent::populateAcl($acl); + $this->_denyResources($acl); + $this->_loadVirtualResources($acl); + } +} diff --git a/app/code/core/Mage/Webapi/Model/Authorization/Loader/Role.php b/app/code/core/Mage/Webapi/Model/Authorization/Loader/Role.php new file mode 100644 index 0000000000000000000000000000000000000000..a873eba7f070ffb241bcce49c1f93767699f69e1 --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Authorization/Loader/Role.php @@ -0,0 +1,70 @@ +<?php +/** + * API ACL Role Loader + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Authorization_Loader_Role implements Magento_Acl_Loader +{ + /** + * @var Mage_Webapi_Model_Resource_Acl_Role + */ + protected $_roleResource; + + /** + * @var Mage_Webapi_Model_Authorization_Role_Factory + */ + protected $_roleFactory; + + /** + * @var Mage_Core_Model_Config + */ + protected $_config; + + /** + * @param Mage_Webapi_Model_Resource_Acl_Role $roleResource + * @param Mage_Webapi_Model_Authorization_Role_Factory $roleFactory + */ + public function __construct(Mage_Webapi_Model_Resource_Acl_Role $roleResource, + Mage_Webapi_Model_Authorization_Role_Factory $roleFactory + ) { + $this->_roleResource = $roleResource; + $this->_roleFactory = $roleFactory; + } + + /** + * Populate ACL with roles from external storage. + * + * @param Magento_Acl $acl + */ + public function populateAcl(Magento_Acl $acl) + { + $roleList = $this->_roleResource->getRolesIds(); + foreach ($roleList as $roleId) { + /** @var $aclRole Mage_Webapi_Model_Authorization_Role */ + $aclRole = $this->_roleFactory->createRole(array($roleId)); + $acl->addRole($aclRole); + //Deny all privileges to Role. Some of them could be allowed later by whitelist + $acl->deny($aclRole); + } + } +} diff --git a/app/code/core/Mage/Webapi/Model/Authorization/Loader/Rule.php b/app/code/core/Mage/Webapi/Model/Authorization/Loader/Rule.php new file mode 100644 index 0000000000000000000000000000000000000000..bf37b06f799c277eb7cba6cb993a7a11fe691093 --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Authorization/Loader/Rule.php @@ -0,0 +1,57 @@ +<?php +/** + * API ACL Rule Loader + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Authorization_Loader_Rule implements Magento_Acl_Loader +{ + /** + * @var Mage_Webapi_Model_Resource_Acl_Rule + */ + protected $_ruleResource; + + /** + * @param Mage_Webapi_Model_Resource_Acl_Rule $ruleResource + */ + public function __construct(Mage_Webapi_Model_Resource_Acl_Rule $ruleResource) + { + $this->_ruleResource = $ruleResource; + } + + /** + * Populate ACL with rules from external storage. + * + * @param Magento_Acl $acl + */ + public function populateAcl(Magento_Acl $acl) + { + $ruleList = $this->_ruleResource->getRuleList(); + foreach ($ruleList as $rule) { + $role = $rule['role_id']; + $resource = $rule['resource_id']; + if ($acl->hasRole($role) && $acl->has($resource)) { + $acl->allow($role, $resource); + } + } + } +} diff --git a/app/code/core/Mage/Webapi/Model/Authorization/Role.php b/app/code/core/Mage/Webapi/Model/Authorization/Role.php new file mode 100644 index 0000000000000000000000000000000000000000..7cfaf9ed86cd503832c1997b2366da77c67a79d8 --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Authorization/Role.php @@ -0,0 +1,29 @@ +<?php +/** + * API ACL Role + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Authorization_Role extends Zend_Acl_Role +{ + +} diff --git a/app/code/core/Mage/Webapi/Model/Authorization/Role/Factory.php b/app/code/core/Mage/Webapi/Model/Authorization/Role/Factory.php new file mode 100644 index 0000000000000000000000000000000000000000..e655dea7b27c9f9c47440bfd3ea6a311a8407e7f --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Authorization/Role/Factory.php @@ -0,0 +1,53 @@ +<?php +/** + * Factory for Mage_Webapi_Model_Authorization_Role + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Authorization_Role_Factory +{ + const ROLE_CLASS_NAME = 'Mage_Webapi_Model_Authorization_Role'; + + /** + * @var Magento_ObjectManager + */ + protected $_objectManager; + + /** + * @param Magento_ObjectManager $objectManager + */ + public function __construct(Magento_ObjectManager $objectManager) + { + $this->_objectManager = $objectManager; + } + + /** + * Return new ACL role model. + * + * @param array $arguments + * @return Mage_Webapi_Model_Authorization_Role + */ + public function createRole(array $arguments = array()) + { + return $this->_objectManager->create(self::ROLE_CLASS_NAME, $arguments, false); + } +} diff --git a/app/code/core/Mage/Webapi/Model/Authorization/RoleLocator.php b/app/code/core/Mage/Webapi/Model/Authorization/RoleLocator.php new file mode 100644 index 0000000000000000000000000000000000000000..281301f34471527d05d79e94acbacb9721be7b1c --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Authorization/RoleLocator.php @@ -0,0 +1,62 @@ +<?php +/** + * API ACL RoleLocator + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Authorization_RoleLocator implements Magento_Authorization_RoleLocator +{ + /** + * @var string|null + */ + protected $_roleId = null; + + /** + * Initialize role ID. + * + * @param array $data + */ + public function __construct(array $data = array()) + { + $this->_roleId = isset($data['roleId']) ? $data['roleId'] : null; + } + + /** + * Set role ID into role locator. + * + * @param string $roleId + */ + public function setRoleId($roleId) + { + $this->_roleId = $roleId; + } + + /** + * Retrieve current role. + * + * @return string|null + */ + public function getAclRoleId() + { + return $this->_roleId; + } +} diff --git a/app/code/core/Mage/Webapi/Model/Config/Reader/ClassReflectorAbstract.php b/app/code/core/Mage/Webapi/Model/Config/Reader/ClassReflectorAbstract.php new file mode 100644 index 0000000000000000000000000000000000000000..b0210c5b19f4f2484d0af37625d6bf22fce9f145 --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Config/Reader/ClassReflectorAbstract.php @@ -0,0 +1,285 @@ +<?php +use Zend\Server\Reflection, + Zend\Code\Reflection\DocBlockReflection, + Zend\Server\Reflection\ReflectionMethod; + +/** + * Abstract class reflector for config reader. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +abstract class Mage_Webapi_Model_Config_Reader_ClassReflectorAbstract +{ + /** @var Mage_Webapi_Helper_Config */ + protected $_helper; + + /** @var Mage_Webapi_Model_Config_Reader_TypeProcessor */ + protected $_typeProcessor; + + /** + * Construct reflector. + * + * @param Mage_Webapi_Helper_Config $helper + * @param Mage_Webapi_Model_Config_Reader_TypeProcessor $typeProcessor + */ + public function __construct( + Mage_Webapi_Helper_Config $helper, + Mage_Webapi_Model_Config_Reader_TypeProcessor $typeProcessor + ) { + $this->_helper = $helper; + $this->_typeProcessor = $typeProcessor; + } + + /** + * Retrieve data that has been collected during reflection of all classes. + * + * @return array + */ + abstract public function getPostReflectionData(); + + /** + * Reflect methods in given class and set retrieved data into reader. + * + * @param $className + * @return array + */ + public function reflectClassMethods($className) + { + $data = array( + 'controller' => $className, + ); + $serverReflection = new Reflection; + foreach ($serverReflection->reflectClass($className)->getMethods() as $methodReflection) { + try { + $method = $this->getMethodNameWithoutVersionSuffix($methodReflection); + } catch (InvalidArgumentException $e) { + /** Resources can contain methods that should not be exposed through API. */ + continue; + } + $version = $this->getMethodVersion($methodReflection); + if ($version) { + $data['versions'][$version]['methods'][$method] = $this->extractMethodData($methodReflection); + } + } + // Sort versions array for further fallback. + ksort($data['versions']); + + return array( + 'resources' => array( + $this->_helper->translateResourceName($className) => $data, + ), + ); + } + + /** + * Identify API method name without version suffix by its reflection. + * + * @param ReflectionMethod|string $method Method name or method reflection. + * @return string Method name without version suffix on success. + * @throws InvalidArgumentException When method name is invalid API resource method. + */ + public function getMethodNameWithoutVersionSuffix($method) + { + if ($method instanceof ReflectionMethod) { + $methodNameWithSuffix = $method->getName(); + } else { + $methodNameWithSuffix = $method; + } + $regularExpression = $this->_getMethodNameRegularExpression(); + if (preg_match($regularExpression, $methodNameWithSuffix, $methodMatches)) { + $methodName = $methodMatches[1]; + return $methodName; + } + throw new InvalidArgumentException(sprintf('"%s" is an invalid API resource method.', $methodNameWithSuffix)); + } + + /** + * Identify API method version by its reflection. + * + * @param ReflectionMethod $methodReflection + * @return string|bool Method version with prefix on success. + * false is returned in case when method should not be exposed via API. + */ + public function getMethodVersion(ReflectionMethod $methodReflection) + { + $methodVersion = false; + $methodNameWithSuffix = $methodReflection->getName(); + $regularExpression = $this->_getMethodNameRegularExpression(); + if (preg_match($regularExpression, $methodNameWithSuffix, $methodMatches)) { + $resourceNamePosition = 2; + $methodVersion = ucfirst($methodMatches[$resourceNamePosition]); + } + return $methodVersion; + } + + /** + * Get regular expression to be used for method name separation into name itself and version. + * + * @return string + */ + protected function _getMethodNameRegularExpression() + { + return sprintf('/(%s)(V\d+)/', implode('|', Mage_Webapi_Controller_ActionAbstract::getAllowedMethods())); + } + + /** + * Retrieve method interface and documentation description. + * + * @param ReflectionMethod $method + * @return array + * @throws InvalidArgumentException + */ + public function extractMethodData(ReflectionMethod $method) + { + $methodData = array('documentation' => $method->getDescription()); + $prototypes = $method->getPrototypes(); + /** Take the fullest interface that also includes optional parameters. */ + /** @var \Zend\Server\Reflection\Prototype $prototype */ + $prototype = end($prototypes); + /** @var \Zend\Server\Reflection\ReflectionParameter $parameter */ + foreach ($prototype->getParameters() as $parameter) { + $parameterData = array( + 'type' => $this->_typeProcessor->process($parameter->getType()), + 'required' => !$parameter->isOptional(), + 'documentation' => $parameter->getDescription(), + ); + if ($parameter->isOptional()) { + $parameterData['default'] = $parameter->getDefaultValue(); + } + $methodData['interface']['in']['parameters'][$parameter->getName()] = $parameterData; + } + if ($prototype->getReturnType() != 'void') { + $methodData['interface']['out']['parameters']['result'] = array( + 'type' => $this->_typeProcessor->process($prototype->getReturnType()), + 'documentation' => $prototype->getReturnValue()->getDescription(), + 'required' => true, + ); + } + $deprecationPolicy = $this->_extractDeprecationPolicy($method); + if ($deprecationPolicy) { + $methodData['deprecation_policy'] = $deprecationPolicy; + } + + return $methodData; + } + + /** + * Extract method deprecation policy. + * + * Return result in the following format:<pre> + * array( + * 'removed' => true, // either 'deprecated' or 'removed' item must be specified + * 'deprecated' => true, + * 'use_resource' => 'operationName' // resource to be used instead + * 'use_method' => 'operationName' // method to be used instead + * 'use_version' => N, // version of method to be used instead + * ) + * </pre> + * + * @param ReflectionMethod $methodReflection + * @return array|bool On success array with policy details; false otherwise. + * @throws LogicException If deprecation tag format is incorrect. + */ + protected function _extractDeprecationPolicy(ReflectionMethod $methodReflection) + { + $deprecationPolicy = false; + $methodDocumentation = $methodReflection->getDocComment(); + if ($methodDocumentation) { + /** Zend server reflection is not able to work with annotation tags of the method. */ + $docBlock = new DocBlockReflection($methodDocumentation); + $removedTag = $docBlock->getTag('apiRemoved'); + $deprecatedTag = $docBlock->getTag('apiDeprecated'); + if ($removedTag) { + $deprecationPolicy = array('removed' => true); + $useMethod = $removedTag->getContent(); + } elseif ($deprecatedTag) { + $deprecationPolicy = array('deprecated' => true); + $useMethod = $deprecatedTag->getContent(); + } + + if (isset($useMethod) && is_string($useMethod) && !empty($useMethod)) { + $this->_extractDeprecationPolicyUseMethod($methodReflection, $useMethod, $deprecationPolicy); + } + } + return $deprecationPolicy; + } + + /** + * Extract method deprecation policy "use method" data. + * + * @param ReflectionMethod $methodReflection + * @param string $useMethod + * @param array $deprecationPolicy + * @throws LogicException + */ + protected function _extractDeprecationPolicyUseMethod( + ReflectionMethod $methodReflection, + $useMethod, + &$deprecationPolicy + ) { + $invalidFormatMessage = sprintf( + 'The "%s" method has invalid format of Deprecation policy. ' + . 'Accepted formats are createV1, catalogProduct::createV1 ' + . 'and Mage_Catalog_Webapi_ProductController::createV1.', + $methodReflection->getDeclaringClass()->getName() . '::' . $methodReflection->getName() + ); + /** Add information about what method should be used instead of deprecated/removed one. */ + /** + * Description is expected in one of the following formats: + * - Mage_Catalog_Webapi_ProductController::createV1 + * - catalogProduct::createV1 + * - createV1 + */ + $useMethodParts = explode('::', $useMethod); + switch (count($useMethodParts)) { + case 2: + try { + /** Support of: Mage_Catalog_Webapi_ProductController::createV1 */ + $resourceName = $this->_helper->translateResourceName($useMethodParts[0]); + } catch (InvalidArgumentException $e) { + /** Support of: catalogProduct::createV1 */ + $resourceName = $useMethodParts[0]; + } + $deprecationPolicy['use_resource'] = $resourceName; + $methodName = $useMethodParts[1]; + break; + case 1: + $methodName = $useMethodParts[0]; + /** If resource was not specified, current one should be used. */ + $deprecationPolicy['use_resource'] = $this->_helper->translateResourceName( + $methodReflection->getDeclaringClass()->getName() + ); + break; + default: + throw new LogicException($invalidFormatMessage); + break; + } + try { + $methodWithoutVersion = $this->getMethodNameWithoutVersionSuffix($methodName); + } catch (Exception $e) { + throw new LogicException($invalidFormatMessage); + } + $deprecationPolicy['use_method'] = $methodWithoutVersion; + $methodVersion = str_replace($methodWithoutVersion, '', $methodName); + $deprecationPolicy['use_version'] = ucfirst($methodVersion); + } +} diff --git a/app/code/core/Mage/Webapi/Model/Config/Reader/Rest.php b/app/code/core/Mage/Webapi/Model/Config/Reader/Rest.php new file mode 100644 index 0000000000000000000000000000000000000000..fbec1096a84c04d822bfd8ae22c72351ed132075 --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Config/Reader/Rest.php @@ -0,0 +1,57 @@ +<?php +/** + * REST specific API config reader. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Config_Reader_Rest extends Mage_Webapi_Model_Config_ReaderAbstract +{ + /** + * Config type. + */ + const CONFIG_TYPE = 'REST'; + + /** + * Construct config reader with REST class reflector. + * + * @param Mage_Webapi_Model_Config_Reader_Rest_ClassReflector $classReflector + * @param Mage_Core_Model_Config $appConfig + * @param Mage_Core_Model_Cache $cache + */ + public function __construct( + Mage_Webapi_Model_Config_Reader_Rest_ClassReflector $classReflector, + Mage_Core_Model_Config $appConfig, + Mage_Core_Model_Cache $cache + ) { + parent::__construct($classReflector, $appConfig, $cache); + } + + /** + * Retrieve cache ID. + * + * @return string + */ + public function getCacheId() + { + return self::CONFIG_CACHE_ID . '-' . self::CONFIG_TYPE; + } +} diff --git a/app/code/core/Mage/Webapi/Model/Config/Reader/Rest/ClassReflector.php b/app/code/core/Mage/Webapi/Model/Config/Reader/Rest/ClassReflector.php new file mode 100644 index 0000000000000000000000000000000000000000..ada41e259a11b2d2ddd4dba622d8f729d52b9bb3 --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Config/Reader/Rest/ClassReflector.php @@ -0,0 +1,77 @@ +<?php +use Zend\Server\Reflection\ReflectionMethod; + +/** + * REST API specific class reflector. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Config_Reader_Rest_ClassReflector extends Mage_Webapi_Model_Config_Reader_ClassReflectorAbstract +{ + /** @var Mage_Webapi_Model_Config_Reader_Rest_RouteGenerator */ + protected $_routeGenerator; + + /** + * Construct reflector with route generator. + * + * @param Mage_Webapi_Helper_Config $helper + * @param Mage_Webapi_Model_Config_Reader_TypeProcessor $typeProcessor + * @param Mage_Webapi_Model_Config_Reader_Rest_RouteGenerator $routeGenerator + */ + public function __construct( + Mage_Webapi_Helper_Config $helper, + Mage_Webapi_Model_Config_Reader_TypeProcessor $typeProcessor, + Mage_Webapi_Model_Config_Reader_Rest_RouteGenerator $routeGenerator + ) { + parent::__construct($helper, $typeProcessor); + $this->_routeGenerator = $routeGenerator; + } + + /** + * Set types and REST routes data into reader after reflecting all files. + * + * @return array + */ + public function getPostReflectionData() + { + return array( + 'types' => $this->_typeProcessor->getTypesData(), + 'type_to_class_map' => $this->_typeProcessor->getTypeToClassMap(), + 'rest_routes' => $this->_routeGenerator->getRoutes(), + ); + } + + /** + * Add REST routes to method data. + * + * @param Zend\Server\Reflection\ReflectionMethod $method + * @return array + */ + public function extractMethodData(ReflectionMethod $method) + { + $methodData = parent::extractMethodData($method); + $restRoutes = $this->_routeGenerator->generateRestRoutes($method); + $methodData['rest_routes'] = array_keys($restRoutes); + + return $methodData; + } +} diff --git a/app/code/core/Mage/Webapi/Model/Config/Reader/Rest/RouteGenerator.php b/app/code/core/Mage/Webapi/Model/Config/Reader/Rest/RouteGenerator.php new file mode 100644 index 0000000000000000000000000000000000000000..5bdb454bc156b846b3f47f7a33e5f33c83ecb3ee --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Config/Reader/Rest/RouteGenerator.php @@ -0,0 +1,233 @@ +<?php +use Zend\Server\Reflection\ReflectionMethod; + +/** + * REST routes generator. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Config_Reader_Rest_RouteGenerator +{ + /** @var array */ + protected $_routes = array(); + + /** + * @var Mage_Webapi_Helper_Config + */ + protected $_helper; + + /** + * Construct routes generator. + * + * @param Mage_Webapi_Helper_Config $helper + */ + public function __construct(Mage_Webapi_Helper_Config $helper) + { + $this->_helper = $helper; + } + + /** + * Generate a list of routes available fo the specified method. + * + * @param ReflectionMethod $methodReflection + * @return array + */ + public function generateRestRoutes(ReflectionMethod $methodReflection) + { + $routes = array(); + $routePath = "/:" . Mage_Webapi_Controller_Router_Route_Rest::PARAM_VERSION; + $routeParts = $this->_helper->getResourceNameParts($methodReflection->getDeclaringClass()->getName()); + $partsCount = count($routeParts); + for ($i = 0; $i < $partsCount; $i++) { + if ($this->_isParentResourceIdExpected($methodReflection) + /** + * In case of subresource route, parent ID must be specified before the last route part. + * E.g.: /v1/grandParent/parent/:parentId/resource + */ + && ($i == ($partsCount - 1)) + ) { + $routePath .= "/:" . Mage_Webapi_Controller_Router_Route_Rest::PARAM_PARENT_ID; + } + $routePath .= "/" . lcfirst($this->_helper->convertSingularToPlural($routeParts[$i])); + } + if ($this->_isResourceIdExpected($methodReflection)) { + $routePath .= "/:" . Mage_Webapi_Controller_Router_Route_Rest::PARAM_ID; + } + + foreach ($this->_getAdditionalRequiredParamNames($methodReflection) as $additionalRequired) { + $routePath .= "/$additionalRequired/:$additionalRequired"; + } + + $actionType = Mage_Webapi_Controller_Request_Rest::getActionTypeByOperation( + $this->_helper->getMethodNameWithoutVersionSuffix($methodReflection) + ); + $resourceName = $this->_helper->translateResourceName($methodReflection->getDeclaringClass()->getName()); + $optionalParams = $this->_getOptionalParamNames($methodReflection); + foreach ($this->_getPathCombinations($optionalParams, $routePath) as $finalRoutePath) { + $routes[$finalRoutePath] = array('actionType' => $actionType, 'resourceName' => $resourceName); + } + + $this->_routes = array_merge($this->_routes, $routes); + return $routes; + } + + /** + * Retrieve all generated routes. + * + * @return array + */ + public function getRoutes() + { + return $this->_routes; + } + + /** + * Identify if method expects Parent resource ID to be present in the request. + * + * @param Zend\Server\Reflection\ReflectionMethod $methodReflection + * @return bool + */ + protected function _isParentResourceIdExpected(ReflectionMethod $methodReflection) + { + $isIdFieldExpected = false; + if ($this->_helper->isSubresource($methodReflection)) { + $methodsWithParentId = array( + Mage_Webapi_Controller_ActionAbstract::METHOD_CREATE, + Mage_Webapi_Controller_ActionAbstract::METHOD_LIST, + Mage_Webapi_Controller_ActionAbstract::METHOD_MULTI_UPDATE, + Mage_Webapi_Controller_ActionAbstract::METHOD_MULTI_DELETE, + Mage_Webapi_Controller_ActionAbstract::METHOD_MULTI_CREATE, + ); + $methodName = $this->_helper->getMethodNameWithoutVersionSuffix($methodReflection); + if (in_array($methodName, $methodsWithParentId)) { + $isIdFieldExpected = true; + } + } + return $isIdFieldExpected; + } + + /** + * Identify if method expects Resource ID to be present in the request. + * + * @param Zend\Server\Reflection\ReflectionMethod $methodReflection + * @return bool + */ + protected function _isResourceIdExpected(ReflectionMethod $methodReflection) + { + $isIdFieldExpected = false; + $methodsWithId = array( + Mage_Webapi_Controller_ActionAbstract::METHOD_GET, + Mage_Webapi_Controller_ActionAbstract::METHOD_UPDATE, + Mage_Webapi_Controller_ActionAbstract::METHOD_DELETE, + ); + $methodName = $this->_helper->getMethodNameWithoutVersionSuffix($methodReflection); + if (in_array($methodName, $methodsWithId)) { + $isIdFieldExpected = true; + } + return $isIdFieldExpected; + } + + /** + * Retrieve the list of names of required params except ID and Request body. + * + * @param ReflectionMethod $methodReflection + * @return array + */ + protected function _getAdditionalRequiredParamNames(ReflectionMethod $methodReflection) + { + $paramNames = array(); + $methodInterfaces = $methodReflection->getPrototypes(); + /** Take the fullest interface that includes optional parameters also. */ + /** @var \Zend\Server\Reflection\Prototype $methodInterface */ + $methodInterface = end($methodInterfaces); + $methodParams = $methodInterface->getParameters(); + $idParamName = $this->_helper->getOperationIdParamName($methodReflection); + $bodyParamName = $this->_helper->getOperationBodyParamName($methodReflection); + /** @var ReflectionParameter $paramReflection */ + foreach ($methodParams as $paramReflection) { + if (!$paramReflection->isOptional() + && $paramReflection->getName() != $bodyParamName + && $paramReflection->getName() != $idParamName + ) { + $paramNames[] = $paramReflection->getName(); + } + } + return $paramNames; + } + + /** + * Generate list of possible routes taking into account optional params. + * + * Note: this is called recursively. + * + * @param array $optionalParams + * @param string $basePath + * @return array List of possible route params + */ + /** + * TODO: Assure that performance is not heavily impacted during routes match process. + * It can happen due creation of routes with optional parameters. HTTP get parameters can be used for that. + */ + protected function _getPathCombinations($optionalParams, $basePath) + { + $pathCombinations = array(); + /** Add current base path to the resulting array of routes. */ + $pathCombinations[] = $basePath; + foreach ($optionalParams as $key => $paramName) { + /** Add current param name to the route path and make recursive call. */ + $paramsWithoutCurrent = $optionalParams; + unset($paramsWithoutCurrent[$key]); + $currentPath = "$basePath/$paramName/:$paramName"; + $pathCombinations = array_merge( + $pathCombinations, + $this->_getPathCombinations( + $paramsWithoutCurrent, + $currentPath + ) + ); + } + return $pathCombinations; + } + + /** + * Retrieve all optional parameters names. + * + * @param ReflectionMethod $methodReflection + * @return array + */ + protected function _getOptionalParamNames(ReflectionMethod $methodReflection) + { + $optionalParamNames = array(); + $methodInterfaces = $methodReflection->getPrototypes(); + /** Take the fullest interface that includes optional parameters also. */ + /** @var \Zend\Server\Reflection\Prototype $methodInterface */ + $methodInterface = end($methodInterfaces); + $methodParams = $methodInterface->getParameters(); + /** @var ReflectionParameter $paramReflection */ + foreach ($methodParams as $paramReflection) { + if ($paramReflection->isOptional()) { + $optionalParamNames[] = $paramReflection->getName(); + } + } + return $optionalParamNames; + } +} diff --git a/app/code/core/Mage/Webapi/Model/Config/Reader/Soap.php b/app/code/core/Mage/Webapi/Model/Config/Reader/Soap.php new file mode 100644 index 0000000000000000000000000000000000000000..6b33c190ca49eb7f7dd8ed38d44497749d044c7d --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Config/Reader/Soap.php @@ -0,0 +1,57 @@ +<?php +/** + * SOAP specific API config reader. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Config_Reader_Soap extends Mage_Webapi_Model_Config_ReaderAbstract +{ + /** + * Config type. + */ + const CONFIG_TYPE = 'SOAP'; + + /** + * Construct config reader with SOAP class reflector. + * + * @param Mage_Webapi_Model_Config_Reader_Soap_ClassReflector $classReflector + * @param Mage_Core_Model_Config $appConfig + * @param Mage_Core_Model_Cache $cache + */ + public function __construct( + Mage_Webapi_Model_Config_Reader_Soap_ClassReflector $classReflector, + Mage_Core_Model_Config $appConfig, + Mage_Core_Model_Cache $cache + ) { + parent::__construct($classReflector, $appConfig, $cache); + } + + /** + * Retrieve cache ID. + * + * @return string + */ + public function getCacheId() + { + return self::CONFIG_CACHE_ID . '-' . self::CONFIG_TYPE; + } +} diff --git a/app/code/core/Mage/Api/controllers/IndexController.php b/app/code/core/Mage/Webapi/Model/Config/Reader/Soap/ClassReflector.php similarity index 65% rename from app/code/core/Mage/Api/controllers/IndexController.php rename to app/code/core/Mage/Webapi/Model/Config/Reader/Soap/ClassReflector.php index 174536a6fe1245144a34f3ab9bead60099bd9255..4c0cd7cd15f0c20e9dbd83f7d1ea327250ffc62c 100644 --- a/app/code/core/Mage/Api/controllers/IndexController.php +++ b/app/code/core/Mage/Webapi/Model/Config/Reader/Soap/ClassReflector.php @@ -1,5 +1,7 @@ <?php /** + * SOAP API specific class reflector. + * * Magento * * NOTICE OF LICENSE @@ -18,25 +20,22 @@ * versions in the future. If you wish to customize Magento for your * needs please refer to http://www.magentocommerce.com for more information. * - * @category Mage - * @package Mage_Api * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ - -/** - * Webservice main controller - * - * @category Mage - * @package Mage_Api - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api_IndexController extends Mage_Api_Controller_Action +class Mage_Webapi_Model_Config_Reader_Soap_ClassReflector + extends Mage_Webapi_Model_Config_Reader_ClassReflectorAbstract { - public function indexAction() + /** + * Set types data into reader after reflecting all files. + * + * @return array + */ + public function getPostReflectionData() { - /* @var $server Mage_Api_Model_Server */ - $this->_getServer()->init($this) - ->run(); + return array( + 'types' => $this->_typeProcessor->getTypesData(), + 'type_to_class_map' => $this->_typeProcessor->getTypeToClassMap(), + ); } -} // Class Mage_Api_IndexController End +} diff --git a/app/code/core/Mage/Webapi/Model/Config/Reader/TypeProcessor.php b/app/code/core/Mage/Webapi/Model/Config/Reader/TypeProcessor.php new file mode 100644 index 0000000000000000000000000000000000000000..478e56c01e81b78e8c80fd0114518cae159f6b9f --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Config/Reader/TypeProcessor.php @@ -0,0 +1,194 @@ +<?php +use Zend\Code\Reflection\ClassReflection; + +/** + * Type processor of config reader properties + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Config_Reader_TypeProcessor +{ + /** @var Mage_Webapi_Helper_Config */ + protected $_helper; + + /** + * Array of types data. + * + * @var array + */ + protected $_types; + + /** + * Types class map. + * + * @var array + */ + protected $_typeToClassMap; + + /** + * Construct type processor. + * + * @param Mage_Webapi_Helper_Config $helper + */ + public function __construct(Mage_Webapi_Helper_Config $helper) + { + $this->_helper = $helper; + } + + /** + * Retrieve processed types data. + * + * @return array + */ + public function getTypesData() + { + return $this->_types; + } + + /** + * Retrieve processed types to class map. + * + * @return array + */ + public function getTypeToClassMap() + { + return $this->_typeToClassMap; + } + + /** + * Process type name. + * In case parameter type is a complex type (class) - process its properties. + * + * @param string $type + * @return string + */ + public function process($type) + { + $typeName = $this->_helper->normalizeType($type); + if (!$this->_helper->isTypeSimple($typeName)) { + $complexTypeName = $this->_helper->translateTypeName($type); + if (!isset($this->_types[$complexTypeName])) { + $this->_processComplexType($type); + if (!$this->_helper->isArrayType($complexTypeName)) { + $this->_typeToClassMap[$complexTypeName] = $type; + } + } + $typeName = $complexTypeName; + } + + return $typeName; + } + + /** + * Retrieve complex type information from class public properties. + * + * @param string $class + * @return array + * @throws InvalidArgumentException + */ + protected function _processComplexType($class) + { + $typeName = $this->_helper->translateTypeName($class); + $this->_types[$typeName] = array(); + if ($this->_helper->isArrayType($class)) { + $this->process($this->_helper->getArrayItemType($class)); + } else { + if (!class_exists($class)) { + throw new InvalidArgumentException(sprintf('Could not load the "%s" class as parameter type.', $class)); + } + $reflection = new ClassReflection($class); + $docBlock = $reflection->getDocBlock(); + $this->_types[$typeName]['documentation'] = $docBlock ? $this->_getDescription($docBlock) : ''; + $defaultProperties = $reflection->getDefaultProperties(); + /** @var \Zend\Code\Reflection\PropertyReflection $property */ + foreach ($reflection->getProperties(ReflectionProperty::IS_PUBLIC) as $property) { + $this->_processProperty($property, $defaultProperties, $typeName); + } + } + + return $this->_types[$typeName]; + } + + /** + * Process class property. + * + * @param Zend\Code\Reflection\PropertyReflection $property + * @param $defaultProperties + * @param $typeName + * @throws InvalidArgumentException + */ + protected function _processProperty( + \Zend\Code\Reflection\PropertyReflection $property, + $defaultProperties, + $typeName + ) { + $propertyName = $property->getName(); + $propertyDocBlock = $property->getDocBlock(); + if (!$propertyDocBlock) { + throw new InvalidArgumentException('Each property must have description with @var annotation.'); + } + $varTags = $propertyDocBlock->getTags('var'); + if (empty($varTags)) { + throw new InvalidArgumentException('Property type must be defined with @var tag.'); + } + /** @var \Zend\Code\Reflection\DocBlock\Tag\GenericTag $varTag */ + $varTag = current($varTags); + $varContentParts = explode(' ', $varTag->getContent(), 2); + $varType = current($varContentParts); + $varInlineDoc = (count($varContentParts) > 1) ? end($varContentParts) : ''; + $optionalTags = $propertyDocBlock->getTags('optional'); + if (!empty($optionalTags)) { + /** @var \Zend\Code\Reflection\DocBlock\Tag\GenericTag $isOptionalTag */ + $isOptionalTag = current($optionalTags); + $isOptional = $isOptionalTag->getName() == 'optional'; + } else { + $isOptional = false; + } + + $this->_types[$typeName]['parameters'][$propertyName] = array( + 'type' => $this->process($varType), + 'required' => !$isOptional && is_null($defaultProperties[$propertyName]), + 'default' => $defaultProperties[$propertyName], + 'documentation' => $varInlineDoc . $this->_getDescription($propertyDocBlock) + ); + } + + /** + * Get short and long description from docblock and concatenate. + * + * @param Zend\Code\Reflection\DocBlockReflection $doc + * @return string + */ + protected function _getDescription(\Zend\Code\Reflection\DocBlockReflection $doc) + { + $shortDescription = $doc->getShortDescription(); + $longDescription = $doc->getLongDescription(); + + $description = $shortDescription; + if ($longDescription && !empty($description)) { + $description .= "\r\n"; + } + $description .= $longDescription; + + return $description; + } +} diff --git a/app/code/core/Mage/Webapi/Model/Config/ReaderAbstract.php b/app/code/core/Mage/Webapi/Model/Config/ReaderAbstract.php new file mode 100644 index 0000000000000000000000000000000000000000..f078468a05d72a76c8c7b56aea0ad0a0f07f2814 --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Config/ReaderAbstract.php @@ -0,0 +1,204 @@ +<?php +/** + * Abstract config data reader. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +abstract class Mage_Webapi_Model_Config_ReaderAbstract +{ + /** + * Cache ID for resource config. + */ + const CONFIG_CACHE_ID = 'API-RESOURCE-CACHE'; + + /** + * Pattern for API action controllers class name. + */ + const RESOURCE_CLASS_PATTERN = '/^(.*)_(.*)_Controller_Webapi(_.*)+$/'; + + /** + * @var Zend\Code\Scanner\DirectoryScanner + */ + protected $_directoryScanner; + + /** + * @var Mage_Webapi_Model_Config_Reader_ClassReflectorAbstract + */ + protected $_classReflector; + + /** + * @var Mage_Core_Model_Config + */ + protected $_applicationConfig; + + /** + * @var Mage_Core_Model_Cache + */ + protected $_cache; + + /** + * @var array + */ + protected $_data = array(); + + /** + * Construct config reader. + * + * @param Mage_Webapi_Model_Config_Reader_ClassReflectorAbstract $classReflector + * @param Mage_Core_Model_Config $appConfig + * @param Mage_Core_Model_Cache $cache + */ + public function __construct( + Mage_Webapi_Model_Config_Reader_ClassReflectorAbstract $classReflector, + Mage_Core_Model_Config $appConfig, + Mage_Core_Model_Cache $cache + ) { + $this->_classReflector = $classReflector; + $this->_applicationConfig = $appConfig; + $this->_cache = $cache; + } + + /** + * Retrieve cache ID. + * + * @return string + */ + abstract public function getCacheId(); + + /** + * Get current directory scanner. Initialize if it was not initialized previously. + * + * @return Zend\Code\Scanner\DirectoryScanner + */ + public function getDirectoryScanner() + { + if (!$this->_directoryScanner) { + $this->_directoryScanner = new Zend\Code\Scanner\DirectoryScanner(); + /** @var Mage_Core_Model_Config_Element $module */ + foreach ($this->_applicationConfig->getNode('modules')->children() as $moduleName => $module) { + if ($module->is('active')) { + /** Invalid type is specified to retrieve path to module directory. */ + $moduleDir = $this->_applicationConfig->getModuleDir('invalid_type', $moduleName); + $directory = $moduleDir . DS . 'Controller' . DS . 'Webapi'; + if (is_dir($directory)) { + $this->_directoryScanner->addDirectory($directory); + } + } + } + } + + return $this->_directoryScanner; + } + + /** + * Set directory scanner object. + * + * @param Zend\Code\Scanner\DirectoryScanner $directoryScanner + */ + public function setDirectoryScanner(Zend\Code\Scanner\DirectoryScanner $directoryScanner) + { + $this->_directoryScanner = $directoryScanner; + } + + /** + * Read configuration data from the action controllers files using class reflector. + * + * @throws InvalidArgumentException + * @throws LogicException + * @return array + */ + public function getData() + { + if (!$this->_data && !$this->_loadDataFromCache()) { + /** @var \Zend\Code\Scanner\FileScanner $file */ + foreach ($this->getDirectoryScanner()->getFiles(true) as $file) { + $filename = $file->getFile(); + $classes = $file->getClasses(); + if (count($classes) > 1) { + throw new LogicException(sprintf( + 'There can be only one class in the "%s" controller file .', + $filename + )); + } + /** @var \Zend\Code\Scanner\ClassScanner $class */ + $class = current($classes); + $className = $class->getName(); + if (preg_match(self::RESOURCE_CLASS_PATTERN, $className)) { + $classData = $this->_classReflector->reflectClassMethods($className); + $this->_addData($classData); + } + } + $postReflectionData = $this->_classReflector->getPostReflectionData(); + $this->_addData($postReflectionData); + + if (!isset($this->_data['resources'])) { + throw new LogicException('Cannot populate config - no action controllers were found.'); + } + + $this->_saveDataToCache(); + } + + return $this->_data; + } + + /** + * Add data to reader. + * + * @param array $data + */ + protected function _addData($data) + { + $this->_data = array_merge_recursive($this->_data, $data); + } + + /** + * Load config data from cache. + * + * @return bool Return true on successful load; false otherwise + */ + protected function _loadDataFromCache() + { + $isLoaded = false; + if ($this->_cache->canUse(Mage_Webapi_Model_ConfigAbstract::WEBSERVICE_CACHE_NAME)) { + $cachedData = $this->_cache->load($this->getCacheId()); + if ($cachedData !== false) { + $this->_data = unserialize($cachedData); + $isLoaded = true; + } + } + return $isLoaded; + } + + /** + * Save data to cache if it is enabled. + */ + protected function _saveDataToCache() + { + if ($this->_cache->canUse(Mage_Webapi_Model_ConfigAbstract::WEBSERVICE_CACHE_NAME)) { + $this->_cache->save( + serialize($this->_data), + $this->getCacheId(), + array(Mage_Webapi_Model_ConfigAbstract::WEBSERVICE_CACHE_TAG) + ); + } + } +} diff --git a/app/code/core/Mage/Webapi/Model/Config/Rest.php b/app/code/core/Mage/Webapi/Model/Config/Rest.php new file mode 100644 index 0000000000000000000000000000000000000000..438d4bafcf90c43a64ca35eb57067b277007ecad --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Config/Rest.php @@ -0,0 +1,135 @@ +<?php +/** + * REST specific API config. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Config_Rest extends Mage_Webapi_Model_ConfigAbstract +{ + /** @var Magento_Controller_Router_Route_Factory */ + protected $_routeFactory; + + /** + * Construct config with REST reader & route factory. + * + * @param Mage_Webapi_Model_Config_Reader_Rest $reader + * @param Mage_Webapi_Helper_Config $helper + * @param Mage_Core_Model_App $app + * @param Magento_Controller_Router_Route_Factory $routeFactory + */ + public function __construct( + Mage_Webapi_Model_Config_Reader_Rest $reader, + Mage_Webapi_Helper_Config $helper, + Mage_Core_Model_App $app, + Magento_Controller_Router_Route_Factory $routeFactory + ) { + parent::__construct($reader, $helper, $app); + $this->_routeFactory = $routeFactory; + } + + /** + * Get all modules routes defined in config. + * + * @return Mage_Webapi_Controller_Router_Route_Rest[] + * @throws LogicException When config data has invalid structure. + */ + public function getAllRestRoutes() + { + $routes = array(); + foreach ($this->_data['rest_routes'] as $routePath => $routeData) { + $routes[] = $this->_createRoute($routePath, $routeData['resourceName'], $routeData['actionType']); + } + return $routes; + } + + /** + * Retrieve a list of all route objects associated with specified method. + * + * @param string $resourceName + * @param string $methodName + * @param string $version + * @return Mage_Webapi_Controller_Router_Route_Rest[] + * @throws InvalidArgumentException + */ + public function getMethodRestRoutes($resourceName, $methodName, $version) + { + $resourceData = $this->_getResourceData($resourceName, $version); + if (!isset($resourceData['methods'][$methodName]['rest_routes'])) { + throw new InvalidArgumentException( + sprintf( + 'The "%s" resource does not have any REST routes for "%s" method.', + $resourceName, + $methodName + )); + } + $routes = array(); + foreach ($resourceData['methods'][$methodName]['rest_routes'] as $routePath) { + $routes[] = $this->_createRoute( + $routePath, + $resourceName, + Mage_Webapi_Controller_Request_Rest::getActionTypeByOperation($methodName) + ); + } + return $routes; + } + + /** + * Identify the shortest available route to the item of specified resource. + * + * @param string $resourceName + * @return string + * @throws InvalidArgumentException + */ + public function getRestRouteToItem($resourceName) + { + $restRoutes = $this->_data['rest_routes']; + /** The shortest routes must go first. */ + ksort($restRoutes); + foreach ($restRoutes as $routePath => $routeMetadata) { + if ($routeMetadata['actionType'] == Mage_Webapi_Controller_Request_Rest::ACTION_TYPE_ITEM + && $routeMetadata['resourceName'] == $resourceName + ) { + return $routePath; + } + } + throw new InvalidArgumentException(sprintf('No route to the item of "%s" resource was found.', $resourceName)); + } + + /** + * Create route object. + * + * @param string $routePath + * @param string $resourceName + * @param string $actionType + * @return Mage_Webapi_Controller_Router_Route_Rest + */ + protected function _createRoute($routePath, $resourceName, $actionType) + { + $apiTypeRoutePath = Mage_Webapi_Controller_Router_Route_Webapi::API_AREA_NAME + . '/:' . Mage_Webapi_Controller_Front::API_TYPE_REST; + $fullRoutePath = $apiTypeRoutePath . $routePath; + /** @var $route Mage_Webapi_Controller_Router_Route_Rest */ + $route = $this->_routeFactory->createRoute('Mage_Webapi_Controller_Router_Route_Rest', $fullRoutePath); + $route->setResourceName($resourceName)->setResourceType($actionType); + return $route; + } +} diff --git a/app/code/core/Mage/Webapi/Model/Config/Soap.php b/app/code/core/Mage/Webapi/Model/Config/Soap.php new file mode 100644 index 0000000000000000000000000000000000000000..c43036abda559882216a689f1b59804bba5ff5c9 --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Config/Soap.php @@ -0,0 +1,101 @@ +<?php +/** + * SOAP specific API config. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Config_Soap extends Mage_Webapi_Model_ConfigAbstract +{ + /** + * Initialize dependencies. + * + * @param Mage_Webapi_Model_Config_Reader_Soap $reader + * @param Mage_Webapi_Helper_Config $helper + * @param Mage_Core_Model_App $app + */ + public function __construct( + Mage_Webapi_Model_Config_Reader_Soap $reader, + Mage_Webapi_Helper_Config $helper, + Mage_Core_Model_App $app + ) { + parent::__construct($reader, $helper, $app); + } + + /** + * Retrieve specific resource version interface data. + * + * Perform metadata merge from previous method versions. + * + * @param string $resourceName + * @param string $resourceVersion Two formats are acceptable: 'v1' and '1' + * @return array + * @throws RuntimeException + */ + public function getResourceDataMerged($resourceName, $resourceVersion) + { + /** Allow to take resource version in two formats: with prefix and without it */ + $resourceVersion = is_numeric($resourceVersion) + ? self::VERSION_NUMBER_PREFIX . $resourceVersion + : ucfirst($resourceVersion); + $this->_checkIfResourceVersionExists($resourceName, $resourceVersion); + $resourceData = array(); + foreach ($this->_data['resources'][$resourceName]['versions'] as $version => $data) { + $resourceData = array_replace_recursive($resourceData, $data); + if ($version == $resourceVersion) { + break; + } + } + return $resourceData; + } + + /** + * Identify resource name by operation name. + * + * If $resourceVersion is set, the check for operation validity in specified resource version will be performed. + * If $resourceVersion is not set, the only check will be: if resource exists. + * + * @param string $operationName + * @param string $resourceVersion Two formats are acceptable: 'v1' and '1' + * @return string|bool Resource name on success; false on failure + */ + public function getResourceNameByOperation($operationName, $resourceVersion = null) + { + list($resourceName, $methodName) = $this->_parseOperationName($operationName); + $resourceExists = isset($this->_data['resources'][$resourceName]); + if (!$resourceExists) { + return false; + } + $resourceData = $this->_data['resources'][$resourceName]; + $versionCheckRequired = is_string($resourceVersion); + if ($versionCheckRequired) { + /** Allow to take resource version in two formats: with prefix and without it */ + $resourceVersion = is_numeric($resourceVersion) + ? self::VERSION_NUMBER_PREFIX . $resourceVersion + : ucfirst($resourceVersion); + $operationIsValid = isset($resourceData['versions'][$resourceVersion]['methods'][$methodName]); + if (!$operationIsValid) { + return false; + } + } + return $resourceName; + } +} diff --git a/app/code/core/Mage/Webapi/Model/ConfigAbstract.php b/app/code/core/Mage/Webapi/Model/ConfigAbstract.php new file mode 100644 index 0000000000000000000000000000000000000000..49ec164803cc3657a86141dc3d5a655db330ba17 --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/ConfigAbstract.php @@ -0,0 +1,451 @@ +<?php +use Zend\Server\Reflection\ReflectionMethod; + +/** + * Web API configuration. + * + * This class is responsible for collecting web API configuration using reflection + * as well as for implementing interface to provide access to collected configuration. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +abstract class Mage_Webapi_Model_ConfigAbstract +{ + /**#@+ + * Cache parameters. + */ + const WEBSERVICE_CACHE_NAME = 'config_webservice'; + const WEBSERVICE_CACHE_TAG = 'WEBSERVICE'; + /**#@-*/ + + /**#@+ + * Version parameters. + */ + const VERSION_NUMBER_PREFIX = 'V'; + const VERSION_MIN = 1; + /**#@-*/ + + /** @var Mage_Webapi_Model_Config_ReaderAbstract */ + protected $_reader; + + /** @var Mage_Webapi_Helper_Config */ + protected $_helper; + + /** @var Mage_Core_Model_App */ + protected $_app; + + /** + * Resources configuration data. + * + * @var array + */ + protected $_data; + + /** + * Initialize dependencies. Initialize data. + * + * @param Mage_Webapi_Model_Config_ReaderAbstract $reader + * @param Mage_Webapi_Helper_Config $helper + * @param Mage_Core_Model_App $app + */ + public function __construct( + Mage_Webapi_Model_Config_ReaderAbstract $reader, + Mage_Webapi_Helper_Config $helper, + Mage_Core_Model_App $app + ) { + $this->_reader = $reader; + $this->_helper = $helper; + $this->_app = $app; + $this->_data = $this->_reader->getData(); + } + + /** + * Retrieve data type details for the given type name. + * + * @param string $typeName + * @return array + * @throws InvalidArgumentException + */ + public function getTypeData($typeName) + { + if (!isset($this->_data['types'][$typeName])) { + throw new InvalidArgumentException(sprintf('Data type "%s" was not found in config.', $typeName)); + } + return $this->_data['types'][$typeName]; + } + + /** + * Add or update type data in config. + * + * @param string $typeName + * @param array $data + */ + public function setTypeData($typeName, $data) + { + if (!isset($this->_data['types'][$typeName])) { + $this->_data['types'][$typeName] = $data; + } else { + $this->_data['types'][$typeName] = array_merge_recursive($this->_data['types'][$typeName], $data); + } + } + + /** + * Identify method name by operation name. + * + * @param string $operationName + * @param string $resourceVersion Two formats are acceptable: 'v1' and '1' + * @return string|bool Method name on success; false on failure + */ + public function getMethodNameByOperation($operationName, $resourceVersion = null) + { + list($resourceName, $methodName) = $this->_parseOperationName($operationName); + $versionCheckRequired = is_string($resourceVersion); + if (!$versionCheckRequired) { + return $methodName; + } + /** Allow to take resource version in two formats: with prefix and without it */ + $resourceVersion = is_numeric($resourceVersion) + ? self::VERSION_NUMBER_PREFIX . $resourceVersion + : ucfirst($resourceVersion); + return isset($this->_data['resources'][$resourceName]['versions'][$resourceVersion]['methods'][$methodName]) + ? $methodName : false; + } + + /** + * Parse operation name to separate resource name from method name. + * + * <pre>Result format: + * array( + * 0 => 'resourceName', + * 1 => 'methodName' + * )</pre> + * + * @param string $operationName + * @return array + * @throws InvalidArgumentException In case when the specified operation name is invalid. + */ + protected function _parseOperationName($operationName) + { + /** Note that '(.*?)' must not be greedy to allow regexp to match 'multiUpdate' method before 'update' */ + $regEx = sprintf('/(.*?)(%s)$/i', implode('|', Mage_Webapi_Controller_ActionAbstract::getAllowedMethods())); + if (preg_match($regEx, $operationName, $matches)) { + $resourceName = $matches[1]; + $methodName = lcfirst($matches[2]); + $result = array($resourceName, $methodName); + return $result; + } + throw new InvalidArgumentException(sprintf( + 'The "%s" is not a valid API resource operation name.', + $operationName + )); + } + + /** + * Identify controller class by operation name. + * + * @param string $operationName + * @return string Resource name on success + * @throws LogicException + * @SuppressWarnings(PHPMD.UnusedLocalVariable) + */ + public function getControllerClassByOperationName($operationName) + { + list($resourceName, $methodName) = $this->_parseOperationName($operationName); + if (isset($this->_data['resources'][$resourceName]['controller'])) { + return $this->_data['resources'][$resourceName]['controller']; + } + throw new LogicException(sprintf('Resource "%s" must have associated controller class.', $resourceName)); + } + + /** + * Retrieve method metadata. + * + * @param Zend\Server\Reflection\ReflectionMethod $methodReflection + * @return array + * @throws InvalidArgumentException If specified method was not previously registered in API config. + */ + public function getMethodMetadata(ReflectionMethod $methodReflection) + { + $resourceName = $this->_helper->translateResourceName($methodReflection->getDeclaringClass()->getName()); + $resourceVersion = $this->_getMethodVersion($methodReflection); + $methodName = $this->_helper->getMethodNameWithoutVersionSuffix($methodReflection); + + if (!isset($this->_data['resources'][$resourceName]['versions'][$resourceVersion]['methods'][$methodName])) { + throw new InvalidArgumentException(sprintf( + 'The "%s" method of "%s" resource in version "%s" is not registered.', + $methodName, + $resourceName, + $resourceVersion + )); + } + return $this->_data['resources'][$resourceName]['versions'][$resourceVersion]['methods'][$methodName]; + } + + /** + * Retrieve mapping of complex types defined in WSDL to real data classes. + * + * @return array + */ + public function getTypeToClassMap() + { + return $this->_data['type_to_class_map']; + } + + /** + * Identify deprecation policy for the specified operation. + * + * Return result in the following format:<pre> + * array( + * 'removed' => true, // either 'deprecated' or 'removed' item must be specified + * 'deprecated' => true, + * 'use_resource' => 'operationName' // resource to be used instead + * 'use_method' => 'operationName' // method to be used instead + * 'use_version' => N, // version of method to be used instead + * ) + * </pre> + * + * @param string $resourceName + * @param string $method + * @param string $resourceVersion + * @return array|bool On success array with policy details; false otherwise. + * @throws InvalidArgumentException + */ + public function getDeprecationPolicy($resourceName, $method, $resourceVersion) + { + $deprecationPolicy = false; + $resourceData = $this->_getResourceData($resourceName, $resourceVersion); + if (!isset($resourceData['methods'][$method])) { + throw new InvalidArgumentException(sprintf( + 'Method "%s" does not exist in "%s" version of resource "%s".', + $method, + $resourceVersion, + $resourceName + )); + } + $methodData = $resourceData['methods'][$method]; + if (isset($methodData['deprecation_policy']) && is_array($methodData['deprecation_policy'])) { + $deprecationPolicy = $methodData['deprecation_policy']; + } + return $deprecationPolicy; + } + + /** + * Check if specified method is deprecated or removed. + * + * Throw exception in two cases:<br/> + * - method is removed<br/> + * - method is deprecated and developer mode is enabled + * + * @param string $resourceName + * @param string $method + * @param string $resourceVersion + * @throws Mage_Webapi_Exception + * @throws LogicException + */ + public function checkDeprecationPolicy($resourceName, $method, $resourceVersion) + { + $deprecationPolicy = $this->getDeprecationPolicy($resourceName, $method, $resourceVersion); + if ($deprecationPolicy) { + /** Initialize message with information about what method should be used instead of requested one. */ + if (isset($deprecationPolicy['use_resource']) && isset($deprecationPolicy['use_method']) + && isset($deprecationPolicy['use_version']) + ) { + $messageUseMethod = $this->_helper + ->__('Please use version "%s" of "%s" method in "%s" resource instead.', + $deprecationPolicy['use_version'], + $deprecationPolicy['use_method'], + $deprecationPolicy['use_resource'] + ); + } else { + $messageUseMethod = ''; + } + + $badRequestCode = Mage_Webapi_Exception::HTTP_BAD_REQUEST; + if (isset($deprecationPolicy['removed'])) { + $removalMessage = $this->_helper + ->__('Version "%s" of "%s" method in "%s" resource was removed.', + $resourceVersion, + $method, + $resourceName + ); + throw new Mage_Webapi_Exception($removalMessage . ' ' . $messageUseMethod, $badRequestCode); + } elseif (isset($deprecationPolicy['deprecated']) && $this->_app->isDeveloperMode()) { + $deprecationMessage = $this->_helper + ->__('Version "%s" of "%s" method in "%s" resource is deprecated.', + $resourceVersion, + $method, + $resourceName + ); + throw new Mage_Webapi_Exception($deprecationMessage . ' ' . $messageUseMethod, $badRequestCode); + } + } + } + + /** + * Identify the maximum version of the specified resource available. + * + * @param string $resourceName + * @return int + * @throws InvalidArgumentException When resource with the specified name does not exist. + */ + public function getResourceMaxVersion($resourceName) + { + if (!isset($this->_data['resources'][$resourceName])) { + throw new InvalidArgumentException(sprintf('Resource "%s" does not exist.', $resourceName)); + } + $resourceVersions = array_keys($this->_data['resources'][$resourceName]['versions']); + foreach ($resourceVersions as &$version) { + $version = str_replace(self::VERSION_NUMBER_PREFIX, '', $version); + } + $maxVersion = max($resourceVersions); + return (int)$maxVersion; + } + + /** + * Find the most appropriate version suffix for the requested action. + * + * If there is no action with requested version, fallback mechanism is used. + * If there is no appropriate action found after fallback - exception is thrown. + * + * @param string $operationName + * @param int $requestedVersion + * @param Mage_Webapi_Controller_ActionAbstract $controllerInstance + * @return string + * @throws Mage_Webapi_Exception + */ + public function identifyVersionSuffix($operationName, $requestedVersion, $controllerInstance) + { + $methodName = $this->getMethodNameByOperation($operationName, $requestedVersion); + $methodVersion = $requestedVersion; + while ($methodVersion >= self::VERSION_MIN) { + $versionSuffix = Mage_Webapi_Model_ConfigAbstract::VERSION_NUMBER_PREFIX . $methodVersion; + if ($controllerInstance->hasAction($methodName . $versionSuffix)) { + return $versionSuffix; + } + $methodVersion--; + } + throw new Mage_Webapi_Exception($this->_helper + ->__('The "%s" operation is not implemented in version %s', $operationName, $requestedVersion), + Mage_Webapi_Exception::HTTP_BAD_REQUEST + ); + } + + /** + * Check if version number is from valid range. + * + * @param int $version + * @param string $resourceName + * @throws Mage_Webapi_Exception + */ + public function validateVersionNumber($version, $resourceName) + { + $maxVersion = $this->getResourceMaxVersion($resourceName); + if ((int)$version > $maxVersion) { + throw new Mage_Webapi_Exception( + $this->_helper->__('The maximum version of the requested resource is "%s".', $maxVersion), + Mage_Webapi_Exception::HTTP_BAD_REQUEST + ); + } elseif ((int)$version < self::VERSION_MIN) { + throw new Mage_Webapi_Exception( + $this->_helper->__('Resource version cannot be lower than "%s".', self::VERSION_MIN), + Mage_Webapi_Exception::HTTP_BAD_REQUEST + ); + } + } + + /** + * Retrieve the list of all resources with their versions. + * + * @return array + */ + public function getAllResourcesVersions() + { + $resources = array(); + foreach ($this->_data['resources'] as $resourceName => $data) { + $resources[$resourceName] = array_keys($data['versions']); + } + + return $resources; + } + + /** + * Identify API method version by its reflection. + * + * @param ReflectionMethod $methodReflection + * @return string|bool Method version with prefix on success. + * false is returned in case when method should not be exposed via API. + */ + protected function _getMethodVersion(ReflectionMethod $methodReflection) + { + $methodVersion = false; + $methodNameWithSuffix = $methodReflection->getName(); + $regularExpression = $this->_helper->getMethodNameRegularExpression(); + if (preg_match($regularExpression, $methodNameWithSuffix, $methodMatches)) { + $resourceNamePosition = 2; + $methodVersion = ucfirst($methodMatches[$resourceNamePosition]); + } + return $methodVersion; + } + + /** + * Retrieve resource description for specified version. + * + * @param string $resourceName + * @param string $resourceVersion Two formats are acceptable: 'v1' and '1' + * @return array + * @throws InvalidArgumentException When the specified resource version does not exist. + */ + protected function _getResourceData($resourceName, $resourceVersion) + { + /** Allow to take resource version in two formats: with prefix and without it */ + $resourceVersion = is_numeric($resourceVersion) + ? self::VERSION_NUMBER_PREFIX . $resourceVersion + : ucfirst($resourceVersion); + try { + $this->_checkIfResourceVersionExists($resourceName, $resourceVersion); + } catch (RuntimeException $e) { + throw new InvalidArgumentException($e->getMessage()); + } + return $this->_data['resources'][$resourceName]['versions'][$resourceVersion]; + } + + /** + * Check if specified version of resource exists. If not - exception is thrown. + * + * @param string $resourceName + * @param string $resourceVersion + * @throws RuntimeException When resource does not exist. + */ + protected function _checkIfResourceVersionExists($resourceName, $resourceVersion) + { + if (!isset($this->_data['resources'][$resourceName])) { + throw new RuntimeException($this->_helper->__('Unknown resource "%s".', $resourceName)); + } + if (!isset($this->_data['resources'][$resourceName]['versions'][$resourceVersion])) { + throw new RuntimeException($this->_helper->__( + 'Unknown version "%s" for resource "%s".', + $resourceVersion, + $resourceName + )); + } + } +} diff --git a/app/code/core/Mage/Webapi/Model/Resource/Acl/Role.php b/app/code/core/Mage/Webapi/Model/Resource/Acl/Role.php new file mode 100644 index 0000000000000000000000000000000000000000..46cd96c0948089ec10dd8db89ae9cff4d4f26460 --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Resource/Acl/Role.php @@ -0,0 +1,94 @@ +<?php +/** + * Web API ACL role resource. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Resource_Acl_Role extends Mage_Core_Model_Resource_Db_Abstract +{ + /** + * @var Mage_Webapi_Helper_Data + */ + protected $_helper; + + /** + * Class constructor. + * + * @param Mage_Core_Model_Resource $resource + * @param Mage_Webapi_Helper_Data $helper + */ + public function __construct(Mage_Core_Model_Resource $resource, Mage_Webapi_Helper_Data $helper) + { + $this->_helper = $helper; + parent::__construct($resource); + } + + /** + * Resource initialization. + */ + protected function _construct() + { + $this->_init('webapi_role', 'role_id'); + } + + /** + * Initialize unique fields. + * + * @return Mage_Webapi_Model_Resource_Acl_Role + */ + protected function _initUniqueFields() + { + $this->_uniqueFields = array( + array( + 'field' => 'role_name', + 'title' => $this->_helper->__('Role Name') + ), + ); + return $this; + } + + /** + * Get roles list for selects. + * + * @return array + */ + public function getRolesList() + { + $adapter = $this->getReadConnection(); + $select = $adapter->select() + ->from($this->getMainTable(), array($this->getIdFieldName(), 'role_name')) + ->order('role_name'); + return $adapter->fetchPairs($select); + } + + /** + * Get all roles IDs. + * + * @return array + */ + public function getRolesIds() + { + $adapter = $this->getReadConnection(); + $select = $adapter->select()->from($this->getMainTable(), array($this->getIdFieldName())); + return $adapter->fetchCol($select); + } +} diff --git a/app/code/core/Mage/Webapi/Model/Resource/Acl/Role/Collection.php b/app/code/core/Mage/Webapi/Model/Resource/Acl/Role/Collection.php new file mode 100644 index 0000000000000000000000000000000000000000..e9f88ea8ad9a61545a3d9bbdb0d7cc97ea30bcd8 --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Resource/Acl/Role/Collection.php @@ -0,0 +1,35 @@ +<?php +/** + * Web API Role Resource Collection. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Resource_Acl_Role_Collection extends Mage_Core_Model_Resource_Db_Collection_Abstract +{ + /** + * Resource collection initialization. + */ + protected function _construct() + { + $this->_init('Mage_Webapi_Model_Acl_Role', 'Mage_Webapi_Model_Resource_Acl_Role'); + } +} diff --git a/app/code/core/Mage/Webapi/Model/Resource/Acl/Rule.php b/app/code/core/Mage/Webapi/Model/Resource/Acl/Rule.php new file mode 100644 index 0000000000000000000000000000000000000000..521eae7432d2a541d53611f2052d9d407b4abd67 --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Resource/Acl/Rule.php @@ -0,0 +1,107 @@ +<?php +/** + * Resource model for ACL rule. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * + * @method array getResources() getResources() + * @method Mage_Webapi_Model_Resource_Acl_Rule setResources() setResources(array $resourcesList) + * @method int getRoleId() getRoleId() + * @method Mage_Webapi_Model_Resource_Acl_Rule setRoleId() setRoleId(int $roleId) + */ +class Mage_Webapi_Model_Resource_Acl_Rule extends Mage_Core_Model_Resource_Db_Abstract +{ + /** + * Resource initialization. + */ + protected function _construct() + { + $this->_init('webapi_rule', 'rule_id'); + } + + /** + * Get all rules from DB. + * + * @return array + */ + public function getRuleList() + { + $adapter = $this->getReadConnection(); + $select = $adapter->select()->from($this->getMainTable(), array('resource_id', 'role_id')); + return $adapter->fetchAll($select); + } + + /** + * Get resource IDs assigned to role. + * + * @param integer $roleId Web api user role ID + * @return array + */ + public function getResourceIdsByRole($roleId) + { + $adapter = $this->getReadConnection(); + $select = $adapter->select() + ->from($this->getMainTable(), array('resource_id')) + ->where('role_id = ?', (int)$roleId); + return $adapter->fetchCol($select); + } + + /** + * Save resources. + * + * @param Mage_Webapi_Model_Acl_Rule $rule + * @throws Exception + */ + public function saveResources(Mage_Webapi_Model_Acl_Rule $rule) + { + $roleId = $rule->getRoleId(); + if ($roleId > 0) { + $adapter = $this->_getWriteAdapter(); + $adapter->beginTransaction(); + + try { + $adapter->delete($this->getMainTable(), array('role_id = ?' => (int)$roleId)); + + $resources = $rule->getResources(); + if ($resources) { + $resourcesToInsert = array(); + foreach ($resources as $resName) { + $resourcesToInsert[] = array( + 'role_id' => $roleId, + 'resource_id' => trim($resName) + ); + } + $adapter->insertArray( + $this->getMainTable(), + array('role_id', 'resource_id'), + $resourcesToInsert + ); + } + + $adapter->commit(); + } catch (Exception $e) { + $adapter->rollBack(); + throw $e; + } + } + } +} diff --git a/app/code/core/Mage/Api/Model/Resource/Roles/User/Collection.php b/app/code/core/Mage/Webapi/Model/Resource/Acl/Rule/Collection.php old mode 100755 new mode 100644 similarity index 67% rename from app/code/core/Mage/Api/Model/Resource/Roles/User/Collection.php rename to app/code/core/Mage/Webapi/Model/Resource/Acl/Rule/Collection.php index 4aad945592fda0431faab0c39194211fb0057b57..879a4b1d20fd255fe04acd721e1dfd2acddcbcd5 --- a/app/code/core/Mage/Api/Model/Resource/Roles/User/Collection.php +++ b/app/code/core/Mage/Webapi/Model/Resource/Acl/Rule/Collection.php @@ -19,41 +19,37 @@ * needs please refer to http://www.magentocommerce.com for more information. * * @category Mage - * @package Mage_Api + * @package Mage_Webapi * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ - /** - * Roles User Resource Collection + * Web API Rules Resource Collection. * * @category Mage - * @package Mage_Api + * @package Mage_Webpi * @author Magento Core Team <core@magentocommerce.com> */ -class Mage_Api_Model_Resource_Roles_User_Collection extends Mage_Core_Model_Resource_Db_Collection_Abstract +class Mage_Webapi_Model_Resource_Acl_Rule_Collection extends Mage_Core_Model_Resource_Db_Collection_Abstract { /** - * Resource collection initialization - * + * Resource collection initialization. */ protected function _construct() { - $this->_init('Mage_Api_Model_User', 'Mage_Api_Model_Resource_User'); + $this->_init('Mage_Webapi_Model_Acl_Rule', 'Mage_Webapi_Model_Resource_Acl_Rule'); } /** - * Init collection select + * Retrieve rules by role. * - * @return Mage_Api_Model_Resource_Roles_User_Collection + * @param int $roleId + * @return Mage_Webapi_Model_Resource_Acl_Rule_Collection */ - protected function _initSelect() + public function getByRole($roleId) { - parent::_initSelect(); - - $this->getSelect()->where("user_id > 0"); - + $this->getSelect()->where("role_id = ?", (int)$roleId); return $this; } } diff --git a/app/code/core/Mage/Webapi/Model/Resource/Acl/User.php b/app/code/core/Mage/Webapi/Model/Resource/Acl/User.php new file mode 100644 index 0000000000000000000000000000000000000000..a63ce1e5d76a8a76a8f751f2740d1be30ca29d97 --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Resource/Acl/User.php @@ -0,0 +1,83 @@ +<?php +/** + * Web API User resource model. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Resource_Acl_User extends Mage_Core_Model_Resource_Db_Abstract +{ + /** + * @var Mage_Webapi_Helper_Data + */ + protected $_helper; + + /** + * Class constructor. + * + * @param Mage_Core_Model_Resource $resource + * @param Mage_Webapi_Helper_Data $helper + */ + public function __construct(Mage_Core_Model_Resource $resource, Mage_Webapi_Helper_Data $helper) + { + $this->_helper = $helper; + parent::__construct($resource); + } + + /** + * Resource initialization. + */ + protected function _construct() + { + $this->_init('webapi_user', 'user_id'); + } + + /** + * Initialize unique fields. + * + * @return Mage_Webapi_Model_Resource_Acl_User + */ + protected function _initUniqueFields() + { + $this->_uniqueFields = array( + array( + 'field' => 'api_key', + 'title' => $this->_helper->__('API Key') + ), + ); + return $this; + } + + /** + * Get role users. + * + * @param integer $roleId + * @return array + */ + public function getRoleUsers($roleId) + { + $adapter = $this->_getReadAdapter(); + $select = $adapter->select() + ->from($this->getMainTable(), array('user_id')) + ->where('role_id = ?', (int)$roleId); + return $adapter->fetchCol($select); + } +} diff --git a/app/code/core/Mage/Webapi/Model/Resource/Acl/User/Collection.php b/app/code/core/Mage/Webapi/Model/Resource/Acl/User/Collection.php new file mode 100755 index 0000000000000000000000000000000000000000..59f44b58ffde71d505df8fd5089ab18877b9eb5f --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Resource/Acl/User/Collection.php @@ -0,0 +1,35 @@ +<?php +/** + * Web API User Resource Collection. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Resource_Acl_User_Collection extends Mage_Core_Model_Resource_Db_Collection_Abstract +{ + /** + * Resource collection initialization. + */ + protected function _construct() + { + $this->_init('Mage_Webapi_Model_Acl_User', 'Mage_Webapi_Model_Resource_Acl_User'); + } +} diff --git a/app/code/core/Mage/Webapi/Model/Rest/Oauth/Server.php b/app/code/core/Mage/Webapi/Model/Rest/Oauth/Server.php new file mode 100644 index 0000000000000000000000000000000000000000..5e24a1408119e8a4b1fe29dbf4980e7e27c23248 --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Rest/Oauth/Server.php @@ -0,0 +1,66 @@ +<?php +/** + * Two-legged OAuth server. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Rest_Oauth_Server extends Mage_Oauth_Model_Server +{ + /** + * Construct server. + * + * @param Mage_Webapi_Controller_Request_Rest $request + * @param Mage_Oauth_Model_Token_Factory $tokenFactory + * @param Mage_Webapi_Model_Acl_User_Factory $consumerFactory + * @param Mage_Oauth_Model_Nonce_Factory $nonceFactory + */ + public function __construct( + Mage_Webapi_Controller_Request_Rest $request, + Mage_Oauth_Model_Token_Factory $tokenFactory, + Mage_Webapi_Model_Acl_User_Factory $consumerFactory, + Mage_Oauth_Model_Nonce_Factory $nonceFactory + ) { + parent::__construct($request, $tokenFactory, $consumerFactory, $nonceFactory); + } + + /** + * Authenticate two-legged REST request. + * + * @return Mage_Webapi_Model_Acl_User + */ + public function authenticateTwoLegged() + { + // get parameters from request + $this->_fetchParams(); + + // make generic validation of request parameters + $this->_validateProtocolParams(); + + // initialize consumer + $this->_initConsumer(); + + // validate signature + $this->_validateSignature(); + + return $this->_consumer; + } +} diff --git a/app/code/core/Mage/Webapi/Model/Soap/AutoDiscover.php b/app/code/core/Mage/Webapi/Model/Soap/AutoDiscover.php new file mode 100644 index 0000000000000000000000000000000000000000..f94c51f38bd36ddbade96eb0b76ff480a237b79b --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Soap/AutoDiscover.php @@ -0,0 +1,387 @@ +<?php +use Zend\Soap\Wsdl; + +/** + * Auto discovery tool for WSDL generation from Magento web API configuration. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Soap_AutoDiscover +{ + const WSDL_NAME = 'MagentoWSDL'; + + /** + * Cache ID for generated WSDL content. + */ + const WSDL_CACHE_ID = 'WSDL'; + + /** + * API Resource config instance. + * Used to retrieve complex types data. + * + * @var Mage_Webapi_Model_Config_Soap + */ + protected $_apiConfig; + + /** + * WSDL factory instance. + * + * @var Mage_Webapi_Model_Soap_Wsdl_Factory + */ + protected $_wsdlFactory; + + /** + * @var Mage_Webapi_Helper_Config + */ + protected $_helper; + + /** @var Mage_Core_Model_Cache */ + protected $_cache; + + /** + * Construct auto discover with resource config and list of requested resources. + * + * @param Mage_Webapi_Model_Config_Soap $apiConfig + * @param Mage_Webapi_Model_Soap_Wsdl_Factory $wsdlFactory + * @param Mage_Webapi_Helper_Config $helper + * @param Mage_Core_Model_Cache $cache + * + * @throws InvalidArgumentException + */ + public function __construct( + Mage_Webapi_Model_Config_Soap $apiConfig, + Mage_Webapi_Model_Soap_Wsdl_Factory $wsdlFactory, + Mage_Webapi_Helper_Config $helper, + Mage_Core_Model_Cache $cache + ) { + $this->_apiConfig = $apiConfig; + $this->_wsdlFactory = $wsdlFactory; + $this->_helper = $helper; + $this->_cache = $cache; + } + + /** + * Generate WSDL content and save it to cache. + * + * @param array $requestedResources + * @param string $endpointUrl + * @return string + * @throws Mage_Webapi_Exception + */ + public function handle($requestedResources, $endpointUrl) + { + /** Sort requested resources by names to prevent caching of the same wsdl file more than once. */ + ksort($requestedResources); + $cacheId = self::WSDL_CACHE_ID . hash('md5', serialize($requestedResources)); + if ($this->_cache->canUse(Mage_Webapi_Model_ConfigAbstract::WEBSERVICE_CACHE_NAME)) { + $cachedWsdlContent = $this->_cache->load($cacheId); + if ($cachedWsdlContent !== false) { + return $cachedWsdlContent; + } + } + + $resources = array(); + try { + foreach ($requestedResources as $resourceName => $resourceVersion) { + $resources[$resourceName] = $this->_apiConfig->getResourceDataMerged($resourceName, $resourceVersion); + } + } catch (Exception $e) { + throw new Mage_Webapi_Exception($e->getMessage(), Mage_Webapi_Exception::HTTP_BAD_REQUEST); + } + + $wsdlContent = $this->generate($resources, $endpointUrl); + + if ($this->_cache->canUse(Mage_Webapi_Model_ConfigAbstract::WEBSERVICE_CACHE_NAME)) { + $this->_cache->save($wsdlContent, $cacheId, array(Mage_Webapi_Model_ConfigAbstract::WEBSERVICE_CACHE_TAG)); + } + + return $wsdlContent; + } + + /** + * Generate WSDL file based on requested resources. + * + * @param array $requestedResources + * @param string $endPointUrl + * @return string + */ + public function generate($requestedResources, $endPointUrl) + { + $this->_collectCallInfo($requestedResources); + $wsdl = $this->_wsdlFactory->create(self::WSDL_NAME, $endPointUrl); + $wsdl->addSchemaTypeSection(); + + foreach ($requestedResources as $resourceName => $resourceData) { + $portTypeName = $this->getPortTypeName($resourceName); + $bindingName = $this->getBindingName($resourceName); + $portType = $wsdl->addPortType($portTypeName); + $binding = $wsdl->addBinding($bindingName, Wsdl::TYPES_NS . ':' . $portTypeName); + $wsdl->addSoapBinding($binding, 'document', 'http://schemas.xmlsoap.org/soap/http', SOAP_1_2); + $portName = $this->getPortName($resourceName); + $serviceName = $this->getServiceName($resourceName); + $wsdl->addService($serviceName, $portName, 'tns:' . $bindingName, $endPointUrl, SOAP_1_2); + + foreach ($resourceData['methods'] as $methodName => $methodData) { + $operationName = $this->getOperationName($resourceName, $methodName); + $inputBinding = array('use' => 'literal'); + $inputMessageName = $this->_createOperationInput($wsdl, $operationName, $methodData); + + $outputMessageName = false; + $outputBinding = false; + if (isset($methodData['interface']['out']['parameters'])) { + $outputBinding = $inputBinding; + $outputMessageName = $this->_createOperationOutput($wsdl, $operationName, $methodData); + } + + $wsdl->addPortOperation($portType, $operationName, $inputMessageName, $outputMessageName); + $bindingOperation = $wsdl->addBindingOperation( + $binding, + $operationName, + $inputBinding, + $outputBinding, + false, + SOAP_1_2 + ); + $wsdl->addSoapOperation($bindingOperation, $operationName, SOAP_1_2); + // @TODO: implement faults binding + } + } + + return $wsdl->toXML(); + } + + /** + * Create input message and corresponding element and complex types in WSDL. + * + * @param Mage_Webapi_Model_Soap_Wsdl $wsdl + * @param string $operationName + * @param array $methodData + * @return string input message name + */ + protected function _createOperationInput(Mage_Webapi_Model_Soap_Wsdl $wsdl, $operationName, $methodData) + { + $inputMessageName = $this->getInputMessageName($operationName); + $complexTypeName = $this->getElementComplexTypeName($inputMessageName); + $inputParameters = array(); + $elementData = array( + 'name' => $inputMessageName, + 'type' => Wsdl::TYPES_NS . ':' . $complexTypeName + ); + if (isset($methodData['interface']['in']['parameters'])) { + $inputParameters = $methodData['interface']['in']['parameters']; + } else { + $elementData['nillable'] = 'true'; + } + $wsdl->addElement($elementData); + $callInfo = array(); + $callInfo['requiredInput']['yes']['calls'] = array($operationName); + $typeData = array( + 'documentation' => $methodData['documentation'], + 'parameters' => $inputParameters, + 'callInfo' => $callInfo, + ); + $this->_apiConfig->setTypeData($complexTypeName, $typeData); + $wsdl->addComplexType($complexTypeName); + $wsdl->addMessage( + $inputMessageName, + array( + 'messageParameters' => array( + 'element' => Wsdl::TYPES_NS . ':' . $inputMessageName + ) + ) + ); + + return Wsdl::TYPES_NS . ':' . $inputMessageName; + } + + /** + * Create output message and corresponding element and complex types in WSDL. + * + * @param Mage_Webapi_Model_Soap_Wsdl $wsdl + * @param string $operationName + * @param array $methodData + * @return string output message name + */ + protected function _createOperationOutput(Mage_Webapi_Model_Soap_Wsdl $wsdl, $operationName, $methodData) + { + $outputMessageName = $this->getOutputMessageName($operationName); + $complexTypeName = $this->getElementComplexTypeName($outputMessageName); + $wsdl->addElement( + array( + 'name' => $outputMessageName, + 'type' => Wsdl::TYPES_NS . ':' . $complexTypeName + ) + ); + $callInfo = array(); + $callInfo['returned']['always']['calls'] = array($operationName); + $typeData = array( + 'documentation' => sprintf('Response container for the %s call.', $operationName), + 'parameters' => $methodData['interface']['out']['parameters'], + 'callInfo' => $callInfo, + ); + $this->_apiConfig->setTypeData($complexTypeName, $typeData); + $wsdl->addComplexType($complexTypeName); + $wsdl->addMessage( + $outputMessageName, + array( + 'messageParameters' => array( + 'element' => Wsdl::TYPES_NS . ':' . $outputMessageName + ) + ) + ); + + return Wsdl::TYPES_NS . ':' . $outputMessageName; + } + + /** + * Get name of complexType for message element. + * + * @param string $messageName + * @return string + */ + public function getElementComplexTypeName($messageName) + { + return ucfirst($messageName); + } + + /** + * Get name for resource portType node. + * + * @param string $resourceName + * @return string + */ + public function getPortTypeName($resourceName) + { + return $resourceName . 'PortType'; + } + + /** + * Get name for resource binding node. + * + * @param string $resourceName + * @return string + */ + public function getBindingName($resourceName) + { + return $resourceName . 'Binding'; + } + + /** + * Get name for resource port node. + * + * @param string $resourceName + * @return string + */ + public function getPortName($resourceName) + { + return $resourceName . 'Port'; + } + + /** + * Get name for resource service. + * + * @param string $resourceName + * @return string + */ + public function getServiceName($resourceName) + { + return $resourceName . 'Service'; + } + + /** + * Get name of operation based on resource and method names. + * + * @param string $resourceName + * @param string $methodName + * @return string + */ + public function getOperationName($resourceName, $methodName) + { + return $resourceName . ucfirst($methodName); + } + + /** + * Get input message node name for operation. + * + * @param string $operationName + * @return string + */ + public function getInputMessageName($operationName) + { + return $operationName . 'Request'; + } + + /** + * Get output message node name for operation. + * + * @param string $operationName + * @return string + */ + public function getOutputMessageName($operationName) + { + return $operationName . 'Response'; + } + + /** + * Collect data about complex types call info. + * Walks through all requested resources and checks all methods 'in' and 'out' parameters. + * + * @param array $requestedResources + */ + protected function _collectCallInfo($requestedResources) + { + foreach ($requestedResources as $resourceName => $resourceData) { + foreach ($resourceData['methods'] as $methodName => $methodData) { + $this->_processInterfaceCallInfo($methodData['interface'], $resourceName, $methodName); + } + } + } + + /** + * Process call info data from interface. + * + * @param array $interface + * @param string $resourceName + * @param string $methodName + */ + protected function _processInterfaceCallInfo($interface, $resourceName, $methodName) + { + foreach ($interface as $direction => $interfaceData) { + $direction = ($direction == 'in') ? 'requiredInput' : 'returned'; + foreach ($interfaceData['parameters'] as $parameterData) { + $parameterType = $parameterData['type']; + if (!$this->_helper->isTypeSimple($parameterType)) { + $operation = $this->getOperationName($resourceName, $methodName); + if ($parameterData['required']) { + $condition = ($direction == 'requiredInput') ? 'yes' : 'always'; + } else { + $condition = ($direction == 'requiredInput') ? 'no' : 'conditionally'; + } + $callInfo = array(); + $callInfo[$direction][$condition]['calls'][] = $operation; + $this->_apiConfig->setTypeData($parameterType, array('callInfo' => $callInfo)); + } + } + } + } + +} diff --git a/app/code/core/Mage/Webapi/Model/Soap/Fault.php b/app/code/core/Mage/Webapi/Model/Soap/Fault.php new file mode 100644 index 0000000000000000000000000000000000000000..6939c9ef379781a8cd03f7166daa65388f33a3ef --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Soap/Fault.php @@ -0,0 +1,142 @@ +<?php +/** + * Magento-specific SOAP fault. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Soap_Fault extends RuntimeException +{ + const FAULT_REASON_INTERNAL = 'Internal Error.'; + + const FAULT_CODE_SENDER = 'Sender'; + const FAULT_CODE_RECEIVER = 'Receiver'; + + /** @var string */ + protected $_soapCode; + + /** + * Construct exception. + * + * @param string $reason + * @param string $code + * @param Exception $previous + */ + public function __construct( + $reason = self::FAULT_REASON_INTERNAL, + $code = self::FAULT_CODE_RECEIVER, + Exception $previous = null + ) { + parent::__construct($reason, 0, $previous); + $this->_soapCode = $code; + } + + /** + * Render exception as XML. + * + * @param $isDeveloperMode + * @return string + */ + public function toXml($isDeveloperMode) + { + $details = null; + if ($isDeveloperMode) { + $details = array( + 'ExceptionTrace' => "<![CDATA[{$this->getTraceAsString()}]]>" + ); + } + + // TODO: Implement Current language definition + $language = 'en'; + return $this->getSoapFaultMessage($this->getMessage(), $this->getSoapCode(), $language, $details); + } + + /** + * Retrieve SOAP fault code. + * + * @return string + */ + public function getSoapCode() + { + return $this->_soapCode; + } + + /** + * Generate SOAP fault message in XML format. + * + * @param string $reason Human-readable explanation of the fault + * @param string $code SOAP fault code + * @param string $language Reason message language + * @param string|array|null $details Detailed reason message(s) + * @return string + */ + public function getSoapFaultMessage($reason, $code, $language, $details) + { + if (is_string($details)) { + $detailsXml = "<env:Detail>" . htmlspecialchars($details) . "</env:Detail>"; + } elseif (is_array($details)) { + $detailsXml = "<env:Detail>" . $this->_convertDetailsToXml($details) . "</env:Detail>"; + } else { + $detailsXml = ''; + } + $reason = htmlentities($reason); + $message = <<<FAULT_MESSAGE +<?xml version="1.0" encoding="utf-8" ?> +<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"> + <env:Body> + <env:Fault> + <env:Code> + <env:Value>env:$code</env:Value> + </env:Code> + <env:Reason> + <env:Text xml:lang="$language">$reason</env:Text> + </env:Reason> + $detailsXml + </env:Fault> + </env:Body> +</env:Envelope> +FAULT_MESSAGE; + return $message; + } + + /** + * Recursively convert details array into XML structure. + * + * @param array $details + * @return string + */ + protected function _convertDetailsToXml($details) + { + $detailsXml = ''; + foreach ($details as $detailNode => $detailValue) { + $detailNode = htmlspecialchars($detailNode); + if (is_numeric($detailNode)) { + continue; + } + if (is_string($detailValue)) { + $detailsXml .= "<$detailNode>" . htmlspecialchars($detailValue) . "</$detailNode>"; + } elseif (is_array($detailValue)) { + $detailsXml .= "<$detailNode>" . $this->_convertDetailsToXml($detailValue) . "</$detailNode>"; + } + } + return $detailsXml; + } +} diff --git a/app/code/core/Mage/Webapi/Model/Soap/Security/UsernameToken.php b/app/code/core/Mage/Webapi/Model/Soap/Security/UsernameToken.php new file mode 100644 index 0000000000000000000000000000000000000000..239af446c5a690320fb063181c2521e9fcc75512 --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Soap/Security/UsernameToken.php @@ -0,0 +1,137 @@ +<?php +/** + * Model of SOAP WS-Security user token. + * + * @see http://docs.oasis-open.org/wss-m/wss/v1.1.1/os/wss-UsernameTokenProfile-v1.1.1-os.html + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Soap_Security_UsernameToken +{ + /**#@+ + * Available password types. + */ + const PASSWORD_TYPE_TEXT = 'PasswordText'; + const PASSWORD_TYPE_DIGEST = 'PasswordDigest'; + /**#@-*/ + + /** + * Password type value. + * + * @var string + */ + protected $_passwordType = self::PASSWORD_TYPE_TEXT; + + /** + * Nonce storage. + * + * @var Mage_Webapi_Model_Soap_Security_UsernameToken_NonceStorage + */ + protected $_nonceStorage; + + /** + * Webapi users factory. + * + * @var Mage_Webapi_Model_Acl_User_Factory + */ + protected $_userFactory; + + /** + * Constructor. + * + * @param Mage_Webapi_Model_Soap_Security_UsernameToken_NonceStorage $nonceStorage + * @param Mage_Webapi_Model_Acl_User_Factory $userFactory + * @param string $passwordType + * @throws Mage_Webapi_Model_Soap_Security_UsernameToken_InvalidPasswordTypeException + */ + public function __construct( + Mage_Webapi_Model_Soap_Security_UsernameToken_NonceStorage $nonceStorage, + Mage_Webapi_Model_Acl_User_Factory $userFactory, + $passwordType = self::PASSWORD_TYPE_DIGEST + ) { + if (!in_array($passwordType, array(self::PASSWORD_TYPE_DIGEST, self::PASSWORD_TYPE_TEXT))) { + throw new Mage_Webapi_Model_Soap_Security_UsernameToken_InvalidPasswordTypeException; + } + $this->_passwordType = $passwordType; + $this->_nonceStorage = $nonceStorage; + $this->_userFactory = $userFactory; + } + + /** + * Authenticate username token data. + * + * @param string $username username value from token. + * @param string $password password value from token. + * @param string $created timestamp created value (must be in ISO-8601 format). + * @param string $nonce timestamp nonce. + * @return Mage_Webapi_Model_Acl_User + * @throws Mage_Webapi_Model_Soap_Security_UsernameToken_InvalidCredentialException + * @throws Mage_Webapi_Model_Soap_Security_UsernameToken_InvalidDateException + */ + public function authenticate($username, $password, $created, $nonce) + { + $createdTimestamp = $this->_getTimestampFromDate($created); + if (!$createdTimestamp) { + throw new Mage_Webapi_Model_Soap_Security_UsernameToken_InvalidDateException; + } + $this->_nonceStorage->validateNonce($nonce, $createdTimestamp); + + $user = $this->_userFactory->create(); + if (!$user->load($username, 'api_key')->getId()) { + throw new Mage_Webapi_Model_Soap_Security_UsernameToken_InvalidCredentialException; + } + + $localPassword = $user->getSecret(); + if ($this->_passwordType == self::PASSWORD_TYPE_DIGEST) { + $baseString = base64_decode($nonce) . $created . $localPassword; + $localPassword = base64_encode(hash('sha1', $baseString, true)); + } + + if ($localPassword != $password) { + throw new Mage_Webapi_Model_Soap_Security_UsernameToken_InvalidCredentialException; + } + + return $user; + } + + /** + * Convert ISO8601 date string to timestamp. + * Date format with microseconds is accepted as well. + * + * @param string $date + * @return int + */ + protected function _getTimestampFromDate($date) + { + $timestamp = 0; + $dateTime = DateTime::createFromFormat(DateTime::ISO8601, $date); + if (!$dateTime) { + // Format with microseconds + $dateTime = DateTime::createFromFormat('Y-m-d\TH:i:s.uO', $date); + } + + if ($dateTime) { + $timestamp = $dateTime->format('U'); + } + + return $timestamp; + } +} diff --git a/app/code/core/Mage/Webapi/Model/Soap/Security/UsernameToken/Factory.php b/app/code/core/Mage/Webapi/Model/Soap/Security/UsernameToken/Factory.php new file mode 100644 index 0000000000000000000000000000000000000000..9181f150f004ec2bb3af1b2b1d7c4d1477829eb2 --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Soap/Security/UsernameToken/Factory.php @@ -0,0 +1,51 @@ +<?php +/** + * Factory of username token builders. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Soap_Security_UsernameToken_Factory +{ + /** + * @var Magento_ObjectManager + */ + protected $_objectManager; + + /** + * @param Magento_ObjectManager $objectManager + */ + public function __construct(Magento_ObjectManager $objectManager) + { + $this->_objectManager = $objectManager; + } + + /** + * Create username token. + * + * @param array $arguments + * @return Mage_Webapi_Model_Soap_Security_usernameToken + */ + public function createFromArray($arguments = array()) + { + return $this->_objectManager->create('Mage_Webapi_Model_Soap_Security_UsernameToken', $arguments); + } +} diff --git a/app/code/core/Mage/Webapi/Model/Soap/Security/UsernameToken/InvalidCredentialException.php b/app/code/core/Mage/Webapi/Model/Soap/Security/UsernameToken/InvalidCredentialException.php new file mode 100644 index 0000000000000000000000000000000000000000..83addf05dbb8283be916b9ade81f1b0818181c81 --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Soap/Security/UsernameToken/InvalidCredentialException.php @@ -0,0 +1,29 @@ +<?php +/** + * Exception for case of invalid SOAP WS-Security credentials. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @see http://docs.oasis-open.org/wss-m/wss/v1.1.1/os/wss-UsernameTokenProfile-v1.1.1-os.html + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Soap_Security_UsernameToken_InvalidCredentialException extends RuntimeException +{ +} diff --git a/app/code/core/Mage/Webapi/Model/Soap/Security/UsernameToken/InvalidDateException.php b/app/code/core/Mage/Webapi/Model/Soap/Security/UsernameToken/InvalidDateException.php new file mode 100644 index 0000000000000000000000000000000000000000..a4793e6dfccaec5944e25a684ed46baef40dc07c --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Soap/Security/UsernameToken/InvalidDateException.php @@ -0,0 +1,29 @@ +<?php +/** + * Exception for case of invalid date (SOAP WS-Security). + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @see http://docs.oasis-open.org/wss-m/wss/v1.1.1/os/wss-UsernameTokenProfile-v1.1.1-os.html + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Soap_Security_UsernameToken_InvalidDateException extends RuntimeException +{ +} diff --git a/app/code/core/Mage/Webapi/Model/Soap/Security/UsernameToken/InvalidPasswordTypeException.php b/app/code/core/Mage/Webapi/Model/Soap/Security/UsernameToken/InvalidPasswordTypeException.php new file mode 100644 index 0000000000000000000000000000000000000000..273330373e6945316b067ec236ae52e3c6d03bc3 --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Soap/Security/UsernameToken/InvalidPasswordTypeException.php @@ -0,0 +1,29 @@ +<?php +/** + * Exception for case of invalid password type (SOAP WS-Security). + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @see http://docs.oasis-open.org/wss-m/wss/v1.1.1/os/wss-UsernameTokenProfile-v1.1.1-os.html + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Soap_Security_UsernameToken_InvalidPasswordTypeException extends RuntimeException +{ +} diff --git a/app/code/core/Mage/Webapi/Model/Soap/Security/UsernameToken/NonceStorage.php b/app/code/core/Mage/Webapi/Model/Soap/Security/UsernameToken/NonceStorage.php new file mode 100644 index 0000000000000000000000000000000000000000..98b895ad2a5411d44a339f99af76c876e81bae0d --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Soap/Security/UsernameToken/NonceStorage.php @@ -0,0 +1,100 @@ +<?php +/** + * Temporary storage of SOAP WS-Security username token nonce & timestamp. + * + * @see http://docs.oasis-open.org/wss-m/wss/v1.1.1/os/wss-UsernameTokenProfile-v1.1.1-os.html + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Soap_Security_UsernameToken_NonceStorage +{ + /** + * Nonce time to life in seconds. + */ + const NONCE_TTL = 600; + + /** + * Acceptance time interval for nonce 'from future'. Helps to prevent errors due to time sync issues. + */ + const NONCE_FROM_FUTURE_ACCEPTABLE_RANGE = 60; + + /** + * Nonce prefix in cache ID. + */ + const NONCE_CACHE_ID_PREFIX = 'WEBAPI_NONCE_'; + + /** + * @var Mage_Core_Model_Cache + */ + protected $_cacheInstance; + + /** + * Construct nonce storage object. + * + * @param Mage_Core_Model_Cache $cacheInstance + */ + public function __construct(Mage_Core_Model_Cache $cacheInstance) + { + $this->_cacheInstance = $cacheInstance; + } + + /** + * Validate nonce and timestamp pair. + * Write nonce to storage if it's valid. + * + * @param string $nonce + * @param int $timestamp + * @throws Mage_Webapi_Model_Soap_Security_UsernameToken_TimestampRefusedException + * @throws Mage_Webapi_Model_Soap_Security_UsernameToken_NonceUsedException + */ + public function validateNonce($nonce, $timestamp) + { + $timestamp = (int)$timestamp; + $isNonceUsed = $timestamp <= (time() - self::NONCE_TTL); + $isNonceFromFuture = $timestamp > (time() + self::NONCE_FROM_FUTURE_ACCEPTABLE_RANGE); + if ($timestamp <= 0 || $isNonceUsed || $isNonceFromFuture) { + throw new Mage_Webapi_Model_Soap_Security_UsernameToken_TimestampRefusedException; + } + + if ($this->_cacheInstance->load($this->getNonceCacheId($nonce)) == $timestamp) { + throw new Mage_Webapi_Model_Soap_Security_UsernameToken_NonceUsedException; + } + + $nonceCacheTtl = self::NONCE_TTL + self::NONCE_FROM_FUTURE_ACCEPTABLE_RANGE; + $this->_cacheInstance->save( + $timestamp, + $this->getNonceCacheId($nonce), + array(Mage_Webapi_Model_ConfigAbstract::WEBSERVICE_CACHE_TAG), + $nonceCacheTtl + ); + } + + /** + * Generate cache ID for given nonce. + * + * @param string $nonce + * @return string + */ + public function getNonceCacheId($nonce) + { + return hash('md5', self::NONCE_CACHE_ID_PREFIX . $nonce); + } +} diff --git a/app/code/core/Mage/Webapi/Model/Soap/Security/UsernameToken/NonceUsedException.php b/app/code/core/Mage/Webapi/Model/Soap/Security/UsernameToken/NonceUsedException.php new file mode 100644 index 0000000000000000000000000000000000000000..d2d7e1c35f40d0bed5d4e6cac6c0ac841a8904c7 --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Soap/Security/UsernameToken/NonceUsedException.php @@ -0,0 +1,29 @@ +<?php +/** + * Exception for case of used nonce (SOAP WS-Security). + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @see http://docs.oasis-open.org/wss-m/wss/v1.1.1/os/wss-UsernameTokenProfile-v1.1.1-os.html + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Soap_Security_UsernameToken_NonceUsedException extends RuntimeException +{ +} diff --git a/app/code/core/Mage/Webapi/Model/Soap/Security/UsernameToken/TimestampRefusedException.php b/app/code/core/Mage/Webapi/Model/Soap/Security/UsernameToken/TimestampRefusedException.php new file mode 100644 index 0000000000000000000000000000000000000000..677196a976223a7b6960c4ac13e26bbef0514fc8 --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Soap/Security/UsernameToken/TimestampRefusedException.php @@ -0,0 +1,29 @@ +<?php +/** + * Exception for case of refused timestamp (SOAP WS-Security). + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @see http://docs.oasis-open.org/wss-m/wss/v1.1.1/os/wss-UsernameTokenProfile-v1.1.1-os.html + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Soap_Security_UsernameToken_TimestampRefusedException extends RuntimeException +{ +} diff --git a/app/code/core/Mage/Webapi/Model/Soap/Server.php b/app/code/core/Mage/Webapi/Model/Soap/Server.php new file mode 100644 index 0000000000000000000000000000000000000000..e4db0b5ee22255850de1948e53034b0b6337848a --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Soap/Server.php @@ -0,0 +1,199 @@ +<?php +/** + * Magento-specific SOAP server. + * TODO: Remove dependency on Zend SOAP Server and methods overrides. Create Magento_Soap_Server instead. + * TODO: Remove dependence on application config, probably move it to dispatcher. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Soap_Server extends \Zend\Soap\Server +{ + const SOAP_DEFAULT_ENCODING = 'UTF-8'; + + /**#@+ + * Path in config to Webapi settings. + */ + const CONFIG_PATH_WSDL_CACHE_ENABLED = 'webapi/soap/wsdl_cache_enabled'; + const CONFIG_PATH_SOAP_CHARSET = 'webapi/soap/charset'; + /**#@-*/ + + const REQUEST_PARAM_RESOURCES = 'resources'; + const REQUEST_PARAM_WSDL = 'wsdl'; + + /** @var Mage_Core_Model_Store */ + protected $_application; + + /** @var Magento_DomDocument_Factory */ + protected $_domDocumentFactory; + + /** @var Mage_Webapi_Controller_Request_Soap */ + protected $_request; + + /** + * Initialize dependencies. + * + * @param Mage_Core_Model_App $application + * @param Mage_Webapi_Controller_Request_Soap $request + * @param Magento_DomDocument_Factory $domDocumentFactory + */ + public function __construct( + Mage_Core_Model_App $application, + Mage_Webapi_Controller_Request_Soap $request, + Magento_DomDocument_Factory $domDocumentFactory + ) { + parent::__construct(); + + $this->_application = $application; + $this->_request = $request; + $this->_domDocumentFactory = $domDocumentFactory; + } + + /** + * Process Webapi SOAP fault. + * + * @param Mage_Webapi_Model_Soap_Fault|Exception|string $fault + * @param string $code + * @return SoapFault|string + */ + public function fault($fault = null, $code = null) + { + if ($fault instanceof Mage_Webapi_Model_Soap_Fault) { + return $fault->toXml($this->_application->isDeveloperMode()); + } else { + return parent::fault($fault, $code); + } + } + + /** + * Catch exceptions if request is invalid and output fault message. + * + * @param DOMDocument|DOMNode|SimpleXMLElement|stdClass|string $request + * @return Mage_Webapi_Model_Soap_Server + * @SuppressWarnings(PHPMD.ExitExpression) + */ + protected function _setRequest($request) + { + try { + parent::_setRequest($request); + } catch (Exception $e) { + $fault = new Mage_Webapi_Model_Soap_Fault( + $e->getMessage(), + Mage_Webapi_Model_Soap_Fault::FAULT_CODE_SENDER + ); + die($fault->toXml($this->_application->isDeveloperMode())); + } + return $this; + } + + /** + * Suppress PHP error output because it has already been displayed by SoapServer extension. + * TODO: remove this method when removing dependence on Zend/Soap/Server + * + * @param int $errno + * @param string $errstr + * @param string $errfile + * @param int $errline + * @param array $errcontext + * @return void + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + * @SuppressWarnings(PHPMD.ExitExpression) + */ + public function handlePhpErrors($errno, $errstr, $errfile = null, $errline = null, array $errcontext = null) + { + die(); + } + + /** + * Get SOAP Header names from request. + * + * @return array + * @SuppressWarnings(PHPMD.UnusedLocalVariable) + */ + public function getRequestHeaders() + { + $dom = $this->_domDocumentFactory->createDomDocument(); + $dom->loadXML($this->getLastRequest()); + $headers = array(); + /** @var DOMElement $header */ + foreach ($dom->getElementsByTagName('Header')->item(0)->childNodes as $header) { + list($headerNs, $headerName) = explode(":", $header->nodeName); + $headers[] = $headerName; + } + + return $headers; + } + + /** + * Enable or disable SOAP extension WSDL cache depending on Magento configuration. + */ + public function initWsdlCache() + { + $wsdlCacheEnabled = (bool)$this->_application->getStore()->getConfig(self::CONFIG_PATH_WSDL_CACHE_ENABLED); + if ($wsdlCacheEnabled) { + ini_set('soap.wsdl_cache_enabled', '1'); + } else { + ini_set('soap.wsdl_cache_enabled', '0'); + } + } + + /** + * Retrieve charset used in SOAP API. + * + * @return string + */ + public function getApiCharset() + { + $charset = $this->_application->getStore()->getConfig(self::CONFIG_PATH_SOAP_CHARSET); + return $charset ? $charset : Mage_Webapi_Model_Soap_Server::SOAP_DEFAULT_ENCODING; + } + + /** + * Get SOAP endpoint URL. + * + * @param bool $isWsdl + * @return string + */ + public function generateUri($isWsdl = false) + { + $params = array( + self::REQUEST_PARAM_RESOURCES => $this->_request->getRequestedResources() + ); + if ($isWsdl) { + $params[self::REQUEST_PARAM_WSDL] = true; + } + $query = http_build_query($params, '', '&'); + return $this->getEndpointUri() . '?' . $query; + } + + /** + * Generate URI of SOAP endpoint. + * + * @return string + */ + public function getEndpointUri() + { + // @TODO: Implement proper endpoint URL retrieval mechanism in APIA-718 story + return $this->_application->getStore()->getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB) + . Mage_Webapi_Controller_Router_Route_Webapi::API_AREA_NAME . '/' + . Mage_Webapi_Controller_Front::API_TYPE_SOAP; + } +} diff --git a/app/code/core/Mage/Customer/Model/Customer/Api/V2.php b/app/code/core/Mage/Webapi/Model/Soap/Wsdl.php similarity index 62% rename from app/code/core/Mage/Customer/Model/Customer/Api/V2.php rename to app/code/core/Mage/Webapi/Model/Soap/Wsdl.php index 62ecda3e8e67777adb917f850d2a78d6b3c3b74b..d49c58ff21391e9677be1e27d45c203d70ee8e79 100644 --- a/app/code/core/Mage/Customer/Model/Customer/Api/V2.php +++ b/app/code/core/Mage/Webapi/Model/Soap/Wsdl.php @@ -1,5 +1,9 @@ <?php +use Zend\Soap\Wsdl; + /** + * Magento-specific WSDL builder. + * * Magento * * NOTICE OF LICENSE @@ -18,33 +22,27 @@ * versions in the future. If you wish to customize Magento for your * needs please refer to http://www.magentocommerce.com for more information. * - * @category Mage - * @package Mage_Customer * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ - -/** - * Customer api V2 - * - * @category Mage - * @package Mage_Customer - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Customer_Model_Customer_Api_V2 extends Mage_Customer_Model_Customer_Api +class Mage_Webapi_Model_Soap_Wsdl extends Wsdl { /** - * Prepare data to insert/update. - * Creating array for stdClass Object + * @var string|Zend\Uri\Uri + */ + protected $_uri; + + /** + * Constructor. + * Save URI for targetNamespace generation. * - * @param stdClass $data - * @return array + * @param string $name + * @param string|Zend\Uri\Uri $uri + * @param Mage_Webapi_Model_Soap_Wsdl_ComplexTypeStrategy_ConfigBased $strategy */ - protected function _prepareData($data) + public function __construct($name, $uri, Mage_Webapi_Model_Soap_Wsdl_ComplexTypeStrategy_ConfigBased $strategy) { - if (null !== ($_data = get_object_vars($data))) { - return parent::_prepareData($_data); - } - return array(); + $this->_uri = $uri; + parent::__construct($name, $uri, $strategy); } } diff --git a/app/code/core/Mage/Webapi/Model/Soap/Wsdl/ComplexTypeStrategy/ConfigBased.php b/app/code/core/Mage/Webapi/Model/Soap/Wsdl/ComplexTypeStrategy/ConfigBased.php new file mode 100644 index 0000000000000000000000000000000000000000..07d10c3450778701a9154004c12a46f097af1035 --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Soap/Wsdl/ComplexTypeStrategy/ConfigBased.php @@ -0,0 +1,457 @@ +<?php +use Zend\Soap\Wsdl\ComplexTypeStrategy\AbstractComplexTypeStrategy, + Zend\Soap\Wsdl\ComplexTypeStrategy\ComplexTypeStrategyInterface, + Zend\Soap\Wsdl; + +/** + * Magento-specific Complex type strategy for WSDL auto discovery. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Soap_Wsdl_ComplexTypeStrategy_ConfigBased extends AbstractComplexTypeStrategy +{ + /** + * Array item key value for element. + */ + const ARRAY_ITEM_KEY_NAME = 'item'; + + /** + * Appinfo nodes namespace. + */ + const APP_INF_NS = 'inf'; + + /** + * @var Mage_Webapi_Model_Config_Soap + */ + protected $_config; + + /** + * @var Mage_Webapi_Helper_Config + */ + protected $_helper; + + /** + * @var DOMDocument + */ + protected $_dom; + + /** + * Construct strategy with resource config. + * + * @param Mage_Webapi_Model_Config_Soap $config + * @param Mage_Webapi_Helper_Config $helper + */ + public function __construct(Mage_Webapi_Model_Config_Soap $config, Mage_Webapi_Helper_Config $helper) + { + $this->_config = $config; + $this->_helper = $helper; + } + + /** + * Add complex type. + * + * @param string $type + * @param array $parentCallInfo array of callInfo from parent complex type + * @return string + * @throws InvalidArgumentException + */ + public function addComplexType($type, $parentCallInfo = array()) + { + if (($soapType = $this->scanRegisteredTypes($type)) !== null) { + return $soapType; + } + + /** @var DOMDocument $dom */ + $dom = $this->getContext()->toDomDocument(); + $this->_dom = $dom; + $soapType = Wsdl::TYPES_NS . ':' . $type; + + // Register type here to avoid recursion + $this->getContext()->addType($type, $soapType); + + $complexType = $this->_dom->createElement(Wsdl::XSD_NS . ':complexType'); + $complexType->setAttribute('name', $type); + $typeData = $this->_config->getTypeData($type); + if (isset($typeData['documentation'])) { + $this->addAnnotation($complexType, $typeData['documentation']); + } + + if (isset($typeData['parameters']) && is_array($typeData['parameters'])) { + $callInfo = isset($typeData['callInfo']) ? $typeData['callInfo'] : $parentCallInfo; + $sequence = $this->_processParameters($typeData['parameters'], $callInfo); + $complexType->appendChild($sequence); + } + + $this->getContext()->getSchema()->appendChild($complexType); + return $soapType; + } + + /** + * Process type parameters and create complex type sequence. + * + * @param array $parameters + * @param array $callInfo + * @return DOMElement + */ + protected function _processParameters($parameters, $callInfo) + { + $sequence = $this->_dom->createElement(Wsdl::XSD_NS . ':sequence'); + foreach ($parameters as $parameterName => $parameterData) { + $parameterType = $parameterData['type']; + $element = $this->_dom->createElement(Wsdl::XSD_NS . ':element'); + $element->setAttribute('name', $parameterName); + $isRequired = isset($parameterData['required']) && $parameterData['required']; + $default = isset($parameterData['default']) ? $parameterData['default'] : null; + $this->_revertRequiredCallInfo($isRequired, $callInfo); + + if ($this->_helper->isArrayType($parameterType)) { + $this->_processArrayParameter($parameterType, $callInfo); + $element->setAttribute( + 'type', + Wsdl::TYPES_NS . ':' . $this->_helper->translateArrayTypeName($parameterType) + ); + } else { + $this->_processParameter($element, $isRequired, $parameterData, $parameterType, $callInfo); + } + + $this->addAnnotation($element, $parameterData['documentation'], $default, $callInfo); + $sequence->appendChild($element); + } + + return $sequence; + } + + /** + * @param DOMElement $element + * @param boolean $isRequired + * @param array $parameterData + * @param string $parameterType + * @param array $callInfo + */ + protected function _processParameter(DOMElement $element, $isRequired, $parameterData, $parameterType, $callInfo) + { + $element->setAttribute('minOccurs', $isRequired ? 1 : 0); + $maxOccurs = (isset($parameterData['isArray']) && $parameterData['isArray']) ? 'unbounded' : 1; + $element->setAttribute('maxOccurs', $maxOccurs); + if ($this->_helper->isTypeSimple($parameterType)) { + $typeNs = Wsdl::XSD_NS; + } else { + $typeNs = Wsdl::TYPES_NS; + $this->addComplexType($parameterType, $callInfo); + } + $element->setAttribute('type', $typeNs . ':' . $parameterType); + } + + /** + * Process array of types. + * + * @param string $type + * @param array $callInfo + */ + protected function _processArrayParameter($type, $callInfo = array()) + { + $arrayItemType = $this->_helper->getArrayItemType($type); + $arrayTypeName = $this->_helper->translateArrayTypeName($type); + if (!$this->_helper->isTypeSimple($arrayItemType)) { + $this->addComplexType($arrayItemType, $callInfo); + } + $arrayTypeParameters = array( + self::ARRAY_ITEM_KEY_NAME => array( + 'type' => $arrayItemType, + 'required' => false, + 'isArray' => true, + 'documentation' => sprintf('An item of %s.', $arrayTypeName) + ) + ); + $arrayTypeData = array( + 'documentation' => sprintf('An array of %s items.', $arrayItemType), + 'parameters' => $arrayTypeParameters, + ); + $this->_config->setTypeData($arrayTypeName, $arrayTypeData); + $this->addComplexType($arrayTypeName, $callInfo); + } + + /** + * Revert required call info data if needed. + * + * @param boolean $isRequired + * @param array $callInfo + */ + protected function _revertRequiredCallInfo($isRequired, &$callInfo) + { + if (!$isRequired) { + if (isset($callInfo['requiredInput']['yes'])) { + $callInfo['requiredInput']['no']['calls'] = $callInfo['requiredInput']['yes']['calls']; + unset($callInfo['requiredInput']['yes']); + } + if (isset($callInfo['returned']['always'])) { + $callInfo['returned']['conditionally']['calls'] = $callInfo['returned']['always']['calls']; + unset($callInfo['returned']['always']); + } + } + } + + /** + * Generate annotation data for WSDL. + * Convert all {key:value} from documentation into appinfo nodes. + * Override default callInfo values if defined in parameter documentation. + * + * @param DOMElement $element + * @param string $documentation parameter documentation string + * @param string|null $default + * @param array $callInfo + */ + public function addAnnotation(DOMElement $element, $documentation, $default = null, $callInfo = array()) + { + $annotationNode = $this->_dom->createElement(Wsdl::XSD_NS . ':annotation'); + + $elementType = $this->_getElementType($element); + $appInfoNode = $this->_dom->createElement(Wsdl::XSD_NS . ':appinfo'); + $appInfoNode->setAttributeNS( + Wsdl::XML_NS_URI, + Wsdl::XML_NS . ':' . self::APP_INF_NS, + $this->getContext()->getTargetNamespace() + ); + + $this->_processDefaultValueAnnotation($elementType, $default, $appInfoNode); + $this->_processElementType($elementType, $documentation, $appInfoNode); + + if (preg_match_all('/{([a-z]+):(.+)}/Ui', $documentation, $matches)) { + for ($i = 0; $i < count($matches[0]); $i++) { + $appinfoTag = $matches[0][$i]; + $tagName = $matches[1][$i]; + $tagValue = $matches[2][$i]; + switch ($tagName) { + case 'callInfo': + $callInfoRegExp = '/([a-z].+):(returned|requiredInput):(yes|no|always|conditionally)/i'; + if (preg_match($callInfoRegExp, $tagValue)) { + list($callName, $direction, $condition) = explode(':', $tagValue); + $condition = strtolower($condition); + if (preg_match('/allCallsExcept\(([a-zA-Z].+)\)/', $callName, $calls)) { + $callInfo[$direction][$condition] = array( + 'allCallsExcept' => $calls[1], + ); + } else if (!isset($callInfo[$direction][$condition]['allCallsExcept'])) { + $this->_overrideCallInfoName($callInfo, $callName); + $callInfo[$direction][$condition]['calls'][] = $callName; + } + } + break; + case 'seeLink': + $this->_processSeeLink($appInfoNode, $tagValue); + break; + case 'docInstructions': + $this->_processDocInstructions($appInfoNode, $tagValue); + break; + default: + $nodeValue = trim($tagValue); + $simpleTextNode = $this->_dom->createElement(self::APP_INF_NS . ':' . $tagName); + $simpleTextNode->appendChild($this->_dom->createTextNode($nodeValue)); + $appInfoNode->appendChild($simpleTextNode); + break; + } + $documentation = str_replace($appinfoTag, '', $documentation); + } + } + $this->_processCallInfo($appInfoNode, $callInfo); + $documentationNode = $this->_dom->createElement(Wsdl::XSD_NS . ':documentation'); + $documentationText = trim($documentation); + $documentationNode->appendChild($this->_dom->createTextNode($documentationText)); + $annotationNode->appendChild($documentationNode); + $annotationNode->appendChild($appInfoNode); + $element->appendChild($annotationNode); + } + + /** + * Process different element types. + * + * @param string $elementType + * @param string $documentation + * @param DOMElement $appInfoNode + */ + protected function _processElementType($elementType, $documentation, DOMElement $appInfoNode) + { + if ($elementType == 'int') { + $this->_processRequiredAnnotation('min', $documentation, $appInfoNode); + $this->_processRequiredAnnotation('max', $documentation, $appInfoNode); + } + if ($elementType == 'string') { + $this->_processRequiredAnnotation('maxLength', $documentation, $appInfoNode); + } + + if ($this->_helper->isArrayType($elementType)) { + $natureOfTypeNode = $this->_dom->createElement(self::APP_INF_NS . ':natureOfType'); + $natureOfTypeNode->appendChild($this->_dom->createTextNode('array')); + $appInfoNode->appendChild($natureOfTypeNode); + } + } + + /** + * Process default value annotation. + * + * @param string $elementType + * @param string $default + * @param DOMElement $appInfoNode + */ + protected function _processDefaultValueAnnotation($elementType, $default, DOMElement $appInfoNode) + { + if ($elementType == 'boolean') { + $default = (bool)$default ? 'true' : 'false'; + } + if ($default) { + $defaultNode = $this->_dom->createElement(self::APP_INF_NS . ':default'); + $defaultNode->appendChild($this->_dom->createTextNode($default)); + $appInfoNode->appendChild($defaultNode); + } + } + + /** + * Retrieve element type. + * + * @param DOMElement $element + * @return string|null + * @SuppressWarnings(PHPMD.UnusedLocalVariable) + */ + protected function _getElementType(DOMElement $element) + { + $elementType = null; + if ($element->hasAttribute('type')) { + list($typeNs, $elementType) = explode(':', $element->getAttribute('type')); + } + return $elementType; + } + + /** + * Check if there is given annotation in documentation, and if not - create an empty one. + * + * @param $annotation + * @param $documentation + * @param DOMElement $appInfoNode + */ + protected function _processRequiredAnnotation($annotation, $documentation, DOMElement $appInfoNode) + { + if (!preg_match("/{{$annotation}:.+}/Ui", $documentation)) { + $annotationNode = $this->_dom->createElement(self::APP_INF_NS . ':' . $annotation); + $appInfoNode->appendChild($annotationNode); + } + } + + /** + * Process 'callInfo' appinfo tag. + * + * @param DOMElement $appInfoNode + * @param $callInfo + */ + protected function _processCallInfo(DOMElement $appInfoNode, $callInfo) + { + if (!empty($callInfo)) { + foreach ($callInfo as $direction => $conditions) { + foreach ($conditions as $condition => $info) { + $callInfoNode = $this->_dom->createElement(self::APP_INF_NS . ':callInfo'); + if (isset($info['allCallsExcept'])) { + $allExceptNode = $this->_dom->createElement(self::APP_INF_NS . ':allCallsExcept'); + $allExceptNode->appendChild($this->_dom->createTextNode($info['allCallsExcept'])); + $callInfoNode->appendChild($allExceptNode); + } else if (isset($info['calls'])) { + foreach ($info['calls'] as $callName) { + $callNode = $this->_dom->createElement(self::APP_INF_NS . ':callName'); + $callNode->appendChild($this->_dom->createTextNode($callName)); + $callInfoNode->appendChild($callNode); + } + } + $directionNode = $this->_dom->createElement(self::APP_INF_NS . ':' . $direction); + $directionNode->appendChild($this->_dom->createTextNode(ucfirst($condition))); + $callInfoNode->appendChild($directionNode); + $appInfoNode->appendChild($callInfoNode); + } + } + } + } + + /** + * Process 'docInstructions' appinfo tag. + * + * @param DOMElement $appInfoNode + * @param $tagValue + */ + protected function _processDocInstructions(DOMElement $appInfoNode, $tagValue) + { + if (preg_match('/(input|output):(.+)/', $tagValue, $docMatches)) { + $docInstructionsNode = $this->_dom->createElement(self::APP_INF_NS . ':docInstructions'); + $directionNode = $this->_dom->createElement(self::APP_INF_NS . ':' . $docMatches[1]); + $directionValueNode = $this->_dom->createElement(self::APP_INF_NS . ':' . $docMatches[2]); + $directionNode->appendChild($directionValueNode); + $docInstructionsNode->appendChild($directionNode); + $appInfoNode->appendChild($docInstructionsNode); + } + } + + /** + * Process 'seeLink' appinfo tag. + * + * @param DOMElement $appInfoNode + * @param $tagValue + */ + protected function _processSeeLink(DOMElement $appInfoNode, $tagValue) + { + if (preg_match('|([http://]?.+):(.+):(.+)|i', $tagValue, $matches)) { + $seeLink = array( + 'url' => $matches[1], + 'title' => $matches[2], + 'for' => $matches[3], + ); + $seeLinkNode = $this->_dom->createElement(self::APP_INF_NS . ':seeLink'); + foreach (array('url', 'title', 'for') as $subNodeName) { + if (isset($seeLink[$subNodeName])) { + $seeLinkSubNode = $this->_dom->createElement(self::APP_INF_NS . ':' . $subNodeName); + $seeLinkSubNode->appendChild($this->_dom->createTextNode($seeLink[$subNodeName])); + $seeLinkNode->appendChild($seeLinkSubNode); + } + } + $appInfoNode->appendChild($seeLinkNode); + } + } + + /** + * Delete callName if it's already defined in some direction group. + * + * @param $callInfo + * @param $callName + */ + protected function _overrideCallInfoName(&$callInfo, $callName) + { + foreach ($callInfo as $direction => &$callInfoData) { + foreach ($callInfoData as $condition => &$data) { + if (isset($data['calls'])) { + $foundCallNameIndex = array_search($callName, $data['calls']); + if ($foundCallNameIndex !== false) { + unset($data['calls'][$foundCallNameIndex]); + if (empty($data['calls'])) { + unset($callInfo[$direction][$condition]); + } + break; + } + } + } + } + } +} diff --git a/app/code/core/Mage/Webapi/Model/Soap/Wsdl/Factory.php b/app/code/core/Mage/Webapi/Model/Soap/Wsdl/Factory.php new file mode 100644 index 0000000000000000000000000000000000000000..e622905d5cc7ac36629ffd8ddcc59d0f0feaf3a7 --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Soap/Wsdl/Factory.php @@ -0,0 +1,59 @@ +<?php +/** + * Factory of WSDL builders. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Soap_Wsdl_Factory +{ + /** + * @var Magento_ObjectManager + */ + protected $_objectManager; + + /** + * @param Magento_ObjectManager $objectManager + */ + public function __construct(Magento_ObjectManager $objectManager) + { + $this->_objectManager = $objectManager; + } + + /** + * Create WSDL builder instance. + * + * @param string $wsdlName + * @param string $endpointUrl + * @return Mage_Webapi_Model_Soap_Wsdl + */ + public function create($wsdlName, $endpointUrl) + { + return $this->_objectManager->create( + 'Mage_Webapi_Model_Soap_Wsdl', + array( + 'name' => $wsdlName, + 'uri' => $endpointUrl, + ), + false + ); + } +} diff --git a/app/code/core/Mage/Webapi/Model/Source/Acl/Role.php b/app/code/core/Mage/Webapi/Model/Source/Acl/Role.php new file mode 100644 index 0000000000000000000000000000000000000000..0d48e320cfb80d866fb06267bef87583a9e18a0a --- /dev/null +++ b/app/code/core/Mage/Webapi/Model/Source/Acl/Role.php @@ -0,0 +1,90 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_Webapi + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Web API Role source model. + * + * @category Mage + * @package Mage_Webapi + * @author Magento Core Team <core@magentocommerce.com> + */ +class Mage_Webapi_Model_Source_Acl_Role implements Mage_Core_Model_Option_ArrayInterface +{ + /** + * @var Mage_Webapi_Model_Resource_Acl_Role + */ + protected $_resource = null; + + /** + * Prepare required models. + * + * @param array $data + */ + public function __construct($data = array()) + { + if (isset($data['resource'])) { + $this->_resource = $data['resource']; + } else { + $this->_resource = Mage::getResourceModel('Mage_Webapi_Model_Resource_Acl_Role'); + } + } + + /** + * Retrieve option hash of Web API Roles. + * + * @param bool $addEmpty + * @return array + */ + public function toOptionHash($addEmpty = true) + { + $options = $this->_getResourceModel()->getRolesList(); + if ($addEmpty) { + $options = array('' => '') + $options; + } + return $options; + } + + /** + * Get roles resource model. + * + * @return Mage_Webapi_Model_Resource_Acl_Role + */ + protected function _getResourceModel() + { + return $this->_resource; + } + + /** + * Return option array. + * + * @return array + */ + public function toOptionArray() + { + $options = $this->_getResourceModel()->getRolesList(); + return $options; + } +} diff --git a/app/code/core/Mage/Webapi/controllers/Adminhtml/Webapi/RoleController.php b/app/code/core/Mage/Webapi/controllers/Adminhtml/Webapi/RoleController.php new file mode 100644 index 0000000000000000000000000000000000000000..71dc4712248166e2ef46458dee597acbf64ff349 --- /dev/null +++ b/app/code/core/Mage/Webapi/controllers/Adminhtml/Webapi/RoleController.php @@ -0,0 +1,306 @@ +<?php +/** + * Controller for web API roles management in Magento admin panel. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Adminhtml_Webapi_RoleController extends Mage_Adminhtml_Controller_Action +{ + /** + * Init. + * + * @return Mage_Webapi_Adminhtml_Webapi_RoleController + */ + protected function _initAction() + { + $this->loadLayout(); + $this->_setActiveMenu('Mage_Webapi::system_api_webapi_roles'); + $this->_addBreadcrumb( + $this->__('Web Api'), + $this->__('Web Api') + ); + $this->_addBreadcrumb( + $this->__('API Roles'), + $this->__('API Roles') + ); + return $this; + } + + /** + * Web API roles grid. + */ + public function indexAction() + { + $this->_title($this->__('System')) + ->_title($this->__('Web Api')) + ->_title($this->__('API Roles')); + $this->_initAction(); + $this->renderLayout(); + } + + /** + * AJAX Web API roles grid. + */ + public function rolegridAction() + { + $this->loadLayout(false); + $this->renderLayout(); + } + + /** + * Grid in edit role form. + */ + public function usersgridAction() + { + $this->loadLayout(false); + $this->renderLayout(); + } + + /** + * Edit Web API role. + */ + public function editAction() + { + $this->_initAction(); + $this->_title($this->__('System')) + ->_title($this->__('Web Api')) + ->_title($this->__('API Roles')); + + $roleId = $this->getRequest()->getParam('role_id'); + + /** @var Mage_Webapi_Model_Acl_Role $role */ + $role = $this->_objectManager->create('Mage_Webapi_Model_Acl_Role'); + if ($roleId) { + $role->load($roleId); + if (!$role->getId()) { + $this->_getSession()->addError( + $this->__('This API role no longer exists.') + ); + $this->_redirect('*/*/'); + return; + } + $this->_addBreadcrumb( + $this->__('Edit API Role'), + $this->__('Edit API Role') + ); + $this->_title($this->__('Edit API Role')); + } else { + $this->_addBreadcrumb( + $this->__('Add New API Role'), + $this->__('Add New API Role') + ); + $this->_title($this->__('New API Role')); + } + + // Restore previously entered form data from session + $data = $this->_getSession()->getWebapiUserData(true); + if (!empty($data)) { + $role->setData($data); + } + + /** @var Mage_Webapi_Block_Adminhtml_Role_Edit $editBlock */ + $editBlock = $this->getLayout()->getBlock('webapi.role.edit'); + if ($editBlock) { + $editBlock->setApiRole($role); + } + + /** @var Mage_Webapi_Block_Adminhtml_Role_Edit_Tabs $tabsBlock */ + $tabsBlock = $this->getLayout()->getBlock('webapi.role.edit.tabs'); + if ($tabsBlock) { + $tabsBlock->setApiRole($role); + } + + $this->renderLayout(); + } + + /** + * Remove role. + */ + public function deleteAction() + { + $roleId = $this->getRequest()->getParam('role_id', false); + + try { + $this->_objectManager->create('Mage_Webapi_Model_Acl_Role')->load($roleId)->delete(); + $this->_getSession()->addSuccess( + $this->__('The API role has been deleted.') + ); + } catch (Exception $e) { + $this->_getSession()->addError( + $this->__('An error occurred while deleting this role.') + ); + } + + $this->_redirect("*/*/"); + } + + /** + * Save role. + */ + public function saveAction() + { + $data = $this->getRequest()->getPost(); + if ($data) { + $roleId = $this->getRequest()->getPost('role_id', false); + /** @var Mage_Webapi_Model_Acl_Role $role */ + $role = $this->_objectManager->create('Mage_Webapi_Model_Acl_Role')->load($roleId); + if (!$role->getId() && $roleId) { + $this->_getSession()->addError( + $this->__('This role no longer exists.') + ); + $this->_redirect('*/*/'); + return; + } + $role->setData($data); + + try { + $this->_validateRole($role); + $role->save(); + + $isNewRole = empty($roleId); + $this->_saveResources($role->getId(), $isNewRole); + $this->_saveUsers($role->getId()); + + $this->_getSession()->addSuccess( + $this->__('The API role has been saved.') + ); + $this->_getSession()->setWebapiRoleData(false); + + if ($roleId && !$this->getRequest()->has('continue')) { + $this->_redirect('*/*/'); + } else { + $this->_redirect('*/*/edit', array('role_id' => $role->getId())); + } + } catch (Exception $e) { + $this->_getSession()->addError($e->getMessage()); + $this->_getSession()->setWebapiRoleData($data); + $this->_redirect('*/*/edit', array('role_id' => $role->getId())); + } + } + } + + /** + * Validate Web API role data. + * + * @param Mage_Webapi_Model_Acl_Role $role + * @throws Magento_Validator_Exception + */ + protected function _validateRole($role) + { + $group = $role->isObjectNew() ? 'create' : 'update'; + $validator = $this->_objectManager->get('Mage_Core_Model_Validator_Factory') + ->createValidator('api_role', $group); + if (!$validator->isValid($role)) { + throw new Magento_Validator_Exception($validator->getMessages()); + } + } + + /** + * Save role resources. + * + * @param integer $roleId + * @param boolean $isNewRole + */ + protected function _saveResources($roleId, $isNewRole) + { + // parse resource list + $resources = explode(',', $this->getRequest()->getParam('resource', false)); + $isAll = $this->getRequest()->getParam('all'); + if ($isAll) { + $resources = array(Mage_Webapi_Model_Authorization::API_ACL_RESOURCES_ROOT_ID); + } elseif (in_array(Mage_Webapi_Helper_Data::RESOURCES_TREE_ROOT_ID, $resources)) { + unset($resources[array_search( + Mage_Webapi_Helper_Data::RESOURCES_TREE_ROOT_ID, + $resources + )]); + } + + $saveResourcesFlag = true; + if (!$isNewRole) { + // Check changes + /** @var Mage_Webapi_Model_Resource_Acl_Rule $ruleResource */ + $ruleResource = $this->_objectManager->get('Mage_Webapi_Model_Resource_Acl_Rule'); + $oldResources = $ruleResource->getResourceIdsByRole($roleId); + if (count($oldResources) == count($resources) && !array_diff($oldResources, $resources)) { + $saveResourcesFlag = false; + } + } + + if ($saveResourcesFlag) { + $this->_objectManager->create('Mage_Webapi_Model_Acl_Rule') + ->setRoleId($roleId) + ->setResources($resources) + ->saveResources(); + } + } + + /** + * Save linked users. + * + * @param integer $roleId + */ + protected function _saveUsers($roleId) + { + // parse users list + $roleUsers = $this->_parseRoleUsers($this->getRequest()->getParam('in_role_user')); + $oldRoleUsers = $this->_parseRoleUsers($this->getRequest()->getParam('in_role_user_old')); + + if ($roleUsers != $oldRoleUsers) { + foreach ($oldRoleUsers as $userId) { + $user = $this->_objectManager->create('Mage_Webapi_Model_Acl_User')->load($userId); + $user->setRoleId(null)->save(); + } + + foreach ($roleUsers as $userId) { + $user = $this->_objectManager->create('Mage_Webapi_Model_Acl_User')->load($userId); + $user->setRoleId($roleId)->save(); + } + } + } + + /** + * Parse request string with users. + * + * @param string $roleUsers + * @return array + */ + protected function _parseRoleUsers($roleUsers) + { + parse_str($roleUsers, $roleUsers); + if ($roleUsers && count($roleUsers)) { + return array_keys($roleUsers); + } + + return array(); + } + + /** + * Check access rights. + * + * @return boolean + */ + protected function _isAllowed() + { + return $this->_objectManager->get('Mage_Core_Model_Authorization')->isAllowed('Mage_Webapi::webapi_roles'); + } + +} diff --git a/app/code/core/Mage/Webapi/controllers/Adminhtml/Webapi/UserController.php b/app/code/core/Mage/Webapi/controllers/Adminhtml/Webapi/UserController.php new file mode 100644 index 0000000000000000000000000000000000000000..3212acbd5cb8919ee002f3380ed8e455b48e7ea1 --- /dev/null +++ b/app/code/core/Mage/Webapi/controllers/Adminhtml/Webapi/UserController.php @@ -0,0 +1,252 @@ +<?php +/** + * Controller for web API users management in Magento admin panel. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Adminhtml_Webapi_UserController extends Mage_Backend_Controller_ActionAbstract +{ + /** + * Initialize breadcrumbs. + * + * @return Mage_Webapi_Adminhtml_Webapi_UserController + */ + protected function _initAction() + { + $this->loadLayout() + ->_setActiveMenu('Mage_Webapi::system_api_webapi_users') + ->_addBreadcrumb( + $this->__('Web Services'), + $this->__('Web Services') + ) + ->_addBreadcrumb( + $this->__('API Users'), + $this->__('API Users') + ); + + return $this; + } + + /** + * Show web API users grid. + */ + public function indexAction() + { + $this->_initAction(); + $this->_title($this->__('System')) + ->_title($this->__('Web Services')) + ->_title($this->__('API Users')); + + $this->renderLayout(); + } + + /** + * Create New Web API user. + */ + public function newAction() + { + $this->getRequest()->setParam('user_id', null); + $this->_forward('edit'); + } + + /** + * Edit Web API user. + */ + public function editAction() + { + $this->_initAction(); + $this->_title($this->__('System')) + ->_title($this->__('Web Services')) + ->_title($this->__('API Users')); + + $userId = (int)$this->getRequest()->getParam('user_id'); + $user = $this->_loadApiUser($userId); + if (!$user) { + return; + } + + // Update title and breadcrumb record. + $actionTitle = $user->getId() + ? $this->_objectManager->get('Mage_Webapi_Helper_Data')->escapeHtml($user->getApiKey()) + : $this->__('New API User'); + $this->_title($actionTitle); + $this->_addBreadcrumb($actionTitle, $actionTitle); + + // Restore previously entered form data from session. + $data = $this->_getSession()->getWebapiUserData(true); + if (!empty($data)) { + $user->setData($data); + } + + /** @var Mage_Webapi_Block_Adminhtml_User_Edit $editBlock */ + $editBlock = $this->getLayout()->getBlock('webapi.user.edit'); + if ($editBlock) { + $editBlock->setApiUser($user); + } + /** @var Mage_Webapi_Block_Adminhtml_User_Edit_Tabs $tabsBlock */ + $tabsBlock = $this->getLayout()->getBlock('webapi.user.edit.tabs'); + if ($tabsBlock) { + $tabsBlock->setApiUser($user); + } + + $this->renderLayout(); + } + + /** + * Save Web API user. + */ + public function saveAction() + { + $userId = (int)$this->getRequest()->getPost('user_id'); + $data = $this->getRequest()->getPost(); + $redirectBack = false; + if ($data) { + $user = $this->_loadApiUser($userId); + if (!$user) { + return; + } + + $user->setData($data); + try { + $this->_validateUserData($user); + $user->save(); + $userId = $user->getId(); + + $this->_getSession() + ->setWebapiUserData(null) + ->addSuccess($this->__('The API user has been saved.')); + $redirectBack = $this->getRequest()->has('back'); + } catch (Mage_Core_Exception $e) { + $this->_getSession() + ->setWebapiUserData($data) + ->addError($e->getMessage()); + $redirectBack = true; + } catch (Exception $e) { + $this->_objectManager->get('Mage_Core_Model_Logger')->logException($e); + $this->_getSession() + ->setWebapiUserData($data) + ->addError($e->getMessage()); + $redirectBack = true; + } + } + if ($redirectBack) { + $this->_redirect('*/*/edit', array('user_id' => $userId)); + } else { + $this->_redirect('*/*/'); + } + } + + /** + * Delete user. + */ + public function deleteAction() + { + $userId = (int)$this->getRequest()->getParam('user_id'); + if ($userId) { + $user = $this->_loadApiUser($userId); + if (!$user) { + return; + } + try { + $user->delete(); + + $this->_getSession()->addSuccess( + $this->__('The API user has been deleted.') + ); + $this->_redirect('*/*/'); + return; + } catch (Exception $e) { + $this->_getSession()->addError($e->getMessage()); + $this->_redirect('*/*/edit', array('user_id' => $userId)); + return; + } + } + $this->_getSession()->addError( + $this->__('Unable to find a user to be deleted.') + ); + $this->_redirect('*/*/'); + } + + /** + * AJAX Web API users grid. + */ + public function gridAction() + { + $this->loadLayout(false); + $this->renderLayout(); + } + + /** + * Web API user roles grid. + */ + public function rolesgridAction() + { + $this->loadLayout(false); + $this->renderLayout(); + } + + /** + * Check ACL. + * + * @return boolean + */ + protected function _isAllowed() + { + return $this->_objectManager->get('Mage_Core_Model_Authorization')->isAllowed('Mage_Webapi::webapi_users'); + } + + /** + * Validate Web API user data. + * + * @param Mage_Webapi_Model_Acl_User $user + * @throws Magento_Validator_Exception + */ + protected function _validateUserData($user) + { + $group = $user->isObjectNew() ? 'create' : 'update'; + $validator = $this->_objectManager->get('Mage_Core_Model_Validator_Factory') + ->createValidator('api_user', $group); + if (!$validator->isValid($user)) { + throw new Magento_Validator_Exception($validator->getMessages()); + } + } + + /** + * Load Web API user. + * + * @param int $userId + * @return bool|Mage_Webapi_Model_Acl_User + */ + protected function _loadApiUser($userId) + { + /** @var Mage_Webapi_Model_Acl_User $user */ + $user = $this->_objectManager->create('Mage_Webapi_Model_Acl_User')->load($userId); + if (!$user->getId() && $userId) { + $this->_getSession()->addError( + $this->__('This user no longer exists.') + ); + $this->_redirect('*/*/'); + return false; + } + return $user; + } +} diff --git a/app/code/core/Mage/Api/etc/adminhtml/acl.xml b/app/code/core/Mage/Webapi/etc/adminhtml/acl.xml similarity index 68% rename from app/code/core/Mage/Api/etc/adminhtml/acl.xml rename to app/code/core/Mage/Webapi/etc/adminhtml/acl.xml index eece5a0db86a54a04b89ed898ccce3a36091b50f..582cf660256d04f1f1299699310ffe44cb3a3b49 100644 --- a/app/code/core/Mage/Api/etc/adminhtml/acl.xml +++ b/app/code/core/Mage/Webapi/etc/adminhtml/acl.xml @@ -1,6 +1,8 @@ <?xml version="1.0"?> <!-- /** + * Configuration of ACL for Webapi module. + * * Magento * * NOTICE OF LICENSE @@ -19,8 +21,6 @@ * versions in the future. If you wish to customize Magento for your * needs please refer to http://www.magentocommerce.com for more information. * - * @category Mage - * @package Mage_Api * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) */ @@ -30,12 +30,9 @@ <resources> <resource id="Mage_Adminhtml::admin"> <resource id="Mage_Adminhtml::system"> - <resource id="Mage_Api::api" module="Mage_Api" title="Web Services" sortOrder="0"> - <resource id="Mage_Api::users" title="SOAP/XML-RPC - Users" sortOrder="10" /> - <resource id="Mage_Api::roles" title="SOAP/XML-RPC - Roles" sortOrder="20" /> - </resource> - <resource id="Mage_Adminhtml::config"> - <resource id="Mage_Api::config_api" module="Mage_Api" title="Magento Core API Section" /> + <resource id="Mage_Webapi::webapi" module="Mage_Webapi" title="Web Services" sortOrder="0"> + <resource id="Mage_Webapi::webapi_users" title="API Users" sortOrder="1"/> + <resource id="Mage_Webapi::webapi_roles" title="API Roles" sortOrder="2"/> </resource> </resource> </resource> diff --git a/app/code/core/Mage/Api/etc/adminhtml/menu.xml b/app/code/core/Mage/Webapi/etc/adminhtml/menu.xml similarity index 58% rename from app/code/core/Mage/Api/etc/adminhtml/menu.xml rename to app/code/core/Mage/Webapi/etc/adminhtml/menu.xml index 77d3a679684f4959a337ec576f28dde03e337920..349eb37b573c0c7f75474619ac8f8175f4928886 100644 --- a/app/code/core/Mage/Api/etc/adminhtml/menu.xml +++ b/app/code/core/Mage/Webapi/etc/adminhtml/menu.xml @@ -1,6 +1,8 @@ <?xml version="1.0"?> <!-- /** + * Configuration of Webapi module menu in Magento admin panel. + * * Magento * * NOTICE OF LICENSE @@ -19,16 +21,17 @@ * versions in the future. If you wish to customize Magento for your * needs please refer to http://www.magentocommerce.com for more information. * - * @category Mage - * @package Mage_Api * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) */ --> <config> <menu> - <add id="Mage_Api::system_api" title="Web Services" module="Mage_Api" sortOrder="25" parent="Mage_Adminhtml::system" resource="Mage_Api::api"/> - <add id="Mage_Api::system_api_users" title="SOAP/XML-RPC - Users" module="Mage_Api" sortOrder="10" parent="Mage_Api::system_api" action="adminhtml/api_user" resource="Mage_Api::users"/> - <add id="Mage_Api::system_api_roles" title="SOAP/XML-RPC - Roles" module="Mage_Api" sortOrder="20" parent="Mage_Api::system_api" action="adminhtml/api_role" resource="Mage_Api::roles"/> + <add id="Mage_Webapi::system_api" title="Web Services" module="Mage_Webapi" sortOrder="25" + parent="Mage_Adminhtml::system" resource="Mage_Webapi::webapi"/> + <add id="Mage_Webapi::system_api_webapi_users" title="API Users" module="Mage_Webapi" sortOrder="1" + parent="Mage_Webapi::system_api" action="adminhtml/webapi_user" resource="Mage_Webapi::webapi_users"/> + <add id="Mage_Webapi::system_api_webapi_roles" title="API Roles" module="Mage_Webapi" sortOrder="2" + parent="Mage_Webapi::system_api" action="adminhtml/webapi_role" resource="Mage_Webapi::webapi_roles"/> </menu> </config> diff --git a/app/code/core/Mage/Api/etc/adminhtml/system.xml b/app/code/core/Mage/Webapi/etc/adminhtml/system.xml similarity index 56% rename from app/code/core/Mage/Api/etc/adminhtml/system.xml rename to app/code/core/Mage/Webapi/etc/adminhtml/system.xml index 336985d42a624003860a81945a80f43aa8f9321e..1bfd4176802a65cc05cc6d15925d41fafdcc75e0 100644 --- a/app/code/core/Mage/Api/etc/adminhtml/system.xml +++ b/app/code/core/Mage/Webapi/etc/adminhtml/system.xml @@ -1,6 +1,8 @@ <?xml version="1.0"?> <!-- /** + * Representation of Webapi module in System Configuration (Magento admin panel). + * * Magento * * NOTICE OF LICENSE @@ -19,30 +21,21 @@ * versions in the future. If you wish to customize Magento for your * needs please refer to http://www.magentocommerce.com for more information. * - * @category Mage - * @package Mage_Api * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) */ --> <config> <system> - <section id="api" translate="label" module="Mage_Api" type="text" sortOrder="101" showInDefault="1" showInWebsite="1" showInStore="1"> - <label>Magento Core API</label> + <section id="webapi" translate="label" module="Mage_Webapi" type="text" sortOrder="102" showInDefault="1" showInWebsite="1" showInStore="1"> + <label>Magento Web API</label> <tab>service</tab> - <resource>Mage_Api::config_api</resource> - <group id="config" translate="label" type="text" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="1"> - <label>General Settings</label> - <field id="charset" translate="label" type="text" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1"> + <resource>Mage_Webapi::config_webapi</resource> + <group id="soap" translate="label" type="text" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="1"> + <label>SOAP Settings</label> + <field id="charset" translate="label comment" type="text" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Default Response Charset</label> - </field> - <field id="session_timeout" translate="label" type="text" sortOrder="20" showInDefault="1" showInWebsite="1" showInStore="1"> - <label>Client Session Timeout (sec.)</label> - </field> - <field id="compliance_wsi" translate="label" type="select" sortOrder="30" showInDefault="1" showInWebsite="1" showInStore="1"> - <label>WS-I Compliance</label> - <source_model>Mage_Backend_Model_Config_Source_Yesno</source_model> - <backend_model>Mage_Backend_Model_Config_Backend_Store</backend_model> + <comment>If empty, UTF-8 will be used.</comment> </field> <field id="wsdl_cache_enabled" translate="label" type="select" sortOrder="40" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Enable WSDL Cache</label> @@ -53,3 +46,4 @@ </section> </system> </config> + diff --git a/app/code/core/Mage/Webapi/etc/config.xml b/app/code/core/Mage/Webapi/etc/config.xml new file mode 100644 index 0000000000000000000000000000000000000000..49b3d138c93446772ab51c793b67b72c6f0d4f85 --- /dev/null +++ b/app/code/core/Mage/Webapi/etc/config.xml @@ -0,0 +1,171 @@ +<?xml version="1.0"?> +<!-- +/** + * Webapi module configuration. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Academic Free License (AFL 3.0) + * that is bundled with this package in the file LICENSE_AFL.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/afl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ +--> +<config> + <modules> + <Mage_Webapi> + <version>1.0.0.3</version> + <active>true</active> + <codePool>core</codePool> + <depends> + <Mage_Core/> + <Mage_Oauth/> + <Mage_Backend/> + </depends> + </Mage_Webapi> + </modules> + <global> + <areas> + <webapi> + <frontName>api</frontName> + <front_controller>Mage_Webapi_Controller_Front</front_controller> + <!--TODO: Utilize base action controller from config, not constant--> + <base_controller>Mage_Webapi_Controller_ActionAbstract</base_controller> + <acl> + <policy>Magento_Authorization_Policy_Acl</policy> + <resourceLoader>Mage_Webapi_Model_Authorization_Loader_Resource</resourceLoader> + <roleLoader>Mage_Webapi_Model_Authorization_Loader_Role</roleLoader> + <ruleLoader>Mage_Webapi_Model_Authorization_Loader_Rule</ruleLoader> + <roleLocator>Mage_Webapi_Model_Authorization_RoleLocator</roleLocator> + </acl> + </webapi> + </areas> + <resources> + <webapi_setup> + <setup> + <module>Mage_Webapi</module> + </setup> + </webapi_setup> + </resources> + <cache> + <types> + <config_webservice translate="label,description" module="Mage_Webapi"> + <label>Web Services Configuration</label> + <description>REST and SOAP configurations, generated WSDL file.</description> + <tags>WEBSERVICE</tags> + </config_webservice> + </types> + </cache> + <webapi> + <rest> + <request> + <interpreters> + <!-- JSON --> + <application_json> + <type>application/json</type> + <model>Mage_Webapi_Controller_Request_Rest_Interpreter_Json</model> + </application_json> + + <!-- XML --> + <application_xml> + <type>application/xml</type> + <model>Mage_Webapi_Controller_Request_Rest_Interpreter_Xml</model> + </application_xml> + <application_xhtml_xml> + <type>application/xhtml+xml</type> + <model>Mage_Webapi_Controller_Request_Rest_Interpreter_Xml</model> + </application_xhtml_xml> + <text_xml> + <type>text/xml</type> + <model>Mage_Webapi_Controller_Request_Rest_Interpreter_Xml</model> + </text_xml> + </interpreters> + </request> + <response> + <renders> + <!-- JSON --> + <default> + <type>*/*</type> + <model>Mage_Webapi_Controller_Response_Rest_Renderer_Json</model> + </default> + <application_json> + <type>application/json</type> + <model>Mage_Webapi_Controller_Response_Rest_Renderer_Json</model> + </application_json> + + <!-- XML --> + <text_xml> + <type>text/xml</type> + <model>Mage_Webapi_Controller_Response_Rest_Renderer_Xml</model> + </text_xml> + <application_xml> + <type>application/xml</type> + <model>Mage_Webapi_Controller_Response_Rest_Renderer_Xml</model> + </application_xml> + <application_xhtml_xml> + <type>application/xhtml+xml</type> + <model>Mage_Webapi_Controller_Response_Rest_Renderer_Xml</model> + </application_xhtml_xml> + </renders> + </response> + </rest> + </webapi> + <di> + <!--<Zend/Server/Reflection><shared>0</shared></Zend/Server/Reflection>--> + <Mage_Webapi_Controller_Router_Route_Webapi> + <shared>0</shared> + </Mage_Webapi_Controller_Router_Route_Webapi> + <Mage_Xml_Generator> + <shared>0</shared> + </Mage_Xml_Generator> + <Mage_Xml_Parser> + <shared>0</shared> + </Mage_Xml_Parser> + <Magento_Code_Scanner_DirectoryScanner> + <shared>0</shared> + </Magento_Code_Scanner_DirectoryScanner> + <Magento_Server_Reflection> + <shared>0</shared> + </Magento_Server_Reflection> + <Mage_Webapi_Model_Authorization_Loader_Resource> + <parameters> + <configuration>Mage_Webapi_Model_Authorization_Config</configuration> + </parameters> + </Mage_Webapi_Model_Authorization_Loader_Resource> + </di> + </global> + <admin> + <routers> + <adminhtml> + <args> + <modules> + <Mage_Webapi before="Mage_Backend">Mage_Webapi_Adminhtml</Mage_Webapi> + </modules> + </args> + </adminhtml> + </routers> + </admin> + <adminhtml> + <layout> + <updates> + <webapi_permissions module="Mage_Webapi"> + <file>layout.xml</file> + </webapi_permissions> + </updates> + </layout> + </adminhtml> +</config> diff --git a/app/code/core/Mage/Webapi/etc/validation.xml b/app/code/core/Mage/Webapi/etc/validation.xml new file mode 100644 index 0000000000000000000000000000000000000000..ae7568f1879079baba8b982a6e318bc8a40832c8 --- /dev/null +++ b/app/code/core/Mage/Webapi/etc/validation.xml @@ -0,0 +1,109 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Webapi module validation configuration. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Academic Free License (AFL 3.0) + * that is bundled with this package in the file LICENSE_AFL.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/afl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ +--> +<validation> + <entity name="api_user"> + <rules> + <rule name="form"> + <property_constraints> + <property name="company_name"> + <constraint class="Magento_Validator_StringLength"> + <argument> + <option name="max">250</option> + </argument> + </constraint> + </property> + <property name="contact_email"> + <constraint class="Magento_Validator_EmailAddress"/> + <constraint class="Magento_Validator_StringLength"> + <argument> + <option name="min">1</option> + <option name="max">250</option> + </argument> + </constraint> + </property> + <property name="api_key"> + <constraint class="Magento_Validator_StringLength"> + <argument> + <option name="min">1</option> + <option name="max">250</option> + </argument> + </constraint> + </property> + <property name="secret"> + <constraint class="Magento_Validator_StringLength"> + <argument> + <option name="min">1</option> + <option name="max">250</option> + </argument> + </constraint> + </property> + </property_constraints> + </rule> + </rules> + <groups> + <group name="create"> + <uses> + <use rule="form"/> + </uses> + </group> + <group name="update"> + <uses> + <use rule="form"/> + </uses> + </group> + </groups> + </entity> + <entity name="api_role"> + <rules> + <rule name="form"> + <property_constraints> + <property name="role_name"> + <constraint class="Magento_Validator_StringLength"> + <argument> + <option name="min">1</option> + <option name="max">250</option> + </argument> + </constraint> + </property> + </property_constraints> + </rule> + </rules> + <groups> + <group name="create"> + <uses> + <use rule="form"/> + </uses> + </group> + <group name="update"> + <uses> + <use rule="form"/> + </uses> + </group> + </groups> + </entity> +</validation> diff --git a/app/code/core/Mage/Webapi/sql/webapi_setup/install-1.0.0.0.php b/app/code/core/Mage/Webapi/sql/webapi_setup/install-1.0.0.0.php new file mode 100644 index 0000000000000000000000000000000000000000..3226a93700bb0eba678b7998f8771226176c4593 --- /dev/null +++ b/app/code/core/Mage/Webapi/sql/webapi_setup/install-1.0.0.0.php @@ -0,0 +1,167 @@ +<?php +/** + * Setup script for Webapi module. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/* @var $installer Mage_Core_Model_Resource_Setup */ +$installer = $this; + +$installer->startSetup(); + +$table = $installer->getConnection() + ->newTable($installer->getTable('webapi_role')) + ->addColumn( + 'role_id', + Varien_Db_Ddl_Table::TYPE_INTEGER, + null, + array( + 'identity' => true, + 'unsigned' => true, + 'nullable' => false, + 'primary' => true, + ), + 'Webapi role ID' +) + ->addColumn( + 'role_name', + Varien_Db_Ddl_Table::TYPE_TEXT, + 255, + array( + 'nullable' => false, + ), + 'Role name is displayed in Adminhtml interface' +) + ->addIndex( + $installer->getIdxName('webapi_role', array('role_name'), Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE), + array('role_name'), + array('type' => Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE) +) + ->setComment('Roles of unified webapi ACL'); +$installer->getConnection()->createTable($table); + +$table = $installer->getConnection() + ->newTable($installer->getTable('webapi_user')) + ->addColumn( + 'user_id', + Varien_Db_Ddl_Table::TYPE_INTEGER, + null, + array( + 'identity' => true, + 'unsigned' => true, + 'nullable' => false, + 'primary' => true, + ), + 'Webapi user ID' +) + ->addColumn( + 'user_name', + Varien_Db_Ddl_Table::TYPE_TEXT, + 255, + array( + 'nullable' => false, + ), + 'User name is displayed in Adminhtml interface' +) + ->addColumn( + 'role_id', + Varien_Db_Ddl_Table::TYPE_INTEGER, + null, + array( + 'unsigned' => true, + 'default' => null, + 'nullable' => true + ), + 'User role from webapi_role' +) + ->addIndex( + $installer->getIdxName('webapi_user', array('role_id'), Varien_Db_Adapter_Interface::INDEX_TYPE_INDEX), + array('role_id'), + array('type' => Varien_Db_Adapter_Interface::INDEX_TYPE_INDEX) +) + ->addIndex( + $installer->getIdxName('webapi_user', array('user_name'), Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE), + array('user_name'), + array('type' => Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE) +) + ->addForeignKey( + $installer->getFkName('webapi_user', 'role_id', 'webapi_role', 'role_id'), + 'role_id', + $installer->getTable('webapi_role'), + 'role_id', + Varien_Db_Ddl_Table::ACTION_SET_NULL, + Varien_Db_Ddl_Table::ACTION_CASCADE +) + ->setComment('Users of unified webapi'); +$installer->getConnection()->createTable($table); + +$table = $installer->getConnection() + ->newTable($installer->getTable('webapi_rule')) + ->addColumn( + 'rule_id', + Varien_Db_Ddl_Table::TYPE_INTEGER, + null, + array( + 'identity' => true, + 'unsigned' => true, + 'nullable' => false, + 'primary' => true + ), + 'Rule ID' +) + ->addColumn( + 'resource_id', + Varien_Db_Ddl_Table::TYPE_TEXT, + 255, + array( + 'nullable' => false, + ), + 'Resource name. Must match resource calls in xml.' +) + ->addColumn( + 'role_id', + Varien_Db_Ddl_Table::TYPE_INTEGER, + null, + array( + 'unsigned' => true, + 'nullable' => false + ), + 'User role from webapi_role' +) + ->addIndex( + $installer->getIdxName('webapi_rule', array('role_id'), Varien_Db_Adapter_Interface::INDEX_TYPE_INDEX), + array('role_id'), + array('type' => Varien_Db_Adapter_Interface::INDEX_TYPE_INDEX) +) + ->addForeignKey( + $installer->getFkName('webapi_rule', 'role_id', 'webapi_role', 'role_id'), + 'role_id', + $installer->getTable('webapi_role'), + 'role_id', + Varien_Db_Ddl_Table::ACTION_CASCADE, + Varien_Db_Ddl_Table::ACTION_CASCADE +) + ->setComment('Permissions of roles to resources'); +$installer->getConnection()->createTable($table); + +$installer->endSetup(); diff --git a/app/code/core/Mage/Webapi/sql/webapi_setup/upgrade-1.0.0.0-1.0.0.1.php b/app/code/core/Mage/Webapi/sql/webapi_setup/upgrade-1.0.0.0-1.0.0.1.php new file mode 100644 index 0000000000000000000000000000000000000000..76e478e83ae1139b37b05e4f36b6f9c56100b3af --- /dev/null +++ b/app/code/core/Mage/Webapi/sql/webapi_setup/upgrade-1.0.0.0-1.0.0.1.php @@ -0,0 +1,44 @@ +<?php +/** + * Update script for Webapi module. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/* @var Mage_Core_Model_Resource_Setup $installer */ +$installer = $this; +$installer->startSetup(); +$connection = $installer->getConnection(); + +$table = $installer->getTable('webapi_user'); +$connection->addColumn( + $table, + 'api_secret', + array( + 'type' => Varien_Db_Ddl_Table::TYPE_TEXT, + 'length' => 255, + 'nullable' => false, + 'comment' => 'API Secret used for authentication.', + ) +); + +$installer->endSetup(); diff --git a/app/code/core/Mage/Webapi/sql/webapi_setup/upgrade-1.0.0.1-1.0.0.2.php b/app/code/core/Mage/Webapi/sql/webapi_setup/upgrade-1.0.0.1-1.0.0.2.php new file mode 100644 index 0000000000000000000000000000000000000000..1452442cf545ddcebbee17184e5897c59a32e85a --- /dev/null +++ b/app/code/core/Mage/Webapi/sql/webapi_setup/upgrade-1.0.0.1-1.0.0.2.php @@ -0,0 +1,77 @@ +<?php +/** + * Update script for Webapi module. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/* @var Mage_Core_Model_Resource_Setup $installer */ +$installer = $this; +$installer->startSetup(); +$connection = $installer->getConnection(); +$table = $installer->getTable('webapi_user'); + +$connection->dropIndex( + $table, + $installer->getIdxName('webapi_user', array('user_name'), Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE) +); + +$connection->addColumn( + $table, + 'company_name', + array( + 'type' => Varien_Db_Ddl_Table::TYPE_TEXT, + 'length' => 255, + 'nullable' => true, + 'comment' => 'Company Name', + ) +); +$connection->addColumn( + $table, + 'contact_email', + array( + 'type' => Varien_Db_Ddl_Table::TYPE_TEXT, + 'length' => 255, + 'nullable' => false, + 'comment' => 'Contact Email', + ) +); +$connection->changeColumn( + $table, + 'user_name', + 'api_key', + array( + 'type' => Varien_Db_Ddl_Table::TYPE_TEXT, + 'length' => 255, + 'nullable' => false, + 'comment' => 'Web API key' + ) +); + +$connection->addIndex( + $table, + $installer->getIdxName('webapi_user', array('api_key'), Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE), + 'api_key', + Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE +); + +$installer->endSetup(); diff --git a/app/code/core/Mage/Webapi/sql/webapi_setup/upgrade-1.0.0.2-1.0.0.3.php b/app/code/core/Mage/Webapi/sql/webapi_setup/upgrade-1.0.0.2-1.0.0.3.php new file mode 100644 index 0000000000000000000000000000000000000000..f88ac4ab356786bd432b4075a40888f546a6c70f --- /dev/null +++ b/app/code/core/Mage/Webapi/sql/webapi_setup/upgrade-1.0.0.2-1.0.0.3.php @@ -0,0 +1,45 @@ +<?php +/** + * Update script for Webapi module. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/* @var Mage_Core_Model_Resource_Setup $installer */ +$installer = $this; +$installer->startSetup(); +$connection = $installer->getConnection(); +$table = $installer->getTable('webapi_user'); + +$connection->changeColumn( + $table, + 'api_secret', + 'secret', + array( + 'type' => Varien_Db_Ddl_Table::TYPE_TEXT, + 'length' => 255, + 'nullable' => false, + 'comment' => 'Secret used for authentication.' + ) +); + +$installer->endSetup(); diff --git a/app/code/core/Mage/Webapi/view/adminhtml/layout.xml b/app/code/core/Mage/Webapi/view/adminhtml/layout.xml new file mode 100644 index 0000000000000000000000000000000000000000..0bf7b5ae82dff73aa1acea16b383088777c4e71b --- /dev/null +++ b/app/code/core/Mage/Webapi/view/adminhtml/layout.xml @@ -0,0 +1,333 @@ +<?xml version="1.0"?> +<!-- +/** + * Layout of Webapi module for Magento admin panel. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Academic Free License (AFL 3.0) + * that is bundled with this package in the file LICENSE_AFL.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/afl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ +--> +<layout> + <adminhtml_webapi_user_grid_block> + <reference name="webapi_user.grid.container"> + <block type="Mage_Backend_Block_Widget_Grid" as="grid" name="webapi.user.grid"> + <arguments> + <id>permissionsUserGrid</id> + <dataSource type="object">Mage_Webapi_Model_Resource_Acl_User_Collection</dataSource> + <use_ajax>true</use_ajax> + <default_sort>user_name</default_sort> + <default_dir>asc</default_dir> + <grid_url type="url"> + <path>*/*/grid</path> + <params> + <_current>1</_current> + </params> + </grid_url> + </arguments> + <block type="Mage_Backend_Block_Widget_Grid_ColumnSet" as="grid.columnSet" name="webapi.user.grid.columnSet"> + <arguments> + <rowUrl> + <path>*/*/edit</path> + <extraParamsTemplate> + <user_id>getId</user_id> + </extraParamsTemplate> + </rowUrl> + <empty_text translate="true" module="Mage_Webapi">No Users Found</empty_text> + </arguments> + <block type="Mage_Backend_Block_Widget_Grid_Column" as="user_id"> + <arguments> + <header translate="true" module="Mage_Webapi">ID</header> + <width>80px</width> + <type>text</type> + <index>user_id</index> + </arguments> + </block> + <block type="Mage_Backend_Block_Widget_Grid_Column" as="contact_email"> + <arguments> + <header translate="true" module="Mage_Webapi">Contact Email</header> + <index>contact_email</index> + </arguments> + </block> + <block type="Mage_Backend_Block_Widget_Grid_Column" as="api_key"> + <arguments> + <header translate="true" module="Mage_Webapi">API Key</header> + <index>api_key</index> + </arguments> + </block> + <block type="Mage_Backend_Block_Widget_Grid_Column" as="role_name"> + <arguments> + <header translate="true" module="Mage_Webapi">Role Name</header> + <index>role_id</index> + <width>200px</width> + <type>options</type> + <options type="options">Mage_Webapi_Model_Source_Acl_Role</options> + </arguments> + </block> + </block> + </block> + </reference> + </adminhtml_webapi_user_grid_block> + + <adminhtml_webapi_user_index> + <update handle="adminhtml_webapi_user_grid_block"/> + <reference name="content"> + <block type="Mage_Webapi_Block_Adminhtml_User" name="webapi_user.grid.container" /> + </reference> + </adminhtml_webapi_user_index> + + <adminhtml_webapi_user_grid> + <update handle="formkey"/> + <update handle="adminhtml_webapi_user_grid_block"/> + <container name="webapi_user.grid.container" label="API Users Grid Container" output="1" /> + </adminhtml_webapi_user_grid> + + <adminhtml_webapi_user_edit> + <update handle="adminhtml_webapi_user_edit_tab_roles_grid_block"/> + <reference name="content"> + <block type="Mage_Webapi_Block_Adminhtml_User_Edit" name="webapi.user.edit"/> + </reference> + <reference name="left"> + <block type="Mage_Webapi_Block_Adminhtml_User_Edit_Tabs" name="webapi.user.edit.tabs"> + <block type="Mage_Webapi_Block_Adminhtml_User_Edit_Tab_Main" name="webapi.user.edit.tab.main" /> + <block type='Mage_Backend_Block_Widget_Grid_Container' name="webapi.user.edit.tab.roles.grid.container"/> + </block> + </reference> + </adminhtml_webapi_user_edit> + + <adminhtml_webapi_user_edit_tab_roles_grid_block> + <reference name="webapi.user.edit.tab.roles.grid.container"> + <block type="Mage_Backend_Block_Widget_Grid" name="webapi.user.edit.tab.roles.grid" as="grid"> + <arguments> + <id>permissionsUserRolesGrid</id> + <dataSource type="object">Mage_Webapi_Model_Resource_Acl_Role_Collection</dataSource> + <use_ajax>true</use_ajax> + <default_sort>sort_order</default_sort> + <default_dir>ASC</default_dir> + <grid_url type="url"> + <path>*/*/rolesgrid</path> + <params> + <_current>1</_current> + </params> + </grid_url> + </arguments> + <action method="setTitle" translate="value"><value>User Roles Information</value></action> + <block type="Mage_Backend_Block_Widget_Grid_ColumnSet" name="webapi.user.edit.tab.roles.grid.columnSet" as="grid.columnSet"> + <arguments> + <id>permissionsUserRolesGrid</id> + </arguments> + <block type="Mage_Backend_Block_Widget_Grid_Column" name="webapi.user.edit.tab.roles.grid.columnSet.role_id" as="role_id"> + <arguments> + <id>role_id</id> + <index>role_id</index> + <html_name>role_id</html_name> + <header translate="true" module="Mage_Webapi">Assigned</header> + <type>radio</type> + <header_css_class>a-center</header_css_class> + <align>center</align> + <filter>0</filter> + <sortable>0</sortable> + <required>0</required> + <value> + <updater>Mage_Webapi_Model_Acl_User_RoleUpdater</updater> + </value> + </arguments> + </block> + <block type="Mage_Backend_Block_Widget_Grid_Column" as="role_name"> + <arguments> + <id>role_name</id> + <header translate="true" module="Mage_Webapi">Role Name</header> + <index>role_name</index> + </arguments> + </block> + </block> + </block> + </reference> + </adminhtml_webapi_user_edit_tab_roles_grid_block> + + <adminhtml_webapi_user_rolesgrid> + <update handle="formkey"/> + <update handle="adminhtml_webapi_user_edit_tab_roles_grid_block"/> + <container name="webapi.user.edit.tab.roles.grid.container" label="API User Roles Grid Container" output="1" /> + </adminhtml_webapi_user_rolesgrid> + + <adminhtml_webapi_role_grid_block> + <reference name="webapi_role.grid.container"> + <block type="Mage_Backend_Block_Widget_Grid" as="grid" name="webapi.role.grid"> + <arguments> + <id>webapiRoleGrid</id> + <dataSource type="object">Mage_Webapi_Model_Resource_Acl_Role_Collection</dataSource> + <use_ajax>true</use_ajax> + <default_sort>role_id</default_sort> + <default_dir>asc</default_dir> + <grid_url type="url"> + <path>*/*/rolegrid</path> + <params> + <_current>1</_current> + </params> + </grid_url> + </arguments> + <block type="Mage_Backend_Block_Widget_Grid_ColumnSet" as="grid.columnSet" name="webapi.role.grid.columnSet"> + <arguments> + <rowUrl> + <path>*/*/edit</path> + <extraParamsTemplate> + <role_id>getId</role_id> + </extraParamsTemplate> + </rowUrl> + <empty_text translate="true" module="Mage_Webapi">No Roles Found</empty_text> + </arguments> + <block type="Mage_Backend_Block_Widget_Grid_Column" as="role_id"> + <arguments> + <header translate="true" module="Mage_Webapi">ID</header> + <width>80px</width> + <type>text</type> + <index>role_id</index> + </arguments> + </block> + <block type="Mage_Backend_Block_Widget_Grid_Column" as="role_name"> + <arguments> + <header translate="true" module="Mage_Webapi">Role Name</header> + <index>role_name</index> + </arguments> + </block> + </block> + </block> + </reference> + </adminhtml_webapi_role_grid_block> + + <adminhtml_webapi_role_index> + <update handle="adminhtml_webapi_role_grid_block"/> + <reference name="content"> + <block type="Mage_Webapi_Block_Adminhtml_Role" name="webapi_role.grid.container"/> + </reference> + </adminhtml_webapi_role_index> + + <adminhtml_webapi_role_rolegrid> + <update handle="formkey"/> + <update handle="adminhtml_webapi_role_grid_block"/> + <container name="webapi_role.grid.container" label="API Roles Grid Container" output="1"/> + </adminhtml_webapi_role_rolegrid> + + <adminhtml_webapi_role_edit> + <update handle="adminhtml_webapi_role_edit_tab_users_grid_block"/> + <reference name="content"> + <block type="Mage_Webapi_Block_Adminhtml_Role_Edit" name="webapi.role.edit"/> + </reference> + <reference name="left"> + <block type="Mage_Webapi_Block_Adminhtml_Role_Edit_Tabs" name="webapi.role.edit.tabs"> + <block type="Mage_Webapi_Block_Adminhtml_Role_Edit_Tab_Main" name="webapi.role.edit.tab.main"/> + <block type="Mage_Webapi_Block_Adminhtml_Role_Edit_Tab_Resource" name="webapi.role.edit.tab.resource" + template="Mage_Webapi::rolesedit.phtml"/> + <block type='Mage_Backend_Block_Widget_Grid_Container' name="webapi.role.edit.tab.users.grid.container"/> + </block> + </reference> + <reference name="head"> + <action method="setCanLoadExtJs"> + <flag>1</flag> + </action> + </reference> + <reference name="js"> + <block type="Mage_Core_Block_Template" template="Mage_Webapi::rolesusersgridjs.phtml"/> + </reference> + </adminhtml_webapi_role_edit> + + <adminhtml_webapi_role_usersgrid> + <update handle="formkey"/> + <update handle="adminhtml_webapi_role_edit_tab_users_grid_block"/> + <container name="webapi.role.edit.tab.users.grid.container" label="API Role Users Grid Container" output="1" /> + </adminhtml_webapi_role_usersgrid> + + <adminhtml_webapi_role_edit_tab_users_grid_block> + <reference name="webapi.role.edit.tab.users.grid"> + <arguments> + <dataSource> + <updater>Mage_Webapi_Model_Acl_Role_UsersUpdater</updater> + </dataSource> + </arguments> + </reference> + <reference name="webapi.role.edit.tab.users.grid.container"> + <block type="Mage_Backend_Block_Widget_Grid" name="webapi.role.edit.tab.users.grid" as="grid"> + <arguments> + <id>roleUserGrid</id> + <dataSource type="object">Mage_Webapi_Model_Resource_Acl_User_Collection</dataSource> + <use_ajax>true</use_ajax> + <default_sort>role_user_id</default_sort> + <default_dir>ASC</default_dir> + <grid_url type="url"> + <path>*/*/usersgrid</path> + <params> + <_current>1</_current> + </params> + </grid_url> + </arguments> + <action method="setTitle" translate="value"><value>Role Users Information</value></action> + <action method="setDefaultFilter"> + <value> + <in_role_users>1</in_role_users> + </value> + </action> + <block type="Mage_Backend_Block_Widget_Grid_ColumnSet" name="webapi.role.edit.tab.users.grid.columnSet" as="grid.columnSet"> + <block type="Mage_Backend_Block_Widget_Grid_Column" name="webapi.role.edit.tab.users.grid.columnSet.in_role_users" as="in_role_users"> + <arguments> + <id>in_role_users</id> + <index>in_role_users</index> + <html_name>in_role_users</html_name> + <header_css_class>a-center</header_css_class> + <type>checkbox</type> + <values> + <updater>Mage_Webapi_Model_Acl_Role_InRoleUserUpdater</updater> + </values> + <name>in_role_users</name> + <align>center</align> + <index>user_id</index> + </arguments> + </block> + <block type="Mage_Backend_Block_Widget_Grid_Column" as="role_user_id"> + <arguments> + <id>role_name</id> + <header translate="true" module="Mage_Webapi">User ID</header> + <width>20</width> + <align>left</align> + <sortable>1</sortable> + <index>user_id</index> + </arguments> + </block> + <block type="Mage_Backend_Block_Widget_Grid_Column" as="role_user_contactemail"> + <arguments> + <id>role_user_contactemail</id> + <header translate="true" module="Mage_Webapi">Contact Email</header> + <align>left</align> + <index>contact_email</index> + </arguments> + </block> + <block type="Mage_Backend_Block_Widget_Grid_Column" as="role_user_apikey"> + <arguments> + <id>role_user_apikey</id> + <header translate="true" module="Mage_Webapi">API Key</header> + <align>left</align> + <index>api_key</index> + </arguments> + </block> + </block> + </block> + </reference> + </adminhtml_webapi_role_edit_tab_users_grid_block> +</layout> diff --git a/app/code/core/Mage/Adminhtml/view/adminhtml/api/rolesedit.phtml b/app/code/core/Mage/Webapi/view/adminhtml/rolesedit.phtml similarity index 67% rename from app/code/core/Mage/Adminhtml/view/adminhtml/api/rolesedit.phtml rename to app/code/core/Mage/Webapi/view/adminhtml/rolesedit.phtml index 756a9ec33ccf0eac840e0cc439101fae8ae0d9a8..57d37370d2277cd8d0d48c69d3ba6561260b9d1d 100644 --- a/app/code/core/Mage/Adminhtml/view/adminhtml/api/rolesedit.phtml +++ b/app/code/core/Mage/Webapi/view/adminhtml/rolesedit.phtml @@ -1,5 +1,7 @@ <?php /** + * Template of web API roles edit page in Magento admin panel. + * * Magento * * NOTICE OF LICENSE @@ -18,24 +20,27 @@ * versions in the future. If you wish to customize Magento for your * needs please refer to http://www.magentocommerce.com for more information. * - * @category design - * @package default_default * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + * + * @var Mage_Webapi_Block_Adminhtml_Role_Edit_Tab_Resource $this */ ?> <div class="entry-edit"> <div class="entry-edit-head"> - <h4 class="icon-head head-edit-form fieldset-legend"><?php echo $this->__('Roles Resources') ?></h4> + <h4 class="icon-head head-edit-form fieldset-legend"><?php + echo $this->__('Roles Resources') ?></h4> </div> <input type="hidden" name="resource" id="role_resources" value=""> - <fieldset id="role_resources"> + <fieldset> <span class="field-row"> <label for="all"><?php echo $this->__('Resource Access') ?></label> <select id="all" name="all" onchange="$('resources_container').toggle()" class="select"> - <option value="0" <?php echo ($this->getEverythingAllowed()?'':'selected="selected"'); ?>><?php echo $this->__('Custom') ?></option> - <option value="1" <?php echo ($this->getEverythingAllowed()?'selected="selected"':''); ?>><?php echo $this->__('All') ?></option> + <option value="0" <?php echo $this->isEverythingAllowed() ? '' : 'selected="selected"'; ?>><?php + echo $this->__('Custom') ?></option> + <option value="1" <?php echo $this->isEverythingAllowed() ? 'selected="selected"' : ''; ?>><?php + echo $this->__('All') ?></option> </select> </span> @@ -50,14 +55,14 @@ </div> <!-- Draw Resources Tree --> <script type="text/javascript"> -<?php if($this->getEverythingAllowed()): ?> +<?php if ($this->isEverythingAllowed()): ?> $('resources_container').hide(); <?php endif; ?> Ext.EventManager.onDocumentReady(function() { var tree = new Ext.tree.TreePanel('resource-tree', { - animate:false, + animate: false, loader: false, - enableDD:false, + enableDD: false, containerScroll: true, rootUIProvider: Ext.tree.CheckboxNodeUI, selModel: new Ext.tree.CheckNodeMultiSelectionModel(), @@ -69,14 +74,15 @@ Ext.EventManager.onDocumentReady(function() { // set the root node var root = new Ext.tree.TreeNode({ text: 'root', - draggable:false, - checked:'false', - id:'__root__', + draggable: false, + checked: 'false', + id: '<?php echo Mage_Webapi_Helper_Data::RESOURCES_TREE_ROOT_ID; ?>', uiProvider: Ext.tree.CheckboxNodeUI }); tree.setRootNode(root); - bildResourcesTree(root, <?php echo $this->getResTreeJson() ?>); + buildResourcesTree(root, <?php echo $this->helper('Mage_Core_Helper_Data') + ->jsonEncode($this->getResourcesTree()) ?>); tree.addListener('click', resourceClick.createDelegate(this)); // render the tree @@ -87,41 +93,43 @@ Ext.EventManager.onDocumentReady(function() { $('role_resources').value = tree.getChecked().join(','); }); -function resourceClick(node, e){ +function resourceClick(node, e) { node.getUI().check(!node.getUI().checked()); varienElementMethods.setHasChanges(Event.element(e), e); -}; +} -function bildResourcesTree(parent, config){ - if (!config) return null; +function buildResourcesTree(parent, config) { + if (!config) { + return null; + } - if (parent && config && config.length){ - for (var i = 0; i < config.length; i++){ + if (parent && config && config.length) { + for (var i = 0; i < config.length; i++) { config[i].uiProvider = Ext.tree.CheckboxNodeUI; var node = new Ext.tree.TreeNode(config[i]); parent.appendChild(node); - if(config[i].children){ - bildResourcesTree(node, config[i].children); + if (config[i].children) { + buildResourcesTree(node, config[i].children); } } } } -function checkHandler(node) -{ - if ( node.attributes.checked && node.parentNode ) { +function checkHandler(node) { + if (node.attributes.checked && node.parentNode) { var n = node.parentNode; this.removeListener('check', checkHandler); do { - if (!n || n.attributes.id == 'admin' || n.attributes.id == '__root__') { + if (!n || n.attributes.id == 'admin' || n.attributes.id == '<?php + echo Mage_Webapi_Helper_Data::RESOURCES_TREE_ROOT_ID; ?>') { break; } else { n.ui.check(true); } - } while (n = n.parentNode ); + } while (n = n.parentNode); this.on('check', checkHandler); } - if ( !node.isLeaf() && node.hasChildNodes() ) { + if (!node.isLeaf() && node.hasChildNodes()) { this.removeListener('check', checkHandler); processChildren(node, node.attributes.checked); this.on('check', checkHandler); @@ -129,12 +137,14 @@ function checkHandler(node) $('role_resources').value = this.getChecked().join(','); } -function processChildren(node, state) -{ - if ( !node.hasChildNodes() ) return false; - for(var i = 0; i < node.childNodes.length; i++ ) { +function processChildren(node, state) { + if (!node.hasChildNodes()) { + return false; + } + + for (var i = 0; i < node.childNodes.length; i++) { node.childNodes[i].ui.check(state); - if ( node.childNodes[i].hasChildNodes() ) { + if (node.childNodes[i].hasChildNodes()) { processChildren(node.childNodes[i], state); } } diff --git a/app/code/core/Mage/Adminhtml/view/adminhtml/api/role_users_grid_js.phtml b/app/code/core/Mage/Webapi/view/adminhtml/rolesusersgridjs.phtml similarity index 51% rename from app/code/core/Mage/Adminhtml/view/adminhtml/api/role_users_grid_js.phtml rename to app/code/core/Mage/Webapi/view/adminhtml/rolesusersgridjs.phtml index 282028f9a8b25150ca406c9f8b464a68d18fefd5..885245224022c532ed651c685fbb60719103722b 100644 --- a/app/code/core/Mage/Adminhtml/view/adminhtml/api/role_users_grid_js.phtml +++ b/app/code/core/Mage/Webapi/view/adminhtml/rolesusersgridjs.phtml @@ -1,5 +1,7 @@ <?php /** + * Template contains JS that handles checkbox on users grid in role edit tab. + * * Magento * * NOTICE OF LICENSE @@ -18,24 +20,36 @@ * versions in the future. If you wish to customize Magento for your * needs please refer to http://www.magentocommerce.com for more information. * - * @category design - * @package default_default * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + * + * @var Mage_Core_Block_Template $this */ ?> -<script type="text/javascript"> -<!-- -<?php $myBlock = $this->getLayout()->getBlock('roleUsersGrid'); ?> -<?php if( is_object($myBlock) && $myBlock->getJsObjectName() ): ?> +<?php $usersGridBlock = $this->getLayout()->getBlock('webapi.role.edit.tab.users.grid'); ?> +<?php $inRoleUsersColumn = $this->getLayout()->getBlock('webapi.role.edit.tab.users.grid.columnSet.in_role_users'); ?> +<?php if ($usersGridBlock && $usersGridBlock->getJsObjectName()): ?> + <script type="text/javascript"> var checkBoxes = $H({}); var warning = false; - var inRoleUsers = $H(<?php echo $myBlock->_getUsers(true) ?>); - if (inRoleUsers.size() > 0) warning = true; + var inRoleUsers = $H(arrayToObject( + <?php echo $this->helper('Mage_Core_Helper_Data')->jsonEncode($inRoleUsersColumn->getValues()) ?>) + ); + if (inRoleUsers.size() > 0) { + warning = true; + } $('in_role_user').value = inRoleUsers.toQueryString(); - function registerUserRole(grid, element, checked){ - if(checked){ + function arrayToObject(array) { + var result = {}; + for (var i = 0; i < array.length; ++i) { + result[array[i]] = 1; + } + return result; + } + + function registerUserRole(grid, element, checked) { + if (checked) { inRoleUsers.set(element.value, 0); } else { inRoleUsers.unset(element.value); @@ -44,15 +58,17 @@ grid.reloadParams = {'in_role_user[]':inRoleUsers.keys()}; } - function roleUsersRowClick(grid, event){ + function roleUsersRowClick(grid, event) { var trElement = Event.findElement(event, 'tr'); - var isInput = Event.element(event).tagName == 'INPUT'; - if(trElement){ + var isInput = Event.element(event).tagName == 'INPUT'; + if (trElement) { var checkbox = Element.getElementsBySelector(trElement, 'input'); - if(checkbox[0]){ + if (checkbox[0]) { var checked = isInput ? checkbox[0].checked : !checkbox[0].checked; - if (warning && checkBoxes.size() > 0) { - if ( !confirm("<?php echo $this->__('Warning!\r\nThis action will remove this user from already assigned role\r\nAre you sure?') ?>") ) { + if (inRoleUsers.get(checkbox[0].value) && !checked && warning && checkBoxes.size() > 0) { + if (!confirm("<?php echo $this + ->__('Warning!\r\nThis action will remove this user from already assigned role\r\nAre you sure?' + ) ?>")) { checkbox[0].checked = false; checkBoxes.each(function(elem) { if (elem.value.status == 1) { @@ -63,22 +79,23 @@ } warning = false; } - <?php echo $myBlock->getJsObjectName() ?>.setCheckboxChecked(checkbox[0], checked); + <?php echo $usersGridBlock->getJsObjectName() ?>.setCheckboxChecked(checkbox[0], checked); } } } - function roleUsersRowInit(grid, row){ + function roleUsersRowInit(grid, row) { var checkbox = $(row).getElementsByClassName('checkbox')[0]; if (checkbox) { checkBoxes.set(checkbox.value, {'status' : ((checkbox.checked) ? 1 : 0), 'object' : checkbox}); } } - function myhandler(obj) - { - if (checkBoxes.size() > 0) { - if ( !confirm("<?php echo $this->__('Warning!\r\nThis action will remove those users from already assigned roles\r\nAre you sure?') ?>") ) { + function checkCheckboxesHandler(obj) { + if (warning && checkBoxes.size() > 0) { + if (!confirm("<?php echo $this + ->__('Warning!\r\nThis action will remove those users from already assigned roles\r\nAre you sure?')?>") + ) { obj.checked = false; checkBoxes.each(function(elem) { if (elem.value.status == 1) { @@ -90,16 +107,18 @@ warning = false; } checkBoxes.each(function(elem) { - <?php echo $myBlock->getJsObjectName() ?>.setCheckboxChecked(elem.value.object, obj.checked); + <?php echo $usersGridBlock->getJsObjectName() ?>.setCheckboxChecked(elem.value.object, obj.checked); }); } -<?php echo $myBlock->getJsObjectName() ?>.rowClickCallback = roleUsersRowClick; -<?php echo $myBlock->getJsObjectName() ?>.initRowCallback = roleUsersRowInit; -<?php echo $myBlock->getJsObjectName() ?>.checkboxCheckCallback = registerUserRole; -<?php echo $myBlock->getJsObjectName() ?>.checkCheckboxes = myhandler; -<?php echo $myBlock->getJsObjectName() ?>.rows.each(function(row){roleUsersRowInit(<?php echo $myBlock->getJsObjectName() ?>, row)}); + <?php echo $usersGridBlock->getJsObjectName() ?>.rowClickCallback = roleUsersRowClick; + <?php echo $usersGridBlock->getJsObjectName() ?>.initRowCallback = roleUsersRowInit; + <?php echo $usersGridBlock->getJsObjectName() ?>.checkboxCheckCallback = registerUserRole; + <?php echo $usersGridBlock->getJsObjectName() ?>.checkCheckboxes = checkCheckboxesHandler; + <?php echo $usersGridBlock->getJsObjectName() ?>.rows.each( + function(row) { + roleUsersRowInit(<?php echo $usersGridBlock->getJsObjectName() ?>, row)} + ); $('in_role_user_old').value = $('in_role_user').value; + </script> <?php endif; ?> -//--> -</script> diff --git a/app/code/core/Mage/Widget/Block/Interface.php b/app/code/core/Mage/Widget/Block/Interface.php index 9e2ab9f4454e108ed00ec7504c719ac22c9a75b5..53d69f4fca8f00e9f6e6a634d8a51c44e47df5d0 100644 --- a/app/code/core/Mage/Widget/Block/Interface.php +++ b/app/code/core/Mage/Widget/Block/Interface.php @@ -33,13 +33,6 @@ */ interface Mage_Widget_Block_Interface { - /** - * Produce and return widget's html output - * - * @return string - */ - public function toHtml(); - /** * Add data to the widget. * Retains previous data in the widget. diff --git a/app/code/core/Zend/Soap/Wsdl.php b/app/code/core/Zend/Soap/Wsdl.php new file mode 100644 index 0000000000000000000000000000000000000000..fac2bd986242474047e3f444b6f2d59ea208aa49 --- /dev/null +++ b/app/code/core/Zend/Soap/Wsdl.php @@ -0,0 +1,736 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Soap + */ + +namespace Zend\Soap; + +use DOMDocument; +use DOMElement; +use Zend\Soap\Wsdl\ComplexTypeStrategy\ComplexTypeStrategyInterface as ComplexTypeStrategy; +use Zend\Uri\Uri; + +/** + * \Zend\Soap\Wsdl + * + * @category Zend + * @package Zend_Soap + */ +class Wsdl +{ + /**#@+ + * XML Namespaces. + */ + const XML_NS = 'xmlns'; + const XML_NS_URI = 'http://www.w3.org/2000/xmlns/'; + const WSDL_NS = 'wsdl'; + const WSDL_NS_URI = 'http://schemas.xmlsoap.org/wsdl/'; + const SOAP_11_NS = 'soap'; + const SOAP_11_NS_URI = 'http://schemas.xmlsoap.org/wsdl/soap/'; + const SOAP_12_NS = 'soap12'; + const SOAP_12_NS_URI = 'http://schemas.xmlsoap.org/wsdl/soap12/'; + const SOAP_ENC_NS = 'soap-enc'; + const SOAP_ENC_URI = 'http://schemas.xmlsoap.org/soap/encoding/'; + const XSD_NS = 'xsd'; + const XSD_NS_URI = 'http://www.w3.org/2001/XMLSchema'; + const TYPES_NS = 'tns'; + /**#@-*/ + + /** + * @var object DomDocument Instance + */ + private $dom; + + /** + * @var object WSDL Root XML_Tree_Node + */ + private $wsdl; + + /** + * @var DOMElement + */ + private $schema = null; + + /** + * Types defined on schema + * + * @var array + */ + private $includedTypes = array(); + + /** + * Strategy for detection of complex types + */ + protected $strategy = null; + + /** + * Map of PHP Class names to WSDL QNames. + * + * @var array + */ + protected $classMap = array(); + + /** + * Constructor + * + * @param string $name Name of the Web Service being Described + * @param string|Uri $uri URI where the WSDL will be available + * @param null|ComplexTypeStrategy $strategy Strategy for detection of complex types + * @param null|array $classMap Map of PHP Class names to WSDL QNames + * @throws Exception\RuntimeException + */ + public function __construct($name, $uri, ComplexTypeStrategy $strategy = null, array $classMap = array()) + { + if ($uri instanceof Uri) { + $uri = $uri->toString(); + } + $this->classMap = $classMap; + $this->dom = new DOMDocument('1.0', 'utf-8'); + $targetNamespace = $this->_escapeUri($uri); + $definitions = $this->dom->createElement('definitions'); + $definitions->setAttributeNS(self::XML_NS_URI, self::XML_NS, self::WSDL_NS_URI); + $definitions->setAttributeNS(self::XML_NS_URI, self::XML_NS . ':' . self::TYPES_NS, $targetNamespace); + $definitions->setAttributeNS(self::XML_NS_URI, self::XML_NS . ':' . self::SOAP_11_NS, self::SOAP_11_NS_URI); + $definitions->setAttributeNS(self::XML_NS_URI, self::XML_NS . ':' . self::SOAP_12_NS, self::SOAP_12_NS_URI); + $definitions->setAttributeNS(self::XML_NS_URI, self::XML_NS . ':' . self::XSD_NS, self::XSD_NS_URI); + $definitions->setAttributeNS(self::XML_NS_URI, self::XML_NS . ':' . self::SOAP_ENC_NS, self::SOAP_ENC_URI); + $definitions->setAttributeNS(self::XML_NS_URI, self::XML_NS . ':' . self::WSDL_NS, self::WSDL_NS_URI); + $definitions->setAttribute('name', $name); + $definitions->setAttribute('targetNamespace', $targetNamespace); + $this->dom->appendChild($definitions); + $this->wsdl = $this->dom->documentElement; + $this->setComplexTypeStrategy($strategy ?: new Wsdl\ComplexTypeStrategy\DefaultComplexType); + } + + /** + * URL encode query part of the URI if it is present. + * + * @param string $uri + * @return string + */ + protected function _escapeUri($uri) + { + // normalize URL + $uri = urldecode($uri); + if (preg_match('/\?(.+)$/', $uri, $matches)) { + $query = $matches[1]; + $uri = str_replace($query, urlencode($query), $uri); + } + + return $uri; + } + + /** + * Convert encoded ampersand back to decoded value, to avoid double encoding by DOMElement::setAttribute() + * + * @param $uri + * @return mixed + */ + protected function _decodeAmpersand($uri) + { + return str_replace('&', '&', $uri); + } + + /** + * Retrieve target namespace of the WSDL document. + * + * @return string + */ + public function getTargetNamespace() + { + $targetNamespace = null; + if ($this->wsdl !== null) { + $targetNamespace = $this->wsdl->getAttribute('targetNamespace'); + } + return $targetNamespace; + } + + /** + * Get the class map of php to wsdl qname types. + * + * @return array + */ + public function getClassMap() + { + return $this->classMap; + } + + /** + * Set the class map of php to wsdl qname types. + */ + public function setClassMap($classMap) + { + $this->classMap = $classMap; + } + + /** + * Set a new uri for this WSDL + * + * @param string|Uri $uri + * @return \Zend\Soap\Wsdl + */ + public function setUri($uri) + { + if ($uri instanceof Uri) { + $uri = $uri->toString(); + } + + if ($this->wsdl !== null) { + $targetNamespace = $this->_escapeUri($uri); + $this->wsdl->setAttributeNS(self::XML_NS_URI, self::XML_NS . ':' . self::TYPES_NS, $targetNamespace); + $this->wsdl->setAttribute('targetNamespace', $targetNamespace); + if ($this->schema !== null) { + $this->schema->setAttribute('targetNamespace', $targetNamespace); + } + } + + return $this; + } + + /** + * Set a strategy for complex type detection and handling + * + * @param ComplexTypeStrategy $strategy + * @return \Zend\Soap\Wsdl + */ + public function setComplexTypeStrategy(ComplexTypeStrategy $strategy) + { + $this->strategy = $strategy; + return $this; + } + + /** + * Get the current complex type strategy + * + * @return ComplexTypeStrategy + */ + public function getComplexTypeStrategy() + { + return $this->strategy; + } + + /** + * Add a {@link http://www.w3.org/TR/wsdl#_messages message} element to the WSDL + * + * @param string $name Name for the {@link http://www.w3.org/TR/wsdl#_messages message} + * @param array $parts An array of {@link http://www.w3.org/TR/wsdl#_message parts} + * The array is constructed like: 'name of part' => 'part xml schema data type' + * or 'name of part' => array('type' => 'part xml schema type') + * or 'name of part' => array('element' => 'part xml element name') + * @return DOMElement The new message's XML_Tree_Node for use in {@link function addDocumentation} + */ + public function addMessage($name, $parts) + { + $message = $this->dom->createElement('message'); + + $message->setAttribute('name', $name); + + if (count($parts) > 0) { + foreach ($parts as $name => $type) { + $part = $this->dom->createElement('part'); + $part->setAttribute('name', $name); + if (is_array($type)) { + foreach ($type as $key => $value) { + $part->setAttribute($key, $value); + } + } else { + $part->setAttribute('type', $type); + } + $message->appendChild($part); + } + } + + $this->wsdl->appendChild($message); + + return $message; + } + + /** + * Add a {@link http://www.w3.org/TR/wsdl#_porttypes portType} element to the WSDL + * + * @param string $name portType element's name + * @return DOMElement The new portType's XML_Tree_Node for use in {@link function addPortOperation} and {@link function addDocumentation} + */ + public function addPortType($name) + { + $portType = $this->dom->createElement('portType'); + $portType->setAttribute('name', $name); + $this->wsdl->appendChild($portType); + + return $portType; + } + + /** + * Add an {@link http://www.w3.org/TR/wsdl#request-response operation} element to a portType element + * + * @param DOMElement $portType a portType XML_Tree_Node, from {@link function addPortType} + * @param string $name Operation name + * @param bool|string $input Input Message + * @param bool|string $output Output Message + * @param bool|string $fault Fault Message + * @return DOMElement The new operation's XML_Tree_Node for use in {@link function addDocumentation} + */ + public function addPortOperation($portType, $name, $input = false, $output = false, $fault = false) + { + $operation = $this->dom->createElement('operation'); + $operation->setAttribute('name', $name); + + if (is_string($input) && (strlen(trim($input)) >= 1)) { + $node = $this->dom->createElement('input'); + $node->setAttribute('message', $input); + $operation->appendChild($node); + } + if (is_string($output) && (strlen(trim($output)) >= 1)) { + $node= $this->dom->createElement('output'); + $node->setAttribute('message', $output); + $operation->appendChild($node); + } + if (is_string($fault) && (strlen(trim($fault)) >= 1)) { + $node = $this->dom->createElement('fault'); + $node->setAttribute('message', $fault); + $operation->appendChild($node); + } + + $portType->appendChild($operation); + + return $operation; + } + + /** + * Add a {@link http://www.w3.org/TR/wsdl#_bindings binding} element to WSDL + * + * @param string $name Name of the Binding + * @param string $portType name of the portType to bind + * @return DOMElement The new binding's XML_Tree_Node for use with {@link function addBindingOperation} and {@link function addDocumentation} + */ + public function addBinding($name, $portType) + { + $binding = $this->dom->createElement('binding'); + $binding->setAttribute('name', $name); + $binding->setAttribute('type', $portType); + + $this->wsdl->appendChild($binding); + + return $binding; + } + + /** + * Add an operation to a binding element + * + * @param DOMElement $binding A binding XML_Tree_Node returned by {@link function addBinding} + * @param string $name + * @param bool|array $input An array of attributes for the input element, allowed keys are: 'use', 'namespace', 'encodingStyle'. {@link http://www.w3.org/TR/wsdl#_soap:body More Information} + * @param bool|array $output An array of attributes for the output element, allowed keys are: 'use', 'namespace', 'encodingStyle'. {@link http://www.w3.org/TR/wsdl#_soap:body More Information} + * @param bool|array $fault An array of attributes for the fault element, allowed keys are: 'name', 'use', 'namespace', 'encodingStyle'. {@link http://www.w3.org/TR/wsdl#_soap:body More Information} + * @param int $soapVersion SOAP version to be used in binding operation. 1.1 used by default. + * @return DOMElement The new Operation's XML_Tree_Node for use with {@link function addSoapOperation} and {@link function addDocumentation} + */ + public function addBindingOperation($binding, $name, $input = false, $output = false, $fault = false, + $soapVersion = SOAP_1_1 + ) { + $operation = $this->dom->createElement('operation'); + $operation->setAttribute('name', $name); + + $soapNs = $soapVersion == SOAP_1_1 ? self::SOAP_11_NS : self::SOAP_12_NS; + if (is_array($input)) { + $node = $this->dom->createElement('input'); + $soap_node = $this->dom->createElement($soapNs . ':body'); + foreach ($input as $name => $value) { + $soap_node->setAttribute($name, $this->_decodeAmpersand($value)); + } + $node->appendChild($soap_node); + $operation->appendChild($node); + } + + if (is_array($output)) { + $node = $this->dom->createElement('output'); + $soap_node = $this->dom->createElement($soapNs . ':body'); + foreach ($output as $name => $value) { + $soap_node->setAttribute($name, $this->_decodeAmpersand($value)); + } + $node->appendChild($soap_node); + $operation->appendChild($node); + } + + if (is_array($fault)) { + $node = $this->dom->createElement('fault'); + if (isset($fault['name'])) { + $node->setAttribute('name', $fault['name']); + } + $soap_node = $this->dom->createElement($soapNs . ':fault'); + foreach ($fault as $name => $value) { + $soap_node->setAttribute($name, $this->_decodeAmpersand($value)); + } + $node->appendChild($soap_node); + $operation->appendChild($node); + } + + $binding->appendChild($operation); + + return $operation; + } + + /** + * Add a {@link http://www.w3.org/TR/wsdl#_soap:binding SOAP binding} element to a Binding element + * + * @param DOMElement $binding A binding XML_Tree_Node returned by {@link function addBinding} + * @param string $style binding style, possible values are "rpc" (the default) and "document" + * @param string $transport Transport method (defaults to HTTP) + * @param int $soapVersion SOAP version to be used in binding. 1.1 used by default. + * @return DOMElement + */ + public function addSoapBinding($binding, $style = 'document', $transport = 'http://schemas.xmlsoap.org/soap/http', + $soapVersion = SOAP_1_1 + ) { + $soapNs = $soapVersion == SOAP_1_1 ? self::SOAP_11_NS : self::SOAP_12_NS; + $soap_binding = $this->dom->createElement($soapNs . ':binding'); + $soap_binding->setAttribute('style', $style); + $soap_binding->setAttribute('transport', $transport); + + $binding->appendChild($soap_binding); + + return $soap_binding; + } + + /** + * Add a {@link http://www.w3.org/TR/wsdl#_soap:operation SOAP operation} to an operation element + * + * @param DOMElement $operation An operation XML_Tree_Node returned by {@link function addBindingOperation} + * @param string $soap_action SOAP Action + * @param int $soapVersion SOAP version to be used in operation. 1.1 used by default. + * @return DOMElement + */ + public function addSoapOperation($operation, $soap_action, $soapVersion = SOAP_1_1) + { + if ($soap_action instanceof Uri) { + $soap_action = $soap_action->toString(); + } + $soapNs = $soapVersion ? self::SOAP_11_NS : self::SOAP_12_NS; + $soap_operation = $this->dom->createElement($soapNs . ':operation'); + $soap_operation->setAttribute('soapAction', $this->_decodeAmpersand($soap_action)); + + $operation->insertBefore($soap_operation, $operation->firstChild); + + return $soap_operation; + } + + /** + * Add a {@link http://www.w3.org/TR/wsdl#_services service} element to the WSDL + * + * @param string $name Service Name + * @param string $port_name Name of the port for the service + * @param string $binding Binding for the port + * @param string $location SOAP Address for the service + * @param int $soapVersion SOAP version to be used in service. 1.1 used by default. + * @return DOMElement The new service's XML_Tree_Node for use with {@link function addDocumentation} + */ + public function addService($name, $port_name, $binding, $location, $soapVersion = SOAP_1_1) + { + if ($location instanceof Uri) { + $location = $location->toString(); + } + $service = $this->dom->createElement('service'); + $service->setAttribute('name', $name); + + $port = $this->dom->createElement('port'); + $port->setAttribute('name', $port_name); + $port->setAttribute('binding', $binding); + + $soapNs = $soapVersion ? self::SOAP_11_NS : self::SOAP_12_NS; + $soap_address = $this->dom->createElement($soapNs . ':address'); + $soap_address->setAttribute('location', $this->_decodeAmpersand($location)); + + $port->appendChild($soap_address); + $service->appendChild($port); + + $this->wsdl->appendChild($service); + + return $service; + } + + /** + * Add a documentation element to any element in the WSDL. + * + * Note that the WSDL {@link http://www.w3.org/TR/wsdl#_documentation specification} uses 'document', + * but the WSDL {@link http://schemas.xmlsoap.org/wsdl/ schema} uses 'documentation' instead. + * The {@link http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html#WSDL_documentation_Element WS-I Basic Profile 1.1} recommends using 'documentation'. + * + * @param DOMElement $input_node An XML_Tree_Node returned by another method to add the documentation to + * @param string $documentation Human readable documentation for the node + * @return DOMElement The documentation element + */ + public function addDocumentation($input_node, $documentation) + { + if ($input_node === $this) { + $node = $this->dom->documentElement; + } else { + $node = $input_node; + } + + $doc = $this->dom->createElement('documentation'); + $doc_cdata = $this->dom->createTextNode(str_replace(array("\r\n", "\r"), "\n", $documentation)); + $doc->appendChild($doc_cdata); + + if ($node->hasChildNodes()) { + $node->insertBefore($doc, $node->firstChild); + } else { + $node->appendChild($doc); + } + + return $doc; + } + + /** + * Add WSDL Types element + * + * @param object $types A DomDocument|DomNode|DomElement|DomDocumentFragment with all the XML Schema types defined in it + */ + public function addTypes($types) + { + if ($types instanceof \DomDocument) { + $dom = $this->dom->importNode($types->documentElement); + $this->wsdl->appendChild($types->documentElement); + } elseif ($types instanceof \DomNode || $types instanceof \DomElement || $types instanceof \DomDocumentFragment ) { + $dom = $this->dom->importNode($types); + $this->wsdl->appendChild($dom); + } + } + + /** + * Add a complex type name that is part of this WSDL and can be used in signatures. + * + * @param string $type + * @param string $wsdlType + * @return \Zend\Soap\Wsdl + */ + public function addType($type, $wsdlType) + { + if (!isset($this->includedTypes[$type])) { + $this->includedTypes[$type] = $wsdlType; + } + return $this; + } + + /** + * Return an array of all currently included complex types + * + * @return array + */ + public function getTypes() + { + return $this->includedTypes; + } + + /** + * Return the Schema node of the WSDL + * + * @return DOMElement + */ + public function getSchema() + { + if ($this->schema == null) { + $this->addSchemaTypeSection(); + } + + return $this->schema; + } + + /** + * Return the WSDL as XML + * + * @return string WSDL as XML + */ + public function toXML() + { + return $this->dom->saveXML(); + } + + /** + * Return DOM Document + * + * @return object DomDocument + */ + public function toDomDocument() + { + return $this->dom; + } + + /** + * Echo the WSDL as XML + * + * @param bool|string $filename + * @return boolean + */ + public function dump($filename = false) + { + if (!$filename) { + echo $this->toXML(); + return true; + } + return file_put_contents($filename, $this->toXML()); + } + + /** + * Returns an XSD Type for the given PHP type + * + * @param string $type PHP Type to get the XSD type for + * @return string + */ + public function getType($type) + { + switch (strtolower($type)) { + case 'string': + case 'str': + return 'xsd:string'; + case 'long': + return 'xsd:long'; + case 'int': + case 'integer': + return 'xsd:int'; + case 'float': + return 'xsd:float'; + case 'double': + return 'xsd:double'; + case 'boolean': + case 'bool': + return 'xsd:boolean'; + case 'array': + return 'soap-enc:Array'; + case 'object': + return 'xsd:struct'; + case 'mixed': + return 'xsd:anyType'; + case 'void': + return ''; + default: + // delegate retrieval of complex type to current strategy + return $this->addComplexType($type); + } + } + + /** + * This function makes sure a complex types section and schema additions are set. + * + * @return \Zend\Soap\Wsdl + */ + public function addSchemaTypeSection() + { + if ($this->schema === null) { + $this->schema = $this->dom->createElement(self::XSD_NS . ':schema'); + $this->schema->setAttribute('targetNamespace', $this->getTargetNamespace()); + $types = $this->dom->createElement('types'); + $types->appendChild($this->schema); + $this->wsdl->appendChild($types); + } + return $this; + } + + /** + * Translate PHP type into WSDL QName + * + * @param string $type + * @return string QName + */ + public function translateType($type) + { + if (isset($this->classMap[$type])) { + return $this->classMap[$type]; + } + + if ($type[0] == '\\') { + $type = substr($type, 1); + } + + $pos = strrpos($type, '\\'); + if ($pos) { + $type = substr($type, $pos+1); + } + + return str_replace('\\', '.', $type); + } + + /** + * Add a {@link http://www.w3.org/TR/wsdl#_types types} data type definition + * + * @param string $type Name of the class to be specified + * @return string XSD Type for the given PHP type + */ + public function addComplexType($type) + { + if (isset($this->includedTypes[$type])) { + return $this->includedTypes[$type]; + } + $this->addSchemaTypeSection(); + + $strategy = $this->getComplexTypeStrategy(); + $strategy->setContext($this); + // delegates the detection of a complex type to the current strategy + return $strategy->addComplexType($type); + } + + /** + * Parse an xsd:element represented as an array into a DOMElement. + * + * @param array $element an xsd:element represented as an array + * @throws Exception\RuntimeException if $element is not an array + * @return DOMElement parsed element + */ + private function _parseElement($element) + { + if (!is_array($element)) { + throw new Exception\RuntimeException("The 'element' parameter needs to be an associative array."); + } + + $elementXml = $this->dom->createElement(self::XSD_NS . ':element'); + foreach ($element as $key => $value) { + if (in_array($key, array('sequence', 'all', 'choice'))) { + if (is_array($value)) { + $complexType = $this->dom->createElement(self::XSD_NS . ':complexType'); + if (count($value) > 0) { + $container = $this->dom->createElement(self::XSD_NS . ':' . $key); + foreach ($value as $subelement) { + $subelementXml = $this->_parseElement($subelement); + $container->appendChild($subelementXml); + } + $complexType->appendChild($container); + } + $elementXml->appendChild($complexType); + } + } else { + $elementXml->setAttribute($key, $value); + } + } + return $elementXml; + } + + /** + * Add an xsd:element represented as an array to the schema. + * + * Array keys represent attribute names and values their respective value. + * The 'sequence', 'all' and 'choice' keys must have an array of elements as their value, + * to add them to a nested complexType. + * + * Example: array( 'name' => 'MyElement', + * 'sequence' => array( array('name' => 'myString', 'type' => 'string'), + * array('name' => 'myInteger', 'type' => 'int') ) ); + * Resulting XML: <xsd:element name="MyElement"><xsd:complexType><xsd:sequence> + * <xsd:element name="myString" type="string"/> + * <xsd:element name="myInteger" type="int"/> + * </xsd:sequence></xsd:complexType></xsd:element> + * + * @param array $element an xsd:element represented as an array + * @return string xsd:element for the given element array + */ + public function addElement($element) + { + $schema = $this->getSchema(); + $elementXml = $this->_parseElement($element); + $schema->appendChild($elementXml); + return self::TYPES_NS . ':' . $element['name']; + } +} diff --git a/dev/api-tests/integration/etc/local-mysql.xml.dist b/dev/api-tests/integration/etc/local-mysql.xml.dist new file mode 100644 index 0000000000000000000000000000000000000000..a59c35ed33d69b41894f50bdc8bfc4820e1341cc --- /dev/null +++ b/dev/api-tests/integration/etc/local-mysql.xml.dist @@ -0,0 +1,68 @@ +<?xml version="1.0"?> +<!-- +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Academic Free License (AFL 3.0) + * that is bundled with this package in the file LICENSE_AFL.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/afl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Magento + * @subpackage integration_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ +--> +<config> + <global> + <install> + <!-- Important: validity of installation date indicates whether an application is installed or not --> + <date><![CDATA[d-d-d-d-d]]></date> + </install> + <crypt> + <key><![CDATA[k-k-k-k-k]]></key> + </crypt> + <disable_local_modules>false</disable_local_modules> + <resources> + <db> + <table_prefix><![CDATA[]]></table_prefix> + </db> + <default_setup> + <connection> + <host><![CDATA[localhost]]></host> + <username><![CDATA[root]]></username> + <password><![CDATA[]]></password> + <dbname><![CDATA[magento_integration_tests]]></dbname> + <initStatements><![CDATA[SET NAMES utf8]]></initStatements> + <model><![CDATA[mysql4]]></model> + <type><![CDATA[pdo_mysql]]></type> + <pdoType><![CDATA[]]></pdoType> + <active>1</active> + </connection> + </default_setup> + </resources> + <session_save><![CDATA[files]]></session_save> + </global> + <admin> + <routers> + <adminhtml> + <args> + <frontName><![CDATA[admin]]></frontName> + </args> + </adminhtml> + </routers> + </admin> +</config> diff --git a/dev/build/publication/extruder/ce.txt b/dev/build/publication/extruder/ce.txt index c3e488f3693939a780ed932d1bacfa9e00cde4f6..4306a0d6b9545d120330402ac79f0691bcf7f76e 100644 --- a/dev/build/publication/extruder/ce.txt +++ b/dev/build/publication/extruder/ce.txt @@ -30,6 +30,8 @@ dev/tests/static/testsuite/Legacy/_files/obsolete_properties_ee.php dev/tests/static/testsuite/Legacy/_files/words_ee.xml dev/tests/static/testsuite/Legacy/Enterprise dev/tests/static/testsuite/Php/_files/{whitelist,blacklist}/ee.txt +dev/tests/unit/testsuite/Magento/Profiler/Driver/PinbaTest.php +dev/tests/unit/testsuite/Magento/Profiler/_files/pinba_functions.php dev/tests/unit/testsuite/Enterprise dev/tools/migration/factory_table_names/replace_ee.php dev/tools/migration/aliases_map/composite_modules_ee.php @@ -40,5 +42,6 @@ downloader/skin/install/images/enterprise.gif downloader/template/enterprise downloader/template/professional lib/Apache +lib/Magento/Profiler/Driver/Pinba.php pub/errors/enterprise pub/errors/pro diff --git a/dev/build/publication/extruder/common.txt b/dev/build/publication/extruder/common.txt index a706f57882eadbe7ecfaf782f103aa3490dae824..999e5dca7f95a1b65efa714ba291041d1c199cfc 100644 --- a/dev/build/publication/extruder/common.txt +++ b/dev/build/publication/extruder/common.txt @@ -9,7 +9,6 @@ app/code/core/Mage/Install/Model/Installer/Db/{Mssql,Oracle}.php app/code/core/Mage/Install/view/install/db/{mssql,oracle}.phtml app/code/core/Mage/Install/view/install/layout_{oracle,mssql}.xml app/etc/config.{oracle,mssql}.xml -dev/api-tests dev/tests/functional dev/tests/integration/etc/local-{oracle,mssql}.xml.dist dev/tests/integration/framework/Magento/Test/Db/cleanup_database.{oracle,mssql}.sql diff --git a/dev/build/publication/sanity/ce.xml b/dev/build/publication/sanity/ce.xml index 6fc81b9267f195a64a0514d62a8828e55bea71b5..9860ab3a100820a3d77cb0baf925e14a00d5b305 100644 --- a/dev/build/publication/sanity/ce.xml +++ b/dev/build/publication/sanity/ce.xml @@ -37,6 +37,7 @@ <word>petervarien</word> <word>sqlsrv</word> <word>ukpromerchant</word> + <word>pinba</word> </words> <whitelist> <item> diff --git a/dev/tests/integration/framework/Magento/Test/Profiler/OutputBamboo.php b/dev/tests/integration/framework/Magento/Test/Profiler/OutputBamboo.php index 78d74a02ef7df2005073ddcd7542a21959f0250f..ac966a9781aef00ffb50cad8665c6f1f5f23c58c 100644 --- a/dev/tests/integration/framework/Magento/Test/Profiler/OutputBamboo.php +++ b/dev/tests/integration/framework/Magento/Test/Profiler/OutputBamboo.php @@ -28,7 +28,7 @@ /** * Class that used for output Magento Profiler results in format compatible with Bamboo Jmeter plugin */ -class Magento_Test_Profiler_OutputBamboo extends Magento_Profiler_Output_Csvfile +class Magento_Test_Profiler_OutputBamboo extends Magento_Profiler_Driver_Standard_Output_Csvfile { /** * @var array @@ -50,19 +50,23 @@ class Magento_Test_Profiler_OutputBamboo extends Magento_Profiler_Output_Csvfile */ public function __construct($filename, array $metrics, $delimiter = ',', $enclosure = '"') { - parent::__construct($filename, null, $delimiter, $enclosure); + parent::__construct($filename, $delimiter, $enclosure); $this->_metrics = $metrics; } /** * Calculate metric value from set of timer names * + * @param Magento_Profiler_Driver_Standard_Stat $stat * @param array $timerNames * @param string $fetchKey * @return int */ - protected function _aggregateTimerValues(array $timerNames, $fetchKey = Magento_Profiler::FETCH_AVG) - { + protected function _aggregateTimerValues( + Magento_Profiler_Driver_Standard_Stat $stat, + array $timerNames, + $fetchKey = Magento_Profiler_Driver_Standard_Stat::AVG + ) { /* Prepare pattern that matches timers with deepest nesting level only */ $nestingSep = preg_quote(Magento_Profiler::NESTING_SEPARATOR, '/'); array_map('preg_quote', $timerNames, array('/')); @@ -70,9 +74,9 @@ class Magento_Test_Profiler_OutputBamboo extends Magento_Profiler_Output_Csvfile /* Sum profiler values for matched timers */ $result = 0; - foreach ($this->_getTimers() as $timerId) { + foreach ($this->_getTimerIds($stat) as $timerId) { if (preg_match($pattern, $timerId)) { - $result += Magento_Profiler::fetch($timerId, $fetchKey); + $result += $stat->fetch($timerId, $fetchKey); } } @@ -86,13 +90,14 @@ class Magento_Test_Profiler_OutputBamboo extends Magento_Profiler_Output_Csvfile * Write content into an opened file handle * * @param resource $fileHandle + * @param Magento_Profiler_Driver_Standard_Stat $stat */ - protected function _writeFileContent($fileHandle) + protected function _writeFileContent($fileHandle, Magento_Profiler_Driver_Standard_Stat $stat) { /* First column must be a timestamp */ $result = array('Timestamp' => time()); foreach ($this->_metrics as $metricName => $timerNames) { - $result[$metricName] = $this->_aggregateTimerValues($timerNames); + $result[$metricName] = $this->_aggregateTimerValues($stat, $timerNames); } fputcsv($fileHandle, array_keys($result), $this->_delimiter, $this->_enclosure); fputcsv($fileHandle, array_values($result), $this->_delimiter, $this->_enclosure); diff --git a/dev/tests/integration/framework/bootstrap.php b/dev/tests/integration/framework/bootstrap.php index 8569042f57a4aa99199e2f03f4c6b8e657b2442a..f4f8f1399fb1673a2ac2d72e86d06e47ce9d98f6 100644 --- a/dev/tests/integration/framework/bootstrap.php +++ b/dev/tests/integration/framework/bootstrap.php @@ -72,17 +72,21 @@ $isDeveloperMode = (defined('TESTS_MAGENTO_DEVELOPER_MODE') && TESTS_MAGENTO_DEV /* Enable profiler if necessary */ if (defined('TESTS_PROFILER_FILE') && TESTS_PROFILER_FILE) { - Magento_Profiler::registerOutput( - new Magento_Profiler_Output_Csvfile($testsBaseDir . DIRECTORY_SEPARATOR . TESTS_PROFILER_FILE) - ); + $driver = new Magento_Profiler_Driver_Standard(); + $driver->registerOutput(new Magento_Profiler_Driver_Standard_Output_Csvfile( + $testsBaseDir . DIRECTORY_SEPARATOR . TESTS_PROFILER_FILE + )); + Magento_Profiler::add($driver); } /* Enable profiler with bamboo friendly output format */ if (defined('TESTS_BAMBOO_PROFILER_FILE') && defined('TESTS_BAMBOO_PROFILER_METRICS_FILE')) { - Magento_Profiler::registerOutput(new Magento_Test_Profiler_OutputBamboo( + $driver = new Magento_Profiler_Driver_Standard(); + $driver->registerOutput(new Magento_Test_Profiler_OutputBamboo( $testsBaseDir . DIRECTORY_SEPARATOR . TESTS_BAMBOO_PROFILER_FILE, require($testsBaseDir . DIRECTORY_SEPARATOR . TESTS_BAMBOO_PROFILER_METRICS_FILE) )); + Magento_Profiler::add($driver); } /* diff --git a/dev/tests/integration/framework/tests/unit/testsuite/Magento/Test/Profiler/OutputBambooTest.php b/dev/tests/integration/framework/tests/unit/testsuite/Magento/Test/Profiler/OutputBambooTest.php index 887c94b5fd3746e3854afef2e3bb135986087a32..16d9239adf2f3ede6f0f6c8a71780115886d1327 100644 --- a/dev/tests/integration/framework/tests/unit/testsuite/Magento/Test/Profiler/OutputBambooTest.php +++ b/dev/tests/integration/framework/tests/unit/testsuite/Magento/Test/Profiler/OutputBambooTest.php @@ -109,7 +109,7 @@ class Magento_Test_Profiler_OutputBambooTest extends PHPUnit_Framework_TestCase public function testDisplay() { - $this->_output->display(); + $this->_output->display(new Magento_Profiler_Driver_Standard_Stat()); Magento_Test_Profiler_OutputBambooTestFilter::assertCollectedData("Timestamp,\"sample metric (ms)\"\n%d,%d"); } } diff --git a/dev/tests/integration/testsuite/Mage/Adminhtml/Utility/Controller.php b/dev/tests/integration/testsuite/Mage/Adminhtml/Utility/Controller.php index 3b8cc50a32e81dd3d26f8cae185b949bf9c314e0..6170cab2ad01632713ab2ac9b6ac7fd7b490da0a 100644 --- a/dev/tests/integration/testsuite/Mage/Adminhtml/Utility/Controller.php +++ b/dev/tests/integration/testsuite/Mage/Adminhtml/Utility/Controller.php @@ -46,6 +46,7 @@ class Mage_Adminhtml_Utility_Controller extends Magento_Test_TestCase_Controller { parent::setUp(); + Mage::setCurrentArea('adminhtml'); Mage::getSingleton('Mage_Backend_Model_Url')->turnOffSecretKey(); $this->_auth = Mage::getModel('Mage_Backend_Model_Auth'); diff --git a/dev/tests/integration/testsuite/Mage/Adminhtml/controllers/CustomerControllerTest.php b/dev/tests/integration/testsuite/Mage/Adminhtml/controllers/CustomerControllerTest.php index 32b4077ea5a559f73f0e536999da1b1998984d99..f97f3d679867ab405556f438e1a8be190a3525c9 100644 --- a/dev/tests/integration/testsuite/Mage/Adminhtml/controllers/CustomerControllerTest.php +++ b/dev/tests/integration/testsuite/Mage/Adminhtml/controllers/CustomerControllerTest.php @@ -79,7 +79,7 @@ class Mage_Adminhtml_CustomerControllerTest extends Mage_Adminhtml_Utility_Contr * Check that customer data were set to session */ $this->assertEquals($post, Mage::getSingleton('Mage_Backend_Model_Session')->getCustomerData()); - $this->assertRedirect($this->stringStartsWith($this->_baseControllerUrl . 'edit/key')); + $this->assertRedirect($this->stringStartsWith($this->_baseControllerUrl . 'new/key')); } public function testSaveActionWithInvalidCustomerAddressData() @@ -106,7 +106,7 @@ class Mage_Adminhtml_CustomerControllerTest extends Mage_Adminhtml_Utility_Contr * Check that customer data were set to session */ $this->assertEquals($post, Mage::getSingleton('Mage_Backend_Model_Session')->getCustomerData()); - $this->assertRedirect($this->stringStartsWith($this->_baseControllerUrl . 'edit/key')); + $this->assertRedirect($this->stringStartsWith($this->_baseControllerUrl . 'new/key')); } /** diff --git a/dev/tests/integration/testsuite/Mage/Adminhtml/controllers/Sales/Order/CreditmemoControllerTest.php b/dev/tests/integration/testsuite/Mage/Adminhtml/controllers/Sales/Order/CreditmemoControllerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..03fe35167b5116a28676b7e097e2ccae5661d364 --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Adminhtml/controllers/Sales/Order/CreditmemoControllerTest.php @@ -0,0 +1,64 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_Adminhtml + * @subpackage integration_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_Adminhtml_Sales_Order_CreditmemoControllerTest extends Mage_Adminhtml_Utility_Controller +{ + /** + * @magentoConfigFixture current_store cataloginventory/item_options/auto_return 1 + * @magentoDataFixture Mage/Adminhtml/controllers/Sales/_files/order_info.php + */ + public function testAddCommentAction() + { + /** @var $stockItem Mage_CatalogInventory_Model_Stock_Item */ + $stockItem = Mage::getModel('Mage_CatalogInventory_Model_Stock_Item'); + $stockItem->loadByProduct(1); + $this->assertEquals(95, $stockItem->getStockQty()); + $stockItem = null; + + /** @var $order Mage_Sales_Model_Order */ + $order = Mage::getModel('Mage_Sales_Model_Order'); + $order->load('100000001', 'increment_id'); + + $items = $order->getCreditmemosCollection()->getItems(); + $creditmemo = array_shift($items); + $comment = 'Test Comment 02'; + + $this->getRequest()->setParam('creditmemo_id', $creditmemo->getId()); + $this->getRequest()->setPost('comment', array( + 'comment' => $comment)); + $this->dispatch('backend/admin/sales_order_creditmemo/addComment/id/' . $creditmemo->getId()); + + $html = $this->getResponse()->getBody(); + + $this->assertContains($comment, $html); + /** @var $stockItem Mage_CatalogInventory_Model_Stock_Item */ + $stockItem = Mage::getModel('Mage_CatalogInventory_Model_Stock_Item'); + $stockItem->loadByProduct(1); + $this->assertEquals(95, $stockItem->getStockQty()); + } + +} diff --git a/dev/tests/integration/testsuite/Mage/Adminhtml/controllers/Sales/_files/address_data.php b/dev/tests/integration/testsuite/Mage/Adminhtml/controllers/Sales/_files/address_data.php new file mode 100644 index 0000000000000000000000000000000000000000..4f4be49a3a8bae9a5f2830755ad03ce577d5a0b8 --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Adminhtml/controllers/Sales/_files/address_data.php @@ -0,0 +1,38 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Adminhtml + * @subpackage integration_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +return array( + 'region' => 'CA', + 'postcode' => '11111', + 'lastname' => 'lastname', + 'firstname' => 'firstname', + 'street' => 'street', + 'city' => 'Los Angeles', + 'email' => 'admin@example.com', + 'telephone' => '11111111', + 'country_id' => 'US', +); diff --git a/dev/tests/integration/testsuite/Mage/Adminhtml/controllers/Sales/_files/order_info.php b/dev/tests/integration/testsuite/Mage/Adminhtml/controllers/Sales/_files/order_info.php new file mode 100644 index 0000000000000000000000000000000000000000..1b6be24aa4c7b0abe4c73275fcd99c6082d7c017 --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Adminhtml/controllers/Sales/_files/order_info.php @@ -0,0 +1,112 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Adminhtml + * @subpackage integration_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** @var $product Mage_Catalog_Model_Product */ +$product = Mage::getModel('Mage_Catalog_Model_Product'); +$product->setTypeId('simple') + ->setId(1) + ->setAttributeSetId(4) + ->setName('Simple Product') + ->setSku('simple') + ->setPrice(10) + ->setStockData(array( + 'use_config_manage_stock' => 1, + 'qty' => 100, + 'is_qty_decimal' => 0, + 'is_in_stock' => 100, + )) + ->setVisibility(Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH) + ->setStatus(Mage_Catalog_Model_Product_Status::STATUS_ENABLED) + ->save(); +$product->load(1); + +$addressData = include(__DIR__ . DIRECTORY_SEPARATOR . 'address_data.php'); + +$billingAddress = Mage::getModel('Mage_Sales_Model_Quote_Address', array('data' => $addressData)); +$billingAddress->setAddressType('billing'); + +$shippingAddress = clone $billingAddress; +$shippingAddress->setId(null) + ->setAddressType('shipping'); +$shippingAddress->setShippingMethod('flatrate_flatrate'); + +/** @var $quote Mage_Sales_Model_Quote */ +$quote = Mage::getModel('Mage_Sales_Model_Quote'); +$quote->setCustomerIsGuest(true) + ->setStoreId(Mage::app()->getStore()->getId()) + ->setReservedOrderId('test01') + ->setBillingAddress($billingAddress) + ->setShippingAddress($shippingAddress) + ->addProduct($product, 10); +$quote->getPayment()->setMethod('checkmo'); +$quote->getShippingAddress()->setShippingMethod('flatrate_flatrate'); +$quote->save(); + +$quote->getShippingAddress()->setCollectShippingRates(true); +$quote->getShippingAddress()->collectShippingRates(); +$quote->collectTotals(); +$quote->save(); + +/** @var $service Mage_Sales_Model_Service_Quote */ +$service = Mage::getModel('Mage_Sales_Model_Service_Quote', array('quote' => $quote)); +$service->setOrderData(array('increment_id' => '100000001')); +$service->submitAll(); + +$order = $service->getOrder(); +$order->save(); + +$orderItems = $order->getAllItems(); + +/** @var $item Mage_Sales_Model_Order_Item */ +$item = $orderItems[0]; + +/** @var $invoice Mage_Sales_Model_Order_Invoice */ +$invoice = Mage::getModel('Mage_Sales_Model_Service_Order', array('order' => $order)) + ->prepareInvoice(array($item->getId() => 10)); + +$invoice->register(); +$invoice->save(); + +$creditmemo = Mage::getModel('Mage_Sales_Model_Service_Order', array('order' => $order)) + ->prepareInvoiceCreditmemo($invoice, array('qtys' => array($item->getId() => 5))); + +foreach ($creditmemo->getAllItems() as $creditmemoItem) { + //Workaround to return items to stock + $creditmemoItem->setBackToStock(true); +} + +$creditmemo->register(); +$creditmemo->save(); + +$transactionSave = Mage::getModel('Mage_Core_Model_Resource_Transaction') + ->addObject($creditmemo) + ->addObject($creditmemo->getOrder()); +if ($creditmemo->getInvoice()) { + $transactionSave->addObject($creditmemo->getInvoice()); +} + +$transactionSave->save(); diff --git a/dev/tests/integration/testsuite/Mage/Backend/Block/System/Config/FormStub.php b/dev/tests/integration/testsuite/Mage/Backend/Block/System/Config/FormStub.php index 4e0a63b9f1d88806663ba88dadbc26e910298510..746fc31aaa3d01c09eee81c860366ced456aab29 100644 --- a/dev/tests/integration/testsuite/Mage/Backend/Block/System/Config/FormStub.php +++ b/dev/tests/integration/testsuite/Mage/Backend/Block/System/Config/FormStub.php @@ -55,7 +55,7 @@ class Mage_Backend_Block_System_Config_FormStub extends Mage_Backend_Block_Syste { parent::_initObjects(); $this->_configData = $this->_configDataStub; - $this->_defaultFieldRenderer = Mage::app()->getLayout()->createBlock( + $this->_fieldRenderer = Mage::app()->getLayout()->createBlock( 'Mage_Backend_Block_System_Config_Form_Field' ); } diff --git a/dev/tests/integration/testsuite/Mage/Backend/Block/System/Config/FormTest.php b/dev/tests/integration/testsuite/Mage/Backend/Block/System/Config/FormTest.php index 50ef3196e5c5af3a7039219cd64b790f62072fa6..a0f4bcb42cbf438ecf15192ab57f4413bdeea5a0 100644 --- a/dev/tests/integration/testsuite/Mage/Backend/Block/System/Config/FormTest.php +++ b/dev/tests/integration/testsuite/Mage/Backend/Block/System/Config/FormTest.php @@ -31,9 +31,9 @@ class Mage_Backend_Block_System_Config_FormTest extends PHPUnit_Framework_TestCa { /** @var $layout Mage_Core_Model_Layout */ $layout = Mage::getModel('Mage_Core_Model_Layout'); + Mage::getConfig()->setCurrentAreaCode('adminhtml'); /** @var $block Mage_Backend_Block_System_Config_Form */ $block = $layout->createBlock('Mage_Backend_Block_System_Config_Form', 'block'); - $block->setArea('adminhtml'); /** @var $childBlock Mage_Core_Block_Text */ $childBlock = $layout->addBlock('Mage_Core_Block_Text', 'element_dependence', 'block'); @@ -47,17 +47,18 @@ class Mage_Backend_Block_System_Config_FormTest extends PHPUnit_Framework_TestCa /** * @covers Mage_Backend_Block_System_Config_Form::initFields - * @param $section Mage_Core_Model_Config_Element - * @param $group Mage_Core_Model_Config_Element - * @param $field Mage_Core_Model_Config_Element + * @param $section Mage_Backend_Model_Config_Structure_Element_Section + * @param $group Mage_Backend_Model_Config_Structure_Element_Group + * @param $field Mage_Backend_Model_Config_Structure_Element_Field * @param array $configData * @param bool $expectedUseDefault * @dataProvider initFieldsInheritCheckboxDataProvider */ public function testInitFieldsUseDefaultCheckbox($section, $group, $field, array $configData, $expectedUseDefault) { + Mage::getConfig()->setCurrentAreaCode('adminhtml'); $form = new Varien_Data_Form(); - $fieldset = $form->addFieldset($section['id'] . '_' . $group['id'], array()); + $fieldset = $form->addFieldset($section->getId() . '_' . $group->getId(), array()); /** @var $block Mage_Backend_Block_System_Config_FormStub */ $block = Mage::app()->getLayout()->createBlock('Mage_Backend_Block_System_Config_FormStub'); @@ -66,10 +67,10 @@ class Mage_Backend_Block_System_Config_FormTest extends PHPUnit_Framework_TestCa $block->initFields($fieldset, $group, $section); $fieldsetSel = 'fieldset'; - $valueSel = sprintf('input#%s_%s_%s', $section['id'], $group['id'], $field['id']); + $valueSel = sprintf('input#%s_%s_%s', $section->getId(), $group->getId(), $field->getId()); $valueDisabledSel = sprintf('%s[disabled="disabled"]', $valueSel); - $useDefaultSel = sprintf('input#%s_%s_%s_inherit.checkbox', $section['id'], $group['id'], - $field['id']); + $useDefaultSel = sprintf('input#%s_%s_%s_inherit.checkbox', $section->getId(), $group->getId(), + $field->getId()); $useDefaultCheckedSel = sprintf('%s[checked="checked"]', $useDefaultSel); $fieldsetHtml = $fieldset->getElementHtml(); @@ -96,15 +97,32 @@ class Mage_Backend_Block_System_Config_FormTest extends PHPUnit_Framework_TestCa */ public function initFieldsInheritCheckboxDataProvider() { + Mage::getConfig()->setCurrentAreaCode('adminhtml'); + Mage::getConfig()->setOptions(array('global_ban_use_cache' => 1)); + + $configMock = $this->getMock('Mage_Core_Model_Config', array(), array(), '', false, false); + $configMock->expects($this->any())->method('getModuleConfigurationFiles') + ->will($this->returnValue(array(__DIR__ . '/_files/test_section_config.xml'))); + $configMock->expects($this->any())->method('getAreaConfig')->will($this->returnValue('adminhtml')); + + $structureReader = Mage::getSingleton('Mage_Backend_Model_Config_Structure_Reader', + array('config' => $configMock) + ); + /** @var Mage_Backend_Model_Config_Structure $structure */ $structure = Mage::getSingleton('Mage_Backend_Model_Config_Structure', array( - 'sourceFiles' => array(__DIR__ . '/_files/test_section_config.xml') + 'structureReader' => $structureReader, )); - // @codingStandardsIgnoreStart - $section = $structure->getSection('test_section'); - $group = $section['groups']['test_group']; - $field = $group['fields']['test_field']; - $fieldPath = isset($field['config_path']) ? (string) $field['config_path'] : null; - // @codingStandardsIgnoreEnd + + /** @var Mage_Backend_Model_Config_Structure_Element_Section $section */ + $section = $structure->getElement('test_section'); + + /** @var Mage_Backend_Model_Config_Structure_Element_Group $group */ + $group = $structure->getElement('test_section/test_group'); + + /** @var Mage_Backend_Model_Config_Structure_Element_Field $field */ + $field = $structure->getElement('test_section/test_group/test_field'); + + $fieldPath = $field->getConfigPath(); return array( array($section, $group, $field, array(), true), diff --git a/dev/tests/integration/testsuite/Mage/Backend/Model/Config/Source/Admin/PageTest.php b/dev/tests/integration/testsuite/Mage/Backend/Model/Config/Source/Admin/PageTest.php index cd7d11b4551860e3b60a1d098a60b7db1bcdcb83..b9080e053147fc8f2b0d43d7755d8c6c7a5d3be8 100644 --- a/dev/tests/integration/testsuite/Mage/Backend/Model/Config/Source/Admin/PageTest.php +++ b/dev/tests/integration/testsuite/Mage/Backend/Model/Config/Source/Admin/PageTest.php @@ -32,6 +32,7 @@ class Mage_Backend_Model_Config_Source_Admin_PageTest extends Mage_Adminhtml_Uti { public function testToOptionArray() { + Mage::getConfig()->setCurrentAreaCode('adminhtml'); $this->dispatch('backend/admin/system_config/edit/section/admin'); $dom = PHPUnit_Util_XML::load($this->getResponse()->getBody(), true); diff --git a/dev/tests/integration/testsuite/Mage/Backend/Model/ConfigTest.php b/dev/tests/integration/testsuite/Mage/Backend/Model/ConfigTest.php index 4392d87e5fa934777f13b07cc99822e36147afca..1beca7f334db4d493b9e5f2b6fd4ef2219264f29 100644 --- a/dev/tests/integration/testsuite/Mage/Backend/Model/ConfigTest.php +++ b/dev/tests/integration/testsuite/Mage/Backend/Model/ConfigTest.php @@ -38,6 +38,7 @@ class Mage_Backend_Model_Config_DataTest extends PHPUnit_Framework_TestCase */ public function testSaveWithSingleStoreModeEnabled($groups) { + Mage::getConfig()->setCurrentAreaCode('adminhtml'); /** @var $_configDataObject Mage_Backend_Model_Config */ $_configDataObject = Mage::getModel('Mage_Backend_Model_Config'); $_configData = $_configDataObject->setSection('dev') diff --git a/dev/tests/integration/testsuite/Mage/Backend/Model/UrlTest.php b/dev/tests/integration/testsuite/Mage/Backend/Model/UrlTest.php index d127e913a5d0fa2428d57144aa583924f16924c5..2716a1fd438e1c1d7b78bfb3747c3d6b6adea9e0 100644 --- a/dev/tests/integration/testsuite/Mage/Backend/Model/UrlTest.php +++ b/dev/tests/integration/testsuite/Mage/Backend/Model/UrlTest.php @@ -48,20 +48,20 @@ class Mage_Backend_Model_UrlTest extends PHPUnit_Framework_TestCase /** * @covers Mage_Backend_Model_Url::getSecure */ - public function testGetSecure() + public function testIsSecure() { Mage::app()->getStore()->setConfig('web/secure/use_in_adminhtml', true); - $this->assertTrue($this->_model->getSecure()); + $this->assertTrue($this->_model->isSecure()); Mage::app()->getStore()->setConfig('web/secure/use_in_adminhtml', false); - $this->assertFalse($this->_model->getSecure()); + $this->assertFalse($this->_model->isSecure()); $this->_model->setData('secure_is_forced', true); $this->_model->setData('secure', true); - $this->assertTrue($this->_model->getSecure()); + $this->assertTrue($this->_model->isSecure()); $this->_model->setData('secure', false); - $this->assertFalse($this->_model->getSecure()); + $this->assertFalse($this->_model->isSecure()); } /** diff --git a/dev/tests/integration/testsuite/Mage/Catalog/Model/Category/Api/V2Test.php b/dev/tests/integration/testsuite/Mage/Catalog/Model/Category/Api/V2Test.php deleted file mode 100644 index c45101cd99b487a3bc5091eae74627d515377064..0000000000000000000000000000000000000000 --- a/dev/tests/integration/testsuite/Mage/Catalog/Model/Category/Api/V2Test.php +++ /dev/null @@ -1,79 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Magento - * @package Magento_Catalog - * @subpackage integration_tests - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Test class for Mage_Catalog_Model_Category_Api_V2. - */ -class Mage_Catalog_Model_Category_Api_V2Test extends PHPUnit_Framework_TestCase -{ - /** - * @var Mage_Catalog_Model_Category_Api_V2 - */ - protected $_model; - - protected function setUp() - { - $this->_model = Mage::getModel('Mage_Catalog_Model_Category_Api_V2'); - Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID); - } - - protected function tearDown() - { - $this->_model = null; - } - - public function testCRUD() - { - // @codingStandardsIgnoreStart - $category = new stdClass(); - $category->name = 'test category'; - $category->available_sort_by = 'name'; - $category->default_sort_by = 'name'; - $category->is_active = 1; - $category->include_in_menu = 1; - // @codingStandardsIgnoreEnd - - $categoryId = $this->_model->create(1, $category); - $this->assertNotEmpty($categoryId); - $data = $this->_model->info($categoryId); - $this->assertNotEmpty($data); - $this->assertEquals($category->name, $data['name']); - // @codingStandardsIgnoreStart - $this->assertEquals($category->default_sort_by, $data['default_sort_by']); - $this->assertEquals($category->is_active, $data['is_active']); - // @codingStandardsIgnoreEnd - - $category->name = 'new name'; - $this->_model->update($categoryId, $category); - $data = $this->_model->info($categoryId); - $this->assertNotEmpty($data); - $this->assertEquals($category->name, $data['name']); - - $this->assertTrue($this->_model->delete($categoryId)); - } - -} diff --git a/dev/tests/integration/testsuite/Mage/Catalog/Model/Category/ApiTest.php b/dev/tests/integration/testsuite/Mage/Catalog/Model/Category/ApiTest.php deleted file mode 100644 index dcb45530a958e5b10bbf230763b4b37668b495c1..0000000000000000000000000000000000000000 --- a/dev/tests/integration/testsuite/Mage/Catalog/Model/Category/ApiTest.php +++ /dev/null @@ -1,181 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Magento - * @package Magento_Catalog - * @subpackage integration_tests - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Test class for Mage_Catalog_Model_Category_Api. - * - * @magentoDataFixture Mage/Catalog/_files/categories.php - */ -class Mage_Catalog_Model_Category_ApiTest extends PHPUnit_Framework_TestCase -{ - /** - * @var Mage_Catalog_Model_Category_Api - */ - protected $_model; - - protected function setUp() - { - $this->_model = Mage::getModel('Mage_Catalog_Model_Category_Api'); - Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID); - } - - protected function tearDown() - { - $this->_model = null; - } - - public function testLevel() - { - $default = $this->_model->level(); - $this->assertNotEmpty($default); - - $forWebsite = $this->_model->level(1); - $this->assertNotEmpty($forWebsite); - - $this->assertEquals($default, $forWebsite); - $this->assertEquals( - $default, - array( - array( - 'category_id' => 2, - 'parent_id' => 1, - 'name' => 'Default Category', - 'is_active' => 1, - 'position' => 1, - 'level' => 1 - ) - ) - ); - - } - - public function testTree() - { - $tree = $this->_model->tree(); - $this->assertNotEmpty($tree); - $this->assertArrayHasKey('category_id', $tree); - $this->assertArrayHasKey('name', $tree); - $this->assertEquals(Mage_Catalog_Model_Category::TREE_ROOT_ID, $tree['category_id']); - } - - public function testCRUD() - { - $categoryId = $this->_model->create(1, array( - 'name' => 'test category', - 'available_sort_by' => 'name', - 'default_sort_by' => 'name', - 'is_active' => 1, - 'include_in_menu' => 1 - )); - $this->assertNotEmpty($categoryId); - $data = $this->_model->info($categoryId); - $this->assertNotEmpty($data); - $this->assertEquals('test category', $data['name']); - - $this->_model->update($categoryId, array( - 'name' => 'new name', - 'available_sort_by' => 'name', - 'default_sort_by' => 'name', - 'is_active' => 1, - 'include_in_menu' => 1 - )); - $data = $this->_model->info($categoryId); - $this->assertEquals('new name', $data['name']); - - $this->_model->delete($categoryId); - } - - public function testMove() - { - $this->assertTrue($this->_model->move(7, 6, 0)); - } - - public function testAssignedProducts() - { - $this->assertEmpty($this->_model->assignedProducts(1)); - $this->assertEquals( - array(array( - 'product_id' => 1, - 'type' => 'simple', - 'set' => 4, - 'sku' => 'simple', - 'position' => '1', - )), - $this->_model->assignedProducts(3) - ); - } - - /** - * @param int $categoryId - * @param int|string $productId - * @param string|null $identifierType - * @dataProvider assignProductDataProvider - */ - public function testAssignProduct($categoryId, $productId, $identifierType = null) - { - $this->assertEmpty($this->_model->assignedProducts($categoryId)); - $this->assertTrue($this->_model->assignProduct($categoryId, $productId, null, $identifierType)); - $this->assertNotEmpty($this->_model->assignedProducts($categoryId)); - } - - public function assignProductDataProvider() - { - return array( - 'product id' => array(1, 1), - 'product sku implicit' => array(6, 'simple'), - 'product sku explicit' => array(7, 12345, 'sku'), - ); - } - - /** - * @depends testAssignProduct - */ - public function testUpdateProduct() - { - $this->assertTrue($this->_model->updateProduct(6, 1, 2)); - $this->assertEquals( - array(array( - 'product_id' => 1, - 'type' => 'simple', - 'set' => 4, - 'sku' => 'simple', - 'position' => '2', - )), - $this->_model->assignedProducts(6) - ); - } - - /** - * @depends testAssignProduct - */ - public function testRemoveProduct() - { - $this->assertNotEmpty($this->_model->assignedProducts(6)); - $this->assertTrue($this->_model->removeProduct(6, 1)); - $this->assertEmpty($this->_model->assignedProducts(6)); - } -} diff --git a/dev/tests/integration/testsuite/Mage/Catalog/Model/Category/Attribute/ApiTest.php b/dev/tests/integration/testsuite/Mage/Catalog/Model/Category/Attribute/ApiTest.php deleted file mode 100644 index 519e25ac13725f7ab85c777be6f97d628404292e..0000000000000000000000000000000000000000 --- a/dev/tests/integration/testsuite/Mage/Catalog/Model/Category/Attribute/ApiTest.php +++ /dev/null @@ -1,104 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Magento - * @package Magento_Catalog - * @subpackage integration_tests - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Test class for Mage_Catalog_Model_Category_Attribute_Api. - */ -class Mage_Catalog_Model_Category_Attribute_ApiTest extends PHPUnit_Framework_TestCase -{ - /** - * @var Mage_Catalog_Model_Category_Attribute_Api - */ - protected $_model; - - protected function setUp() - { - $this->_model = Mage::getModel('Mage_Catalog_Model_Category_Attribute_Api'); - } - - protected function tearDown() - { - $this->_model = null; - } - - public function testItems() - { - $attributes = $this->_model->items(); - $this->assertNotEmpty($attributes); - $attribute = array_shift($attributes); - $this->assertContains('attribute_id', array_keys($attribute)); - $this->assertContains('code', array_keys($attribute)); - } - - /** - * Internal assert that validate options structure - * - * @param array $options - */ - protected function _assertOptionsStructure(array $options) - { - $first = current($options); - $this->assertArrayHasKey('value', $first); - $this->assertArrayHasKey('label', $first); - } - - public function testLayoutOptions() - { - $options = $this->_model->options('page_layout'); - $this->assertNotEmpty($options); - $this->_assertOptionsStructure($options); - } - - public function testModeOptions() - { - $options = $this->_model->options('display_mode'); - $this->assertNotEmpty($options); - $this->_assertOptionsStructure($options); - } - - public function testPageOptions() - { - $options = $this->_model->options('landing_page'); - $this->assertNotEmpty($options); - $this->_assertOptionsStructure($options); - } - - public function testSortByOptions() - { - $options = $this->_model->options('available_sort_by'); - $this->assertNotEmpty($options); - $this->_assertOptionsStructure($options); - } - - /** - * @expectedException Mage_Api_Exception - */ - public function testFault() - { - $this->_model->options('not_exists'); - } -} diff --git a/dev/tests/integration/testsuite/Mage/Catalog/Model/Layer/Filter/ItemTest.php b/dev/tests/integration/testsuite/Mage/Catalog/Model/Layer/Filter/ItemTest.php index 8e17098b5bcda22df20063c271dd0f97a10e8727..b6a34e0389bd9459006632f69f3a8cd0b534ec59 100644 --- a/dev/tests/integration/testsuite/Mage/Catalog/Model/Layer/Filter/ItemTest.php +++ b/dev/tests/integration/testsuite/Mage/Catalog/Model/Layer/Filter/ItemTest.php @@ -69,13 +69,11 @@ class Mage_Catalog_Model_Layer_Filter_ItemTest extends PHPUnit_Framework_TestCas public function testGetUrl() { - Mage::getModel( + $action = Mage::getModel( 'Mage_Core_Controller_Front_Action', array('request' => new Magento_Test_Request(), 'response' => new Magento_Test_Response()) ); - /* - * Mage::app()->getFrontController()->setAction($action); // done in action's constructor - */ + Mage::app()->getFrontController()->setAction($action); // done in action's constructor $this->assertStringEndsWith('/?cat%5B0%5D=valuePart1&cat%5B1%5D=valuePart2', $this->_model->getUrl()); } diff --git a/dev/tests/integration/testsuite/Mage/Catalog/Model/Product/Attribute/ApiTest.php b/dev/tests/integration/testsuite/Mage/Catalog/Model/Product/Attribute/ApiTest.php deleted file mode 100644 index 5fbf49baf1def685a8ad0a15609a16ef58797840..0000000000000000000000000000000000000000 --- a/dev/tests/integration/testsuite/Mage/Catalog/Model/Product/Attribute/ApiTest.php +++ /dev/null @@ -1,80 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Magento - * @package Magento_Catalog - * @subpackage integration_tests - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Test class for Mage_Catalog_Model_Product_Attribute_Api. - */ -class Mage_Catalog_Model_Product_Attribute_ApiTest extends PHPUnit_Framework_TestCase -{ - /** - * @var Mage_Catalog_Model_Product_Attribute_Api - */ - protected $_model; - - protected function setUp() - { - $this->_model = Mage::getModel('Mage_Catalog_Model_Product_Attribute_Api'); - } - - protected function tearDown() - { - $this->_model = null; - } - - public function testItems() - { - $items = $this->_model->items(4); /* default product attribute set after installation */ - $this->assertInternalType('array', $items); - $element = current($items); - $this->assertArrayHasKey('attribute_id', $element); - $this->assertArrayHasKey('code', $element); - $this->assertArrayHasKey('type', $element); - $this->assertArrayHasKey('required', $element); - $this->assertArrayHasKey('scope', $element); - foreach ($items as $item) { - if ($item['code'] == 'status') { - return $item['attribute_id']; - } - } - return false; - } - - /** - * @depends testItems - */ - public function testOptions($attributeId) - { - if (!$attributeId) { - $this->fail('Wromg attribute id'); - } - $options = $this->_model->options($attributeId); - $this->assertInternalType('array', $options); - $element = current($options); - $this->assertArrayHasKey('value', $element); - $this->assertArrayHasKey('label', $element); - } -} diff --git a/dev/tests/integration/testsuite/Mage/Catalog/Model/Product/Attribute/Media/ApiTest.php b/dev/tests/integration/testsuite/Mage/Catalog/Model/Product/Attribute/Media/ApiTest.php deleted file mode 100644 index 3e3943f5938fdad4897080e6d436a673fb7ea8a3..0000000000000000000000000000000000000000 --- a/dev/tests/integration/testsuite/Mage/Catalog/Model/Product/Attribute/Media/ApiTest.php +++ /dev/null @@ -1,175 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Magento - * @package Magento_Catalog - * @subpackage integration_tests - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Test class for Mage_Catalog_Model_Product_Attribute_Media_Api. - * - * @magentoDataFixture Mage/Catalog/_files/product_simple.php - * @magentoDataFixture productMediaFixture - */ -class Mage_Catalog_Model_Product_Attribute_Media_ApiTest extends PHPUnit_Framework_TestCase -{ - /** - * @var Mage_Catalog_Model_Product_Attribute_Media_Api - */ - protected $_model; - - /** - * @var string - */ - protected static $_fixtureDir; - - /** - * @var string - */ - protected static $_mediaTmpDir; - - protected function setUp() - { - $this->_model = Mage::getModel('Mage_Catalog_Model_Product_Attribute_Media_Api'); - } - - protected function tearDown() - { - $this->_model = null; - } - - public static function setUpBeforeClass() - { - self::$_fixtureDir = realpath(__DIR__ . '/../../../../_files'); - self::$_mediaTmpDir = Mage::getSingleton('Mage_Catalog_Model_Product_Media_Config')->getBaseTmpMediaPath(); - mkdir(self::$_mediaTmpDir . "/m/a", 0777, true); - copy(self::$_fixtureDir . '/magento_image.jpg', self::$_mediaTmpDir . '/m/a/magento_image.jpg'); - } - - public static function tearDownAfterClass() - { - Varien_Io_File::rmdirRecursive(self::$_mediaTmpDir); - /** @var $config Mage_Catalog_Model_Product_Media_Config */ - $config = Mage::getSingleton('Mage_Catalog_Model_Product_Media_Config'); - Varien_Io_File::rmdirRecursive($config->getBaseMediaPath()); - } - - public static function productMediaFixture() - { - /** @var $product Mage_Catalog_Model_Product */ - $product = Mage::getModel('Mage_Catalog_Model_Product'); - $product->load(1); - $product->setTierPrice(array()); - $product->setData('media_gallery', array('images' => array(array('file' => '/m/a/magento_image.jpg',),))); - $product->save(); - } - - /** - * @covers Mage_Catalog_Model_Product_Attribute_Media_Api::items - * @covers Mage_Catalog_Model_Product_Attribute_Media_Api::info - */ - public function testItemsAndInfo() - { - $items = $this->_model->items(1); - $this->assertNotEmpty($items); - $this->assertEquals(1, count($items)); - $item = current($items); - $this->assertArrayHasKey('file', $item); - $this->assertArrayHasKey('label', $item);; - $this->assertArrayHasKey('url', $item); - - $info = $this->_model->info(1, $item['file']); - $this->assertArrayHasKey('file', $info); - $this->assertArrayHasKey('label', $info);; - $this->assertArrayHasKey('url', $info); - return $item['file']; - } - - /** - * @depends testItemsAndInfo - */ - public function testCreate() - { - $data = array( - 'file' => array( - 'mime' => 'image/jpeg', - 'content' => base64_encode(file_get_contents(self::$_fixtureDir.'/magento_small_image.jpg')) - ) - ); - $this->_model->create(1, $data); - $items = $this->_model->items(1); - $this->assertEquals(2, count($items)); - } - - public function createFaultDataProvider() - { - return array( - array('floor' => 'ceiling'), - array('file' => array('mime' => 'test')), - array('file' => array('mime' => 'image/jpeg', 'content' => 'not valid')) - ); - } - - /** - * @dataProvider createFaultDataProvider - * @expectedException Mage_Api_Exception - */ - public function testCreateFault($data) - { - $this->_model->create(1, $data); - } - - /** - * @depends testItemsAndInfo - */ - public function testUpdate($file) - { - $data = array( - 'file' => array( - 'mime' => 'image/jpeg', - 'content' => base64_encode(file_get_contents(self::$_fixtureDir.'/magento_small_image.jpg')) - ) - ); - $this->assertTrue($this->_model->update(1, $file, $data)); - } - - /** - * @depends testItemsAndInfo - * @expectedException Mage_Api_Exception - */ - public function testRemove($file) - { - $this->assertTrue($this->_model->remove(1, $file)); - $this->_model->info(1, $file); - } - - public function testTypes() - { - $types = $this->_model->types(4); - $this->assertNotEmpty($types); - $this->assertInternalType('array', $types); - $type = current($types); - $this->assertArrayHasKey('code', $type); - $this->assertArrayHasKey('scope', $type); - } -} diff --git a/dev/tests/integration/testsuite/Mage/Catalog/Model/Product/Attribute/Tierprice/Api/V2Test.php b/dev/tests/integration/testsuite/Mage/Catalog/Model/Product/Attribute/Tierprice/Api/V2Test.php deleted file mode 100644 index 570ca67e18d30998d0ccf65f904f3ba40b57fb5f..0000000000000000000000000000000000000000 --- a/dev/tests/integration/testsuite/Mage/Catalog/Model/Product/Attribute/Tierprice/Api/V2Test.php +++ /dev/null @@ -1,84 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Magento - * @package Magento_Catalog - * @subpackage integration_tests - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Test class for Mage_Catalog_Model_Product_Attribute_Tierprice_Api_V2. - */ -class Mage_Catalog_Model_Product_Attribute_Tierprice_Api_V2Test extends PHPUnit_Framework_TestCase -{ - /** - * @var Mage_Catalog_Model_Product_Attribute_Tierprice_Api_V2 - */ - protected $_model; - - protected function setUp() - { - $this->_model = Mage::getModel('Mage_Catalog_Model_Product_Attribute_Tierprice_Api_V2'); - } - - protected function tearDown() - { - $this->_model = null; - } - - /** - * @expectedException Mage_Api_Exception - */ - public function testPrepareTierPricesInvalidData() - { - $product = Mage::getModel('Mage_Catalog_Model_Product'); - $this->_model->prepareTierPrices($product, array(1)); - } - - public function testPrepareTierPricesInvalidWebsite() - { - $product = Mage::getModel('Mage_Catalog_Model_Product'); - $data = $this->_model->prepareTierPrices( - $product, - array((object) array('qty' => 3, 'price' => 8, 'website' => 100)) - ); - $this->assertEquals( - array(array('website_id' => 0, 'cust_group' => 32000, 'price_qty' => 3, 'price' => 8)), - $data - ); - } - - public function testPrepareTierPrices() - { - $product = Mage::getModel('Mage_Catalog_Model_Product'); - - $this->assertNull($this->_model->prepareTierPrices($product)); - - $data = $this->_model->prepareTierPrices($product, - array((object) array('qty' => 3, 'price' => 8)) - ); - $this->assertEquals( - array(array('website_id' => 0, 'cust_group' => 32000, 'price_qty' => 3, 'price' => 8)), - $data - ); - } -} diff --git a/dev/tests/integration/testsuite/Mage/Catalog/Model/Product/Attribute/Tierprice/ApiTest.php b/dev/tests/integration/testsuite/Mage/Catalog/Model/Product/Attribute/Tierprice/ApiTest.php deleted file mode 100644 index 08027cb69dad6b384785e34dd0fbd1da344f4a8e..0000000000000000000000000000000000000000 --- a/dev/tests/integration/testsuite/Mage/Catalog/Model/Product/Attribute/Tierprice/ApiTest.php +++ /dev/null @@ -1,103 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Magento - * @package Magento_Catalog - * @subpackage integration_tests - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Test class for Mage_Catalog_Model_Product_Attribute_Tierprice_Api - * - * @magentoDataFixture Mage/Catalog/_files/product_simple.php - */ -class Mage_Catalog_Model_Product_Attribute_Tierprice_ApiTest extends PHPUnit_Framework_TestCase -{ - /** - * @var Mage_Catalog_Model_Product_Attribute_Tierprice_Api - */ - protected $_model; - - protected function setUp() - { - $this->_model = Mage::getModel('Mage_Catalog_Model_Product_Attribute_Tierprice_Api'); - } - - protected function tearDown() - { - $this->_model = null; - } - - public function testInfo() - { - $info = $this->_model->info(1); - $this->assertInternalType('array', $info); - $this->assertEquals(2, count($info)); - $element = current($info); - $this->assertArrayHasKey('customer_group_id', $element); - $this->assertArrayHasKey('website', $element); - $this->assertArrayHasKey('qty', $element); - $this->assertArrayHasKey('price', $element); - } - - public function testUpdate() - { - Mage::app()->setCurrentStore(Mage::app()->getStore(Mage_Core_Model_App::ADMIN_STORE_ID)); - $this->_model->update(1, array(array('qty' => 3, 'price' => 8))); - $info = $this->_model->info(1); - $this->assertEquals(1, count($info)); - } - - /** - * @expectedException Mage_Api_Exception - */ - public function testPrepareTierPricesInvalidData() - { - $product = Mage::getModel('Mage_Catalog_Model_Product'); - $this->_model->prepareTierPrices($product, array(1)); - } - - public function testPrepareTierPricesInvalidWebsite() - { - $product = Mage::getModel('Mage_Catalog_Model_Product'); - $data = $this->_model->prepareTierPrices($product, array(array('qty' => 3, 'price' => 8, 'website' => 100))); - $this->assertEquals( - array(array('website_id' => 0, 'cust_group' => 32000, 'price_qty' => 3, 'price' => 8)), - $data - ); - } - - public function testPrepareTierPrices() - { - $product = Mage::getModel('Mage_Catalog_Model_Product'); - - $this->assertNull($this->_model->prepareTierPrices($product)); - - $data = $this->_model->prepareTierPrices($product, - array(array('qty' => 3, 'price' => 8)) - ); - $this->assertEquals( - array(array('website_id' => 0, 'cust_group' => 32000, 'price_qty' => 3, 'price' => 8)), - $data - ); - } -} diff --git a/dev/tests/integration/testsuite/Mage/Core/Controller/RequestHttpTest.php b/dev/tests/integration/testsuite/Mage/Core/Controller/RequestHttpTest.php index 038c2dc5e02ed5acb80f1e4d5e0e0d38d2400727..90d2d5e137ef430592a2d5f94422eee514121834 100644 --- a/dev/tests/integration/testsuite/Mage/Core/Controller/RequestHttpTest.php +++ b/dev/tests/integration/testsuite/Mage/Core/Controller/RequestHttpTest.php @@ -93,12 +93,18 @@ class Mage_Core_Controller_RequestHttpTest extends PHPUnit_Framework_TestCase public function testIsDirectAccessFrontendName() { $this->assertFalse($this->_model->isDirectAccessFrontendName('test')); - $this->assertTrue($this->_model->isDirectAccessFrontendName('api')); + $this->assertFalse( + $this->_model->isDirectAccessFrontendName('api'), + "Mage_Core_Controller_RequestHttp should not be used in API area." + ); } public function testGetDirectFrontNames() { - $this->assertContains('api', array_keys($this->_model->getDirectFrontNames())); + $this->assertEmpty( + $this->_model->getDirectFrontNames(), + "After API module removal there should not be areas with direct front name." + ); } public function testGetOriginalRequest() diff --git a/dev/tests/integration/testsuite/Mage/Core/Controller/Varien/ActionTest.php b/dev/tests/integration/testsuite/Mage/Core/Controller/Varien/ActionTest.php index af182bb49819c2d9778c4247c4ab172413b6ab6a..985a14330d1d98fb2f33a1ae9ceb6d11ad9b6d35 100644 --- a/dev/tests/integration/testsuite/Mage/Core/Controller/Varien/ActionTest.php +++ b/dev/tests/integration/testsuite/Mage/Core/Controller/Varien/ActionTest.php @@ -314,7 +314,6 @@ class Mage_Core_Controller_Varien_ActionTest extends PHPUnit_Framework_TestCase 'install' => array('Mage_Install_Controller_Action', 'install', 'default', 'default/basic'), 'frontend' => array('Mage_Core_Controller_Front_Action', 'frontend', 'default', 'default/demo'), 'backend' => array('Mage_Adminhtml_Controller_Action', 'adminhtml', 'admin', 'default/basic'), - 'api' => array('Mage_Api_Controller_Action', 'adminhtml', 'admin', ''), ); } diff --git a/dev/tests/integration/testsuite/Mage/Core/Model/ConfigTest.php b/dev/tests/integration/testsuite/Mage/Core/Model/ConfigTest.php index 07e4cf6a27d9bef4845834010f8c1390885ca657..a5a6442291c522c32406adf0f5428371aeea819c 100644 --- a/dev/tests/integration/testsuite/Mage/Core/Model/ConfigTest.php +++ b/dev/tests/integration/testsuite/Mage/Core/Model/ConfigTest.php @@ -1,5 +1,7 @@ <?php /** + * Integration test for Mage_Core_Model_Config + * * Magento * * NOTICE OF LICENSE @@ -18,9 +20,6 @@ * versions in the future. If you wish to customize Magento for your * needs please refer to http://www.magentocommerce.com for more information. * - * @category Magento - * @package Mage_Core - * @subpackage integration_tests * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ diff --git a/dev/tests/integration/testsuite/Mage/Core/Model/Resource/Db/ProfilerTest.php b/dev/tests/integration/testsuite/Mage/Core/Model/Resource/Db/ProfilerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..45a31a05ac40072131e5cef74363a805db59ac7c --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Core/Model/Resource/Db/ProfilerTest.php @@ -0,0 +1,151 @@ +<?php +/** + * Test for Mage_Core_Model_Resource_Db_Profiler + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Core_Model_Resource_Db_ProfilerTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Core_Model_Resource + */ + protected $_model; + + /** + * @var string + */ + protected static $_testResourceName = 'testtest_0000_setup'; + + public static function setUpBeforeClass() + { + self::$_testResourceName = 'testtest_' . mt_rand(1000, 9999) . '_setup'; + + Magento_Profiler::enable(); + } + + public static function tearDownAfterClass() + { + Magento_Profiler::disable(); + } + + public function setUp() + { + $this->_model = Mage::getModel('Mage_Core_Model_Resource'); + } + + /** + * @return Varien_Simplexml_Element + */ + protected function _getConnectionReadConfig() + { + $connReadConfig = Mage::getConfig()->getResourceConnectionConfig('core_read'); + $profilerConfig = $connReadConfig->addChild('profiler'); + $profilerConfig->addChild('class', 'Mage_Core_Model_Resource_Db_Profiler'); + $profilerConfig->addChild('enabled', 'true'); + + return $connReadConfig; + } + + /** + * Init profiler during creation of DB connect + * + * @param string $selectQuery + * @param int $queryType + * @dataProvider profileQueryDataProvider + */ + public function testProfilerInit($selectQuery, $queryType) + { + $connReadConfig = $this->_getConnectionReadConfig(); + /** @var Magento_Test_Db_Adapter_Mysql $connection */ + $connection = $this->_model->getConnection('core_read'); + + /** @var Mage_Core_Model_Resource $resource */ + $resource = Mage::getSingleton('Mage_Core_Model_Resource'); + $testTableName = $resource->getTableName('core_resource'); + $selectQuery = sprintf($selectQuery, $testTableName); + + $result = $connection->query($selectQuery); + if ($queryType == Zend_Db_Profiler::SELECT) { + $result->fetchAll(); + } + + /** @var Mage_Core_Model_Resource_Db_Profiler $profiler */ + $profiler = $connection->getProfiler(); + $this->assertInstanceOf('Mage_Core_Model_Resource_Db_Profiler', $profiler); + $this->assertAttributeEquals((string)$connReadConfig->type, '_type', $profiler); + + $queryProfiles = $profiler->getQueryProfiles($queryType); + $this->assertCount(1, $queryProfiles); + + /** @var Zend_Db_Profiler_Query $queryProfile */ + $queryProfile = end($queryProfiles); + $this->assertInstanceOf('Zend_Db_Profiler_Query', $queryProfile); + + $this->assertEquals($selectQuery, $queryProfile->getQuery()); + } + + /** + * @return array + */ + public function profileQueryDataProvider() + { + return array( + array("SELECT * FROM %s", Varien_Db_Profiler::SELECT), + array("INSERT INTO %s (code, version, data_version) " + . "VALUES ('" . self::$_testResourceName . "', '1.1', '1.1')", Varien_Db_Profiler::INSERT), + array("UPDATE %s SET version = '1.2' WHERE code = '" . self::$_testResourceName . "'", + Varien_Db_Profiler::UPDATE), + array("DELETE FROM %s WHERE code = '" . self::$_testResourceName . "'", + Varien_Db_Profiler::DELETE), + ); + } + + /** + * Test correct event starting and stopping in magento profile during SQL query fail + */ + public function testProfilerDuringSqlException() + { + /** @var Zend_Db_Adapter_Pdo_Abstract $connection */ + $connection = $this->_model->getConnection('core_read'); + + try { + $connection->query('SELECT * FROM unknown_table'); + } catch (Zend_Db_Statement_Exception $exception) { + } + + if (!isset($exception)) { + $this->fail("Expected exception didn't thrown!"); + } + + /** @var Mage_Core_Model_Resource $resource */ + $resource = Mage::getSingleton('Mage_Core_Model_Resource'); + $testTableName = $resource->getTableName('core_resource'); + $connection->query('SELECT * FROM ' . $testTableName); + + /** @var Mage_Core_Model_Resource_Db_Profiler $profiler */ + $profiler = $connection->getProfiler(); + $this->assertInstanceOf('Mage_Core_Model_Resource_Db_Profiler', $profiler); + + $queryProfiles = $profiler->getQueryProfiles(Varien_Db_Profiler::SELECT); + $this->assertCount(2, $queryProfiles); + } +} diff --git a/dev/tests/integration/testsuite/Mage/Core/Model/Resource/Store/CollectionTest.php b/dev/tests/integration/testsuite/Mage/Core/Model/Resource/Store/CollectionTest.php index 6eb57751813e46e798031d13c72c91bfb670698e..5d06efa250aee16209896e1b51faee7fc8264361 100644 --- a/dev/tests/integration/testsuite/Mage/Core/Model/Resource/Store/CollectionTest.php +++ b/dev/tests/integration/testsuite/Mage/Core/Model/Resource/Store/CollectionTest.php @@ -56,7 +56,9 @@ class Mage_Core_Model_Resource_Store_CollectionTest extends PHPUnit_Framework_Te public function testSetWithoutDefaultFilter() { $this->_collection->setWithoutDefaultFilter(); - $this->assertContains('store_id > 0', (string)$this->_collection->getSelect()); + $quote = $this->_getQuoteIdentifierSymbol(); + + $this->assertContains("{$quote}store_id{$quote} > 0", (string)$this->_collection->getSelect()); } /** @@ -68,16 +70,38 @@ class Mage_Core_Model_Resource_Store_CollectionTest extends PHPUnit_Framework_Te public function testAddFilters() { $this->_collection->addGroupFilter(1); - $this->assertContains('group_id IN', (string)$this->_collection->getSelect(), 'Group filter'); + $quote = $this->_getQuoteIdentifierSymbol(); + $this->assertContains("{$quote}group_id{$quote} IN", (string)$this->_collection->getSelect(), 'Group filter'); $this->_collection->addIdFilter(1); - $this->assertContains('store_id IN', (string)$this->_collection->getSelect(), 'Id filter'); + $this->assertContains("{$quote}store_id{$quote} IN", (string)$this->_collection->getSelect(), 'Id filter'); $this->_collection->addWebsiteFilter(1); - $this->assertContains('website_id IN', (string)$this->_collection->getSelect(), 'Website filter'); + $this->assertContains( + "{$quote}website_id{$quote} IN", + (string)$this->_collection->getSelect(), + 'Website filter' + ); $this->_collection->addCategoryFilter(1); - $this->assertContains('root_category_id IN', (string)$this->_collection->getSelect(), 'Category filter'); + $this->assertContains( + "{$quote}root_category_id{$quote} IN", + (string)$this->_collection->getSelect(), + 'Category filter' + ); + } + + /** + * Get quote symbol from adapter. + * + * @return string + */ + protected function _getQuoteIdentifierSymbol() + { + /** @var Zend_Db_Adapter_Abstract $adapter */ + $adapter = $this->_collection->getConnection(); + $quote = $adapter->getQuoteIdentifierSymbol(); + return $quote; } public function testToOptionArrayHash() diff --git a/dev/tests/integration/testsuite/Mage/Core/Model/ResourceTest.php b/dev/tests/integration/testsuite/Mage/Core/Model/ResourceTest.php index 72039f6ec0881ba8fc53a7946fff7691f699cb81..b8381bc0162998128914ec3c71376c3bc294ca67 100644 --- a/dev/tests/integration/testsuite/Mage/Core/Model/ResourceTest.php +++ b/dev/tests/integration/testsuite/Mage/Core/Model/ResourceTest.php @@ -1,5 +1,7 @@ <?php /** + * Test for Mage_Core_Model_Resource + * * Magento * * NOTICE OF LICENSE @@ -18,13 +20,9 @@ * versions in the future. If you wish to customize Magento for your * needs please refer to http://www.magentocommerce.com for more information. * - * @category Magento - * @package Mage_Core - * @subpackage integration_tests * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ - class Mage_Core_Model_ResourceTest extends PHPUnit_Framework_TestCase { /** @@ -56,4 +54,25 @@ class Mage_Core_Model_ResourceTest extends PHPUnit_Framework_TestCase $this->assertContains($tableSuffix, $tableName); $this->assertContains($tableNameOrig, $tableName); } + + /** + * Init profiler during creation of DB connect + */ + public function testProfilerInit() + { + $connReadConfig = Mage::getConfig()->getResourceConnectionConfig('core_read'); + $profilerConfig = $connReadConfig->addChild('profiler'); + $profilerConfig->addChild('class', 'Mage_Core_Model_Resource_Db_Profiler'); + $profilerConfig->addChild('enabled', 'true'); + + /** @var Zend_Db_Adapter_Abstract $connection */ + $connection = $this->_model->getConnection('core_read'); + /** @var Mage_Core_Model_Resource_Db_Profiler $profiler */ + $profiler = $connection->getProfiler(); + + $this->assertInstanceOf('Mage_Core_Model_Resource_Db_Profiler', $profiler); + $this->assertTrue($profiler->getEnabled()); + $this->assertAttributeEquals((string)$connReadConfig->host, '_host', $profiler); + $this->assertAttributeEquals((string)$connReadConfig->type, '_type', $profiler); + } } diff --git a/dev/tests/integration/testsuite/Mage/Core/Model/UrlTest.php b/dev/tests/integration/testsuite/Mage/Core/Model/UrlTest.php index 7f0f09801d593c3e5de1378f9fa899a34d60bc11..497b97d73ef40bbde88e3bc7055d215b95469fe3 100644 --- a/dev/tests/integration/testsuite/Mage/Core/Model/UrlTest.php +++ b/dev/tests/integration/testsuite/Mage/Core/Model/UrlTest.php @@ -108,13 +108,13 @@ class Mage_Core_Model_UrlTest extends PHPUnit_Framework_TestCase /** * @magentoAppIsolation enabled */ - public function testGetSecure() + public function testIsSecure() { - $this->assertFalse($this->_model->getSecure()); + $this->assertFalse($this->_model->isSecure()); $this->_model->setSecureIsForced(1); - $this->assertTrue(is_bool($this->_model->getSecure())); + $this->assertTrue(is_bool($this->_model->isSecure())); Mage::app()->getStore()->setId(Mage_Core_Model_App::ADMIN_STORE_ID); - $this->assertFalse($this->_model->getSecure()); + $this->assertFalse($this->_model->isSecure()); } public function testSetGetStore() diff --git a/dev/tests/integration/testsuite/Mage/Core/Model/Validator/FactoryTest.php b/dev/tests/integration/testsuite/Mage/Core/Model/Validator/FactoryTest.php new file mode 100644 index 0000000000000000000000000000000000000000..7bc66615bfac967bedfa2df92feb624d72c40eef --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Core/Model/Validator/FactoryTest.php @@ -0,0 +1,49 @@ +<?php +/** + * Integration test for Mage_Core_Model_Validator_Factory + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Core_Model_Validator_FactoryTest extends PHPUnit_Framework_TestCase +{ + /** + * Test creation of validator config + * + * @magentoAppIsolation enabled + */ + public function testGetValidatorConfig() + { + $objectManager = Mage::getObjectManager(); + /** @var Mage_Core_Model_Validator_Factory $factory */ + $factory = $objectManager->get('Mage_Core_Model_Validator_Factory'); + $this->assertInstanceOf('Magento_Validator_Config', $factory->getValidatorConfig()); + // Check that default translator was set + $translator = Magento_Validator_ValidatorAbstract::getDefaultTranslator(); + $this->assertInstanceOf('Magento_Translate_AdapterInterface', $translator); + $this->assertEquals('Message', $translator->__('Message')); + $this->assertEquals('Message', $translator->translate('Message')); + $this->assertEquals( + 'Message with "placeholder one" and "placeholder two"', + $translator->__('Message with "%s" and "%s"', 'placeholder one', 'placeholder two') + ); + } +} diff --git a/dev/tests/integration/testsuite/Mage/Core/_files/etc/config.xml b/dev/tests/integration/testsuite/Mage/Core/_files/etc/config.xml index c62baf7587b1cf23cf418ae44338e9eecfc2dcf5..9b6e69dedccc706a41e3cb8f79081c1f14106305 100644 --- a/dev/tests/integration/testsuite/Mage/Core/_files/etc/config.xml +++ b/dev/tests/integration/testsuite/Mage/Core/_files/etc/config.xml @@ -60,14 +60,6 @@ </test_router> </routers> </test_area3> - <test_area4> - <base_controller>Mage_Core_Controller_Varien_Action</base_controller> - <routers> - </routers> - </test_area4> - <test_area5> - <base_controller>Mage_Core_Controller_Varien_Action</base_controller> - </test_area5> </areas> </global> <test_area1> diff --git a/dev/tests/integration/testsuite/Mage/Customer/Service/CustomerTest.php b/dev/tests/integration/testsuite/Mage/Customer/Service/CustomerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..f486e4939654f02d79e7c8ceddf3f4c2329a33e2 --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Customer/Service/CustomerTest.php @@ -0,0 +1,563 @@ +<?php +/** + * Integration test for service layer Mage_Customer_Service_Customer + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Customer_Service_CustomerTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Customer_Service_Customer + */ + protected $_model; + + /** + * @var Magento_ObjectManager + */ + protected $_objectManager = null; + + /** + * @var Mage_Customer_Model_Customer + */ + protected $_createdCustomer; + + /** + * @var Mage_Customer_Model_Customer_Factory + */ + protected $_customerFactory = null; + + protected function setUp() + { + $this->_objectManager = Mage::getObjectManager(); + $this->_customerFactory = new Mage_Customer_Model_Customer_Factory($this->_objectManager); + $this->_model = $this->_objectManager->create('Mage_Customer_Service_Customer'); + } + + protected function tearDown() + { + $previousStoreId = Mage::app()->getStore(); + Mage::app()->setCurrentStore(Mage::app()->getStore(Mage_Core_Model_App::ADMIN_STORE_ID)); + if ($this->_createdCustomer && $this->_createdCustomer->getId() > 0) { + $this->_createdCustomer->getAddressesCollection()->delete(); + $this->_createdCustomer->delete(); + } + Mage::app()->setCurrentStore($previousStoreId); + + $this->_model = null; + } + + /** + * @param array $customerData + * @dataProvider createDataProvider + */ + public function testCreate($customerData) + { + $this->_createdCustomer = $this->_model->create($customerData); + $this->assertInstanceOf('Mage_Customer_Model_Customer', $this->_createdCustomer); + $this->assertNotEmpty($this->_createdCustomer->getId()); + + $loadedCustomer = $this->_customerFactory->create() + ->load($this->_createdCustomer->getId()); + if (array_key_exists('sendemail', $customerData)) { + unset($customerData['sendemail']); + } + $expectedData = $customerData; + $actualData = $loadedCustomer->toArray(array_keys($customerData)); + if (isset($expectedData['password'])) { + // TODO Add assertions for password if needed + unset($expectedData['password'], $actualData['password']); + } + $this->assertEquals($expectedData, $actualData); + } + + /** + * @return array + */ + public function createDataProvider() + { + return array( + 'Valid data' => array(array( + 'website_id' => 1, + 'sendemail' => true, + 'group_id' => 1, + 'disable_auto_group_change' => 0, + 'prefix' => 'Prefix', + 'firstname' => 'Service', + 'middlename' => 'Middlename', + 'lastname' => 'CreateValid', + 'suffix' => 'Suffix', + 'email' => 'test' . mt_rand(1000, 9999) . '@mail.com', + 'dob' => date('Y-m-d H:i:s'), + 'taxvat' => null, + 'gender' => 1, + 'password' => '123123q', + 'default_billing' => null, + 'default_shipping' => null, + 'store_id' => Mage_Core_Model_App::ADMIN_STORE_ID + )), + 'Mandatory data' => array(array( + 'firstname' => 'SomeName', + 'lastname' => 'CreateMandatory', + 'email' => 'test' . mt_rand(1000, 9999) . '@mail.com', + )), + ); + } + + /** + * @param array $customerData + * @param string $exceptionName + * @param string $exceptionText + * @dataProvider createExceptionsDataProvider + */ + public function testCreateExceptions($customerData, $exceptionName, $exceptionText = '') + { + $this->setExpectedException($exceptionName, $exceptionText); + $this->_createdCustomer = $this->_model->create($customerData); + } + + /** + * @return array + */ + public function createExceptionsDataProvider() + { + return array( + 'First name is required field' => array(array( + 'website_id' => 0, + 'group_id' => 1, + 'disable_auto_group_change' => 0, + 'prefix' => null, + 'firstname' => null, + 'lastname' => 'ServiceTestCreateExceptionFNR', + 'suffix' => null, + 'email' => 'test' . mt_rand(1000, 9999) . '@mail.com', + 'password' => '123123q', + 'store_id' => Mage_Core_Model_App::ADMIN_STORE_ID + ), 'Magento_Validator_Exception'), + 'Invalid email' => array(array( + 'website_id' => 0, + 'group_id' => 1, + 'disable_auto_group_change' => 0, + 'prefix' => null, + 'firstname' => 'ServiceTestCreate', + 'lastname' => 'ExceptionInvalidEmail', + 'suffix' => null, + 'email' => '111@111', + 'password' => '123123q', + 'store_id' => Mage_Core_Model_App::ADMIN_STORE_ID + ), 'Magento_Validator_Exception'), + 'Invalid password' => array(array( + 'website_id' => 0, + 'group_id' => 1, + 'disable_auto_group_change' => 0, + 'prefix' => null, + 'firstname' => 'ServiceTestCreate', + 'lastname' => 'ExceptionPassword', + 'suffix' => null, + 'email' => 'test' . mt_rand(1000, 9999) . '@mail.com', + 'password' => '123', + 'store_id' => Mage_Core_Model_App::ADMIN_STORE_ID + ), 'Mage_Eav_Model_Entity_Attribute_Exception', 'The password must have at least 6 characters.') + ); + } + + /** + * @param array $addressesData + * @dataProvider createWithAddressesDataProvider + */ + public function testCreateWithAddresses($addressesData) + { + $customerData = array( + 'firstname' => 'ServiceTest', + 'lastname' => 'CreateWithAddress', + 'email' => 'test' . mt_rand(1000, 9999) . '@mail.com', + ); + + $this->_createdCustomer = $this->_model->create($customerData, $addressesData); + $this->assertCount(count($addressesData), $this->_createdCustomer->getAddresses()); + + /** @var Mage_Customer_Model_Customer $loadedCustomer */ + $loadedCustomer = $this->_customerFactory->create() + ->load($this->_createdCustomer->getId()); + + $createdData = array(); + /** @var Mage_Customer_Model_Address $address */ + foreach ($loadedCustomer->getAddresses() as $address) { + $addressData = current($addressesData); + $createdData[] = $address->toArray(array_keys($addressData)); + next($addressesData); + } + + $this->assertEquals( + $this->_getSortedByKey($createdData, 'firstname'), + $this->_getSortedByKey($addressesData, 'firstname') + ); + } + + /** + * @param array $data + * @param string $sortKey + * @return array + */ + protected function _getSortedByKey($data, $sortKey) + { + $callback = function ($elementOne, $elementTwo) use ($sortKey) { + return strcmp($elementOne[$sortKey], $elementTwo[$sortKey]); + }; + usort($data, $callback); + return $data; + } + + /** + * @return array + */ + public function createWithAddressesDataProvider() + { + return array( + 'Two addresses' => array( + array( + array( + 'prefix' => 'Mrs.', + 'firstname' => 'Linda', + 'middlename' => 'G.', + 'lastname' => 'Jones', + 'suffix' => 'Suffix', + 'company' => 'Vitagee', + 'street' => "3083 Eagles Nest Drive\nHoopa", + 'country_id' => 'US', + 'region_id' => '12', // California + 'city' => 'Los Angeles', + 'postcode' => '95546', + 'fax' => '55512450056', + 'telephone' => '55512450000', + 'vat_id' => '556-70-1739', + ), + array( + 'firstname' => 'John', + 'lastname' => 'Smith', + 'street' => 'Green str, 67', + 'country_id' => 'AL', + 'city' => 'CityM', + 'postcode' => '75477', + 'telephone' => '3468676', + ) + ) + ), + 'One address' => array( + array( + array( + 'firstname' => 'John', + 'lastname' => 'Smith', + 'street' => 'Green str, 67', + 'country_id' => 'AL', + 'city' => 'CityM', + 'postcode' => '75477', + 'telephone' => '3468676', + ) + ) + ) + ); + } + + /** + * @expectedException Mage_Core_Exception + * @expectedExceptionMessage The address with the specified ID not found. + */ + public function testCreateWithInvalidAddressId() + { + $customerData = array( + 'firstname' => 'ServiceTest', + 'lastname' => 'InvalidAddress', + 'email' => 'test' . mt_rand(1000, 9999) . '@mail.com', + ); + + $addressData = array( + 'entity_id' => 'fake', + 'firstname' => 'John', + 'lastname' => 'Smith', + 'street' => 'Green str, 67', + 'country_id' => 'AL', + 'city' => 'CityM', + 'postcode' => '75477', + 'telephone' => '3468676', + ); + + $this->_createdCustomer = $this->_model->create($customerData, array($addressData)); + } + + /** + * @param array $customerData + * @magentoDataFixture Mage/Customer/_files/customer.php + * @dataProvider updateDataProvider + */ + public function testUpdate($customerData) + { + $expected = $this->_customerFactory->create() + ->load(1); + + $updatedCustomer = $this->_model->update($expected->getId(), $customerData); + $this->assertInstanceOf('Mage_Customer_Model_Customer', $updatedCustomer); + $this->assertFalse($updatedCustomer->isObjectNew()); + + $actualData = $this->_customerFactory->create() + ->load($expected->getId())->getData(); + $expectedData = array_merge($updatedCustomer->toArray(array_keys($actualData)), $customerData); + unset($expectedData['updated_at'], $actualData['updated_at']); + if (isset($expectedData['password'])) { + // TODO Add assertions for password if needed + unset($expectedData['password'], $actualData['password']); + } + $this->assertEquals($expectedData, $actualData); + } + + /** + * @return array + */ + public function updateDataProvider() + { + return array( + 'Change name' => array(array( + 'firstname' => 'SomeName2', + )), + 'Change password' => array(array( + 'password' => '111111' + )), + 'Multiple properties' => array(array( + 'disable_auto_group_change' => 0, + 'prefix' => 'Prefix', + 'firstname' => 'ServiceTest', + 'middlename' => 'Middlename', + 'lastname' => 'UpdateMultiple', + 'suffix' => 'Suffix', + 'email' => 'test' . mt_rand(1000, 9999) . '@mail.com', + 'dob' => date('Y-m-d H:i:s'), + 'gender' => 1, + 'store_id' => Mage_Core_Model_App::ADMIN_STORE_ID + )) + ); + } + + /** + * @param array $customerData + * @param string $exceptionName + * @param string $exceptionMessage + * @magentoDataFixture Mage/Customer/_files/customer.php + * @dataProvider updateExceptionsDataProvider + */ + public function testUpdateExceptions($customerData, $exceptionName, $exceptionMessage = '') + { + $this->setExpectedException($exceptionName, $exceptionMessage); + $this->_model->update(1, $customerData); + } + + /** + * @return array + */ + public function updateExceptionsDataProvider() + { + return array( + 'Invalid password' => array(array( + 'password' => '111' + ), 'Mage_Eav_Model_Entity_Attribute_Exception'), + 'Invalid name' => array(array( + 'firstname' => null + ), 'Magento_Validator_Exception'), + 'Invalid email' => array(array( + 'email' => '3434@23434' + ), 'Magento_Validator_Exception') + ); + } + + /** + * @expectedException Mage_Core_Exception + * @expectedExceptionMessage The customer with the specified ID not found. + */ + public function testUpdateInvalidCustomerId() + { + $this->_model->update(1, array('firstname' => 'Foo')); + } + + /** + * @magentoDataFixture Mage/Customer/_files/customer.php + */ + public function testAutoGeneratePassword() + { + $oldPasswordHash = $this->_customerFactory->create() + ->load(1) + ->getPasswordHash(); + $updatedCustomer = $this->_model->update(1, array( + 'autogenerate_password' => true, + )); + $this->assertNotEquals($oldPasswordHash, $updatedCustomer->getPasswordHash()); + } + + /** + * @param array $addressesData + * @dataProvider customerAddressDataProvider + * @magentoDataFixture Mage/Customer/_files/customer.php + * @magentoDataFixture Mage/Customer/_files/customer_two_addresses.php + */ + public function testCustomerAddressManipulation($addressesData) + { + /** @var Mage_Customer_Model_Customer $customer */ + $customer = $this->_customerFactory->create() + ->load(1); + $this->assertCount(2, $customer->getAddresses(), 'Not all customer addresses were created.'); + $updatedCustomer = $this->_model->update(1, array(), $addressesData); + $this->assertCount(count($addressesData), $updatedCustomer->getAddresses(), + 'Customer address was not deleted.'); + + /** @var Mage_Customer_Model_Customer $actualCustomer */ + $actualCustomer = $this->_customerFactory->create() + ->load(1); + $actualAddresses = $actualCustomer->getAddresses(); + $this->assertCount(count($addressesData), $actualAddresses, 'Customer address was not actually deleted.'); + + // Check that all addresses were updated correctly + $updatedData = array(); + /** @var Mage_Customer_Model_Address $address */ + $addressesData = $this->_getSortedByKey($addressesData, 'postcode'); + foreach ($this->_getSortedByKey($actualAddresses, 'postcode') as $address) { + $addressData = current($addressesData); + $updatedData[] = $address->toArray(array_keys($addressData)); + next($addressesData); + } + $this->assertEquals($addressesData, $updatedData, 'Customer addresses are incorrect.'); + } + + /** + * @return array + */ + public function customerAddressDataProvider() + { + return array( + 'Addresses update' => array( + array( + array('entity_id' => 1, 'postcode' => '1000001'), + array('entity_id' => 2, 'postcode' => '1000002') + ) + ), + 'First address delete' => array( + array( + array('entity_id' => 2) + ) + ), + 'First address update, second delete' => array( + array( + array('entity_id' => 1, 'city' => 'Updated city', 'postcode' => '1000001') + ) + ), + 'All addresses delete' => array( + array() + ), + 'Addresses updated and one created' => array( + array( + array('entity_id' => 1, 'postcode' => '1000001'), + array('entity_id' => 2, 'city' => 'Updated city', 'postcode' => '1000002') + ) + ), + 'Address updated, deleted and created' => array( + array( + array( + 'firstname' => 'John', + 'lastname' => 'Smith', + 'street' => 'Green str, 67', + 'country_id' => 'AL', + 'city' => 'CityM', + 'postcode' => '1000001', + 'telephone' => '3468676' + ), + array('entity_id' => 2, 'city' => 'Updated city', 'postcode' => '1000002') + ) + ) + ); + } + + /** + * Test beforeSave and afterSave callback + * + * @magentoDataFixture Mage/Customer/_files/customer.php + */ + public function testCallback() + { + $customer = $this->_customerFactory->create() + ->load(1); + $customerData = array('firstname' => 'Updated name'); + $customer->addData($customerData); + $addressData = array(array( + 'firstname' => 'John', + 'lastname' => 'Smith', + 'street' => 'Green str, 67', + 'country_id' => 'AL', + 'city' => 'CityM', + 'postcode' => '75477', + 'telephone' => '3468676', + )); + + $callbackCount = 0; + $callback = function($actualCustomer, $actualData, $actualAddresses) use ($customer, $customerData, + $addressData, &$callbackCount + ) { + $callbackCount++; + // Remove updated_at as in afterSave updated_at may be changed + $expectedCustomerData = $customer->getData(); + unset($expectedCustomerData['updated_at']); + PHPUnit_Framework_Assert::assertEquals($expectedCustomerData, + $actualCustomer->toArray(array_keys($expectedCustomerData))); + PHPUnit_Framework_Assert::assertEquals($customerData, $actualData); + PHPUnit_Framework_Assert::assertEquals($addressData, $actualAddresses); + }; + + $this->_model->setBeforeSaveCallback($callback); + $this->_model->setAfterSaveCallback($callback); + $this->_model->update(1, $customerData, $addressData); + $this->assertEquals(2, $callbackCount, 'Not all expected callbacks were called.'); + } + + /** + * @param bool $isAdminStore + * @param boolean $isConfirmed + * @dataProvider forceConfirmedDataProvider + */ + public function testCustomerSetForceConfirmed($isAdminStore, $isConfirmed) + { + $this->_model->setIsAdminStore($isAdminStore); + $customerData = array( + 'firstname' => 'ServiceTest', + 'lastname' => 'ForceConfirmed', + 'email' => 'test' . mt_rand(1000, 9999) . '@mail.com', + 'password' => '123123q' + ); + $this->_createdCustomer = $this->_model->create($customerData); + $this->assertEquals($isConfirmed, $this->_createdCustomer->getForceConfirmed()); + } + + /** + * @return array + */ + public function forceConfirmedDataProvider() + { + return array( + 'admin store' => array(true, true), + 'distro store' => array(false, false), + ); + } +} diff --git a/app/code/core/Mage/Adminhtml/Block/Api/Roles.php b/dev/tests/integration/testsuite/Mage/Customer/_files/customer_address.php similarity index 61% rename from app/code/core/Mage/Adminhtml/Block/Api/Roles.php rename to dev/tests/integration/testsuite/Mage/Customer/_files/customer_address.php index fb6fb863e8970df8b1377e296fa28e6be82c1264..0798af1fea2c2b86bbb7a4fc82862071e90eeaaf 100644 --- a/app/code/core/Mage/Adminhtml/Block/Api/Roles.php +++ b/dev/tests/integration/testsuite/Mage/Customer/_files/customer_address.php @@ -1,5 +1,7 @@ <?php /** + * Customer address fixture with entity_id = 1 + * * Magento * * NOTICE OF LICENSE @@ -18,31 +20,23 @@ * versions in the future. If you wish to customize Magento for your * needs please refer to http://www.magentocommerce.com for more information. * - * @category Mage - * @package Mage_Adminhtml * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -/** - * user roles block - * - * @category Mage - * @package Mage_Adminhtml - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Adminhtml_Block_Api_Roles extends Mage_Adminhtml_Block_Template -{ - - protected $_template = 'api/roles.phtml'; - - public function getAddNewUrl() - { - return $this->getUrl('*/*/editrole'); - } - - public function getGridHtml() - { - return $this->getLayout()->createBlock('Mage_Adminhtml_Block_Api_Grid_Role')->toHtml(); - } -} +/** @var Mage_Customer_Model_Address $customerAddress */ +$customerAddress = Mage::getModel('Mage_Customer_Model_Address'); +$customerAddress->setCustomerId(1) + ->setData(array( + 'entity_id' => 1, + 'telephone' => 3468676, + 'postcode' => 75477, + 'country_id' => 'AL', + 'city' => 'CityM', + 'street' => 'Green str, 67', + 'lastname' => 'Smith', + 'firstname' => 'John', + 'parent_id' => 1, + 'created_at' => date('YYY-MM-DD hh:mm:ss') + )); +$customerAddress->save(); diff --git a/dev/tests/integration/testsuite/Mage/Customer/_files/customer_two_addresses.php b/dev/tests/integration/testsuite/Mage/Customer/_files/customer_two_addresses.php new file mode 100644 index 0000000000000000000000000000000000000000..3db1a82e43c10ea384d43eb027cbdbb2c0eb6bd6 --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Customer/_files/customer_two_addresses.php @@ -0,0 +1,44 @@ +<?php +/** + * Customer address fixture with entity_id = 2, this fixture also creates address with entity_id = 1 + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +require 'customer_address.php'; + +/** @var Mage_Customer_Model_Address $customerAddress */ +$customerAddress = Mage::getModel('Mage_Customer_Model_Address'); +$customerAddress->setCustomerId(1) + ->setData(array( + 'entity_id' => 2, + 'telephone' => 3234676, + 'postcode' => 47676, + 'country_id' => 'AL', + 'city' => 'CityX', + 'street' => 'Black str, 48', + 'lastname' => 'Smith', + 'firstname' => 'John', + 'parent_id' => 1, + 'created_at' => date('YYY-MM-DD hh:mm:ss') + )); +$customerAddress->save(); diff --git a/dev/tests/integration/testsuite/Mage/Eav/Model/Validator/Attribute/BackendTest.php b/dev/tests/integration/testsuite/Mage/Eav/Model/Validator/Attribute/BackendTest.php new file mode 100644 index 0000000000000000000000000000000000000000..13cb9a2be58010f1bb1a47bcf3444efc19b20462 --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Eav/Model/Validator/Attribute/BackendTest.php @@ -0,0 +1,65 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Core + * @subpackage integration_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Test for Mage_Eav_Model_Validator_Attribute_Backend + */ +class Mage_Eav_Model_Validator_Attribute_BackendTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Eav_Model_Validator_Attribute_Backend + */ + protected $_model; + + protected function setUp() + { + $this->_model = new Mage_Eav_Model_Validator_Attribute_Backend(); + } + + /** + * Test method for Mage_Eav_Model_Validator_Attribute_Backend::isValid + * + * @magentoDataFixture Mage/Customer/_files/customer.php + */ + public function testIsValid() + { + /** @var $entity Mage_Customer_Model_Customer */ + $entity = Mage::getModel('Mage_Customer_Model_Customer')->load(1); + + $this->assertTrue($this->_model->isValid($entity)); + $this->assertEmpty($this->_model->getMessages()); + + $entity->setData('email', null); + $this->assertFalse($this->_model->isValid($entity)); + $this->assertArrayHasKey('email', $this->_model->getMessages()); + + $entity->setData('store_id', null); + $this->assertFalse($this->_model->isValid($entity)); + $this->assertArrayHasKey('email', $this->_model->getMessages()); + $this->assertArrayHasKey('store_id', $this->_model->getMessages()); + } +} diff --git a/dev/tests/integration/testsuite/Mage/Tax/Model/Resource/Calculation/Rule/CollectionTest.php b/dev/tests/integration/testsuite/Mage/Tax/Model/Resource/Calculation/Rule/CollectionTest.php index a7097f52c413f223efd85dfa6ab2ed157921be63..949efebd02c2c112906767316281b5b68c5fcc4c 100644 --- a/dev/tests/integration/testsuite/Mage/Tax/Model/Resource/Calculation/Rule/CollectionTest.php +++ b/dev/tests/integration/testsuite/Mage/Tax/Model/Resource/Calculation/Rule/CollectionTest.php @@ -46,8 +46,10 @@ class Mage_Tax_Model_Resource_Calculation_Rule_CollectionTest extends PHPUnit_Fr public function setClassTypeFilterDataProvider() { return array( - array(Mage_Tax_Model_Class::TAX_CLASS_TYPE_PRODUCT, 1, '/cd\.product_tax_class_id = [\S]{0,1}1[\S]{0,1}/'), - array(Mage_Tax_Model_Class::TAX_CLASS_TYPE_CUSTOMER, 1, '/cd\.customer_tax_class_id = [\S]{0,1}1[\S]{0,1}/') + array(Mage_Tax_Model_Class::TAX_CLASS_TYPE_PRODUCT, 1, + '/`?cd`?\.`?product_tax_class_id`? = [\S]{0,1}1[\S]{0,1}/'), + array(Mage_Tax_Model_Class::TAX_CLASS_TYPE_CUSTOMER, 1, + '/`?cd`?\.`?customer_tax_class_id`? = [\S]{0,1}1[\S]{0,1}/') ); } diff --git a/dev/tests/integration/testsuite/Mage/Catalog/Model/Product/Type/ApiTest.php b/dev/tests/integration/testsuite/Mage/Tax/Model/Resource/CalculationTest.php similarity index 50% rename from dev/tests/integration/testsuite/Mage/Catalog/Model/Product/Type/ApiTest.php rename to dev/tests/integration/testsuite/Mage/Tax/Model/Resource/CalculationTest.php index 26b45d4fecd0b22da56db806305e7944b88e4194..3a0a4f89cb0f6ff5b7ce1960234fb0b1f4a0824f 100644 --- a/dev/tests/integration/testsuite/Mage/Catalog/Model/Product/Type/ApiTest.php +++ b/dev/tests/integration/testsuite/Mage/Tax/Model/Resource/CalculationTest.php @@ -19,36 +19,34 @@ * needs please refer to http://www.magentocommerce.com for more information. * * @category Magento - * @package Magento_Catalog + * @package Mage_Tax * @subpackage integration_tests * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -class Mage_Catalog_Model_Product_Type_ApiTest extends PHPUnit_Framework_TestCase +class Mage_Tax_Model_Resource_CalculationTest extends PHPUnit_Framework_TestCase { /** - * @param string $class - * @dataProvider itemsDataProvider + * Test that Tax Rate applied only once + * + * @magentoDataFixture Mage/Tax/_files/tax_classes.php */ - public function testItems($class) + public function testGetRate() { - /** @var $model Mage_Catalog_Model_Product_Type_Api */ - $model = Mage::getModel($class); - $result = $model->items(); - $this->assertInternalType('array', $result); - $this->assertNotEmpty($result); - foreach ($result as $item) { - $this->assertArrayHasKey('type', $item); - $this->assertArrayHasKey('label', $item); - } - } - - public function itemsDataProvider() - { - return array( - array('Mage_Catalog_Model_Product_Type_Api'), - array('Mage_Catalog_Model_Product_Type_Api_V2'), // a dummy class, doesn't require separate test suite - ); + $taxRule = Mage::registry('_fixture/Mage_Tax_Model_Calculation_Rule'); + $customerTaxClasses = $taxRule->getTaxCustomerClass(); + $productTaxClasses = $taxRule->getTaxProductClass(); + $taxRate = Mage::registry('_fixture/Mage_Tax_Model_Calculation_Rate'); + $data = new Varien_Object(); + $data->setData(array( + 'country_id' => 'US', + 'region_id' => '12', + 'postcode' => '5555', + 'customer_class_id' => $customerTaxClasses[0], + 'product_class_id' => $productTaxClasses[0] + )); + $taxCalculation = Mage::getResourceSingleton('Mage_Tax_Model_Resource_Calculation'); + $this->assertEquals($taxRate->getRate(), $taxCalculation->getRate($data)); } } diff --git a/dev/tests/integration/testsuite/Mage/Tax/_files/tax_classes.php b/dev/tests/integration/testsuite/Mage/Tax/_files/tax_classes.php index 1806c7767a31ccbaa8f6246a28c3a9872842d769..71270acd2d9122fb906f3c547e355b75394859ec 100644 --- a/dev/tests/integration/testsuite/Mage/Tax/_files/tax_classes.php +++ b/dev/tests/integration/testsuite/Mage/Tax/_files/tax_classes.php @@ -54,6 +54,8 @@ $taxRate = array( ); $rate = Mage::getModel('Mage_Tax_Model_Calculation_Rate')->setData($taxRate)->save(); +Mage::register('_fixture/Mage_Tax_Model_Calculation_Rate', $rate); + $ruleData = array( 'code' => 'Test Rule', 'priority' => '0', @@ -66,3 +68,7 @@ $ruleData = array( $taxRule = Mage::getModel('Mage_Tax_Model_Calculation_Rule')->setData($ruleData)->save(); Mage::register('_fixture/Mage_Tax_Model_Calculation_Rule', $taxRule); + +$ruleData['code'] = 'Test Rule Duplicate'; + +Mage::getModel('Mage_Tax_Model_Calculation_Rule')->setData($ruleData)->save(); diff --git a/dev/tests/integration/testsuite/Mage/User/Model/Resource/Rules/CollectionTest.php b/dev/tests/integration/testsuite/Mage/User/Model/Resource/Rules/CollectionTest.php index 42a29cd1d82184d10d9a222de4d8ee42bd190d77..e07394a7666d447214a7ddebcf08ff5cceef1ca5 100644 --- a/dev/tests/integration/testsuite/Mage/User/Model/Resource/Rules/CollectionTest.php +++ b/dev/tests/integration/testsuite/Mage/User/Model/Resource/Rules/CollectionTest.php @@ -52,7 +52,10 @@ class Mage_User_Model_Resource_Rules_CollectionTest extends PHPUnit_Framework_Te $this->_collection->getByRoles($user->getRole()->getId()); $where = $this->_collection->getSelect()->getPart(Zend_Db_Select::WHERE); - $this->assertContains("(role_id = '" . $user->getRole()->getId()."')", $where); + /** @var Zend_Db_Adapter_Abstract $adapter */ + $adapter = $this->_collection->getConnection(); + $quote = $adapter->getQuoteIdentifierSymbol(); + $this->assertContains("({$quote}role_id{$quote} = '" . $user->getRole()->getId()."')", $where); } public function testAddSortByLength() diff --git a/dev/tests/integration/testsuite/Mage/Webapi/Block/Adminhtml/FormTestAbstract.php b/dev/tests/integration/testsuite/Mage/Webapi/Block/Adminhtml/FormTestAbstract.php new file mode 100644 index 0000000000000000000000000000000000000000..68c4df943c4eed8374a053c2aa7a045c1700f6c7 --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/Block/Adminhtml/FormTestAbstract.php @@ -0,0 +1,101 @@ +<?php +/** + * Abstract test case for Webapi forms. It was introduced to avoid copy-paste in form tests. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Block_Adminhtml_FormTestAbstract extends PHPUnit_Framework_TestCase +{ + /** + * Form class must be defined in children. + * + * @var string + */ + protected $_formClass = ''; + + /** + * @var Mage_Webapi_Block_Adminhtml_User_Edit_Form + */ + protected $_block; + + /** + * @var Magento_Test_ObjectManager + */ + protected $_objectManager; + + /** + * @var Mage_Backend_Model_Url|PHPUnit_Framework_MockObject_MockObject + */ + protected $_urlBuilder; + + /** + * @var Mage_Core_Model_Layout + */ + protected $_layout; + + /** + * @var Mage_Core_Model_BlockFactory + */ + protected $_blockFactory; + + protected function setUp() + { + $this->_objectManager = Mage::getObjectManager(); + $this->_urlBuilder = $this->getMockBuilder('Mage_Backend_Model_Url') + ->disableOriginalConstructor() + ->getMock(); + $this->_layout = $this->_objectManager->get('Mage_Core_Model_Layout'); + $this->_blockFactory = $this->_objectManager->get('Mage_Core_Model_BlockFactory'); + $this->_block = $this->_blockFactory->createBlock($this->_formClass, array( + 'urlBuilder' => $this->_urlBuilder + )); + $this->_layout->addBlock($this->_block); + } + + protected function tearDown() + { + $this->_objectManager->removeSharedInstance('Mage_Core_Model_Layout'); + unset($this->_objectManager, $this->_urlBuilder, $this->_layout, $this->_blockFactory, $this->_block); + } + + /** + * Test _prepareForm method + */ + public function testPrepareForm() + { + // TODO Move to unit tests after MAGETWO-4015 complete + $this->assertEmpty($this->_block->getForm()); + + $this->_urlBuilder->expects($this->once()) + ->method('getUrl') + ->with('*/*/save', array()) + ->will($this->returnValue('action_url')); + $this->_block->toHtml(); + + $form = $this->_block->getForm(); + $this->assertInstanceOf('Varien_Data_Form', $form); + $this->assertTrue($form->getUseContainer()); + $this->assertEquals('edit_form', $form->getId()); + $this->assertEquals('post', $form->getMethod()); + $this->assertEquals('action_url', $form->getAction()); + } +} diff --git a/dev/tests/integration/testsuite/Mage/Webapi/Block/Adminhtml/Role/Edit/FormTest.php b/dev/tests/integration/testsuite/Mage/Webapi/Block/Adminhtml/Role/Edit/FormTest.php new file mode 100644 index 0000000000000000000000000000000000000000..16eae0f9c794de126a0c7969b2d74953a38f2090 --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/Block/Adminhtml/Role/Edit/FormTest.php @@ -0,0 +1,34 @@ +<?php +/** + * Test for Mage_Webapi_Block_Adminhtml_Role_Edit_Form block + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Block_Adminhtml_Role_Edit_FormTest extends Mage_Webapi_Block_Adminhtml_FormTestAbstract +{ + protected $_formClass = 'Mage_Webapi_Block_Adminhtml_Role_Edit_Form'; + + /** + * @var Mage_Webapi_Block_Adminhtml_Role_Edit_Form + */ + protected $_block; +} diff --git a/dev/tests/integration/testsuite/Mage/Webapi/Block/Adminhtml/Role/Edit/Tab/MainTest.php b/dev/tests/integration/testsuite/Mage/Webapi/Block/Adminhtml/Role/Edit/Tab/MainTest.php new file mode 100644 index 0000000000000000000000000000000000000000..8f5afb830350fa628a4b12133c59d3effe1c3835 --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/Block/Adminhtml/Role/Edit/Tab/MainTest.php @@ -0,0 +1,130 @@ +<?php +/** + * Test for Mage_Webapi_Block_Adminhtml_Role_Edit_Tab_Main block + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Block_Adminhtml_Role_Edit_Tab_MainTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Magento_Test_ObjectManager + */ + protected $_objectManager; + + /** + * @var Mage_Core_Model_Layout + */ + protected $_layout; + + /** + * @var Mage_Core_Model_BlockFactory + */ + protected $_blockFactory; + + /** + * @var Mage_Webapi_Block_Adminhtml_Role_Edit_Tab_Main + */ + protected $_block; + + protected function setUp() + { + $this->_objectManager = Mage::getObjectManager(); + $this->_layout = $this->_objectManager->get('Mage_Core_Model_Layout'); + $this->_blockFactory = $this->_objectManager->get('Mage_Core_Model_BlockFactory'); + $this->_block = $this->_blockFactory->createBlock('Mage_Webapi_Block_Adminhtml_Role_Edit_Tab_Main'); + $this->_layout->addBlock($this->_block); + } + + protected function tearDown() + { + $this->_objectManager->removeSharedInstance('Mage_Core_Model_Layout'); + $this->_objectManager->removeSharedInstance('Mage_Core_Model_BlockFactory'); + unset($this->_objectManager, $this->_layout, $this->_blockFactory, $this->_block); + } + + /** + * Test _prepareForm method + * + * @dataProvider prepareFormDataProvider + * @param Varien_Object $apiRole + * @param array $formElements + */ + public function testPrepareForm($apiRole, array $formElements) + { + // TODO Move to unit tests after MAGETWO-4015 complete + $this->assertEmpty($this->_block->getForm()); + + $this->_block->setApiRole($apiRole); + $this->_block->toHtml(); + + $form = $this->_block->getForm(); + $this->assertInstanceOf('Varien_Data_Form', $form); + /** @var Varien_Data_Form_Element_Fieldset $fieldset */ + $fieldset = $form->getElement('base_fieldset'); + $this->assertInstanceOf('Varien_Data_Form_Element_Fieldset', $fieldset); + $elements = $fieldset->getElements(); + foreach ($formElements as $elementId) { + $element = $elements->searchById($elementId); + $this->assertNotEmpty($element, "Element '$elementId' not found in form fieldset"); + $this->assertEquals($apiRole->getData($elementId), $element->getValue()); + } + } + + /** + * @return array + */ + public function prepareFormDataProvider() + { + return array( + 'Empty API Role' => array( + new Varien_Object(), + array( + 'role_name', + 'in_role_user', + 'in_role_user_old' + ) + ), + 'New API Role' => array( + new Varien_Object(array( + 'role_name' => 'Role' + )), + array( + 'role_name', + 'in_role_user', + 'in_role_user_old' + ) + ), + 'Existed API Role' => array( + new Varien_Object(array( + 'id' => 1, + 'role_name' => 'Role' + )), + array( + 'role_id', + 'role_name', + 'in_role_user', + 'in_role_user_old' + ) + ) + ); + } +} diff --git a/dev/tests/integration/testsuite/Mage/Webapi/Block/Adminhtml/Role/Edit/Tab/ResourceTest.php b/dev/tests/integration/testsuite/Mage/Webapi/Block/Adminhtml/Role/Edit/Tab/ResourceTest.php new file mode 100644 index 0000000000000000000000000000000000000000..a07876536eb79ed3d80e50291e8eba86eb572f42 --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/Block/Adminhtml/Role/Edit/Tab/ResourceTest.php @@ -0,0 +1,160 @@ +<?php +/** + * Test for Mage_Webapi_Block_Adminhtml_Role_Edit_Tab_Resource block + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Block_Adminhtml_Role_Edit_Tab_ResourceTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Magento_Test_ObjectManager + */ + protected $_objectManager; + + /** + * @var Mage_Core_Model_Layout + */ + protected $_layout; + + /** + * @var Mage_Webapi_Model_Authorization_Config|PHPUnit_Framework_MockObject_MockObject + */ + protected $_authorizationConfig; + + /** + * @var Mage_Webapi_Model_Resource_Acl_Rule|PHPUnit_Framework_MockObject_MockObject + */ + protected $_ruleResource; + + /** + * @var Mage_Core_Model_BlockFactory + */ + protected $_blockFactory; + + /** + * @var Mage_Webapi_Block_Adminhtml_Role_Edit_Tab_Resource + */ + protected $_block; + + protected function setUp() + { + $this->_authorizationConfig = $this->getMockBuilder('Mage_Webapi_Model_Authorization_Config') + ->disableOriginalConstructor() + ->setMethods(array('getAclResourcesAsArray')) + ->getMock(); + + $this->_ruleResource = $this->getMockBuilder('Mage_Webapi_Model_Resource_Acl_Rule') + ->disableOriginalConstructor() + ->setMethods(array('getResourceIdsByRole')) + ->getMock(); + + $this->_objectManager = Mage::getObjectManager(); + $this->_layout = $this->_objectManager->get('Mage_Core_Model_Layout'); + $this->_blockFactory = $this->_objectManager->get('Mage_Core_Model_BlockFactory'); + $this->_block = $this->_blockFactory->createBlock('Mage_Webapi_Block_Adminhtml_Role_Edit_Tab_Resource', array( + 'authorizationConfig' => $this->_authorizationConfig, + 'ruleResource' => $this->_ruleResource + )); + $this->_layout->addBlock($this->_block); + } + + protected function tearDown() + { + $this->_objectManager->removeSharedInstance('Mage_Core_Model_Layout'); + unset($this->_objectManager, $this->_layout, $this->_authorizationConfig, $this->_blockFactory, $this->_block); + } + + /** + * Test _prepareForm method + * + * @dataProvider prepareFormDataProvider + * @param array $originResTree + * @param array $selectedRes + * @param array $expectedRes + */ + public function testPrepareForm($originResTree, $selectedRes, $expectedRes) + { + // TODO Move to unit tests after MAGETWO-4015 complete + $apiRole = new Varien_Object(array( + 'role_id' => 1 + )); + $apiRole->setIdFieldName('role_id'); + + $this->_block->setApiRole($apiRole); + + $this->_authorizationConfig->expects($this->once()) + ->method('getAclResourcesAsArray') + ->with(false) + ->will($this->returnValue($originResTree)); + + $this->_ruleResource->expects($this->once()) + ->method('getResourceIdsByRole') + ->with($apiRole->getId()) + ->will($this->returnValue($selectedRes)); + + $this->_block->toHtml(); + + $this->assertEquals($expectedRes, $this->_block->getResourcesTree()); + } + + /** + * @return array + */ + public function prepareFormDataProvider() + { + $resourcesTree = array( + array( + 'id' => 'customer', + 'text' => 'Manage Customers', + 'sortOrder' => 20, + 'children' => array( + array( + 'id' => 'customer/get', + 'text' => 'Get Customer', + 'sortOrder' => 20, + 'children' => array(), + ), + array( + 'id' => 'customer/create', + 'text' => 'Create Customer', + 'sortOrder' => 30, + 'children' => array(), + ) + ) + ) + ); + $resTreeCustomerGet = $resourcesTree; + $resTreeCustomerGet[0]['children'][0]['checked'] = true; + return array( + 'Empty Selected Resources' => array( + 'originResourcesTree' => $resourcesTree, + 'selectedResources' => array(), + 'expectedResourcesTree' => $resourcesTree + ), + 'One Selected Resource' => array( + 'originResourcesTree' => $resourcesTree, + 'selectedResources' => array('customer/get'), + 'expectedResourcesTree' => $resTreeCustomerGet + ) + ); + } +} diff --git a/dev/tests/integration/testsuite/Mage/Webapi/Block/Adminhtml/User/Edit/FormTest.php b/dev/tests/integration/testsuite/Mage/Webapi/Block/Adminhtml/User/Edit/FormTest.php new file mode 100644 index 0000000000000000000000000000000000000000..02509684b7a76080aa128de440bbc5634f557dc2 --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/Block/Adminhtml/User/Edit/FormTest.php @@ -0,0 +1,34 @@ +<?php +/** + * Test for Mage_Webapi_Block_Adminhtml_User_Edit_Form block + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Block_Adminhtml_User_Edit_FormTest extends Mage_Webapi_Block_Adminhtml_FormTestAbstract +{ + protected $_formClass = 'Mage_Webapi_Block_Adminhtml_User_Edit_Form'; + + /** + * @var Mage_Webapi_Block_Adminhtml_User_Edit_Form + */ + protected $_block; +} diff --git a/dev/tests/integration/testsuite/Mage/Webapi/Block/Adminhtml/User/Edit/Tab/MainTest.php b/dev/tests/integration/testsuite/Mage/Webapi/Block/Adminhtml/User/Edit/Tab/MainTest.php new file mode 100644 index 0000000000000000000000000000000000000000..d6ff31f661d120d83333a92a0f7aeaa4d70a8f91 --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/Block/Adminhtml/User/Edit/Tab/MainTest.php @@ -0,0 +1,140 @@ +<?php +/** + * Test for Mage_Webapi_Block_Adminhtml_User_Edit_Tab_Main block + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Block_Adminhtml_User_Edit_Tab_MainTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Magento_Test_ObjectManager + */ + protected $_objectManager; + + /** + * @var Mage_Core_Model_Layout + */ + protected $_layout; + + /** + * @var Mage_Core_Model_BlockFactory + */ + protected $_blockFactory; + + /** + * @var Mage_Webapi_Block_Adminhtml_User_Edit_Tab_Main + */ + protected $_block; + + protected function setUp() + { + $this->_objectManager = Mage::getObjectManager(); + $this->_layout = $this->_objectManager->get('Mage_Core_Model_Layout'); + $this->_blockFactory = $this->_objectManager->get('Mage_Core_Model_BlockFactory'); + $this->_block = $this->_blockFactory->createBlock('Mage_Webapi_Block_Adminhtml_User_Edit_Tab_Main'); + $this->_layout->addBlock($this->_block); + } + + protected function tearDown() + { + $this->_objectManager->removeSharedInstance('Mage_Core_Model_Layout'); + unset($this->_objectManager, $this->_urlBuilder, $this->_layout, $this->_blockFactory, $this->_block); + } + + /** + * Test _prepareForm method + * + * @dataProvider prepareFormDataProvider + * @param Varien_Object $apiUser + * @param array $formElements + */ + public function testPrepareForm($apiUser, array $formElements) + { + // TODO Move to unit tests after MAGETWO-4015 complete + $this->assertEmpty($this->_block->getForm()); + + $this->_block->setApiUser($apiUser); + $this->_block->toHtml(); + + $form = $this->_block->getForm(); + $this->assertInstanceOf('Varien_Data_Form', $form); + /** @var Varien_Data_Form_Element_Fieldset $fieldset */ + $fieldset = $form->getElement('base_fieldset'); + $this->assertInstanceOf('Varien_Data_Form_Element_Fieldset', $fieldset); + $elements = $fieldset->getElements(); + foreach ($formElements as $elementId) { + $element = $elements->searchById($elementId); + $this->assertNotEmpty($element, "Element '$elementId' not found in form fieldset"); + $this->assertEquals($apiUser->getData($elementId), $element->getValue()); + } + } + + /** + * @return array + */ + public function prepareFormDataProvider() + { + return array( + 'Empty API User' => array( + new Varien_Object(), + array( + 'company_name', + 'contact_email', + 'api_key', + 'secret' + ) + ), + 'New API User' => array( + new Varien_Object(array( + 'company_name' => 'Company', + 'contact_email' => 'mail@example.com', + 'api_key' => 'API Key', + 'secret' => 'API Secret', + 'role_id' => 1 + )), + array( + 'company_name', + 'contact_email', + 'api_key', + 'secret' + ) + ), + 'Existed API User' => array( + new Varien_Object(array( + 'id' => 1, + 'company_name' => 'Company', + 'contact_email' => 'mail@example.com', + 'api_key' => 'API Key', + 'secret' => 'API Secret', + 'role_id' => 1 + )), + array( + 'user_id', + 'company_name', + 'contact_email', + 'api_key', + 'secret' + ) + ) + ); + } +} diff --git a/dev/tests/integration/testsuite/Mage/Webapi/Block/Adminhtml/User/Edit/TabsTest.php b/dev/tests/integration/testsuite/Mage/Webapi/Block/Adminhtml/User/Edit/TabsTest.php new file mode 100644 index 0000000000000000000000000000000000000000..4408b66724a143b8d32dd947f2fcb648be40574f --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/Block/Adminhtml/User/Edit/TabsTest.php @@ -0,0 +1,130 @@ +<?php +/** + * Test for Mage_Webapi_Block_Adminhtml_User_Edit_Tabs block + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Block_Adminhtml_User_Edit_TabsTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Magento_Test_ObjectManager + */ + protected $_objectManager; + + /** + * @var Mage_Core_Model_Layout + */ + protected $_layout; + + /** + * @var Mage_Webapi_Block_Adminhtml_User_Edit_Tabs + */ + protected $_block; + + protected function setUp() + { + $this->_objectManager = Mage::getObjectManager(); + $this->_layout = $this->_objectManager->get('Mage_Core_Model_Layout'); + $this->_block = $this->_layout->createBlock('Mage_Webapi_Block_Adminhtml_User_Edit_Tabs', + 'webapi.user.edit.tabs'); + } + + protected function tearDown() + { + $this->_objectManager->removeSharedInstance('Mage_Core_Model_Layout'); + unset($this->_objectManager, $this->_layout, $this->_block); + } + + /** + * Test _beforeToHtml method + */ + public function testBeforeToHtml() + { + // TODO Move to unit tests after MAGETWO-4015 complete + /** @var Mage_Webapi_Block_Adminhtml_User_Edit_Tab_Main $mainTabBlock */ + $mainTabBlock = $this->_layout->addBlock( + 'Mage_Core_Block_Text', + 'webapi.user.edit.tab.main', + 'webapi.user.edit.tabs' + )->setText('Main Block Content'); + + $this->_layout->addBlock( + 'Mage_Core_Block_Text', + 'webapi.user.edit.tab.roles.grid', + 'webapi.user.edit.tabs' + )->setText('Grid Block Content'); + + $apiUser = new Varien_Object(array( + 'role_id' => 1 + )); + $this->_block->setApiUser($apiUser); + $this->_block->toHtml(); + + $this->assertSame($apiUser, $mainTabBlock->getApiUser()); + + $tabs = $this->_getProtectedTabsValue($this->_block); + $this->assertArrayHasKey('main_section', $tabs); + $this->assertInstanceOf('Varien_Object', $tabs['main_section']); + $this->assertEquals(array( + 'label' => 'User Info', + 'title' => 'User Info', + 'content' => 'Main Block Content', + 'active' => '1', + 'url' => '#', + 'id' => 'main_section', + 'tab_id' => 'main_section', + ), $tabs['main_section']->getData()); + + $this->assertArrayHasKey('roles_section', $tabs); + $this->assertInstanceOf('Varien_Object', $tabs['roles_section']); + $this->assertEquals(array( + 'label' => 'User Role', + 'title' => 'User Role', + 'content' => 'Grid Block Content', + 'url' => '#', + 'id' => 'roles_section', + 'tab_id' => 'roles_section' + ), $tabs['roles_section']->getData()); + } + + /** + * Get protected _tabs property of Mage_Backend_Block_Widget_Tabs block + * + * @param Mage_Backend_Block_Widget_Tabs $tabs + * @return array + */ + protected function _getProtectedTabsValue(Mage_Backend_Block_Widget_Tabs $tabs) + { + $result = null; + try { + $classReflection = new ReflectionClass(get_class($tabs)); + $tabsProperty = $classReflection->getProperty('_tabs'); + $tabsProperty->setAccessible(true); + $result = $tabsProperty->getValue($tabs); + } catch (ReflectionException $exception) { + $this->fail('Cannot get tabs value'); + + } + $this->assertInternalType('array', $result, 'Tabs value expected to be an array'); + return $result; + } +} diff --git a/dev/tests/integration/testsuite/Mage/Webapi/Block/Adminhtml/User/EditTest.php b/dev/tests/integration/testsuite/Mage/Webapi/Block/Adminhtml/User/EditTest.php new file mode 100644 index 0000000000000000000000000000000000000000..859cc59e29d47cf260d1f831382e9836572a0765 --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/Block/Adminhtml/User/EditTest.php @@ -0,0 +1,72 @@ +<?php +/** + * Test for Mage_Webapi_Block_Adminhtml_User_Edit block + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Block_Adminhtml_User_EditTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Magento_Test_ObjectManager + */ + protected $_objectManager; + + /** + * @var Mage_Core_Model_Layout + */ + protected $_layout; + + /** + * @var Mage_Webapi_Block_Adminhtml_User_Edit + */ + protected $_block; + + /** + * Initialize block + */ + protected function setUp() + { + $this->_objectManager = Mage::getObjectManager(); + $this->_layout = Mage::getObjectManager()->get('Mage_Core_Model_Layout'); + $this->_block = $this->_layout->createBlock('Mage_Webapi_Block_Adminhtml_User_Edit'); + } + + /** + * Clear clock + */ + protected function tearDown() + { + unset($this->_objectManager, $this->_layout, $this->_block); + } + + /** + * Test _beforeToHtml method + */ + public function testBeforeToHtml() + { + // TODO Move to unit tests after MAGETWO-4015 complete + $apiUser = new Varien_Object(); + $this->_block->setApiUser($apiUser); + $this->_block->toHtml(); + $this->assertSame($apiUser, $this->_block->getChildBlock('form')->getApiUser()); + } +} diff --git a/dev/tests/integration/testsuite/Mage/Webapi/Helper/ConfigTest.php b/dev/tests/integration/testsuite/Mage/Webapi/Helper/ConfigTest.php new file mode 100644 index 0000000000000000000000000000000000000000..086b53f7b6f888e32df03bca652f72c0070f157f --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/Helper/ConfigTest.php @@ -0,0 +1,199 @@ +<?php +/** + * Config helper tests. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + + +/** + * Class implements tests for Mage_Webapi_Helper_Data class. + */ +class Mage_Webapi_Helper_ConfigTest extends PHPUnit_Framework_TestCase +{ + /** @var Mage_Webapi_Helper_Config */ + protected $_helper; + + /** + * Set up helper. + */ + protected function setUp() + { + $objectManager = new Magento_Test_ObjectManager(); + $this->_helper = $objectManager->get('Mage_Webapi_Helper_Config'); + parent::setUp(); + } + + /** + * @dataProvider dataProviderForTestConvertSingularToPlural + */ + public function testConvertSingularToPlural($singular, $expectedPlural) + { + $this->assertEquals( + $expectedPlural, + $this->_helper->convertSingularToPlural($singular), + "Conversion from singular to plural was performed incorrectly." + ); + } + + public static function dataProviderForTestConvertSingularToPlural() + { + return array( + array('customer', 'customers'), + array('category', 'categories'), + array('webapi', 'webapis'), + array('downloadable', 'downloadables'), + array('eway', 'eways'), + array('tax', 'taxes'), + array('', '') + ); + } + + /** + * @dataProvider dataProviderTestTranslateArrayTypeName + * @param string $typeToBeTranslated + * @param string $expectedResult + */ + public function testTranslateArrayTypeName($typeToBeTranslated, $expectedResult) + { + $this->assertEquals( + $expectedResult, + $this->_helper->translateArrayTypeName($typeToBeTranslated), + "Array type was translated incorrectly." + ); + } + + public static function dataProviderTestTranslateArrayTypeName() + { + return array( + array('ComplexType[]', 'ArrayOfComplexType'), + array('string[]', 'ArrayOfString'), + array('integer[]', 'ArrayOfInt'), + array('bool[]', 'ArrayOfBoolean'), + ); + } + + /** + * @dataProvider dataProviderForTestTranslateTypeName + * @param string $typeName + * @param string $expectedResult + */ + public function testTranslateTypeName($typeName, $expectedResult) + { + $this->assertEquals( + $expectedResult, + $this->_helper->translateTypeName($typeName), + "Type translation was performed incorrectly." + ); + } + + public static function dataProviderForTestTranslateTypeName() + { + return array( + array('Mage_Customer_Model_Webapi_CustomerData', 'CustomerData'), + array('Mage_Catalog_Model_Webapi_ProductData', 'CatalogProductData'), + array('Vendor_Customer_Model_Webapi_Customer_AddressData', 'VendorCustomerAddressData'), + array('Producer_Module_Model_Webapi_ProducerData', 'ProducerModuleProducerData'), + array('Producer_Module_Model_Webapi_ProducerModuleData', 'ProducerModuleProducerModuleData'), + ); + } + + public function testTranslateTypeNameInvalidArgument() + { + $this->setExpectedException('InvalidArgumentException', 'Invalid parameter type "Invalid_Type_Name".'); + $this->_helper->translateTypeName('Invalid_Type_Name'); + } + + public function testGetBodyParamNameInvalidInterface() + { + $methodName = 'updateV1'; + $bodyPosition = 2; + $this->setExpectedException( + 'LogicException', + sprintf( + 'Method "%s" must have parameter for passing request body. ' + . 'Its position must be "%s" in method interface.', + $methodName, + $bodyPosition + ) + ); + $this->_helper->getOperationBodyParamName( + Mage_Webapi_Helper_Data::createMethodReflection( + 'Vendor_Module_Controller_Webapi_Invalid_Interface', + $methodName + ) + ); + } + + public function testGetIdParamNameEmptyMethodInterface() + { + $this->setExpectedException('LogicException', 'must have at least one parameter: resource ID.'); + $this->_helper->getOperationIdParamName( + Mage_Webapi_Helper_Data::createMethodReflection( + 'Vendor_Module_Controller_Webapi_Invalid_Interface', + 'emptyInterfaceV2' + ) + ); + } + + public function testGetResourceNamePartsException() + { + $className = 'Vendor_Module_Webapi_Resource_Invalid'; + $this->setExpectedException( + 'InvalidArgumentException', + sprintf('The controller class name "%s" is invalid.', $className) + ); + $this->_helper->getResourceNameParts($className); + } + + /** + * @dataProvider dataProviderForTestGetResourceNameParts + * @param $className + * @param $expectedParts + */ + public function testGetResourceNameParts($className, $expectedParts) + { + $this->assertEquals( + $expectedParts, + $this->_helper->getResourceNameParts($className), + "Resource parts for rest route were identified incorrectly." + ); + } + + public static function dataProviderForTestGetResourceNameParts() + { + return array( + array('Vendor_Customer_Controller_Webapi_Customer_Address', array('VendorCustomer', 'Address')), + /** Check removal of 'Mage' prefix as well as duplicating parts ('Customer') */ + array('Mage_Customer_Controller_Webapi_Customer_Address', array('Customer', 'Address')), + ); + } + + public function testGetIdParamException() + { + $className = 'Vendor_Module_Webapi_Resource_Invalid'; + $this->setExpectedException('LogicException', sprintf('"%s" is not a valid resource class.', $className)); + $this->_helper->getOperationIdParamName( + Mage_Webapi_Helper_Data::createMethodReflection($className, 'updateV1') + ); + } +} diff --git a/dev/tests/integration/testsuite/Mage/Webapi/Helper/DataTest.php b/dev/tests/integration/testsuite/Mage/Webapi/Helper/DataTest.php new file mode 100644 index 0000000000000000000000000000000000000000..d4dc92545edbefac2d17a1940dde6634142c0242 --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/Helper/DataTest.php @@ -0,0 +1,246 @@ +<?php +/** + * File contains tests for Auto Discovery functionality. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/**#@+ + * API resources must be available without auto loader as the file name cannot be calculated from class name. + */ +include_once __DIR__ . '/../_files/data_types/Customer/AddressData.php'; +include_once __DIR__ . '/../_files/data_types/CustomerData.php'; +include_once __DIR__ . '/../_files/autodiscovery/subresource_class_fixture.php'; +/**#@-*/ + +/** + * Class implements tests for Mage_Webapi_Helper_Data class. + */ +class Mage_Webapi_Helper_DataTest extends PHPUnit_Framework_TestCase +{ + /** @var Mage_Webapi_Helper_Data */ + protected $_helper; + + /** @var Mage_Webapi_Model_ConfigAbstract */ + protected static $_apiConfig; + + protected function setUp() + { + $this->_helper = Mage::getObjectManager()->get('Mage_Webapi_Helper_Data'); + parent::setUp(); + } + + /** + * @return Mage_Webapi_Model_ConfigAbstract + */ + protected function _getApiConfig() + { + if (!self::$_apiConfig) { + $objectManager = new Magento_Test_ObjectManager(); + /** Prepare arguments for SUT constructor. */ + $pathToFixtures = __DIR__ . '/../_files/autodiscovery'; + /** @var Mage_Webapi_Model_Config_Reader_Soap $reader */ + $reader = $objectManager->get('Mage_Webapi_Model_Config_Reader_Soap'); + $reader->setDirectoryScanner(new Zend\Code\Scanner\DirectoryScanner($pathToFixtures)); + /** Initialize SUT. */ + self::$_apiConfig = $objectManager->create('Mage_Webapi_Model_Config_Soap', array('reader' => $reader)); + } + return self::$_apiConfig; + } + + public static function tearDownAfterClass() + { + self::$_apiConfig = null; + parent::tearDownAfterClass(); + } + + /** + * @dataProvider dataProviderForTestPrepareMethodParamsPositive + * @param string|object $class + * @param string $methodName + * @param array $requestData + * @param array $expectedResult + */ + public function testPrepareMethodParamsPositive( + $class, + $methodName, + $requestData, + $expectedResult = array() + ) { + $actualResult = $this->_helper->prepareMethodParams($class, $methodName, $requestData, $this->_getApiConfig()); + $this->assertEquals($expectedResult, $actualResult, "The array of arguments was prepared incorrectly."); + } + + public static function dataProviderForTestPrepareMethodParamsPositive() + { + $customerDataObject = new Vendor_Module_Model_Webapi_CustomerData(); + $customerDataObject->email = "test_email@example.com"; + $customerDataObject->firstname = "firstName"; + $customerDataObject->address = new Vendor_Module_Model_Webapi_Customer_AddressData(); + $customerDataObject->address->city = "cityName"; + $customerDataObject->address->street = "streetName"; + + /** Test passing of complex type parameter with optional field not set */ + $optionalNotSetInput = array( + 'email' => "test_email@example.com", + 'firstname' => 'firstName' + ); + $optionalNotSetOutput = new Vendor_Module_Model_Webapi_CustomerData(); + $optionalNotSetOutput->email = "test_email@example.com"; + $optionalNotSetOutput->firstname = "firstName"; + $optionalNotSetOutput->lastname = "DefaultLastName"; + $optionalNotSetOutput->password = "123123q"; + + return array( + // Test valid data that does not need transformations + array( + 'Vendor_Module_Controller_Webapi_Resource_Subresource', + 'createV1', + array('param1' => 1, 'param2' => 2, 'param3' => array($customerDataObject), 'param4' => 4), + array('param1' => 1, 'param2' => 2, 'param3' => array($customerDataObject), 'param4' => 4), + ), + // Test filtering unnecessary data + array( + 'Vendor_Module_Controller_Webapi_Resource_Subresource', + 'createV2', + array('param1' => 1, 'param2' => 2, 'param3' => array($customerDataObject), 'param4' => 4), + array('param1' => 1, 'param2' => 2), + ), + // Test parameters sorting + array( + 'Vendor_Module_Controller_Webapi_Resource_Subresource', + 'createV1', + array('param4' => 4, 'param2' => 2, 'param3' => array($customerDataObject), 'param1' => 1), + array('param1' => 1, 'param2' => 2, 'param3' => array($customerDataObject), 'param4' => 4), + ), + // Test default values setting + array( + 'Vendor_Module_Controller_Webapi_Resource_Subresource', + 'createV1', + array('param1' => 1, 'param2' => 2), + array('param1' => 1, 'param2' => 2, 'param3' => array(), 'param4' => 'default_value'), + ), + // Test with object instead of class name + array( + new Vendor_Module_Controller_Webapi_Resource_Subresource(), + 'createV2', + array('param2' => 2, 'param1' => 1), + array('param1' => 1, 'param2' => 2), + ), + // Test passing of partially formatted objects + array( + new Vendor_Module_Controller_Webapi_Resource_Subresource(), + 'updateV1', + array('param1' => 1, 'param2' => get_object_vars($customerDataObject)), + array('param1' => 1, 'param2' => $customerDataObject), + ), + // Test passing of complex type parameter with optional field not set + array( + new Vendor_Module_Controller_Webapi_Resource_Subresource(), + 'updateV1', + array('param1' => 1, 'param2' => $optionalNotSetInput), + array('param1' => 1, 'param2' => $optionalNotSetOutput), + ), + ); + } + + /** + * Test prepareMethodParams method with unexpected data instead of array. + */ + public function testPrepareMethodParamsArrayExpectedException() + { + $this->setExpectedException( + 'Mage_Webapi_Exception', + 'Data corresponding to "VendorModuleCustomerData[]" type is expected to be an array.', + Mage_Webapi_Exception::HTTP_BAD_REQUEST + ); + $this->_helper->prepareMethodParams( + 'Vendor_Module_Controller_Webapi_Resource_Subresource', + 'createV1', + array('param1' => 1, 'param2' => 2, 'param3' => 'not_array', 'param4' => 4), + $this->_getApiConfig() + ); + } + + /** + * Test prepareMethodParams method with complex type equal to unexpected data instead of array. + */ + public function testPrepareMethodParamsComplexTypeArrayExpectedException() + { + $this->setExpectedException( + 'Mage_Webapi_Exception', + 'Data corresponding to "VendorModuleCustomerData" type is expected to be an array.', + Mage_Webapi_Exception::HTTP_BAD_REQUEST + ); + $this->_helper->prepareMethodParams( + 'Vendor_Module_Controller_Webapi_Resource_Subresource', + 'updateV1', + array('param1' => 1, 'param2' => 'Non array complex data'), + $this->_getApiConfig() + ); + } + + /** + * @dataProvider dataProviderForTestPrepareMethodParamsNegative + * @param string|object $class + * @param string $methodName + * @param array $requestData + * @param string $exceptionClass + * @param string $exceptionMessage + */ + public function testPrepareMethodParamsNegative( + $class, + $methodName, + $requestData, + $exceptionClass, + $exceptionMessage + ) { + $this->setExpectedException($exceptionClass, $exceptionMessage); + $this->_helper->prepareMethodParams($class, $methodName, $requestData, $this->_getApiConfig()); + } + + public static function dataProviderForTestPrepareMethodParamsNegative() + { + /** Customer data without required field */ + $withoutRequired = array( + 'email' => "test_email@example.com" + ); + return array( + // Test exception in case of missing required parameter + array( + 'Vendor_Module_Controller_Webapi_Resource_Subresource', + 'createV1', + array('param2' => 2, 'param4' => 4), + 'Mage_Webapi_Exception', + 'Required parameter "param1" is missing.' + ), + // Test passing of complex type parameter with not specified required field + array( + new Vendor_Module_Controller_Webapi_Resource_Subresource(), + 'updateV1', + array('param1' => 1, 'param2' => $withoutRequired), + 'Mage_Webapi_Exception', + 'Value of "firstname" attribute is required.' + ), + ); + } +} diff --git a/dev/tests/integration/testsuite/Mage/Webapi/Model/Acl/RoleTest.php b/dev/tests/integration/testsuite/Mage/Webapi/Model/Acl/RoleTest.php new file mode 100644 index 0000000000000000000000000000000000000000..cd926f447d3aa3c94c0295b7bc2a4dd534fe9836 --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/Model/Acl/RoleTest.php @@ -0,0 +1,65 @@ +<?php +/** + * Test for Mage_Webapi_Model_Acl_Role model + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * @magentoDataFixture Mage/Webapi/_files/role.php + */ +class Mage_Webapi_Model_Acl_RoleTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Magento_Test_ObjectManager + */ + protected $_objectManager; + + /** + * @var Mage_Webapi_Model_Acl_Role + */ + protected $_model; + + /** + * Initialize model + */ + protected function setUp() + { + $this->_objectManager = Mage::getObjectManager(); + $this->_model = $this->_objectManager->create('Mage_Webapi_Model_Acl_Role'); + } + + /** + * Cleanup model instance + */ + protected function tearDown() + { + unset($this->_objectManager, $this->_model); + } + + /** + * Test Web API Role CRUD + */ + public function testCRUD() + { + $this->_model->setRoleName('Test Role Name'); + $crud = new Magento_Test_Entity($this->_model, array('role_name' => '_Role_Name_')); + $crud->testCrud(); + } +} diff --git a/dev/tests/integration/testsuite/Mage/Webapi/Model/Acl/RuleTest.php b/dev/tests/integration/testsuite/Mage/Webapi/Model/Acl/RuleTest.php new file mode 100644 index 0000000000000000000000000000000000000000..00b31715a7e467c71b8cf66d722d4b62cb764710 --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/Model/Acl/RuleTest.php @@ -0,0 +1,92 @@ +<?php +/** + * Test for Mage_Webapi_Model_Acl_Rule model + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * @magentoDataFixture Mage/Webapi/_files/role.php + */ +class Mage_Webapi_Model_Acl_RuleTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Magento_Test_ObjectManager + */ + protected $_objectManager; + + /** + * @var Mage_Webapi_Model_Acl_Role_Factory + */ + protected $_roleFactory; + + /** + * @var Mage_Webapi_Model_Acl_Rule + */ + protected $_model; + + protected function setUp() + { + $this->_objectManager = Mage::getObjectManager(); + $this->_roleFactory = $this->_objectManager->get('Mage_Webapi_Model_Acl_Role_Factory'); + $this->_model = $this->_objectManager->create('Mage_Webapi_Model_Acl_Rule'); + } + + /** + * Cleanup model instance + */ + protected function tearDown() + { + unset($this->_objectManager, $this->_model); + } + + /** + * Test Web API Rule CRUD + */ + public function testCRUD() + { + $role = $this->_roleFactory->create()->load('test_role', 'role_name'); + $allowResourceId = 'customer/multiGet'; + + $this->_model->setRoleId($role->getId()) + ->setResourceId($allowResourceId); + + $crud = new Magento_Test_Entity($this->_model, array('resource_id' => 'customer/get')); + $crud->testCrud(); + } + + /** + * Test method Mage_Webapi_Model_Acl_Rule::saveResources() + */ + public function testSaveResources() + { + $role = $this->_roleFactory->create()->load('test_role', 'role_name'); + $resources = array('customer/create', 'customer/update'); + + $this->_model + ->setRoleId($role->getId()) + ->setResources($resources) + ->saveResources(); + + /** @var $rulesSet Mage_Webapi_Model_Resource_Acl_Rule_Collection */ + $rulesSet = $this->_objectManager->get('Mage_Webapi_Model_Resource_Acl_Rule_Collection') + ->getByRole($role->getRoleId())->load(); + $this->assertCount(2, $rulesSet); + } +} diff --git a/dev/tests/integration/testsuite/Mage/Webapi/Model/Acl/UserTest.php b/dev/tests/integration/testsuite/Mage/Webapi/Model/Acl/UserTest.php new file mode 100644 index 0000000000000000000000000000000000000000..89cb37eaf5b4ff5aff0a3fefd95dd6095ec2ff9b --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/Model/Acl/UserTest.php @@ -0,0 +1,78 @@ +<?php +/** + * Test for Mage_Webapi_Model_Acl_User model + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * @magentoDataFixture Mage/Webapi/_files/role.php + */ +class Mage_Webapi_Model_Acl_UserTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Magento_Test_ObjectManager + */ + protected $_objectManager; + + /** + * @var Mage_Webapi_Model_Acl_User + */ + protected $_model; + + /** + * @var Mage_Webapi_Model_Acl_Role_Factory + */ + protected $_roleFactory; + + /** + * Initialize model + */ + protected function setUp() + { + $this->_objectManager = Mage::getObjectManager(); + $this->_roleFactory = $this->_objectManager->get('Mage_Webapi_Model_Acl_Role_Factory'); + $this->_model = $this->_objectManager->create('Mage_Webapi_Model_Acl_User'); + } + + /** + * Cleanup model instance + */ + protected function tearDown() + { + unset($this->_objectManager, $this->_model); + } + + /** + * Test Web API User CRUD + */ + public function testCRUD() + { + $role = $this->_roleFactory->create()->load('test_role', 'role_name'); + + $this->_model + ->setApiKey('Test User Name') + ->setContactEmail('null@null.com') + ->setSecret('null@null.com') + ->setRoleId($role->getId()); + + $crud = new Magento_Test_Entity($this->_model, array('api_key' => '_User_Name_')); + $crud->testCrud(); + } +} diff --git a/dev/tests/integration/testsuite/Mage/Webapi/Model/Config/Reader/Rest/RouteGeneratorTest.php b/dev/tests/integration/testsuite/Mage/Webapi/Model/Config/Reader/Rest/RouteGeneratorTest.php new file mode 100644 index 0000000000000000000000000000000000000000..733e34e535e21a3a65d9349aeac6ca06f56d1556 --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/Model/Config/Reader/Rest/RouteGeneratorTest.php @@ -0,0 +1,255 @@ +<?php +/** + * File with unit tests for REST routes generator class: Mage_Webapi_Model_Config_Reader_Rest_RouteGenerator + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/**#@+ + * API resources must be available without auto loader as the file name cannot be calculated from class name. + */ +require_once __DIR__ . '/../../../../_files/autodiscovery/resource_class_fixture.php'; +require_once __DIR__ . '/../../../../_files/autodiscovery/subresource_class_fixture.php'; +require_once __DIR__ . '/../../../_files/resource_with_invalid_interface.php'; +require_once __DIR__ . '/../../../_files/resource_with_invalid_name.php'; + +/**#@-*/ + +class Mage_Webapi_Model_Config_Reader_Rest_RouteGeneratorTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Webapi_Model_Config_Reader_Rest_RouteGenerator + */ + protected $_model; + + protected function setUp() + { + $helper = $this->getMock('Mage_Webapi_Helper_Config', array('__')); + $this->_model = new Mage_Webapi_Model_Config_Reader_Rest_RouteGenerator($helper); + } + + /** + * @dataProvider dataProviderTestGenerateRestRoutesTopLevelResource + * @param string $className + * @param string $methodName + * @param array $expectedRoutes + */ + public function testGenerateRestRoutesTopLevelResource($className, $methodName, $expectedRoutes) + { + $actualRoutes = $this->_model->generateRestRoutes( + Mage_Webapi_Helper_Data::createMethodReflection($className, $methodName) + ); + $this->assertRoutesEqual($expectedRoutes, $actualRoutes); + } + + public static function dataProviderTestGenerateRestRoutesTopLevelResource() + { + $versionParam = Mage_Webapi_Controller_Router_Route_Rest::PARAM_VERSION; + $className = "Vendor_Module_Controller_Webapi_Resource"; + $createPath = "/:$versionParam/vendorModuleResources/requiredField/:requiredField"; + return array( + array( + $className, + "createV1", + array( + $createPath => array( + "actionType" => "collection", + "resourceName" => "vendorModuleResource" + ), + $createPath . "/optionalField/:optionalField" => array( + "actionType" => "collection", + "resourceName" => "vendorModuleResource" + ), + $createPath . "/secondOptional/:secondOptional" => array( + "actionType" => "collection", + "resourceName" => "vendorModuleResource" + ), + $createPath . "/optionalField/:optionalField/secondOptional/:secondOptional" => array( + "actionType" => "collection", + "resourceName" => "vendorModuleResource" + ), + $createPath . "/secondOptional/:secondOptional/optionalField/:optionalField" => array( + "actionType" => "collection", + "resourceName" => "vendorModuleResource" + ) + ), + ), + array( + $className, + "updateV2", + array( + "/:$versionParam/vendorModuleResources/:id/additionalRequired/:additionalRequired" => array( + "actionType" => "item", + "resourceName" => "vendorModuleResource" + ), + ), + ), + array( + $className, + "getV2", + array( + "/:$versionParam/vendorModuleResources/:id" => array( + "actionType" => "item", + "resourceName" => "vendorModuleResource" + ), + ), + ), + array( + $className, + "listV2", + array( + "/:$versionParam/vendorModuleResources/additionalRequired/:additionalRequired" => array( + "actionType" => "collection", + "resourceName" => "vendorModuleResource" + ), + "/:$versionParam/vendorModuleResources/additionalRequired/:additionalRequired/" + . "optional/:optional" => array( + "actionType" => "collection", + "resourceName" => "vendorModuleResource" + ), + ), + ), + array( + $className, + "deleteV3", + array( + "/:$versionParam/vendorModuleResources/:id" => array( + "actionType" => "item", + "resourceName" => "vendorModuleResource" + ), + ), + ), + array( + $className, + "multiUpdateV2", + array( + "/:$versionParam/vendorModuleResources" => array( + "actionType" => "collection", + "resourceName" => "vendorModuleResource" + ), + ), + ), + array( + $className, + "multiDeleteV2", + array( + "/:$versionParam/vendorModuleResources" => array( + "actionType" => "collection", + "resourceName" => "vendorModuleResource" + ), + ), + ), + ); + } + + /** + * @dataProvider dataProviderTestGenerateRestRoutesSubresource + * @param string $className + * @param string $methodName + * @param array $expectedRoutes + */ + public function testGenerateRestRoutesSubresource($className, $methodName, $expectedRoutes) + { + $actualRoutes = $this->_model->generateRestRoutes( + Mage_Webapi_Helper_Data::createMethodReflection($className, $methodName) + ); + $this->assertRoutesEqual($expectedRoutes, $actualRoutes); + } + + public static function dataProviderTestGenerateRestRoutesSubresource() + { + $className = 'Vendor_Module_Controller_Webapi_Resource_Subresource'; + $versionParam = Mage_Webapi_Controller_Router_Route_Rest::PARAM_VERSION; + return array( + array( + $className, + 'createV2', + array( + "/:$versionParam/vendorModuleResources/:parentId/subresources" => array( + 'actionType' => 'collection', + 'resourceName' => 'vendorModuleResourceSubresource' + ) + ), + ), + array( + $className, + 'updateV1', + array( + "/:$versionParam/vendorModuleResources/subresources/:id" => array( + 'actionType' => 'item', + 'resourceName' => 'vendorModuleResourceSubresource' + ) + ), + ), + ); + } + + /** + * Check if list of REST routes are equal. + * + * @param array $expectedRoutes + * @param array $actualRoutes + * @SuppressWarnings(PHPMD.UnusedLocalVariable) + */ + public function assertRoutesEqual($expectedRoutes, $actualRoutes) + { + $this->assertInternalType( + 'array', + $actualRoutes, + "Mage_Webapi_Model_Config::generateRestRoutes() must return value of 'array' type." + ); + + foreach ($expectedRoutes as $expectedRoute => $expectedMetadata) { + $this->assertArrayHasKey( + $expectedRoute, + $actualRoutes, + "'$expectedRoute' route was expected to be present in results." + ); + } + foreach ($actualRoutes as $actualRoute => $actualRouteMetadata) { + $this->assertArrayHasKey( + $actualRoute, + $expectedRoutes, + "'$actualRoute' route was not expected to be present in results." + ); + $this->assertEquals( + $expectedRoutes[$actualRoute], + $actualRouteMetadata, + "'$actualRoute' route metadata is invalid." + ); + } + } + + public function testGenerateRestRoutesInvalidMethod() + { + $this->setExpectedException( + 'InvalidArgumentException', + '"invalidMethodNameV2" is an invalid API resource method.' + ); + $this->_model->generateRestRoutes( + Mage_Webapi_Helper_Data::createMethodReflection( + 'Vendor_Module_Controller_Webapi_Invalid_Interface', + 'invalidMethodNameV2' + ) + ); + } +} diff --git a/dev/tests/integration/testsuite/Mage/Webapi/Model/Config/RestTest.php b/dev/tests/integration/testsuite/Mage/Webapi/Model/Config/RestTest.php new file mode 100644 index 0000000000000000000000000000000000000000..18342bb068a6fe72285f7f567d1eb478ae516c3f --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/Model/Config/RestTest.php @@ -0,0 +1,188 @@ +<?php +/** + * File with unit tests for API configuration class: Mage_Webapi_Model_Config_Rest + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/**#@+ + * API resources must be available without auto loader as the file name cannot be calculated from class name. + */ +require_once __DIR__ . '/../../_files/autodiscovery/resource_class_fixture.php'; +require_once __DIR__ . '/../../_files/autodiscovery/subresource_class_fixture.php'; +require_once __DIR__ . '/../../_files/data_types/CustomerData.php'; +require_once __DIR__ . '/../../_files/data_types/Customer/AddressData.php'; +require_once __DIR__ . '/../_files/resource_with_invalid_interface.php'; +require_once __DIR__ . '/../_files/resource_with_invalid_name.php'; +/**#@-*/ + + +/** + * Test of API configuration class: Mage_Webapi_Model_Config + */ +class Mage_Webapi_Model_Config_RestTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Webapi_Model_Config_Rest + */ + protected static $_apiConfig; + + public static function tearDownAfterClass() + { + self::$_apiConfig = null; + parent::tearDownAfterClass(); + } + + /** + * @return Mage_Webapi_Model_Config_Rest + */ + protected function _getModel() + { + if (!self::$_apiConfig) { + $pathToFixtures = __DIR__ . '/../../_files/autodiscovery'; + self::$_apiConfig = $this->_createResourceConfig($pathToFixtures); + } + return self::$_apiConfig; + } + + public function testGetAllResourcesVersions() + { + $expectedResult = array( + 'vendorModuleResource' => array('V1', 'V2', 'V3', 'V4', 'V5'), + 'vendorModuleResourceSubresource' => array('V1', 'V2', 'V4') + ); + $allResourcesVersions = $this->_getModel()->getAllResourcesVersions(); + $this->assertEquals($expectedResult, $allResourcesVersions, "The list of all resources versions is incorrect."); + } + + public function testGetMethodMetadataDataNotAvailable() + { + $this->setExpectedException( + 'InvalidArgumentException', + 'The "update" method of "vendorModuleInvalidInterface" resource in version "V2" is not registered.' + ); + $this->_getModel()->getMethodMetadata( + $this->_createMethodReflection( + 'Vendor_Module_Controller_Webapi_Invalid_Interface', + 'updateV2' + ) + ); + } + + public function testGetRestRoutes() + { + $actualRoutes = $this->_getModel()->getAllRestRoutes(); + $expectedRoutesCount = 16; + + /** + * Vendor_Module_Controller_Webapi_Resource fixture contains two methods getV2 and deleteV3 that have + * different names of ID param. + * If there will be two different routes generated for these methods with different ID param names, + * it will be impossible to identify which route should be used as they both will match the same requests. + * E.g. DELETE /resource/:deleteId and GET /resource/:getId will match same requests. + */ + $this->assertNotCount( + $expectedRoutesCount + 1, + $actualRoutes, + "Some resource methods seem to have different routes, in case when should have the same ones." + ); + + $this->assertCount($expectedRoutesCount, $actualRoutes, "Routes quantity does not equal to expected one."); + /** @var $actualRoute Mage_Webapi_Controller_Router_Route_Rest */ + foreach ($actualRoutes as $actualRoute) { + $this->assertInstanceOf('Mage_Webapi_Controller_Router_Route_Rest', $actualRoute); + } + } + + public function testGetRestRouteToItem() + { + $expectedRoute = '/:resourceVersion/vendorModuleResources/subresources/:id'; + $this->assertEquals($expectedRoute, $this->_getModel()->getRestRouteToItem('vendorModuleResourceSubresource')); + } + + public function testGetRestRouteToItemInvalidArguments() + { + $resourceName = 'vendorModuleResources'; + $this->setExpectedException( + 'InvalidArgumentException', + sprintf('No route to the item of "%s" resource was found.', $resourceName) + ); + $this->_getModel()->getRestRouteToItem($resourceName); + } + + public function testGetMethodRestRoutes() + { + $actualRoutes = $this->_getModel()->getMethodRestRoutes('vendorModuleResourceSubresource', 'create', 'v1'); + $this->assertCount(5, $actualRoutes, "Routes quantity does not match expected one."); + foreach ($actualRoutes as $actualRoute) { + $this->assertInstanceOf('Mage_Webapi_Controller_Router_Route_Rest', $actualRoute); + } + } + + public function testGetMethodRestRoutesException() + { + $resourceName = 'vendorModuleResourceSubresource'; + $methodName = 'multiUpdate'; + $this->setExpectedException( + 'InvalidArgumentException', + sprintf('"%s" resource does not have any REST routes for "%s" method.', $resourceName, $methodName) + ); + $this->_getModel()->getMethodRestRoutes($resourceName, $methodName, 'v1'); + } + + /** + * Create resource config initialized with classes found in the specified directory. + * + * @param string $pathToResources + * @return Mage_Webapi_Model_Config_Rest + */ + protected function _createResourceConfig($pathToResources) + { + $objectManager = new Magento_Test_ObjectManager(); + /** Prepare arguments for SUT constructor. */ + /** @var Mage_Core_Model_Cache $cache */ + $cache = $this->getMockBuilder('Mage_Core_Model_Cache')->disableOriginalConstructor()->getMock(); + /** @var Mage_Webapi_Model_Config_Reader_Rest $reader */ + $reader = $objectManager->get('Mage_Webapi_Model_Config_Reader_Rest', array('cache' => $cache)); + $reader->setDirectoryScanner(new Zend\Code\Scanner\DirectoryScanner($pathToResources)); + + /** Initialize SUT. */ + $apiConfig = $objectManager->create('Mage_Webapi_Model_Config_Rest', array('reader' => $reader)); + return $apiConfig; + } + + /** + * Create Zend method reflection object. + * + * @param string|object $classOrObject + * @param string $methodName + * @return Zend\Server\Reflection\ReflectionMethod + */ + protected function _createMethodReflection($classOrObject, $methodName) + { + $methodReflection = new \ReflectionMethod($classOrObject, $methodName); + $classReflection = new \ReflectionClass($classOrObject); + $zendClassReflection = new Zend\Server\Reflection\ReflectionClass($classReflection); + $zendMethodReflection = new Zend\Server\Reflection\ReflectionMethod($zendClassReflection, $methodReflection); + return $zendMethodReflection; + } +} diff --git a/dev/tests/integration/testsuite/Mage/Webapi/Model/Config/Soap/DataTest.php b/dev/tests/integration/testsuite/Mage/Webapi/Model/Config/Soap/DataTest.php new file mode 100644 index 0000000000000000000000000000000000000000..f5527dbd85dfc8e2564773b9c0237ba3398dc394 --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/Model/Config/Soap/DataTest.php @@ -0,0 +1,103 @@ +<?php +/** + * API Resource config integration tests. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/**#@+ + * Data structures should be available without auto loader as the file name cannot be calculated from class name. + */ +include __DIR__ . '/../../../_files/Model/Webapi/ModuleA/ModuleAData.php'; +include __DIR__ . '/../../../_files/Model/Webapi/ModuleA/ModuleADataB.php'; +include __DIR__ . '/../../../_files/Controller/Webapi/ModuleA.php'; +include __DIR__ . '/../../../_files/Controller/Webapi/SubresourceB.php'; +/**#@-*/ + +/** + * Class for {@see Mage_Webapi_Model_Config} model testing. + * + * The main purpose of this test case is to check config data structure after initialization. + */ +class Mage_Webapi_Model_Config_Soap_DataTest extends PHPUnit_Framework_TestCase +{ + /** @var Mage_Webapi_Model_Config_Soap */ + protected $_config; + + /** + * Set up config with fixture controllers directory scanner + */ + protected function setUp() + { + $fixtureDir = __DIR__ . '/../../../_files/Controller/Webapi/'; + $directoryScanner = new \Zend\Code\Scanner\DirectoryScanner($fixtureDir); + /** @var Mage_Core_Model_Cache $cache */ + $cache = $this->getMockBuilder('Mage_Core_Model_Cache')->disableOriginalConstructor()->getMock(); + /** @var Mage_Core_Model_App $app */ + $app = $this->getMockBuilder('Mage_Core_Model_App')->disableOriginalConstructor()->getMock(); + $appConfig = Mage::app()->getConfig(); + $objectManager = new Magento_Test_ObjectManager(); + /** @var Mage_Webapi_Helper_Config $helper */ + $helper = $objectManager->get('Mage_Webapi_Helper_Config'); + /** @var Mage_Webapi_Model_Config_Reader_Soap_ClassReflector $classReflector */ + $classReflector = $objectManager->get('Mage_Webapi_Model_Config_Reader_Soap_ClassReflector'); + $reader = new Mage_Webapi_Model_Config_Reader_Soap($classReflector, $appConfig, $cache); + $reader->setDirectoryScanner($directoryScanner); + + $this->_config = new Mage_Webapi_Model_Config_Soap($reader, $helper, $app); + $objectManager->addSharedInstance($this->_config, 'Mage_Webapi_Model_Config_Soap'); + } + + + /** + * Test getResourceDataMerged() functionality. + * Expected result of method is placed in file fixture. + */ + public function testGetResource() + { + $expectedResourceA = include __DIR__ . '/../../../_files/config/resource_a_fixture.php'; + $this->assertEquals($expectedResourceA, $this->_config->getResourceDataMerged('namespaceAModuleA', 'v1'), + 'Version 1 resource_a data does not match'); + + $this->assertEquals( + include __DIR__ . '/../../../_files/config/resource_a_fixture_v2.php', + $this->_config->getResourceDataMerged('namespaceAModuleA', 'v2'), + 'Version 2 resource_a data does not match.' + ); + + $this->assertEquals( + include __DIR__ . '/../../../_files/config/resource_a_subresource_b_fixture.php', + $this->_config->getResourceDataMerged('namespaceAModuleASubresourceB', 'v1'), + 'Version 1 resource_a_subresource_b data does no match.' + ); + } + + /** + * Test getDataType functionality. + * Expected result of method is placed in file fixture. + */ + public function testGetDataType() + { + $expectedType = include __DIR__ . '/../../../_files/config/data_structure_fixture.php'; + $this->assertEquals($expectedType, $this->_config->getTypeData('NamespaceAModuleAData')); + } +} diff --git a/dev/tests/integration/testsuite/Mage/Webapi/Model/Config/SoapTest.php b/dev/tests/integration/testsuite/Mage/Webapi/Model/Config/SoapTest.php new file mode 100644 index 0000000000000000000000000000000000000000..06682ddf2cdbec6c099e1adefb3a9824a7183fd5 --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/Model/Config/SoapTest.php @@ -0,0 +1,569 @@ +<?php +/** + * File with unit tests for API configuration class: Mage_Webapi_Model_Config_Soap + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/**#@+ + * API resources must be available without auto loader as the file name cannot be calculated from class name. + */ +require_once __DIR__ . '/../../_files/autodiscovery/resource_class_fixture.php'; +require_once __DIR__ . '/../../_files/autodiscovery/subresource_class_fixture.php'; +require_once __DIR__ . '/../../_files/data_types/CustomerData.php'; +require_once __DIR__ . '/../../_files/data_types/Customer/AddressData.php'; +require_once __DIR__ . '/../_files/resource_with_invalid_interface.php'; +require_once __DIR__ . '/../_files/resource_with_invalid_name.php'; +require_once __DIR__ . '/../_files/autodiscovery/invalid_deprecation_policy/class.php'; +require_once __DIR__ . '/../_files/autodiscovery/empty_var_tags/data_type.php'; +require_once __DIR__ . '/../_files/autodiscovery/empty_var_tags/class.php'; +require_once __DIR__ . '/../_files/autodiscovery/empty_property_description/data_type.php'; +require_once __DIR__ . '/../_files/autodiscovery/empty_property_description/class.php'; +require_once __DIR__ . '/../_files/autodiscovery/reference_to_invalid_type/class.php'; +/**#@-*/ + +/** + * Test of API configuration class: Mage_Webapi_Model_Config + */ +class Mage_Webapi_Model_Config_SoapTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Webapi_Model_Config_Soap + */ + protected static $_apiConfig; + + public static function tearDownAfterClass() + { + self::$_apiConfig = null; + parent::tearDownAfterClass(); + } + + /** + * @return Mage_Webapi_Model_Config_Soap + */ + protected function _getModel() + { + if (!self::$_apiConfig) { + $pathToFixtures = __DIR__ . '/../../_files/autodiscovery'; + self::$_apiConfig = $this->_createResourceConfig($pathToFixtures); + } + return self::$_apiConfig; + } + + /** + * @dataProvider dataProviderTestGetResourceNameByOperationPositive + * @param string $operation + * @param string $resourceVersion + * @param string $expectedResourceName + * @param string $message + */ + public function testGetResourceNameByOperationPositive( + $operation, + $resourceVersion, + $expectedResourceName, + $message = 'Resource name was identified incorrectly by given operation.' + ) { + $actualResourceName = $this->_getModel()->getResourceNameByOperation($operation, $resourceVersion); + $this->assertEquals($expectedResourceName, $actualResourceName, $message); + } + + public function dataProviderTestGetResourceNameByOperationPositive() + { + return array( + array('vendorModuleResourceCreate', 'v1', 'vendorModuleResource'), + array( + 'vendorModuleResourceCreate', + '1', + 'vendorModuleResource', + "Resource was identified incorrectly by version without 'v' prefix" + ), + array( + 'vendorModuleResourceMultiUpdate', + 'v2', + 'vendorModuleResource', + 'Compound method names or version seem to be identified incorrectly.' + ), + array( + 'vendorModuleResourceSubresourceUpdate', + 'v1', + 'vendorModuleResourceSubresource', + 'Compound resource name is identified incorrectly.' + ), + array( + 'vendorModuleResourceSubresourceMultiDelete', + null, + 'vendorModuleResourceSubresource', + "If version is not set - no check must be performed for operation existence in resource." + ), + ); + } + + /** + * @dataProvider dataProviderTestGetResourceNameByOperationNegative + * @param string $operation + * @param string $resourceVersion + * @param string $expectedResourceName + * @param string $message + */ + public function testGetResourceNameByOperationNegative( + $operation, + $resourceVersion, + $expectedResourceName, + $message = 'Resource name was identified incorrectly by given operation.' + ) { + $actualResourceName = $this->_getModel()->getResourceNameByOperation($operation, $resourceVersion); + $this->assertEquals($expectedResourceName, $actualResourceName, $message); + } + + public function dataProviderTestGetResourceNameByOperationNegative() + { + return array( + array('customerUpdate', 'v1', false, "In case when resource not found 'false' is expected."), + array('vendorModuleResourceCreate', 'v100', false, "In case when version not found 'false' is expected."), + ); + } + + /** + * @dataProvider dataProviderTestGetResourceNameByOperationException + * @param string $operation + * @param string $resourceVersion + */ + public function testGetResourceNameByOperationException($operation, $resourceVersion) + { + $this->setExpectedException( + 'InvalidArgumentException', + sprintf('The "%s" is not a valid API resource operation name.', $operation) + ); + $this->_getModel()->getResourceNameByOperation($operation, $resourceVersion); + } + + public function dataProviderTestGetResourceNameByOperationException() + { + return array( + array('customerMultiDeleteExcessiveSuffix', 'v2', 'Excessive suffix is ignored.'), + array('customerInvalid', 'v1', "In case when operation not found 'false' is expected."), + ); + } + + /** + * @dataProvider dataProviderTestGetMethodNameByOperation + * @param string $operation + * @param string $resourceVersion + * @param string $expectedResourceName + * @param string $message + */ + public function testGetMethodNameByOperation( + $operation, + $resourceVersion, + $expectedResourceName, + $message = 'Resource name was identified incorrectly by given operation.' + ) { + $actualResourceName = $this->_getModel()->getMethodNameByOperation($operation, $resourceVersion); + $this->assertEquals($expectedResourceName, $actualResourceName, $message); + } + + public function dataProviderTestGetMethodNameByOperation() + { + return array( + array('vendorModuleResourceCreate', 'v1', 'create'), + array( + 'vendorModuleResourceMultiUpdate', + 'v2', + 'multiUpdate', + 'Compound method names seem be be identified incorrectly or version processing is broken.' + ), + array( + 'vendorModuleResourceSubresourceMultiDelete', + null, + 'multiDelete', + "If version is not set - no check must be performed for operation existence in resource." + ), + array('vendorModuleResourceUpdate', 'v100', false, "In case when version not found 'false' is expected."), + ); + } + + /** + * @dataProvider dataProviderTestGetMethodNameByOperationException + * @param string $operation + * @param string $resourceVersion + */ + public function testGetMethodNameByOperationException($operation, $resourceVersion) + { + $this->setExpectedException( + 'InvalidArgumentException', + sprintf('The "%s" is not a valid API resource operation name.', $operation) + ); + $this->_getModel()->getMethodNameByOperation($operation, $resourceVersion); + } + + public function dataProviderTestGetMethodNameByOperationException() + { + return array( + array('vendorModuleResourceMultiUpdateExcessiveSuffix', 'v2', 'Excessive suffix is ignored.'), + array('vendorModuleResourceInvalid', 'v1', "In case when operation not found 'false' is expected."), + ); + } + + public function testGetControllerClassByOperationNamePositive() + { + $actualController = $this->_getModel()->getControllerClassByOperationName('vendorModuleResourceList'); + $message = 'Controller class was identified incorrectly by given operation.'; + $this->assertEquals('Vendor_Module_Controller_Webapi_Resource', $actualController, $message); + } + + /** + * @dataProvider dataProviderTestGetControllerClassByOperationNameNegative + * @param string $operation + */ + public function testGetControllerClassByOperationNameNegative($operation) + { + $this->setExpectedException( + 'InvalidArgumentException', + sprintf('The "%s" is not a valid API resource operation name.', $operation) + ); + $this->_getModel()->getControllerClassByOperationName($operation); + } + + public function dataProviderTestGetControllerClassByOperationNameNegative() + { + return array( + array('customerMultiDeleteExcessiveSuffix', 'Excessive suffix is ignored.'), + array('customerInvalid', "In case when operation not found 'false' is expected."), + ); + } + + public function testGetControllerClassByOperationNameWithException() + { + $this->setExpectedException( + 'LogicException', + 'Resource "resourceWithoutControllerAndModule" must have associated controller class.' + ); + $this->_getModel()->getControllerClassByOperationName('resourceWithoutControllerAndModuleGet'); + } + + /** + * @dataProvider dataProviderForTestGetResourceMaxVersion + * @param string $resourceName + * @param int $expectedMaxVersion + */ + public function testGetResourceMaxVersion($resourceName, $expectedMaxVersion) + { + $this->assertEquals( + $expectedMaxVersion, + $this->_getModel()->getResourceMaxVersion($resourceName), + "Resource Maximum available version was identified incorrectly." + ); + } + + public function dataProviderForTestGetResourceMaxVersion() + { + return array( + array('vendorModuleResource', 5), + array('vendorModuleResourceSubresource', 4), + ); + } + + public function testGetResourceMaxVersionException() + { + $resourceName = 'InvalidResource'; + $this->setExpectedException( + 'InvalidArgumentException', + sprintf('Resource "%s" does not exist.', $resourceName) + ); + $this->_getModel()->getResourceMaxVersion($resourceName); + } + + public function testGetResource() + { + $resourceData = $this->_getModel()->getResourceDataMerged('vendorModuleResource', 'v1'); + $this->assertTrue(isset($resourceData['methods']['create']), "Information about methods is not available."); + $this->assertTrue( + isset($resourceData['methods']['create']['interface']['in']['parameters']['requiredField']), + "Data structure seems to be missing method input parameters." + ); + $this->assertTrue( + isset($resourceData['methods']['create']['interface']['out']['parameters']['result']['type']), + "Data structure seems to be missing method output parameters." + ); + } + + public function testGetResourceInvalidResourceName() + { + $this->setExpectedException('RuntimeException', 'Unknown resource "invalidResource".'); + $this->_getModel()->getResourceDataMerged('invalidResource', 'v1'); + } + + public function testGetResourceInvalidVersion() + { + $this->setExpectedException('RuntimeException', 'Unknown version "V100" for resource "vendorModuleResource".'); + $this->_getModel()->getResourceDataMerged('vendorModuleResource', 'v100'); + } + + public function testGetTypeData() + { + $actualDataType = $this->_getModel()->getTypeData('VendorModuleCustomerAddressData'); + $expectedDataType = array( + 'documentation' => 'Tests fixture for Auto Discovery functionality. Customer address entity.', + 'parameters' => array( + 'street' => array( + 'type' => 'string', + 'required' => true, + 'default' => NULL, + 'documentation' => 'Street', + ), + 'city' => array( + 'type' => 'string', + 'required' => true, + 'default' => NULL, + 'documentation' => 'City', + ), + 'state' => array( + 'type' => 'string', + 'required' => false, + 'default' => NULL, + 'documentation' => 'State', + ), + ), + ); + $this->assertEquals($expectedDataType, $actualDataType); + } + + public function testGetTypeDataInvalidName() + { + $this->setExpectedException( + 'InvalidArgumentException', + 'Data type "InvalidDataTypeName" was not found in config.' + ); + $this->_getModel()->getTypeData('InvalidDataTypeName'); + } + + public function testGetAllResourcesVersions() + { + $expectedResult = array( + 'vendorModuleResource' => array('V1', 'V2', 'V3', 'V4', 'V5'), + 'vendorModuleResourceSubresource' => array('V1', 'V2', 'V4') + ); + $allResourcesVersions = $this->_getModel()->getAllResourcesVersions(); + $this->assertEquals($expectedResult, $allResourcesVersions, "The list of all resources versions is incorrect."); + } + + public function testGetMethodMetadataDataNotAvailable() + { + $this->setExpectedException( + 'InvalidArgumentException', + 'The "update" method of "vendorModuleInvalidInterface" resource in version "V2" is not registered.' + ); + $this->_getModel()->getMethodMetadata( + $this->_createMethodReflection( + 'Vendor_Module_Controller_Webapi_Invalid_Interface', + 'updateV2' + ) + ); + } + + public function testExtractDataPopulateClassException() + { + $this->setExpectedException('LogicException', 'There can be only one class in'); + $this->_createResourceConfig(__DIR__ . '/../_files/autodiscovery/several_classes_in_one_file'); + } + + public function testExtractDataEmptyResult() + { + $this->setExpectedException('LogicException', 'Cannot populate config - no action controllers were found.'); + $this->_createResourceConfig(__DIR__ . '/../_files/autodiscovery/no_resources'); + } + + public function testExtractDataInvalidTypeOfArgument() + { + $this->setExpectedException('InvalidArgumentException', 'Could not load the '); + $this->_createResourceConfig(__DIR__ . '/../_files/autodiscovery/reference_to_invalid_type'); + } + + public function testExtractDataUndocumentedProperty() + { + $this->setExpectedException( + 'InvalidArgumentException', + 'Each property must have description with @var annotation.' + ); + $this->_createResourceConfig(__DIR__ . '/../_files/autodiscovery/empty_property_description'); + } + + public function testExtractDataPropertyWithoutVarTag() + { + $this->setExpectedException('InvalidArgumentException', 'Property type must be defined with @var tag.'); + $this->_createResourceConfig(__DIR__ . '/../_files/autodiscovery/empty_var_tags'); + } + + public function testExtractDataInvalidDeprecationPolicy() + { + $this->setExpectedException( + 'LogicException', + '"Invalid_Deprecation_Controller_Webapi_Policy::getV1" ' + . 'method has invalid format of Deprecation policy. Accepted formats are createV1, ' + . 'catalogProduct::createV1 and Mage_Catalog_Webapi_ProductController::createV1.' + ); + $this->_createResourceConfig(__DIR__ . '/../_files/autodiscovery/invalid_deprecation_policy'); + } + + /** + * @dataProvider dataProviderForTestGetDeprecationPolicy + * @param string $resource + * @param string $method + * @param string $version + * @param string $deprecationFormat + * @param array $expectedResult + */ + public function testGetDeprecationPolicy($resource, $method, $version, $expectedResult, $deprecationFormat) + { + $actualResult = $this->_getModel()->getDeprecationPolicy($resource, $method, $version); + $this->assertEquals( + $expectedResult, + $actualResult, + "Deprecation policy was defined incorrectly. The following definition was used: '$deprecationFormat'" + ); + } + + public static function dataProviderForTestGetDeprecationPolicy() + { + return array( + array( + 'vendorModuleResource', + 'list', + 2, + array( + 'deprecated' => true, + 'use_resource' => 'vendorModuleResource', + 'use_method' => 'list', + 'use_version' => 'V3' + ), + '@apiDeprecated vendorModuleResource::listV3' + ), + array('vendorModuleResource', 'list', 3, false, 'No policy defined.'), + array( + 'vendorModuleResource', + 'delete', + 'V1', + array( + 'removed' => true, + 'use_resource' => 'vendorModuleResource', + 'use_method' => 'delete', + 'use_version' => 'V3' + ), + '@apiRemoved deleteV3' + ), + array( + 'vendorModuleResource', + 'delete', + 2, + array( + 'deprecated' => true, + 'use_resource' => 'vendorModuleResourceSubresource', + 'use_method' => 'delete', + 'use_version' => 'V3' + ), + '@apiDeprecated Vendor_Module_Controller_Webapi_Resource_Subresource::deleteV3' + ), + array( + 'vendorModuleResource', + 'delete', + 'v3', + array( + 'removed' => true, + ), + '@apiDeprecated \n @apiRemoved' + ), + array( + 'vendorModuleResource', + 'delete', + 'v4', + array( + 'deprecated' => true, + ), + '@apiDeprecated' + ), + ); + } + + /** + * @dataProvider dataProviderForTestGetDeprecationPolicyException + * @param string $resource + * @param string $method + * @param string $version + * @param string $expectedMessage + */ + public function testGetDeprecationPolicyException($resource, $method, $version, $expectedMessage) + { + $this->setExpectedException('InvalidArgumentException', $expectedMessage); + $this->_getModel()->getDeprecationPolicy($resource, $method, $version); + } + + public static function dataProviderForTestGetDeprecationPolicyException() + { + return array( + array('invalidResource', 'delete', 1, 'Unknown resource "invalidResource".'), + array('vendorModuleResource', 'update', 10, 'Unknown version "V10" for resource "vendorModuleResource".'), + array( + 'vendorModuleResource', + 'update', + 1, + 'Method "update" does not exist in "1" version of resource "vendorModuleResource".' + ), + ); + } + + /** + * Create resource config initialized with classes found in the specified directory. + * + * @param string $pathToResources + * @return Mage_Webapi_Model_Config_Soap + */ + protected function _createResourceConfig($pathToResources) + { + $objectManager = new Magento_Test_ObjectManager(); + /** Prepare arguments for SUT constructor. */ + /** @var Mage_Core_Model_Cache $cache */ + $cache = $this->getMockBuilder('Mage_Core_Model_Cache')->disableOriginalConstructor()->getMock(); + /** @var Mage_Webapi_Model_Config_Reader_Soap $reader */ + $reader = $objectManager->get('Mage_Webapi_Model_Config_Reader_Soap', array('cache' => $cache)); + $reader->setDirectoryScanner(new Zend\Code\Scanner\DirectoryScanner($pathToResources)); + + /** Initialize SUT. */ + $apiConfig = $objectManager->create('Mage_Webapi_Model_Config_Soap', array('reader' => $reader)); + return $apiConfig; + } + + /** + * Create Zend method reflection object. + * + * @param string|object $classOrObject + * @param string $methodName + * @return Zend\Server\Reflection\ReflectionMethod + */ + protected function _createMethodReflection($classOrObject, $methodName) + { + $methodReflection = new \ReflectionMethod($classOrObject, $methodName); + $classReflection = new \ReflectionClass($classOrObject); + $zendClassReflection = new Zend\Server\Reflection\ReflectionClass($classReflection); + $zendMethodReflection = new Zend\Server\Reflection\ReflectionMethod($zendClassReflection, $methodReflection); + return $zendMethodReflection; + } +} diff --git a/dev/tests/integration/testsuite/Mage/Webapi/Model/Resource/Acl/RoleTest.php b/dev/tests/integration/testsuite/Mage/Webapi/Model/Resource/Acl/RoleTest.php new file mode 100644 index 0000000000000000000000000000000000000000..3e6284362d7c5b6560fd01b0a4bf5e14de6a3558 --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/Model/Resource/Acl/RoleTest.php @@ -0,0 +1,108 @@ +<?php +/** + * Test for Mage_Webapi_Model_Resource_Acl_Role + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Resource_Acl_RoleTest extends PHPUnit_Framework_TestCase +{ + /** + * Test for Mage_Webapi_Model_Resource_Acl_Role::getRolesIds() + * + * @magentoDataFixture Mage/Webapi/_files/role.php + * @magentoDataFixture Mage/Webapi/_files/role_with_rule.php + */ + public function testGetRolesIds() + { + $expectedRoleNames = array('test_role', 'Test role'); + /** @var $roleResource Mage_Webapi_Model_Resource_Acl_Role */ + $roleResource = Mage::getResourceModel('Mage_Webapi_Model_Resource_Acl_Role'); + $rolesIds = $roleResource->getRolesIds(); + $this->assertCount(2, $rolesIds); + foreach ($rolesIds as $roleId) { + /** @var $role Mage_Webapi_Model_Acl_Role */ + $role = Mage::getModel('Mage_Webapi_Model_Acl_Role')->load($roleId); + $this->assertNotEmpty($role->getId()); + $this->assertContains($role->getRoleName(), $expectedRoleNames); + } + } + + /** + * Test for Mage_Webapi_Model_Resource_Acl_Role::getRolesList() + * + * @magentoDataFixture Mage/Webapi/_files/role.php + * @magentoDataFixture Mage/Webapi/_files/role_with_rule.php + */ + public function testGetRolesList() + { + /** @var $roleResource Mage_Webapi_Model_Resource_Acl_Role */ + $roleResource = Mage::getResourceModel('Mage_Webapi_Model_Resource_Acl_Role'); + $rolesList = $roleResource->getRolesList(); + $this->assertCount(2, $rolesList); + foreach ($rolesList as $roleId => $roleName) { + $role = Mage::getModel('Mage_Webapi_Model_Acl_Role')->load($roleId); + $this->assertEquals($roleId, $role->getId()); + $this->assertEquals($roleName, $role->getRoleName()); + } + } + + /** + * Test for Mage_Webapi_Model_Resource_Acl_Role::_initUniqueFields() + * + * @expectedException Mage_Core_Exception + * @expectedExceptionMessage Role Name already exists. + * @magentoDataFixture Mage/Webapi/_files/role.php + */ + public function testInitUniqueFields() + { + /** @var $roleResource Mage_Webapi_Model_Resource_Acl_Role */ + $roleResource = Mage::getResourceModel('Mage_Webapi_Model_Resource_Acl_Role'); + $uniqueFields = $roleResource->getUniqueFields(); + $expectedUnique = array( + array( + 'field' => 'role_name', + 'title' => 'Role Name' + ), + ); + $this->assertEquals($expectedUnique, $uniqueFields); + + Mage::getModel('Mage_Webapi_Model_Acl_Role') + ->setRoleName('test_role') + ->save(); + } + + /** + * Test for Mage_Webapi_Model_Resource_Acl_Role::delete() + * + * @magentoDataFixture Mage/Webapi/_files/user_with_role.php + */ + public function testDeleteRole() + { + Mage::getModel('Mage_Webapi_Model_Acl_Role') + ->load('Test role', 'role_name') + ->delete(); + /** @var Mage_Webapi_Model_Acl_User $user */ + $user = Mage::getModel('Mage_Webapi_Model_Acl_User') + ->load('test_username', 'api_key'); + $this->assertNotEmpty($user->getId()); + } +} diff --git a/dev/tests/integration/testsuite/Mage/Webapi/Model/Resource/Acl/RuleTest.php b/dev/tests/integration/testsuite/Mage/Webapi/Model/Resource/Acl/RuleTest.php new file mode 100644 index 0000000000000000000000000000000000000000..42b70f05d589a7a561dac1758dd5c8edcbf6d5ef --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/Model/Resource/Acl/RuleTest.php @@ -0,0 +1,74 @@ +<?php +/** + * Test for Mage_Webapi_Model_Resource_Acl_Rule + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * + * @magentoDataFixture Mage/Webapi/_files/role_with_rule.php + */ +class Mage_Webapi_Model_Resource_Acl_RuleTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Magento_Test_ObjectManager + */ + protected $_objectManager; + + /** + * @var Mage_Webapi_Model_Resource_Acl_Rule + */ + protected $_ruleResource; + + protected function setUp() + { + $this->_objectManager = Mage::getObjectManager(); + $this->_ruleResource = $this->_objectManager->get('Mage_Webapi_Model_Resource_Acl_Rule'); + } + + protected function tearDown() + { + unset($this->_objectManager, $this->_ruleResource); + } + + /** + * Test for Mage_Webapi_Model_Resource_Acl_Role::getRolesIds() + */ + public function testGetRuleList() + { + /** @var Mage_Webapi_Model_Acl_Role $role */ + $role = $this->_objectManager->create('Mage_Webapi_Model_Acl_Role')->load('Test role', 'role_name'); + $allowResourceId = 'customer/get'; + $rules = $this->_ruleResource->getRuleList(); + $this->assertCount(1, $rules); + $this->assertEquals($allowResourceId, $rules[0]['resource_id']); + $this->assertEquals($role->getId(), $rules[0]['role_id']); + } + + /** + * Test for Mage_Webapi_Model_Resource_Acl_Role::getResourceIdsByRole() + */ + public function testGetResourceIdsByRole() + { + /** @var Mage_Webapi_Model_Acl_Role $role */ + $role = $this->_objectManager->create('Mage_Webapi_Model_Acl_Role')->load('Test role', 'role_name'); + $this->assertEquals(array('customer/get'), $this->_ruleResource->getResourceIdsByRole($role->getId())); + } +} diff --git a/dev/tests/integration/testsuite/Mage/Webapi/Model/Soap/AutoDiscoverTest.php b/dev/tests/integration/testsuite/Mage/Webapi/Model/Soap/AutoDiscoverTest.php new file mode 100644 index 0000000000000000000000000000000000000000..0073f1d12d6f1915e95a6c24475ad0d8a11baaa9 --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/Model/Soap/AutoDiscoverTest.php @@ -0,0 +1,532 @@ +<?php +use Zend\Soap\Wsdl; + +/** + * SOAP AutoDiscover integration tests. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/**#@+ + * Data structures should be available without auto loader as the file name cannot be calculated from class name. + */ +include __DIR__ . '/../../_files/Model/Webapi/ModuleB/Subresource/SubresourceData.php'; +include __DIR__ . '/../../_files/Model/Webapi/ModuleB/ModuleBData.php'; +include __DIR__ . '/../../_files/Controller/AutoDiscover/ModuleB.php'; +/**#@-*/ + +/** + * Class for {@see Mage_Webapi_Model_Soap_AutoDiscover} model testing. + */ +class Mage_Webapi_Model_Soap_AutoDiscoverTest extends PHPUnit_Framework_TestCase +{ + /** @var Mage_Webapi_Model_Config_Soap */ + protected $_config; + + /** @var Mage_Webapi_Model_Soap_AutoDiscover */ + protected $_autoDiscover; + + /** @var Mage_Webapi_Helper_Config */ + protected $_helper; + + /** + * Name of the resource under the test. + * + * @var string + */ + protected $_resourceName; + + /** + * Resource under the test data from config. + * + * @var array + */ + protected $_resourceData; + + /** + * DOMDocument containing generated WSDL. + * + * @var DOMDocument + */ + protected $_dom; + + /** + * DOMXpath containing generated WSDL DOM. + * + * @var DOMXPath + */ + protected $_xpath; + + /** + * Set up config with fixture controllers directory scanner + */ + protected function setUp() + { + $fixtureDir = __DIR__ . '/../../_files/Controller/AutoDiscover/'; + $directoryScanner = new \Zend\Code\Scanner\DirectoryScanner($fixtureDir); + /** @var Mage_Core_Model_App $app */ + $app = $this->getMockBuilder('Mage_Core_Model_App')->disableOriginalConstructor()->getMock(); + $objectManager = new Magento_Test_ObjectManager(); + $this->_helper = $objectManager->get('Mage_Webapi_Helper_Config'); + $reader = $objectManager->get('Mage_Webapi_Model_Config_Reader_Soap'); + $reader->setDirectoryScanner($directoryScanner); + $this->_config = new Mage_Webapi_Model_Config_Soap($reader, $this->_helper, $app); + $objectManager->addSharedInstance($this->_config, 'Mage_Webapi_Model_Config_Soap'); + $wsdlFactory = new Mage_Webapi_Model_Soap_Wsdl_Factory($objectManager); + $cache = $this->getMockBuilder('Mage_Core_Model_Cache')->disableOriginalConstructor()->getMock(); + $this->_autoDiscover = new Mage_Webapi_Model_Soap_AutoDiscover( + $this->_config, + $wsdlFactory, + $this->_helper, + $cache + ); + + $this->_resourceName = 'vendorModuleB'; + $this->_resourceData = $this->_config->getResourceDataMerged($this->_resourceName, 'v1'); + $xml = $this->_autoDiscover->generate(array($this->_resourceName => $this->_resourceData), + 'http://magento.host/api/soap'); + $this->_dom = new DOMDocument('1.0', 'utf-8'); + $this->_dom->loadXML($xml); + $this->_xpath = new DOMXPath($this->_dom); + $this->_xpath->registerNamespace(Wsdl::WSDL_NS, Wsdl::WSDL_NS_URI); + + parent::setUp(); + } + + /** + * Test WSDL operations Generation. + * Generate WSDL XML using AutoDiscover and prepared config. + * Walk through all methods from "vendorModuleB resource" (_files/controllers/AutoDiscover/ModuleBController.php) + * Assert that service, portType and binding has been generated correctly for resource. + * Assert that each method from controller has generated operations in portType and binding nodes. + * Assert that each method has input and output messages and complexTypes generated correctly. + */ + public function testGenerateOperations() + { + $this->_assertServiceNode(); + $binding = $this->_assertBinding(); + $portType = $this->_assertPortType(); + + foreach ($this->_resourceData['methods'] as $methodName => $methodData) { + $operationName = $this->_autoDiscover->getOperationName($this->_resourceName, $methodName); + $this->_assertBindingOperation($operationName, $binding); + $portOperation = $this->_assertPortTypeOperation($operationName, $portType); + // Assert portType operation input + /** @var DOMElement $operationInput */ + $operationInput = $portOperation->getElementsByTagName('input')->item(0); + $this->assertNotNull($operationInput, sprintf('"input" node was not found in "%s" port operation.', + $operationName)); + $messageName = $this->_autoDiscover->getInputMessageName($operationName); + $operationRequest = $this->_assertMessage($operationInput, $messageName, $methodData['documentation']); + if (isset($methodData['interface']['in'])) { + foreach ($methodData['interface']['in']['parameters'] as $parameterName => $parameterData) { + $expectedAppinfo = array( + 'callInfo' => array( + $operationName => array( + 'requiredInput' => $parameterData['required'] ? 'Yes' : 'No' + ) + ), + ); + $this->_assertParameter($parameterName, $parameterData['type'], $parameterData['required'], + $parameterData['documentation'], $expectedAppinfo, $operationRequest); + } + } + // Assert portType operation output + if (isset($methodData['interface']['out'])) { + /** @var DOMElement $operationOutput */ + $operationOutput = $portOperation->getElementsByTagName('output')->item(0); + $this->assertNotNull($operationOutput, sprintf('"output" node was not found in "%s" port operation.', + $operationName)); + $messageName = $this->_autoDiscover->getInputMessageName($operationName); + $expectedDoc = sprintf('Response container for the %s call.', $operationName); + $operationResponse = $this->_assertMessage($operationOutput, $messageName, $expectedDoc); + foreach ($methodData['interface']['out']['parameters'] as $parameterName => $parameterData) { + $expectedAppinfo = array( + 'callInfo' => array( + $operationName => array( + 'returned' => $parameterData['required'] ? 'Always' : 'Conditionally' + ), + ), + ); + $this->_assertParameter($parameterName, $parameterData['type'], $parameterData['required'], + $parameterData['documentation'], $expectedAppinfo, $operationResponse); + } + } + } + } + + /** + * Test that complexType for Data structures has been generated correctly in WSDL. + * See /_files/controllers/AutoDiscover/ModuleB/SubresourceData.php + */ + public function testGenerateDataStructureComplexTypes() + { + $wsdlNs = Wsdl::WSDL_NS; + $xsdNs = Wsdl::XSD_NS; + + // Generated from Vendor_ModuleB_Model_Webapi_ModuleBData class. + $dataStructureName = 'VendorModuleBData'; + $typeData = $this->_config->getTypeData($dataStructureName); + $complexTypeXpath = "//{$wsdlNs}:types/{$xsdNs}:schema/{$xsdNs}:complexType[@name='%s']"; + /** @var DOMElement $dataStructure */ + $dataStructure = $this->_xpath->query(sprintf($complexTypeXpath, $dataStructureName))->item(0); + $this->assertNotNull($dataStructure, sprintf('Complex type for data structure "%s" was not found in WSDL.', + $dataStructureName)); + $this->_assertDocumentation($typeData['documentation'], $dataStructure); + // Expected appinfo tags. + $expectedAppinfo = include __DIR__ . '/../../_files/Controller/annotation_fixture.php'; + + foreach ($typeData['parameters'] as $parameterName => $parameterData) { + // remove all appinfo placeholders from expected doc. + $expectedDoc = trim(preg_replace('/(\{.*\}|\\r)/U', '', $parameterData['documentation'])); + $this->_assertParameter($parameterName, $parameterData['type'], $parameterData['required'], + $expectedDoc, $expectedAppinfo[$parameterName], $dataStructure); + } + } + + /** + * Assert parameter data. + * + * @param string $expectedName + * @param string $expectedType + * @param string $expectedIsRequired + * @param string $expectedDoc + * @param array $expectedAppinfo + * @param DOMElement $complexType with actual parameter element. + */ + protected function _assertParameter($expectedName, $expectedType, $expectedIsRequired, $expectedDoc, + $expectedAppinfo, DOMElement $complexType + ) { + $xsdNs = Wsdl::XSD_NS; + $tns = Wsdl::TYPES_NS; + /** @var DOMElement $parameterElement */ + $parameterElement = $this->_xpath->query("{$xsdNs}:sequence/{$xsdNs}:element[@name='{$expectedName}']", + $complexType)->item(0); + $this->assertNotNull($parameterElement, sprintf('"%s" element was not found in complex type "%s".', + $expectedName, $complexType->getAttribute('name'))); + $isArray = $this->_helper->isArrayType($expectedType); + if ($isArray) { + $expectedType = $this->_helper->translateArrayTypeName($expectedType); + } else { + $this->assertEquals($expectedIsRequired ? 1 : 0, $parameterElement->getAttribute('minOccurs')); + $this->assertEquals(1, $parameterElement->getAttribute('maxOccurs')); + } + $expectedNs = $this->_helper->isTypeSimple($expectedType) ? $xsdNs : $tns; + $this->assertEquals("{$expectedNs}:{$expectedType}", $parameterElement->getAttribute('type')); + $this->_assertDocumentation($expectedDoc, $parameterElement); + $this->_assertAppinfo($expectedAppinfo, $parameterElement); + } + + /** + * Assert appinfo nodes in given element. + * + * @param array $expectedAppinfo + * @param DOMElement $element with actual appinfo node + */ + protected function _assertAppinfo($expectedAppinfo, DOMElement $element) + { + $xsdNs = Wsdl::XSD_NS; + $infNs = Mage_Webapi_Model_Soap_Wsdl_ComplexTypeStrategy_ConfigBased::APP_INF_NS; + /** @var DOMElement $appInfoNode */ + $appInfoNode = $this->_xpath->query("{$xsdNs}:annotation/{$xsdNs}:appinfo", $element)->item(0); + $elementName = $element->getAttribute('name'); + $this->assertNotNull($appInfoNode, sprintf('"appinfo" node not found in "%s" element.', $elementName)); + + foreach ($expectedAppinfo as $appInfoKey => $appInfoData) { + switch ($appInfoKey) { + case 'callInfo': + $this->_assertCallInfo($appInfoNode, $appInfoData); + break; + case 'seeLink': + $this->_assertSeeLink($appInfoNode, $appInfoData); + break; + case 'docInstructions': + $this->_assertDocInstructions($appInfoNode, $appInfoData); + break; + default: + $tagNode = $this->_xpath->query($infNs . ':' . $appInfoKey, $appInfoNode)->item(0); + $this->assertNotNull($tagNode, sprintf('Appinfo node "%s" was not found in element "%s"', + $appInfoKey, $elementName)); + $this->assertEquals($appInfoData, $tagNode->nodeValue, sprintf('Appinfo node "%s" is not correct.', + $appInfoKey)); + break; + } + } + } + + /** + * Assert docInstructions appinfo node and it's subnodes. + * + * @param DOMElement $appInfoNode + * @param array $appInfoData + */ + protected function _assertDocInstructions(DOMElement $appInfoNode, array $appInfoData) + { + $infNs = Mage_Webapi_Model_Soap_Wsdl_ComplexTypeStrategy_ConfigBased::APP_INF_NS; + $elementName = $appInfoNode->parentNode->parentNode->getAttribute('name'); + /** @var DOMElement $docInstructionsNode */ + $docInstructionsNode = $this->_xpath->query("{$infNs}:docInstructions", $appInfoNode)->item(0); + $this->assertNotNull($docInstructionsNode, + sprintf('"docInstructions" node was not found in "%s" element appinfo.', $elementName)); + foreach ($appInfoData as $direction => $value) { + /** @var DOMElement $subNode */ + $subNode = $this->_xpath->query("{$infNs}:{$direction}/{$infNs}:{$value}", $docInstructionsNode)->item(0); + $this->assertNotNull($subNode, + sprintf('"%s/%s" node was not found in "%s" element appinfo "docInstructions".', + $direction, $value, $elementName)); + } + } + + /** + * Assert 'seeLink' annotation node and it's subnodes. + * + * @param DOMElement $appInfoNode + * @param array $appInfoData + */ + protected function _assertSeeLink(DOMElement $appInfoNode, array $appInfoData) + { + $infNs = Mage_Webapi_Model_Soap_Wsdl_ComplexTypeStrategy_ConfigBased::APP_INF_NS; + $elementName = $appInfoNode->parentNode->parentNode->getAttribute('name'); + /** @var DOMElement $seeLinkNode */ + $seeLinkNode = $this->_xpath->query("{$infNs}:seeLink", $appInfoNode)->item(0); + $this->assertNotNull($seeLinkNode, sprintf('"seeLink" node was not found in "%s" element appinfo.', + $elementName)); + foreach (array('url', 'title', 'for') as $subNodeName) { + if (isset($appInfoData[$subNodeName])) { + /** @var DOMElement $subNode */ + $subNodeValue = $appInfoData[$subNodeName]; + $subNode = $this->_xpath->query("{$infNs}:{$subNodeName}[text()='{$subNodeValue}']", $seeLinkNode) + ->item(0); + $this->assertNotNull($subNode, + sprintf('"%s" node with value "%s" was not found in "%s" element appinfo "seeLink".', + $subNodeName, $subNodeValue, $elementName)); + } + } + } + + /** + * Assert 'callInfo' annotation node and it's subnodes. + * + * @param DOMElement $appInfoNode + * @param array $appInfoData + */ + protected function _assertCallInfo(DOMElement $appInfoNode, array $appInfoData) + { + $infNs = Mage_Webapi_Model_Soap_Wsdl_ComplexTypeStrategy_ConfigBased::APP_INF_NS; + $elementName = $appInfoNode->parentNode->parentNode->getAttribute('name'); + foreach ($appInfoData as $callName => $callData) { + if ($callName == 'allCallsExcept') { + /** @var DOMElement $callNode */ + $callNode = $this->_xpath + ->query("{$infNs}:callInfo/{$infNs}:allCallsExcept[text()='{$callData['calls']}']", $appInfoNode) + ->item(0); + $this->assertNotNull($callNode, + sprintf('allCallsExcept node for call "%s" was not found in element "%s" appinfo.', + $callData['calls'], $elementName)); + } else { + /** @var DOMElement $callNameNode */ + $callNode = $this->_xpath->query("{$infNs}:callInfo/{$infNs}:callName[text()='{$callName}']", + $appInfoNode)->item(0); + $this->assertNotNull($callNode, + sprintf('callName node for call "%s" was not found in element "%s" appinfo.', $callName, + $elementName)); + } + if (isset($callData['requiredInput'])) { + $direction = 'requiredInput'; + $condition = $callData['requiredInput']; + } else { + $direction = 'returned'; + $condition = $callData['returned']; + } + $conditionNode = $this->_xpath->query("{$infNs}:{$direction}[text()='{$condition}']", $callNode->parentNode) + ->item(0); + $this->assertNotNull($conditionNode, + sprintf('"%s" node with value "%s" not found for callName "%s" in element "%s"', $direction, + $condition, $callName, $elementName)); + } + } + + /** + * Assert that given complex type has correct documentation node. + * + * @param string $expectedDoc + * @param DOMElement $element + */ + protected function _assertDocumentation($expectedDoc, DOMElement $element) + { + $elementName = $element->getAttribute('name'); + $xsdNs = Wsdl::XSD_NS; + /** @var DOMElement $documentation */ + $documentation = $this->_xpath->query("{$xsdNs}:annotation/{$xsdNs}:documentation", $element)->item(0); + $this->assertNotNull($documentation, + sprintf('"annotation/documentation" node was not found inside "%s" element.', $elementName)); + $this->assertEquals($expectedDoc, $documentation->nodeValue, + sprintf('"documentation" node value is incorrect in "%s" element.', $elementName)); + } + + /** + * Assert operation message (input/output) and that message node is present in WSDL + * + * @param DOMElement $operationMessage + * @param $methodName + * @param $expectedDoc + * @return DOMElement + */ + protected function _assertMessage(DOMElement $operationMessage, $methodName, $expectedDoc) + { + $wsdlNs = Wsdl::WSDL_NS; + $tns = Wsdl::TYPES_NS; + $xsdNs = Wsdl::XSD_NS; + + $this->assertTrue($operationMessage->hasAttribute('message')); + $messageName = str_replace("{$tns}:", '', $operationMessage->getAttribute('message')); + $this->assertEquals(Wsdl::TYPES_NS . ':' . $messageName, + $operationMessage->getAttribute('message')); + $messageTypeName = $this->_autoDiscover->getElementComplexTypeName($messageName); + $complexTypeXpath = "//{$wsdlNs}:types/{$xsdNs}:schema/{$xsdNs}:complexType[@name='%s']"; + /** @var DOMElement $messageComplexType */ + $messageComplexType = $this->_xpath->query(sprintf($complexTypeXpath, $messageTypeName))->item(0); + $this->assertNotNull($messageComplexType, + sprintf('Complex type for "%s" operation was not found in WSDL.', $methodName)); + $this->_assertDocumentation($expectedDoc, $messageComplexType); + + /** @var DOMElement $message */ + $expression = "//{$wsdlNs}:message[@name='{$messageName}']"; + $message = $this->_xpath->query($expression)->item(0); + $this->assertNotNull($message, sprintf('Message "%s" not found in WSDL.', $messageName)); + $partXpath = "{$wsdlNs}:part[@element='{$tns}:{$messageName}']"; + $messagePart = $this->_xpath->query($partXpath, $message)->item(0); + $this->assertNotNull($messagePart, sprintf('Message part not found in "%s".', $messageName)); + + return $messageComplexType; + } + + /** + * Assert operation is present in portType node and return it. + * + * @param $operationName + * @param DOMElement $portType + * @return DOMElement + */ + protected function _assertPortTypeOperation($operationName, DOMElement $portType) + { + $operationXpath = sprintf('%s:operation[@name="%s"]', Wsdl::WSDL_NS, $operationName); + /** @var DOMElement $portOperation */ + $portOperation = $this->_xpath->query($operationXpath, $portType)->item(0); + $this->assertNotNull($portOperation, sprintf('Operation "%s" was not found in portType "%s".', + $operationName, $this->_autoDiscover->getPortTypeName($this->_resourceName))); + return $portOperation; + } + + /** + * Assert operation is present in binding node. + * + * @param string $operationName + * @param DOMElement $binding + */ + protected function _assertBindingOperation($operationName, DOMElement $binding) + { + $operationXpath = sprintf('%s:operation[@name="%s"]', Wsdl::WSDL_NS, $operationName); + /** @var DOMElement $bindingOperation */ + $bindingOperation = $this->_xpath->query($operationXpath, $binding)->item(0); + $this->assertNotNull($bindingOperation, sprintf('Operation "%s" was not found in binding "%s".', + $operationName, $this->_autoDiscover->getBindingName($this->_resourceName))); + } + + /** + * Assert binding node is present and return it. + * + * @return DOMElement + */ + protected function _assertBinding() + { + $bindings = $this->_dom->getElementsByTagNameNS(Wsdl::WSDL_NS_URI, 'binding'); + $this->assertEquals(1, $bindings->length, 'There should be only one binding in this test case.'); + /** @var DOMElement $binding */ + $binding = $bindings->item(0); + $this->assertTrue($binding->hasAttribute('name')); + $bindingName = $this->_autoDiscover->getBindingName($this->_resourceName); + $this->assertEquals($bindingName, $binding->getAttribute('name')); + $this->assertTrue($binding->hasAttribute('type')); + $portTypeName = $this->_autoDiscover->getPortTypeName($this->_resourceName); + $this->assertEquals(Wsdl::TYPES_NS . ':' . $portTypeName, + $binding->getAttribute('type')); + /** @var DOMElement $soapBinding */ + $soapBinding = $binding->getElementsByTagNameNS(Wsdl::SOAP_12_NS_URI, 'binding') + ->item(0); + $this->assertNotNull($soapBinding, sprintf('Missing soap binding in "%s"', $bindingName)); + $this->assertTrue($soapBinding->hasAttribute('style')); + $this->assertEquals('document', $soapBinding->getAttribute('style')); + + return $binding; + } + + /** + * Assert port type node is present and return it. + * + * @return DOMElement + */ + protected function _assertPortType() + { + $portTypes = $this->_dom->getElementsByTagNameNs(Wsdl::WSDL_NS_URI, 'portType'); + $this->assertEquals(1, $portTypes->length, 'There should be only one portType in this test case.'); + /** @var DOMElement $portType */ + $portType = $portTypes->item(0); + $this->assertTrue($portType->hasAttribute('name')); + $expectedName = $this->_autoDiscover->getPortTypeName($this->_resourceName); + $this->assertEquals($expectedName, $portType->getAttribute('name')); + + return $portType; + } + + /** + * Assert port node is present within service node. + * + * @param DOMElement $service + */ + protected function _assertPortNode($service) + { + /** @var DOMElement $port */ + $port = $service->getElementsByTagName('port')->item(0); + $this->assertNotNull($port, 'port node not found within service node.'); + $this->assertTrue($port->hasAttribute('name')); + $this->assertEquals($this->_autoDiscover->getPortName($this->_resourceName), $port->getAttribute('name')); + $bindingName = $this->_autoDiscover->getBindingName($this->_resourceName); + $this->assertEquals(Wsdl::TYPES_NS . ':' . $bindingName, $port->getAttribute('binding')); + } + + /** + * Assert service node is present in xml. + * + * @return DOMElement + */ + protected function _assertServiceNode() + { + /** @var DOMElement $service */ + $service = $this->_dom->getElementsByTagNameNS(Wsdl::WSDL_NS_URI, 'service')->item(0); + $this->assertNotNull($service, 'service node not found in WSDL.'); + $this->assertTrue($service->hasAttribute('name')); + $this->assertEquals($this->_autoDiscover->getServiceName($this->_resourceName), $service->getAttribute('name')); + + $this->_assertPortNode($service, $this->_resourceName); + } +} diff --git a/dev/tests/integration/testsuite/Mage/Webapi/Model/Soap/Security/UsernameTokenTest.php b/dev/tests/integration/testsuite/Mage/Webapi/Model/Soap/Security/UsernameTokenTest.php new file mode 100644 index 0000000000000000000000000000000000000000..f39d3b5babb9dd0ec6793d83f62f745d8317d1d6 --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/Model/Soap/Security/UsernameTokenTest.php @@ -0,0 +1,116 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Webapi + * @subpackage integration_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * @magentoDataFixture Mage/Webapi/_files/user_with_role.php + */ +class Mage_Webapi_Model_Soap_Security_UsernameTokenTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Magento_Test_ObjectManager + */ + protected $_objectManager; + + /** @var Mage_Webapi_Model_Acl_User_Factory */ + protected $_userFactory; + + /** + * Set up object manager and user factory. + */ + protected function setUp() + { + $this->_objectManager = new Magento_Test_ObjectManager(); + $this->_userFactory = new Mage_Webapi_Model_Acl_User_Factory($this->_objectManager); + } + + /** + * Clean up. + */ + protected function tearDown() + { + unset($this->_objectManager); + unset($this->_userFactory); + } + + /** + * Test positive authenticate with text password type. + */ + public function testAuthenticatePasswordText() + { + $user = $this->_userFactory->create(); + $user->load('test_username', 'api_key'); + /** @var Mage_Webapi_Model_Soap_Security_UsernameToken $usernameToken */ + $usernameToken = $this->_objectManager->create('Mage_Webapi_Model_Soap_Security_UsernameToken', array( + 'passwordType' => Mage_Webapi_Model_Soap_Security_UsernameToken::PASSWORD_TYPE_TEXT + )); + + $created = date('c'); + $nonce = base64_encode(mt_rand()); + $authenticatedUser = $usernameToken->authenticate($user->getApiKey(), $user->getSecret(), $created, $nonce); + $this->assertEquals($user->getRoleId(), $authenticatedUser->getRoleId()); + } + + /** + * Test positive authenticate with digest password type + */ + public function testAuthenticatePasswordDigest() + { + $user = $this->_userFactory->create(); + $user->load('test_username', 'api_key'); + /** @var Mage_Webapi_Model_Soap_Security_UsernameToken $usernameToken */ + $usernameToken = $this->_objectManager->create('Mage_Webapi_Model_Soap_Security_UsernameToken'); + + $created = date('c'); + $nonce = mt_rand(); + $password = base64_encode(hash('sha1', $nonce . $created . $user->getSecret(), true)); + $nonce = base64_encode($nonce); + $authenticatedUser = $usernameToken->authenticate($user->getApiKey(), $password, $created, $nonce); + $this->assertEquals($user->getRoleId(), $authenticatedUser->getRoleId()); + } + + /** + * Test negative authentication with used nonce-timestamp pair. + * + * @expectedException Mage_Webapi_Model_Soap_Security_UsernameToken_NonceUsedException + */ + public function testAuthenticateWithNonceUsed() + { + $user = $this->_userFactory->create(); + $user->load('test_username', 'api_key'); + /** @var Mage_Webapi_Model_Soap_Security_UsernameToken $usernameToken */ + $usernameToken = $this->_objectManager->create('Mage_Webapi_Model_Soap_Security_UsernameToken'); + + $created = date('c'); + $nonce = mt_rand(); + $password = base64_encode(hash('sha1', $nonce . $created . $user->getSecret(), true)); + $nonce = base64_encode($nonce); + $authenticatedUser = $usernameToken->authenticate($user->getApiKey(), $password, $created, $nonce); + $this->assertEquals($user, $authenticatedUser); + // Try to authenticate with the same nonce and timestamp + $usernameToken->authenticate($user->getApiKey(), $password, $created, $nonce); + } +} diff --git a/dev/tests/integration/testsuite/Mage/Webapi/Model/Soap/ServerTest.php b/dev/tests/integration/testsuite/Mage/Webapi/Model/Soap/ServerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..cc849dde3ca5d9fe0bbdfa999882c0bc6231097a --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/Model/Soap/ServerTest.php @@ -0,0 +1,98 @@ +<?php +/** + * Test Soap server model. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Soap_ServerTest extends PHPUnit_Framework_TestCase +{ + /** @var Mage_Core_Model_App */ + protected $_applicationMock; + + /** @var Mage_Webapi_Controller_Request_Soap */ + protected $_requestMock; + + /** @var Magento_DomDocument_Factory */ + protected $_domDocumentFactory; + + /** @var Mage_Core_Model_Store */ + protected $_storeMock; + + protected function setUp() + { + /** Init all dependencies for SUT. */ + $this->_storeMock = $this->getMockBuilder('Mage_Core_Model_Store')->disableOriginalConstructor()->getMock(); + $this->_applicationMock = $this->getMockBuilder('Mage_Core_Model_App')->disableOriginalConstructor()->getMock(); + $this->_applicationMock->expects($this->any())->method('getStore')->will($this->returnValue($this->_storeMock)); + $this->_requestMock = $this->getMockBuilder('Mage_Webapi_Controller_Request_Soap')->disableOriginalConstructor() + ->getMock(); + $this->_domDocumentFactory = $this->getMockBuilder('Magento_DomDocument_Factory') + ->disableOriginalConstructor()->getMock(); + + parent::setUp(); + } + + protected function tearDown() + { + unset($this->_applicationMock); + unset($this->_requestMock); + unset($this->_domDocumentFactory); + unset($this->_storeMock); + parent::tearDown(); + } + + /** + * Test Soap server construction with WSDL cache enabling. + */ + public function testConstructEnableWsdlCache() + { + /** Mock getConfig method to return true. */ + $this->_storeMock->expects($this->any())->method('getConfig')->will($this->returnValue(true)); + /** Create Soap server object. */ + $server = new Mage_Webapi_Model_Soap_Server( + $this->_applicationMock, + $this->_requestMock, + $this->_domDocumentFactory + ); + $server->initWsdlCache(); + /** Assert soap wsdl caching option was enabled after soap server initialization. */ + $this->assertTrue((bool)ini_get('soap.wsdl_cache_enabled'), 'WSDL caching was not enabled.'); + } + + /** + * Test Soap server construction with WSDL cache disabling. + */ + public function testConstructDisableWsdlCache() + { + /** Mock getConfig method to return false. */ + $this->_storeMock->expects($this->any())->method('getConfig')->will($this->returnValue(false)); + /** Create Soap server object. */ + $server = new Mage_Webapi_Model_Soap_Server( + $this->_applicationMock, + $this->_requestMock, + $this->_domDocumentFactory + ); + $server->initWsdlCache(); + /** Assert soap wsdl caching option was disabled after soap server initialization. */ + $this->assertFalse((bool)ini_get('soap.wsdl_cache_enabled'), 'WSDL caching was not disabled.'); + } +} diff --git a/dev/tests/integration/testsuite/Mage/Webapi/Model/_files/autodiscovery/empty_property_description/class.php b/dev/tests/integration/testsuite/Mage/Webapi/Model/_files/autodiscovery/empty_property_description/class.php new file mode 100644 index 0000000000000000000000000000000000000000..b9c0d8176260305c88634fd4137a856ec9f90398 --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/Model/_files/autodiscovery/empty_property_description/class.php @@ -0,0 +1,36 @@ +<?php +/** + * Tests fixture for Auto Discovery functionality. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ +class Vendor_Module_Controller_Webapi_Empty_Property_Description +{ + /** + * @param Vendor_Module_Model_Webapi_Property_Empty_Description $data + */ + public function createV1($data) + { + // Body is intentionally left empty + } +} diff --git a/dev/tests/integration/testsuite/Mage/Webapi/Model/_files/autodiscovery/empty_property_description/data_type.php b/dev/tests/integration/testsuite/Mage/Webapi/Model/_files/autodiscovery/empty_property_description/data_type.php new file mode 100644 index 0000000000000000000000000000000000000000..3b9f6dc6d2b21d469b4acd02005f25eebec3229c --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/Model/_files/autodiscovery/empty_property_description/data_type.php @@ -0,0 +1,32 @@ +<?php +/** + * Tests fixture for Auto Discovery functionality. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Vendor_Module_Model_Webapi_Property_Empty_Description +{ + public $noDescription; + + /** @var int */ + public $validProperty; +} diff --git a/dev/tests/integration/testsuite/Mage/Webapi/Model/_files/autodiscovery/empty_var_tags/class.php b/dev/tests/integration/testsuite/Mage/Webapi/Model/_files/autodiscovery/empty_var_tags/class.php new file mode 100644 index 0000000000000000000000000000000000000000..9f002c615aca45a0d75e5c6d9bcec04d3b1f9853 --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/Model/_files/autodiscovery/empty_var_tags/class.php @@ -0,0 +1,36 @@ +<?php +/** + * Tests fixture for Auto Discovery functionality. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ +class Vendor_Module_Controller_Webapi_Empty_Var_Tag +{ + /** + * @param Vendor_Module_Model_Webapi_Property_Without_Var $data + */ + public function createV1($data) + { + // Body is intentionally left empty + } +} diff --git a/dev/tests/integration/testsuite/Mage/Webapi/Model/_files/autodiscovery/empty_var_tags/data_type.php b/dev/tests/integration/testsuite/Mage/Webapi/Model/_files/autodiscovery/empty_var_tags/data_type.php new file mode 100644 index 0000000000000000000000000000000000000000..0e758baaed92a00b8daf78ca81bcb706232bab7e --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/Model/_files/autodiscovery/empty_var_tags/data_type.php @@ -0,0 +1,35 @@ +<?php +/** + * Tests fixture for Auto Discovery functionality. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Vendor_Module_Model_Webapi_Property_Without_Var +{ + /** + * Property without var tag + */ + public $propertyWithoutVar; + + /** @var int */ + public $validProperty; +} diff --git a/dev/tests/integration/testsuite/Mage/Webapi/Model/_files/autodiscovery/invalid_deprecation_policy/class.php b/dev/tests/integration/testsuite/Mage/Webapi/Model/_files/autodiscovery/invalid_deprecation_policy/class.php new file mode 100644 index 0000000000000000000000000000000000000000..c9c42d9600fb02fcf2c1c1586d8481de05d39488 --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/Model/_files/autodiscovery/invalid_deprecation_policy/class.php @@ -0,0 +1,37 @@ +<?php +/** + * Tests fixture for Auto Discovery functionality. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ +class Invalid_Deprecation_Controller_Webapi_Policy +{ + /** + * @apiDeprecated resource::get + */ + public function getV1() + { + // Body was intentionally left empty + } +} + diff --git a/dev/tests/integration/testsuite/Mage/Webapi/Model/_files/autodiscovery/no_resources/class.php b/dev/tests/integration/testsuite/Mage/Webapi/Model/_files/autodiscovery/no_resources/class.php new file mode 100644 index 0000000000000000000000000000000000000000..e616cc98c66a883b1f8297eb5f626267c4be1559 --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/Model/_files/autodiscovery/no_resources/class.php @@ -0,0 +1,36 @@ +<?php +/** + * Tests fixture for Auto Discovery functionality. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ +class Invalid_Resource_Name +{ + /** + * @param int[] $data + */ + public function createV1($data) + { + // Body is intentionally left empty + } +} diff --git a/dev/tests/integration/testsuite/Mage/Webapi/Model/_files/autodiscovery/reference_to_invalid_type/class.php b/dev/tests/integration/testsuite/Mage/Webapi/Model/_files/autodiscovery/reference_to_invalid_type/class.php new file mode 100644 index 0000000000000000000000000000000000000000..02539ae427862ae9db53cfea3283f7d7a44099c1 --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/Model/_files/autodiscovery/reference_to_invalid_type/class.php @@ -0,0 +1,36 @@ +<?php +/** + * Tests fixture for Auto Discovery functionality. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ +class Vendor_Module_Controller_Webapi_Invalid_Type +{ + /** + * @param Not_Existing_Model_Webapi_Class $data + */ + public function createV1($data) + { + // Body is intentionally left empty + } +} diff --git a/dev/tests/integration/testsuite/Mage/Webapi/Model/_files/autodiscovery/several_classes_in_one_file/file_with_classes.php b/dev/tests/integration/testsuite/Mage/Webapi/Model/_files/autodiscovery/several_classes_in_one_file/file_with_classes.php new file mode 100644 index 0000000000000000000000000000000000000000..48ab1fd858b39d49d1ae4b91f62a3c13bae06d3a --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/Model/_files/autodiscovery/several_classes_in_one_file/file_with_classes.php @@ -0,0 +1,34 @@ +<?php +/** + * Tests fixture for Auto Discovery functionality. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class First_Class +{ + // Body was intentionally left empty +} + +class Second_Class +{ + // Body was intentionally left empty +} diff --git a/dev/tests/integration/testsuite/Mage/Webapi/Model/_files/resource_with_invalid_interface.php b/dev/tests/integration/testsuite/Mage/Webapi/Model/_files/resource_with_invalid_interface.php new file mode 100644 index 0000000000000000000000000000000000000000..e986c0485a2c3a384f2938d97dcf8bb3690b4854 --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/Model/_files/resource_with_invalid_interface.php @@ -0,0 +1,56 @@ +<?php +/** + * Tests fixture for Auto Discovery functionality. + * + * Fake resource controller with invalid interface. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ +class Vendor_Module_Controller_Webapi_Invalid_Interface +{ + /** + * @param int $resourceId + */ + public function updateV1($resourceId) + { + // Body is intentionally left empty + } + + public function updateV2() + { + // Body is intentionally left empty + } + + public function emptyInterfaceV2() + { + // Body is intentionally left empty + } + + /** + * @param int $resourceId + */ + public function invalidMethodNameV2($resourceId) + { + // Body is intentionally left empty + } +} diff --git a/dev/tests/integration/testsuite/Mage/Webapi/Model/_files/resource_with_invalid_name.php b/dev/tests/integration/testsuite/Mage/Webapi/Model/_files/resource_with_invalid_name.php new file mode 100644 index 0000000000000000000000000000000000000000..ab64482b18426d28ed80959cb5e0407b56fb9384 --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/Model/_files/resource_with_invalid_name.php @@ -0,0 +1,38 @@ +<?php +/** + * Tests fixture for Auto Discovery functionality. + * + * Fake resource controller with invalid name. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ +class Vendor_Module_Webapi_Resource_Invalid +{ + /** + * @param int $resourceId + */ + public function updateV1($resourceId) + { + // Body is intentionally left empty + } +} diff --git a/dev/tests/integration/testsuite/Mage/Webapi/_files/Controller/AutoDiscover/ModuleB.php b/dev/tests/integration/testsuite/Mage/Webapi/_files/Controller/AutoDiscover/ModuleB.php new file mode 100644 index 0000000000000000000000000000000000000000..dc1131086d862c8cf0d3cbd8d6251c7528eed7dd --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/_files/Controller/AutoDiscover/ModuleB.php @@ -0,0 +1,77 @@ +<?php +/** + * API Resource action controller fixture. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ +class Vendor_ModuleB_Controller_Webapi_ModuleB extends Mage_Webapi_Controller_ActionAbstract +{ + /** + * Short description. + * + * Long description. + * + * @param Vendor_ModuleB_Model_Webapi_ModuleBData $resourceData Data of the resource + * @param Vendor_ModuleB_Model_Webapi_ModuleB_SubresourceData $complexParam + * @return int ID of created resource + */ + public function createV1($resourceData, $complexParam = null) + { + + } + + /** + * Update description. + * + * Update short doc. + * + * @param int $resourceId + * @param Vendor_ModuleB_Model_Webapi_ModuleBData $resourceData + * @param bool $optionalParam + */ + public function updateV1($resourceId, $resourceData, $optionalParam = false) + { + + } + + /** + * Method without input parameters. + * + * @return Vendor_ModuleB_Model_Webapi_ModuleBData[] array of resources + */ + public function listV1() + { + + } + + /** + * Get resource operation. + * + * @param int $resourceId Resource ID. + * @return Vendor_ModuleB_Model_Webapi_ModuleBData + */ + public function getV1($resourceId) + { + + } +} diff --git a/dev/tests/integration/testsuite/Mage/Webapi/_files/Controller/Webapi/ModuleA.php b/dev/tests/integration/testsuite/Mage/Webapi/_files/Controller/Webapi/ModuleA.php new file mode 100644 index 0000000000000000000000000000000000000000..ed743aa5f311b3edaa8b9cc2984dde684cf42910 --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/_files/Controller/Webapi/ModuleA.php @@ -0,0 +1,75 @@ +<?php +/** + * API Resource action controller fixture. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ +class NamespaceA_ModuleA_Controller_Webapi_ModuleA extends Mage_Webapi_Controller_ActionAbstract +{ + /** + * Get resource v2. + * + * @param int $resourceId ID of resource + * @param string $newParameter new parameter in version 2 + * @return NamespaceA_ModuleA_Model_Webapi_ModuleAData data of resource + */ + public function getV2($resourceId, $newParameter) + { + + } + + /** + * Short description. + * Long description. + * Multiline <b>with html</b>. + * + * @param NamespaceA_ModuleA_Model_Webapi_ModuleAData $resourceData Data of the resource + * @return int ID of created resource + */ + public function createV1($resourceData) + { + + } + + /** + * Get resource. + * + * @param int $resourceId ID of resource + * @return NamespaceA_ModuleA_Model_Webapi_ModuleAData data of resource + */ + public function getV1($resourceId) + { + + } + + /** + * Get resource v3. + * + * @param string $v3param + * @return NamespaceA_ModuleA_Model_Webapi_ModuleAData data of resource + */ + public function getV3($v3param) + { + + } +} diff --git a/dev/tests/integration/testsuite/Mage/Webapi/_files/Controller/Webapi/SubresourceB.php b/dev/tests/integration/testsuite/Mage/Webapi/_files/Controller/Webapi/SubresourceB.php new file mode 100644 index 0000000000000000000000000000000000000000..f7eabaf1736f3d77ac3df7365e460fe033bfbce5 --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/_files/Controller/Webapi/SubresourceB.php @@ -0,0 +1,50 @@ +<?php +/** + * API Resource action controller fixture. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ +class NamespaceA_ModuleA_Controller_Webapi_ModuleA_SubresourceB extends Mage_Webapi_Controller_ActionAbstract +{ + /** + * Subresource description. + * + * @param int $subresourceId ID of subresource. + * @return NamespaceA_ModuleA_Model_Webapi_ModuleAData Data of resource + */ + public function getV1($subresourceId) + { + + } + + /** + * List description. + * + * @param int $parentId Id of parent resource + * @return NamespaceA_ModuleA_Model_Webapi_ModuleAData[] list of resources + */ + public function listV1($parentId) + { + + } +} diff --git a/dev/tests/integration/testsuite/Mage/Webapi/_files/Controller/annotation_fixture.php b/dev/tests/integration/testsuite/Mage/Webapi/_files/Controller/annotation_fixture.php new file mode 100644 index 0000000000000000000000000000000000000000..75efbdae3da333dea517f232b12166db11dddbf6 --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/_files/Controller/annotation_fixture.php @@ -0,0 +1,70 @@ +<?php +/** + * Annotations fixture for Vendor_ModuleB_Model_Webapi_ModuleBData class + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +return array( + 'stringParam' => array( + 'maxLength' => '255 chars.', + 'callInfo' => array( + 'vendorModuleBUpdate' => array('requiredInput' => 'Yes'), + 'vendorModuleBCreate' => array('requiredInput' => 'Conditionally'), + 'vendorModuleBGet' => array('returned' => 'Always'), + ), + ), + 'integerParam' => array( + 'default' => $typeData['parameters']['integerParam']['default'], + 'min' => 10, + 'max' => 100, + 'callInfo' => array( + 'vendorModuleBCreate' => array('requiredInput' => 'No'), + 'vendorModuleBUpdate' => array('requiredInput' => 'No'), + 'allCallsExcept' => array('calls' => 'vendorModuleBUpdate', 'requiredInput' => 'Yes'), + 'vendorModuleBGet' => array('returned' => 'Conditionally'), + ), + ), + 'optionalBool' => array( + 'default' => 'false', + 'summary' => 'this is summary', + 'seeLink' => array( + 'url' => 'http://google.com/', + 'title' => 'link title', + 'for' => 'link for', + ), + 'docInstructions' => array('output' => 'noDoc'), + 'callInfo' => array( + 'vendorModuleBCreate' => array('requiredInput' => 'No'), + 'vendorModuleBUpdate' => array('requiredInput' => 'No'), + 'vendorModuleBGet' => array('returned' => 'Conditionally'), + ), + ), + 'complexTypeArray' => array( + 'tagStatus' => 'some status', + 'natureOfType' => 'array', + 'callInfo' => array( + 'vendorModuleBCreate' => array('requiredInput' => 'No'), + 'vendorModuleBUpdate' => array('requiredInput' => 'No'), + 'vendorModuleBGet' => array('returned' => 'Conditionally'), + ), + ), +); diff --git a/dev/tests/integration/testsuite/Mage/Webapi/_files/Model/Webapi/ModuleA/ModuleAData.php b/dev/tests/integration/testsuite/Mage/Webapi/_files/Model/Webapi/ModuleA/ModuleAData.php new file mode 100644 index 0000000000000000000000000000000000000000..50aad5f8316199cab4d0720bdfa2c8a89a3a633d --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/_files/Model/Webapi/ModuleA/ModuleAData.php @@ -0,0 +1,59 @@ +<?php +/** + * Test data structure fixture + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class NamespaceA_ModuleA_Model_Webapi_ModuleAData +{ + /** + * String param. + * + * @var string inline doc. + */ + public $stringParam; + + /** + * Integer param. + * + * @var int + */ + public $integerParam; + + /** + * Optional string param. + * + * @var string + */ + public $optionalParam = 'default'; + + /** + * Recursive link to self. + * + * @var NamespaceA_ModuleA_Model_Webapi_ModuleAData + */ + public $linkToSelf; + + /** + * Recursive link to array of selves. + * + * @var NamespaceA_ModuleA_Model_Webapi_ModuleAData[] + */ + public $linkToArrayOfSelves; + + /** + * Link to complex type which has link to this type. + * + * @var NamespaceA_ModuleA_Model_Webapi_ModuleADataB + */ + public $loopLink; + + /** + * Link to array of loops + * + * @var NamespaceA_ModuleA_Model_Webapi_ModuleADataB[] + * @optional true + */ + public $loopArray; +} diff --git a/dev/tests/integration/testsuite/Mage/Webapi/_files/Model/Webapi/ModuleA/ModuleADataB.php b/dev/tests/integration/testsuite/Mage/Webapi/_files/Model/Webapi/ModuleA/ModuleADataB.php new file mode 100644 index 0000000000000000000000000000000000000000..b4d4dd551d4419d98b197d0850cc295d5414ec17 --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/_files/Model/Webapi/ModuleA/ModuleADataB.php @@ -0,0 +1,23 @@ +<?php +/** + * Test data structure fixture + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class NamespaceA_ModuleA_Model_Webapi_ModuleADataB +{ + /** + * Loop back to complex type. + * + * @var NamespaceA_ModuleA_Model_Webapi_ModuleAData + */ + public $loopBack; + + /** + * Loop back to complex type. + * + * @var NamespaceA_ModuleA_Model_Webapi_ModuleAData[] + */ + public $loopBackArray; +} diff --git a/dev/tests/integration/testsuite/Mage/Webapi/_files/Model/Webapi/ModuleB/ModuleBData.php b/dev/tests/integration/testsuite/Mage/Webapi/_files/Model/Webapi/ModuleB/ModuleBData.php new file mode 100644 index 0000000000000000000000000000000000000000..37eb8143a318e4c62f4fa106359166fcb501e263 --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/_files/Model/Webapi/ModuleB/ModuleBData.php @@ -0,0 +1,63 @@ +<?php +/** + * Data structure fixture. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Vendor_ModuleB_Model_Webapi_ModuleBData +{ + /** + * String doc. + * {callInfo:vendorModuleBCreate:requiredInput:conditionally} + * {maxLength:255 chars.} + * + * @var string + */ + public $stringParam; + + /** + * Integer doc. + * {min:10}{max:100} + * {callInfo:vendorModuleBGet:returned:Conditionally} + * + * @var int {callInfo:allCallsExcept(vendorModuleBUpdate):requiredInput:yes} + */ + public $integerParam = 5; + + /** + * Optional bool doc. + * {summary:this is summary} + * {seeLink:http://google.com/:link title:link for} + * {docInstructions:output:noDoc} + * + * @var bool + */ + public $optionalBool = false; + + /** + * {tagStatus:some status} + * + * @optional + * @var Vendor_ModuleB_Model_Webapi_ModuleB_SubresourceData[] + */ + public $complexTypeArray; +} diff --git a/dev/tests/integration/testsuite/Mage/Webapi/_files/Model/Webapi/ModuleB/Subresource/SubresourceData.php b/dev/tests/integration/testsuite/Mage/Webapi/_files/Model/Webapi/ModuleB/Subresource/SubresourceData.php new file mode 100644 index 0000000000000000000000000000000000000000..5949d546bd7134a62743cd2bfdcddab583e4d0fe --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/_files/Model/Webapi/ModuleB/Subresource/SubresourceData.php @@ -0,0 +1,35 @@ +<?php +/** + * Data structure fixture. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Vendor_ModuleB_Model_Webapi_ModuleB_SubresourceData +{ + /** + * Loop back to complex type. + * {docInstructions:input:noDoc} + * + * @var Vendor_ModuleB_Model_Webapi_ModuleBData + */ + public $complexTypeLoop; +} diff --git a/dev/tests/integration/testsuite/Mage/Webapi/_files/autodiscovery/resource_class_fixture.php b/dev/tests/integration/testsuite/Mage/Webapi/_files/autodiscovery/resource_class_fixture.php new file mode 100644 index 0000000000000000000000000000000000000000..e14e53402df2c8cf67bae6366a84984108b8b92d --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/_files/autodiscovery/resource_class_fixture.php @@ -0,0 +1,146 @@ +<?php +/** + * Tests fixture for Auto Discovery functionality. + * + * Fake resource controller. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ +class Vendor_Module_Controller_Webapi_Resource +{ + /** + * @param Vendor_Module_Model_Webapi_CustomerData[] $resourceData + * @param bool $requiredField + * @param string $optionalField + * @param int $secondOptional + * @return Vendor_Module_Model_Webapi_CustomerData + */ + public function createV1($resourceData, $requiredField, $optionalField = 'optionalField', $secondOptional = 1) + { + // Body is intentionally omitted + } + + /** + * @param int $resourceId + * @param Vendor_Module_Model_Webapi_CustomerData $resourceData + * @param float $additionalRequired + */ + public function updateV2($resourceId, $resourceData, $additionalRequired) + { + // Body is intentionally omitted + } + + /** + * @param int $resourceId + * @return Vendor_Module_Model_Webapi_CustomerData + */ + public function getV2($resourceId) + { + // Body is intentionally omitted + } + + /** + * @apiDeprecated vendorModuleResource::listV3 + * @param float $additionalRequired + * @param bool $optional + * @return Vendor_Module_Model_Webapi_CustomerData[] + */ + public function listV2($additionalRequired, $optional = false) + { + // Body is intentionally omitted + } + + public function listV3() + { + // Body is intentionally omitted + } + + /** + * @param int $deleteId The name of this parameter MUST be different from name used in get method. + * @apiRemoved deleteV3 + */ + public function deleteV1($deleteId) + { + // Body is intentionally omitted + } + + /** + * @param int $deleteId The name of this parameter MUST be different from name used in get method. + * @apiDeprecated Vendor_Module_Controller_Webapi_Resource_Subresource::deleteV3 + */ + public function deleteV2($deleteId) + { + // Body is intentionally omitted + } + + /** + * @apiDeprecated + * @apiRemoved + * @param int $deleteId The name of this parameter MUST be different from name used in get method. + */ + public function deleteV3($deleteId) + { + // Body is intentionally omitted + } + + /** + * @apiDeprecated + * @param int $deleteId The name of this parameter MUST be different from name used in get method. + */ + public function deleteV4($deleteId) + { + // Body is intentionally omitted + } + + /** + * @param int $deleteId The name of this parameter MUST be different from name used in get method. + */ + public function deleteV5($deleteId) + { + // Body is intentionally omitted + } + + /** + * @param Vendor_Module_Model_Webapi_CustomerData[] $resourceData + */ + public function multiUpdateV2($resourceData) + { + // Body is intentionally omitted + } + + /** + * @param int[] $idsToBeRemoved + */ + public function multiDeleteV2($idsToBeRemoved) + { + // Body is intentionally omitted + } + + /** + * Test situation of internal method, that should not be exposed through API. + */ + public function someMethodThatWillBeSkipped() + { + // Body is intentionally omitted + } +} diff --git a/app/code/core/Mage/Api/Model/Resource/Rules/Collection.php b/dev/tests/integration/testsuite/Mage/Webapi/_files/autodiscovery/subresource_class_fixture.php old mode 100755 new mode 100644 similarity index 50% rename from app/code/core/Mage/Api/Model/Resource/Rules/Collection.php rename to dev/tests/integration/testsuite/Mage/Webapi/_files/autodiscovery/subresource_class_fixture.php index 3c9fdd1a0fd28f4f06536ad1e59700cfa13c1e81..03e95383a9b092a18b593c2365ff21c5e14cff02 --- a/app/code/core/Mage/Api/Model/Resource/Rules/Collection.php +++ b/dev/tests/integration/testsuite/Mage/Webapi/_files/autodiscovery/subresource_class_fixture.php @@ -1,5 +1,9 @@ <?php /** + * Tests fixture for Auto Discovery functionality. + * + * Fake resource controller. + * * Magento * * NOTICE OF LICENSE @@ -18,52 +22,47 @@ * versions in the future. If you wish to customize Magento for your * needs please refer to http://www.magentocommerce.com for more information. * - * @category Mage - * @package Mage_Api * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - - -/** - * Api Rules Resource Collection - * - * @category Mage - * @package Mage_Api - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api_Model_Resource_Rules_Collection extends Mage_Core_Model_Resource_Db_Collection_Abstract +class Vendor_Module_Controller_Webapi_Resource_Subresource { /** - * Resource collection initialization - * + * @param int $param1 + * @param string $param2 + * @param Vendor_Module_Model_Webapi_CustomerData[] $param3 + * @param string $param4 + */ + public function createV1($param1, $param2, $param3 = array(), $param4 = 'default_value') + { + // Body is intentionally left empty + } + + /** + * @param int $param1 + * @param bool $param2 */ - protected function _construct() + public function createV2($param1, $param2) { - $this->_init('Mage_Api_Model_Rules', 'Mage_Api_Model_Resource_Rules'); + // Body is intentionally left empty } /** - * Retrieve rules by role - * - * @param int $id - * @return Mage_Api_Model_Resource_Rules_Collection + * @param int $param1 + * @param Vendor_Module_Model_Webapi_CustomerData $param2 */ - public function getByRoles($id) + public function updateV1($param1, $param2) { - $this->getSelect()->where("role_id = ?", (int)$id); - return $this; + // Body is intentionally left empty } /** - * Add sort by length - * - * @return Mage_Api_Model_Resource_Rules_Collection + * @param int $param1 + * @param float $param2 */ - public function addSortByLength() + public function updateV4($param1, $param2) { - $this->getSelect()->columns(array('length' => $this->getConnection()->getLengthSql('resource_id'))) - ->order('length DESC'); - return $this; + // Body is intentionally left empty } } diff --git a/dev/tests/integration/testsuite/Mage/Webapi/_files/config/data_structure_fixture.php b/dev/tests/integration/testsuite/Mage/Webapi/_files/config/data_structure_fixture.php new file mode 100644 index 0000000000000000000000000000000000000000..a90d159382f87e9fb9f4a13552cdae53ec1e2ca5 --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/_files/config/data_structure_fixture.php @@ -0,0 +1,73 @@ +<?php +/** + * Fixture of processed complex type class. + * Complex type class is at /_files/controllers/Webapi/ModuleA/SubresourceData.php + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +return array( + 'documentation' => 'Test data structure fixture', + 'parameters' => array( + 'stringParam' => array( + 'type' => 'string', + 'required' => true, + 'default' => null, + 'documentation' => 'inline doc.String param.', + ), + 'integerParam' => array( + 'type' => 'int', + 'required' => true, + 'default' => null, + 'documentation' => 'Integer param.', + ), + 'optionalParam' => array( + 'type' => 'string', + 'required' => false, + 'default' => 'default', + 'documentation' => 'Optional string param.', + ), + 'linkToSelf' => array( + 'type' => 'NamespaceAModuleAData', + 'required' => true, + 'default' => null, + 'documentation' => 'Recursive link to self.', + ), + 'linkToArrayOfSelves' => array( + 'type' => 'NamespaceAModuleAData[]', + 'required' => true, + 'default' => null, + 'documentation' => 'Recursive link to array of selves.', + ), + 'loopLink' => array( + 'type' => 'NamespaceAModuleADataB', + 'required' => true, + 'default' => null, + 'documentation' => 'Link to complex type which has link to this type.', + ), + 'loopArray' => array( + 'type' => 'NamespaceAModuleADataB[]', + 'required' => false, + 'default' => null, + 'documentation' => 'Link to array of loops', + ), + ), +); diff --git a/dev/tests/integration/testsuite/Mage/Webapi/_files/config/resource_a_fixture.php b/dev/tests/integration/testsuite/Mage/Webapi/_files/config/resource_a_fixture.php new file mode 100644 index 0000000000000000000000000000000000000000..6e38e8f0eee50d0dd1b9477de131ff6d5552fa70 --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/_files/config/resource_a_fixture.php @@ -0,0 +1,78 @@ +<?php +/** + * Fixture of processed API action controller for resource config. + * Controller files is at _files/controllers/Webapi/ResourceAController.php + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +return array( + 'methods' => array( + 'create' => array( + 'documentation' => "Short description. +Long description. +Multiline <b>with html</b>.", + 'interface' => array( + 'in' => array( + 'parameters' => array( + 'resourceData' => array( + 'type' => 'NamespaceAModuleAData', + 'required' => true, + 'documentation' => 'Data of the resource' + ) + ) + ), + 'out' => array( + 'parameters' => array( + 'result' => array( + 'type' => 'int', + 'documentation' => 'ID of created resource', + 'required' => true, + ) + ), + ), + ), + ), + 'get' => array( + 'documentation' => 'Get resource.', + 'interface' => array( + 'in' => array( + 'parameters' => array( + 'resourceId' => array( + 'type' => 'int', + 'required' => true, + 'documentation' => 'ID of resource' + ) + ) + ), + 'out' => array( + 'parameters' => array( + 'result' => array( + 'type' => 'NamespaceAModuleAData', + 'documentation' => 'data of resource', + 'required' => true, + ) + ), + ), + ), + ), + ), +); diff --git a/dev/tests/integration/testsuite/Mage/Webapi/_files/config/resource_a_fixture_v2.php b/dev/tests/integration/testsuite/Mage/Webapi/_files/config/resource_a_fixture_v2.php new file mode 100644 index 0000000000000000000000000000000000000000..7bcbc8c4ed9c7ab3f9fb28762fbb747d9fb16c0e --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/_files/config/resource_a_fixture_v2.php @@ -0,0 +1,83 @@ +<?php +/** + * Fixture of processed API action controller for resource config. + * Controller files is at _files/controllers/Webapi/ResourceAController.php + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +return array( + 'methods' => array( + 'create' => array( + 'documentation' => "Short description. +Long description. +Multiline <b>with html</b>.", + 'interface' => array( + 'in' => array( + 'parameters' => array( + 'resourceData' => array( + 'type' => 'NamespaceAModuleAData', + 'required' => true, + 'documentation' => 'Data of the resource' + ) + ) + ), + 'out' => array( + 'parameters' => array( + 'result' => array( + 'type' => 'int', + 'documentation' => 'ID of created resource', + 'required' => true, + ), + ) + ), + ), + ), + 'get' => array( + 'documentation' => 'Get resource v2.', + 'interface' => array( + 'in' => array( + 'parameters' => array( + 'resourceId' => array( + 'type' => 'int', + 'required' => true, + 'documentation' => 'ID of resource' + ), + 'newParameter' => array( + 'type' => 'string', + 'required' => true, + 'documentation' => 'new parameter in version 2' + ), + ) + ), + 'out' => array( + 'parameters' => array( + 'result' => array( + 'type' => 'NamespaceAModuleAData', + 'documentation' => 'data of resource', + 'required' => true, + ) + ), + ), + ), + ), + ) +); diff --git a/dev/tests/integration/testsuite/Mage/Webapi/_files/config/resource_a_subresource_b_fixture.php b/dev/tests/integration/testsuite/Mage/Webapi/_files/config/resource_a_subresource_b_fixture.php new file mode 100644 index 0000000000000000000000000000000000000000..f654fc34a82e359e472c7b972f16efc38a0aef94 --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/_files/config/resource_a_subresource_b_fixture.php @@ -0,0 +1,76 @@ +<?php +/** + * Fixture of processed API action controller for resource config. + * Controller files is at _files/controllers/Webapi/ResourceAController.php + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +return array( + 'methods' => array( + 'get' => array( + 'documentation' => 'Subresource description.', + 'interface' => array( + 'in' => array( + 'parameters' => array( + 'subresourceId' => array( + 'type' => 'int', + 'required' => true, + 'documentation' => 'ID of subresource.' + ) + ) + ), + 'out' => array( + 'parameters' => array( + 'result' => array( + 'type' => 'NamespaceAModuleAData', + 'documentation' => 'Data of resource', + 'required' => true, + ) + ), + ), + ), + ), + 'list' => array( + 'documentation' => 'List description.', + 'interface' => array( + 'in' => array( + 'parameters' => array( + 'parentId' => array( + 'type' => 'int', + 'required' => 1, + 'documentation' => 'Id of parent resource' + ) + ), + ), + 'out' => array( + 'parameters' => array( + 'result' => array( + 'type' => 'NamespaceAModuleAData[]', + 'documentation' => 'list of resources', + 'required' => true, + ) + ), + ), + ), + ) + ) +); diff --git a/dev/tests/integration/testsuite/Mage/Webapi/_files/data_types/Customer/AddressData.php b/dev/tests/integration/testsuite/Mage/Webapi/_files/data_types/Customer/AddressData.php new file mode 100644 index 0000000000000000000000000000000000000000..cdd6dabf33d9d4505064b8d8731a4ee1e5a0dffa --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/_files/data_types/Customer/AddressData.php @@ -0,0 +1,31 @@ +<?php +/** + * Tests fixture for Auto Discovery functionality. Customer address entity. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Vendor_Module_Model_Webapi_Customer_AddressData +{ + /** + * Street + * + * @var string + */ + public $street; + + /** + * City + * + * @var string + */ + public $city; + + /** + * State + * + * @optional true + * @var string + */ + public $state; +} diff --git a/dev/tests/integration/testsuite/Mage/Webapi/_files/data_types/CustomerData.php b/dev/tests/integration/testsuite/Mage/Webapi/_files/data_types/CustomerData.php new file mode 100644 index 0000000000000000000000000000000000000000..b6a99ce929b1e869cc4f4af9c43f2401e94c275f --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/_files/data_types/CustomerData.php @@ -0,0 +1,64 @@ +<?php +/** + * Tests fixture for Auto Discovery functionality. Customer entity. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Vendor_Module_Model_Webapi_CustomerData +{ + /** + * Customer email. + * Use this field to set customer <b>email</b>! + * + * @var string + */ + public $email; + + /** + * Customer first name + * + * @var string + */ + public $firstname; + + /** + * Customer last name + * + * @var string + */ + public $lastname = 'DefaultLastName'; + + /** + * Customer password + * + * @var string + */ + public $password = '123123q'; + + /** + * Customer address + * + * @optional true + * @var Vendor_Module_Model_Webapi_Customer_AddressData + */ + public $address; +} diff --git a/app/code/core/Mage/Api/Model/Acl/Role/Generic.php b/dev/tests/integration/testsuite/Mage/Webapi/_files/role.php similarity index 80% rename from app/code/core/Mage/Api/Model/Acl/Role/Generic.php rename to dev/tests/integration/testsuite/Mage/Webapi/_files/role.php index ac7d8995e55c68944d1583b10c3603671bc3cd94..625e9a5012de78122c928c0c891f8f0cc70a779e 100644 --- a/app/code/core/Mage/Api/Model/Acl/Role/Generic.php +++ b/dev/tests/integration/testsuite/Mage/Webapi/_files/role.php @@ -19,20 +19,11 @@ * needs please refer to http://www.magentocommerce.com for more information. * * @category Mage - * @package Mage_Api + * @package Mage_Webapi + * @subpackage integration_tests * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ - - -/** - * User acl role - * - * @category Mage - * @package Mage_Api - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api_Model_Acl_Role_Generic extends Zend_Acl_Role -{ - -} +/** @var Mage_Webapi_Model_Acl_Role $role */ +$role = Mage::getModel('Mage_Webapi_Model_Acl_Role'); +$role->setRoleName('test_role')->save(); diff --git a/dev/tests/integration/testsuite/Mage/Webapi/_files/role_with_rule.php b/dev/tests/integration/testsuite/Mage/Webapi/_files/role_with_rule.php new file mode 100644 index 0000000000000000000000000000000000000000..dad1da12017edc44783a3eef3e0a16013f476450 --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Webapi/_files/role_with_rule.php @@ -0,0 +1,41 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_Webapi + * @subpackage integration_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +$allowResourceId = 'customer/get'; +/** @var Mage_Webapi_Model_Acl_Role $role */ +$role = Mage::getModel('Mage_Webapi_Model_Acl_Role'); +$role->setData(array( + 'role_name' => 'Test role' +)); +$role->save(); +/** @var Mage_Webapi_Model_Acl_Rule $rule */ +$rule = Mage::getModel('Mage_Webapi_Model_Acl_Rule'); +$rule->setData(array( + 'resource_id' => $allowResourceId, + 'role_id' => $role->getRoleId() +)); +$rule->save(); diff --git a/dev/tests/integration/testsuite/Mage/Api2/controllers/Adminhtml/UserControllerTest.php b/dev/tests/integration/testsuite/Mage/Webapi/_files/user_with_role.php similarity index 65% rename from dev/tests/integration/testsuite/Mage/Api2/controllers/Adminhtml/UserControllerTest.php rename to dev/tests/integration/testsuite/Mage/Webapi/_files/user_with_role.php index 1b0b90458e8f7a02ec771a26e7c18b9eda235263..83fa1ed13a77ec4a43b007bb64394fcacaafb49c 100644 --- a/dev/tests/integration/testsuite/Mage/Api2/controllers/Adminhtml/UserControllerTest.php +++ b/dev/tests/integration/testsuite/Mage/Webapi/_files/user_with_role.php @@ -19,26 +19,23 @@ * needs please refer to http://www.magentocommerce.com for more information. * * @category Mage - * @package Mage_Api2 + * @package Mage_Webapi * @subpackage integration_tests * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ - -/** - * Test class for Mage_User_Adminhtml_UserController - * @group module:Mage_Api2 - */ -class Mage_Api2_Adminhtml_UserControllerTest extends Mage_Adminhtml_Utility_Controller -{ - /** - * Test that a block added by Api2 layout is present in content of action - * - * @return void - */ - public function testNewActionTest() - { - $this->dispatch('backend/admin/user/new'); - $this->assertContains('name="api2_roles_section"', $this->getResponse()->getBody()); - } -} +/** @var Mage_Webapi_Model_Acl_Role $role */ +$role = Mage::getModel('Mage_Webapi_Model_Acl_Role'); +$role->setData(array( + 'role_name' => 'Test role' +)); +$role->save(); +/** @var Mage_Webapi_Model_Acl_User $user */ +$user = Mage::getModel('Mage_Webapi_Model_Acl_User'); +$user->setData(array( + 'api_key' => 'test_username', + 'secret' => '123123qa', + 'contact_email' => 'null@null.com', + 'role_id' => $role->getRoleId() +)); +$user->save(); diff --git a/dev/tests/integration/testsuite/Magento/Profiler/Driver/Standard/Output/CsvfileTest.php b/dev/tests/integration/testsuite/Magento/Profiler/Driver/Standard/Output/CsvfileTest.php new file mode 100644 index 0000000000000000000000000000000000000000..c8c1a381262432b674d182f030d922e020b5eabb --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Profiler/Driver/Standard/Output/CsvfileTest.php @@ -0,0 +1,80 @@ +<?php +/** + * Test case for Magento_Profiler_Driver_Standard_Output_Csvfile + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Magento_Profiler_Driver_Standard_Output_CsvfileTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Magento_Profiler_Driver_Standard_Output_Csvfile + */ + protected $_output; + + /** + * @var string + */ + protected $_outputFile; + + protected function setUp() + { + $this->_outputFile = tempnam(sys_get_temp_dir(), __CLASS__); + } + + /** + * Test display method + * + * @dataProvider displayDataProvider + * @param string $statFile + * @param string $expectedFile + * @param string $delimiter + * @param string $enclosure + */ + public function testDisplay($statFile, $expectedFile, $delimiter = ',', $enclosure = '"') + { + $this->_output = new Magento_Profiler_Driver_Standard_Output_Csvfile( + $this->_outputFile, $delimiter, $enclosure + ); + $stat = include $statFile; + $this->_output->display($stat); + $this->assertFileEquals($expectedFile, $this->_outputFile); + } + + /** + * @return array + */ + public function displayDataProvider() + { + return array( + 'Default delimiter & enclosure' => array( + 'statFile' => __DIR__ . '/_files/timers.php', + 'expectedHtmlFile' => __DIR__ . '/_files/output_default.csv' + ), + 'Custom delimiter & enclosure' => array( + 'statFile' => __DIR__ . '/_files/timers.php', + 'expectedHtmlFile' => __DIR__ . '/_files/output_custom.csv', + '.', + '`' + ), + ); + } +} diff --git a/dev/tests/unit/testsuite/Magento/Profiler/Output/FirebugTest.php b/dev/tests/integration/testsuite/Magento/Profiler/Driver/Standard/Output/FirebugTest.php similarity index 52% rename from dev/tests/unit/testsuite/Magento/Profiler/Output/FirebugTest.php rename to dev/tests/integration/testsuite/Magento/Profiler/Driver/Standard/Output/FirebugTest.php index 5cfcdde6ca70696712d6b7efee054a015c7e6fd4..221aef85930f00079e3aeb399c35e1be93ed4971 100644 --- a/dev/tests/unit/testsuite/Magento/Profiler/Output/FirebugTest.php +++ b/dev/tests/integration/testsuite/Magento/Profiler/Driver/Standard/Output/FirebugTest.php @@ -1,5 +1,7 @@ <?php /** + * Test case for Magento_Profiler_Driver_Standard_Output_Firebug + * * Magento * * NOTICE OF LICENSE @@ -18,72 +20,55 @@ * versions in the future. If you wish to customize Magento for your * needs please refer to http://www.magentocommerce.com for more information. * - * @category Magento - * @package Magento_Profiler - * @subpackage unit_tests * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ - -/** - * Test case for Magento_Profiler_Output_Firebug - * - * @group profiler - */ -class Magento_Profiler_Output_FirebugTest extends PHPUnit_Framework_TestCase +class Magento_Profiler_Driver_Standard_Output_FirebugTest extends PHPUnit_Framework_TestCase { /** - * @var Magento_Profiler_Output_Firebug|PHPUnit_Framework_MockObject_MockObject + * @var Magento_Profiler_Driver_Standard_Output_Firebug */ - protected $_object; + protected $_output; /** - * @var Zend_Controller_Response_Abstract|PHPUnit_Framework_MockObject_MockObject + * @var Zend_Controller_Response_Http|PHPUnit_Framework_MockObject_MockObject */ protected $_response; - public static function setUpBeforeClass() - { - Magento_Profiler::enable(); - /* Profiler measurements fixture */ - $timersProperty = new ReflectionProperty('Magento_Profiler', '_timers'); - $timersProperty->setAccessible(true); - $timersProperty->setValue(include __DIR__ . '/../_files/timers.php'); - $timersProperty->setAccessible(false); - } - - public static function tearDownAfterClass() - { - Magento_Profiler::reset(); - } + /** + * @var Zend_Controller_Request_Http|PHPUnit_Framework_MockObject_MockObject + */ + protected $_request; protected function setUp() { - $this->_object = $this->getMock('Magento_Profiler_Output_Firebug', array('_renderCaption')); - $this->_object - ->expects($this->any()) - ->method('_renderCaption') - ->will($this->returnValue('Code Profiler Title')) - ; $this->_response = $this->getMock('Zend_Controller_Response_Http', array('canSendHeaders', 'sendHeaders')); $this->_response ->expects($this->any()) ->method('canSendHeaders') - ->will($this->returnValue(true)) - ; - $this->_object->setResponse($this->_response); + ->will($this->returnValue(true)); + + $this->_request = $this->getMock('Zend_Controller_Request_Http', array('getHeader')); + $this->_request + ->expects($this->any()) + ->method('getHeader') + ->with('User-Agent') + ->will($this->returnValue('Mozilla/5.0 with FirePHP/1.6')); + + $this->_output = new Magento_Profiler_Driver_Standard_Output_Firebug(); + $this->_output->setResponse($this->_response); + $this->_output->setRequest($this->_request); } public function testDisplay() { - $_SERVER['HTTP_USER_AGENT'] = 'Mozilla/5.0 with FirePHP/1.6'; - $this->_response - ->expects($this->atLeastOnce()) - ->method('sendHeaders') - ; - $this->_object->display(); - $actualHeaders = $this->_response->getHeaders(); + $this->_response->expects($this->atLeastOnce())->method('sendHeaders'); + $this->_request->expects($this->atLeastOnce())->method('getHeader'); + + $stat = include __DIR__ . '/_files/timers.php'; + $this->_output->display($stat); + $actualHeaders = $this->_response->getHeaders(); $this->assertNotEmpty($actualHeaders); $actualProtocol = false; @@ -98,14 +83,19 @@ class Magento_Profiler_Output_FirebugTest extends PHPUnit_Framework_TestCase $actualProfilerData = $headerValue; } } + + $this->assertNotEmpty($actualProtocol, 'Cannot get protocol header'); + $this->assertNotEmpty($actualProfilerData, 'Cannot get profiler header'); $this->assertContains('Protocol/JsonStream', $actualProtocol); - $this->assertContains('"Type":"TABLE","Label":"Code Profiler Title"', $actualProfilerData); + $this->assertRegExp('/"Type":"TABLE","Label":"Code Profiler \(Memory usage: real - \d+, emalloc - \d+\)"/', + $actualProfilerData); $this->assertContains('[' . '["Timer Id","Time","Avg","Cnt","Emalloc","RealMem"],' - . '["some_root_timer","0.080000","0.040000","2","51,000,000","50,000,000"],' - . '[". some_nested_timer","0.080000","0.026667","3","42,000,000","40,000,000"],' - . '[". . some_deeply_nested_timer","0.030000","0.010000","3","13,000,000","10,000,000"],' - . '["one_more_root_timer","0.010000","0.010000","1","23,456,789","12,345,678"]]', + . '["root","0.080000","0.080000","1","1,000","50,000"],' + . '[". init","0.040000","0.040000","1","200","2,500"],' + . '[". . init_store","0.020000","0.010000","2","100","2,000"],' + . '["system","0.030000","0.015000","2","400","20,000"]' + . ']', $actualProfilerData ); } diff --git a/dev/tests/integration/testsuite/Magento/Profiler/Driver/Standard/Output/HtmlTest.php b/dev/tests/integration/testsuite/Magento/Profiler/Driver/Standard/Output/HtmlTest.php new file mode 100644 index 0000000000000000000000000000000000000000..1ea7226116df708a855c197ea73e15d44e81fd6f --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Profiler/Driver/Standard/Output/HtmlTest.php @@ -0,0 +1,87 @@ +<?php +/** + * Test case for Magento_Profiler_Driver_Standard_Output_Html + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Magento_Profiler_Driver_Standard_Output_HtmlTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Magento_Profiler_Driver_Standard_Output_Html + */ + protected $_output; + + protected function setUp() + { + $this->_output = new Magento_Profiler_Driver_Standard_Output_Html(); + } + + /** + * Test display method + * + * @dataProvider displayDataProvider + * @param string $statFile + * @param string $expectedHtmlFile + */ + public function testDisplay($statFile, $expectedHtmlFile) + { + $stat = include $statFile; + $expectedHtml = file_get_contents($expectedHtmlFile); + + ob_start(); + $this->_output->display($stat); + $actualHtml = ob_get_clean(); + + $this->_assertDisplayResultEquals($actualHtml, $expectedHtml); + } + + /** + * @return array + */ + public function displayDataProvider() + { + return array( + array('statFile' => __DIR__ . '/_files/timers.php', 'expectedHtmlFile' => __DIR__ . '/_files/output.html') + ); + } + + /** + * Asserts display() result equals + * + * @param string $actualHtml + * @param string $expectedHtml + */ + protected function _assertDisplayResultEquals($actualHtml, $expectedHtml) + { + $expectedHtml = ltrim(preg_replace('/^<!--.+?-->/s', '', $expectedHtml)); + if (preg_match('/Code Profiler \(Memory usage: real - (\d+), emalloc - (\d+)\)/', $actualHtml, $matches)) { + list(, $realMemory, $emallocMemory) = $matches; + $expectedHtml = str_replace( + array('%real_memory%', '%emalloc_memory%'), + array($realMemory, $emallocMemory), + $expectedHtml + ); + } + $this->assertEquals($expectedHtml, $actualHtml); + + } +} diff --git a/dev/tests/integration/testsuite/Magento/Profiler/Driver/Standard/Output/_files/output.html b/dev/tests/integration/testsuite/Magento/Profiler/Driver/Standard/Output/_files/output.html new file mode 100644 index 0000000000000000000000000000000000000000..84a350cf3251904b229aa21157953d21dd70a62c --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Profiler/Driver/Standard/Output/_files/output.html @@ -0,0 +1,69 @@ +<!-- +/** + * Result of HTML output (Magento_Profiler_Driver_Standard_Output_Html) + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Academic Free License (AFL 3.0) + * that is bundled with this package in the file LICENSE_AFL.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/afl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ +--> +<table border="1" cellspacing="0" cellpadding="2"> +<caption>Code Profiler (Memory usage: real - %real_memory%, emalloc - %emalloc_memory%)</caption> +<tr> +<th>Timer Id</th> +<th>Time</th> +<th>Avg</th> +<th>Cnt</th> +<th>Emalloc</th> +<th>RealMem</th> +</tr> +<tr> +<td title="root">root</td> +<td title="root">0.080000</td> +<td title="root">0.080000</td> +<td title="root">1</td> +<td title="root">1,000</td> +<td title="root">50,000</td> +</tr> +<tr> +<td title="root->init">· init</td> +<td title="root->init">0.040000</td> +<td title="root->init">0.040000</td> +<td title="root->init">1</td> +<td title="root->init">200</td> +<td title="root->init">2,500</td> +</tr> +<tr> +<td title="root->init->init_store">· · init_store</td> +<td title="root->init->init_store">0.020000</td> +<td title="root->init->init_store">0.010000</td> +<td title="root->init->init_store">2</td> +<td title="root->init->init_store">100</td> +<td title="root->init->init_store">2,000</td> +</tr> +<tr> +<td title="system">system</td> +<td title="system">0.030000</td> +<td title="system">0.015000</td> +<td title="system">2</td> +<td title="system">400</td> +<td title="system">20,000</td> +</tr> +</table> diff --git a/dev/tests/integration/testsuite/Magento/Profiler/Driver/Standard/Output/_files/output_custom.csv b/dev/tests/integration/testsuite/Magento/Profiler/Driver/Standard/Output/_files/output_custom.csv new file mode 100644 index 0000000000000000000000000000000000000000..160c6aa6f18b1010cd1bf0154f0166fffdecc4e3 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Profiler/Driver/Standard/Output/_files/output_custom.csv @@ -0,0 +1,4 @@ +root.`0.080000`.`0.080000`.1.1,000.50,000 +root->init.`0.040000`.`0.040000`.1.200.2,500 +root->init->init_store.`0.020000`.`0.010000`.2.100.2,000 +system.`0.030000`.`0.015000`.2.400.20,000 diff --git a/dev/tests/integration/testsuite/Magento/Profiler/Driver/Standard/Output/_files/output_default.csv b/dev/tests/integration/testsuite/Magento/Profiler/Driver/Standard/Output/_files/output_default.csv new file mode 100644 index 0000000000000000000000000000000000000000..dd8dbe5067d0c64bd40b7623766c01f7fa32e0ad --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Profiler/Driver/Standard/Output/_files/output_default.csv @@ -0,0 +1,4 @@ +root,0.080000,0.080000,1,"1,000","50,000" +root->init,0.040000,0.040000,1,200,"2,500" +root->init->init_store,0.020000,0.010000,2,100,"2,000" +system,0.030000,0.015000,2,400,"20,000" diff --git a/dev/tests/integration/testsuite/Magento/Profiler/Driver/Standard/Output/_files/timers.php b/dev/tests/integration/testsuite/Magento/Profiler/Driver/Standard/Output/_files/timers.php new file mode 100644 index 0000000000000000000000000000000000000000..857e51fd883038f51488000ceb99735fdee6249e --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Profiler/Driver/Standard/Output/_files/timers.php @@ -0,0 +1,45 @@ +<?php +/** + * Fixture timers statistics for output tests + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +$timer = new Magento_Profiler_Driver_Standard_Stat(); +$timer->start('root', 0.01, 50000, 1000); + +$timer->start('root->init', 0.02, 55000, 1400); + +$timer->start('root->init->init_store', 0.02, 55000, 1400); +$timer->stop('root->init->init_store', 0.03, 56000, 1450); +$timer->start('root->init->init_store', 0.02, 56500, 1550); +$timer->stop('root->init->init_store', 0.03, 57500, 1600); + +$timer->stop('root->init', 0.06, 57500, 1600); + +$timer->stop('root', 0.09, 100000, 2000); + +$timer->start('system', 0.11, 50000, 1000); +$timer->stop('system', 0.13, 60000, 1200); +$timer->start('system', 0.14, 50000, 1000); +$timer->stop('system', 0.15, 60000, 1200); + +return $timer; diff --git a/dev/tests/integration/testsuite/integrity/modular/SystemConfigFilesTest.php b/dev/tests/integration/testsuite/integrity/modular/SystemConfigFilesTest.php index aa6d4e0611dc29699d06fe7c38325092f3b9f38d..7b888865a8497d267e49d113847b986e18deb4c8 100644 --- a/dev/tests/integration/testsuite/integrity/modular/SystemConfigFilesTest.php +++ b/dev/tests/integration/testsuite/integrity/modular/SystemConfigFilesTest.php @@ -34,7 +34,20 @@ class Integrity_Modular_SystemConfigFilesTest extends PHPUnit_Framework_TestCase { $fileList = glob(Mage::getBaseDir('app') . '/*/*/*/*/etc/adminhtml/system.xml'); try { - new Mage_Backend_Model_Config_Structure(array('sourceFiles' => $fileList)); + $configMock = $this->getMock( + 'Mage_Core_Model_Config', array('getModuleConfigurationFiles'), array(), '', false + ); + $configMock->expects($this->any()) + ->method('getModuleConfigurationFiles') + ->will($this->returnValue($fileList)); + $cacheMock = $this->getMock('Mage_Core_Model_Cache', array(), array(), '', false); + $cacheMock->expects($this->any())->method('canUse')->will($this->returnValue(false)); + $converter = new Mage_Backend_Model_Config_Structure_Converter( + new Mage_Backend_Model_Config_Structure_Mapper_Factory(Mage::getObjectManager()) + ); + new Mage_Backend_Model_Config_Structure_Reader( + $configMock, $cacheMock, $converter, true + ); } catch (Magento_Exception $exp) { $this->fail($exp->getMessage()); } diff --git a/dev/tests/static/testsuite/Legacy/_files/obsolete_methods.php b/dev/tests/static/testsuite/Legacy/_files/obsolete_methods.php index 70cc13636affdc0a2ab4eeed46e1d57ff0a0ec42..3982d03131330612426c277c1cb9ebeb12fb5de9 100644 --- a/dev/tests/static/testsuite/Legacy/_files/obsolete_methods.php +++ b/dev/tests/static/testsuite/Legacy/_files/obsolete_methods.php @@ -42,6 +42,7 @@ return array( $this->_getRule('_avoidDoubleTransactionProcessing'), $this->_getRule('_beforeChildToHtml'), $this->_getRule('_calculatePrice', 'Mage_Sales_Model_Quote_Item_Abstract'), + $this->_getRule('_canShowField', 'Mage_Backend_Block_System_Config_Form'), $this->_getRule('_canUseLocalModules'), $this->_getRule('_checkUrlSettings', 'Mage_Adminhtml_Controller_Action'), $this->_getRule('_collectOrigData', 'Mage_Catalog_Model_Resource_Abstract'), @@ -58,6 +59,7 @@ return array( $this->_getRule('_getCacheKey', 'Mage_Catalog_Model_Layer_Filter_Price'), $this->_getRule('_getCacheTags', 'Mage_Core_Model_App'), $this->_getRule('_getChildHtml'), + $this->_getRule('_getCollapseState', 'Mage_Backend_Block_System_Config_Form_Fieldset', '_isCollapseState'), $this->_getRule('_getCollectionNames', 'Mage_Adminhtml_Report_SalesController'), $this->_getRule('_getConnenctionType', 'Mage_Install_Model_Installer_Db'), $this->_getRule('_getDateFromToHtml', 'Mage_ImportExport_Block_Adminhtml_Export_Filter'), @@ -111,6 +113,7 @@ return array( $this->_getRule('_sendUploadResponse', 'Mage_Adminhtml_CustomerController'), $this->_getRule('_sendUploadResponse', 'Mage_Adminhtml_Newsletter_SubscriberController'), $this->_getRule('_setAttribteValue'), + $this->_getRule('_sort', 'Mage_Backend_Model_Config_Structure_Converter'), $this->_getRule('_usePriceIncludeTax'), $this->_getRule('addBackupedFilter'), $this->_getRule('addConfigField', 'Mage_Core_Model_Resource_Setup'), @@ -253,11 +256,15 @@ return array( $this->_getRule('getRowId', 'Mage_Adminhtml_Block_Widget_Grid'), $this->_getRule('getSaveTemplateFlag', 'Mage_Newsletter_Model_Queue'), $this->_getRule('getSelectionFinalPrice', 'Mage_Bundle_Model_Product_Price'), + $this->_getRule('getSecure', 'Mage_Core_Model_Url', 'isSecure'), + $this->_getRule('getSecure', 'Mage_Backend_Model_Url', 'isSecure'), $this->_getRule('getShipId', 'Mage_Shipping_Block_Tracking_Popup'), $this->_getRule('getSortedChildren', null, 'getChildNames'), $this->_getRule('getSortedChildBlocks', null, 'getChildNames() + $this->getLayout()->getBlock($name)'), $this->_getRule('getStatrupPageUrl'), + $this->_getRule('getStoreButtonsHtml', 'Mage_Backend_Block_System_Config_Tabs'), $this->_getRule('getStoreCurrency', 'Mage_Sales_Model_Order'), + $this->_getRule('getStoreSelectOptions', 'Mage_Backend_Block_System_Config_Tabs'), $this->_getRule('getSuggestedZeroDate'), $this->_getRule('getSuggestionsByQuery'), $this->_getRule('getTaxAmount', 'Mage_Sales_Model_Quote_Item_Abstract'), diff --git a/dev/tests/static/testsuite/Php/_files/blacklist/common.txt b/dev/tests/static/testsuite/Php/_files/blacklist/common.txt index fe059cace34e98fe1b1879014f7bf7a283aa3929..3758d42598015f016606146e9e278ae7abb8224a 100644 --- a/dev/tests/static/testsuite/Php/_files/blacklist/common.txt +++ b/dev/tests/static/testsuite/Php/_files/blacklist/common.txt @@ -2,22 +2,26 @@ # Glob patterns are supported # Overrides the white list # +app/code/core/Mage/Backend/Model/Config.php +app/code/core/Mage/Backend/Model/Config/Structure/Converter.php +app/code/core/Mage/Backend/Model/Menu/Config.php +app/code/core/Mage/Backend/Block/Widget/Grid app/code/core/Mage/DesignEditor/view +app/code/core/Mage/Webapi/view app/code/core/Mage/Core/data/core_setup/data-upgrade-1.6.0.4-1.6.0.5.php app/code/core/Mage/Theme/Helper/Data.php app/code/core/Mage/Theme/Block/Adminhtml/System/Design/Theme/Edit/Tab/General.php app/code/core/Mage/User/view -lib/Magento/Acl/Config/ReaderInterface.php -lib/Magento/Acl/Role/Registry.php lib/Magento/Config/Dom.php lib/Magento/Config/Theme.php -lib/Magento/Data/Graph.php -lib/Magento/Data/Structure.php +lib/Magento/Data lib/Magento/Shell.php lib/Magento/Validator.php dev/tests/integration/testsuite/integrity/modular/TemplateFilesTest.php dev/tests/integration/testsuite/integrity/theme/TemplateFilesTest.php +dev/tests/integration/testsuite/Mage/Backend/Block/System/Config/FormStub.php dev/tests/integration/testsuite/Mage/Core/Block/_files dev/tests/integration/tmp dev/tests/static/testsuite/Php/Exemplar/_files/phpcs/input dev/tests/static/testsuite/Php/Exemplar/_files/phpmd/input +app/code/core/Mage/Backend/view diff --git a/dev/tests/static/testsuite/Php/_files/whitelist/common.txt b/dev/tests/static/testsuite/Php/_files/whitelist/common.txt index 86c7ffcd8091ed9b21435ac6a898eb96abf70aff..333c085de974f64cd77ff9166bcdaea86c1ff38b 100644 --- a/dev/tests/static/testsuite/Php/_files/whitelist/common.txt +++ b/dev/tests/static/testsuite/Php/_files/whitelist/common.txt @@ -17,16 +17,7 @@ app/code/core/Mage/Adminhtml/Block/System/Store/Edit.php app/code/core/Mage/Adminhtml/controllers/Report/CustomerController.php app/code/core/Mage/Adminhtml/controllers/Report/ProductController.php app/code/core/Mage/Adminhtml/controllers/UrlrewriteController.php -app/code/core/Mage/Backend/Model/Acl/Config.php -app/code/core/Mage/Backend/Block/System/Config/Form/Field/Regexceptions.php -app/code/core/Mage/Backend/Block/Widget/Grid/ColumnSet.php -app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Theme.php -app/code/core/Mage/Backend/Block/Widget/Grid/Export.php -app/code/core/Mage/Backend/Block/Widget/Grid/ExportInterface.php -app/code/core/Mage/Backend/Block/System/Config/Form/Field.php -app/code/core/Mage/Backend/controllers/Adminhtml/System/ConfigController.php -app/code/core/Mage/Backend/controllers/Adminhtml/SystemController.php -app/code/core/Mage/Backend/Model/Widget/Grid +app/code/core/Mage/Backend app/code/core/Mage/Catalog/Block/Product/Configurable app/code/core/Mage/Catalog/Model/Resource/Product/Collection app/code/core/Mage/CatalogInventory/Block/Adminhtml/Form/Field/Stock.php @@ -75,6 +66,7 @@ app/code/core/Mage/Core/Controller/Varien/Router/Standard.php app/code/core/Mage/Core/Controller/Varien/Router/Abstract.php app/code/core/Mage/Cms/Controller/Router.php app/code/core/Mage/Page/Helper/Robots.php +app/code/core/Mage/Webapi dev/shell dev/tests/integration dev/tests/js diff --git a/dev/tests/unit/framework/Magento/Test/Helper/ObjectManager.php b/dev/tests/unit/framework/Magento/Test/Helper/ObjectManager.php index ea3c1d72bc7f7a93f92af4445745f18834c7ab3d..a82f111278b2e8f9eb84702b52ecc559c6126033 100644 --- a/dev/tests/unit/framework/Magento/Test/Helper/ObjectManager.php +++ b/dev/tests/unit/framework/Magento/Test/Helper/ObjectManager.php @@ -53,7 +53,7 @@ class Magento_Test_Helper_ObjectManager 'layout' => 'Mage_Core_Model_Layout', 'eventManager' => 'Mage_Core_Model_Event_Manager', 'urlBuilder' => 'Mage_Core_Model_Url', - 'translator' => 'Mage_Core_Model_Translate', + 'translator' => '_getTranslatorMock', 'cache' => 'Mage_Core_Model_Cache', 'designPackage' => 'Mage_Core_Model_Design_Package', 'session' => 'Mage_Core_Model_Session', @@ -163,6 +163,32 @@ class Magento_Test_Helper_ObjectManager return $resourceMock; } + /** + * Retrieve mock of core translator model + * + * @return Mage_Core_Model_Translate|PHPUnit_Framework_MockObject_MockObject + */ + protected function _getTranslatorMock() + { + $translator = $this->_testObject->getMockBuilder('Mage_Core_Model_Translate') + ->disableOriginalConstructor() + ->setMethods(array('translate')) + ->getMock(); + $translateCallback = function ($arguments) { + $result = ''; + if (is_array($arguments) && current($arguments) instanceof Mage_Core_Model_Translate_Expr) { + /** @var Mage_Core_Model_Translate_Expr $expression */ + $expression = array_shift($arguments); + $result = vsprintf($expression->getText(), $arguments); + } + return $result; + }; + $translator->expects($this->_testObject->any()) + ->method('translate') + ->will($this->_testObject->returnCallback($translateCallback)); + return $translator; + } + /** * Sort constructor arguments array as is defined for current class interface * @@ -198,6 +224,7 @@ class Magento_Test_Helper_ObjectManager */ protected function _getMockWithoutConstructorCall($className) { + return $this->_testObject->getMock($className, array(), array(), '', false); } diff --git a/dev/tests/unit/testsuite/Mage/Adminhtml/Block/System/Email/Template/EditTest.php b/dev/tests/unit/testsuite/Mage/Adminhtml/Block/System/Email/Template/EditTest.php new file mode 100644 index 0000000000000000000000000000000000000000..177140ff1488459dab7808a87d7e5c6c140f05e3 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Adminhtml/Block/System/Email/Template/EditTest.php @@ -0,0 +1,170 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Adminhtml + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_Adminhtml_Block_System_Email_Template_EditTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Adminhtml_Block_System_Email_Template_Edit + */ + protected $_block; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_configStructureMock; + + protected function setUp() + { + $objectManager = new Magento_Test_Helper_ObjectManager($this); + $registryMock = $this->getMock('Mage_Core_Model_Registry', array(), array(), '', false, false); + $layoutMock = $this->getMock('Mage_Core_Model_Layout', array(), array(), '', false, false); + $helperMock = $this->getMock('Mage_Adminhtml_Helper_Data', array(), array(), '', false, false); + $menuConfigMock = $this->getMock('Mage_Backend_Model_Menu_Config', array(), array(), '', false, false); + $menuMock = $this->getMock('Mage_Backend_Model_Menu', array(), array(), '', false, false); + $menuItemMock = $this->getMock('Mage_Backend_Model_Menu_Item', array(), array(), '', false, false); + $urlBuilder = $this->getMock('Mage_Backend_Model_Url', array(), array(), '', false, false); + $this->_configStructureMock = $this->getMock('Mage_Backend_Model_Config_Structure', + array(), array(), '', false, false + ); + + $params = array( + 'urlBuilder' => $urlBuilder, + 'registry' => $registryMock, + 'layout' => $layoutMock, + 'menuConfig' => $menuConfigMock, + 'configStructure' => $this->_configStructureMock, + ); + $arguments = $objectManager->getConstructArguments( + Magento_Test_Helper_ObjectManager::BLOCK_ENTITY, + 'Mage_Adminhtml_Block_System_Email_Template_Edit', + $params + ); + + $urlBuilder->expects($this->any())->method('getUrl')->will($this->returnArgument(0)); + $menuConfigMock->expects($this->any())->method('getMenu')->will($this->returnValue($menuMock)); + $menuMock->expects($this->any())->method('get')->will($this->returnValue($menuItemMock)); + $menuItemMock->expects($this->any())->method('getModuleHelper')->will($this->returnValue($helperMock)); + $menuItemMock->expects($this->any())->method('getTitle')->will($this->returnValue('Title')); + + $paths = array( + array( + 'scope' => 'scope_11', + 'scope_id' => 'scope_id_1', + 'path' => 'section1/group1/field1', + ), + array( + 'scope' => 'scope_11', + 'scope_id' => 'scope_id_1', + 'path' => 'section1/group1/group2/field1', + ), + array( + 'scope' => 'scope_11', + 'scope_id' => 'scope_id_1', + 'path' => 'section1/group1/group2/group3/field1', + ), + ); + $templateMock = $this->getMock('Mage_Adminhtml_Model_Email_Template', array(), array(), '', false, false); + $templateMock->expects($this->once()) + ->method('getSystemConfigPathsWhereUsedCurrently') + ->will($this->returnValue($paths)); + + $registryMock->expects($this->once())->method('registry') + ->with('current_email_template')->will($this->returnValue($templateMock)); + + $layoutMock->expects($this->any())->method('helper')->will($this->returnValue($helperMock)); + $helperMock->expects($this->any())->method('__')->will($this->returnArgument(0)); + + $this->_block = $objectManager->getBlock('Mage_Adminhtml_Block_System_Email_Template_Edit', $arguments); + } + + public function testGetUsedCurrentlyForPaths() + { + $sectionMock = $this->getMock('Mage_Backend_Model_Config_Structure_Element_Section', + array(), array(), '', false, false + ); + $groupMock1 = $this->getMock('Mage_Backend_Model_Config_Structure_Element_Group', + array(), array(), '', false, false + ); + $groupMock2 = $this->getMock('Mage_Backend_Model_Config_Structure_Element_Group', + array(), array(), '', false, false + ); + $groupMock3 = $this->getMock('Mage_Backend_Model_Config_Structure_Element_Group', + array(), array(), '', false, false + ); + $filedMock = $this->getMock('Mage_Backend_Model_Config_Structure_Element_Field', + array(), array(), '', false, false + ); + $map = array( + array(array('section1', 'group1'), $groupMock1), + array(array('section1', 'group1', 'group2'), $groupMock2), + array(array('section1', 'group1', 'group2', 'group3'), $groupMock3), + array(array('section1', 'group1', 'field1'), $filedMock), + array(array('section1', 'group1', 'group2', 'field1'), $filedMock), + array(array('section1', 'group1', 'group2', 'group3', 'field1'), $filedMock), + ); + $sectionMock->expects($this->any())->method('getLabel')->will($this->returnValue('Section_1_Label')); + $groupMock1->expects($this->any())->method('getLabel')->will($this->returnValue('Group_1_Label')); + $groupMock2->expects($this->any())->method('getLabel')->will($this->returnValue('Group_2_Label')); + $groupMock3->expects($this->any())->method('getLabel')->will($this->returnValue('Group_3_Label')); + $filedMock->expects($this->any())->method('getLabel')->will($this->returnValue('Field_1_Label')); + + $this->_configStructureMock->expects($this->any()) + ->method('getElement')->with('section1')->will($this->returnValue($sectionMock)); + + $this->_configStructureMock->expects($this->any()) + ->method('getElementByPathParts')->will($this->returnValueMap($map)); + + $actual = $this->_block->getUsedCurrentlyForPaths(false); + $expected = array( + array( + array('title' => 'Title',), + array('title' => 'Title', 'url' => 'adminhtml/system_config/',), + array('title' => 'Section_1_Label', 'url' => 'adminhtml/system_config/edit',), + array('title' => 'Group_1_Label',), + array('title' => 'Field_1_Label', 'scope' => 'GLOBAL',), + ), + array( + array('title' => 'Title',), + array('title' => 'Title', 'url' => 'adminhtml/system_config/',), + array('title' => 'Section_1_Label', 'url' => 'adminhtml/system_config/edit',), + array('title' => 'Group_1_Label',), + array('title' => 'Group_2_Label',), + array('title' => 'Field_1_Label', 'scope' => 'GLOBAL',), + ), + array( + array('title' => 'Title',), + array('title' => 'Title', 'url' => 'adminhtml/system_config/',), + array('title' => 'Section_1_Label', 'url' => 'adminhtml/system_config/edit',), + array('title' => 'Group_1_Label',), + array('title' => 'Group_2_Label',), + array('title' => 'Group_3_Label',), + array('title' => 'Field_1_Label', 'scope' => 'GLOBAL',), + ) + ); + $this->assertEquals($expected, $actual); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Backend/Block/System/Config/EditTest.php b/dev/tests/unit/testsuite/Mage/Backend/Block/System/Config/EditTest.php index 43bf35e93fd8ad8ef0585ca5321acfa05dd42756..38fea83c3125585298255a242e9ff8d30a515bb6 100644 --- a/dev/tests/unit/testsuite/Mage/Backend/Block/System/Config/EditTest.php +++ b/dev/tests/unit/testsuite/Mage/Backend/Block/System/Config/EditTest.php @@ -52,6 +52,11 @@ class Mage_Backend_Block_System_Config_EditTest extends PHPUnit_Framework_TestCa */ protected $_urlModelMock; + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_sectionMock; + protected function setUp() { $this->_systemConfigMock = $this->getMock('Mage_Backend_Model_Config_Structure', @@ -61,7 +66,7 @@ class Mage_Backend_Block_System_Config_EditTest extends PHPUnit_Framework_TestCa $this->_requestMock = $this->getMock('Mage_Core_Controller_Request_Http', array(), array(), '', false, false ); - $this->_requestMock->expects($this->once()) + $this->_requestMock->expects($this->any()) ->method('getParam') ->with('section') ->will($this->returnValue('test_section')); @@ -72,15 +77,13 @@ class Mage_Backend_Block_System_Config_EditTest extends PHPUnit_Framework_TestCa $this->_urlModelMock = $this->getMock('Mage_Backend_Model_Url', array(), array(), '', false, false); - $sections = array( - 'frontend_model' => 'Some_Frontend_Model', - 'label' => 'test_label' + $this->_sectionMock = $this->getMock( + 'Mage_Backend_Model_Config_Structure_Element_Section', array(), array(), '', false ); - $this->_systemConfigMock->expects($this->once()) - ->method('getSection') + $this->_systemConfigMock->expects($this->any()) + ->method('getElement') ->with('test_section') - ->will($this->returnValue($sections) - ); + ->will($this->returnValue($this->_sectionMock)); $data = array( 'data' => array( @@ -88,7 +91,8 @@ class Mage_Backend_Block_System_Config_EditTest extends PHPUnit_Framework_TestCa ), 'request' => $this->_requestMock, 'layout' => $this->_layoutMock, - 'urlBuilder' => $this->_urlModelMock + 'urlBuilder' => $this->_urlModelMock, + 'configStructure' => $this->_systemConfigMock ); $helper = new Magento_Test_Helper_ObjectManager($this); @@ -111,7 +115,7 @@ class Mage_Backend_Block_System_Config_EditTest extends PHPUnit_Framework_TestCa public function testGetSaveUrl() { - $expectedUrl = '*/*/save'; + $expectedUrl = '*/system_config_save/index'; $expectedParams = array('_current' => true); $this->_urlModelMock->expects($this->once()) @@ -122,22 +126,4 @@ class Mage_Backend_Block_System_Config_EditTest extends PHPUnit_Framework_TestCa $this->assertEquals($expectedUrl, $this->_object->getSaveUrl()); } - - public function testInitFormWhenFrontendModelIsSet() - { - $block = $this->getMock('Mage_Core_Block_Template', - array('initForm', 'getNameInLayout', 'getIsAnonymous'), array(), '', false, false - ); - $block->expects($this->once())->method('initForm'); - $block->expects($this->once())->method('getNameInLayout')->will($this->returnValue('test_block_name')); - - $this->_layoutMock->expects($this->once()) - ->method('createBlock') - ->with('Some_Frontend_Model') - ->will($this->returnValue($block) - ); - - $this->_layoutMock->expects($this->once())->method('setChild')->with(null, 'test_block_name', 'form'); - $this->_object->initForm(); - } } diff --git a/dev/tests/unit/testsuite/Mage/Backend/Block/System/Config/Form/FieldsetTest.php b/dev/tests/unit/testsuite/Mage/Backend/Block/System/Config/Form/FieldsetTest.php index 2ddb475717dedd4993a6e8ad38781dd8537c7a11..5a3d28b4e73740b374b46480d7d1d9c042511699 100644 --- a/dev/tests/unit/testsuite/Mage/Backend/Block/System/Config/Form/FieldsetTest.php +++ b/dev/tests/unit/testsuite/Mage/Backend/Block/System/Config/Form/FieldsetTest.php @@ -63,13 +63,15 @@ class Mage_Backend_Block_System_Config_Form_FieldsetTest extends PHPUnit_Framewo $this->_requestMock = $this->getMock('Mage_Core_Controller_Request_Http', array(), array(), '', false, false); $this->_urlModelMock = $this->getMock('Mage_Backend_Model_Url', array(), array(), '', false, false); $this->_layoutMock = $this->getMock('Mage_Core_Model_Layout', array(), array(), '', false, false); + $groupMock = $this->getMock('Mage_Backend_Model_Config_Structure_Element_Group', array(), array(), '', false); + $groupMock->expects($this->once())->method('getFieldsetCss')->will($this->returnValue('test_fieldset_css')); $data = array( 'request' => $this->_requestMock, 'urlBuilder' => $this->_urlModelMock, 'layout' => $this->_layoutMock, 'data' => array( - 'group' => array('fieldset_css' => 'test_fieldset_css') + 'group' => $groupMock ) ); $helper = new Magento_Test_Helper_ObjectManager($this); @@ -115,7 +117,7 @@ class Mage_Backend_Block_System_Config_Form_FieldsetTest extends PHPUnit_Framewo $this->_elementMock->expects($this->any())->method('getSortedElements')->will($this->returnValue(array())); - $expected = '<div class="entry-edit-head collapseable" >'; + $expected = '<div><div><div class="entry-edit-head collapseable" >'; $expected .= '<a id="' . $this->_testData['htmlId'] . '-head" href="#"' . ' onclick="Fieldset.toggleCollapse(\'' . $this->_testData['htmlId'] . '\', \'\'); ' @@ -135,7 +137,7 @@ class Mage_Backend_Block_System_Config_Form_FieldsetTest extends PHPUnit_Framewo $expected .= '<colgroup class="value" />'; $expected .= '<colgroup class="scope-label" />'; $expected .= '<colgroup class="" />'; - $expected .= '<tbody></tbody></table></fieldset>'; + $expected .= '<tbody></tbody></table></fieldset></div></div>'; $this->assertEquals($expected, $this->_object->render($this->_elementMock)); } diff --git a/dev/tests/unit/testsuite/Mage/Backend/Block/System/Config/FormTest.php b/dev/tests/unit/testsuite/Mage/Backend/Block/System/Config/FormTest.php new file mode 100644 index 0000000000000000000000000000000000000000..44f3df500390b4afd165d5f9084c36bce11e1729 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Backend/Block/System/Config/FormTest.php @@ -0,0 +1,299 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Backend + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_Backend_Block_System_Config_FormTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Backend_Block_System_Config_Form + */ + protected $_object; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_systemConfigMock; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_formMock; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_fieldFactoryMock; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_urlModelMock; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_formFactoryMock; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_backendConfigMock; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_fieldsetFactoryMock; + + protected function setUp() + { + $this->_systemConfigMock = $this->getMock('Mage_Backend_Model_Config_Structure', + array(), array(), '', false, false + ); + + $requestMock = $this->getMock('Mage_Core_Controller_Request_Http', + array(), array(), '', false, false + ); + $requestParams = array( + array('website', '', 'website_code'), + array('section', '', 'section_code'), + array('store', '', 'store_code'), + ); + $requestMock->expects($this->any()) + ->method('getParam') + ->will($this->returnValueMap($requestParams)); + + $helperMock = $this->getMock('Mage_Backend_Helper_Data', array(), array(), '', false, false); + + $layoutMock = $this->getMock('Mage_Core_Model_Layout', + array(), array(), '', false, false + ); + $layoutMock->expects($this->any())->method('helper')->will($this->returnValue($helperMock)); + $helperMock->expects($this->any())->method('__')->will($this->returnArgument(0)); + + $this->_urlModelMock = $this->getMock('Mage_Backend_Model_Url', array(), array(), '', false, false); + $configFactoryMock = $this->getMock('Mage_Backend_Model_Config_Factory', array(), array(), '', false, false); + $this->_formFactoryMock = $this->getMock('Varien_Data_Form_Factory', array(), array(), '', false, false); + $cloneFactoryMock = $this->getMock('Mage_Backend_Model_Config_Clone_Factory', + array(), array(), '', false, false + ); + $this->_fieldsetFactoryMock = $this->getMock('Mage_Backend_Block_System_Config_Form_Fieldset_Factory', + array(), array(), '', false, false + ); + $this->_fieldFactoryMock = $this->getMock('Mage_Backend_Block_System_Config_Form_Field_Factory', + array(), array(), '', false, false + ); + $coreConfigMock = $this->getMock('Mage_Core_Model_Config', + array(), array(), '', false, false + ); + + $this->_backendConfigMock = $this->getMock('Mage_Backend_Model_Config', + array(), array(), '', false, false + ); + + $configFactoryMock->expects($this->once())->method('create') + ->with(array('section' => 'section_code', 'website' => 'website_code', 'store' => 'store_code')) + ->will($this->returnValue($this->_backendConfigMock)); + + $this->_backendConfigMock->expects($this->once())->method('load') + ->will($this->returnValue(array('section1/group1/field1' => 'some_value'))); + + $this->_formMock = $this->getMock('Varien_Data_Form', + array('setParent', 'setBaseUrl', 'addFieldset'), array(), '', false, false + ); + $data = array( + 'request' => $requestMock, + 'layout' => $layoutMock, + 'urlBuilder' => $this->_urlModelMock, + 'configStructure' => $this->_systemConfigMock, + 'configFactory' => $configFactoryMock, + 'formFactory' => $this->_formFactoryMock, + 'cloneModelFactory' => $cloneFactoryMock, + 'fieldsetFactory' => $this->_fieldsetFactoryMock, + 'fieldFactory' => $this->_fieldFactoryMock, + 'coreConfig' => $coreConfigMock, + ); + + $helper = new Magento_Test_Helper_ObjectManager($this); + $this->_object = $helper->getBlock('Mage_Backend_Block_System_Config_Form', $data); + $this->_object->setData('scope_id', 1); + } + + public function testInitFormWithoutSection() + { + $this->_formFactoryMock->expects($this->any())->method('create')->will($this->returnValue($this->_formMock)); + $this->_formMock->expects($this->once())->method('setParent')->with($this->_object); + $this->_formMock->expects($this->once())->method('setBaseUrl')->with('base_url'); + $this->_urlModelMock->expects($this->any())->method('getBaseUrl')->will($this->returnValue('base_url')); + + $this->_systemConfigMock->expects($this->once())->method('getElement') + ->with('section_code')->will($this->returnValue(null)); + + $this->_object->initForm(); + $this->assertEquals($this->_formMock, $this->_object->getForm()); + } + + public function testInitGroup() + { + $this->_formFactoryMock->expects($this->any())->method('create')->will($this->returnValue($this->_formMock)); + $this->_formMock->expects($this->once())->method('setParent')->with($this->_object); + $this->_formMock->expects($this->once())->method('setBaseUrl')->with('base_url'); + $this->_urlModelMock->expects($this->any())->method('getBaseUrl')->will($this->returnValue('base_url')); + + $fieldsetRendererMock = $this->getMock('Mage_Backend_Block_System_Config_Form_Fieldset', + array(), array(), '', false, false + ); + $this->_fieldsetFactoryMock->expects($this->once())->method('create') + ->will($this->returnValue($fieldsetRendererMock)); + + $cloneModelMock = $this->getMock('Mage_Backend_Model_Config', + array('getPrefixes'), array(), '', false, false + ); + + $cloneModelMock->expects($this->once())->method('getPrefixes')->will($this->returnValue(array())); + + $groupMock = $this->getMock('Mage_Backend_Model_Config_Structure_Element_Group', + array(), array(), '', false, false + ); + $groupMock->expects($this->once())->method('getFrontendModel')->will($this->returnValue(false)); + $groupMock->expects($this->any())->method('getPath')->will($this->returnValue('section_id_group_id')); + $groupMock->expects($this->once())->method('getLabel')->will($this->returnValue('label')); + $groupMock->expects($this->once())->method('getComment')->will($this->returnValue('comment')); + $groupMock->expects($this->once())->method('isExpanded')->will($this->returnValue(false)); + $groupMock->expects($this->once())->method('populateFieldset'); + $groupMock->expects($this->once())->method('shouldCloneFields')->will($this->returnValue(true)); + $groupMock->expects($this->once())->method('getCloneModel')->will($this->returnValue($cloneModelMock)); + $groupMock->expects($this->once()) + ->method('getDependencies')->with('store_code')->will($this->returnValue(array())); + + $sectionMock = $this->getMock('Mage_Backend_Model_Config_Structure_Element_Section', + array(), array(), '', false, false + ); + + $sectionMock->expects($this->once())->method('isVisible')->will($this->returnValue(true)); + $sectionMock->expects($this->once())->method('getChildren')->will($this->returnValue(array($groupMock))); + + $this->_systemConfigMock->expects($this->once())->method('getElement') + ->with('section_code')->will($this->returnValue($sectionMock)); + + $formFieldsetMock = $this->getMock('Varien_Data_Form_Element_Fieldset', + array(), array(), '', false, false + ); + + $params = array( + 'legend' => 'label', + 'comment' => 'comment', + 'expanded' => false, + ); + $this->_formMock->expects($this->once())->method('addFieldset')->with('section_id_group_id', $params) + ->will($this->returnValue($formFieldsetMock)); + $this->_object->initForm(); + } + + public function testInitFields() + { + // Parameters initialization + $fieldsetMock = $this->getMock('Varien_Data_Form_Element_Fieldset', array(), array(), '', false, false); + $groupMock = $this->getMock('Mage_Backend_Model_Config_Structure_Element_Group', + array(), array(), '', false, false + ); + $sectionMock = $this->getMock('Mage_Backend_Model_Config_Structure_Element_Section', + array(), array(), '', false, false + ); + $fieldPrefix = 'fieldPrefix'; + $labelPrefix = 'labelPrefix'; + + // Field Renderer Mock configuration + $fieldRendererMock = $this->getMock('Mage_Backend_Block_System_Config_Form_Field', + array(), array(), '', false, false + ); + $this->_fieldFactoryMock->expects($this->once())->method('create') + ->will($this->returnValue($fieldRendererMock)); + + $this->_backendConfigMock->expects($this->once())->method('extendConfig') + ->with('some/config/path', false, array('section1/group1/field1' => 'some_value')) + ->will($this->returnArgument(2)); + + + // Field mock configuration + $fieldMock = $this->getMock('Mage_Backend_Model_Config_Structure_Element_Field', + array(), array(), '', false, false + ); + $fieldMock->expects($this->any())->method('getPath') + ->will($this->returnValue('section1/group1/field1')); + $fieldMock->expects($this->any())->method('getGroupPath')->will($this->returnValue('some/config/path')); + $fieldMock->expects($this->once())->method('getSectionId')->will($this->returnValue('some_section')); + + $fieldMock->expects($this->once())->method('hasBackendModel')->will($this->returnValue(false)); + $fieldMock->expects($this->once())->method('getDependencies') + ->with($fieldPrefix)->will($this->returnValue(array())); + $fieldMock->expects($this->any())->method('getType')->will($this->returnValue('field')); + $fieldMock->expects($this->once())->method('getLabel')->will($this->returnValue('label')); + $fieldMock->expects($this->once())->method('getComment')->will($this->returnValue('comment')); + $fieldMock->expects($this->once())->method('getTooltip')->will($this->returnValue('tooltip')); + $fieldMock->expects($this->once())->method('getHint')->will($this->returnValue('hint')); + $fieldMock->expects($this->once())->method('getFrontendClass')->will($this->returnValue('frontClass')); + $fieldMock->expects($this->once())->method('showInDefault')->will($this->returnValue(false)); + $fieldMock->expects($this->any())->method('showInWebsite')->will($this->returnValue(false)); + $fieldMock->expects($this->once())->method('getData')->will($this->returnValue('fieldData')); + + + $fields = array($fieldMock); + $groupMock->expects($this->once())->method('getChildren')->will($this->returnValue($fields)); + + $sectionMock->expects($this->once())->method('getId')->will($this->returnValue('section1')); + + $formFieldMock = $this->getMockForAbstractClass('Varien_Data_Form_Element_Abstract', + array(), '', false, false, true, array('setRenderer') + ); + + $params = array( + 'name' => 'groups[group1][fields][fieldPrefixfield1][value]', + 'label' => 'label', + 'comment' => 'comment', + 'tooltip' => 'tooltip', + 'hint' => 'hint', + 'value' => 'some_value', + 'inherit' => false, + 'class' => 'frontClass', + 'field_config' => 'fieldData', + 'scope' => 'stores', + 'scope_id' => 1, + 'scope_label' => '[GLOBAL]', + 'can_use_default_value' => false, + 'can_use_website_value' => false, + ); + + $formFieldMock->expects($this->once())->method('setRenderer')->with($fieldRendererMock); + + $fieldsetMock->expects($this->once())->method('addField') + ->with('section1_group1_field1', 'field', $params) + ->will($this->returnValue($formFieldMock)); + + $fieldMock->expects($this->once())->method('populateInput'); + + $this->_object->initFields($fieldsetMock, $groupMock, $sectionMock, $fieldPrefix, $labelPrefix); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Backend/Block/System/Config/TabsTest.php b/dev/tests/unit/testsuite/Mage/Backend/Block/System/Config/TabsTest.php new file mode 100644 index 0000000000000000000000000000000000000000..7e1685fbba7cc4d34ce1fec2dd109ffda9dc60ad --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Backend/Block/System/Config/TabsTest.php @@ -0,0 +1,111 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Backend + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_Backend_Block_System_Config_TabsTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Backend_Block_System_Config_Tabs + */ + protected $_object; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_structureMock; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_requestMock; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_urlBuilderMock; + + protected function setUp() + { + $this->_requestMock = $this->getMock('Mage_Core_Controller_Request_Http', array(), array(), '', false); + $this->_requestMock->expects($this->any())->method('getParam')->with('section') + ->will($this->returnValue('currentSectionId')); + $this->_structureMock = $this->getMock('Mage_Backend_Model_Config_Structure', array(), array(), '', false); + $this->_structureMock->expects($this->once())->method('getTabs')->will($this->returnValue(array())); + $this->_urlBuilderMock = $this->getMock('Mage_Backend_Model_Url', array(), array(), '', false); + $layoutMock = $this->getMock('Mage_Core_Model_Layout', array(), array(), '', false); + $helperMock = $this->getMock('Mage_Core_Helper_Data', array('__', 'addPageHelpUrl'), array(), '', false); + $helperMock->expects($this->any())->method('__')->will($this->returnArgument(0)); + $helperMock->expects($this->once())->method('addPageHelpUrl')->with('currentSectionId/'); + $layoutMock->expects($this->any())->method('helper')->will($this->returnValue($helperMock)); + + $data = array( + 'configStructure' => $this->_structureMock, + 'request' => $this->_requestMock, + 'urlBuilder' => $this->_urlBuilderMock, + 'layout' => $layoutMock, + ); + $helper = new Magento_Test_Helper_ObjectManager($this); + $this->_object = $helper->getBlock('Mage_Backend_Block_System_Config_Tabs', $data); + } + + protected function tearDown() + { + unset($this->_object); + unset($this->_requestMock); + unset($this->_structureMock); + unset($this->_urlBuilderMock); + } + + public function testGetSectionUrl() + { + $this->_urlBuilderMock->expects($this->once())->method('getUrl') + ->with('*/*/*', array('_current' => true, 'section' => 'testSectionId')) + ->will($this->returnValue('testSectionUrl')); + $sectionMock = $this->getMock( + 'Mage_Backend_Model_Config_Structure_Element_Section', array(), array(), '', false + ); + $sectionMock->expects($this->once())->method('getId')->will($this->returnValue('testSectionId')); + $this->assertEquals('testSectionUrl', $this->_object->getSectionUrl($sectionMock)); + } + + public function testIsSectionActiveReturnsTrueForActiveSection() + { + $sectionMock = $this->getMock( + 'Mage_Backend_Model_Config_Structure_Element_Section', array(), array(), '', false + ); + $sectionMock->expects($this->once())->method('getId')->will($this->returnValue('currentSectionId')); + $this->assertTrue($this->_object->isSectionActive($sectionMock)); + } + + public function testIsSectionActiveReturnsFalseForNonActiveSection() + { + $sectionMock = $this->getMock( + 'Mage_Backend_Model_Config_Structure_Element_Section', array(), array(), '', false + ); + $sectionMock->expects($this->once())->method('getId')->will($this->returnValue('nonCurrentSectionId')); + $this->assertFalse($this->_object->isSectionActive($sectionMock)); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Backend/File/RequestDataTest.php b/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Backend/File/RequestDataTest.php new file mode 100644 index 0000000000000000000000000000000000000000..51528208c1f994bb77eb25edba1dc22e4379bc56 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Backend/File/RequestDataTest.php @@ -0,0 +1,109 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Backend + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_Backend_Model_Config_Backend_File_RequestDataTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Backend_Model_Config_Backend_File_RequestData + */ + protected $_model; + + protected function setUp() + { + $_FILES = array( + 'groups' => array( + 'name' => array( + 'group_1' => array( + 'fields' => array( + 'field_1' => array( + 'value' => 'file_name_1' + ) + ) + ), + 'group_2' => array( + 'groups' => array( + 'group_2_1' => array( + 'fields' => array( + 'field_2' => array( + 'value' => 'file_name_2' + ) + ) + ) + ) + ) + ), + 'tmp_name' => array( + 'group_1' => array( + 'fields' => array( + 'field_1' => array( + 'value' => 'file_tmp_name_1' + ) + ) + ), + 'group_2' => array( + 'groups' => array( + 'group_2_1' => array( + 'fields' => array( + 'field_2' => array( + 'value' => 'file_tmp_name_2' + ) + ) + ) + ) + ) + ) + ) + ); + + $this->_model = new Mage_Backend_Model_Config_Backend_File_RequestData(); + } + + protected function tearDown() + { + unset($this->_model); + } + + public function testGetNameRetrievesFileName() + { + $this->assertEquals('file_name_1', $this->_model->getName('section_1/group_1/field_1')); + $this->assertEquals('file_name_2', $this->_model->getName('section_1/group_2/group_2_1/field_2')); + } + + public function testGetTmpNameRetrievesFileName() + { + $this->assertEquals('file_tmp_name_1', $this->_model->getTmpName('section_1/group_1/field_1')); + $this->assertEquals('file_tmp_name_2', $this->_model->getTmpName('section_1/group_2/group_2_1/field_2')); + } + + public function testGetNameReturnsNullIfInvalidPathIsProvided() + { + $this->assertNull($this->_model->getName('section_1/group_2/field_1')); + $this->assertNull($this->_model->getName('section_1/group_3/field_1')); + $this->assertNull($this->_model->getName('section_1/group_1/field_2')); + $this->assertNull($this->_model->getName('section_1/group_1')); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Backend/Model/Config/LoaderTest.php b/dev/tests/unit/testsuite/Mage/Backend/Model/Config/LoaderTest.php new file mode 100644 index 0000000000000000000000000000000000000000..4313e72ecdc37813fe7f467762acf375cc4c9a95 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Backend/Model/Config/LoaderTest.php @@ -0,0 +1,89 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Backend + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_Backend_Model_Config_LoaderTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Backend_Model_Config_Loader + */ + protected $_model; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_configDataFactory; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_configCollection; + + protected function setUp() + { + $this->_configDataFactory = $this->getMock( + 'Mage_Core_Model_Config_Data_Factory', array('create', 'getCollection'), array(), '', false + ); + $this->_model = new Mage_Backend_Model_Config_Loader($this->_configDataFactory); + + $this->_configCollection = $this->getMock( + 'Mage_Core_Model_Resource_Config_Data_Collection', array(), array(), '', false + ); + $this->_configCollection->expects($this->once())->method('addScopeFilter')->with('scope', 'scopeId', 'section') + ->will($this->returnSelf()); + + $configDataMock = $this->getMock('Mage_Core_Model_Config_Data', array(), array(), '', false); + $this->_configDataFactory->expects($this->once())->method('create')->will($this->returnValue($configDataMock)); + $configDataMock->expects($this->any())->method('getCollection') + ->will($this->returnValue($this->_configCollection)); + + $this->_configCollection->expects($this->once())->method('getItems')->will($this->returnValue( + array( + new Varien_Object(array('path' => 'section', 'value' => 10, 'config_id' => 20)) + ) + )); + } + + protected function tearDown() + { + unset($this->_configDataFactory); + unset($this->_model); + unset($this->_configCollection); + } + + public function testGetConfigByPathInFullMode() + { + $expected = array('section' => array('path' => 'section', 'value' => 10, 'config_id' => 20)); + $this->assertEquals($expected, $this->_model->getConfigByPath('section', 'scope', 'scopeId', true)); + } + + public function testGetConfigByPath() + { + $expected = array('section' => 10); + $this->assertEquals($expected, $this->_model->getConfigByPath('section', 'scope', 'scopeId', false)); + } +} + diff --git a/dev/tests/unit/testsuite/Mage/Backend/Model/Config/ScopeDefinerTest.php b/dev/tests/unit/testsuite/Mage/Backend/Model/Config/ScopeDefinerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..397f278ec8960da759d10e2205b77f5b497b2b94 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Backend/Model/Config/ScopeDefinerTest.php @@ -0,0 +1,68 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Backend + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_Backend_Model_Config_ScopeDefinerTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Backend_Model_Config_ScopeDefiner + */ + protected $_model; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_requestMock; + + protected function setUp() + { + $this->_requestMock = $this->getMock('Mage_Core_Controller_Request_Http', array(), array(), '', false); + $this->_model = new Mage_Backend_Model_Config_ScopeDefiner($this->_requestMock); + } + + public function testGetScopeReturnsDefaultScopeIfNoScopeDataIsSpecified() + { + $this->assertEquals(Mage_Backend_Model_Config_ScopeDefiner::SCOPE_DEFAULT, $this->_model->getScope()); + } + + public function testGetScopeReturnsStoreScopeIfStoreIsSpecified() + { + $this->_requestMock->expects($this->any())->method('getParam')->will($this->returnValueMap(array( + array('website', null, 'someWebsite'), + array('store', null, 'someStore') + ))); + $this->assertEquals(Mage_Backend_Model_Config_ScopeDefiner::SCOPE_STORE, $this->_model->getScope()); + } + + public function testGetScopeReturnsWebsiteScopeIfWebsiteIsSpecified() + { + $this->_requestMock->expects($this->any())->method('getParam')->will($this->returnValueMap(array( + array('website', null, 'someWebsite'), + array('store', null, null) + ))); + $this->assertEquals(Mage_Backend_Model_Config_ScopeDefiner::SCOPE_WEBSITE, $this->_model->getScope()); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/ConverterTest.php b/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/ConverterTest.php index 27b4f5e62f93edbeabf3e9eee688f4be3e152f59..9e4e62f4dc9cf7d7aa799cfe424302cc31373219 100644 --- a/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/ConverterTest.php +++ b/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/ConverterTest.php @@ -34,7 +34,25 @@ class Mage_Backend_Model_Config_Structure_ConverterTest extends PHPUnit_Framewor public function setUp() { - $this->_model = new Mage_Backend_Model_Config_Structure_Converter(); + $factoryMock = $this->getMock('Mage_Backend_Model_Config_Structure_Mapper_Factory', + array(), + array(), + '', + false, + false + ); + + $mapperMock = $this->getMock('Mage_Backend_Model_Config_Structure_Mapper_Dependencies', + array(), + array(), + '', + false, + false + ); + $mapperMock->expects($this->any())->method('map')->will($this->returnArgument(0)); + $factoryMock->expects($this->any())->method('create')->will($this->returnValue($mapperMock)); + + $this->_model = new Mage_Backend_Model_Config_Structure_Converter($factoryMock); } public function testConvertCorrectlyConvertsConfigStructureToArray() diff --git a/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/Element/CompositeAbstractTest.php b/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/Element/CompositeAbstractTest.php new file mode 100644 index 0000000000000000000000000000000000000000..20b44703479b3173429343797c9a6c753966fb36 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/Element/CompositeAbstractTest.php @@ -0,0 +1,132 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Backend + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_Backend_Model_Config_Structure_Element_CompositeAbstractTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Backend_Model_Config_Structure_Element_CompositeAbstract + */ + protected $_model; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_factoryHelperMock; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_applicationMock; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_iteratorMock; + + /** + * Test element data + * + * @var array + */ + protected $_testData = array( + 'id' => 'elementId', + 'label' => 'Element Label', + 'customAttribute' => 'Custom attribute value', + 'children' => array( + 'someGroup' => array() + ) + ); + + public function setUp() + { + $this->_iteratorMock = $this->getMock( + 'Mage_Backend_Model_Config_Structure_Element_Iterator', array(), array(), '', false + ); + $this->_factoryHelperMock = $this->getMock('Mage_Core_Model_Factory_Helper', array(), array(), '', false); + $this->_applicationMock = $this->getMock('Mage_Core_Model_App', array(), array(), '', false); + + $this->_model = $this->getMockForAbstractClass( + 'Mage_Backend_Model_Config_Structure_Element_CompositeAbstract', + array($this->_factoryHelperMock, $this->_applicationMock, $this->_iteratorMock) + ); + } + + protected function tearDown() + { + unset($this->_iteratorMock); + unset($this->_applicationMock); + unset($this->_factoryHelperMock); + unset($this->_model); + } + + public function testSetDataInitializesChildIterator() + { + $this->_iteratorMock->expects($this->once())->method('setElements') + ->with(array('someGroup' => array()), 'scope'); + $this->_model->setData($this->_testData, 'scope'); + } + + public function testSetDataInitializesChildIteratorWithEmptyArrayIfNoChildrenArePresent() + { + $this->_iteratorMock->expects($this->once())->method('setElements') + ->with(array(), 'scope'); + $this->_model->setData(array(), 'scope'); + } + + public function testHasChildrenReturnsFalseIfThereAreNoChildren() + { + $this->assertFalse($this->_model->hasChildren()); + } + + public function testHasChildrenReturnsTrueIfThereAreVisibleChildren() + { + $this->_iteratorMock->expects($this->once())->method('current')->will($this->returnValue(true)); + $this->_iteratorMock->expects($this->once())->method('valid')->will($this->returnValue(true)); + $this->assertTrue($this->_model->hasChildren()); + } + + public function testIsVisibleReturnsTrueIfThereAreVisibleChildren() + { + $this->_applicationMock->expects($this->once())->method('isSingleStoreMode')->will($this->returnValue(true)); + $this->_iteratorMock->expects($this->once())->method('current')->will($this->returnValue(true)); + $this->_iteratorMock->expects($this->once())->method('valid')->will($this->returnValue(true)); + $this->assertTrue($this->_model->isVisible()); + } + + public function testIsVisibleReturnsTrueIfElementHasFrontEndModel() + { + $this->_applicationMock->expects($this->once())->method('isSingleStoreMode')->will($this->returnValue(true)); + $this->_model->setData(array('frontend_model' => 'Model_Name'), 'scope'); + $this->assertTrue($this->_model->isVisible()); + } + + public function testIsVisibleReturnsFalseIfElementHasNoChildrenAndFrontendModel() + { + $this->_applicationMock->expects($this->once())->method('isSingleStoreMode')->will($this->returnValue(true)); + $this->assertFalse($this->_model->isVisible()); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/Element/Dependency/MapperTest.php b/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/Element/Dependency/MapperTest.php new file mode 100644 index 0000000000000000000000000000000000000000..03fa10e7b20d577c50e099c5ce4b2d8546bbac73 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/Element/Dependency/MapperTest.php @@ -0,0 +1,201 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Backend + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_Backend_Model_Config_Structure_Element_Dependency_MapperTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Backend_Model_Config_Structure_Element_Dependency_Mapper + */ + protected $_model; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_applicationMock; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_configStructureMock; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_fieldMock; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_storeMock; + + /** + * Test data + * + * @var array + */ + protected $_testData; + + public function setUp() + { + $this->_applicationMock = $this->getMock('Mage_Core_Model_App', array(), array(), '', false); + $this->_configStructureMock = $this->getMock( + 'Mage_Backend_Model_Config_Structure', array(), array(), '', false + ); + $this->_fieldMock = $this->getMock( + 'Mage_Backend_Model_Config_Structure_Element_Field', array(), array(), '', false + ); + + $this->_storeMock = $this->getMock( + 'Mage_Core_Model_Store', array(), array(), '', false + ); + + $this->_testData = array( + 'field_4' => array( + 'id' => 'section_2/group_3/field_4', + 'value' => 'someValue', + 'dependPath' => array( + 'section_2', + 'group_3', + 'field_4', + ), + ), + ); + + $this->_configStructureMock->expects($this->once()) + ->method('getElement')->with('section_2/group_3/field_4')->will($this->returnValue($this->_fieldMock)); + + $this->_model = new Mage_Backend_Model_Config_Structure_Element_Dependency_Mapper( + $this->_applicationMock, + $this->_configStructureMock + ); + } + + public function testGetDependenciesWhenDependentValueIsNotEqualValueInStoreAndDependentIsInvisible() + { + $this->_applicationMock->expects($this->once()) + ->method('getStore')->with('store_code')->will($this->returnValue($this->_storeMock)); + + $this->_fieldMock->expects($this->once()) + ->method('getPath')->with('prefix')->will($this->returnValue('field_path')); + + $this->_fieldMock->expects($this->once())->method('isVisible')->will($this->returnValue(false)); + + $this->_storeMock->expects($this->once())->method('getConfig')->with('field_path')->will($this->returnValue(1)); + + $actual = $this->_model->getDependencies($this->_testData, 'store_code', 'prefix'); + + $expected = array('section_2_group_3_prefixfield_4' => 'someValue'); + + $this->assertEquals($expected, $actual); + } + + public function testGetDependenciesWhenDependentValueIsArray() + { + $testData = array( + 'field_4' => array( + 'id' => 'section_2/group_3/field_4', + 'value' => 'value1,value2', + 'separator' => ',', + 'dependPath' => array( + 'section_2', + 'group_3', + 'field_4', + ), + ), + ); + $this->_applicationMock->expects($this->once()) + ->method('getStore')->with('store_code')->will($this->returnValue($this->_storeMock)); + + $this->_fieldMock->expects($this->once()) + ->method('getPath')->with('prefix')->will($this->returnValue('field_path')); + + $this->_fieldMock->expects($this->once())->method('isVisible')->will($this->returnValue(false)); + + $this->_storeMock->expects($this->once()) + ->method('getConfig')->with('field_path')->will($this->returnValue('value2')); + + $actual = $this->_model->getDependencies($testData, 'store_code', 'prefix'); + + $expected = array(); + + $this->assertEquals($expected, $actual); + } + + public function testGetDependenciesWhenDependentValueIsEqualValueInStoreAndDependentIsInvisible() + { + $this->_fieldMock->expects($this->once())->method('isVisible')->will($this->returnValue(false)); + + $this->_applicationMock->expects($this->once()) + ->method('getStore')->with('store_code')->will($this->returnValue($this->_storeMock)); + + $this->_fieldMock->expects($this->once()) + ->method('getPath')->with('prefix')->will($this->returnValue('field_path')); + + $this->_storeMock->expects($this->once()) + ->method('getConfig')->with('field_path')->will($this->returnValue('someValue')); + + $actual = $this->_model->getDependencies($this->_testData, 'store_code', 'prefix'); + + $expected = array(); + + $this->assertEquals($expected, $actual); + } + + public function testGetDependenciesIsVisible() + { + $this->_fieldMock->expects($this->once())->method('isVisible')->will($this->returnValue(true)); + + $actual = $this->_model->getDependencies($this->_testData, 'store_code', 'prefix'); + + $expected = array('section_2_group_3_prefixfield_4' => 'someValue'); + + $this->assertEquals($expected, $actual); + } + + public function testGetDependenciesWithSeparator() + { + $testData = array( + 'field_4' => array( + 'id' => 'section_2/group_3/field_4', + 'value' => 'value1,value2', + 'separator' => ',', + 'dependPath' => array( + 'section_2', + 'group_3', + 'field_4', + ), + ), + ); + $this->_fieldMock->expects($this->once())->method('isVisible')->will($this->returnValue(true)); + + $actual = $this->_model->getDependencies($testData, 'store_code', 'prefix'); + + $expected = array('section_2_group_3_prefixfield_4' => array('value1', 'value2')); + + $this->assertEquals($expected, $actual); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/Element/FieldTest.php b/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/Element/FieldTest.php new file mode 100644 index 0000000000000000000000000000000000000000..4b11a5e6e9c32d7393d01c7e6da240defc7fcb29 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/Element/FieldTest.php @@ -0,0 +1,388 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Backend + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_Backend_Model_Config_Structure_Element_FieldTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Backend_Model_Config_Structure_Element_Field + */ + protected $_model; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_factoryHelperMock; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_applicationMock; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_backendFactoryMock; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_sourceFactoryMock; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_commentFactoryMock; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_blockFactoryMock; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_depMapperMock; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_iteratorMock; + + public function setUp() + { + $this->_iteratorMock = $this->getMock( + 'Mage_Backend_Model_Config_Structure_Element_Iterator', array(), array(), '', false + ); + $helperMock = $this->getMock('Mage_Backend_Helper_Data', array(), array(), '', false); + $helperMock->expects($this->any())->method('__')->will($this->returnCallback(function($arg) { + return 'translated ' . $arg; + })); + $this->_factoryHelperMock = $this->getMock('Mage_Core_Model_Factory_Helper', array(), array(), '', false); + $this->_factoryHelperMock->expects($this->any())->method('get')->with('Mage_Module_Helper_Data') + ->will($this->returnValue($helperMock)); + $this->_applicationMock = $this->getMock('Mage_Core_Model_App', array(), array(), '', false); + $this->_backendFactoryMock = $this->getMock( + 'Mage_Backend_Model_Config_BackendFactory', array(), array(), '', false + ); + $this->_sourceFactoryMock = $this->getMock( + 'Mage_Backend_Model_Config_SourceFactory', array(), array(), '', false + ); + $this->_commentFactoryMock = $this->getMock( + 'Mage_Backend_Model_Config_CommentFactory', array(), array(), '', false + ); + $this->_blockFactoryMock = $this->getMock( + 'Mage_Core_Model_BlockFactory', array(), array(), '', false + ); + $this->_depMapperMock = $this->getMock( + 'Mage_Backend_Model_Config_Structure_Element_Dependency_Mapper', array(), array(), '', false + ); + + $this->_model = new Mage_Backend_Model_Config_Structure_Element_Field( + $this->_factoryHelperMock, + $this->_applicationMock, + $this->_backendFactoryMock, + $this->_sourceFactoryMock, + $this->_commentFactoryMock, + $this->_blockFactoryMock, + $this->_depMapperMock + ); + } + + protected function tearDown() + { + unset($this->_iteratorMock); + unset($this->_applicationMock); + unset($this->_backendFactoryMock); + unset($this->_sourceFactoryMock); + unset($this->_commentFactoryMock); + unset($this->_depMapperMock); + unset($this->_factoryHelperMock); + unset($this->_model); + unset($this->_blockFactoryMock); + } + + public function testGetLabelTranslatesLabelAndPrefix() + { + $this->_model->setData(array('label' => 'element label', 'module' => 'Mage_Module'), 'scope'); + $this->assertEquals('translated some prefix translated element label', $this->_model->getLabel('some prefix')); + } + + public function testGetHintTranslatesElementHint() + { + $this->_model->setData(array('hint' => 'element hint', 'module' => 'Mage_Module'), 'scope'); + $this->assertEquals('translated element hint', $this->_model->getHint()); + } + + public function testGetCommentTranslatesCommentTextIfNoCommentModelIsProvided() + { + $this->_model->setData(array('comment' => 'element comment', 'module' => 'Mage_Module'), 'scope'); + $this->assertEquals('translated element comment', $this->_model->getComment()); + } + + public function testGetCommentRetrievesCommentFromCommentModelIfItsProvided() + { + $config = array('comment' => array('model' => 'Model_Name')); + $this->_model->setData($config, 'scope'); + $commentModelMock = $this->getMock('Mage_Backend_Model_Config_CommentInterface'); + $commentModelMock->expects($this->once()) + ->method('getCommentText') + ->with('currentValue') + ->will($this->returnValue('translatedValue')); + $this->_commentFactoryMock->expects($this->once()) + ->method('create') + ->with('Model_Name') + ->will($this->returnValue($commentModelMock)); + $this->assertEquals('translatedValue', $this->_model->getComment('currentValue')); + } + + public function testGetTooltipRetunrsTranslatedAttributeIfNoBlockIsProvided() + { + $this->_model->setData(array('tooltip' => 'element tooltip', 'module' => 'Mage_Module'), 'scope'); + $this->assertEquals('translated element tooltip', $this->_model->getTooltip()); + } + + public function testGetTooltipCreatesTooltipBlock() + { + $this->_model->setData(array('tooltip_block' => 'Mage_Core_Block_Tooltip'), 'scope'); + $tooltipBlock = $this->getMock('Mage_Core_Block'); + $tooltipBlock->expects($this->once())->method('toHtml')->will($this->returnValue('tooltip block')); + $this->_blockFactoryMock->expects($this->once()) + ->method('createBlock') + ->with('Mage_Core_Block_Tooltip') + ->will($this->returnValue($tooltipBlock)); + $this->assertEquals('tooltip block', $this->_model->getTooltip()); + } + + public function testGetTypeReturnsTextByDefault() + { + $this->assertEquals('text', $this->_model->getType()); + } + + public function testGetTypeReturnsProvidedType() + { + $this->_model->setData(array('type' => 'some_type'), 'scope'); + $this->assertEquals('some_type', $this->_model->getType()); + } + + public function testGetFrontendClass() + { + $this->assertEquals('', $this->_model->getFrontendClass()); + $this->_model->setData(array('frontend_class' => 'some class'), 'scope'); + $this->assertEquals('some class', $this->_model->getFrontendClass()); + } + + public function testHasBackendModel() + { + $this->assertFalse($this->_model->hasBackendModel()); + $this->_model->setData(array('backend_model' => 'some_model'), 'scope'); + $this->assertTrue($this->_model->hasBackendModel()); + } + + public function testGetBackendModelCreatesBackendModel() + { + $this->_backendFactoryMock->expects($this->once()) + ->method('create') + ->with('Mage_Model_Name') + ->will($this->returnValue('backend_model_object')); + $this->_model->setData(array('backend_model' => 'Mage_Model_Name'), 'scope'); + $this->assertEquals('backend_model_object', $this->_model->getBackendModel()); + } + + public function testGetSectionId() + { + $this->_model->setData(array('id' => 'fieldId', 'path' => 'sectionId/groupId/subgroupId'), 'scope'); + $this->assertEquals('sectionId', $this->_model->getSectionId()); + } + + public function testGetGroupPath() + { + $this->_model->setData(array('id' => 'fieldId', 'path' => 'sectionId/groupId/subgroupId'), 'scope'); + $this->assertEquals('sectionId/groupId/subgroupId', $this->_model->getGroupPath()); + } + + public function testGetConfigPath() + { + $this->_model->setData(array('config_path' => 'custom_config_path'), 'scope'); + $this->assertEquals('custom_config_path', $this->_model->getConfigPath()); + } + + public function testShowInDefault() + { + $this->assertFalse($this->_model->showInDefault()); + $this->_model->setData(array('showInDefault' => 1), 'scope'); + $this->assertTrue($this->_model->showInDefault()); + } + + public function testShowInWebsite() + { + $this->assertFalse($this->_model->showInWebsite()); + $this->_model->setData(array('showInWebsite' => 1), 'scope'); + $this->assertTrue($this->_model->showInWebsite()); + } + + public function testShowInStore() + { + $this->assertFalse($this->_model->showInStore()); + $this->_model->setData(array('showInStore' => 1), 'scope'); + $this->assertTrue($this->_model->showInStore()); + } + + public function testPopulateInput() + { + $params = array( + 'type' => 'multiselect', + 'can_be_empty' => true, + 'source_model' => 'some_model', + 'someArr' => array( + 'testVar' => 'testVal' + ) + ); + $this->_model->setData($params, 'scope'); + $elementMock = $this->getMock('Varien_Data_Form_Element_Text', array('setOriginalData'), array(), '', false); + unset($params['someArr']); + $elementMock->expects($this->once())->method('setOriginalData')->with($params); + $this->_model->populateInput($elementMock); + } + + public function testHasValidation() + { + $this->assertFalse($this->_model->hasValidation()); + $this->_model->setData(array('validate' => 'validation class'), 'scope'); + $this->assertTrue($this->_model->hasValidation()); + } + + public function testCanBeEmpty() + { + $this->assertFalse($this->_model->canBeEmpty()); + $this->_model->setData(array('can_be_empty' => true), 'scope'); + $this->assertTrue($this->_model->canBeEmpty()); + } + + public function testHasSourceModel() + { + $this->assertFalse($this->_model->hasSourceModel()); + $this->_model->setData(array('source_model' => 'some_model'), 'scope'); + $this->assertTrue($this->_model->hasSourceModel()); + } + + public function testGetOptionsUsesOptionsInterfaceIfNoMethodIsProvided() + { + $this->_model->setData(array('source_model' => 'Source_Model_Name'), 'scope'); + $sourceModelMock = $this->getMock('Mage_Core_Model_Option_ArrayInterface'); + $this->_sourceFactoryMock->expects($this->once()) + ->method('create') + ->with('Source_Model_Name') + ->will($this->returnValue($sourceModelMock)); + $expected = array('testVar' => 'testVal'); + $sourceModelMock->expects($this->once()) + ->method('toOptionArray') + ->with(false) + ->will($this->returnValue($expected)); + $this->assertEquals($expected, $this->_model->getOptions()); + } + + public function testGetOptionsUsesProvidedMethodOfSourceModel() + { + $this->_model->setData( + array('source_model' => 'Source_Model_Name::retrieveElements', 'path' => 'path', 'type' => 'multiselect'), + 'scope' + ); + $sourceModelMock = $this->getMock('Varien_Object', array('setPath', 'retrieveElements')); + $this->_sourceFactoryMock->expects($this->once()) + ->method('create') + ->with('Source_Model_Name') + ->will($this->returnValue($sourceModelMock)); + $expected = array('testVar1' => 'testVal1', 'testVar2' => array('subvar1' => 'subval1')); + $sourceModelMock->expects($this->once())->method('setPath')->with('path/'); + $sourceModelMock->expects($this->once()) + ->method('retrieveElements') + ->will($this->returnValue($expected)); + $this->assertEquals($expected, $this->_model->getOptions()); + } + + public function testGetOptionsParsesResultOfProvidedMethodOfSourceModelIfTypeIsNotMultiselect() + { + $this->_model->setData( + array('source_model' => 'Source_Model_Name::retrieveElements', 'path' => 'path', 'type' => 'select'), + 'scope' + ); + $sourceModelMock = $this->getMock('Varien_Object', array('setPath', 'retrieveElements')); + $this->_sourceFactoryMock->expects($this->once()) + ->method('create') + ->with('Source_Model_Name') + ->will($this->returnValue($sourceModelMock)); + $sourceModelMock->expects($this->once())->method('setPath')->with('path/'); + $sourceModelMock->expects($this->once()) + ->method('retrieveElements') + ->will($this->returnValue(array( + 'var1' => 'val1', + 'var2' => array( + 'subvar1' => 'subval1' + ) + ))); + $expected = array( + array('label' => 'val1', 'value' => 'var1'), + array('subvar1' => 'subval1') + ); + $this->assertEquals($expected, $this->_model->getOptions()); + } + + public function testGetDependenciesWithoutDependencies() + { + $this->_depMapperMock->expects($this->never())->method('getDependencies'); + } + + public function testGetDependenciesWithDependencies() + { + $fields = array( + 'field_4' => array( + 'id' => 'section_2/group_3/field_4', + 'value' => 'someValue', + 'dependPath' => array( + 'section_2', + 'group_3', + 'field_4', + ), + ), + 'field_1' => array( + 'id' => 'section_1/group_3/field_1', + 'value' => 'someValue', + 'dependPath' => array( + 'section_1', + 'group_3', + 'field_1', + ), + ), + ); + $this->_model->setData(array('depends' => array('fields' => $fields)), 0); + $this->_depMapperMock->expects($this->once()) + ->method('getDependencies')->with($fields, 'test_scope', 'test_prefix') + ->will($this->returnArgument(0)); + + $this->assertEquals($fields, $this->_model->getDependencies('test_prefix', 'test_scope')); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/Element/FlyweightFactoryTest.php b/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/Element/FlyweightFactoryTest.php new file mode 100644 index 0000000000000000000000000000000000000000..5a9fca19c9b245894fe6f68dfd7981a0afef5e93 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/Element/FlyweightFactoryTest.php @@ -0,0 +1,63 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Backend + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_Backend_Model_Config_Structure_Element_FlyweightFactoryTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Backend_Model_Config_Structure_Element_FlyweightFactory + */ + protected $_model; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_objectManagerMock; + + protected function setUp() + { + $this->_objectManagerMock = $this->getMock('Magento_ObjectManager_Zend', array(), array(), '', false); + $this->_model = new Mage_Backend_Model_Config_Structure_Element_FlyweightFactory($this->_objectManagerMock); + } + + protected function tearDown() + { + unset($this->_model); + unset($this->_objectManagerMock); + } + + public function testCreate() + { + $this->_objectManagerMock->expects($this->any())->method('create')->will($this->returnValueMap(array( + array('Mage_Backend_Model_Config_Structure_Element_Section', array(), true, 'sectionObject'), + array('Mage_Backend_Model_Config_Structure_Element_Group', array(), true, 'groupObject'), + array('Mage_Backend_Model_Config_Structure_Element_Field', array(), true, 'fieldObject'), + ))); + $this->assertEquals('sectionObject', $this->_model->create('section')); + $this->assertEquals('groupObject', $this->_model->create('group')); + $this->assertEquals('fieldObject', $this->_model->create('field')); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/Element/Group/ProxyTest.php b/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/Element/Group/ProxyTest.php new file mode 100644 index 0000000000000000000000000000000000000000..1dbac85efc9c40f7b66af12da60aa359dc3328cd --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/Element/Group/ProxyTest.php @@ -0,0 +1,66 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Backend + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_Backend_Model_Config_Structure_Element_Group_ProxyTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Backend_Model_Config_Structure_Element_Group_Proxy + */ + protected $_model; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_objectManagerMock; + + protected function setUp() + { + $this->_objectManagerMock = $this->getMock('Magento_ObjectManager_Zend', array(), array(), '', false); + $this->_model = new Mage_Backend_Model_Config_Structure_Element_Group_Proxy($this->_objectManagerMock); + } + + protected function tearDown() + { + unset($this->_model); + unset($this->_objectManagerMock); + } + + public function testProxyInitializesProxiedObjectOnFirstCall() + { + $groupMock = $this->getMock('Mage_Backend_Model_Config_Structure_Element_Group', array(), array(), '', false); + + $groupMock->expects($this->once())->method('setData'); + $groupMock->expects($this->once())->method('getId')->will($this->returnValue('group_id')); + $this->_objectManagerMock->expects($this->once()) + ->method('create') + ->with('Mage_Backend_Model_Config_Structure_Element_Group') + ->will($this->returnValue($groupMock)); + + $this->_model->setData(array(), ''); + $this->assertEquals('group_id', $this->_model->getId()); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/Element/GroupTest.php b/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/Element/GroupTest.php new file mode 100644 index 0000000000000000000000000000000000000000..4925bf3c75b9cb279a0857fa481309ef4fbcce5b --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/Element/GroupTest.php @@ -0,0 +1,181 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Backend + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_Backend_Model_Config_Structure_Element_GroupTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Backend_Model_Config_Structure_Element_Group + */ + protected $_model; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_factoryHelperMock; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_applicationMock; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_cloneFactoryMock; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_iteratorMock; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_depMapperMock; + + protected function setUp() + { + $this->_iteratorMock = $this->getMock( + 'Mage_Backend_Model_Config_Structure_Element_Iterator_Field', array(), array(), '', false + ); + $this->_factoryHelperMock = $this->getMock('Mage_Core_Model_Factory_Helper', array(), array(), '', false); + $this->_applicationMock = $this->getMock('Mage_Core_Model_App', array(), array(), '', false); + $this->_cloneFactoryMock = $this->getMock( + 'Mage_Backend_Model_Config_Clone_Factory', array(), array(), '', false + ); + $this->_depMapperMock = $this->getMock( + 'Mage_Backend_Model_Config_Structure_Element_Dependency_Mapper', array(), array(), '', false + ); + + $this->_model = new Mage_Backend_Model_Config_Structure_Element_Group( + $this->_factoryHelperMock, + $this->_applicationMock, + $this->_iteratorMock, $this->_cloneFactoryMock, + $this->_depMapperMock + ); + } + + protected function tearDown() + { + unset($this->_model); + unset($this->_iteratorMock); + unset($this->_factoryHelperMock); + unset($this->_applicationMock); + unset($this->_cloneFactoryMock); + unset($this->_depMapperMock); + } + + public function testShouldCloneFields() + { + $this->assertFalse($this->_model->shouldCloneFields()); + $this->_model->setData(array('clone_fields' => 1), 'scope'); + $this->assertTrue($this->_model->shouldCloneFields()); + $this->_model->setData(array('clone_fields' => 0), 'scope'); + $this->assertFalse($this->_model->shouldCloneFields()); + $this->_model->setData(array('clone_fields' => false), 'scope'); + $this->assertFalse($this->_model->shouldCloneFields()); + } + + /** + * @expectedException Mage_Core_Exception + */ + public function testGetCloneModelThrowsExceptionIfNoSourceModelIsSet() + { + $this->_model->getCloneModel(); + } + + public function testGetCloneModelCreatesCloneModel() + { + $cloneModel = $this->getMock('Mage_Core_Model_Config_Data', array(), array(), '', false); + $this->_depMapperMock = $this->getMock( + 'Mage_Backend_Model_Config_Structure_Element_Dependency_Mapper', array(), array(), '', false + ); + $this->_cloneFactoryMock->expects($this->once())->method('create') + ->with('clone_model_name') + ->will($this->returnValue($cloneModel)); + $this->_model->setData(array('clone_model' => 'clone_model_name'), 'scope'); + $this->assertEquals($cloneModel, $this->_model->getCloneModel()); + } + + public function testGetFieldsetSetsOnlyNonArrayValuesToFieldset() + { + $fieldsetMock = $this->getMock( + 'Varien_Data_Form_Element_Fieldset', array('setOriginalData'), array(), '', false + ); + $fieldsetMock->expects($this->once())->method('setOriginalData')->with(array( + 'var1' => 'val1', + 'var2' => 'val2' + )); + + $this->_model->setData(array('var1' => 'val1', 'var2' => 'val2', 'var3' => array('val3')), 'scope'); + $this->_model->populateFieldset($fieldsetMock); + } + + public function testIsExpanded() + { + $this->assertFalse($this->_model->isExpanded()); + $this->_model->setData(array('expanded' => 1), 'scope'); + $this->assertTrue($this->_model->isExpanded()); + $this->_model->setData(array('expanded' => 0), 'scope'); + $this->assertFalse($this->_model->isExpanded()); + $this->_model->setData(array('expanded' => null), 'scope'); + $this->assertFalse($this->_model->isExpanded()); + } + + public function testGetFieldsetCss() + { + $this->assertEquals('', $this->_model->getFieldsetCss()); + $this->_model->setData(array('fieldset_css' => 'some_css'), 'scope'); + $this->assertEquals('some_css', $this->_model->getFieldsetCss()); + } + + public function testGetDependenciesWithoutDependencies() + { + $this->_depMapperMock->expects($this->never())->method('getDependencies'); + } + + public function testGetDependenciesWithDependencies() + { + $fields = array( + 'field_4' => array( + 'id' => 'section_2/group_3/field_4', + 'value' => 'someValue', + 'dependPath' => array( + 'section_2', + 'group_3', + 'field_4' + ), + ), + ); + $this->_model->setData(array('depends' => array('fields' => $fields)), 0); + $this->_depMapperMock->expects($this->once()) + ->method('getDependencies')->with($fields, 'test_scope') + ->will($this->returnArgument(0)); + + $this->assertEquals($fields, $this->_model->getDependencies('test_scope')); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/Element/Iterator/FieldTest.php b/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/Element/Iterator/FieldTest.php new file mode 100644 index 0000000000000000000000000000000000000000..ab72ae57833a9e51b2a276a2b3e5fc37dd505c17 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/Element/Iterator/FieldTest.php @@ -0,0 +1,107 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Backend + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_Backend_Model_Config_Structure_Element_Iterator_FieldTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Backend_Model_Config_Structure_Element_Iterator_Field + */ + protected $_model; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_fieldMock; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_groupMock; + + public function setUp() + { + $this->_fieldMock = $this->getMock( + 'Mage_Backend_Model_Config_Structure_Element_Field', array(), array(), '', false + ); + $this->_groupMock = $this->getMock( + 'Mage_Backend_Model_Config_Structure_Element_Group', array(), array(), '', false + ); + $this->_model = new Mage_Backend_Model_Config_Structure_Element_Iterator_Field( + $this->_groupMock, $this->_fieldMock + ); + $this->_model->setElements(array( + 'someGroup_1' => array( + '_elementType' => 'group', + 'id' => 'someGroup_1' + ), + 'someField_1' => array( + '_elementType' => 'field', + 'id' => 'someField_1' + ), + 'someGroup_2' => array( + '_elementType' => 'group', + 'id' => 'someGroup_2' + ), + 'someField_2' => array( + '_elementType' => 'field', + 'id' => 'someField_2' + ) + ), 'scope'); + } + + protected function tearDown() + { + unset($this->_fieldMock); + unset($this->_groupMock); + unset($this->_model); + } + + public function testIteratorInitializesCorrespondingFlyweights() + { + $this->_groupMock->expects($this->at(0))->method('setData') + ->with(array('_elementType' => 'group', 'id' => 'someGroup_1'), 'scope'); + $this->_groupMock->expects($this->at(2))->method('setData') + ->with(array('_elementType' => 'group', 'id' => 'someGroup_2'), 'scope'); + $this->_groupMock->expects($this->any())->method('isVisible')->will($this->returnValue(true)); + + $this->_fieldMock->expects($this->at(0))->method('setData') + ->with(array('_elementType' => 'field', 'id' => 'someField_1'), 'scope'); + $this->_fieldMock->expects($this->at(2))->method('setData') + ->with(array('_elementType' => 'field', 'id' => 'someField_2'), 'scope'); + $this->_fieldMock->expects($this->any())->method('isVisible')->will($this->returnValue(true)); + + $items = array(); + foreach ($this->_model as $item) { + $items[] = $item; + } + $this->assertEquals($this->_groupMock, $items[0]); + $this->assertEquals($this->_fieldMock, $items[1]); + $this->assertEquals($this->_groupMock, $items[2]); + $this->assertEquals($this->_fieldMock, $items[3]); + } +} + diff --git a/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/Element/IteratorTest.php b/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/Element/IteratorTest.php new file mode 100644 index 0000000000000000000000000000000000000000..ed86ad9700be68aa5d805db5af0266f1865fe612 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/Element/IteratorTest.php @@ -0,0 +1,111 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Backend + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_Backend_Model_Config_Structure_Element_IteratorTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Backend_Model_Config_Structure_Element_Iterator + */ + protected $_model; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_flyweightMock; + + protected function setUp() + { + $elementData = array( + 'group1' => array( + 'id' => 1 + ), + 'group2' => array( + 'id' => 2 + ), + 'group3' => array( + 'id' => 3 + ) + ); + $this->_flyweightMock = $this->getMock( + 'Mage_Backend_Model_Config_Structure_Element_Group', array(), array(), '', false + ); + + $this->_model = new Mage_Backend_Model_Config_Structure_Element_Iterator($this->_flyweightMock); + $this->_model->setElements($elementData, 'scope'); + } + + protected function tearDown() + { + unset($this->_model); + unset($this->_flyweightMock); + } + + public function testIteratorInitializesFlyweight() + { + $this->_flyweightMock->expects($this->at(0))->method('setData')->with(array('id' => 1), 'scope'); + $this->_flyweightMock->expects($this->at(2))->method('setData')->with(array('id' => 2), 'scope'); + $this->_flyweightMock->expects($this->at(4))->method('setData')->with(array('id' => 3), 'scope'); + $this->_flyweightMock->expects($this->any())->method('isVisible')->will($this->returnValue(true)); + $counter = 0; + foreach ($this->_model as $item) { + $this->assertEquals($this->_flyweightMock, $item); + $counter++; + } + $this->assertEquals(3, $counter); + } + + public function testIteratorSkipsNonValidElements() + { + $this->_flyweightMock->expects($this->exactly(3))->method('isVisible')->will($this->returnValue(false)); + $this->_flyweightMock->expects($this->exactly(3))->method('setData'); + foreach ($this->_model as $item) { + unset($item); + $this->fail('Iterator shows non visible fields'); + } + } + + /** + * @param string $elementId + * @param bool $result + * @dataProvider isLastDataProvider + */ + public function testIsLast($elementId, $result) + { + $elementMock = $this->getMock('Mage_Backend_Model_Config_Structure_Element_Field', array(), array(), '', false); + $elementMock->expects($this->once())->method('getId')->will($this->returnValue($elementId)); + $this->assertEquals($result, $this->_model->isLast($elementMock)); + } + + public function isLastDataProvider() + { + return array( + array(1, false), + array(2, false), + array(3, true) + ); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/Element/SectionTest.php b/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/Element/SectionTest.php new file mode 100644 index 0000000000000000000000000000000000000000..c3310a3edff0bcffbde969f804c4227620fc1b57 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/Element/SectionTest.php @@ -0,0 +1,110 @@ + +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Backend + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_Backend_Model_Config_Structure_Element_SectionTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Backend_Model_Config_Structure_Element_Section + */ + protected $_model; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_factoryHelperMock; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_applicationMock; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_authorizationMock; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_iteratorMock; + + protected function setUp() + { + $this->_iteratorMock = $this->getMock( + 'Mage_Backend_Model_Config_Structure_Element_Iterator_Field', array(), array(), '', false + ); + $this->_factoryHelperMock = $this->getMock('Mage_Core_Model_Factory_Helper', array(), array(), '', false); + $this->_applicationMock = $this->getMock('Mage_Core_Model_App', array(), array(), '', false); + $this->_authorizationMock = $this->getMock('Mage_Core_Model_Authorization', array(), array(), '', false); + + $this->_model = new Mage_Backend_Model_Config_Structure_Element_Section( + $this->_factoryHelperMock, $this->_applicationMock, $this->_iteratorMock, $this->_authorizationMock + ); + } + + protected function tearDown() + { + unset($this->_model); + unset($this->_iteratorMock); + unset($this->_factoryHelperMock); + unset($this->_applicationMock); + unset($this->_authorizationMock); + } + + public function testIsAllowedReturnsFalseIfNoResourceIsSpecified() + { + $this->assertFalse($this->_model->isAllowed()); + } + + public function testIsAllowedReturnsTrueIfResourcesIsValidAndAllowed() + { + $this->_authorizationMock->expects($this->once()) + ->method('isAllowed') + ->with('someResource') + ->will($this->returnValue(true)); + + $this->_model->setData(array('resource' => 'someResource'), 'store'); + $this->assertTrue($this->_model->isAllowed()); + } + + public function testIsVisibleFirstChecksIfSectionIsAllowed() + { + $this->_applicationMock->expects($this->never())->method('isSingleStoreMode'); + $this->assertFalse($this->_model->isVisible()); + } + + public function testIsVisibleProceedsWithVisibilityCheckIfSectionIsAllowed() + { + $this->_authorizationMock->expects($this->any())->method('isAllowed')->will($this->returnValue(true)); + $this->_applicationMock->expects($this->once())->method('isSingleStoreMode')->will($this->returnValue(true)); + $this->_model->setData(array('resource' => 'Mage_Adminhtml::all'), 'scope'); + $this->_model->isVisible(); + } +} + + diff --git a/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/Element/TabTest.php b/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/Element/TabTest.php new file mode 100644 index 0000000000000000000000000000000000000000..725bf6845d4e1bc9c706287610daacf81b7963db --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/Element/TabTest.php @@ -0,0 +1,78 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Backend + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_Backend_Model_Config_Structure_Element_TabTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Backend_Model_Config_Structure_Element_Tab + */ + protected $_model; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_factoryHelperMock; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_applicationMock; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_iteratorMock; + + protected function setUp() + { + $this->_iteratorMock = $this->getMock( + 'Mage_Backend_Model_Config_Structure_Element_Iterator_Field', array(), array(), '', false + ); + $this->_factoryHelperMock = $this->getMock('Mage_Core_Model_Factory_Helper', array(), array(), '', false); + $this->_applicationMock = $this->getMock('Mage_Core_Model_App', array(), array(), '', false); + + $this->_model = new Mage_Backend_Model_Config_Structure_Element_Tab( + $this->_factoryHelperMock, $this->_applicationMock, $this->_iteratorMock + ); + } + + protected function tearDown() + { + unset($this->_model); + unset($this->_iteratorMock); + unset($this->_factoryHelperMock); + unset($this->_applicationMock); + } + + public function testIsVisibleOnlyChecksPresenceOfChildren() + { + $this->_model->setData(array('showInStore' => 0, 'showInWebsite' => 0, 'showInDefault' => 0), 'store'); + $this->_iteratorMock->expects($this->once())->method('current')->will($this->returnValue(true)); + $this->_iteratorMock->expects($this->once())->method('valid')->will($this->returnValue(true)); + $this->assertTrue($this->_model->isVisible()); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/ElementAbstractTest.php b/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/ElementAbstractTest.php new file mode 100644 index 0000000000000000000000000000000000000000..8fa160ac7ce2055f6a40644d7a6da6c96745e7a7 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/ElementAbstractTest.php @@ -0,0 +1,197 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Backend + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_Backend_Model_Config_Structure_ElementAbstractTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Backend_Model_Config_Structure_ElementAbstract + */ + protected $_model; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_factoryHelperMock; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_applicationMock; + + protected function setUp() + { + $this->_factoryHelperMock = $this->getMock('Mage_Core_Model_Factory_Helper', array(), array(), '', false); + $this->_applicationMock = $this->getMock('Mage_Core_Model_App', array(), array(), '', false); + + $this->_model = $this->getMockForAbstractClass( + 'Mage_Backend_Model_Config_Structure_ElementAbstract', + array($this->_factoryHelperMock, $this->_applicationMock) + ); + } + + protected function tearDown() + { + unset($this->_model); + unset($this->_factoryHelperMock); + unset($this->_applicationMock); + } + + public function testGetId() + { + $this->assertEquals('', $this->_model->getId()); + $this->_model->setData(array('id' => 'someId'), 'someScope'); + $this->assertEquals('someId', $this->_model->getId()); + } + + public function testGetLabelTranslatesLabel() + { + $helperMock = $this->getMock('Mage_Backend_Helper_Data', array(), array(), '', false); + $helperMock->expects($this->once())->method('__')->with('some_label') + ->will($this->returnValue('translatedLabel')); + $this->_factoryHelperMock->expects($this->once())->method('get')->with('Mage_Module_Helper_Data') + ->will($this->returnValue($helperMock)); + $this->assertEquals('', $this->_model->getLabel()); + $this->_model->setData(array('label' => 'some_label', 'module' => 'Mage_Module'), 'someScope'); + $this->assertEquals('translatedLabel', $this->_model->getLabel()); + } + + public function testGetCommentTranslatesComment() + { + $helperMock = $this->getMock('Mage_Backend_Helper_Data', array(), array(), '', false); + $helperMock->expects($this->once())->method('__')->with('some_comment') + ->will($this->returnValue('translatedComment')); + $this->_factoryHelperMock->expects($this->once())->method('get')->with('Mage_Module_Helper_Data') + ->will($this->returnValue($helperMock)); + $this->assertEquals('', $this->_model->getLabel()); + $this->_model->setData(array('label' => 'some_comment', 'module' => 'Mage_Module'), 'someScope'); + $this->assertEquals('translatedComment', $this->_model->getLabel()); + } + + public function testGetFrontEndModel() + { + $this->_model->setData(array('frontend_model' => 'frontend_model_name'), 'store'); + $this->assertEquals('frontend_model_name', $this->_model->getFrontendModel()); + } + + public function testGetAttribute() + { + $this->_model->setData(array( + 'id' => 'elementId', + 'label' => 'Element Label', + 'customAttribute' => 'Custom attribute value' + ), 'someScope'); + $this->assertEquals('elementId', $this->_model->getAttribute('id')); + $this->assertEquals('Element Label', $this->_model->getAttribute('label')); + $this->assertEquals('Custom attribute value', $this->_model->getAttribute('customAttribute')); + $this->assertNull($this->_model->getAttribute('nonexistingAttribute')); + } + + + public function testIsVisibleReturnsTrueInSingleStoreModeForNonHiddenElements() + { + $this->_applicationMock->expects($this->once())->method('isSingleStoreMode')->will($this->returnValue(true)); + $this->assertTrue($this->_model->isVisible()); + } + + public function testIsVisibleReturnsFalseInSingleStoreModeForHiddenElements() + { + $this->_applicationMock->expects($this->once())->method('isSingleStoreMode')->will($this->returnValue(true)); + $this->_model->setData(array('hide_in_single_store_mode' => 1), 'scope'); + $this->assertFalse($this->_model->isVisible()); + } + + /** + * @param array $settings + * @param string $scope + * @dataProvider isVisibleReturnsTrueForProperScopesDataProvider + */ + public function testIsVisibleReturnsTrueForProperScopes($settings, $scope) + { + $this->_model->setData($settings, $scope); + $this->assertTrue($this->_model->isVisible()); + } + + public function isVisibleReturnsTrueForProperScopesDataProvider() + { + return array( + array( + array('showInDefault' => 1, 'showInStore' => 0, 'showInWebsite' => 0), + Mage_Backend_Model_Config_ScopeDefiner::SCOPE_DEFAULT + ), + array( + array('showInDefault' => 0, 'showInStore' => 1, 'showInWebsite' => 0), + Mage_Backend_Model_Config_ScopeDefiner::SCOPE_STORE + ), + array( + array('showInDefault' => 0, 'showInStore' => 0, 'showInWebsite' => 1), + Mage_Backend_Model_Config_ScopeDefiner::SCOPE_WEBSITE + ), + ); + } + + /** + * @param array $settings + * @param string $scope + * @dataProvider isVisibleReturnsFalseForNonProperScopesDataProvider + */ + public function testIsVisibleReturnsFalseForNonProperScopes($settings, $scope) + { + $this->_model->setData($settings, $scope); + $this->assertFalse($this->_model->isVisible()); + } + + public function isVisibleReturnsFalseForNonProperScopesDataProvider() + { + return array( + array( + array('showInDefault' => 0, 'showInStore' => 1, 'showInWebsite' => 1), + Mage_Backend_Model_Config_ScopeDefiner::SCOPE_DEFAULT + ), + array( + array('showInDefault' => 1, 'showInStore' => 0, 'showInWebsite' => 1), + Mage_Backend_Model_Config_ScopeDefiner::SCOPE_STORE + ), + array( + array('showInDefault' => 1, 'showInStore' => 1, 'showInWebsite' => 0), + Mage_Backend_Model_Config_ScopeDefiner::SCOPE_WEBSITE + ), + ); + } + + public function testGetClass() + { + $this->assertEquals('', $this->_model->getClass()); + $this->_model->setData(array('class' => 'some_class'), 'store'); + $this->assertEquals('some_class', $this->_model->getClass()); + } + + public function testGetPathBuildsFullPath() + { + $this->_model->setData(array('path' => 'section/group', 'id' => 'fieldId'), 'scope'); + $this->assertEquals('section/group/prefix_fieldId', $this->_model->getPath('prefix_')); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/Mapper/DependenciesTest.php b/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/Mapper/DependenciesTest.php new file mode 100644 index 0000000000000000000000000000000000000000..25468dbbd48dde505813b9f3f88743aaa5104b12 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/Mapper/DependenciesTest.php @@ -0,0 +1,48 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Backend + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_Backend_Model_Config_Structure_Mapper_DependenciesTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Backend_Model_Config_Structure_Mapper_Dependencies + */ + protected $_model; + + public function setUp() + { + $this->_model = new Mage_Backend_Model_Config_Structure_Mapper_Dependencies(); + } + + public function testMap() + { + $data = require_once (realpath(dirname(__FILE__) . '/../../../') . '/_files/dependencies_data.php'); + $expected = require_once (realpath(dirname(__FILE__) . '/../../../') . '/_files/dependencies_mapped.php'); + + $actual = $this->_model->map($data); + $this->assertEquals($expected, $actual); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/Mapper/PathTest.php b/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/Mapper/PathTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b86d31f39438f589a57e4ed647f18778ebf30579 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/Mapper/PathTest.php @@ -0,0 +1,108 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Backend + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_Backend_Model_Config_Structure_Mapper_PathTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Backend_Model_Config_Structure_Mapper_Path + */ + protected $_model; + + public function setUp() + { + $this->_model = new Mage_Backend_Model_Config_Structure_Mapper_Path(); + } + + public function testMap() + { + $data = array( + 'config' => array( + 'system' => array( + 'sections' => array( + 'section_1' => array( + 'id' => 'section_1', + 'children' => array( + 'group_1' => array( + 'id' => 'group_1', + 'children' => array( + 'field_1' => array( + 'id' => 'field_1', + ), + 'group_1.1' => array( + 'id' => 'group_1.1', + 'children' => array( + 'field_1.2' => array( + 'id' => 'field_1.2', + ) + ), + ), + ), + ), + ), + ), + ), + ), + ), + ); + $expected = array( + 'config' => array( + 'system' => array( + 'sections' => array( + 'section_1' => array( + 'id' => 'section_1', + 'children' => array( + 'group_1' => array( + 'id' => 'group_1', + 'children' => array( + 'field_1' => array( + 'id' => 'field_1', + 'path' => 'section_1/group_1', + ), + 'group_1.1' => array( + 'id' => 'group_1.1', + 'children' => array( + 'field_1.2' => array( + 'id' => 'field_1.2', + 'path' => 'section_1/group_1/group_1.1', + ), + ), + 'path' => 'section_1/group_1', + ), + ), + 'path' => 'section_1', + ), + ), + ), + ), + ), + ), + ); + + $actual = $this->_model->map($data); + $this->assertEquals($expected, $actual); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/Mapper/SortingTest.php b/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/Mapper/SortingTest.php new file mode 100644 index 0000000000000000000000000000000000000000..732655ee2f901b1a0a5e1350e267a1e7b7e4a11f --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/Mapper/SortingTest.php @@ -0,0 +1,124 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Backend + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_Backend_Model_Config_Structure_Mapper_SortingTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Backend_Model_Config_Structure_Mapper_Sorting + */ + protected $_model; + + public function setUp() + { + $this->_model = new Mage_Backend_Model_Config_Structure_Mapper_Sorting(); + } + + public function testMap() + { + $tabs = array( + 'tab_1' => array('sortOrder' => 10), + 'tab_2' => array('sortOrder' => 5), + 'tab_3' => array('sortOrder' => 1), + ); + + $sections = array( + 'section_1' => array('sortOrder' => 10), + 'section_2' => array('sortOrder' => 5), + 'section_3' => array('sortOrder' => 1), + 'section_4' => array( + 'sortOrder' => 500, + 'children' => array( + 'group_1' => array('sortOrder' => 150), + 'group_2' => array('sortOrder' => 20), + 'group_3' => array( + 'sortOrder' => 30, + 'children' => array( + 'field_1' => array('sortOrder' => 200), + 'field_2' => array('sortOrder' => 100), + 'subGroup' => array( + 'sortOrder' => 0, + 'children' => array( + 'field_4' => array('sortOrder' => 200), + 'field_5' => array('sortOrder' => 100), + ), + ), + ) + ), + ) + ), + ); + + $data = array( + 'config' => array( + 'system' => array( + 'tabs' => $tabs, + 'sections' => $sections, + ) + ) + ); + + $expected = array( + 'config' => array( + 'system' => array( + 'tabs' => array( + 'tab_3' => array('sortOrder' => 1), + 'tab_2' => array('sortOrder' => 5), + 'tab_1' => array('sortOrder' => 10), + ), + 'sections' => array( + 'section_3' => array('sortOrder' => 1), + 'section_2' => array('sortOrder' => 5), + 'section_1' => array('sortOrder' => 10), + 'section_4' => array( + 'sortOrder' => 500, + 'children' => array( + 'group_2' => array('sortOrder' => 20), + 'group_3' => array( + 'sortOrder' => 30, + 'children' => array( + 'subGroup' => array( + 'sortOrder' => 0, + 'children' => array( + 'field_5' => array('sortOrder' => 100), + 'field_4' => array('sortOrder' => 200), + ), + ), + 'field_2' => array('sortOrder' => 100), + 'field_1' => array('sortOrder' => 200), + ), + ), + 'group_1' => array('sortOrder' => 150), + ), + ), + ), + ), + ), + ); + $actual = $this->_model->map($data); + $this->assertEquals($expected, $actual); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/ReaderTest.php b/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/ReaderTest.php index a34385468c525da7f6e2704e1c4757e82edee55b..84e6f6e9091137b1c5bb0974255a1efee2f12d67 100644 --- a/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/ReaderTest.php +++ b/dev/tests/unit/testsuite/Mage/Backend/Model/Config/Structure/ReaderTest.php @@ -42,16 +42,19 @@ class Mage_Backend_Model_Config_Structure_ReaderTest extends PHPUnit_Framework_T */ protected $_cacheMock; + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_converterMock; + public function setUp() { $this->_appConfigMock = $this->getMock('Mage_Core_Model_Config', array(), array(), '', false); $this->_cacheMock = $this->getMock('Mage_Core_Model_Cache', array(), array(), '', false); $this->_cacheMock->expects($this->any())->method('canUse')->will($this->returnValue(true)); - - $this->_model = new Mage_Backend_Model_Config_Structure_Reader(array( - 'config' => $this->_appConfigMock, - 'cache' => $this->_cacheMock - )); + $this->_converterMock = $this->getMock( + 'Mage_Backend_Model_Config_Structure_Converter', array(), array(), '', false + ); } public function testGetConfigurationLoadsConfigFromCacheWhenCacheIsEnabled() @@ -64,31 +67,32 @@ class Mage_Backend_Model_Config_Structure_ReaderTest extends PHPUnit_Framework_T ->with(Mage_Backend_Model_Config_Structure_Reader::CACHE_SYSTEM_CONFIGURATION_STRUCTURE) ->will($this->returnValue($cachedData)); - $this->assertEquals($cachedObject, $this->_model->getConfiguration()); + $model = new Mage_Backend_Model_Config_Structure_Reader( + $this->_appConfigMock, $this->_cacheMock, $this->_converterMock + ); + $this->assertEquals($cachedObject, $model->getData()); } public function testGetConfigurationLoadsConfigFromFilesAndCachesIt() { + $expected = array('var' => 'val'); $this->_cacheMock->expects($this->once())->method('load')->will($this->returnValue(false)); - $testFiles = array('file1', 'file2'); - + $this->_converterMock->expects($this->once())->method('convert')->will($this->returnValue( + array('config' => array('system' => $expected)) + )); + $filePath = dirname(dirname(__DIR__)) . '/_files'; $this->_appConfigMock->expects($this->once()) ->method('getModuleConfigurationFiles') - ->will($this->returnValue($testFiles)); - - $configMock = new StdClass(); - $configMock->foo = "bar"; - - $this->_appConfigMock->expects($this->once()) - ->method('getModelInstance') - ->with('Mage_Backend_Model_Config_Structure', array('sourceFiles' => $testFiles)) - ->will($this->returnValue($configMock)); + ->will($this->returnValue(array($filePath . '/system_2.xml'))); $this->_cacheMock->expects($this->once())->method('save')->with( - $this->isType('string') + serialize($expected) ); - $this->assertEquals($configMock, $this->_model->getConfiguration()); + $model = new Mage_Backend_Model_Config_Structure_Reader( + $this->_appConfigMock, $this->_cacheMock, $this->_converterMock, false + ); + $this->assertEquals($expected, $model->getData()); } } diff --git a/dev/tests/unit/testsuite/Mage/Backend/Model/Config/StructureTest.php b/dev/tests/unit/testsuite/Mage/Backend/Model/Config/StructureTest.php index 00e5e0fd627f49f03b4379bb18d1373ca088862d..19b108e2ec26b10ca44abb1633278c026a6a0092 100644 --- a/dev/tests/unit/testsuite/Mage/Backend/Model/Config/StructureTest.php +++ b/dev/tests/unit/testsuite/Mage/Backend/Model/Config/StructureTest.php @@ -35,210 +35,173 @@ class Mage_Backend_Model_Config_StructureTest extends PHPUnit_Framework_TestCase /** * @var PHPUnit_Framework_MockObject_MockObject */ - protected $_appMock; + protected $_flyweightFactory; /** * @var PHPUnit_Framework_MockObject_MockObject */ - protected $_converterMock; + protected $_tabIteratorMock; /** * @var PHPUnit_Framework_MockObject_MockObject */ - protected $_helperFactoryMock; + protected $_readerMock; - public function setUp() - { - $filePath = dirname(__DIR__) . '/_files'; - - $this->_appMock = $this->getMock('Mage_Core_Model_App', array(), array(), '', false); - $this->_converterMock = $this->getMock('Mage_Backend_Model_Config_Structure_Converter'); - $this->_converterMock->expects($this->once())->method('convert')->will($this->returnValue( - require $filePath . '/converted_config.php' - )); - - $this->_helperFactoryMock = $this->getMock('Mage_Core_Model_Factory_Helper', array(), array(), '', false); - $helperMock = $this->getMock('Mage_Backend_Helper_Data', array(), array(), '', false); - $helperMock->expects($this->any())->method('__')->will($this->returnArgument(0)); - $this->_helperFactoryMock->expects($this->any())->method('get')->will($this->returnValue($helperMock)); - - $this->_model = new Mage_Backend_Model_Config_Structure(array( - 'sourceFiles' => array( - $filePath . '/system_2.xml' - ), - 'app' => $this->_appMock, - 'converter' => $this->_converterMock, - 'helperFactory' => $this->_helperFactoryMock - )); - } - - public function testGetSectionsReturnsAllSections() - { - - $sections = $this->_model->getSections(); - $this->assertCount(2, $sections); - $section = reset($sections); - $this->assertEquals('section_1', $section['id']); - $section = next($sections); - $this->assertEquals('section_2', $section['id']); - } - - public function testGetSectionReturnsSectionByKey() - { - $section = $this->_model->getSection('section_1'); - $this->assertEquals('section_1', $section['id']); - $section = $this->_model->getSection(null, 'section_1'); - $this->assertEquals('section_1', $section['id']); - $section = $this->_model->getSection(null, null, 'section_1'); - $this->assertEquals('section_1', $section['id']); - } - - public function testHasChildrenReturnsFalseIfNodeCannotBeShown() - { - $this->assertFalse($this->_model->hasChildren(array())); - } - - public function testHasChildrenReturnsTrueIfNodeIsField() - { - $this->_appMock->expects($this->any())->method('isSingleStoreMode')->will($this->returnValue(true)); - $this->assertTrue($this->_model->hasChildren(array())); - } + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_scopeDefinerMock; - public function testHasChildrenReturnsFalseForEmptySection() - { - $this->_appMock->expects($this->any())->method('isSingleStoreMode')->will($this->returnValue(true)); - $this->assertFalse($this->_model->hasChildren(array('groups' => array()))); - } + /** + * @var array + */ + protected $_structureData; - public function testHasChildrenReturnsFalseForEmptyGroup() + public function setUp() { - $this->_appMock->expects($this->any())->method('isSingleStoreMode')->will($this->returnValue(true)); - $this->assertFalse($this->_model->hasChildren(array('fields' => array()))); - } + $this->_flyweightFactory = $this->getMock( + 'Mage_Backend_Model_Config_Structure_Element_FlyweightFactory', array(), array(), '', false + ); + $this->_tabIteratorMock = $this->getMock( + 'Mage_Backend_Model_Config_Structure_Element_Iterator_Tab', array(), array(), '', false + ); + $this->_readerMock = $this->getMock( + 'Mage_Backend_Model_Config_Structure_Reader', array(), array(), '', false + ); + $this->_scopeDefinerMock = $this->getMock( + 'Mage_Backend_Model_Config_ScopeDefiner', array(), array(), '', false + ); + $this->_scopeDefinerMock->expects($this->any())->method('getScope')->will($this->returnValue('scope')); - public function testCanShowNodeReturnsFalseByDefault() - { - $this->assertFalse($this->_model->hasChildren(array())); + $filePath = dirname(__DIR__) . '/_files'; + $this->_structureData = require $filePath . '/converted_config.php'; + $this->_readerMock->expects($this->once())->method('getData') + ->will($this->returnValue($this->_structureData['config']['system']) + ); + $this->_model = new Mage_Backend_Model_Config_Structure( + $this->_readerMock, $this->_tabIteratorMock, $this->_flyweightFactory, $this->_scopeDefinerMock + ); } - /** - * @param array $node - * @param string $website - * @param string $store - * @dataProvider testCanShowNodeReturnsTrueForDisplayableNodesDataProvider - */ - public function testCanShowNodeReturnsTrueForDisplayableNodes($node, $website, $store) + protected function tearDown() { - $this->assertTrue($this->_model->hasChildren($node, $website, $store)); + unset($this->_flyweightFactory); + unset($this->_scopeDefinerMock); + unset($this->_structureData); + unset($this->_tabIteratorMock); + unset($this->_readerMock); + unset($this->_model); } - public static function testCanShowNodeReturnsTrueForDisplayableNodesDataProvider() + public function testGetTabsBuildsSectionTree() { - return array( - array(array('showInStore' => 1), null, 'store'), - array(array('showInWebsite' => 1), 'website', null), - array(array('showInDefault' => 1), null, null) + $this->_readerMock = $this->getMock( + 'Mage_Backend_Model_Config_Structure_Reader', array(), array(), '', false + ); + $this->_readerMock->expects($this->any())->method('getData')->will($this->returnValue( + array('sections' => array('section1' => array('tab' => 'tab1')), 'tabs' => array('tab1' => array())) + )); + $expected = array('tab1' => array('children' => array('section1' => array('tab' => 'tab1')))); + $model = new Mage_Backend_Model_Config_Structure( + $this->_readerMock, $this->_tabIteratorMock, $this->_flyweightFactory, $this->_scopeDefinerMock ); + $this->_tabIteratorMock->expects($this->once())->method('setElements')->with($expected); + $this->assertEquals($this->_tabIteratorMock, $model->getTabs()); } /** - * @param array $node - * @param string $website - * @param string $store - * @dataProvider testCanShowNodeReturnsFalseForNonDisplayableNodesDataProvider + * @param string $path + * @param string $expectedType + * @param string $expectedId + * @param string $expectedPath + * @dataProvider emptyElementDataProvider */ - public function testCanShowNodeReturnsFalseForNonDisplayableNodes($node, $website, $store) - { - $this->assertFalse($this->_model->hasChildren($node, $website, $store)); + public function testGetElementReturnsEmptyElementIfNotExistingElementIsRequested( + $path, $expectedType, $expectedId, $expectedPath + ) { + $expectedConfig = array( + 'id' => $expectedId, + 'path' => $expectedPath, + '_elementType' => $expectedType + ); + $elementMock = $this->getMock('Mage_Backend_Model_Config_Structure_ElementInterface'); + $elementMock->expects($this->once())->method('setData')->with($expectedConfig); + $this->_flyweightFactory->expects($this->once())->method('create')->with($expectedType) + ->will($this->returnValue($elementMock)); + $this->assertEquals($elementMock, $this->_model->getElement($path)); } - public static function testCanShowNodeReturnsFalseForNonDisplayableNodesDataProvider() + public function emptyElementDataProvider() { return array( - array(array('showInStore' => 0), null, 'store'), - array(array('showInWebsite' => 0), 'website', null), - array(array('showInStore' => 1), 'website', null), - array(array('showInWebsite' => 1), null, 'store'), - array(array('showInDefault' => 0), null, null) + array('someSection/group_1/nonexisting_field', 'field', 'nonexisting_field', 'someSection/group_1'), + array('section_1/group_1/nonexisting_field', 'field', 'nonexisting_field', 'section_1/group_1'), + array('section_1/nonexisting_group', 'group', 'nonexisting_group', 'section_1'), + array('nonexisting_section', 'section', 'nonexisting_section', ''), ); } - public function testCanShowNodeReturnsTrueForNonDisplayableNodesInSingleStoreMode() - { - $this->_appMock->expects($this->any())->method('isSingleStoreMode')->will($this->returnValue(true)); - $this->assertTrue($this->_model->hasChildren(array(), null, null)); - } - - public function testCanShowNodeReturnsFalseForNonDisplayableNodesInSingleStoreModeWithFlag() + public function testGetElementReturnsProperElementByPath() { - $this->_appMock->expects($this->any())->method('isSingleStoreMode')->will($this->returnValue(true)); - $this->assertTrue($this->_model->hasChildren(array('hide_in_single_store_mode'), null, null)); - } + $elementMock = $this->getMock('Mage_Backend_Model_Config_Structure_Element_Field', array(), array(), '', false); + $section = $this->_structureData['config']['system']['sections']['section_1']; + $fieldData = $section['children']['group_level_1']['children']['field_3']; + $elementMock->expects($this->once())->method('setData')->with($fieldData, 'scope'); - public function testGetAttributeModuleReturnsBackendModuleByDefault() - { - $this->assertEquals('Mage_Backend', $this->_model->getAttributeModule()); + $this->_flyweightFactory->expects($this->once())->method('create') + ->with('field') + ->will($this->returnValue($elementMock)); + $this->assertEquals($elementMock, $this->_model->getElement('section_1/group_level_1/field_3')); } - public function testGetAttributeModuleExtractsModuleAttributeFromNodes() + public function testGetFirstSectionReturnsFirstAllowedSection() { - $this->assertEquals('Mage_Module1', $this->_model->getAttributeModule( - array('module' => 'Mage_Module1') - )); - $this->assertEquals('Mage_Module2', $this->_model->getAttributeModule( - array('module' => 'Mage_Module1'), array('module' => 'Mage_Module2') - )); - $this->assertEquals('Mage_Module3', $this->_model->getAttributeModule( - array('module' => 'Mage_Module1'), array('module' => 'Mage_Module2'), array('module' => 'Mage_Module3') - )); + $tabMock = $this->getMock( + 'Mage_Backend_Model_Config_Structure_Element_Tab', + array('current', 'getChildren', 'rewind'), array(), '', false + ); + $tabMock->expects($this->any())->method('getChildren')->will($this->returnSelf()); + $tabMock->expects($this->once())->method('rewind'); + $tabMock->expects($this->once())->method('current')->will($this->returnValue('currentSection')); + $this->_tabIteratorMock->expects($this->once())->method('rewind'); + $this->_tabIteratorMock->expects($this->once())->method('current')->will($this->returnValue($tabMock)); + $this->assertEquals('currentSection', $this->_model->getFirstSection()); } - /** - * @expectedException InvalidArgumentException - */ - public function testGetSystemConfigNodeLabelThrowsExceptionIfSectionNameIsWrong() + public function testGetElementReturnsProperElementByPathCachesObject() { - $this->_model->getSystemConfigNodeLabel('unexistentSection'); - } + $elementMock = $this->getMock('Mage_Backend_Model_Config_Structure_Element_Field', array(), array(), '', false); + $section = $this->_structureData['config']['system']['sections']['section_1']; + $fieldData = $section['children']['group_level_1']['children']['field_3']; + $elementMock->expects($this->once())->method('setData')->with($fieldData, 'scope'); - /** - * @expectedException InvalidArgumentException - */ - public function testGetSystemConfigNodeLabelThrowsExceptionIfGroupNameIsWrong() - { - $this->_model->getSystemConfigNodeLabel('section_1', 'unexistent_group'); + $this->_flyweightFactory->expects($this->once())->method('create') + ->with('field') + ->will($this->returnValue($elementMock)); + $this->assertEquals($elementMock, $this->_model->getElement('section_1/group_level_1/field_3')); + $this->assertEquals($elementMock, $this->_model->getElement('section_1/group_level_1/field_3')); } /** - * @expectedException InvalidArgumentException + * @param $attributeName + * @param $attributeValue + * @param $paths + * @dataProvider getFieldPathsByAttributeDataProvider */ - public function testGetSystemConfigNodeLabelThrowsExceptionIfFieldNameIsWrong() + public function testGetFieldPathsByAttribute($attributeName, $attributeValue, $paths) { - $this->_model->getSystemConfigNodeLabel('section_1', 'group_1', 'unexistent_field'); + $this->assertEquals($paths, $this->_model->getFieldPathsByAttribute($attributeName, $attributeValue)); } - public function testGetSystemConfigNodeLabelRetreivesLabel() + public function getFieldPathsByAttributeDataProvider() { - $this->assertEquals('Section 1 New', $this->_model->getSystemConfigNodeLabel('section_1')); - $this->assertEquals('Group 1 New', $this->_model->getSystemConfigNodeLabel('section_1', 'group_1')); - $this->assertEquals('Field 2', $this->_model->getSystemConfigNodeLabel('section_1', 'group_1', 'field_2')); - } - - public function testGetEncryptedNodeEntriesPathsReturnsListOfEncryptedFieldPaths() - { - $expected = array( - 'section_1/group_1/field_2', - 'section_2/group_3/field_4' - ); - $this->assertEquals($expected, $this->_model->getEncryptedNodeEntriesPaths()); - } - - public function testGetEncryptedNodeEntriesPathsReturnsListOfEncryptedFieldPathsReturnsExplodedPaths() - { - $expected = array( - array('section' => 'section_1', 'group' => 'group_1', 'field' => 'field_2'), - array('section' => 'section_2', 'group' => 'group_3', 'field' => 'field_4') + return array( + array('backend_model', 'Mage_Backend_Model_Config_Backend_Encrypted', array( + 'section_1/group_1/field_2', + 'section_1/group_level_1/group_level_2/group_level_3/field_3.1.1', + 'section_2/group_3/field_4', + )), + array('attribute_2', 'test_value_2', array('section_2/group_3/field_4')) ); - $this->assertEquals($expected, $this->_model->getEncryptedNodeEntriesPaths(true)); } } diff --git a/dev/tests/unit/testsuite/Mage/Backend/Model/ConfigTest.php b/dev/tests/unit/testsuite/Mage/Backend/Model/ConfigTest.php index 3ce10cb9bd6ddbaae8838432094c3541c1fff935..64f7c3b6616163ec8d042f950ddc9de447bc1cdc 100644 --- a/dev/tests/unit/testsuite/Mage/Backend/Model/ConfigTest.php +++ b/dev/tests/unit/testsuite/Mage/Backend/Model/ConfigTest.php @@ -50,17 +50,22 @@ class Mage_Backend_Model_ConfigTest extends PHPUnit_Framework_TestCase /** * @var PHPUnit_Framework_MockObject_MockObject */ - protected $_objectFactoryMock; + protected $_appConfigMock; /** * @var PHPUnit_Framework_MockObject_MockObject */ - protected $_appConfigMock; + protected $_applicationMock; /** * @var PHPUnit_Framework_MockObject_MockObject */ - protected $_applicationMock; + protected $_configLoaderMock; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_dataFactoryMock; public function setUp() { @@ -73,25 +78,27 @@ class Mage_Backend_Model_ConfigTest extends PHPUnit_Framework_TestCase $this->returnValue($structureMock) ); $this->_transFactoryMock = $this->getMock( - 'Mage_Backend_Model_Resource_Transaction_Factory', array(), array(), '', false + 'Mage_Core_Model_Resource_Transaction_Factory', array(), array(), '', false ); - $this->_objectFactoryMock = $this->getMock('Mage_Core_Model_Config', array(), array(), '', false); $this->_appConfigMock = $this->getMock('Mage_Core_Model_Config', array(), array(), '', false); - $this->_applicationMock = $this->getMock('Mage_Core_Model_Application', array(), array(), '', false); + $this->_configLoaderMock = $this->getMock('Mage_Backend_Model_Config_Loader', array(), array(), '', false); + $this->_applicationMock = $this->getMock('Mage_Core_Model_App', array(), array(), '', false); + $this->_dataFactoryMock = $this->getMock('Mage_Core_Model_Config_Data_Factory', array(), array(), '', false); - $this->_model = new Mage_Backend_Model_Config(array( - 'eventManager' => $this->_eventManagerMock, - 'structureReader' => $this->_structureReaderMock, - 'transactionFactory' => $this->_transFactoryMock, - 'objectFactory' => $this->_objectFactoryMock, - 'applicationConfig' => $this->_appConfigMock, - 'application' => $this->_appConfigMock - )); + $this->_model = new Mage_Backend_Model_Config( + $this->_applicationMock, + $this->_appConfigMock, + $this->_eventManagerMock, + $structureMock, + $this->_transFactoryMock, + $this->_configLoaderMock, + $this->_dataFactoryMock + ); } public function testSaveDoesNotDoAnythingIfGroupsAreNotPassed() { - $this->_structureReaderMock->expects($this->never())->method('getConfiguration'); + $this->_configLoaderMock->expects($this->never())->method('getConfigByPath'); $this->_model->save(); } diff --git a/dev/tests/unit/testsuite/Mage/Backend/Model/UrlTest.php b/dev/tests/unit/testsuite/Mage/Backend/Model/UrlTest.php index 9592057df2b33eb378b062417bfef80e70f386db..b72892e7c8f2a9519dc66d7460ce3342cd44541e 100644 --- a/dev/tests/unit/testsuite/Mage/Backend/Model/UrlTest.php +++ b/dev/tests/unit/testsuite/Mage/Backend/Model/UrlTest.php @@ -54,19 +54,32 @@ class Mage_Backend_Model_UrlTest extends PHPUnit_Framework_TestCase protected $_coreHelperMock; /** - * @var Mage_Core_Controller_Request_Http|PHPUnit_Framework_MockObject_MockObject + * @var Mage_Core_Controller_Request_Http */ - protected $_requestMock; + protected $_storeConfigMock; + + /** + * @var Mage_Core_Controller_Request_Http + */ + protected $_menuConfigMock; + + /** + * @var Mage_Core_Controller_Request_Http + */ + protected $_backendHelperMock; /** - * @var array + * @var Mage_Core_Controller_Request_Http|PHPUnit_Framework_MockObject_MockObject */ - protected $_routes; + protected $_requestMock; public function setUp() { $this->_menuMock = $this->getMock('Mage_Backend_Model_Menu', array(), array(), '', false); + $this->_menuConfigMock = $this->getMock('Mage_Backend_Model_Menu_Config', array(), array(), '', false); + $this->_menuConfigMock->expects($this->any())->method('getMenu')->will($this->returnValue($this->_menuMock)); + $this->_coreSessionMock = $this->getMock('Mage_Core_Model_Session', array('getFormKey'), array(), '', false); $this->_coreSessionMock->expects($this->any())->method('getFormKey')->will($this->returnValue('salt')); @@ -87,20 +100,18 @@ class Mage_Backend_Model_UrlTest extends PHPUnit_Framework_TestCase $helperMock = $this->getMock('Mage_Backend_Helper_Data', array(), array(), '', false); $helperMock->expects($this->any())->method('getAreaFrontName') ->will($this->returnValue($this->_areaFrontName)); - - $this->_routes = array( - 'admin' => 'adminhtml', - 'adminhtml' => '', - ); - - $this->_model = new Mage_Backend_Model_Url(array( - 'startupMenuItemId' => 'Mage_Adminhtml::system_acl_roles', - 'menu' => $this->_menuMock, - 'backendHelper' => $helperMock, - 'coreSession' => $this->_coreSessionMock, - 'coreHelper' => $this->_coreHelperMock, - 'routes' => $this->_routes, - ) + $this->_storeConfigMock = $this->getMock('Mage_Core_Model_Store_Config', array(), array(), '', false); + $this->_storeConfigMock->expects($this->any()) + ->method('getConfig') + ->with(Mage_Backend_Model_Url::XML_PATH_STARTUP_MENU_ITEM) + ->will($this->returnValue('Mage_Adminhtml::system_acl_roles')); + + $this->_model = new Mage_Backend_Model_Url( + $helperMock, + $this->_coreHelperMock, + $this->_coreSessionMock, + $this->_storeConfigMock, + $this->_menuConfigMock ); $this->_requestMock = $this->getMock('Mage_Core_Controller_Request_Http', array(), array(), '', false); @@ -169,13 +180,13 @@ class Mage_Backend_Model_UrlTest extends PHPUnit_Framework_TestCase $helperMock->expects($this->once())->method('getAreaFrontName') ->will($this->returnValue($this->_areaFrontName)); - $urlModel = new Mage_Backend_Model_Url(array( - 'startupMenuItemId' => 'Mage_Adminhtml::system_acl_roles', - 'menu' => $this->_menuMock, - 'backendHelper' => $helperMock, - 'coreSession' => $this->_coreSessionMock, - 'coreHelper' => $this->_coreHelperMock, - )); + $urlModel = new Mage_Backend_Model_Url( + $helperMock, + $this->_coreHelperMock, + $this->_coreSessionMock, + $this->_storeConfigMock, + $this->_menuConfigMock + ); $urlModel->getAreaFrontName(); } @@ -204,13 +215,13 @@ class Mage_Backend_Model_UrlTest extends PHPUnit_Framework_TestCase $helperMock->expects($this->once())->method('getAreaFrontName') ->will($this->returnValue('')); - $urlModel = new Mage_Backend_Model_Url(array( - 'startupMenuItemId' => 'Mage_Adminhtml::system_acl_roles', - 'menu' => $this->_menuMock, - 'backendHelper' => $helperMock, - 'coreSession' => $this->_coreSessionMock, - 'coreHelper' => $this->_coreHelperMock, - )); + $urlModel = new Mage_Backend_Model_Url( + $helperMock, + $this->_coreHelperMock, + $this->_coreSessionMock, + $this->_storeConfigMock, + $this->_menuConfigMock + ); $moduleFrontName = 'moduleFrontName'; $controllerName = 'controllerName'; diff --git a/dev/tests/unit/testsuite/Mage/Backend/Model/_files/converted_config.php b/dev/tests/unit/testsuite/Mage/Backend/Model/_files/converted_config.php index 2f7cd536246e1276cca60d74125de36aceb39218..217ac82dc16fd9473a460e16fabddc0df8a9968c 100644 --- a/dev/tests/unit/testsuite/Mage/Backend/Model/_files/converted_config.php +++ b/dev/tests/unit/testsuite/Mage/Backend/Model/_files/converted_config.php @@ -32,8 +32,9 @@ return array( 'tabs' => array( 'tab_1' => array( 'id' => 'tab_1', - 'label' => 'Tab 1 New' - ) + 'label' => 'Tab 1 New', + '_elementType' => 'tab', + ), ), 'sections' => array( 'section_1' => array( @@ -41,50 +42,88 @@ return array( 'type' => 'text', 'label' => 'Section 1 New', 'tab' => 'tab_1', - 'groups' => array( + 'children' => array( 'group_1' => array( 'id' => 'group_1', 'type' => 'text', 'label' => 'Group 1 New', - 'fields' => array( + 'children' => array( 'field_2' => array( 'id' => 'field_2', 'translate' => 'label', 'showInWebsite' => '1', 'type' => 'text', 'label' => 'Field 2', - 'backend_model' => 'Mage_Backend_Model_Config_Backend_Encrypted' - ) + 'backend_model' => 'Mage_Backend_Model_Config_Backend_Encrypted', + '_elementType' => 'field', + ), ), + '_elementType' => 'group', ), - 'group_2' => array( - 'id' => 'group_2', + 'group_level_1' => array( + 'id' => 'group_level_1', 'type' => 'text', - 'label' => 'Group 2', - 'fields' => array( + 'label' => 'Group Level 1', + 'children' => array( 'field_3' => array( 'id' => 'field_3', 'translate' => 'label', 'showInWebsite' => '1', 'type' => 'text', 'label' => 'Field 3', - ) + '_elementType' => 'field', + ), + 'group_level_2' => array( + 'id' => 'group_level_2', + 'type' => 'text', + 'label' => 'Group Level 2', + 'children' => array( + 'field_3.1' => array( + 'id' => 'field_3.1', + 'translate' => 'label', + 'showInWebsite' => '1', + 'type' => 'text', + 'label' => 'Field 3.1', + '_elementType' => 'field', + ), + 'group_level_3' => array( + 'id' => 'group_level_3', + 'type' => 'text', + 'label' => 'Group Level 3', + 'children' => array( + 'field_3.1.1' => array( + 'id' => 'field_3.1.1', + 'translate' => 'label', + 'showInWebsite' => '1', + 'backend_model' => 'Mage_Backend_Model_Config_Backend_Encrypted', + 'type' => 'text', + 'label' => 'Field 3.1.1', + '_elementType' => 'field', + ), + ), + '_elementType' => 'group', + ), + ), + '_elementType' => 'group', + ), ), - ) + '_elementType' => 'group', + ), ), + '_elementType' => 'section', ), 'section_2' => array( 'id' => 'section_2', 'type' => 'text', 'label' => 'Section 2', 'tab' => 'tab_2', - 'groups' => array( + 'children' => array( 'group_3' => array( 'id' => 'group_3', 'type' => 'text', 'label' => 'Group 3', 'comment' => '<a href="test_url">test_link</a>', - 'fields' => array( + 'children' => array( 'field_3' => array( 'id' => 'field_3', 'translate' => 'label', @@ -93,21 +132,24 @@ return array( 'label' => 'Field 3', 'attribute_0' => array( 'someArr' => array( - 'someVal' => 1 - ) + 'someVal' => '1', + ), ), 'depends' => array( 'fields' => array( 'field_4' => array( 'id' => 'field_4', - 'value' => 'someValue' + 'value' => 'someValue', + '_elementType' => 'field', ), 'field_1' => array( 'id' => 'field_1', - 'value' => 'someValue' - ) - ) - ) + 'value' => 'someValue', + '_elementType' => 'field', + ), + ), + ), + '_elementType' => 'field', ), 'field_4' => array( 'id' => 'field_4', @@ -121,22 +163,52 @@ return array( 'attribute_text' => '<test_value>', 'attribute_text_in_array' => array( 'var' => '<a href="test_url">test_link</a>', - 'type' => 'someType' + 'type' => 'someType', ), 'depends' => array( 'fields' => array( 'field_3' => array( 'id' => 'field_3', - 'value' => 0 - ) - ) - ) + 'value' => '0', + '_elementType' => 'field', + ), + ), + ), + '_elementType' => 'field', + ), + 'field_5' => array( + 'id' => 'field_5', + 'translate' => 'label', + 'showInWebsite' => '1', + 'type' => 'text', + 'label' => '', + '_elementType' => 'field', + ), + ), + '_elementType' => 'group', + ), + 'group_4' => array( + 'id' => 'group_4', + 'label' => 'Group 4', + 'type' => 'text', + 'showInDefault' => 1, + 'showInStore' => 1, + 'showInWebsite' => 1, + 'depends' => array( + 'fields' => array( + 'section_2/group_3/field_5' => array( + 'id' => 'section_2/group_3/field_5', + 'value' => 1, + '_elementType' => 'field' + ), ) ), + '_elementType' => 'group', ) - ) - ) - ) - ) - ) + ), + '_elementType' => 'section', + ), + ), + ), + ), ); diff --git a/dev/tests/unit/testsuite/Mage/Backend/Model/_files/dependencies_data.php b/dev/tests/unit/testsuite/Mage/Backend/Model/_files/dependencies_data.php new file mode 100644 index 0000000000000000000000000000000000000000..c30b4789ee876830e8ea39f6f6ffa8c4b3a38ccc --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Backend/Model/_files/dependencies_data.php @@ -0,0 +1,140 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Backend + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +return array( + 'config' => array( + 'system' => array( + 'sections' => array( + 'section_1' => array( + 'id' => 'section_1', + '_elementType' => 'section', + 'children' => array( + 'group_1' => array( + 'id' => 'group_1', + '_elementType' => 'group', + 'path' => 'section_1', + 'depends' => array( + 'fields' => array( + 'field_2' => array( + 'id' => '*/*/field_2', + 'value' => 10, + ), + ), + ), + 'children' => array( + 'field_2' => array( + 'id' => 'field_2', + '_elementType' => 'field', + ), + ), + ), + 'group_2' => array( + 'id' => 'group_2', + '_elementType' => 'group', + 'children' => array( + 'field_3' => array( + 'id' => 'field_3', + '_elementType' => 'field', + ) + ), + ), + ), + ), + 'section_2' => array( + 'id' => 'section_2', + '_elementType' => 'section', + 'children' => array( + 'group_3' => array( + 'id' => 'group_3', + '_elementType' => 'group', + 'children' => array( + 'field_3' => array( + 'id' => 'field_3', + '_elementType' => 'field', + 'path' => 'section_2/group_3', + 'depends' => array( + 'fields' => array( + 'field_4' => array( + 'id' => '*/*/field_4', + 'value' => 'someValue', + ), + 'field_1' => array( + 'id' => 'section_1/*/field_1', + 'value' => 'someValue', + ), + ), + ), + ), + 'field_4' => array( + 'id' => 'field_4', + '_elementType' => 'field', + 'path' => 'section_2/group_3', + 'depends' => array( + 'fields' => array( + 'field_3' => array( + 'id' => '*/*/field_3', + 'value' => 0, + ), + ), + ), + ), + 'group_4_1' => array( + 'id' => 'group_4_1', + '_elementType' => 'group', + 'path' => 'section_2/group_3', + 'depends' => array( + 'fields' => array( + 'field_3' => array( + 'id' => '*/*/field_3', + 'value' => 0, + ), + ), + ), + 'children' => array( + 'field_5' => array( + 'id' => 'field_5', + '_elementType' => 'field', + 'path' => 'section_2/group_3/group_4_1', + 'depends' => array( + 'fields' => array( + 'field_4' => array( + 'id' => '*/*/*/field_4', + 'value' => 'someValue', + ), + ), + ), + ), + ), + ), + ), + ), + ), + ), + ), + ), + ), +); diff --git a/dev/tests/unit/testsuite/Mage/Backend/Model/_files/dependencies_mapped.php b/dev/tests/unit/testsuite/Mage/Backend/Model/_files/dependencies_mapped.php new file mode 100644 index 0000000000000000000000000000000000000000..06887edbb16fd064d1a4111e1b16b74339c3e3c4 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Backend/Model/_files/dependencies_mapped.php @@ -0,0 +1,171 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Backend + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +return array( + 'config' => array( + 'system' => array( + 'sections' => array( + 'section_1' => array( + 'id' => 'section_1', + '_elementType' => 'section', + 'children' => array( + 'group_1' => array( + 'id' => 'group_1', + '_elementType' => 'group', + 'path' => 'section_1', + 'depends' => array( + 'fields' => array( + 'field_2' => array( + 'id' => 'section_1/group_1/field_2', + 'value' => 10, + 'dependPath' => array( + 'section_1', + 'group_1', + 'field_2', + ), + ), + ), + ), + 'children' => array( + 'field_2' => array( + 'id' => 'field_2', + '_elementType' => 'field', + ), + ), + ), + 'group_2' => array( + 'id' => 'group_2', + '_elementType' => 'group', + 'children' => array( + 'field_3' => array( + 'id' => 'field_3', + '_elementType' => 'field', + ), + ), + ), + ), + ), + 'section_2' => array( + 'id' => 'section_2', + '_elementType' => 'section', + 'children' => array( + 'group_3' => array( + 'id' => 'group_3', + '_elementType' => 'group', + 'children' => array( + 'field_3' => array( + 'id' => 'field_3', + '_elementType' => 'field', + 'path' => 'section_2/group_3', + 'depends' => array( + 'fields' => array( + 'field_4' => array( + 'id' => 'section_2/group_3/field_4', + 'value' => 'someValue', + 'dependPath' => array( + 'section_2', + 'group_3', + 'field_4', + ), + ), + 'field_1' => array( + 'id' => 'section_1/group_3/field_1', + 'value' => 'someValue', + 'dependPath' => array( + 'section_1', + 'group_3', + 'field_1', + ), + ), + ), + ), + ), + 'field_4' => array( + 'id' => 'field_4', + '_elementType' => 'field', + 'path' => 'section_2/group_3', + 'depends' => array( + 'fields' => array( + 'field_3' => array( + 'id' => 'section_2/group_3/field_3', + 'value' => 0, + 'dependPath' => array( + 'section_2', + 'group_3', + 'field_3', + ), + ), + ), + ), + ), + 'group_4_1' => array( + 'id' => 'group_4_1', + '_elementType' => 'group', + 'path' => 'section_2/group_3', + 'depends' => array( + 'fields' => array( + 'field_3' => array( + 'id' => 'section_2/group_3/field_3', + 'value' => 0, + 'dependPath' => array( + 'section_2', + 'group_3', + 'field_3', + ), + ), + ), + ), + 'children' => array( + 'field_5' => array( + 'id' => 'field_5', + '_elementType' => 'field', + 'path' => 'section_2/group_3/group_4_1', + 'depends' => array( + 'fields' => array( + 'field_4' => array( + 'id' => 'section_2/group_3/group_4_1/field_4', + 'value' => 'someValue', + 'dependPath' => array( + 'section_2', + 'group_3', + 'group_4_1', + 'field_4', + ), + ), + ), + ), + ), + ), + ), + ), + ), + ), + ), + ), + ), + ), +); diff --git a/dev/tests/unit/testsuite/Mage/Backend/Model/_files/system_2.xml b/dev/tests/unit/testsuite/Mage/Backend/Model/_files/system_2.xml index d5bd2799f26df633dbe7918e085f5c103b3c9c8a..0297b0d55a7240ad3ab8eb95f5ed11c131a4f75b 100644 --- a/dev/tests/unit/testsuite/Mage/Backend/Model/_files/system_2.xml +++ b/dev/tests/unit/testsuite/Mage/Backend/Model/_files/system_2.xml @@ -41,11 +41,24 @@ <backend_model>Mage_Backend_Model_Config_Backend_Encrypted</backend_model> </field> </group> - <group id="group_2" type="text"> - <label>Group 2</label> + <group id="group_level_1" type="text"> + <label>Group Level 1</label> <field id="field_3" translate="label" showInWebsite="1" type="text"> <label>Field 3</label> </field> + <group id="group_level_2" type="text"> + <label>Group Level 2</label> + <field id="field_3.1" translate="label" showInWebsite="1" type="text"> + <label>Field 3.1</label> + </field> + <group id="group_level_3" type="text"> + <label>Group Level 3</label> + <field id="field_3.1.1" translate="label" showInWebsite="1" type="text"> + <label>Field 3.1.1</label> + <backend_model>Mage_Backend_Model_Config_Backend_Encrypted</backend_model> + </field> + </group> + </group> </group> </section> <section id="section_2" type="text"> @@ -80,6 +93,15 @@ <field id="field_3">0</field> </depends> </field> + <field id="field_5" translate="label" showInWebsite="1" type="text"> + <label></label> + </field> + </group> + <group id="group_4" type="text" showInDefault="1" showInWebsite="1" showInStore="1"> + <label>Group 4</label> + <depends> + <field id="section_2/group_3/field_5">1</field> + </depends> </group> </section> </system> diff --git a/dev/tests/unit/testsuite/Mage/Backend/controllers/Adminhtml/System/Config/SaveControllerTest.php b/dev/tests/unit/testsuite/Mage/Backend/controllers/Adminhtml/System/Config/SaveControllerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..eae1203b11f0039215959e1c841ba33be3525285 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Backend/controllers/Adminhtml/System/Config/SaveControllerTest.php @@ -0,0 +1,264 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Backend + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +require_once (realpath(dirname(__FILE__) . '/../../../../../../../../../../') + . '/app/code/core/Mage/Backend/Controller/System/ConfigAbstract.php'); + +require_once (realpath(dirname(__FILE__) . '/../../../../../../../../../../') + . '/app/code/core/Mage/Backend/controllers/Adminhtml/System/Config/SaveController.php'); + +class Mage_Backend_Adminhtml_System_Config_SaveControllerTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Backend_Adminhtml_System_Config_SaveController + */ + protected $_controller; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_requestMock; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_configFactoryMock; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_configMock; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_eventManagerMock; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_sessionMock; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_authMock; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_appMock; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_sectionMock; + + public function setUp() + { + $this->_requestMock = $this->getMock('Mage_Core_Controller_Request_Http', array(), array(), '', false, false); + $responseMock = $this->getMock('Mage_Core_Controller_Response_Http', array(), array(), '', false, false); + $objectManagerMock = $this->getMock('Magento_ObjectManager', array(), array(), '', false, false); + $frontControllerMock = $this->getMock('Mage_Core_Controller_Varien_Front', array(), array(), '', false, false); + $authorizationMock = $this->getMock('Mage_Core_Model_Authorization', array(), array(), '', false, false); + $this->_configMock = $this->getMock('Mage_Core_Model_Config', array(), array(), '', false, false); + $configStructureMock = $this->getMock('Mage_Backend_Model_Config_Structure', + array(), array(), '', false, false + ); + $this->_configFactoryMock = $this->getMock('Mage_Backend_Model_Config_Factory', + array(), array(), '', false, false + ); + $this->_eventManagerMock = $this->getMock('Mage_Core_Model_Event_Manager', array(), array(), '', false, false); + $this->_appMock = $this->getMock('Mage_Core_Model_App', array(), array(), '', false, false); + $helperMock = $this->getMock('Mage_Backend_Helper_Data', array(), array(), '', false, false); + $this->_sessionMock = $this->getMock('Mage_Backend_Model_Session', + array('addSuccess', 'addException'), array(), '', false, false + ); + + $this->_authMock = $this->getMock('Mage_Backend_Model_Auth_Session', + array('getUser'), array(), '', false, false + ); + + $this->_sectionMock = $this->getMock( + 'Mage_Backend_Model_Config_Structure_Element_Section', array(), array(), '', false + ); + + $configStructureMock->expects($this->any())->method('getElement') + ->will($this->returnValue($this->_sectionMock)); + + $helperMock->expects($this->any())->method('__')->will($this->returnArgument(0)); + $helperMock->expects($this->any())->method('getUrl')->will($this->returnArgument(0)); + $responseMock->expects($this->once())->method('setRedirect')->with('*/system_config/edit'); + + $this->_controller = new Mage_Backend_Adminhtml_System_Config_SaveController($this->_requestMock, + $responseMock, + $objectManagerMock, + $frontControllerMock, + $authorizationMock, + $configStructureMock, + $this->_configMock, + $this->_configFactoryMock, + $this->_eventManagerMock, + $this->_appMock, + $this->_authMock, + array( + 'helper' => $helperMock, + 'session' => $this->_sessionMock, + ) + ); + } + + public function testIndexActionWithAllowedSection() + { + $this->_sectionMock->expects($this->any())->method('isAllowed')->will($this->returnValue(true)); + $this->_configMock->expects($this->once())->method('reinit'); + $this->_sessionMock->expects($this->once())->method('addSuccess')->with('The configuration has been saved.'); + + $groups = array('some_key' => 'some_value'); + $requestParamMap = array( + array('section', null, 'test_section'), + array('website', null, 'test_website'), + array('store', null, 'test_store'), + ); + + $requestPostMap = array( + array('groups', null, $groups), + array('config_state', null, 'test_config_state'), + ); + + $this->_requestMock->expects($this->any())->method('getPost')->will($this->returnValueMap($requestPostMap)); + $this->_requestMock->expects($this->any())->method('getParam')->will($this->returnValueMap($requestParamMap)); + + $backendConfigMock = $this->getMock('Mage_Backend_Model_Config', array(), array(), '', false, false); + $backendConfigMock->expects($this->once())->method('save'); + + $params = array('section' => 'test_section', + 'website' => 'test_website', + 'store' => 'test_store', + 'groups' => $groups + ); + $this->_configFactoryMock->expects($this->once())->method('create')->with(array('data' => $params)) + ->will($this->returnValue($backendConfigMock)); + + $this->_controller->indexAction(); + } + + public function testIndexActionWithNotAllowedSection() + { + $this->_sectionMock->expects($this->any())->method('isAllowed')->will($this->returnValue(false)); + + $backendConfigMock = $this->getMock('Mage_Backend_Model_Config', array(), array(), '', false, false); + $backendConfigMock->expects($this->never())->method('save'); + $this->_configMock->expects($this->never())->method('reinit'); + $this->_eventManagerMock->expects($this->never())->method('dispatch'); + $this->_sessionMock->expects($this->never())->method('addSuccess'); + $this->_sessionMock->expects($this->once())->method('addException'); + + $this->_configFactoryMock->expects($this->any())->method('create') + ->will($this->returnValue($backendConfigMock)); + + $this->_controller->indexAction(); + } + + public function testIndexActionSaveState() + { + $this->_sectionMock->expects($this->any())->method('isAllowed')->will($this->returnValue(false)); + $data = array('some_key' => 'some_value'); + + $userMock = $this->getMock('Mage_User_Model_User', array(), array(), '', false, false); + $userMock->expects($this->once())->method('saveExtra')->with(array('configState' => $data)); + $this->_authMock->expects($this->once())->method('getUser')->will($this->returnValue($userMock)); + + $this->_requestMock->expects($this->any()) + ->method('getPost')->with('config_state')->will($this->returnValue($data)); + $this->_controller->indexAction(); + } + + public function testIndexActionGetGroupForSave() + { + $this->_sectionMock->expects($this->any())->method('isAllowed')->will($this->returnValue(true)); + + $groups = array('some.key' => 'some.val'); + $requestParamMap = array( + array('section', null, 'test_section'), + array('website', null, 'test_website'), + array('store', null, 'test_store'), + ); + + $requestPostMap = array( + array('groups', null, $groups), + array('config_state', null, 'test_config_state'), + ); + + $fixturePath = dirname(__FILE__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR; + $files = require_once($fixturePath . 'files_array.php'); + + $this->_requestMock->expects($this->any())->method('getPost')->will($this->returnValueMap($requestPostMap)); + $this->_requestMock->expects($this->any())->method('getParam')->will($this->returnValueMap($requestParamMap)); + $this->_requestMock->expects($this->once()) + ->method('getFiles') + ->with('groups') + ->will($this->returnValue($files)); + + $groupToSave = require_once($fixturePath . 'expected_array.php'); + + $params = array('section' => 'test_section', + 'website' => 'test_website', + 'store' => 'test_store', + 'groups' => $groupToSave + ); + $backendConfigMock = $this->getMock('Mage_Backend_Model_Config', array(), array(), '', false, false); + $this->_configFactoryMock->expects($this->once())->method('create')->with(array('data' => $params)) + ->will($this->returnValue($backendConfigMock)); + $backendConfigMock->expects($this->once())->method('save'); + + $this->_controller->indexAction(); + } + + public function testIndexActionSaveAdvanced() + { + $this->_sectionMock->expects($this->any())->method('isAllowed')->will($this->returnValue(true)); + + $requestParamMap = array( + array('section', null, 'advanced'), + array('website', null, 'test_website'), + array('store', null, 'test_store'), + ); + + $this->_requestMock->expects($this->any())->method('getParam')->will($this->returnValueMap($requestParamMap)); + + $backendConfigMock = $this->getMock('Mage_Backend_Model_Config', array(), array(), '', false, false); + $this->_configFactoryMock->expects($this->once())->method('create') + ->will($this->returnValue($backendConfigMock)); + $backendConfigMock->expects($this->once())->method('save'); + + $this->_appMock->expects($this->once()) + ->method('cleanCache') + ->with(array('layout', Mage_Core_Model_Layout_Merge::LAYOUT_GENERAL_CACHE_TAG)); + $this->_controller->indexAction(); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Backend/controllers/Adminhtml/System/Config/_files/expected_array.php b/dev/tests/unit/testsuite/Mage/Backend/controllers/Adminhtml/System/Config/_files/expected_array.php new file mode 100644 index 0000000000000000000000000000000000000000..2dc510c5968c171f844793e65acbf2d837dfcaa5 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Backend/controllers/Adminhtml/System/Config/_files/expected_array.php @@ -0,0 +1,51 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Backend + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +return array( + 'some.key' => 'some.val', + 'group.1' => array( + 'fields' => array('f1.1' => array('value' => 'f1.1.val'), 'f1.2' => array('value' => 'f1.2.val')) + ), + 'group.2' => array( + 'fields' => array('f2.1' => array('value' => 'f2.1.val'), 'f2.2' => array('value' => 'f2.2.val')), + 'groups' => array( + 'group.2.1' => array( + 'fields' => array( + 'f2.1.1' => array('value' => 'f2.1.1.val'), 'f2.1.2' => array('value' => 'f2.1.2.val'), + ), + 'groups' => array( + 'group.2.1.1' => array( + 'fields' => array( + 'f2.1.1.1' => array('value' => 'f2.1.1.1.val'), + 'f2.1.1.2' => array('value' => 'f2.1.1.2.val'), + ) + ), + ), + ), + ) + ), +); diff --git a/dev/tests/unit/testsuite/Mage/Backend/controllers/Adminhtml/System/Config/_files/files_array.php b/dev/tests/unit/testsuite/Mage/Backend/controllers/Adminhtml/System/Config/_files/files_array.php new file mode 100644 index 0000000000000000000000000000000000000000..5e33797a98536da180d16908824e946c16af5747 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Backend/controllers/Adminhtml/System/Config/_files/files_array.php @@ -0,0 +1,60 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Backend + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +return array( + 'name' => array( + 'group.1' => array( + 'fields' => array('f1.1' => array('value' => 'f1.1.val'), 'f1.2' => array('value' => 'f1.2.val')) + ), + 'group.2' => array( + 'fields' => array( + 'f2.1' => array('value' => 'f2.1.val'), + 'f2.2' => array('value' => 'f2.2.val'), + 'f2.3' => array('value' => ''), + ), + 'groups' => array( + 'group.2.1' => array( + 'fields' => array( + 'f2.1.1' => array('value' => 'f2.1.1.val'), + 'f2.1.2' => array('value' => 'f2.1.2.val'), + 'f2.1.3' => array('value' => ''), + ), + 'groups' => array( + 'group.2.1.1' => array( + 'fields' => array( + 'f2.1.1.1' => array('value' => 'f2.1.1.1.val'), + 'f2.1.1.2' => array('value' => 'f2.1.1.2.val'), + 'f2.1.1.3' => array('value' => ''), + ) + ), + ), + ), + ) + ), + 'group.3' => 'some.data', + ) +); diff --git a/dev/tests/unit/testsuite/Mage/Core/Model/Acl/Loader/Resource/ResourceAbstractTest.php b/dev/tests/unit/testsuite/Mage/Core/Model/Acl/Loader/Resource/ResourceAbstractTest.php new file mode 100644 index 0000000000000000000000000000000000000000..fa6155ecebe333819be0c9402f5c203f88fc1b1d --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Core/Model/Acl/Loader/Resource/ResourceAbstractTest.php @@ -0,0 +1,74 @@ +<?php +/** + * Test for Mage_Core_Model_Acl_Loader_Resource_ResourceAbstract + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Core_Model_Acl_Loader_Resource_ResourceAbstractTest extends PHPUnit_Framework_TestCase +{ + /** + * Test for Mage_Core_Model_Acl_Loader_Resource_ResourceAbstract::populateAcl + */ + public function testPopulateAclOnValidObjects() + { + /** @var $aclResource Magento_Acl_Resource */ + $aclResource = $this->getMock('Magento_Acl_Resource', array(), array(), '', false); + + /** @var $acl Magento_Acl */ + $acl = $this->getMock('Magento_Acl', array('addResource'), array(), '', false); + $acl->expects($this->exactly(3))->method('addResource'); + $acl->expects($this->at(0))->method('addResource')->with($aclResource, null)->will($this->returnSelf()); + $acl->expects($this->at(1))->method('addResource')->with($aclResource, $aclResource)->will($this->returnSelf()); + $acl->expects($this->at(2))->method('addResource')->with($aclResource, $aclResource)->will($this->returnSelf()); + + /** @var $factoryObject Mage_Core_Model_Config */ + $factoryObject = $this->getMock('Magento_Acl_ResourceFactory', array('createResource'), array(), '', false); + $factoryObject->expects($this->any())->method('createResource')->will($this->returnValue($aclResource)); + + /** @var $configObject Mage_Core_Model_Acl_Config_ConfigInterface */ + $configObject = $this->getMock('Mage_Core_Model_Acl_Config_ConfigInterface', + array('getAclResources'), array(), '', false); + $configObject->expects($this->once())->method('getAclResources') + ->will($this->returnCallback(array($this, 'getResourceNodeList'))); + + /** @var $loaderResource Mage_Core_Model_Acl_Loader_Resource_ResourceAbstract */ + $loaderResource = $this->getMockForAbstractClass('Mage_Core_Model_Acl_Loader_Resource_ResourceAbstract', + array($configObject, $factoryObject)); + + $loaderResource->populateAcl($acl); + } + + /** + * Get Resources DOMNodeList from fixture + * + * @return DOMNodeList + */ + public function getResourceNodeList() + { + $aclResources = new DOMDocument(); + $aclResources->load(__DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR + . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '_files' + . DIRECTORY_SEPARATOR . 'acl_resources.xml'); + $xpath = new DOMXPath($aclResources); + return $xpath->query('/config/resources/*'); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Core/Model/ConfigTest.php b/dev/tests/unit/testsuite/Mage/Core/Model/ConfigTest.php index 5fae9775cf29d0161ffefc2f053a7ef8e92fe6ca..1c5bd62c2cdaaef7d245919cdb13b55f9846bd8e 100644 --- a/dev/tests/unit/testsuite/Mage/Core/Model/ConfigTest.php +++ b/dev/tests/unit/testsuite/Mage/Core/Model/ConfigTest.php @@ -33,39 +33,46 @@ class Mage_Core_Model_ConfigTest extends PHPUnit_Framework_TestCase protected $_model; /** + * @param mixed $data + * @param array $map * @dataProvider constructorDataProvider - * @param array|Varien_Simplexml_Element $data */ - public function testConstructor($data) + public function testConstructor($data, $map) { - /** @var $objectManagerMock Magento_ObjectManager_Zend */ + //TODO: We should not use mocks in integration tests + /** @var Magento_ObjectManager_Zend|PHPUnit_Framework_MockObject_MockObject $objectManagerMock */ $objectManagerMock = $this->getMock('Magento_ObjectManager_Zend', array('create', 'get'), array(), '', false); $objectManagerMock->expects($this->any()) ->method('create') - ->will($this->returnCallback(array($this, 'getInstance'))); + ->will($this->returnValueMap(array( + $map, + array('Mage_Core_Model_Config_Base', array(), true, new Mage_Core_Model_Config_Base()) + ))); $this->_model = new Mage_Core_Model_Config($objectManagerMock, $data); $this->assertInstanceOf('Mage_Core_Model_Config_Options', $this->_model->getOptions()); } + /** + * @return array + */ public function constructorDataProvider() { + $simpleXml = new Varien_Simplexml_Element('<body></body>'); return array( - array('data' => null), - array('data' => array()), - array('data' => new Varien_Simplexml_Element('<body></body>')), + array( + 'data' => null, + 'map' => array('Mage_Core_Model_Config_Options', array('data' => array(null)), true, + new Mage_Core_Model_Config_Options()) + ), + array( + 'data' => array(), + 'map' => array('Mage_Core_Model_Config_Options', array('data' => array()), true, + new Mage_Core_Model_Config_Options()) + ), + array('data' => $simpleXml, + 'map' => array('Mage_Core_Model_Config_Options', array('data' => array($simpleXml)), true, + new Mage_Core_Model_Config_Options())), ); } - - /** - * Callback to use instead Magento_ObjectManager_Zend::create - * - * @param string $className - * @param array $params - * @return string - */ - public function getInstance($className, $params = array()) - { - return new $className($params); - } -} \ No newline at end of file +} diff --git a/dev/tests/unit/testsuite/Mage/Core/Model/Validator/FactoryTest.php b/dev/tests/unit/testsuite/Mage/Core/Model/Validator/FactoryTest.php new file mode 100644 index 0000000000000000000000000000000000000000..26769f75b519cc227faa844d203d3b25b157eb71 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Core/Model/Validator/FactoryTest.php @@ -0,0 +1,160 @@ +<?php +/** + * Unit test for Mage_Core_Model_Validator_Factory + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Core_Model_Validator_FactoryTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Magento_ObjectManager + */ + protected $_objectManager; + + /** + * @var Mage_Core_Model_Config + */ + protected $_config; + + /** + * @var Mage_Core_Model_Translate + */ + protected $_translateAdapter; + + /** + * @var Magento_Validator_Config + */ + protected $_validatorConfig; + + /** + * @var Magento_Translate_AdapterInterface|null + */ + protected $_defaultTranslator = null; + + /** + * Save default translator + */ + protected function setUp() + { + $this->_defaultTranslator = Magento_Validator_ValidatorAbstract::getDefaultTranslator(); + $this->_objectManager = $this->getMockBuilder('Magento_ObjectManager_Zend') + ->setMethods(array('create', 'get')) + ->disableOriginalConstructor() + ->getMock(); + $this->_validatorConfig = $this->getMockBuilder('Magento_Validator_Config') + ->setMethods(array('createValidatorBuilder', 'createValidator')) + ->disableOriginalConstructor() + ->getMock(); + $this->_objectManager->expects($this->once()) + ->method('get') + ->with('Magento_Validator_Config', array('configFiles' => array('/tmp/moduleOne/etc/validation.xml'))) + ->will($this->returnValue($this->_validatorConfig)); + $this->_objectManager->expects($this->at(0)) + ->method('create') + ->with('Magento_Translate_Adapter') + ->will($this->returnValue(new Magento_Translate_Adapter())); + + // Config mock + $this->_config = $this->getMockBuilder('Mage_Core_Model_Config') + ->setMethods(array('getModuleConfigurationFiles')) + ->disableOriginalConstructor() + ->getMock(); + $this->_config->expects($this->once()) + ->method('getModuleConfigurationFiles') + ->with('validation.xml') + ->will($this->returnValue(array('/tmp/moduleOne/etc/validation.xml'))); + + // Translate adapter mock + $this->_translateAdapter = $this->getMockBuilder('Mage_Core_Model_Translate') + ->setConstructorArgs(array()) + ->setMethods(array('_getTranslatedString')) + ->getMock(); + $this->_translateAdapter->expects($this->any()) + ->method('_getTranslatedString') + ->will($this->returnArgument(0)); + } + + /** + * Restore default translator + */ + protected function tearDown() + { + Magento_Validator_ValidatorAbstract::setDefaultTranslator($this->_defaultTranslator); + unset($this->_defaultTranslator); + } + + /** + * Test getValidatorConfig created correct validator config. Check that validator translator was initialized. + */ + public function testGetValidatorConfig() + { + $this->_objectManager->expects($this->at(2)) + ->method('create') + ->with('Mage_Core_Model_Translate_Expr') + ->will($this->returnValue(new Mage_Core_Model_Translate_Expr())); + + $factory = new Mage_Core_Model_Validator_Factory($this->_objectManager, $this->_config, + $this->_translateAdapter); + $actualConfig = $factory->getValidatorConfig(); + $this->assertInstanceOf('Magento_Validator_Config', $actualConfig, + 'Object of incorrect type was created'); + + // Check that validator translator was correctly instantiated + $validatorTranslator = Magento_Validator_ValidatorAbstract::getDefaultTranslator(); + $this->assertInstanceOf('Magento_Translate_Adapter', $validatorTranslator, + 'Default validator translate adapter was not set correctly'); + // Dive into callback + /** @var Mage_Core_Model_Translate $translateAdapter */ + $this->assertEquals('Test message', $validatorTranslator->translate('Test message'), + 'Translator callback function was not initialized'); + } + + /** + * Test createValidatorBuilder call + */ + public function testCreateValidatorBuilder() + { + $this->_validatorConfig->expects($this->once()) + ->method('createValidatorBuilder') + ->with('test', 'class', array()) + ->will($this->returnValue(new Magento_Validator_Builder(array()))); + $factory = new Mage_Core_Model_Validator_Factory($this->_objectManager, $this->_config, + $this->_translateAdapter); + $this->assertInstanceOf('Magento_Validator_Builder', + $factory->createValidatorBuilder('test', 'class', array())); + } + + /** + * Test createValidatorBuilder call + */ + public function testCreateValidator() + { + $this->_validatorConfig->expects($this->once()) + ->method('createValidator') + ->with('test', 'class', array()) + ->will($this->returnValue(new Magento_Validator())); + $factory = new Mage_Core_Model_Validator_Factory($this->_objectManager, $this->_config, + $this->_translateAdapter); + $this->assertInstanceOf('Magento_Validator', + $factory->createValidator('test', 'class', array())); + } +} diff --git a/app/code/core/Mage/Adminhtml/view/adminhtml/api/rolesusers.phtml b/dev/tests/unit/testsuite/Mage/Core/Model/_files/acl_resources.xml similarity index 75% rename from app/code/core/Mage/Adminhtml/view/adminhtml/api/rolesusers.phtml rename to dev/tests/unit/testsuite/Mage/Core/Model/_files/acl_resources.xml index 9ac85acb007b082e319d4da8c34886cf0c76832a..2234a70e6c620d0bd429a019a61652c637b0799a 100644 --- a/app/code/core/Mage/Adminhtml/view/adminhtml/api/rolesusers.phtml +++ b/dev/tests/unit/testsuite/Mage/Core/Model/_files/acl_resources.xml @@ -1,4 +1,5 @@ -<?php +<?xml version="1.0"?> +<!-- /** * Magento * @@ -18,11 +19,18 @@ * versions in the future. If you wish to customize Magento for your * needs please refer to http://www.magentocommerce.com for more information. * - * @category design - * @package default_default + * @category Magento + * @package Mage_Core + * @subpackage unit_tests * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) */ -?> -<h4 class="icon-head head-edit-form fieldset-legend"><?php echo $this->__('Role Users') ?></h4> -<?php echo $this->_getGridHtml() ?> +--> +<config> + <resources> + <resource id="resource1"> + <resource id="resource2" /> + <resource id="resource3" /> + </resource> + </resources> +</config> diff --git a/dev/tests/unit/testsuite/Mage/Core/Service/ServiceAbstractTest.php b/dev/tests/unit/testsuite/Mage/Core/Service/ServiceAbstractTest.php new file mode 100644 index 0000000000000000000000000000000000000000..f3d1f5fea8d08ce561dd733b4087bf0c755b8fea --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Core/Service/ServiceAbstractTest.php @@ -0,0 +1,84 @@ +<?php +/** + * Unit test for abstract service layer Mage_Core_Service_ServiceAbstract + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Core_Service_ServiceAbstractTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Core_Service_ServiceAbstract|PHPUnit_Framework_MockObject_MockObject + */ + protected $_service; + + /** + * Initialize service abstract for testing + */ + protected function setUp() + { + $this->_service = $this->getMockBuilder('Mage_Core_Service_ServiceAbstract') + ->getMock(); + } + + protected function tearDown() + { + unset($this->_service); + } + + /** + * Test for _setDataUsingMethods method + */ + public function testSetDataUsingMethods() + { + /** @var $entity Varien_Object|PHPUnit_Framework_MockObject_MockObject */ + $entity = $this->getMockBuilder('Varien_Object') + ->setMethods(array('setPropertyA', 'setPropertyB')) + ->getMock(); + + $entity->expects($this->once()) + ->method('setPropertyA') + ->with('a'); + + $entity->expects($this->once()) + ->method('setPropertyB') + ->with('b'); + + $this->_callServiceProtectedMethod('_setDataUsingMethods', + array($entity, array('property_a' => 'a', 'property_b' => 'b'))); + + $this->assertEmpty($entity->getData()); + } + + /** + * Call protected method of service + * + * @param string $method + * @param array $arguments + * @return + */ + protected function _callServiceProtectedMethod($method, array $arguments = array()) + { + $method = new ReflectionMethod($this->_service, $method); + $method->setAccessible(true); + return $method->invokeArgs($this->_service, $arguments); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Customer/Service/CustomerTest.php b/dev/tests/unit/testsuite/Mage/Customer/Service/CustomerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..5c852215bd4d235fe5d7b429310a2d715f3007d6 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Customer/Service/CustomerTest.php @@ -0,0 +1,609 @@ +<?php +/** + * Unit test for customer service layer Mage_Customer_Service_Customer + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Customer_Service_CustomerTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Customer_Service_Customer|PHPUnit_Framework_MockObject_MockObject + */ + protected $_service; + + /** + * @var Mage_Customer_Model_Customer_Factory + */ + protected $_customerFactory; + + /** + * @var Mage_Customer_Model_Address_Factory + */ + protected $_addressFactory; + + /** + * @var Mage_Customer_Model_Customer + */ + protected $_customer; + + /** + * @var Mage_Customer_Model_Address + */ + protected $_address; + + protected function setUp() + { + $helper = $this->getMockBuilder('Mage_Customer_Helper_Data') + ->getMock(); + $helper->expects($this->any()) + ->method('__') + ->will($this->returnArgument(0)); + $this->_customerFactory = $this->getMockBuilder('Mage_Customer_Model_Customer_Factory') + ->disableOriginalConstructor() + ->setMethods(array('create')) + ->getMock(); + $this->_addressFactory = $this->getMockBuilder('Mage_Customer_Model_Address_Factory') + ->disableOriginalConstructor() + ->setMethods(array('create')) + ->getMock(); + + $this->_customer = $this->getMockBuilder('Mage_Customer_Model_Customer') + ->setMethods(array('save', 'generatePassword', 'getOrigData', 'sendNewAccountEmail', 'getConfirmation', + 'getPrimaryAddress', 'getAddresses', 'getAdditionalAddresses', 'load', 'getId', 'changePassword', + 'sendPasswordReminderEmail', 'addAddress', 'getAddressItemById', 'getAddressesCollection')) + ->disableOriginalConstructor() + ->getMock(); + $this->_customerFactory->expects($this->any()) + ->method('create') + ->will($this->returnValue($this->_customer)); + + $this->_address = $this->_createAddress(true, null); + $this->_addressFactory->expects($this->any()) + ->method('create') + ->will($this->returnValue($this->_address)); + + $this->_service = new Mage_Customer_Service_Customer($helper, $this->_customerFactory, $this->_addressFactory); + } + + /** + * @param bool $hasChanges + * @param int $addressId + * @return PHPUnit_Framework_MockObject_MockObject + */ + protected function _createAddress($hasChanges, $addressId) + { + $address = $this->getMockBuilder('Mage_Customer_Model_Address') + ->disableOriginalConstructor() + ->setMethods(array('hasDataChanges', 'getId', 'addData', 'setData', 'setCustomerId', 'setPostIndex')) + ->getMock(); + $address->expects($this->any()) + ->method('hasDataChanges') + ->will($this->returnValue($hasChanges)); + if ($addressId) { + $address->expects($this->any()) + ->method('getId') + ->will($this->returnValue($addressId)); + } + return $address; + } + + protected function tearDown() + { + unset($this->_service); + } + + /** + * Test for setSendRemainderEmail + * + * @param bool $set + * @param bool $expected + * @dataProvider setSendRemainderDataProvider + */ + public function testSetSendRemainderEmail($set, $expected) + { + $this->_service->setSendRemainderEmail($set); + $this->assertAttributeEquals($expected, '_sendRemainderEmail', $this->_service); + } + + /** + * @return array + */ + public function setSendRemainderDataProvider() + { + return array( + array(true, true), + array(false, false) + ); + } + + /** + * Test beforeSave and afterSave callback are set correctly + */ + public function testSetBeforeSaveCallback() + { + $this->assertInstanceOf('Mage_Customer_Service_Customer', $this->_service->setBeforeSaveCallback('intval')); + $this->assertAttributeEquals('intval', '_beforeSaveCallback', $this->_service); + } + + /** + * Check beforeSave and afterSave callbacks for create and update methods + * + * @param string $method + * @dataProvider methodsDataProvider + */ + public function testCallback($method) + { + $customerData = array('firstname' => 'test'); + $addressData = null; + $callback = $this->getMockBuilder('stdClass') + ->setMethods(array('beforeSave', 'afterSave')) + ->getMock(); + $callback->expects($this->once()) + ->method('beforeSave') + ->with($this->_customer, $customerData, $addressData); + $callback->expects($this->once()) + ->method('afterSave') + ->with($this->_customer, $customerData, $addressData); + + $this->_service->setBeforeSaveCallback(array($callback, 'beforeSave')); + $this->_service->setAfterSaveCallback(array($callback, 'afterSave')); + if ($method == 'create') { + $this->assertInstanceOf('Mage_Customer_Model_Customer', + $this->_service->create($customerData, $addressData)); + } else { + $this->_customer->expects($this->once()) + ->method('getId') + ->will($this->returnValue(1)); + $this->assertInstanceOf('Mage_Customer_Model_Customer', + $this->_service->update(1, $customerData, $addressData)); + } + } + + /** + * @return array + */ + public function methodsDataProvider() + { + return array( + array('create'), + array('update') + ); + } + + /** + * Test beforeSave and afterSave callback are set correctly + */ + public function testSetAfterSaveCallback() + { + $this->assertInstanceOf('Mage_Customer_Service_Customer', $this->_service->setAfterSaveCallback('intval')); + $this->assertAttributeEquals('intval', '_afterSaveCallback', $this->_service); + } + + /** + * Test setIsAdminStore setter + */ + public function testSetIsAdminStore() + { + $this->assertInstanceOf('Mage_Customer_Service_Customer', $this->_service->setIsAdminStore(true)); + $this->assertAttributeEquals(true, '_isAdminStore', $this->_service); + } + + /** + * @param bool $isAdminStore + * @param array $customerData + * @param array $expectedData + * @dataProvider forceConfirmedDataProvider + */ + public function testCreateForceConfirmed($isAdminStore, array $customerData, array $expectedData) + { + if (array_key_exists('autogenerate_password', $customerData)) { + $this->_customer->expects($this->once()) + ->method('generatePassword') + ->will($this->returnValue('generated_password')); + } + $this->_customer->expects($this->once()) + ->method('save'); + + $this->_service->setIsAdminStore($isAdminStore); + $this->assertInstanceOf('Mage_Customer_Model_Customer', + $this->_service->create($customerData)); + $this->assertEquals($expectedData, $this->_customer->toArray(array_keys($expectedData))); + } + + /** + * @return array + */ + public function forceConfirmedDataProvider() + { + return array( + 'force confirmed not set #1' => array( + 'isAdminStore' => false, + 'customerData' => array( + 'password' => '123123q' + ), + 'expectedData' => array( + 'password' => '123123q', + 'force_confirmed' => null + ), + ), + 'force confirmed not set #2' => array( + 'isAdminStore' => true, + 'customerData' => array(), + 'expectedData' => array( + 'force_confirmed' => null + ), + ), + 'force confirmed is set' => array( + 'isAdminStore' => true, + 'customerData' => array( + 'password' => '123123q' + ), + 'expectedData' => array( + 'password' => '123123q', + 'force_confirmed' => true + ), + ), + 'auto generated password' => array( + 'isAdminStore' => true, + 'customerData' => array( + 'autogenerate_password' => true + ), + 'expectedData' => array( + 'password' => 'generated_password', + 'force_confirmed' => true + ), + ) + ); + } + + /** + * @param array $customerData + * @param string $type + * @param int|null $origId + * @dataProvider welcomeEmailDataProvider + */ + public function testSendWelcomeEmail(array $customerData, $type, $origId) + { + $this->_customer->expects($this->once()) + ->method('sendNewAccountEmail') + ->with($type, '', $customerData['sendemail_store_id']); + $this->_customer->expects($this->once()) + ->method('save'); + $this->_customer->expects($this->once()) + ->method('getOrigData') + ->will($this->returnValue($origId)); + $this->_customer->expects($this->any()) + ->method('getConfirmation') + ->will($this->returnValue(false)); + + $this->assertInstanceOf('Mage_Customer_Model_Customer', $this->_service->create($customerData)); + } + + /** + * @return array + */ + public function welcomeEmailDataProvider() + { + return array( + 'new customer new password' => array( + array( + 'sendemail_store_id' => 1, + 'website_id' => 1, + 'sendemail' => true + ), + 'registered', + null + ), + 'new customer auto generated password' => array( + array( + 'sendemail_store_id' => 1, + 'website_id' => 1, + 'autogenerate_password' => true + ), + 'registered', + null + ), + 'existing customer new password' => array( + array( + 'sendemail_store_id' => 1, + 'website_id' => 1, + 'sendemail' => true + ), + 'confirmed', + 1 + ), + 'existing customer auto generated password' => array( + array( + 'sendemail_store_id' => 1, + 'website_id' => 1, + 'autogenerate_password' => true + ), + 'confirmed', + 1 + ), + ); + } + + /** + * @param array $customerData + * @param int|null $origId + * @dataProvider welcomeEmailNotCalledDataProvider + */ + public function testSendWelcomeEmailNotCalled(array $customerData, $origId) + { + $this->_customer->expects($this->never()) + ->method('sendNewAccountEmail'); + $this->_customer->expects($this->once()) + ->method('save'); + $this->_customer->expects($this->any()) + ->method('getOrigData') + ->will($this->returnValue($origId)); + if (array_key_exists('confirmation', $customerData)) { + $this->_customer->expects($this->any()) + ->method('getConfirmation') + ->will($this->returnValue($customerData['confirmation'])); + } + + $this->assertInstanceOf('Mage_Customer_Model_Customer', $this->_service->create($customerData)); + } + + /** + * @return array + */ + public function welcomeEmailNotCalledDataProvider() + { + return array( + 'unchanged password' => array( + array( + 'website_id' => 1, + ), + null + ), + 'no website new customer send email' => array( + array( + 'website_id' => 0, + 'sendemail' => true + ), + null + ), + 'no website new customer auto generated password' => array( + array( + 'website_id' => 0, + 'autogenerate_password' => true + ), + null + ), + 'no website existing customer new password' => array( + array( + 'website_id' => 0, + 'sendemail' => true + ), + 1 + ), + 'existing customer auto generated password' => array( + array( + 'website_id' => 0, + 'autogenerate_password' => true + ), + 1 + ), + 'not new no confirmation' => array( + array( + 'sendemail_store_id' => 1, + 'website_id' => 1, + 'sendemail' => true, + 'confirmation' => true + ), + 1 + ) + ); + } + + /** + * @expectedException Mage_Core_Exception + * @expectedExceptionMessage The customer with the specified ID not found. + */ + public function testLoadCustomerByIdException() + { + $this->_customer->expects($this->never()) + ->method('save'); + $this->_customer->expects($this->once()) + ->method('load') + ->with(1); + $this->_customer->expects($this->once()) + ->method('getId') + ->will($this->returnValue(false)); + + $this->_service->update(1, array('firstname' => 'test')); + } + + /** + * @param array $customerData + * @dataProvider changePasswordDataProvider + */ + public function testChangePassword(array $customerData) + { + $password = isset($customerData['password']) ? $customerData['password'] : 'generated_password'; + $this->_customer->expects($this->once()) + ->method('save'); + $this->_customer->expects($this->once()) + ->method('getId') + ->will($this->returnValue(1)); + $this->_customer->expects($this->once()) + ->method('changePassword') + ->with($password) + ->will($this->returnSelf()); + $this->_customer->expects($this->once()) + ->method('sendPasswordReminderEmail') + ->will($this->returnSelf()); + if (array_key_exists('autogenerate_password', $customerData)) { + $this->_customer->expects($this->once()) + ->method('generatePassword') + ->will($this->returnValue('generated_password')); + } + + $this->assertInstanceOf('Mage_Customer_Model_Customer', $this->_service->update(1, $customerData)); + } + + /** + * @return array + */ + public function changePasswordDataProvider() + { + return array( + 'new password' => array( + array('password' => '123123q') + ), + 'auto generated password' => array( + array('autogenerate_password' => true) + ) + ); + } + + /** + * @param array $addressData + * @param Mage_Customer_Model_Address|null $newAddress + * @param Mage_Customer_Model_Address|null $existingAddress + * @param array $addressCollection + * @param bool $dataChanged + * @param bool $expectedDataChange + * @dataProvider addressesDataProvider + */ + public function testPrepareCustomerAddressForSave(array $addressData, $newAddress, $existingAddress, + array $addressCollection, $dataChanged, $expectedDataChange + ) { + $this->_customer->setDataChanges($dataChanged); + + $this->_customer->expects($this->any()) + ->method('getId') + ->will($this->returnValue(1)); + + $this->_customer->expects($this->once()) + ->method('getAddressesCollection') + ->will($this->returnValue($addressCollection)); + + if ($newAddress) { + // Check that customer_id is set for new addresses + $newAddress->expects($this->once()) + ->method('setCustomerId') + ->with(1); + // Check that new address is added to customer address collection + $this->_customer->expects($this->once()) + ->method('addAddress'); + + // Check that new address is not deleted + $newAddress->expects($this->never()) + ->method('setData') + ->with('_deleted', true); + } + + // Check that address loaded from customer address collection + if ($existingAddress && $addressData) { + $this->_customer->expects($this->once()) + ->method('getAddressItemById') + ->with($existingAddress->getId()) + ->will($this->returnValue($existingAddress)); + } + + // Check that new data is added + $hasExistingAddress = false; + foreach ($addressData as $data) { + if (array_key_exists('entity_id', $addressData)) { + unset($data['entity_id']); + $existingAddress->expects($this->once()) + ->method('addData') + ->with($data); + $hasExistingAddress = true; + } elseif ($newAddress) { + $newAddress->expects($this->once()) + ->method('addData') + ->with($data); + } + } + // Check that addresses is deleted + if (in_array($existingAddress, $addressCollection) && !$hasExistingAddress) { + $existingAddress->expects($this->atLeastOnce()) + ->method('setData') + ->with('_deleted', true); + } + + $this->assertInstanceOf('Mage_Customer_Model_Customer', $this->_service->update(1, array(), $addressData), + 'Incorrect instance returned'); + + $this->assertEquals($expectedDataChange, $this->_customer->hasDataChanges(), + 'Customer change data status is incorrect'); + } + + /** + * @return array + */ + public function addressesDataProvider() + { + $newAddress = $this->_createAddress(true, null); + $existingAddress = $this->_createAddress(true, 2); + return array( + 'no addresses #1' => array( + array(), null, null, array(), false, false + ), + 'no addresses #2' => array( + array(), null, null, array(), true, true + ), + 'new address' => array( + array(array('city' => 'test')), + $newAddress, null, + array($newAddress), false, true + ), + 'existing address' => array( + array(array('entity_id' => 2, 'city' => 'test')), + null, $existingAddress, + array($existingAddress), false, true + ), + 'new added, existing deleted' => array( + array(array('city' => 'test')), + $newAddress, null, + array($newAddress, $existingAddress), false, true + ), + 'all addresses deleted' => array( + array(), + null, $existingAddress, + array($existingAddress), false, true + ) + ); + } + + /** + * @expectedException Mage_Core_Exception + * @expectedExceptionMessage The address with the specified ID not found. + */ + public function testPrepareCustomerAddressForSaveException() + { + $this->_customer->expects($this->any()) + ->method('getId') + ->will($this->returnValue(1)); + $address = $this->_createAddress(true, 1); + $this->_customer->expects($this->once()) + ->method('getAddressItemById') + ->with($address->getId()) + ->will($this->returnValue(false)); + $this->_service->update(1, array(), array(array('entity_id' => 1, 'city' => 'test'))); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Eav/Model/FormTest.php b/dev/tests/unit/testsuite/Mage/Eav/Model/FormTest.php new file mode 100644 index 0000000000000000000000000000000000000000..e1a9f38908ac944c7edb1dbd1c8155de760a577c --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Eav/Model/FormTest.php @@ -0,0 +1,193 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Eav + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Test for Mage_Eav_Model_Form + */ +class Mage_Eav_Model_FormTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Eav_Model_Form + */ + protected $_model = null; + + /** + * @var array + */ + protected $_attributes = null; + + /** + * @var array + */ + protected $_systemAttribute = null; + + /** + * @var array + */ + protected $_userAttribute = null; + + /** + * @var Varien_Object + */ + protected $_entity = null; + + /** + * Initialize form + */ + protected function setUp() + { + $this->_model = $this->getMockBuilder('Mage_Eav_Model_Form') + ->setMethods(array('_getFilteredFormAttributeCollection', '_getValidator', 'getEntity')) + ->disableOriginalConstructor() + ->getMock(); + + $this->_userAttribute = new Varien_Object(array( + 'is_user_defined' => true, + 'attribute_code' => 'attribute_visible_user', + 'is_visible' => true + )); + $this->_systemAttribute = new Varien_Object(array( + 'is_user_defined' => false, + 'attribute_code' => 'attribute_invisible_system', + 'is_visible' => false + )); + $this->_attributes = array($this->_userAttribute, $this->_systemAttribute); + $this->_model->expects($this->any()) + ->method('_getFilteredFormAttributeCollection') + ->will($this->returnValue($this->_attributes)); + + $this->_entity = new Varien_Object(array('id' => 1, 'attribute_visible_user' => 'abc')); + $this->_model->expects($this->any()) + ->method('getEntity') + ->will($this->returnValue($this->_entity)); + } + + /** + * Unset form + */ + protected function tearDown() + { + unset($this->_model); + } + + /** + * Test getAttributes + */ + public function testGetAttributes() + { + $expected = array( + 'attribute_visible_user' => $this->_userAttribute, + 'attribute_invisible_system' => $this->_systemAttribute + ); + $this->assertEquals($expected, $this->_model->getAttributes()); + } + + /** + * Test getUserAttributes + */ + public function testGetUserAttributes() + { + $expected = array( + 'attribute_visible_user' => $this->_userAttribute + ); + $this->assertEquals($expected, $this->_model->getUserAttributes()); + } + + /** + * Test getSystemAttributes + */ + public function testGetSystemAttributes() + { + $expected = array( + 'attribute_invisible_system' => $this->_systemAttribute + ); + $this->assertEquals($expected, $this->_model->getSystemAttributes()); + } + + /** + * Test getAllowedAttributes + */ + public function testGetAllowedAttributes() + { + $expected = array( + 'attribute_visible_user' => $this->_userAttribute + ); + $this->assertEquals($expected, $this->_model->getAllowedAttributes()); + } + + /** + * Test validateData method + * + * @dataProvider validateDataProvider + * + * @param bool $isValid + * @param bool|array $expected + * @param null|array $messages + */ + public function testValidateDataPassed($isValid, $expected, $messages = null) + { + $validator = $this->getMockBuilder('Mage_Eav_Model_Validator_Attribute_Data') + ->disableOriginalConstructor() + ->setMethods(array('isValid', 'getMessages')) + ->getMock(); + $validator->expects($this->once()) + ->method('isValid') + ->will($this->returnValue($isValid)); + if ($messages) { + $validator->expects($this->once()) + ->method('getMessages') + ->will($this->returnValue($messages)); + } else { + $validator->expects($this->never()) + ->method('getMessages'); + } + + $this->_model->expects($this->once()) + ->method('_getValidator') + ->will($this->returnValue($validator)); + + $data = array('test' => true); + $this->assertEquals($expected, $this->_model->validateData($data)); + } + + /** + * Data provider for testValidateDataPassed + * + * @return array + */ + public function validateDataProvider() + { + return array( + 'is_valid' => array( + true, true, null + ), + 'is_invalid' => array( + false, array('Invalid'), array('attribute_visible_user' => array('Invalid')) + ), + ); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Eav/Model/Validator/Attribute/DataTest.php b/dev/tests/unit/testsuite/Mage/Eav/Model/Validator/Attribute/DataTest.php new file mode 100644 index 0000000000000000000000000000000000000000..03f1e80f6276b6756e04b978dd78d6c38cf9d39c --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Eav/Model/Validator/Attribute/DataTest.php @@ -0,0 +1,384 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Eav + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Test for Mage_Eav_Model_Validator_Attribute_Data + */ +class Mage_Eav_Model_Validator_Attribute_DataTest extends PHPUnit_Framework_TestCase +{ + /** + * Testing Mage_Eav_Model_Validator_Attribute_Data::isValid + * + * @dataProvider isValidDataProvider + * + * @param array $attributeData + * @param array|bool $result + * @param bool $expected + * @param array $messages + * @param array $data + */ + public function testIsValid($attributeData, $result, $expected, $messages, $data = array('attribute' => 'new_test')) + { + $entity = $this->_getEntityMock(); + $attribute = $this->_getAttributeMock($attributeData); + + $validator = new Mage_Eav_Model_Validator_Attribute_Data; + $validator->setAttributes(array($attribute)) + ->setData($data); + if ($attribute->getDataModel() || $attribute->getFrontendInput()) { + $dataModel = $this->_getDataModelMock($result); + $factory = $this->_getFactoryMock($dataModel); + $validator->setAttributeDataModelFactory($factory); + } + $this->assertEquals($expected, $validator->isValid($entity)); + $this->assertEquals($messages, $validator->getMessages()); + } + + /** + * Data provider for testIsValid + * + * @return array + */ + public function isValidDataProvider() + { + return array( + 'is_valid' => array( + 'attributeData' => array( + 'attribute_code' => 'attribute', + 'data_model' => $this->_getDataModelMock(null), + 'frontend_input' => 'text' + ), + 'attributeReturns' => true, + 'isValid' => true, + 'messages' => array() + ), + 'is_invalid' => array( + 'attributeData' => array( + 'attribute_code' => 'attribute', + 'data_model' => $this->_getDataModelMock(null), + 'frontend_input' => 'text' + ), + 'attributeReturns' => array('Error'), + 'isValid' => false, + 'messages' => array('attribute' => array('Error')) + ), + 'no_data_models' => array( + 'attributeData' => array( + 'attribute_code' => 'attribute', + 'frontend_input' => 'text' + ), + 'attributeReturns' => array('Error'), + 'isValid' => false, + 'messages' => array('attribute' => array('Error')) + ), + 'no_data_models_no_frontend_input' => array( + 'attributeData' => array( + 'attribute_code' => 'attribute', + ), + 'attributeReturns' => array('Error'), + 'isValid' => true, + 'messages' => array() + ), + 'no_data_for attribute' => array( + 'attributeData' => array( + 'attribute_code' => 'attribute', + 'data_model' => $this->_getDataModelMock(null), + 'frontend_input' => 'text' + ), + 'attributeReturns' => true, + 'isValid' => true, + 'messages' => array(), + 'setData' => array('attribute2' => 'new_test') + ), + 'is_valid_data_from_entity' => array( + 'attributeData' => array( + 'attribute_code' => 'attribute', + 'data_model' => $this->_getDataModelMock(null), + 'frontend_input' => 'text' + ), + 'attributeReturns' => true, + 'isValid' => true, + 'messages' => array(), + 'setData' => array() + ), + ); + } + + /** + * Testing Mage_Eav_Model_Validator_Attribute_Data::isValid + * + * In this test entity attributes are got from attribute collection. + */ + public function testIsValidAttributesFromCollection() + { + /** @var Mage_Eav_Model_Entity_Abstract $resource */ + $resource = $this->getMockForAbstractClass('Mage_Eav_Model_Entity_Abstract'); + $attribute = $this->_getAttributeMock(array( + 'attribute_code' => 'attribute', + 'data_model' => $this->_getDataModelMock(null), + 'frontend_input' => 'text' + )); + $collection = $this->getMockBuilder('Varien_Object') + ->setMethods(array('getItems')) + ->getMock(); + $collection->expects($this->once())->method('getItems')->will($this->returnValue(array($attribute))); + $entityType = $this->getMockBuilder('Varien_Object') + ->setMethods(array('getAttributeCollection')) + ->getMock(); + $entityType->expects($this->once())->method('getAttributeCollection')->will($this->returnValue($collection)); + $entity = $this->_getEntityMock(); + $entity->expects($this->once())->method('getResource')->will($this->returnValue($resource)); + $entity->expects($this->once())->method('getEntityType')->will($this->returnValue($entityType)); + $dataModel = $this->_getDataModelMock(true); + $factory = $this->_getFactoryMock($dataModel); + + $validator = new Mage_Eav_Model_Validator_Attribute_Data; + $validator->setData(array('attribute' => 'new_test_data')) + ->setAttributeDataModelFactory($factory); + $this->assertTrue($validator->isValid($entity)); + } + + /** + * @dataProvider whiteBlackListProvider + * @param callable $callback + */ + public function testIsValidBlackListWhiteListChecks($callback) + { + $attribute = $this->_getAttributeMock(array( + 'attribute_code' => 'attribute', + 'data_model' => $this->_getDataModelMock(null), + 'frontend_input' => 'text' + )); + $secondAttribute = $this->_getAttributeMock(array( + 'attribute_code' => 'attribute2', + 'data_model' => $this->_getDataModelMock(null), + 'frontend_input' => 'text' + )); + $data = array( + 'attribute' => 'new_test_data', + 'attribute2' => 'some data' + ); + $entity = $this->_getEntityMock(); + $dataModel = $this->_getDataModelMock(true, $data['attribute']); + $factory = $this->_getFactoryMock($dataModel); + + $validator = new Mage_Eav_Model_Validator_Attribute_Data; + $validator->setAttributeDataModelFactory($factory) + ->setAttributes(array($attribute, $secondAttribute)) + ->setData($data); + $callback($validator); + $this->assertTrue($validator->isValid($entity)); + } + + /** + * @return array + */ + public function whiteBlackListProvider() + { + return array( + 'white_list' => array( + function ($validator) { + $validator->setAttributesWhiteList(array('attribute')); + } + ), + 'black_list' => array( + function ($validator) { + $validator->setAttributesBlackList(array('attribute2')); + } + ) + ); + } + + public function testSetAttributesWhiteList() + { + $attributes = array('attr1', 'attr2', 'attr3'); + $validator = new Mage_Eav_Model_Validator_Attribute_Data; + $result = $validator->setAttributesWhiteList($attributes); + $this->assertAttributeEquals($attributes, '_attributesWhiteList', $validator); + $this->assertEquals($validator, $result); + } + + public function testSetAttributesBlackList() + { + $attributes = array('attr1', 'attr2', 'attr3'); + $validator = new Mage_Eav_Model_Validator_Attribute_Data; + $result = $validator->setAttributesBlackList($attributes); + $this->assertAttributeEquals($attributes, '_attributesBlackList', $validator); + $this->assertEquals($validator, $result); + } + + public function testSetAttributeDataModelFactory() + { + $factory = $this->getMockBuilder('Mage_Eav_Model_Attribute_Data')->getMock(); + $validator = new Mage_Eav_Model_Validator_Attribute_Data; + $result = $validator->setAttributeDataModelFactory($factory); + $this->assertAttributeEquals($factory, '_dataModelFactory', $validator); + $this->assertEquals($validator, $result); + } + + public function testGetAttributeDataModelFactory() + { + $validator = new Mage_Eav_Model_Validator_Attribute_Data; + $factory = $validator->getAttributeDataModelFactory(); + $this->assertInstanceOf('Mage_Eav_Model_Attribute_Data', $factory); + $this->assertAttributeEquals($factory, '_dataModelFactory', $validator); + } + + public function testAddErrorMessages() + { + $data = array( + 'attribute1' => 'new_test', + 'attribute2' => 'some data' + ); + $entity = $this->_getEntityMock(); + $firstAttribute = $this->_getAttributeMock(array( + 'attribute_code' => 'attribute1', + 'data_model' => $firstDataModel = $this->_getDataModelMock(array('Error1')), + 'frontend_input' => 'text' + )); + $secondAttribute = $this->_getAttributeMock(array( + 'attribute_code' => 'attribute2', + 'data_model' => $secondDataModel = $this->_getDataModelMock(array('Error2')), + 'frontend_input' => 'text' + )); + $expectedMessages = array( + 'attribute1' => array('Error1'), + 'attribute2' => array('Error2'), + ); + $expectedDouble = array( + 'attribute1' => array('Error1', 'Error1'), + 'attribute2' => array('Error2', 'Error2'), + ); + + $validator = new Mage_Eav_Model_Validator_Attribute_Data; + $validator->setAttributes(array($firstAttribute, $secondAttribute)) + ->setData($data); + + $factory = $this->getMockBuilder('Mage_Eav_Model_Attribute_Data') + ->setMethods(array('factory')) + ->getMock(); + $factory::staticExpects($this->at(0)) + ->method('factory') + ->with($firstAttribute, $entity) + ->will($this->returnValue($firstDataModel)); + $factory::staticExpects($this->at(1)) + ->method('factory') + ->with($secondAttribute, $entity) + ->will($this->returnValue($secondDataModel)); + $factory::staticExpects($this->at(2)) + ->method('factory') + ->with($firstAttribute, $entity) + ->will($this->returnValue($firstDataModel)); + $factory::staticExpects($this->at(3)) + ->method('factory') + ->with($secondAttribute, $entity) + ->will($this->returnValue($secondDataModel)); + + $validator->setAttributeDataModelFactory($factory); + + $this->assertFalse($validator->isValid($entity)); + $this->assertEquals($expectedMessages, $validator->getMessages()); + $this->assertFalse($validator->isValid($entity)); + $this->assertEquals($expectedDouble, $validator->getMessages()); + } + + /** + * @param array $attributeData + * @return PHPUnit_Framework_MockObject_MockObject + */ + protected function _getAttributeMock($attributeData) + { + $attribute = $this->getMockBuilder('Mage_Eav_Model_Attribute') + ->setMethods(array('getAttributeCode', 'getDataModel', 'getFrontendInput')) + ->disableOriginalConstructor() + ->getMock(); + if (isset($attributeData['attribute_code'])) { + $attribute->expects($this->any())->method('getAttributeCode') + ->will($this->returnValue($attributeData['attribute_code'])); + } + if (isset($attributeData['data_model'])) { + $attribute->expects($this->any())->method('getDataModel') + ->will($this->returnValue($attributeData['data_model'])); + } + if (isset($attributeData['frontend_input'])) { + $attribute->expects($this->any())->method('getFrontendInput') + ->will($this->returnValue($attributeData['frontend_input'])); + } + return $attribute; + } + + /** + * @param Mage_Eav_Model_Attribute_Data_Abstract $dataModel + * @return PHPUnit_Framework_MockObject_MockObject + */ + protected function _getFactoryMock($dataModel) + { + $factory = $this->getMockBuilder('Mage_Eav_Model_Attribute_Data') + ->setMethods(array('factory')) + ->getMock(); + $factory::staticExpects($this->once()) + ->method('factory') + ->will($this->returnValue($dataModel)); + return $factory; + } + + /** + * @param boolean $returnValue + * @param string|null $argument + * @return PHPUnit_Framework_MockObject_MockObject + */ + protected function _getDataModelMock($returnValue, $argument = null) + { + $dataModel = $this->getMockBuilder('Mage_Eav_Model_Attribute_Data_Abstract') + ->disableOriginalConstructor() + ->setMethods(array('validateValue')) + ->getMockForAbstractClass(); + if ($argument) { + $dataModel->expects($this->once()) + ->method('validateValue') + ->with($argument) + ->will($this->returnValue($returnValue)); + } else { + $dataModel->expects($this->any()) + ->method('validateValue') + ->will($this->returnValue($returnValue)); + } + return $dataModel; + } + + /** + * @return PHPUnit_Framework_MockObject_MockObject + */ + protected function _getEntityMock() + { + $entity = $this->getMockBuilder('Mage_Core_Model_Abstract') + ->setMethods(array('getAttribute', 'getResource', 'getEntityType')) + ->disableOriginalConstructor() + ->getMock(); + return $entity; + } +} diff --git a/dev/tests/unit/testsuite/Mage/Page/Block/Html/HeaderTest.php b/dev/tests/unit/testsuite/Mage/Page/Block/Html/HeaderTest.php new file mode 100644 index 0000000000000000000000000000000000000000..88b21455f350f1e8716758181dfed778c8da825d --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Page/Block/Html/HeaderTest.php @@ -0,0 +1,72 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_Page + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_Page_Block_Html_HeaderTest extends PHPUnit_Framework_TestCase +{ + /** + * @covers Mage_Page_Block_Html_Header::getLogoSrc + */ + public function testGetLogoSrc() + { + $storeConfig = $this->getMock('Mage_Core_Model_Store_Config', array('getConfig')); + $storeConfig->expects($this->once()) + ->method('getConfig') + ->will($this->returnValue('default/image.gif')); + + $urlBuilder = $this->getMock('Mage_Core_Model_Url', array('getBaseUrl')); + $urlBuilder->expects($this->once()) + ->method('getBaseUrl') + ->will($this->returnValue('http://localhost/pub/media/')); + + $configOptions = $this->getMock('Mage_Core_Model_Config_Options', array('getDir')); + $configOptions->expects($this->once()) + ->method('getDir') + ->will($this->returnValue(__DIR__ . DIRECTORY_SEPARATOR . '_files')); + + $helper = $this->getMock('Mage_Core_Helper_File_Storage_Database', array('checkDbUsage')); + $helper->expects($this->once()) + ->method('checkDbUsage') + ->will($this->returnValue(false)); + + $helperFactory = $this->getMock('Mage_Core_Model_Factory_Helper', array('get')); + $helperFactory->expects($this->once()) + ->method('get') + ->will($this->returnValue($helper)); + + $objectManager = new Magento_Test_Helper_ObjectManager($this); + + $arguments = array( + 'storeConfig' => $storeConfig, + 'urlBuilder' => $urlBuilder, + 'configOptions' => $configOptions, + 'helperFactory' => $helperFactory + ); + $this->_block = $objectManager->getBlock('Mage_Page_Block_Html_Header', $arguments); + + $this->assertEquals('http://localhost/pub/media/logo/default/image.gif', $this->_block->getLogoSrc()); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Page/Block/Html/_files/logo/default/image.gif b/dev/tests/unit/testsuite/Mage/Page/Block/Html/_files/logo/default/image.gif new file mode 100644 index 0000000000000000000000000000000000000000..3fe49d2660832eb0f202bbfafd7366b0e0353c46 Binary files /dev/null and b/dev/tests/unit/testsuite/Mage/Page/Block/Html/_files/logo/default/image.gif differ diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Block/Adminhtml/Role/Edit/Tab/ResourceTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Block/Adminhtml/Role/Edit/Tab/ResourceTest.php new file mode 100644 index 0000000000000000000000000000000000000000..7cf132cf1ebdc9b0a4fcb55bba4ee386d300cefe --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Block/Adminhtml/Role/Edit/Tab/ResourceTest.php @@ -0,0 +1,98 @@ +<?php +/** + * Test for Mage_Webapi_Block_Adminhtml_Role_Edit_Tab_Resource block + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Block_Adminhtml_Role_Edit_Tab_ResourceTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Webapi_Model_Resource_Acl_Rule|PHPUnit_Framework_MockObject_MockObject + */ + protected $_ruleResource; + + /** + * @var Mage_Webapi_Block_Adminhtml_Role_Edit_Tab_Resource + */ + protected $_block; + + protected function setUp() + { + $this->_ruleResource = $this->getMockBuilder('Mage_Webapi_Model_Resource_Acl_Rule') + ->disableOriginalConstructor() + ->setMethods(array('getResourceIdsByRole')) + ->getMock(); + + $helper = new Magento_Test_Helper_ObjectManager($this); + $this->_block = $helper->getBlock('Mage_Webapi_Block_Adminhtml_Role_Edit_Tab_Resource', array( + // TODO Remove injecting of 'urlBuilder' and 'authorizationConfig' after MAGETWO-5038 complete + 'urlBuilder' => $this->getMockBuilder('Mage_Backend_Model_Url') + ->disableOriginalConstructor() + ->getMock(), + 'authorizationConfig' => $this->getMockBuilder('Mage_Webapi_Model_Authorization_Config') + ->disableOriginalConstructor() + ->getMock(), + 'ruleResource' => $this->_ruleResource + )); + } + + /** + * Test isEverythingAllowed method + * + * @dataProvider isEverythingAllowedDataProvider + * @param array $selectedResources + * @param bool $expectedResult + */ + public function testIsEverythingAllowed($selectedResources, $expectedResult) + { + $apiRole = new Varien_Object(array( + 'role_id' => 1 + )); + $apiRole->setIdFieldName('role_id'); + + $this->_block->setApiRole($apiRole); + + $this->_ruleResource->expects($this->once()) + ->method('getResourceIdsByRole') + ->with($apiRole->getId()) + ->will($this->returnValue($selectedResources)); + + $this->assertEquals($expectedResult, $this->_block->isEverythingAllowed()); + } + + /** + * @return array + */ + public function isEverythingAllowedDataProvider() + { + return array( + 'Not Everything Allowed' => array( + array('customer', 'customer/get'), + false + ), + 'Everything Allowed' => array( + array('customer', 'customer/get', Mage_Webapi_Model_Authorization::API_ACL_RESOURCES_ROOT_ID), + true + ) + ); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Block/Adminhtml/Role/Edit/TabsTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Block/Adminhtml/Role/Edit/TabsTest.php new file mode 100644 index 0000000000000000000000000000000000000000..22ffdc7e2638f236154e13e1ef197602b1dd08c5 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Block/Adminhtml/Role/Edit/TabsTest.php @@ -0,0 +1,133 @@ +<?php +/** + * Test class for Mage_Webapi_Block_Adminhtml_Role_Edit_Tabs + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Block_Adminhtml_Role_Edit_TabsTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Webapi_Block_Adminhtml_Role_Edit_Tabs + */ + protected $_block; + + /** + * @var PHPUnit_Framework_MockObject_MockObject|Mage_Core_Model_Layout + */ + protected $_layout; + + /** + * @var Magento_Test_Helper_ObjectManager + */ + protected $_helper; + + /** + * @var PHPUnit_Framework_MockObject_MockObject|Mage_Core_Controller_Request_Http + */ + protected $_request; + + protected function setUp() + { + /** @var Mage_Backend_Model_Url|PHPUnit_Framework_MockObject_MockObject $urlBuilder */ + $urlBuilder = $this->getMockBuilder('Mage_Backend_Model_Url') + ->disableOriginalConstructor() + ->getMock(); + + $this->_layout = $this->getMockBuilder('Mage_Core_Model_Layout') + ->disableOriginalConstructor() + ->setMethods(array('helper', 'getBlock')) + ->getMock(); + + $this->_request = $this->getMockBuilder('Mage_Core_Controller_Request_Http') + ->getMock(); + + $this->_helper = new Magento_Test_Helper_ObjectManager($this); + $this->_block = $this->_helper->getBlock('Mage_Webapi_Block_Adminhtml_Role_Edit_Tabs', array( + 'urlBuilder' => $urlBuilder, + 'layout' => $this->_layout, + 'request' => $this->_request + )); + } + + /** + * Test _construct method + */ + public function testConstruct() + { + $this->assertEquals('page_tabs', $this->_block->getId()); + $this->assertEquals('edit_form', $this->_block->getDestElementId()); + $this->assertEquals('Role Information', $this->_block->getTitle()); + } + + /** + * Test for _beforeToHtml method + * + * @dataProvider beforeToHtmlDataProvider + * @param object $apiRole + * @param array $expectedTabIds + */ + public function testBeforeToHtml($apiRole, $expectedTabIds) + { + $this->_block->setApiRole($apiRole); + + $mainBlock = $this->_helper->getBlock('Mage_Core_Block_Text'); + $resourceBlock = $this->_helper->getBlock('Mage_Core_Block_Text'); + $userBlock = $this->_helper->getBlock('Mage_Core_Block_Text'); + + $this->_layout->expects($this->any()) + ->method('getBlock') + ->will($this->returnValueMap(array( + array('webapi.role.edit.tab.main', $mainBlock), + array('webapi.role.edit.tab.resource', $resourceBlock), + array('webapi.role.edit.tab.users.grid', $userBlock), + ))); + + $this->_request->expects($this->any())->method('getParam')->will($this->returnValueMap(array( + array('active_tab', null, 'main_section') + ))); + + // todo: do checks using toHtml() when DI is implemented for abstract blocks + $toHtmlMethod = new ReflectionMethod($this->_block, '_beforeToHtml'); + $toHtmlMethod->setAccessible(true); + $toHtmlMethod ->invoke($this->_block); + + $this->assertEquals($expectedTabIds, $this->_block->getTabsIds()); + $this->assertEquals($apiRole, $mainBlock->getApiRole()); + $this->assertEquals($apiRole, $resourceBlock->getApiRole()); + } + + /** + * @return array + */ + public function beforeToHtmlDataProvider() + { + return array( + array( + new Varien_Object(array( + 'role_id' => 1, + 'role_name' => 'some_role' + )), + array('main_section', 'resource_section', 'user_section'), + ) + ); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Block/Adminhtml/Role/EditTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Block/Adminhtml/Role/EditTest.php new file mode 100644 index 0000000000000000000000000000000000000000..d62923299539183be9d80a48584535dc87ae9f75 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Block/Adminhtml/Role/EditTest.php @@ -0,0 +1,150 @@ +<?php +/** + * Test class for Mage_Webapi_Block_Adminhtml_Role_Edit + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Block_Adminhtml_Role_EditTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Core_Controller_Request_Http|PHPUnit_Framework_MockObject_MockObject + */ + protected $_request; + + /** + * @var Mage_Backend_Model_Url|PHPUnit_Framework_MockObject_MockObject + */ + protected $_urlBuilder; + + /** + * @var PHPUnit_Framework_MockObject_MockObject|Mage_Core_Model_Layout + */ + protected $_layout; + + /** + * @var Mage_Webapi_Block_Adminhtml_Role_Edit + */ + protected $_block; + + protected function setUp() + { + $this->_urlBuilder = $this->getMockBuilder('Mage_Backend_Model_Url') + ->disableOriginalConstructor() + ->getMock(); + + $this->_layout = $this->getMockBuilder('Mage_Core_Model_Layout') + ->disableOriginalConstructor() + ->setMethods(array('helper', 'getChildBlock', 'getChildName')) + ->getMock(); + + $this->_request = $this->getMockBuilder('Mage_Core_Controller_Request_Http') + ->disableOriginalConstructor() + ->setMethods(array('getParam')) + ->getMock(); + + $this->_request->expects($this->any()) + ->method('getParam') + ->with('role_id') + ->will($this->returnValue(1)); + + $helper = new Magento_Test_Helper_ObjectManager($this); + $this->_block = $helper->getBlock('Mage_Webapi_Block_Adminhtml_Role_Edit', array( + 'urlBuilder' => $this->_urlBuilder, + 'layout' => $this->_layout, + 'request' => $this->_request + )); + } + + /** + * Test _construct method + */ + public function testConstruct() + { + $this->assertAttributeEquals('Mage_Webapi', '_blockGroup', $this->_block); + $this->assertAttributeEquals('adminhtml_role', '_controller', $this->_block); + $this->assertAttributeEquals('role_id', '_objectId', $this->_block); + $this->_assertBlockHasButton(1, 'save', 'Save API Role'); + $this->_assertBlockHasButton(0, 'delete', 'Delete API Role'); + } + + /** + * Test getSaveAndContinueUrl method + */ + public function testGetSaveAndContinueUrl() + { + $expectedUrl = 'save_and_continue_url'; + $this->_urlBuilder + ->expects($this->once()) + ->method('getUrl') + ->with('*/*/save', array('_current' => true, 'continue' => true)) + ->will($this->returnValue($expectedUrl)); + + $this->assertEquals($expectedUrl, $this->_block->getSaveAndContinueUrl()); + } + + /** + * Test getHeaderText method + */ + public function testGetHeaderText() + { + $apiRole = new Varien_Object(); + $this->_block->setApiRole($apiRole); + $this->assertEquals('New API Role', $this->_block->getHeaderText()); + + $apiRole->setId(1)->setRoleName('Test Role'); + + /** @var PHPUnit_Framework_MockObject_MockObject $coreHelper */ + $coreHelper = $this->getMockBuilder('Mage_Core_Helper_Data') + ->disableOriginalConstructor() + ->setMethods(array('escapeHtml')) + ->getMock(); + $coreHelper->expects($this->once()) + ->method('escapeHtml') + ->with($apiRole->getRoleName()) + ->will($this->returnArgument(0)); + $this->_layout->expects($this->once()) + ->method('helper') + ->with('Mage_Core_Helper_Data') + ->will($this->returnValue($coreHelper)); + + $this->assertEquals("Edit API Role 'Test Role'", $this->_block->getHeaderText()); + } + + /** + * Asserts that block has button with id and label at level + * + * @param int $level + * @param string $buttonId + * @param string $label + */ + protected function _assertBlockHasButton($level, $buttonId, $label) + { + $buttonsProperty = new ReflectionProperty($this->_block, '_buttons'); + $buttonsProperty->setAccessible(true); + $buttons = $buttonsProperty->getValue($this->_block); + $this->assertInternalType('array', $buttons, 'Cannot get bloc buttons'); + $this->assertArrayHasKey($level, $buttons, "Block doesn't have buttons at level $level"); + $this->assertArrayHasKey($buttonId, $buttons[$level], "Block doesn't have '$buttonId' button at level $level"); + $this->assertArrayHasKey('label', $buttons[$level][$buttonId], "Block button doesn't have label"); + $this->assertEquals($label, $buttons[$level][$buttonId]['label'], "Block button label has unexpected value"); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Block/Adminhtml/RoleTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Block/Adminhtml/RoleTest.php new file mode 100644 index 0000000000000000000000000000000000000000..4300da0d4b7969fe25f6b952f64307b19e548d2a --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Block/Adminhtml/RoleTest.php @@ -0,0 +1,94 @@ +<?php +/** + * Test class for Mage_Webapi_Block_Adminhtml_Role + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Block_Adminhtml_RoleTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Backend_Model_Url|PHPUnit_Framework_MockObject_MockObject + */ + protected $_urlBuilder; + + /** + * @var Mage_Webapi_Block_Adminhtml_Role + */ + protected $_block; + + protected function setUp() + { + $this->_urlBuilder = $this->getMockBuilder('Mage_Backend_Model_Url') + ->disableOriginalConstructor() + ->getMock(); + + $helper = new Magento_Test_Helper_ObjectManager($this); + $this->_block = $helper->getBlock('Mage_Webapi_Block_Adminhtml_Role', array( + 'urlBuilder' => $this->_urlBuilder + )); + } + + /** + * Test _construct method + */ + public function testConstruct() + { + $this->assertAttributeEquals('Mage_Webapi', '_blockGroup', $this->_block); + $this->assertAttributeEquals('adminhtml_role', '_controller', $this->_block); + $this->assertAttributeEquals('API Roles', '_headerText', $this->_block); + $this->_assertBlockHasButton(0, 'add', 'Add New API Role'); + } + + /** + * Test getCreateUrl method + */ + public function testGetCreateUrl() + { + $expectedUrl = 'create_url'; + $this->_urlBuilder + ->expects($this->once()) + ->method('getUrl') + ->with('*/*/edit', array()) + ->will($this->returnValue($expectedUrl)); + + $this->assertEquals($expectedUrl, $this->_block->getCreateUrl()); + } + + /** + * Asserts that block has button with id and label at level + * + * @param int $level + * @param string $buttonId + * @param string $label + */ + protected function _assertBlockHasButton($level, $buttonId, $label) + { + $buttonsProperty = new ReflectionProperty($this->_block, '_buttons'); + $buttonsProperty->setAccessible(true); + $buttons = $buttonsProperty->getValue($this->_block); + $this->assertInternalType('array', $buttons, 'Cannot get bloc buttons'); + $this->assertArrayHasKey($level, $buttons, "Block doesn't have buttons at level $level"); + $this->assertArrayHasKey($buttonId, $buttons[$level], "Block doesn't have '$buttonId' button at level $level"); + $this->assertArrayHasKey('label', $buttons[$level][$buttonId], "Block button doesn't have label"); + $this->assertEquals($label, $buttons[$level][$buttonId]['label'], "Block button label has unexpected value"); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Block/Adminhtml/User/EditTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Block/Adminhtml/User/EditTest.php new file mode 100644 index 0000000000000000000000000000000000000000..e2b99af9bf803bd414e9b5337aaf13287baa21eb --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Block/Adminhtml/User/EditTest.php @@ -0,0 +1,133 @@ +<?php +/** + * Test class for Mage_Webapi_Block_Adminhtml_User_Edit + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Block_Adminhtml_User_EditTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Core_Controller_Request_Http|PHPUnit_Framework_MockObject_MockObject + */ + protected $_request; + + /** + * @var PHPUnit_Framework_MockObject_MockObject|Mage_Core_Model_Layout + */ + protected $_layout; + + /** + * @var Mage_Webapi_Block_Adminhtml_User_Edit + */ + protected $_block; + + protected function setUp() + { + $this->_layout = $this->getMockBuilder('Mage_Core_Model_Layout') + ->disableOriginalConstructor() + ->setMethods(array('helper', 'getChildBlock', 'getChildName')) + ->getMock(); + + $this->_request = $this->getMockBuilder('Mage_Core_Controller_Request_Http') + ->disableOriginalConstructor() + ->setMethods(array('getParam')) + ->getMock(); + + $this->_request->expects($this->any()) + ->method('getParam') + ->with('user_id') + ->will($this->returnValue(1)); + + $helper = new Magento_Test_Helper_ObjectManager($this); + $this->_block = $helper->getBlock('Mage_Webapi_Block_Adminhtml_User_Edit', array( + // TODO Remove injecting of 'urlBuilder' after MAGETWO-5038 complete + 'urlBuilder' => $this->getMockBuilder('Mage_Backend_Model_Url') + ->disableOriginalConstructor() + ->getMock(), + 'layout' => $this->_layout, + 'request' => $this->_request + )); + } + + /** + * Test _construct method + */ + public function testConstruct() + { + $this->assertAttributeEquals('Mage_Webapi', '_blockGroup', $this->_block); + $this->assertAttributeEquals('adminhtml_user', '_controller', $this->_block); + $this->assertAttributeEquals('user_id', '_objectId', $this->_block); + $this->_assertBlockHasButton(1, 'save', 'label', 'Save API User'); + $this->_assertBlockHasButton(1, 'save', 'id', 'save_button'); + $this->_assertBlockHasButton(0, 'delete', 'label', 'Delete API User'); + } + + /** + * Test getHeaderText method + */ + public function testGetHeaderText() + { + $apiUser = new Varien_Object(); + $this->_block->setApiUser($apiUser); + $this->assertEquals('New API User', $this->_block->getHeaderText()); + + $apiUser->setId(1)->setApiKey('test-api'); + + /** @var PHPUnit_Framework_MockObject_MockObject $coreHelper */ + $coreHelper = $this->getMockBuilder('Mage_Core_Helper_Data') + ->disableOriginalConstructor() + ->setMethods(array('escapeHtml')) + ->getMock(); + $coreHelper->expects($this->once()) + ->method('escapeHtml') + ->with($apiUser->getApiKey()) + ->will($this->returnArgument(0)); + $this->_layout->expects($this->once()) + ->method('helper') + ->with('Mage_Core_Helper_Data') + ->will($this->returnValue($coreHelper)); + + $this->assertEquals("Edit API User 'test-api'", $this->_block->getHeaderText()); + } + + /** + * Asserts that block has button with id and attribute at level + * + * @param int $level + * @param string $buttonId + * @param string $attributeName + * @param string $attributeValue + */ + protected function _assertBlockHasButton($level, $buttonId, $attributeName, $attributeValue) + { + $buttonsProperty = new ReflectionProperty($this->_block, '_buttons'); + $buttonsProperty->setAccessible(true); + $buttons = $buttonsProperty->getValue($this->_block); + $this->assertInternalType('array', $buttons, 'Cannot get bloc buttons'); + $this->assertArrayHasKey($level, $buttons, "Block doesn't have buttons at level $level"); + $this->assertArrayHasKey($buttonId, $buttons[$level], "Block doesn't have '$buttonId' button at level $level"); + $this->assertArrayHasKey($attributeName, $buttons[$level][$buttonId], + "Block button doesn't have attribute $attributeName"); + $this->assertEquals($attributeValue, $buttons[$level][$buttonId][$attributeName], + "Block button $attributeName' has unexpected value"); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Block/Adminhtml/UserTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Block/Adminhtml/UserTest.php new file mode 100644 index 0000000000000000000000000000000000000000..289aa278863a30176b78646e5a21e893beffd5b1 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Block/Adminhtml/UserTest.php @@ -0,0 +1,73 @@ +<?php +/** + * Test class for Mage_Webapi_Block_Adminhtml_User + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Block_Adminhtml_UserTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Webapi_Block_Adminhtml_User + */ + protected $_block; + + protected function setUp() + { + $helper = new Magento_Test_Helper_ObjectManager($this); + $this->_block = $helper->getBlock('Mage_Webapi_Block_Adminhtml_User', array( + // TODO Remove injecting of 'urlBuilder' after MAGETWO-5038 complete + 'urlBuilder' => $this->getMockBuilder('Mage_Backend_Model_Url') + ->disableOriginalConstructor() + ->getMock(), + )); + } + + /** + * Test _construct method + */ + public function testConstruct() + { + $this->assertAttributeEquals('Mage_Webapi', '_blockGroup', $this->_block); + $this->assertAttributeEquals('adminhtml_user', '_controller', $this->_block); + $this->assertAttributeEquals('API Users', '_headerText', $this->_block); + $this->_assertBlockHasButton(0, 'add', 'Add New API User'); + } + + /** + * Asserts that block has button with id and label at level + * + * @param int $level + * @param string $buttonId + * @param string $label + */ + protected function _assertBlockHasButton($level, $buttonId, $label) + { + $buttonsProperty = new ReflectionProperty($this->_block, '_buttons'); + $buttonsProperty->setAccessible(true); + $buttons = $buttonsProperty->getValue($this->_block); + $this->assertInternalType('array', $buttons, 'Cannot get bloc buttons'); + $this->assertArrayHasKey($level, $buttons, "Block doesn't have buttons at level $level"); + $this->assertArrayHasKey($buttonId, $buttons[$level], "Block doesn't have '$buttonId' button at level $level"); + $this->assertArrayHasKey('label', $buttons[$level][$buttonId], "Block button doesn't have label"); + $this->assertEquals($label, $buttons[$level][$buttonId]['label'], "Block button label has unexpected value"); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Controller/Action/FactoryTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Controller/Action/FactoryTest.php new file mode 100644 index 0000000000000000000000000000000000000000..290566e70d28c1f49e6443e76d43e4efa6a6be6e --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Controller/Action/FactoryTest.php @@ -0,0 +1,85 @@ +<?php +/** + * Test action controller factory class. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Controller_Action_FactoryTest extends PHPUnit_Framework_TestCase +{ + /** @var Mage_Webapi_Controller_Action_Factory */ + protected $_factory; + + /** @var Magento_ObjectManager */ + protected $_objectManagerMock; + + protected function setUp() + { + /** Init all dependencies for SUT. */ + $this->_objectManagerMock = $this->getMockBuilder('Magento_ObjectManager')->disableOriginalConstructor() + ->getMock(); + /** Init SUT. */ + $this->_factory = new Mage_Webapi_Controller_Action_Factory($this->_objectManagerMock); + parent::setUp(); + } + + protected function tearDown() + { + unset($this->_factory); + unset($this->_objectManagerMock); + parent::tearDown(); + } + + + /** + * Test create action controller method. + */ + public function testCreateActionController() + { + /** Create mock object of Mage_Webapi_Controller_ActionAbstract. */ + $actionController = $this->getMockBuilder('Mage_Webapi_Controller_ActionAbstract') + ->disableOriginalConstructor()->getMock(); + /** Create request object. */ + $request = new Mage_Webapi_Controller_Request('SOAP'); + $this->_objectManagerMock->expects($this->once())->method('create')->will( + $this->returnValue($actionController) + ); + $this->_factory->createActionController('Mage_Webapi_Controller_ActionAbstract', $request); + } + + /** + * Test action controller method with exception. + */ + public function testCreateActionControllerWithException() + { + /** Create object of class which is not instance of Mage_Webapi_Controller_ActionAbstract. */ + $wrongController = new Varien_Object(); + /** Create request object. */ + $request = new Mage_Webapi_Controller_Request('SOAP'); + /** Mock object manager create method to return wrong controller */ + $this->_objectManagerMock->expects($this->any())->method('create')->will($this->returnValue($wrongController)); + $this->setExpectedException( + 'InvalidArgumentException', + 'The specified class is not a valid API action controller.' + ); + $this->_factory->createActionController('ClassName', $request); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Controller/Dispatcher/ErrorProcessorTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Controller/Dispatcher/ErrorProcessorTest.php new file mode 100644 index 0000000000000000000000000000000000000000..bba5c31dc3e6934dbbfc9d690294eb77c4302688 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Controller/Dispatcher/ErrorProcessorTest.php @@ -0,0 +1,252 @@ +<?php +/** + * Test Webapi Error Processor. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Controller_Dispatcher_ErrorProcessorTest extends PHPUnit_Framework_TestCase +{ + /** @var Mage_Webapi_Controller_Dispatcher_ErrorProcessor */ + protected $_errorProcessor; + + /** @var Mage_Webapi_Helper_Data */ + protected $_helperMock; + + /** @var Mage_Core_Model_App */ + protected $_appMock; + + /** @var Mage_Core_Model_Logger */ + protected $_loggerMock; + + protected function setUp() + { + /** Set up mocks for SUT. */ + $this->_helperMock = $this->getMockBuilder('Mage_Core_Helper_Data')->getMock(); + $this->_helperMock->expects($this->any())->method('__')->will($this->returnArgument(0)); + $helperFactoryMock = $this->getMockBuilder('Mage_Core_Model_Factory_Helper')->getMock(); + $helperFactoryMock->expects($this->any())->method('get')->will($this->returnValue($this->_helperMock)); + $this->_appMock = $this->getMockBuilder('Mage_Core_Model_App')->disableOriginalConstructor()->getMock(); + $this->_loggerMock = $this->getMockBuilder('Mage_Core_Model_Logger')->disableOriginalConstructor()->getMock(); + /** Initialize SUT. */ + $this->_errorProcessor = new Mage_Webapi_Controller_Dispatcher_ErrorProcessor( + $helperFactoryMock, + $this->_appMock, + $this->_loggerMock + ); + parent::setUp(); + } + + protected function tearDown() + { + unset($this->_errorProcessor); + unset($this->_helperMock); + unset($this->_appMock); + parent::tearDown(); + } + + /** + * Test render method in Json format. + */ + public function testRenderJson() + { + $_SERVER['HTTP_ACCEPT'] = 'json'; + /** Assert jsonEncode method will be executed once. */ + $this->_helperMock->expects($this->once())->method('jsonEncode')->will( + $this->returnCallback(array($this, 'callbackJsonEncode'), $this->returnArgument(0)) + ); + /** Init output buffering to catch output via echo function. */ + ob_start(); + $this->_errorProcessor->render('Message'); + /** Get output buffer. */ + $actualResult = ob_get_contents(); + ob_end_clean(); + $expectedResult = '{"messages":{"error":[{"code":500,"message":"Message"}]}}'; + $this->assertEquals($expectedResult, $actualResult, 'Wrong rendering in Json.'); + } + + /** + * Callback function for RenderJson and RenderJsonInDeveloperMode tests. + * + * Method encode data to Json and return it. + * + * @param $data + * @return string + */ + public function callbackJsonEncode($data) + { + return json_encode($data); + } + + /** + * Test render method in Json format with turned on developer mode. + */ + public function testRenderJsonInDeveloperMode() + { + $_SERVER['HTTP_ACCEPT'] = 'json'; + /** Mock app to return enabled developer mode flag. */ + $this->_appMock->expects($this->any())->method('isDeveloperMode')->will($this->returnValue(true)); + /** Assert jsonEncode method will be executed once. */ + $this->_helperMock->expects($this->once())->method('jsonEncode')->will( + $this->returnCallback(array($this, 'callbackJsonEncode'), $this->returnArgument(0)) + ); + ob_start(); + $this->_errorProcessor->render('Message', 'Message trace.', 401); + $actualResult = ob_get_contents(); + ob_end_clean(); + $expectedResult = '{"messages":{"error":[{"code":401,"message":"Message","trace":"Message trace."}]}}'; + $this->assertEquals($expectedResult, $actualResult, 'Wrong rendering in Json.'); + } + + /** + * Test render method in XML format. + */ + public function testRenderXml() + { + $_SERVER['HTTP_ACCEPT'] = 'xml'; + /** Init output buffering to catch output via echo function. */ + ob_start(); + $this->_errorProcessor->render('Message'); + /** Get output buffer. */ + $actualResult = ob_get_contents(); + ob_end_clean(); + $expectedResult = '<?xml version="1.0"?><error><messages><error><data_item><code>500</code>' + . '<message>Message</message></data_item></error></messages></error>'; + $this->assertEquals($expectedResult, $actualResult, 'Wrong rendering in XML.'); + } + + /** + * Test render method in XML format with turned on developer mode. + */ + public function testRenderXmlInDeveloperMode() + { + $_SERVER['HTTP_ACCEPT'] = 'xml'; + /** Mock app to return enabled developer mode flag. */ + $this->_appMock->expects($this->any())->method('isDeveloperMode')->will($this->returnValue(true)); + /** Init output buffering to catch output via echo function. */ + ob_start(); + $this->_errorProcessor->render('Message', 'Trace message.', 401); + /** Get output buffer. */ + $actualResult = ob_get_contents(); + ob_end_clean(); + $expectedResult = '<?xml version="1.0"?><error><messages><error><data_item><code>401</code><message>' + . 'Message</message><trace><![CDATA[Trace message.]]></trace></data_item></error></messages></error>'; + $this->assertEquals($expectedResult, $actualResult, 'Wrong rendering in XML with turned on developer mode.'); + } + + /** + * Test default render format is Json. + */ + public function testRenderDefaultFormat() + { + /** Set undefined rendering format. */ + $_SERVER['HTTP_ACCEPT'] = 'undefined'; + /** Assert jsonEncode method will be executed at least once. */ + $this->_helperMock->expects($this->atLeastOnce())->method('jsonEncode'); + $this->_errorProcessor->render('Message'); + } + + /** + * Test renderException method with Mage_Webapi_Exception. + */ + public function testRenderExecutionWebapiException() + { + $this->markTestIncomplete("Think how to replace this test."); + $_SERVER['HTTP_ACCEPT'] = 'json'; + /** Init Mage_Webapi_Exception. */ + $apiException = new Mage_Webapi_Exception('Exception message', 500); + /** Assert jsonEncode will be executed once. */ + $this->_helperMock->expects($this->once())->method('jsonEncode'); + $this->_errorProcessor->renderException($apiException); + } + + /** + * Test renderException method with turned on Developer mode. + */ + public function testRenderExecutionInDeveloperMode() + { + $this->markTestIncomplete("Think how to replace this test."); + $_SERVER['HTTP_ACCEPT'] = 'json'; + /** Init base Exception object. */ + $exception = new Exception('Message'); + /** Mock app to return enabled developer mode flag. */ + $this->_appMock->expects($this->any())->method('isDeveloperMode')->will($this->returnValue(true)); + /** Assert jsonEncode will be executed once. */ + $this->_helperMock->expects($this->once())->method('jsonEncode'); + $this->_errorProcessor->renderException($exception); + } + + /** + * Test maskException method with Mage_Webapi_Exception. + */ + public function testMaskWebapiException() + { + /** Init mage_webapi_Exception. */ + $apiException = new Mage_Webapi_Exception('Message', 400); + /** Asser Webapi exception was not masked. */ + $this->assertEquals( + $this->_errorProcessor->maskException($apiException), + $apiException, + 'Webapi Exception was masked wrong.' + ); + } + + /** + * Test maskException method with turned on developer mode. + */ + public function testMaskExceptionInDeveloperMode() + { + /** Mock app isDeveloperMode to return true. */ + $this->_appMock->expects($this->once())->method('isDeveloperMode')->will($this->returnValue(true)); + /** Init Logical exception. */ + $logicalException = new LogicException(); + /** Asser Webapi exception was not masked. */ + $this->assertEquals( + $this->_errorProcessor->maskException($logicalException), + $logicalException, + 'Exception was masked wrong in developer mode.' + ); + } + + /** + * Test maskException method with turned on developer mode. + */ + public function testMaskNonWebapiException() + { + /** Assert exception was logged. */ + $this->_loggerMock->expects($this->once())->method('logException'); + $maskedException = $this->_errorProcessor->maskException(new LogicException()); + /** Assert masked exception type is Mage_Webapi_Exception. */ + $this->assertInstanceOf('Mage_Webapi_Exception', $maskedException, 'Masked exception type is not Webapi.'); + /** Asser masked exception code is 500. */ + $this->assertEquals( + Mage_Webapi_Exception::HTTP_INTERNAL_ERROR, + $maskedException->getCode(), + 'Masked exception code is wrong.' + ); + /** Assert masked exception message. */ + $this->assertEquals( + 'Internal Error. Details are available in Magento log file. Report ID: "%s"', + $maskedException->getMessage(), + 'Masked exception message is wrong.' + ); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Controller/Dispatcher/FactoryTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Controller/Dispatcher/FactoryTest.php new file mode 100644 index 0000000000000000000000000000000000000000..8b29f16be2e47146cdb362e9a0d2a3880dc7c5a3 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Controller/Dispatcher/FactoryTest.php @@ -0,0 +1,72 @@ +<?php +/** + * Test Mage_Webapi_Controller_Dispatcher_Factory. + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Controller_Dispatcher_FactoryTest extends PHPUnit_Framework_TestCase +{ + /** @var PHPUnit_Framework_MockObject_MockObject */ + protected $_objectManager; + + /** @var Mage_Webapi_Controller_Dispatcher_Factory */ + protected $_dispatcherFactory; + + protected function setUp() + { + /** Prepare mocks for SUT constructor. */ + $this->_objectManager = $this->getMockBuilder('Magento_ObjectManager') + ->setMethods(array('get')) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + /** Initialize SUT. */ + $this->_dispatcherFactory = new Mage_Webapi_Controller_Dispatcher_Factory($this->_objectManager); + parent::setUp(); + } + + protected function tearDown() + { + unset($this->_objectManager); + unset($this->_dispatcherFactory); + parent::tearDown(); + } + + public function testGetLogicExceptionInvalidApiType() + { + $this->setExpectedException( + 'LogicException', + 'There is no corresponding dispatcher class for the "invalidApiType" API type.' + ); + $this->_dispatcherFactory->get('invalidApiType'); + } + + public function testGet() + { + $expectedController = $this->getMockBuilder('Mage_Webapi_Controller_Dispatcher_Soap') + ->disableOriginalConstructor() + ->getMock(); + $this->_objectManager->expects($this->once())->method('get')->will($this->returnValue($expectedController)); + $this->assertEquals( + $expectedController, + $this->_dispatcherFactory->get(Mage_Webapi_Controller_Front::API_TYPE_SOAP) + ); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Controller/Dispatcher/Rest/AuthenticationTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Controller/Dispatcher/Rest/AuthenticationTest.php new file mode 100644 index 0000000000000000000000000000000000000000..4a6cabc98266b56a6488b777d422a011a4a0b5fc --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Controller/Dispatcher/Rest/AuthenticationTest.php @@ -0,0 +1,103 @@ +<?php +/** + * REST web API authentication test. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Controller_Dispatcher_Rest_AuthenticationTest extends PHPUnit_Framework_TestCase +{ + /** @var PHPUnit_Framework_MockObject_MockObject */ + protected $_roleLocatorMock; + + /** @var PHPUnit_Framework_MockObject_MockObject */ + protected $_oauthServerMock; + + /** @var Mage_Webapi_Controller_Dispatcher_Rest_Authentication */ + protected $_restAuthentication; + + protected function setUp() + { + /** Prepare mocks for SUT constructor. */ + $this->_oauthServerMock = $this->getMockBuilder('Mage_Webapi_Model_Rest_Oauth_Server') + ->setMethods(array('authenticateTwoLegged', 'reportProblem')) + ->disableOriginalConstructor() + ->getMock(); + $this->_roleLocatorMock = $this->getMockBuilder('Mage_Webapi_Model_Authorization_RoleLocator') + ->setMethods(array('setRoleId')) + ->disableOriginalConstructor() + ->getMock(); + /** Initialize SUT. */ + $this->_restAuthentication = new Mage_Webapi_Controller_Dispatcher_Rest_Authentication( + $this->_oauthServerMock, + $this->_roleLocatorMock + ); + parent::setUp(); + } + + protected function tearDown() + { + unset($this->_oauthServerMock); + unset($this->_restAuthentication); + unset($this->_roleLocatorMock); + parent::tearDown(); + } + + public function testAuthenticate() + { + /** Prepare mocks for SUT constructor. */ + $consumerMock = $this->getMockBuilder('Mage_Webapi_Model_Acl_User') + ->disableOriginalConstructor() + ->setMethods(array('getRoleId')) + ->getMock(); + $roleId = 1; + $consumerMock->expects($this->once())->method('getRoleId')->will($this->returnValue($roleId)); + $this->_roleLocatorMock->expects($this->once())->method('setRoleId')->with($roleId); + $this->_oauthServerMock + ->expects($this->once()) + ->method('authenticateTwoLegged') + ->will($this->returnValue($consumerMock)); + /** Execute SUT. */ + $this->_restAuthentication->authenticate(); + } + + public function testAuthenticateMageWebapiException() + { + /** Prepare mocks for SUT constructor. */ + $this->_oauthServerMock + ->expects($this->once()) + ->method('authenticateTwoLegged') + ->will($this->throwException( + Mage::exception('Mage_Oauth', 'Exception message.', Mage_Oauth_Model_Server::HTTP_BAD_REQUEST) + )); + $this->setExpectedException( + 'Mage_Webapi_Exception', + 'Exception message.', + Mage_Webapi_Exception::HTTP_UNAUTHORIZED + ); + $this->_oauthServerMock + ->expects($this->once()) + ->method('reportProblem') + ->will($this->returnValue('Exception message.')); + /** Execute SUT. */ + $this->_restAuthentication->authenticate(); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Controller/Dispatcher/RestTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Controller/Dispatcher/RestTest.php new file mode 100644 index 0000000000000000000000000000000000000000..cf060746d20b0fdf09159ed8cdc50d470193a25d --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Controller/Dispatcher/RestTest.php @@ -0,0 +1,152 @@ +<?php +/** + * Test Rest controller dispatcher. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Controller_Dispatcher_RestTest extends PHPUnit_Framework_TestCase +{ + /** @var Mage_Webapi_Controller_Dispatcher_Rest */ + protected $_restDispatcher; + + /** @var Mage_Webapi_Controller_Dispatcher_Rest_Authentication */ + protected $_authenticationMock; + + /** @var Mage_Webapi_Controller_Response_Rest */ + protected $_responseMock; + + /** @var Mage_Webapi_Controller_Router_Rest */ + protected $_routerMock; + + /** @var Mage_Webapi_Controller_Action_Factory */ + protected $_controllerFactory; + + /** @var Mage_Webapi_Model_Config_Rest */ + protected $_apiConfigMock; + + /** @var Mage_Webapi_Model_Authorization */ + protected $_authorizationMock; + + /** @var Mage_Webapi_Controller_Dispatcher_Rest_Presentation */ + protected $_restPresentation; + + protected function setUp() + { + /** Init dependencies for SUT. */ + $this->_apiConfigMock = $this->getMockBuilder('Mage_Webapi_Model_Config_Rest')->disableOriginalConstructor() + ->getMock(); + $requestMock = $this->getMockBuilder('Mage_Webapi_Controller_Request_Rest')->disableOriginalConstructor() + ->getMock(); + $this->_responseMock = $this->getMockBuilder('Mage_Webapi_Controller_Response_Rest') + ->disableOriginalConstructor()->getMock(); + $this->_controllerFactory = $this->getMockBuilder('Mage_Webapi_Controller_Action_Factory') + ->disableOriginalConstructor()->getMock(); + $this->_restPresentation = $this->getMockBuilder('Mage_Webapi_Controller_Dispatcher_Rest_Presentation') + ->disableOriginalConstructor()->getMock(); + $this->_routerMock = $this->getMockBuilder('Mage_Webapi_Controller_Router_Rest')->disableOriginalConstructor() + ->getMock(); + $this->_authorizationMock = $this->getMockBuilder('Mage_Webapi_Model_Authorization') + ->disableOriginalConstructor()->getMock(); + $this->_authenticationMock = $this->getMockBuilder('Mage_Webapi_Controller_Dispatcher_Rest_Authentication') + ->disableOriginalConstructor()->getMock(); + + /** Init SUT. */ + $this->_restDispatcher = new Mage_Webapi_Controller_Dispatcher_Rest( + $this->_apiConfigMock, + $requestMock, + $this->_responseMock, + $this->_controllerFactory, + $this->_restPresentation, + $this->_routerMock, + $this->_authorizationMock, + $this->_authenticationMock + ); + parent::setUp(); + } + + protected function tearDown() + { + unset($this->_restDispatcher); + unset($this->_authenticationMock); + unset($this->_responseMock); + unset($this->_routerMock); + unset($this->_controllerFactory); + unset($this->_apiConfigMock); + unset($this->_authorizationMock); + unset($this->_restPresentation); + parent::tearDown(); + } + + /** + * Test dispatch method with Exception throwing. + */ + public function testDispatchException() + { + /** Init logical Exception. */ + $logicalException = new LogicException(); + /** Mock authenticate method to throw Exception. */ + $this->_authenticationMock->expects($this->once())->method('authenticate')->will( + $this->throwException($logicalException) + ); + /** Assert setException method will be executed with thrown logical Exception. */ + $this->_responseMock->expects($this->once())->method('setException')->with($this->equalTo($logicalException)); + + $this->_restDispatcher->dispatch(); + } + + /** + * Test dispatch method. + */ + public function testDispatch() + { + $this->_authenticationMock->expects($this->once())->method('authenticate'); + /** Init route mock. */ + $routeMock = $this->getMockBuilder('Mage_Webapi_Controller_Router_Route_Rest')->disableOriginalConstructor() + ->getMock(); + $routeMock->expects($this->any())->method('getResourceName'); + $this->_routerMock->expects($this->once())->method('match')->will($this->returnValue($routeMock)); + /** Mock Api Config getMethodNameByOperation method to return isDeleted method of Varien_Onject. */ + $this->_apiConfigMock->expects($this->once())->method('getMethodNameByOperation')->will( + $this->returnValue('isDeleted') + ); + /** Mock Api config identifyVersionSuffix method to return empty string. */ + $this->_apiConfigMock->expects($this->once())->method('identifyVersionSuffix')->will($this->returnValue('')); + $this->_apiConfigMock->expects($this->once())->method('checkDeprecationPolicy'); + $this->_authorizationMock->expects($this->once())->method('checkResourceAcl'); + /** Create fake controller mock, e. g. Varien_Object object. */ + $controllerMock = $this->getMockBuilder('Varien_Object')->disableOriginalConstructor()->getMock(); + /** Assert isDeleted method will be executed once. */ + $controllerMock->expects($this->once())->method('isDeleted'); + /** Mock factory mock to return fake action controller. */ + $this->_controllerFactory->expects($this->once())->method('createActionController')->will( + $this->returnValue($controllerMock) + ); + /** Mock Rest presentation fetchRequestData method to return empty array. */ + $this->_restPresentation->expects($this->once())->method('fetchRequestData')->will( + $this->returnValue(array()) + ); + /** Assert response sendResponse method will be executed once. */ + $this->_responseMock->expects($this->once())->method('sendResponse'); + + $this->_restDispatcher->dispatch(); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Controller/Dispatcher/Soap/AuthenticationTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Controller/Dispatcher/Soap/AuthenticationTest.php new file mode 100644 index 0000000000000000000000000000000000000000..febb1eb807f1a68dcf3a6e1b45db59d8d0cf0e0c --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Controller/Dispatcher/Soap/AuthenticationTest.php @@ -0,0 +1,161 @@ +<?php +/** + * SOAP web API authentication model. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Controller_Dispatcher_Soap_AuthenticationTest extends PHPUnit_Framework_TestCase +{ + /** @var PHPUnit_Framework_MockObject_MockObject */ + protected $_helperMock; + + /** @var PHPUnit_Framework_MockObject_MockObject */ + protected $_tokenFactoryMock; + + /** @var PHPUnit_Framework_MockObject_MockObject */ + protected $_roleLocatorMock; + + /** @var Mage_Webapi_Controller_Dispatcher_Soap_Authentication */ + protected $_soapAuthentication; + + /** @var stdClass */ + protected $_usernameToken; + + /** @var PHPUnit_Framework_MockObject_MockObject */ + protected $_tokenMock; + + protected function setUp() + { + $this->_usernameToken = new stdClass(); + /** Prepare mocks for SUT constructor. */ + $this->_usernameToken->Username = 'userName'; + $this->_usernameToken->Password = 'password'; + $this->_usernameToken->Created = '2012-12-12'; + $this->_usernameToken->Nonce = 'Nonce'; + + $this->_helperMock = $this->getMockBuilder('Mage_Webapi_Helper_Data') + ->setMethods(array('__')) + ->disableOriginalConstructor() + ->getMock(); + $this->_helperMock->expects($this->any())->method('__')->will($this->returnArgument(0)); + $this->_tokenFactoryMock = $this->getMockBuilder('Mage_Webapi_Model_Soap_Security_UsernameToken_Factory') + ->setMethods(array('createFromArray')) + ->disableOriginalConstructor() + ->getMock(); + $this->_tokenMock = $this->getMockBuilder('Mage_Webapi_Model_Soap_Security_UsernameToken') + ->disableOriginalConstructor() + ->setMethods(array('authenticate')) + ->getMock(); + $this->_tokenFactoryMock + ->expects($this->once()) + ->method('createFromArray') + ->will($this->returnValue($this->_tokenMock)); + $this->_roleLocatorMock = $this->getMockBuilder('Mage_Webapi_Model_Authorization_RoleLocator') + ->setMethods(array('setRoleId')) + ->disableOriginalConstructor() + ->getMock(); + /** Initialize SUT. */ + $this->_soapAuthentication = new Mage_Webapi_Controller_Dispatcher_Soap_Authentication( + $this->_helperMock, + $this->_tokenFactoryMock, + $this->_roleLocatorMock + ); + parent::setUp(); + } + + public function testAuthenticate() + { + /** Prepare mocks for SUT constructor. */ + $user = $this->getMockBuilder('Mage_Webapi_Model_Acl_User') + ->disableOriginalConstructor() + ->setMethods(array('getRoleId')) + ->getMock(); + $roleId = 1; + $user->expects($this->once())->method('getRoleId')->will($this->returnValue($roleId)); + $this->_tokenMock->expects($this->once()) + ->method('authenticate') + ->with( + $this->_usernameToken->Username, + $this->_usernameToken->Password, + $this->_usernameToken->Created, + $this->_usernameToken->Nonce + )->will($this->returnValue($user)); + $this->_tokenFactoryMock + ->expects($this->once()) + ->method('createFromArray') + ->will($this->returnValue($this->_tokenMock)); + $this->_roleLocatorMock->expects($this->once())->method('setRoleId')->with($roleId); + /** Execute SUT. */ + $this->_soapAuthentication->authenticate($this->_usernameToken); + } + + /** + * @dataProvider authenticateExceptionProvider + */ + public function testAuthenticateWithException($exception, $exceptionMessage) + { + /** Prepare mocks for SUT constructor. */ + $this->_tokenMock + ->expects($this->once()) + ->method('authenticate') + ->with( + $this->_usernameToken->Username, + $this->_usernameToken->Password, + $this->_usernameToken->Created, + $this->_usernameToken->Nonce + )->will($this->throwException($exception)); + $this->setExpectedException( + 'Mage_Webapi_Exception', + $exceptionMessage, + Mage_Webapi_Exception::HTTP_BAD_REQUEST + ); + /** Execute SUT. */ + $this->_soapAuthentication->authenticate($this->_usernameToken); + } + + /** + * Exception data provider for authenticate() method + * + * @return array + */ + public function authenticateExceptionProvider() + { + return array( + 'testAuthenticateUsernameTokenInvalidCredentialException.' => array( + new Mage_Webapi_Model_Soap_Security_UsernameToken_InvalidCredentialException(), + 'Invalid Username or Password.', + ), + 'testAuthenticateUsernameTokenNonceUsedException.' => array( + new Mage_Webapi_Model_Soap_Security_UsernameToken_NonceUsedException(), + 'WS-Security UsernameToken Nonce is already used.', + ), + 'testAuthenticateUsernameTokenTimestampRefusedException.' => array( + new Mage_Webapi_Model_Soap_Security_UsernameToken_TimestampRefusedException(), + 'WS-Security UsernameToken Created timestamp is refused.', + ), + 'testAuthenticateUsernameTokenInvalidDateException.' => array( + new Mage_Webapi_Model_Soap_Security_UsernameToken_InvalidDateException(), + 'Invalid UsernameToken Created date.', + ), + ); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Controller/Dispatcher/Soap/HandlerTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Controller/Dispatcher/Soap/HandlerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..c1e378d9af25953a01af59b59c672c2aeb4b8dbc --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Controller/Dispatcher/Soap/HandlerTest.php @@ -0,0 +1,302 @@ +<?php +/** + * Test for Mage_Webapi_Controller_Dispatcher_Soap_Handler. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Controller_Dispatcher_Soap_HandlerTest extends PHPUnit_Framework_TestCase +{ + /** @var Mage_Webapi_Controller_Dispatcher_Soap_Handler */ + protected $_handler; + + /** @var PHPUnit_Framework_MockObject_MockObject */ + protected $_apiConfigMock; + + /** @var PHPUnit_Framework_MockObject_MockObject */ + protected $_helperMock; + + /** @var PHPUnit_Framework_MockObject_MockObject */ + protected $_authenticationMock; + + /** @var PHPUnit_Framework_MockObject_MockObject */ + protected $_factoryMock; + + /** @var PHPUnit_Framework_MockObject_MockObject */ + protected $_authorizationMock; + + /** @var PHPUnit_Framework_MockObject_MockObject */ + protected $_requestMock; + + /** @var PHPUnit_Framework_MockObject_MockObject */ + protected $_errorProcessorMock; + + /** @var array */ + protected $_arguments; + + protected function setUp() + { + /** Prepare mocks for SUT constructor. */ + $this->_apiConfigMock = $this->getMockBuilder('Mage_Webapi_Model_Config_Soap') + ->setMethods( + array( + 'getResourceNameByOperation', + 'validateVersionNumber', + 'getControllerClassByOperationName', + 'getMethodNameByOperation', + 'identifyVersionSuffix', + 'checkDeprecationPolicy' + ) + )->disableOriginalConstructor() + ->getMock(); + $this->_helperMock = $this->getMockBuilder('Mage_Webapi_Helper_Data') + ->setMethods(array('__', 'prepareMethodParams')) + ->disableOriginalConstructor() + ->getMock(); + $this->_authenticationMock = $this->getMockBuilder('Mage_Webapi_Controller_Dispatcher_Soap_Authentication') + ->setMethods(array('authenticate')) + ->disableOriginalConstructor() + ->getMock(); + $this->_factoryMock = $this->getMockBuilder('Mage_Webapi_Controller_Action_Factory') + ->setMethods(array('createActionController')) + ->disableOriginalConstructor() + ->getMock(); + $this->_authorizationMock = $this->getMockBuilder('Mage_Webapi_Model_Authorization') + ->setMethods(array('checkResourceAcl')) + ->disableOriginalConstructor() + ->getMock(); + $this->_requestMock = $this->getMockBuilder('Mage_Webapi_Controller_Request_Soap') + ->setMethods(array('getRequestedResources')) + ->disableOriginalConstructor() + ->getMock(); + $this->_errorProcessorMock = $this->getMockBuilder('Mage_Webapi_Controller_Dispatcher_ErrorProcessor') + ->setMethods(array('maskException')) + ->disableOriginalConstructor() + ->getMock(); + /** Initialize SUT. */ + $this->_handler = new Mage_Webapi_Controller_Dispatcher_Soap_Handler( + $this->_apiConfigMock, + $this->_helperMock, + $this->_authenticationMock, + $this->_factoryMock, + $this->_authorizationMock, + $this->_requestMock, + $this->_errorProcessorMock + ); + parent::setUp(); + } + + protected function tearDown() + { + unset($this->_handler); + unset($this->_apiConfigMock); + unset($this->_helperMock); + unset($this->_authenticationMock); + unset($this->_factoryMock); + unset($this->_authorizationMock); + unset($this->_requestMock); + unset($this->_errorProcessorMock); + parent::tearDown(); + } + + public function testCallEmptyUsernameTokenException() + { + /** Prepare mocks for SUT constructor. */ + $this->_handler->setRequestHeaders(array('invalidHeader')); + $this->_helperMock->expects($this->once())->method('__')->will($this->returnArgument(0)); + $this->setExpectedException( + 'Mage_Webapi_Model_Soap_Fault', + 'WS-Security UsernameToken is not found in SOAP-request.' + ); + /** Execute SUT. */ + $this->_handler->__call('operation', array()); + } + + /** + * This test is checking any other exceptions but Mage_Webapi_Exception handling during __call(). + */ + public function testCallException() + { + /** Prepare mocks for SUT constructor. */ + $exceptionMessage = 'Exception message.'; + $this->setExpectedException( + 'Mage_Webapi_Model_Soap_Fault', + $exceptionMessage + ); + $exception = new Exception($exceptionMessage); + $this->_errorProcessorMock->expects($this->once()) + ->method('maskException') + ->with($exception) + ->will($this->returnValue($exception)); + /** Model situation: authenticate() method throw Exception(). */ + $this->_authenticationMock->expects($this->once()) + ->method('authenticate') + ->will($this->throwException($exception)); + /** Execute SUT. */ + $this->_prepareSoapRequest(); + $this->_handler->__call('operation', $this->_arguments); + } + + public function testCallMethodNotFoundException() + { + /** Prepare mock for authenticate(). */ + $this->_authenticationMock->expects($this->once())->method('authenticate'); + /** Prepare mock for _getOperationVersion() method. */ + $this->_requestMock->expects($this->once()) + ->method('getRequestedResources') + ->will($this->returnValue(array('resourceName' => 'v1'))); + /** Create the arguments map of returned values for getResourceNameByOperation() method. */ + $getResourceValueMap = array( + array('operation', null, 'resourceName'), + array('operation', 'v1', false) + ); + $this->_apiConfigMock->expects($this->any()) + ->method('getResourceNameByOperation') + ->will($this->returnValueMap($getResourceValueMap)); + $this->_apiConfigMock->expects($this->once()) + ->method('validateVersionNumber') + ->with(1, 'resourceName'); + $this->_helperMock->expects($this->once()) + ->method('__') + ->with('Method "%s" is not found.', 'operation') + ->will($this->returnValue('Method "operation" is not found.')); + $this->setExpectedException( + 'Mage_Webapi_Model_Soap_Fault', + 'Method "operation" is not found.' + ); + /** Execute SUT. */ + $this->_prepareSoapRequest(); + $this->_handler->__call('operation', $this->_arguments); + } + + public function testCallInvalidOperationVersionException() + { + $this->_authenticationMock->expects($this->once())->method('authenticate'); + /** Prepare mock for _getOperationVersion() method. */ + $this->_requestMock->expects($this->once()) + ->method('getRequestedResources') + ->will($this->returnValue(array('resourceName' => 'v1'))); + $this->_apiConfigMock->expects($this->once()) + ->method('getResourceNameByOperation') + ->will($this->returnValue(false)); + $this->_helperMock->expects($this->once()) + ->method('__') + ->with('The version of "%s" operation cannot be identified.', 'operationName') + ->will($this->returnValue('The version of "operationName" operation cannot be identified.')); + $this->setExpectedException( + 'Mage_Webapi_Model_Soap_Fault', + 'The version of "operationName" operation cannot be identified.' + ); + /** Execute SUT. */ + $this->_prepareSoapRequest(); + $this->_handler->__call('operationName', $this->_arguments); + } + + public function testCall() + { + /** Prepare mock for SUT. */ + $this->_prepareSoapRequest(); + $method = 'Get'; + $resource = 'resourceName'; + $operation = $resource . $method; + $this->_authenticationMock->expects($this->once())->method('authenticate'); + $this->_requestMock->expects($this->once()) + ->method('getRequestedResources') + ->will($this->returnValue(array($resource => 'v1'))); + $this->_apiConfigMock->expects($this->any()) + ->method('getResourceNameByOperation') + ->will($this->returnValue($resource)); + $this->_apiConfigMock->expects($this->once()) + ->method('validateVersionNumber') + ->with(1, $resource); + $versionAfterFallback = 'V1'; + $action = $method . $versionAfterFallback; + $this->_apiConfigMock->expects($this->once()) + ->method('getControllerClassByOperationName') + ->with($operation) + ->will($this->returnValue('Vendor_Module_Controller_Webapi_Resource')); + $controllerMock = $this->getMockBuilder('Vendor_Module_Controller_Webapi_Resource') + ->disableOriginalConstructor() + ->setMethods(array($action)) + ->getMock(); + $this->_factoryMock->expects($this->once()) + ->method('createActionController') + ->with('Vendor_Module_Controller_Webapi_Resource', $this->_requestMock) + ->will($this->returnValue($controllerMock)); + $this->_apiConfigMock->expects($this->once()) + ->method('getMethodNameByOperation') + ->with($operation, '1') + ->will($this->returnValue($method)); + $this->_authorizationMock->expects($this->once()) + ->method('checkResourceAcl') + ->with($resource, $method); + $this->_apiConfigMock->expects($this->once()) + ->method('identifyVersionSuffix') + ->with($operation, '1', $controllerMock) + ->will($this->returnValue($versionAfterFallback)); + $this->_apiConfigMock->expects($this->once()) + ->method('checkDeprecationPolicy') + ->with($resource, $method, $versionAfterFallback); + $arguments = reset($this->_arguments); + $arguments = get_object_vars($arguments); + $this->_helperMock->expects($this->once()) + ->method('prepareMethodParams') + ->with('Vendor_Module_Controller_Webapi_Resource', $action, $arguments, $this->_apiConfigMock) + ->will($this->returnValue($arguments)); + $expectedResult = array('foo' => 'bar'); + $controllerMock->expects($this->once()) + ->method($action) + ->with($arguments['customerId']) + ->will($this->returnValue($expectedResult)); + + /** Execute SUT. */ + $this->assertEquals( + (object)array(Mage_Webapi_Controller_Dispatcher_Soap_Handler::RESULT_NODE_NAME => $expectedResult), + $this->_handler->__call($operation, $this->_arguments) + ); + } + + /** + * Process security header and prepare request arguments. + */ + protected function _prepareSoapRequest() + { + /** Process security header by __call() method. */ + $this->_handler->setRequestHeaders(array(Mage_Webapi_Controller_Dispatcher_Soap_Handler::HEADER_SECURITY)); + $usernameToken = new stdClass(); + // @codingStandardsIgnoreStart + $usernameToken->UsernameToken = new stdClass(); + $usernameToken->UsernameToken->Username = 'username'; + $usernameToken->UsernameToken->Password = 'password'; + $usernameToken->UsernameToken->Nonce = 'nonce'; + $usernameToken->UsernameToken->Created = 'created'; + // @codingStandardsIgnoreEnd + $this->_handler->__call( + Mage_Webapi_Controller_Dispatcher_Soap_Handler::HEADER_SECURITY, + array($usernameToken) + ); + + /** Override arguments for process action header. */ + $request = new stdClass(); + $request->customerId = 1; + $this->_arguments = array($request); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Controller/Dispatcher/SoapTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Controller/Dispatcher/SoapTest.php new file mode 100644 index 0000000000000000000000000000000000000000..c21fc69cb4d87224333199ea5539ed2a99c0f0dc --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Controller/Dispatcher/SoapTest.php @@ -0,0 +1,277 @@ +<?php +/** + * Test SOAP dispatcher class. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Controller_Dispatcher_SoapTest extends PHPUnit_Framework_TestCase +{ + /** @var Mage_Webapi_Controller_Dispatcher_Soap */ + protected $_dispatcher; + + /** @var PHPUnit_Framework_MockObject_MockObject */ + protected $_apiConfigMock; + + /** @var PHPUnit_Framework_MockObject_MockObject */ + protected $_soapServerMock; + + /** @var PHPUnit_Framework_MockObject_MockObject */ + protected $_autoDiscoverMock; + + /** @var PHPUnit_Framework_MockObject_MockObject */ + protected $_requestMock; + + /** @var PHPUnit_Framework_MockObject_MockObject */ + protected $_soapFaultMock; + + /** @var PHPUnit_Framework_MockObject_MockObject */ + protected $_responseMock; + + /** @var PHPUnit_Framework_MockObject_MockObject */ + protected $_errorProcessorMock; + + /** + * Set up dispatcher object. + */ + protected function setUp() + { + parent::setUp(); + + $this->_apiConfigMock = $this->getMockBuilder('Mage_Webapi_Model_Config_Soap') + ->disableOriginalConstructor() + ->setMethods(array('getAllResourcesVersions')) + ->getMock(); + $this->_soapServerMock = $this->getMockBuilder('Mage_Webapi_Model_Soap_Server') + ->disableOriginalConstructor() + ->getMock(); + $this->_soapServerMock->expects($this->any())->method('setWSDL')->will($this->returnSelf()); + $this->_soapServerMock->expects($this->any())->method('setEncoding')->will($this->returnSelf()); + $this->_soapServerMock->expects($this->any())->method('setSoapVersion')->will($this->returnSelf()); + $this->_soapServerMock->expects($this->any())->method('setClassmap')->will($this->returnSelf()); + $this->_soapServerMock->expects($this->any())->method('setReturnResponse')->will($this->returnSelf()); + $this->_soapServerMock->expects($this->any())->method('setObject')->will($this->returnSelf()); + $this->_autoDiscoverMock = $this->getMockBuilder('Mage_Webapi_Model_Soap_AutoDiscover') + ->disableOriginalConstructor() + ->setMethods(array('handle')) + ->getMock(); + $this->_requestMock = $this->getMockBuilder('Mage_Webapi_Controller_Request_Soap') + ->setMethods(array('getParam', 'getRequestedResources')) + ->disableOriginalConstructor() + ->getMock(); + $this->_responseMock = $this->getMockBuilder('Mage_Webapi_Controller_Response') + ->disableOriginalConstructor() + ->setMethods(array('clearHeaders', 'setHeader', 'setBody', 'sendResponse', 'setHttpResponseCode')) + ->getMock(); + $this->_soapFaultMock = $this->getMockBuilder('Mage_Webapi_Model_Soap_Fault') + ->disableOriginalConstructor() + ->setMethods(array('getSoapFaultMessage')) + ->getMock(); + $this->_errorProcessorMock = $this->getMockBuilder('Mage_Webapi_Controller_Dispatcher_ErrorProcessor') + ->disableOriginalConstructor() + ->setMethods(array('maskException')) + ->getMock(); + $soapHandlerMock = $this->getMockBuilder('Mage_Webapi_Controller_Dispatcher_Soap_Handler') + ->disableOriginalConstructor() + ->getMock(); + + $this->_dispatcher = new Mage_Webapi_Controller_Dispatcher_Soap( + $this->_apiConfigMock, + $this->_requestMock, + $this->_responseMock, + $this->_autoDiscoverMock, + $this->_soapServerMock, + $this->_soapFaultMock, + $this->_errorProcessorMock, + $soapHandlerMock + ); + } + + /** + * Clean up dispatcher and it's dependencies. + */ + protected function tearDown() + { + unset($this->_dispatcher); + unset($this->_apiConfigMock); + unset($this->_requestMock); + unset($this->_responseMock); + unset($this->_autoDiscoverMock); + unset($this->_soapServerMock); + unset($this->_soapFaultMock); + unset($this->_errorProcessorMock); + + parent::tearDown(); + } + + /** + * Test successful WSDL content generation. + */ + public function testDispatchWsdl() + { + $this->_mockGetParam(1); + + $charset = 'utf8'; + $contentType = 'text/xml'; + $this->_mockSetResponseContentType($contentType, $charset); + + $expectedWsdl = '<?xml version="1.0" encoding="' . $charset .'"?><root>WSDL_CONTENT</root>'; + $expectedResources = array('foo' => 'v1'); + $expectedUrl = 'http://magento.host/api/soap?resources[foo]=v1'; + $this->_requestMock->expects($this->once()) + ->method('getRequestedResources') + ->will($this->returnValue($expectedResources)); + $this->_soapServerMock->expects($this->once()) + ->method('generateUri') + ->will($this->returnValue($expectedUrl)); + $this->_autoDiscoverMock->expects($this->once()) + ->method('handle') + ->with($expectedResources, $expectedUrl) + ->will($this->returnValue($expectedWsdl)); + + $this->_mockSetResponse($expectedWsdl); + + $this->_dispatcher->dispatch(); + } + + /** + * Test successful SOAP action request dispatch. + */ + public function testDispatchSoapRequest() + { + $this->_mockGetParam(null); + + $charset = 'utf8'; + $contentType = 'application/soap+xml'; + $this->_mockSetResponseContentType($contentType, $charset); + $expectedResponse = '<?xml version="1.0" encoding="' . $charset .'"?><root>SOAP_RESPONSE</root>'; + + $this->_soapServerMock->expects($this->once()) + ->method('initWsdlCache') + ->with(); + $this->_soapServerMock->expects($this->once()) + ->method('handle') + ->will($this->returnValue($expectedResponse)); + + $this->_mockSetResponse($expectedResponse); + + $this->_dispatcher->dispatch(); + } + + /** + * Test handling exception during dispatch. + */ + public function testDispatchWithException() + { + $this->_mockGetParam(null); + + $expectedException = new Mage_Webapi_Exception('Test message', Mage_Webapi_Exception::HTTP_BAD_REQUEST); + $this->_soapServerMock->expects($this->once()) + ->method('handle') + ->will($this->throwException($expectedException)); + + $this->_mockSetResponseContentType('text/xml'); + $this->_errorProcessorMock->expects($this->once()) + ->method('maskException') + ->with($expectedException) + ->will($this->returnArgument(0)); + $this->_responseMock->expects($this->once()) + ->method('setHttpResponseCode') + ->with(400); + + $expectedResources = array( + 'foo' => array('v1'), + 'bar' => array('v2'), + ); + $expectedUrl = 'http://magento.host/api/soap/'; + $this->_apiConfigMock->expects($this->once()) + ->method('getAllResourcesVersions') + ->will($this->returnValue($expectedResources)); + $this->_soapServerMock->expects($this->any()) + ->method('getEndpointUri') + ->will($this->returnValue($expectedUrl)); + $expectedDetails = array( + 'availableResources' => array( + 'foo' => array('v1' => $expectedUrl . '?wsdl&resources[foo]=v1'), + 'bar' => array('v2' => $expectedUrl . '?wsdl&resources[bar]=v2'), + ) + ); + $expectedFault = '<?xml version="1.0" encoding="utf8"?><root>SOAP_FAULT</root>'; + $this->_soapFaultMock->expects($this->once()) + ->method('getSoapFaultMessage') + ->with( + $expectedException->getMessage(), + Mage_Webapi_Model_Soap_Fault::FAULT_CODE_SENDER, + 'en', + $expectedDetails + ) + ->will($this->returnValue($expectedFault)); + + $this->_dispatcher->dispatch(); + } + + /** + * Mock getParam() of request object to return given value. + * + * @param $value + */ + protected function _mockGetParam($value) + { + $this->_requestMock->expects($this->once()) + ->method('getParam') + ->with(Mage_Webapi_Model_Soap_Server::REQUEST_PARAM_WSDL) + ->will($this->returnValue($value)); + } + + /** + * Mock dispatcher _setResponseContentType() method. + * + * @param $charset + * @param $contentType + */ + protected function _mockSetResponseContentType($contentType = 'application/soap+xml', $charset = 'utf8') + { + $this->_responseMock->expects($this->once()) + ->method('clearHeaders') + ->will($this->returnSelf()); + $this->_soapServerMock->expects($this->any()) + ->method('getApiCharset') + ->will($this->returnValue($charset)); + $this->_responseMock->expects($this->once()) + ->method('setHeader') + ->with('Content-Type', "{$contentType}; charset={$charset}"); + } + + /** + * Mock setting response object to expect given response body. + * + * @param $expectedResponse + */ + protected function _mockSetResponse($expectedResponse) + { + $this->_responseMock->expects($this->once()) + ->method('setBody') + ->with($expectedResponse); + $this->_responseMock->expects($this->once()) + ->method('sendResponse') + ->with(); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Controller/FrontTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Controller/FrontTest.php new file mode 100644 index 0000000000000000000000000000000000000000..6fd447d454e89b7b1ef9301b0527ebb3120c9563 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Controller/FrontTest.php @@ -0,0 +1,191 @@ +<?php +/** + * Test Webapi Front Controller. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Controller_FrontTest extends PHPUnit_Framework_TestCase +{ + /** @var Mage_Webapi_Controller_Front */ + protected $_frontControllerMock; + + /** @var Magento_Controller_Router_Route_Factory. */ + protected $_routeFactoryMock; + + /** @var Mage_Webapi_Controller_Dispatcher_Factory. */ + protected $_dispatcherFactory; + + /** @var Mage_Webapi_Controller_Dispatcher_ErrorProcessor. */ + protected $_errorProcessorMock; + + protected function setUp() + { + /** Prepare mocks for SUT constructor. */ + $helper = $this->getMockBuilder('Mage_Webapi_Helper_Data') + ->disableOriginalConstructor() + ->setMethods(array('__')) + ->getMock(); + $helper->expects($this->any())->method('__')->will($this->returnArgument(0)); + $helperFactory = $this->getMock('Mage_Core_Model_Factory_Helper'); + $helperFactory->expects($this->any())->method('get')->will($this->returnValue($helper)); + + $this->_dispatcherFactory = $this->getMockBuilder('Mage_Webapi_Controller_Dispatcher_Factory') + ->disableOriginalConstructor()->getMock(); + $application = $this->getMockBuilder('Mage_Core_Model_App')->disableOriginalConstructor()->getMock(); + $this->_routeFactoryMock = $this->getMockBuilder('Magento_Controller_Router_Route_Factory') + ->disableOriginalConstructor()->getMock(); + $this->_errorProcessorMock = $this->getMockBuilder('Mage_Webapi_Controller_Dispatcher_ErrorProcessor') + ->disableOriginalConstructor() + ->getMock(); + /** Initialize SUT. */ + $this->_frontControllerMock = new Mage_Webapi_Controller_Front( + $helperFactory, + $this->_dispatcherFactory, + $application, + $this->_routeFactoryMock, + $this->_errorProcessorMock + ); + parent::setUp(); + } + + protected function tearDown() + { + unset($this->_frontControllerMock); + unset($this->_errorProcessorMock); + unset($this->_dispatcherFactory); + unset($this->_routeFactoryMock); + parent::tearDown(); + } + + public function testGetListOfAvailableApiTypes() + { + $expectedApiTypes = array('rest', 'soap'); + $this->assertEquals( + $expectedApiTypes, + $this->_frontControllerMock->getListOfAvailableApiTypes(), + 'Not expected API types.' + ); + } + + /** + * Exception throwing logic for testInitWithException method. + * + * @throws Mage_Webapi_Exception + */ + public function callbackThrowWebapiExcepion() + { + throw new Mage_Webapi_Exception('Message', Mage_Webapi_Exception::HTTP_BAD_REQUEST); + } + + /** + * Test dispatch method. + */ + public function testDispatch() + { + $this->_createMockForApiRouteAndFactory(array('api_type' => Mage_Webapi_Controller_Front::API_TYPE_REST)); + $restDispatcherMock = $this->getMockBuilder('Mage_Webapi_Controller_Dispatcher_Rest') + ->disableOriginalConstructor() + ->getMock(); + /** Assert handle method in mocked object will be executed only once. */ + $restDispatcherMock->expects($this->once())->method('dispatch'); + $this->_dispatcherFactory->expects($this->any())->method('get') + ->will($this->returnValue($restDispatcherMock)); + $this->_frontControllerMock->dispatch(); + } + + /** + * Test dispatch method with exception. + */ + public function testDispatchException() + { + $this->_createMockForApiRouteAndFactory(array('api_type' => Mage_Webapi_Controller_Front::API_TYPE_REST)); + $restDispatcherMock = $this->getMockBuilder('Mage_Webapi_Controller_Dispatcher_Rest') + ->disableOriginalConstructor() + ->getMock(); + /** Init Logical exception. */ + $logicalException = new LogicException(); + /** Mock dispatcher to throw Logical exception. */ + $restDispatcherMock->expects($this->any())->method('dispatch')->will($this->throwException($logicalException)); + $this->_dispatcherFactory->expects($this->any())->method('get')->will($this->returnValue($restDispatcherMock)); + /** Assert error processor renderException method will be executed with Logical Exception. */ + $this->_errorProcessorMock->expects($this->once())->method('renderException')->with( + $this->equalTo($logicalException) + ); + $this->_frontControllerMock->dispatch(); + } + + /** + * Test DetermineApiType method with Not defined API Type. + */ + public function testDetermineApiTypeNotDefined() + { + $apiType = array('api_type' => 'invalidApiType'); + $this->_createMockForApiRouteAndFactory($apiType); + /** Assert Mage_Webapi_Exception type and message. */ + $this->setExpectedException( + 'Mage_Webapi_Exception', + 'The "%s" API type is not defined.', + Mage_Webapi_Exception::HTTP_BAD_REQUEST + ); + $this->_frontControllerMock->determineApiType(); + } + + /** + * Test DeteminateApiType method without API Type specification. + */ + public function testDetermineApiTypeInvalidRoute() + { + $apiType = false; + $this->_createMockForApiRouteAndFactory($apiType); + /** Assert Mage_Webapi_Exception type and message. */ + $this->setExpectedException( + 'Mage_Webapi_Exception', + 'Request does not match any API type route.', + Mage_Webapi_Exception::HTTP_BAD_REQUEST + ); + $this->_frontControllerMock->determineApiType(); + } + + /** + * Create mock for API Route and Route Factory objects. + */ + protected function _createMockForApiRouteAndFactory($apiType) + { + $apiRouteMock = $this->getMockBuilder('Mage_Webapi_Controller_Router_Route_Webapi') + ->disableOriginalConstructor()->getMock(); + $apiRouteMock->expects($this->any())->method('match')->will($this->returnValue($apiType)); + $this->_routeFactoryMock->expects($this->any())->method('createRoute')->will( + $this->returnValue($apiRouteMock) + ); + } + + public function testDeterminateApiTypeApiIsSet() + { + $this->_createMockForApiRouteAndFactory(array('api_type' => Mage_Webapi_Controller_Front::API_TYPE_SOAP)); + /** Assert createRoute method will be executed only once */ + $this->_routeFactoryMock->expects($this->once())->method('createRoute'); + /** The first method call will set apiType property using createRoute method. */ + $this->_frontControllerMock->determineApiType(); + /** The second method call should use set apiType and should not trigger createRoute method. */ + $this->_frontControllerMock->determineApiType(); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Controller/Request/FactoryTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Controller/Request/FactoryTest.php new file mode 100644 index 0000000000000000000000000000000000000000..4c3a66b8ab1ba597b7b0cc9ea465f05dcce2bcfe --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Controller/Request/FactoryTest.php @@ -0,0 +1,88 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Controller_Request_FactoryTest extends PHPUnit_Framework_TestCase +{ + /** @var PHPUnit_Framework_MockObject_MockObject */ + protected $_objectManager; + + /** @var PHPUnit_Framework_MockObject_MockObject */ + protected $_apiFrontMock; + + /** @var Mage_Webapi_Controller_Request_Factory */ + protected $_requestFactory; + + protected function setUp() + { + /** Prepare mocks for SUT constructor. */ + $this->_objectManager = $this->getMockBuilder('Magento_ObjectManager') + ->setMethods(array('get')) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + $this->_apiFrontMock = $this->getMockBuilder('Mage_Webapi_Controller_Front') + ->setMethods(array('determineApiType')) + ->disableOriginalConstructor() + ->getMock(); + /** Initialize SUT. */ + $this->_requestFactory = new Mage_Webapi_Controller_Request_Factory( + $this->_apiFrontMock, + $this->_objectManager + ); + parent::setUp(); + } + + protected function tearDown() + { + unset($this->_objectManager); + unset($this->_apiFrontMock); + unset($this->_requestFactory); + parent::tearDown(); + } + + public function testGetLogicExceptionInvalidApiType() + { + $this->setExpectedException( + 'LogicException', + 'There is no corresponding request class for the "invalidApiType" API type.' + ); + $this->_apiFrontMock->expects($this->once()) + ->method('determineApiType') + ->will($this->returnValue('invalidApiType')); + $this->_requestFactory->get(); + } + + public function testGet() + { + $this->_apiFrontMock->expects($this->once()) + ->method('determineApiType') + ->will($this->returnValue(Mage_Webapi_Controller_Front::API_TYPE_REST)); + $expectedController = $this->getMockBuilder('Mage_Webapi_Controller_Request_Rest') + ->disableOriginalConstructor() + ->getMock(); + $this->_objectManager->expects($this->once())->method('get')->will($this->returnValue($expectedController)); + $this->assertEquals($expectedController, $this->_requestFactory->get()); + } +} + + + diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Controller/Request/Rest/Interpreter/FactoryTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Controller/Request/Rest/Interpreter/FactoryTest.php new file mode 100644 index 0000000000000000000000000000000000000000..8a4b66e76b0c815de183eb4c475423301edd3b66 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Controller/Request/Rest/Interpreter/FactoryTest.php @@ -0,0 +1,153 @@ +<?php +/** + * Test Webapi Json Interpreter Request Rest Controller + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Controller_Request_Rest_Interpreter_FactoryTest extends PHPUnit_Framework_TestCase +{ + /** @var PHPUnit_Framework_MockObject_MockObject */ + protected $_objectManagerMock; + + /** @var PHPUnit_Framework_MockObject_MockObject */ + protected $_applicationConfig; + + /** @var PHPUnit_Framework_MockObject_MockObject */ + protected $_helperMock; + + /** @var PHPUnit_Framework_MockObject_MockObject */ + protected $_helperFactoryMock; + + /** @var Mage_Webapi_Controller_Request_Rest_Interpreter_Factory */ + protected $_interpreterFactory; + + protected function setUp() + { + /** Prepare mocks for SUT constructor. */ + $this->_helperFactoryMock = $this->getMock('Mage_Core_Model_Factory_Helper'); + $this->_helperMock = $this->getMockBuilder('Mage_Webapi_Helper_Data') + ->disableOriginalConstructor() + ->setMethods(array('__')) + ->getMock(); + $this->_helperFactoryMock->expects($this->any()) + ->method('get') + ->will($this->returnValue($this->_helperMock)); + $this->_objectManagerMock = $this->getMockBuilder('Magento_ObjectManager') + ->disableOriginalConstructor() + ->setMethods(array('get')) + ->getMockForAbstractClass(); + $this->_applicationConfig = $this->getMockBuilder('Mage_Core_Model_Config') + ->setMethods(array('getNode')) + ->disableOriginalConstructor() + ->getMock(); + /** Initialize SUT. */ + $this->_interpreterFactory = new Mage_Webapi_Controller_Request_Rest_Interpreter_Factory( + $this->_objectManagerMock, + $this->_applicationConfig, + $this->_helperFactoryMock + ); + parent::setUp(); + } + + protected function tearDown() + { + unset($this->_objectManagerMock); + unset($this->_applicationConfig); + unset($this->_helperMock); + unset($this->_helperFactoryMock); + unset($this->_interpreterFactory); + parent::tearDown(); + } + + public function testGetLogicExceptionEmptyRequestAdapter() + { + $this->setExpectedException('LogicException', 'Request interpreter adapter is not set.'); + $this->_applicationConfig->expects($this->once())->method('getNode')->will($this->returnValue(null)); + $this->_interpreterFactory->get('contentType'); + } + + public function testGet() + { + /** Prepare mocks for SUT constructor. */ + $expectedMetadata = new SimpleXMLElement('<text_xml><type>text/xml</type><model>Xml</model></text_xml>'); + $this->_applicationConfig + ->expects($this->once()) + ->method('getNode') + ->will($this->returnValue(array($expectedMetadata))); + $validInterpreterMock = $this->getMockBuilder('Mage_Webapi_Controller_Request_Rest_Interpreter_Xml') + ->disableOriginalConstructor() + ->getMock(); + $this->_objectManagerMock + ->expects($this->once()) + ->method('get') + ->will($this->returnValue($validInterpreterMock)); + /** Initialize SUT. */ + $this->_interpreterFactory->get('text/xml'); + } + + public function testGetMageWebapiException() + { + /** Prepare mocks for SUT constructor. */ + $expectedMetadata = new SimpleXMLElement('<text_xml><type>text/xml</type><model>Xml</model></text_xml>'); + $this->_applicationConfig + ->expects($this->once()) + ->method('getNode') + ->will($this->returnValue(array($expectedMetadata))); + $this->_helperMock->expects($this->once()) + ->method('__') + ->with('Server cannot understand Content-Type HTTP header media type "%s"', 'text_xml') + ->will($this->returnValue('Server cannot understand Content-Type HTTP header media type "text_xml"')); + $this->setExpectedException( + 'Mage_Webapi_Exception', + 'Server cannot understand Content-Type HTTP header media type "text_xml"', + Mage_Webapi_Exception::HTTP_BAD_REQUEST + ); + /** Initialize SUT. */ + $this->_interpreterFactory->get('text_xml'); + } + + public function testGetLogicExceptionInvalidRequestInterpreter() + { + /** Prepare mocks for SUT constructor. */ + $expectedMetadata = new SimpleXMLElement('<text_xml><type>text/xml</type><model>Xml</model></text_xml>'); + $this->_applicationConfig + ->expects($this->once()) + ->method('getNode') + ->will($this->returnValue(array($expectedMetadata))); + $invalidInterpreter = $this->getMockBuilder('Mage_Webapi_Controller_Response_Rest_Renderer_Json') + ->disableOriginalConstructor() + ->getMock(); + $this->_objectManagerMock + ->expects($this->once()) + ->method('get') + ->will($this->returnValue($invalidInterpreter)); + $this->setExpectedException( + 'LogicException', + 'The interpreter must implement "Mage_Webapi_Controller_Request_Rest_InterpreterInterface".' + ); + /** Initialize SUT. */ + $this->_interpreterFactory->get('text/xml'); + } +} + + + diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Controller/Request/Rest/Interpreter/JsonTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Controller/Request/Rest/Interpreter/JsonTest.php new file mode 100644 index 0000000000000000000000000000000000000000..46feebeb225c1d5a50d52a0e5f4a077aa3fa29b4 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Controller/Request/Rest/Interpreter/JsonTest.php @@ -0,0 +1,143 @@ +<?php +/** + * Test Webapi Json Interpreter Request Rest Controller + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Controller_Request_Rest_Interpreter_JsonTest extends PHPUnit_Framework_TestCase +{ + /** @var PHPUnit_Framework_MockObject_MockObject */ + protected $_helperFactoryMock; + + /** @var Mage_Webapi_Controller_Request_Rest_Interpreter_Json */ + protected $_jsonInterpreter; + + /** @var PHPUnit_Framework_MockObject_MockObject */ + protected $_coreHelperMock; + + /** @var PHPUnit_Framework_MockObject_MockObject */ + protected $_appMock; + + protected function setUp() + { + /** Prepare mocks for SUT constructor. */ + $this->_helperFactoryMock = $this->getMock('Mage_Core_Model_Factory_Helper'); + $this->_coreHelperMock = $this->getMock('Mage_Core_Helper_Data', array('__', 'jsonDecode')); + $this->_helperFactoryMock->expects($this->any()) + ->method('get') + ->will($this->returnValue($this->_coreHelperMock)); + $this->_appMock = $this->getMockBuilder('Mage_Core_Model_App') + ->setMethods(array('isDeveloperMode')) + ->disableOriginalConstructor() + ->getMock(); + /** Initialize SUT. */ + $this->_jsonInterpreter = new Mage_Webapi_Controller_Request_Rest_Interpreter_Json( + $this->_helperFactoryMock, + $this->_appMock + ); + parent::setUp(); + } + + protected function tearDown() + { + unset($this->_helperFactoryMock); + unset($this->_jsonInterpreter); + unset($this->_coreHelperMock); + unset($this->_appMock); + parent::tearDown(); + } + + public function testInterpretInvalidArgumentException() + { + $this->setExpectedException('InvalidArgumentException', 'Invalid data type "boolean". String is expected.'); + $this->_jsonInterpreter->interpret(false); + } + + public function testInterpret() + { + /** Prepare mocks for SUT constructor. */ + $inputEncodedJson = '{"key1":"test1","key2":"test2","array":{"test01":"some1","test02":"some2"}}'; + $expectedDecodedJson = array( + 'key1' => 'test1', + 'key2' => 'test2', + 'array' => array( + 'test01' => 'some1', + 'test02' => 'some2', + ) + ); + $this->_coreHelperMock->expects($this->once()) + ->method('jsonDecode') + ->will($this->returnValue($expectedDecodedJson)); + /** Initialize SUT. */ + $this->assertEquals( + $expectedDecodedJson, + $this->_jsonInterpreter->interpret($inputEncodedJson), + 'Invalid interpretation from json to array.' + ); + } + + public function testInterpretInvalidEncodedBodyExceptionDeveloperModeOn() + { + /** Prepare mocks for SUT constructor. */ + $this->_coreHelperMock->expects($this->once()) + ->method('jsonDecode') + ->will($this->throwException(new Zend_Json_Exception)); + $this->_appMock->expects($this->once()) + ->method('isDeveloperMode') + ->will($this->returnValue(false)); + $this->_coreHelperMock->expects($this->any())->method('__')->will($this->returnArgument(0)); + $this->setExpectedException( + 'Mage_Webapi_Exception', + 'Decoding error.', + Mage_Webapi_Exception::HTTP_BAD_REQUEST + ); + /** Initialize SUT. */ + $inputInvalidJson = '{"key1":"test1"."key2":"test2"}'; + $this->_jsonInterpreter->interpret($inputInvalidJson); + } + + public function testInterpretInvalidEncodedBodyExceptionDeveloperModeOff() + { + /** Prepare mocks for SUT constructor. */ + $this->_coreHelperMock->expects($this->once()) + ->method('jsonDecode') + ->will( + $this->throwException( + new Zend_Json_Exception('Decoding error:' . PHP_EOL . 'Decoding failed: Syntax error') + ) + ); + $this->_appMock->expects($this->once()) + ->method('isDeveloperMode') + ->will($this->returnValue(true)); + $this->setExpectedException( + 'Mage_Webapi_Exception', + 'Decoding error:' . PHP_EOL . 'Decoding failed: Syntax error', + Mage_Webapi_Exception::HTTP_BAD_REQUEST + ); + /** Initialize SUT. */ + $inputInvalidJson = '{"key1":"test1"."key2":"test2"}'; + $this->_jsonInterpreter->interpret($inputInvalidJson); + } +} + + + diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Controller/Request/Rest/Interpreter/XmlTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Controller/Request/Rest/Interpreter/XmlTest.php new file mode 100644 index 0000000000000000000000000000000000000000..90878d2145a95ac79de85e64d2736d39ff64805e --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Controller/Request/Rest/Interpreter/XmlTest.php @@ -0,0 +1,162 @@ +<?php +/** + * + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Controller_Request_Rest_Interpreter_XmlTest extends PHPUnit_Framework_TestCase +{ + /** @var PHPUnit_Framework_MockObject_MockObject */ + protected $_helperFactoryMock; + + /** @var PHPUnit_Framework_MockObject_MockObject */ + protected $_apiHelperMock; + + /** @var PHPUnit_Framework_MockObject_MockObject */ + protected $_xmlParserMock; + + /** @var Mage_Webapi_Controller_Request_Rest_Interpreter_Xml */ + protected $_xmlInterpreter; + + /** @var PHPUnit_Framework_MockObject_MockObject */ + protected $_appMock; + + protected function setUp() + { + /** Prepare mocks for SUT constructor. */ + $this->_helperFactoryMock = $this->getMock('Mage_Core_Model_Factory_Helper'); + $this->_apiHelperMock = $this->getMockBuilder('Mage_Webapi_Helper_Data') + ->disableOriginalConstructor() + ->setMethods(array('__')) + ->getMock(); + $this->_apiHelperMock->expects($this->any())->method('__')->will($this->returnArgument(0)); + $this->_helperFactoryMock->expects($this->any())->method('get') + ->will($this->returnValue($this->_apiHelperMock)); + $this->_xmlParserMock = $this->getMock('Mage_Xml_Parser', array('xmlToArray', 'loadXML')); + $this->_appMock = $this->getMockBuilder('Mage_Core_Model_App') + ->setMethods(array('isDeveloperMode')) + ->disableOriginalConstructor() + ->getMock(); + /** Initialize SUT. */ + $this->_xmlInterpreter = new Mage_Webapi_Controller_Request_Rest_Interpreter_Xml( + $this->_xmlParserMock, + $this->_helperFactoryMock, + $this->_appMock + ); + parent::setUp(); + } + + protected function tearDown() + { + unset($this->_helperFactoryMock); + unset($this->_apiHelperMock); + unset($this->_xmlInterpreter); + unset($this->_xmlParserMock); + unset($this->_appMock); + parent::tearDown(); + } + + public function testInterpretInvalidArgumentException() + { + $this->setExpectedException('InvalidArgumentException', 'Invalid data type "boolean". String is expected.'); + $this->_xmlInterpreter->interpret(false); + } + + public function testInterpret() + { + /** Prepare mocks for SUT constructor. */ + $this->_xmlParserMock->expects($this->once())->method('loadXML'); + $validInputXml = '<?xml version="1.0"?><xml><key1>test1</key1><key2>test2</key2></xml>'; + $returnArray = array('xml' => array('key1' => 'test1', 'key2' => 'test2')); + $this->_xmlParserMock->expects($this->once())->method('xmlToArray')->will($this->returnValue($returnArray)); + $expectedArray = array('key1' => 'test1', 'key2' => 'test2'); + /** Initialize SUT. */ + $this->assertEquals( + $expectedArray, + $this->_xmlInterpreter->interpret($validInputXml), + 'Request xml body was parsed incorrectly into array of params' + ); + } + + public function testHandleErrors() + { + /** Add message to error dispatcher. */ + $firstErrorMessage = "No document type declaration. "; + $this->_xmlInterpreter->handleErrors(null, $firstErrorMessage, null, null); + /** Assert that first error message was added to error dispatcher. */ + $this->assertAttributeEquals( + $firstErrorMessage, + '_errorMessage', + $this->_xmlInterpreter, + 'Error message was not set to error dispatcher.' + ); + /** Add new message to error dispatcher. */ + $secondErrorMessage = "Strings should be wrapped in double quotes."; + $expectedMessages = $firstErrorMessage . $secondErrorMessage; + $this->_xmlInterpreter->handleErrors(null, $secondErrorMessage, null, null); + /** Assert that both error messages were added to error dispatcher. */ + $this->assertAttributeEquals( + $expectedMessages, + '_errorMessage', + $this->_xmlInterpreter, + 'Error messages were not set to error dispatcher.' + ); + } + + public function testInterpretMageWebapiExceptionDeveloperModeOn() + { + /** Prepare mocks for SUT constructor. */ + $this->_appMock->expects($this->once()) + ->method('isDeveloperMode') + ->will($this->returnValue(true)); + $errorMessage = 'End tag for "key1" was omitted.'; + $this->_xmlInterpreter->handleErrors(null, $errorMessage, null, null); + $this->_xmlParserMock->expects($this->once())->method('loadXML'); + $invalidXml = '<?xml version="1.0"?><xml><key1>test1</xml>'; + $this->setExpectedException( + 'Mage_Webapi_Exception', + 'Decoding Error: End tag for "key1" was omitted.', + Mage_Webapi_Exception::HTTP_BAD_REQUEST + ); + /** Initialize SUT. */ + $this->_xmlInterpreter->interpret($invalidXml); + } + + public function testInterpretMageWebapiExceptionDeveloperModeOff() + { + /** Prepare mocks for SUT constructor. */ + $this->_appMock->expects($this->once()) + ->method('isDeveloperMode') + ->will($this->returnValue(false)); + $errorMessage = 'End tag for "key1" was omitted.'; + $this->_xmlInterpreter->handleErrors(null, $errorMessage, null, null); + $this->_xmlParserMock->expects($this->once())->method('loadXML'); + $invalidXml = '<?xml version="1.0"?><xml><key1>test1</xml>'; + $this->setExpectedException( + 'Mage_Webapi_Exception', + 'Decoding error.', + Mage_Webapi_Exception::HTTP_BAD_REQUEST + ); + /** Initialize SUT. */ + $this->_xmlInterpreter->interpret($invalidXml); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Controller/Request/RestTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Controller/Request/RestTest.php new file mode 100644 index 0000000000000000000000000000000000000000..7bf702b4d80be22ba8e58b80a58e8b256119cd9a --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Controller/Request/RestTest.php @@ -0,0 +1,481 @@ +<?php +/** + * Test Webapi Request model + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Controller_Request_RestTest extends PHPUnit_Framework_TestCase +{ + /** + * Request mock + * + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_request; + + /** @var PHPUnit_Framework_MockObject_MockObject */ + protected $_interpreterFactory; + + protected function setUp() + { + parent::setUp(); + /** Prepare mocks for request constructor arguments. */ + $this->_interpreterFactory = $this->getMockBuilder('Mage_Webapi_Controller_Request_Rest_Interpreter_Factory') + ->setMethods(array('interpret', 'get')) + ->disableOriginalConstructor() + ->getMock(); + $helper = $this->getMockBuilder('Mage_Webapi_Helper_Data') + ->disableOriginalConstructor() + ->setMethods(array('__')) + ->getMock(); + $helper->expects($this->any())->method('__')->will($this->returnArgument(0)); + /** Instantiate request. */ + // TODO: Get rid of SUT mocks. + $this->_request = $this->getMock( + 'Mage_Webapi_Controller_Request_Rest', + array('getHeader', 'getMethod', 'isGet', 'isPost', 'isPut', 'isDelete', 'getRawBody'), + array($this->_interpreterFactory, $helper) + ); + } + + protected function tearDown() + { + unset($this->_request); + parent::tearDown(); + } + + /** + * Test for getAcceptTypes() method + * + * @dataProvider providerAcceptType + * @param string $acceptHeader Value of Accept HTTP header + * @param array $expectedResult Method call result + */ + public function testGetAcceptTypes($acceptHeader, $expectedResult) + { + $this->_request + ->expects($this->once()) + ->method('getHeader') + ->with('Accept') + ->will($this->returnValue($acceptHeader)); + /** @var Mage_Webapi_Controller_Request_Rest _requestMock */ + $this->assertSame($expectedResult, $this->_request->getAcceptTypes()); + } + + /** + * Test for getBodyParams() method. + */ + public function testGetBodyParams() + { + $params = array('a' => 123, 'b' => 145); + $this->_prepareSutForGetBodyParamsTest($params); + $this->assertEquals( + $params, + $this->_request->getBodyParams(), + 'Body parameters were retrieved incorrectly.' + ); + } + + /** + * Prepare SUT for GetBodyParams() method mock. + * + * @param array $params + */ + protected function _prepareSutForGetBodyParamsTest($params) + { + $rawBody = 'rawBody'; + $this->_request->expects($this->once()) + ->method('getRawBody') + ->will($this->returnValue($rawBody)); + $contentType = 'contentType'; + $this->_request + ->expects($this->once()) + ->method('getHeader') + ->with('Content-Type') + ->will($this->returnValue($contentType)); + $interpreter = $this->getMockBuilder('Mage_Webapi_Controller_Request_Rest_Interpreter_Json') + ->disableOriginalConstructor() + ->setMethods(array('interpret')) + ->getMock(); + $interpreter->expects($this->once()) + ->method('interpret') + ->with($rawBody) + ->will($this->returnValue($params)); + $this->_interpreterFactory->expects($this->once()) + ->method('get') + ->with($contentType) + ->will($this->returnValue($interpreter)); + } + + /** + * Test for getContentType() method + * + * @dataProvider providerContentType + * @param string $contentTypeHeader 'Content-Type' header value + * @param string $contentType Appropriate content type for header value + * @param string|boolean $exceptionMessage Exception message (boolean FALSE if exception is not expected) + */ + public function testGetContentType($contentTypeHeader, $contentType, $exceptionMessage = false) + { + $this->_request + ->expects($this->once()) + ->method('getHeader') + ->with('Content-Type') + ->will($this->returnValue($contentTypeHeader)); + + try { + $this->assertEquals($contentType, $this->_request->getContentType()); + } catch (Mage_Webapi_Exception $e) { + if ($exceptionMessage) { + $this->assertEquals( + $exceptionMessage, + $e->getMessage(), + 'Exception message does not match expected one' + ); + return; + } else { + $this->fail('Exception thrown on valid header: ' . $e->getMessage()); + } + } + if ($exceptionMessage) { + $this->fail('Expected exception was not raised'); + } + } + + /** + * Test for getOperation() method + * + * @dataProvider providerRequestMethod + * @param string $requestMethod Request method + * @param string $crudOperation CRUD operation name + * @param string|boolean $exceptionMessage Exception message (boolean FALSE if exception is not expected) + */ + public function testGetOperation($requestMethod, $crudOperation, $exceptionMessage = false) + { + $expectedMethod = false; + switch ($requestMethod) { + case 'GET': + case 'POST': + case 'PUT': + case 'DELETE': + $expectedMethod = 'is' . ucfirst($requestMethod); + break; + } + + if ($expectedMethod) { + $this->_request + ->expects($this->once()) + ->method($expectedMethod) + ->will($this->returnValue(true)); + } + + $this->_request + ->expects($this->any()) + ->method('getMethod') + ->will($this->returnValue($requestMethod)); + + try { + $this->assertEquals($crudOperation, $this->_request->getHttpMethod()); + } catch (Mage_Webapi_Exception $e) { + if ($exceptionMessage) { + $this->assertEquals( + $exceptionMessage, + $e->getMessage(), + 'Exception message does not match expected one' + ); + return; + } else { + $this->fail('Exception thrown on valid header: ' . $e->getMessage()); + } + } + if ($exceptionMessage) { + $this->fail('Expected exception was not raised'); + } + } + + /** + * Test for getResourceType() method + * + */ + public function testGetResourceType() + { + $this->assertNull($this->_request->getResourceType()); + $resource = 'test_resource'; + $this->_request->setResourceType($resource); + $this->assertEquals($resource, $this->_request->getResourceType()); + } + + /** + * Data provider for testGetAcceptTypes() + * + * @return array + */ + public function providerAcceptType() + { + return array( + // Each element is: array(Accept HTTP header value, expected result)) + array('', array()), + array( + 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', + array('text/html', 'application/xhtml+xml', 'application/xml', '*/*') + ), + array( + 'text/html, application/*, text, */*', + array('text/html', 'application/*', 'text', '*/*') + ), + array( + 'text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/webp,' + . ' image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1', + array( + 'text/html', + 'application/xhtml+xml', + 'image/png', + 'image/webp', + 'image/jpeg', + 'image/gif', + 'image/x-xbitmap', + 'application/xml', + '*/*' + ) + ) + ); + } + + /** + * Data provider for testGetContentType() + * + * @return array + */ + public function providerContentType() + { + return array( + // Each element is: array(Content-Type header value, content-type part[, expected exception message]) + array('', null, 'Content-Type header is empty'), + array('_?', null, 'Invalid Content-Type header'), + array('application/x-www-form-urlencoded; charset=UTF-8', 'application/x-www-form-urlencoded'), + array('application/x-www-form-urlencoded; charset=utf-8', 'application/x-www-form-urlencoded'), + array('text/html; charset=uTf-8', 'text/html'), + array('text/html; charset=', null, 'Invalid Content-Type header'), + array('text/html;', null, 'Invalid Content-Type header'), + array('application/dialog.dot-info7+xml', 'application/dialog.dot-info7+xml'), + array('application/x-www-form-urlencoded; charset=cp1251', null, 'UTF-8 is the only supported charset') + ); + } + + /** + * Data provider for testGetOperation() + * + * @return array + */ + public function providerRequestMethod() + { + return array( + // Each element is: array(Request method, CRUD operation name[, expected exception message]) + array('INVALID_METHOD', null, 'Invalid request method'), + array('GET', Mage_Webapi_Controller_Request_Rest::HTTP_METHOD_GET), + array('POST', Mage_Webapi_Controller_Request_Rest::HTTP_METHOD_CREATE), + array('PUT', Mage_Webapi_Controller_Request_Rest::HTTP_METHOD_UPDATE), + array('DELETE', Mage_Webapi_Controller_Request_Rest::HTTP_METHOD_DELETE) + ); + } + + /** + * @dataProvider dataProviderTestGetActionTypeByMethod + * @param string $methodName + * @param string $expectedActionType + */ + public function testGetActionTypeByMethod($methodName, $expectedActionType) + { + $this->assertEquals( + $expectedActionType, + Mage_Webapi_Controller_Request_Rest::getActionTypeByOperation($methodName), + "Action type was identified incorrectly by method name." + ); + } + + public static function dataProviderTestGetActionTypeByMethod() + { + return array( + array( + Mage_Webapi_Controller_ActionAbstract::METHOD_CREATE, + Mage_Webapi_Controller_Request_Rest::ACTION_TYPE_COLLECTION + ), + array( + Mage_Webapi_Controller_ActionAbstract::METHOD_DELETE, + Mage_Webapi_Controller_Request_Rest::ACTION_TYPE_ITEM + ), + ); + } + + public function testGetActionTypeException() + { + $methodName = 'invalidMethodV1'; + $this->setExpectedException( + 'InvalidArgumentException', + sprintf('The "%s" method is not a valid resource method.', $methodName) + ); + Mage_Webapi_Controller_Request_Rest::getActionTypeByOperation($methodName); + } + + public function testGetResourceVersion() + { + $this->_request->setParam('resourceVersion', 'v1'); + $this->assertEquals(1, $this->_request->getResourceVersion(), 'Version number was missed.'); + } + + public function testGetResourceVersionVersionIsNotSpecifiedException() + { + $this->setExpectedException( + 'Mage_Webapi_Exception', + 'Resource version is not specified or invalid one is specified', + Mage_Webapi_Exception::HTTP_BAD_REQUEST + ); + $this->_request->getResourceVersion(); + } + + public function testGetResourceName() + { + $resourceName = 'resourceName'; + $this->_request->setResourceName($resourceName); + $this->assertEquals($resourceName, $this->_request->getResourceName()); + } + + public function testGetOperationNameMethodNotExistException() + { + /** Prepare mocks for SUT constructor. */ + $this->setExpectedException( + 'Mage_Webapi_Exception', + 'Requested method does not exist.', + Mage_Webapi_Exception::HTTP_NOT_FOUND + ); + $this->_request->expects($this->once())->method('isPost')->will($this->returnValue(true)); + $this->_request->expects($this->once())->method('getMethod')->will($this->returnValue('POST')); + $this->_request->setResourceType(Mage_Webapi_Controller_Request_Rest::ACTION_TYPE_ITEM); + /** Initialize SUT. */ + $this->_request->getOperationName(); + } + + /** + * @dataProvider getOperationNameProvider + */ + public function testGetOperationName($resourceType, $httpMethod, $operationName) + { + /** Prepare mocks for SUT constructor. */ + $this->_request->setResourceType($resourceType); + $this->_request->expects($this->once())->method('isPost')->will($this->returnValue(true)); + $this->_request->expects($this->once())->method('getMethod')->will($this->returnValue($httpMethod)); + $this->_request->setResourceName('resourceName'); + + /** Initialize SUT. */ + $this->assertEquals( + $operationName, + $this->_request->getOperationName(), + 'Method getOperationName() retrieved invalid resource name. Check $restMethodMap variable.' + ); + } + + /** + * Success getOperationName() method data provider + * + * @return array + */ + public function getOperationNameProvider() + { + return array( + 'GET request with action type: item.' => array( + Mage_Webapi_Controller_Request_Rest::ACTION_TYPE_ITEM, + 'GET', + 'resourceNameGet', + ), + 'PUT request with action type: item.' => array( + Mage_Webapi_Controller_Request_Rest::ACTION_TYPE_ITEM, + 'PUT', + 'resourceNameUpdate', + ), + 'DELETE request with action type: item.' => array( + Mage_Webapi_Controller_Request_Rest::ACTION_TYPE_ITEM, + 'DELETE', + 'resourceNameDelete', + ), + 'GET request with action type: collection.' => array( + Mage_Webapi_Controller_Request_Rest::ACTION_TYPE_COLLECTION, + 'GET', + 'resourceNameList', + ), + 'PUT request with action type: collection.' => array( + Mage_Webapi_Controller_Request_Rest::ACTION_TYPE_COLLECTION, + 'PUT', + 'resourceNameMultiUpdate', + ), + 'DELETE request with action type: collection.' => array( + Mage_Webapi_Controller_Request_Rest::ACTION_TYPE_COLLECTION, + 'DELETE', + 'resourceNameMultiDelete', + ), + ); + } + + public function testGetOperationNameWithCreateMethod() + { + /** Prepare mocks for SUT constructor. */ + $this->_prepareSutForGetOperationNameWithCreateMethod(); + $this->_prepareSutForGetBodyParamsTest(array('key_1' => 'value', 'key_2' => 'value')); + + /** Initialize SUT. */ + $this->assertEquals( + 'resourceNameCreate', + $this->_request->getOperationName(), + 'Invalid resource name for create method.' + ); + } + + public function testGetOperationNameWithMultiCreateMethod() + { + /** Prepare mocks for SUT constructor. */ + $this->_prepareSutForGetOperationNameWithCreateMethod(); + $params = array( + array('key_1' => 'value 1'), + array('key_2' => 'value 2'), + ); + $this->_prepareSutForGetBodyParamsTest($params); + + /** Initialize SUT. */ + $this->assertEquals( + 'resourceNameMultiCreate', + $this->_request->getOperationName(), + 'Invalid resource name for multi create method.' + ); + } + + /** + * Prepare SUT for GetOperationName() with create action. + */ + protected function _prepareSutForGetOperationNameWithCreateMethod() + { + $this->_request->setResourceType(Mage_Webapi_Controller_Request_Rest::ACTION_TYPE_COLLECTION); + $this->_request->expects($this->once())->method('isPost')->will($this->returnValue(true)); + $this->_request->expects($this->once()) + ->method('getMethod') + ->will($this->returnValue('POST')); + $this->_request->setResourceName('resourceName'); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Controller/Request/SoapTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Controller/Request/SoapTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b3c8849aabd6a283573ecefcf995edf984dfbc5c --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Controller/Request/SoapTest.php @@ -0,0 +1,119 @@ +<?php +/** + * Soap API Request Test. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Controller_Request_SoapTest extends PHPUnit_Framework_TestCase +{ + /** @var PHPUnit_Framework_MockObject_MockObject */ + protected $_helperMock; + + /** @var Mage_Webapi_Controller_Request_Soap */ + protected $_soapRequest; + + protected function setUp() + { + /** Prepare mocks for SUT constructor. */ + $this->_helperMock = $this->getMockBuilder('Mage_Webapi_Helper_Data') + ->setMethods(array('__')) + ->disableOriginalConstructor() + ->getMock(); + /** Initialize SUT. */ + $this->_soapRequest = new Mage_Webapi_Controller_Request_Soap($this->_helperMock); + parent::setUp(); + } + + protected function tearDown() + { + unset($this->_helperMock); + unset($this->_soapRequest); + parent::tearDown(); + } + + public function testGetRequestedResourcesNotAllowedParametersException() + { + /** Prepare mocks for SUT constructor. */ + $wsdlParam = Mage_Webapi_Model_Soap_Server::REQUEST_PARAM_WSDL; + $resourcesParam = Mage_Webapi_Model_Soap_Server::REQUEST_PARAM_RESOURCES; + // Set two not allowed parameters and all allowed + $requestParams = array( + 'param_1' => 'foo', + 'param_2' => 'bar', + $wsdlParam => true, + Mage_Webapi_Controller_Router_Route_Webapi::PARAM_API_TYPE => true, + $resourcesParam => true + ); + $this->_soapRequest->setParams($requestParams); + $this->_helperMock->expects($this->at(0)) + ->method('__') + ->with('Not allowed parameters: %s. ', 'param_1, param_2') + ->will($this->returnValue('Not allowed parameters: param_1, param_2. ')); + $this->_helperMock->expects($this->at(1)) + ->method('__') + ->with('Please use only "%s" and "%s".', $wsdlParam, $resourcesParam) + ->will($this->returnValue('Please use only "' . $wsdlParam . '" and "' . $resourcesParam . '".')); + $this->setExpectedException( + 'Mage_Webapi_Exception', + 'Not allowed parameters: param_1, param_2. Please use only "' + . $wsdlParam . '" and "' . $resourcesParam . '".', + Mage_Webapi_Exception::HTTP_BAD_REQUEST + ); + /** Execute SUT. */ + $this->_soapRequest->getRequestedResources(); + } + + public function testGetRequestedResourcesEmptyRequestedResourcesException() + { + /** Prepare mocks for SUT constructor. */ + $requestParams = array(Mage_Webapi_Model_Soap_Server::REQUEST_PARAM_RESOURCES => null); + $this->_soapRequest->setParams($requestParams); + $this->_helperMock->expects($this->once()) + ->method('__') + ->will($this->returnArgument(0)); + $this->setExpectedException( + 'Mage_Webapi_Exception', + 'Requested resources are missing.', + Mage_Webapi_Exception::HTTP_BAD_REQUEST + ); + /** Execute SUT. */ + $this->_soapRequest->getRequestedResources(); + } + + public function testGetRequestedResources() + { + /** Prepare mocks for SUT constructor. */ + $resources = array('resourceName_1' => 'version', 'resourceName_2' => 'version'); + $requestParams = array( + Mage_Webapi_Model_Soap_Server::REQUEST_PARAM_WSDL => true, + Mage_Webapi_Model_Soap_Server::REQUEST_PARAM_RESOURCES => $resources, + Mage_Webapi_Controller_Router_Route_Webapi::PARAM_API_TYPE => 'soap' + ); + $this->_soapRequest->setParams($requestParams); + /** Execute SUT. */ + $this->assertEquals( + $resources, + $this->_soapRequest->getRequestedResources(), + 'Requested resources were retrieved incorrectly. ' + ); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Controller/RequestTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Controller/RequestTest.php new file mode 100644 index 0000000000000000000000000000000000000000..5def59a758b3d16f732de21493199953d3feb4f1 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Controller/RequestTest.php @@ -0,0 +1,139 @@ +<?php +/** + * Test for Webapi Request. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Controller_RequestTest extends PHPUnit_Framework_TestCase +{ + /** + * Request object + * + * @var Mage_Webapi_Controller_Request + */ + protected $_request; + + protected function setUp() + { + parent::setUp(); + + $this->_request = new Mage_Webapi_Controller_RequestStub(Mage_Webapi_Controller_Front::API_TYPE_REST); + } + + /** + * Test for getFilter() method + */ + public function testGetFilter() + { + $_POST[Mage_Webapi_Controller_Request::QUERY_PARAM_FILTER] = 'filter_exists'; + $this->_request->setParam(Mage_Webapi_Controller_Request::QUERY_PARAM_FILTER, 'filter_exists'); + + $this->assertNull($this->_request->getFilter()); + + $_GET[Mage_Webapi_Controller_Request::QUERY_PARAM_FILTER] = 'filter_exists'; + + $this->assertEquals('filter_exists', $this->_request->getFilter()); + } + + /** + * Test for getOrderDirection() method + */ + public function testGetOrderDirection() + { + $_POST[Mage_Webapi_Controller_Request::QUERY_PARAM_ORDER_DIR] = 'asc'; + $this->_request->setParam(Mage_Webapi_Controller_Request::QUERY_PARAM_ORDER_DIR, 'asc'); + + $this->assertNull($this->_request->getOrderDirection()); + + $_GET[Mage_Webapi_Controller_Request::QUERY_PARAM_ORDER_DIR] = 'asc'; + + $this->assertEquals('asc', $this->_request->getOrderDirection()); + } + + /** + * Test for getOrderField() method + */ + public function testGetOrderField() + { + $_POST[Mage_Webapi_Controller_Request::QUERY_PARAM_ORDER_FIELD] = 'order_exists'; + $this->_request->setParam(Mage_Webapi_Controller_Request::QUERY_PARAM_ORDER_FIELD, 'order_exists'); + + $this->assertNull($this->_request->getOrderField()); + + $_GET[Mage_Webapi_Controller_Request::QUERY_PARAM_ORDER_FIELD] = 'order_exists'; + + $this->assertEquals('order_exists', $this->_request->getOrderField()); + } + + /** + * Test for getPageNumber() method + */ + public function testGetPageNumber() + { + $_POST[Mage_Webapi_Controller_Request::QUERY_PARAM_PAGE_NUM] = 5; + $this->_request->setParam(Mage_Webapi_Controller_Request::QUERY_PARAM_PAGE_NUM, 5); + + $this->assertNull($this->_request->getPageNumber()); + + $_GET[Mage_Webapi_Controller_Request::QUERY_PARAM_PAGE_NUM] = 5; + + $this->assertEquals(5, $this->_request->getPageNumber()); + } + + /** + * Test for getPageSize() method + */ + public function testGetPageSize() + { + $_POST[Mage_Webapi_Controller_Request::QUERY_PARAM_PAGE_SIZE] = 5; + $this->_request->setParam(Mage_Webapi_Controller_Request::QUERY_PARAM_PAGE_SIZE, 5); + $this->assertNull($this->_request->getPageSize()); + + $_GET[Mage_Webapi_Controller_Request::QUERY_PARAM_PAGE_SIZE] = 5; + $this->assertEquals(5, $this->_request->getPageSize()); + } + + /** + * Test for getRequestedAttributes() method + */ + public function testGetRequestedAttributes() + { + $_GET[Mage_Webapi_Controller_Request::QUERY_PARAM_REQ_ATTRS][] = 'attr1'; + $_GET[Mage_Webapi_Controller_Request::QUERY_PARAM_REQ_ATTRS][] = 'attr2'; + + $this->assertInternalType('array', $this->_request->getRequestedAttributes()); + $this->assertEquals(array('attr1', 'attr2'), $this->_request->getRequestedAttributes()); + + $_GET[Mage_Webapi_Controller_Request::QUERY_PARAM_REQ_ATTRS] = 'attr1, attr2'; + + $this->assertInternalType('array', $this->_request->getRequestedAttributes()); + $this->assertEquals(array('attr1', 'attr2'), $this->_request->getRequestedAttributes()); + } +} + +class Mage_Webapi_Controller_RequestStub extends Mage_Webapi_Controller_Request +{ + public function getRequestedResources() + { + return array(); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Controller/Response/FactoryTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Controller/Response/FactoryTest.php new file mode 100644 index 0000000000000000000000000000000000000000..4d01b9caafd16ebccfc2355c16a0601aae009ebc --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Controller/Response/FactoryTest.php @@ -0,0 +1,87 @@ +<?php +/** + * Test Response factory. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Controller_Response_FactoryTest extends PHPUnit_Framework_TestCase +{ + /** @var Mage_Webapi_Controller_Response_Factory */ + protected $_factory; + + /** @var Mage_Webapi_Controller_Front */ + protected $_apiFrontController; + + /** @var Magento_ObjectManager */ + protected $_objectManager; + + protected function setUp() + { + $this->_apiFrontController = $this->getMockBuilder('Mage_Webapi_Controller_Front') + ->disableOriginalConstructor()->getMock(); + $this->_objectManager = $this->getMockBuilder('Magento_ObjectManager')->disableOriginalConstructor() + ->getMock(); + $this->_factory = new Mage_Webapi_Controller_Response_Factory( + $this->_apiFrontController, + $this->_objectManager); + parent::setUp(); + } + + protected function tearDown() + { + unset($this->_factory); + unset($this->_apiFrontController); + unset($this->_objectManager); + parent::tearDown(); + } + + /** + * Test get method. + */ + public function testGet() + { + /** Mock front controller mock to return Soap api type. */ + $this->_apiFrontController->expects($this->once())->method('determineApiType')->will( + $this->returnValue(Mage_Webapi_Controller_Front::API_TYPE_SOAP) + ); + /** Assert object manager get method will be executed once with Mage_Webapi_Controller_Response parameter. */ + $this->_objectManager->expects($this->once())->method('get')->with('Mage_Webapi_Controller_Response'); + $this->_factory->get(); + } + + /** + * Test get method with wrong API type. + */ + public function testGetWithWrongApiType() + { + $wrongApiType = 'Wrong SOAP'; + /**Mock front controller determine api method to return wrong api type */ + $this->_apiFrontController->expects($this->once())->method('determineApiType')->will( + $this->returnValue($wrongApiType) + ); + $this->setExpectedException( + 'LogicException', + sprintf('There is no corresponding response class for the "%s" API type.', $wrongApiType) + ); + $this->_factory->get(); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Controller/Response/Rest/Renderer/FactoryTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Controller/Response/Rest/Renderer/FactoryTest.php new file mode 100644 index 0000000000000000000000000000000000000000..e3088cabc617d060444e895c1b0df9d7a0daf137 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Controller/Response/Rest/Renderer/FactoryTest.php @@ -0,0 +1,155 @@ +<?php +/** + * Test Rest renderer factory class. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Controller_Response_Rest_Renderer_FactoryTest extends PHPUnit_Framework_TestCase +{ + /** @var Mage_Webapi_Controller_Response_Rest_Renderer_Factory */ + protected $_factory; + + /** @var Mage_Webapi_Controller_Request_Rest */ + protected $_requestMock; + + /** @var Mage_Core_Model_Config */ + protected $_applicationMock; + + /** @var Magento_ObjectManager */ + protected $_objectManagerMock; + + protected function setUp() + { + /** Init dependencies for SUT. */ + $this->_objectManagerMock = $this->getMockBuilder('Magento_ObjectManager')->disableOriginalConstructor() + ->getMock(); + $this->_applicationMock = $this->getMockBuilder('Mage_Core_Model_Config')->disableOriginalConstructor() + ->getMock(); + $helperDataMock = $this->getMockBuilder('Mage_Webapi_Helper_Data')->disableOriginalConstructor()->getMock(); + $helperDataMock->expects($this->any())->method('__')->will($this->returnArgument(0)); + $helperFactoryMock = $this->getMockBuilder('Mage_Core_Model_Factory_Helper')->disableOriginalConstructor() + ->getMock(); + $helperFactoryMock->expects($this->any())->method('get')->will($this->returnValue($helperDataMock)); + $this->_requestMock = $this->getMockBuilder('Mage_Webapi_Controller_Request_Rest')->disableOriginalConstructor() + ->getMock(); + /** Init SUT. */ + $this->_factory = new Mage_Webapi_Controller_Response_Rest_Renderer_Factory( + $this->_objectManagerMock, + $this->_applicationMock, + $helperFactoryMock, + $this->_requestMock + ); + parent::setUp(); + } + + protected function tearDown() + { + unset($this->_factory); + unset($this->_requestMock); + unset($this->_applicationMock); + unset($this->_objectManagerMock); + parent::tearDown(); + } + + /** + * Test get method. + */ + public function testGet() + { + $acceptTypes = array('application/json'); + $availableRenders = $this->_createConfigElementForRenders(); + /** Mock application config getNode method to return the list of renders. */ + $this->_applicationMock->expects($this->once())->method('getNode')->will( + $this->returnValue($availableRenders) + ); + /** Mock request getAcceptTypes method to return specified value. */ + $this->_requestMock->expects($this->once())->method('getAcceptTypes')->will($this->returnValue($acceptTypes)); + /** Mock renderer. */ + $rendererMock = $this->getMockBuilder('Mage_Webapi_Controller_Response_Rest_Renderer_Json') + ->disableOriginalConstructor() + ->getMock(); + /** Mock object to return mocked renderer. */ + $this->_objectManagerMock->expects($this->once())->method('get')->with( + 'Mage_Webapi_Controller_Response_Rest_Renderer_Json' + )->will($this->returnValue($rendererMock)); + $this->_factory->get(); + } + + protected function _createConfigElementForRenders() + { + /** Xml with the list of renders types and models. */ + $rendersXml = <<<XML + <renders> + <default> + <type>*/*</type> + <model>Mage_Webapi_Controller_Response_Rest_Renderer_Json</model> + </default> + <application_json> + <type>application/json</type> + <model>Mage_Webapi_Controller_Response_Rest_Renderer_Json</model> + </application_json> + </renders> +XML; + /** Return Mage_Core_Model_Config_Element with stored renders data. */ + return new Mage_Core_Model_Config_Element($rendersXml); + } + + /** + * Test get method with wrong Accept Http Header. + */ + public function testGetWithWrongAcceptHttpHeader() + { + /** Mock request to return empty Accept Types. */ + $this->_requestMock->expects($this->once())->method('getAcceptTypes')->will($this->returnValue('')); + $this->setExpectedException( + 'Mage_Webapi_Exception', + 'Server cannot understand Accept HTTP header media type.', + Mage_Webapi_Exception::HTTP_NOT_ACCEPTABLE + ); + $this->_factory->get(); + } + + /** + * Test get method with wrong Renderer class. + */ + public function testGetWithWrongRendererClass() + { + $acceptTypes = array('application/json'); + $availableRenders = $this->_createConfigElementForRenders(); + /** Mock application config getNode method to return the list of renders. */ + $this->_applicationMock->expects($this->once())->method('getNode')->will( + $this->returnValue($availableRenders) + ); + /** Mock request getAcceptTypes method to return specified value. */ + $this->_requestMock->expects($this->once())->method('getAcceptTypes')->will($this->returnValue($acceptTypes)); + /** Mock object to return Varien_Object */ + $this->_objectManagerMock->expects($this->once())->method('get')->with( + 'Mage_Webapi_Controller_Response_Rest_Renderer_Json' + )->will($this->returnValue(new Varien_Object())); + + $this->setExpectedException( + 'LogicException', + 'The renderer must implement "Mage_Webapi_Controller_Response_Rest_RendererInterface".' + ); + $this->_factory->get(); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Controller/Response/Rest/Renderer/JsonTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Controller/Response/Rest/Renderer/JsonTest.php new file mode 100644 index 0000000000000000000000000000000000000000..8bb4e26a8fe889bcc0fe8511d753b74b2159062b --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Controller/Response/Rest/Renderer/JsonTest.php @@ -0,0 +1,71 @@ +<?php +/** + * Test Json Renderer for REST. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Controller_Response_Rest_Renderer_JsonTest extends PHPUnit_Framework_TestCase +{ + /** @var Mage_Webapi_Controller_Response_Rest_Renderer_Json */ + protected $_restJsonRenderer; + + /** @var Mage_Core_Helper_Data */ + protected $_helperMock; + + protected function setUp() + { + /** Prepare mocks and objects for SUT constructor. */ + $this->_helperMock = $this->getMockBuilder('Mage_Core_Helper_Data')->getMock(); + $helperFactoryMock = $this->getMock('Mage_Core_Model_Factory_Helper'); + $helperFactoryMock->expects($this->any())->method('get')->will($this->returnValue($this->_helperMock)); + /** Initialize SUT. */ + $this->_restJsonRenderer = new Mage_Webapi_Controller_Response_Rest_Renderer_Json($helperFactoryMock); + parent::setUp(); + } + + protected function tearDown() + { + unset($this->_helperMock); + unset($this->_restJsonRenderer); + parent::tearDown(); + } + + /** + * Test render method + */ + public function testRender() + { + $arrayToRender = array('key' => 'value'); + /** Assert jsonEncode method in mocked helper will run once */ + $this->_helperMock->expects($this->once())->method('jsonEncode'); + $this->_restJsonRenderer->render($arrayToRender); + } + + /** + * Test GetMimeType method + */ + public function testGetMimeType() + { + $expectedMimeType = 'application/json'; + $this->assertEquals($expectedMimeType, $this->_restJsonRenderer->getMimeType(), 'Unexpected mime type.'); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Controller/Response/Rest/Renderer/XmlTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Controller/Response/Rest/Renderer/XmlTest.php new file mode 100644 index 0000000000000000000000000000000000000000..c71113160df134740ee3ab57e4650a3188485275 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Controller/Response/Rest/Renderer/XmlTest.php @@ -0,0 +1,122 @@ +<?php +/** + * Test XML Renderer for REST. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Controller_Response_Rest_Renderer_XmlTest extends PHPUnit_Framework_TestCase +{ + /** @var Mage_Webapi_Controller_Response_Rest_Renderer_Xml */ + protected $_restXmlRenderer; + + protected function setUp() + { + /** Prepare object for SUT constructor. */ + $xmlGenerator = new Mage_Xml_Generator(); + /** Initialize SUT. */ + $this->_restXmlRenderer = new Mage_Webapi_Controller_Response_Rest_Renderer_Xml($xmlGenerator); + parent::setUp(); + } + + protected function tearDown() + { + unset($this->_restXmlRenderer); + parent::tearDown(); + } + + /** + * Test render method. + * + * @dataProvider providerXmlRender + */ + public function testRender($dataToRender, $expectedXml, $message) + { + $actualXml = $this->_restXmlRenderer->render($dataToRender); + $this->assertXmlStringEqualsXmlString($expectedXml, $actualXml, $message); + } + + /** + * Test GetMimeType method. + */ + public function testGetMimeType() + { + $exceptedMimeType = 'application/xml'; + $this->assertEquals($exceptedMimeType, $this->_restXmlRenderer->getMimeType(), 'Unexpected mime type.'); + } + + /** + * Data provider for render method testing. + * + * @return array + */ + public function providerXmlRender() + { + return array( + //Each array consist of data to render, expected XML and assert message + array( + array('value1', 'value2'), + '<?xml version="1.0"?><response><item>value1</item><item>value2</item></response>', + 'Invalid XML render of unassociated array data.' + ), + array( + array('key1' => 'value1', 'key2' => 'value2'), + '<?xml version="1.0"?><response><key1>value1</key1><key2>value2</key2></response>', + 'Invalid XML render of associated array data.' + ), + array( + (object)array('key' => 'value'), + '<?xml version="1.0"?><response><key>value</key></response>', + 'Invalid XML render of object data.' + ), + array( + array('7key' => 'value'), + '<?xml version="1.0"?><response><item_7key>value</item_7key></response>', + 'Invalid XML render with numeric symbol in data index.' + ), + array( + array('.key' => 'value'), + '<?xml version="1.0"?><response><item_.key>value</item_.key></response>', + 'Invalid XML render with "." symbol in data index.' + ), + array( + array('-key' => 'value'), + '<?xml version="1.0"?><response><item_-key>value</item_-key></response>', + 'Invalid XML render with "-" symbol in data index.' + ), + array( + array(' prefix key:' => 'value'), + '<?xml version="1.0"?><response><prefix_key>value</prefix_key></response>', + 'Invalid XML render with data key trimming.' + ), + array( + 'data', + '<?xml version="1.0"?><response><item>data</item></response>', + 'Invalid XML render with simple data.' + ), + array( + new Varien_Object(array('key' => 'value')), + '<?xml version="1.0"?><response><key>value</key></response>', + 'Invalid XML render with Varien_Object data.' + ), + ); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Controller/Response/RestTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Controller/Response/RestTest.php new file mode 100644 index 0000000000000000000000000000000000000000..c914289585559562318c808440bfbe0a3f64e7c6 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Controller/Response/RestTest.php @@ -0,0 +1,232 @@ +<?php +/** + * Test Rest response controller. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Controller_Response_RestTest extends PHPUnit_Framework_TestCase +{ + /** @var Mage_Webapi_Controller_Response_Rest */ + protected $_responseRest; + + /** @var Mage_Core_Model_App */ + protected $_appMock; + + /** @var Mage_Webapi_Controller_Response_Rest_Renderer_Xml */ + protected $_rendererMock; + + /** @var Mage_Webapi_Controller_Dispatcher_ErrorProcessor */ + protected $_errorProcessorMock; + + protected function setUp() + { + /** Mock all objects required for SUT. */ + $this->_rendererMock = $this->getMockBuilder('Mage_Webapi_Controller_Response_Rest_Renderer_Json') + ->disableOriginalConstructor()->getMock(); + $rendererFactoryMock = $this->getMockBuilder('Mage_Webapi_Controller_Response_Rest_Renderer_Factory') + ->disableOriginalConstructor()->getMock(); + $rendererFactoryMock->expects($this->any())->method('get')->will($this->returnValue($this->_rendererMock)); + $this->_errorProcessorMock = $this->getMockBuilder('Mage_Webapi_Controller_Dispatcher_ErrorProcessor') + ->disableOriginalConstructor()->getMock(); + $this->_errorProcessorMock->expects($this->once())->method('maskException')->will($this->returnArgument(0)); + $helperMock = $this->getMockBuilder('Mage_Webapi_Helper_Data')->disableOriginalConstructor()->getMock(); + $this->_appMock = $this->getMockBuilder('Mage_Core_Model_App')->disableOriginalConstructor()->getMock(); + + /** Init SUP. */ + $this->_responseRest = new Mage_Webapi_Controller_Response_Rest( + $rendererFactoryMock, + $this->_errorProcessorMock, + $helperMock, + $this->_appMock + ); + $this->_responseRest->headersSentThrowsException = false; + parent::setUp(); + } + + protected function tearDown() + { + unset($this->_responseRest); + unset($this->_appMock); + unset($this->_rendererMock); + unset($this->_errorProcessorMock); + parent::tearDown(); + } + + /** + * Test setException method with Mage_Webapi_Exception. + */ + public function testSetWebapiExceptionException() + { + /** Init Mage_Webapi_Exception */ + $apiException = new Mage_Webapi_Exception('Exception message.', 401); + $this->_responseRest->setException($apiException); + /** Assert Mage_Webapi_Exception was set and presented in the list. */ + $this->assertTrue( + $this->_responseRest->hasExceptionOfType('Mage_Webapi_Exception'), + 'Mage_Webapi_Exception was not set.' + ); + } + + /** + * Test sendResponse method with internal error exception during messages rendering. + */ + public function testSendResponseRenderMessagesException() + { + /** Init logic exception. */ + $logicException = new LogicException(); + /** Mock renderer to throw LogicException in getMimeType method. */ + $this->_rendererMock->expects($this->any())->method('getMimeType')->will( + $this->throwException($logicException) + ); + /** Assert renderException method will be executed once with specified parameters. */ + $this->_errorProcessorMock->expects($this->once())->method('renderException')->with( + $logicException, + Mage_Webapi_Exception::HTTP_INTERNAL_ERROR + ); + /** Set exception to Rest response to get in to the _renderMessages method. */ + $this->_responseRest->setException(new Mage_Webapi_Exception('Message.', 400)); + $this->_responseRest->sendResponse(); + } + + /** + * Test sendResponse method with Http Not Acceptable error exception during messages rendering. + */ + public function testSendResponseRenderMessagesHttpNotAcceptable() + { + /** Init logic exception. */ + $logicException = new LogicException('Message', Mage_Webapi_Exception::HTTP_NOT_ACCEPTABLE); + /** Mock renderer to throw LogicException in getMimeType method. */ + $this->_rendererMock->expects($this->any())->method('getMimeType')->will( + $this->throwException($logicException) + ); + /** Assert renderException method will be executed once with specified parameters. */ + $this->_errorProcessorMock->expects($this->once())->method('renderException')->with( + $logicException, + Mage_Webapi_Exception::HTTP_NOT_ACCEPTABLE + ); + /** Set exception to Rest response to get in to the _renderMessages method. */ + $this->_responseRest->setException(new Mage_Webapi_Exception('Message.', 400)); + $this->_responseRest->sendResponse(); + } + + /** + * Test sendResponse method with exception rendering. + * + * @dataProvider dataProviderForSendResponseWithException + */ + public function testSendResponseWithException($exception, $expectedResult, $assertMessage) + { + /** Mock all required objects. */ + $this->_rendererMock->expects($this->any())->method('getMimeType')->will( + $this->returnValue('application/json') + ); + $this->_rendererMock->expects($this->any())->method('render')->will( + $this->returnCallback(array($this, 'callbackForSendResponseTest'), $this->returnArgument(0)) + ); + $this->_responseRest->setException($exception); + /** Start output buffering. */ + ob_start(); + $this->_responseRest->sendResponse(); + /** Clear output buffering. */ + ob_end_clean(); + $actualResponse = $this->_responseRest->getBody(); + $this->assertEquals($expectedResult, $actualResponse, $assertMessage); + } + + /** + * Callback for testSendResponseRenderMessages method. + * + * @param $data + * @return string + */ + public function callbackForSendResponseTest($data) + { + return json_encode($data); + } + + /** + * Test sendResponse method with exception rendering. + * + * @dataProvider dataProviderForSendResponseWithExceptionInDeveloperMode + */ + public function testSendResponseWithExceptionInDeveloperMode($exception, $expectedResult, $assertMessage) + { + /** Mock all required objects. */ + $this->_rendererMock->expects($this->any())->method('getMimeType')->will( + $this->returnValue('application/json') + ); + $this->_rendererMock->expects($this->any())->method('render')->will( + $this->returnCallback(array($this, 'callbackForSendResponseTest'), $this->returnArgument(0)) + ); + $this->_appMock->expects($this->any())->method('isDeveloperMode')->will($this->returnValue(true)); + $this->_responseRest->setException($exception); + /** Start output buffering. */ + ob_start(); + $this->_responseRest->sendResponse(); + /** Clear output buffering. */ + ob_end_clean(); + $actualResponse = $this->_responseRest->getBody(); + $this->assertStringStartsWith($expectedResult, $actualResponse, $assertMessage); + } + + /** + * Data provider for testSendResponseWithException. + * + * @return array + */ + public function dataProviderForSendResponseWithException() + { + return array( + 'Mage_Webapi_Exception' => array( + new Mage_Webapi_Exception('Message', 400), + '{"messages":{"error":[{"code":400,"message":"Message"}]}}', + 'Wrong response sending with Mage_Webapi_Exception' + ), + 'Logical Exception' => array( + new LogicException('Message', 100), + '{"messages":{"error":[{"code":500,"message":"Message"}]}}', + 'Wrong response sending with Logical Exception' + ), + ); + } + + /** + * Data provider for testSendResponseWithExceptionInDeveloperMode. + * + * @return array + */ + public function dataProviderForSendResponseWithExceptionInDeveloperMode() + { + return array( + 'Mage_Webapi_Exception' => array( + new Mage_Webapi_Exception('Message', 400), + '{"messages":{"error":[{"code":400,"message":"Message","trace":"', + 'Wrong response sending with Mage_Webapi_Exception in developer mode' + ), + 'Logical Exception' => array( + new LogicException('Message'), + '{"messages":{"error":[{"code":500,"message":"Message","trace":"', + 'Wrong response sending with Logical Exception in developer mode' + ), + ); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Controller/ResponseTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Controller/ResponseTest.php new file mode 100644 index 0000000000000000000000000000000000000000..d82b9805eceb22605845a8caf65ff710e527f358 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Controller/ResponseTest.php @@ -0,0 +1,95 @@ +<?php +/** + * Test for Webapi Response model. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Controller_ResponseTest extends PHPUnit_Framework_TestCase +{ + /** + * Response object. + * + * @var Mage_Webapi_Controller_Response + */ + protected $_response; + + protected function setUp() + { + /** Initialize SUT. */ + $this->_response = new Mage_Webapi_Controller_Response(); + parent::setUp(); + } + + protected function tearDown() + { + unset($this->_response); + parent::tearDown(); + } + + /** + * Test setMimeType method. + */ + public function testSetMimeType() + { + $this->markTestIncomplete('Fix test to work with output_buffering option.'); + $expectedHeader = array( + array( + 'name' => 'Content-Type', + 'value' => 'application/xml; charset=' . Mage_Webapi_Controller_Response::RESPONSE_CHARSET, + 'replace' => true, + ), + ); + $actualHeader = $this->_response->setMimeType('application/xml')->getHeaders(); + /** Assert headers are equal */ + $this->assertEquals($expectedHeader, $actualHeader, 'Mime type is not set.'); + } + + /** + * Test addMessage, hasMessage, getMessage and clearMessages methods. + */ + public function testMessagesCrud() + { + /** Test new object does not contain any messages. */ + $this->assertFalse($this->_response->hasMessages(), 'New object contains messages.'); + + /** Test message adding functionality. */ + $this->_response->addMessage( + 'Message text', + 200, + array('key' => 'value'), + Mage_Webapi_Controller_Response::MESSAGE_TYPE_SUCCESS + ); + $this->assertTrue($this->_response->hasMessages(), 'New message is not added right.'); + + /** Test message getting functionality. */ + $expectedMessage = array( + Mage_Webapi_Controller_Response::MESSAGE_TYPE_SUCCESS => array( + array('key' => 'value', 'message' => 'Message text', 'code' => 200) + ) + ); + $this->assertEquals($expectedMessage, $this->_response->getMessages(), 'Message is got wrong.'); + + /** Test message clearing functionality. */ + $this->_response->clearMessages(); + $this->assertFalse($this->_response->hasMessages(), 'Message is not cleared.'); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Controller/Router/RestTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Controller/Router/RestTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b5d7391667bf43002dbcecb347d0aa51178e8082 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Controller/Router/RestTest.php @@ -0,0 +1,170 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Webapi + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_Webapi_Controller_Router_RestTest extends PHPUnit_Framework_TestCase +{ + /** @var Mage_Webapi_Controller_Router_Route_Rest */ + protected $_routeMock; + + /** @var Mage_Webapi_Controller_Request_Rest */ + protected $_request; + + /** @var Mage_Webapi_Helper_Data */ + protected $_helperMock; + + /** @var Mage_Webapi_Model_Config_Rest */ + protected $_apiConfigMock; + + /** @var Mage_Webapi_Controller_Router_Rest */ + protected $_router; + + protected function setUp() + { + /** Prepare mocks for SUT constructor. */ + $this->_apiConfigMock = $this->getMockBuilder('Mage_Webapi_Model_Config_Rest') + ->disableOriginalConstructor() + ->getMock(); + $interpreterFactory = $this->getMockBuilder('Mage_Webapi_Controller_Request_Rest_Interpreter_Factory') + ->disableOriginalConstructor() + ->getMock(); + $this->_helperMock = $this->getMockBuilder('Mage_Webapi_Helper_Data') + ->disableOriginalConstructor() + ->setMethods(array('__')) + ->getMock(); + $this->_helperMock->expects($this->any())->method('__')->will($this->returnArgument(0)); + $this->_routeMock = $this->getMockBuilder('Mage_Webapi_Controller_Router_Route_Rest') + ->disableOriginalConstructor() + ->setMethods(array('match')) + ->getMock(); + $this->_request = new Mage_Webapi_Controller_Request_Rest($interpreterFactory, $this->_helperMock); + /** Initialize SUT. */ + $this->_router = new Mage_Webapi_Controller_Router_Rest($this->_helperMock, $this->_apiConfigMock); + } + + protected function tearDown() + { + unset($this->_routeMock); + unset($this->_request); + unset($this->_helperMock); + unset($this->_apiConfigMock); + unset($this->_router); + parent::tearDown(); + } + + public function testMatch() + { + $this->_apiConfigMock->expects($this->once()) + ->method('getAllRestRoutes') + ->will($this->returnValue(array($this->_routeMock))); + $this->_routeMock->expects($this->once()) + ->method('match') + ->with($this->_request) + ->will($this->returnValue(array())); + + $matchedRoute = $this->_router->match($this->_request); + $this->assertEquals($this->_routeMock, $matchedRoute); + } + + /** + * @expectedException Mage_Webapi_Exception + */ + public function testNotMatch() + { + $this->_apiConfigMock->expects($this->once()) + ->method('getAllRestRoutes') + ->will($this->returnValue(array($this->_routeMock))); + $this->_routeMock + ->expects($this->once()) + ->method('match') + ->with($this->_request) + ->will($this->returnValue(false)); + + $this->_router->match($this->_request); + } + + public function testCheckRoute() + { + /** Prepare mocks for SUT constructor. */ + $checkRouteData = $this->_prepareMockDataForCheckRouteTest(); + $this->_routeMock->expects($this->once()) + ->method('match') + ->with($checkRouteData['request']) + ->will($this->returnValue(true)); + + /** Execute SUT. */ + $this->_router->checkRoute( + $checkRouteData['request'], + $checkRouteData['methodName'], + $checkRouteData['version'] + ); + } + + public function testCheckRouteException() + { + /** Prepare mocks for SUT constructor. */ + $checkRouteData = $this->_prepareMockDataForCheckRouteTest(); + $this->_routeMock->expects($this->once()) + ->method('match') + ->with($checkRouteData['request']) + ->will($this->returnValue(false)); + $this->setExpectedException( + 'Mage_Webapi_Exception', + 'Request does not match any route.', + Mage_Webapi_Exception::HTTP_NOT_FOUND + ); + /** Execute SUT. */ + $this->_router->checkRoute( + $checkRouteData['request'], + $checkRouteData['methodName'], + $checkRouteData['version'] + ); + } + + /** + * Prepare mocks for SUT constructor for testCheckRoute(). + * + * @return array + */ + protected function _prepareMockDataForCheckRouteTest() + { + $methodName = 'foo'; + $version = 'bar'; + $request = $this->getMockBuilder('Mage_Webapi_Controller_Request_Rest') + ->disableOriginalConstructor() + ->setMethods(array('getResourceName')) + ->getMock(); + $resourceName = 'Resource Name'; + $request->expects($this->once()) + ->method('getResourceName') + ->will($this->returnValue($resourceName)); + $this->_apiConfigMock->expects($this->once()) + ->method('getMethodRestRoutes') + ->with($resourceName, $methodName, $version) + ->will($this->returnValue(array($this->_routeMock))); + return array('request' => $request, 'methodName' => $methodName, 'version' => $version); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Controller/Router/Route/ApiTypeTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Controller/Router/Route/ApiTypeTest.php new file mode 100644 index 0000000000000000000000000000000000000000..58a77d0b66966b3f4415179f0d90c03a057c6fc6 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Controller/Router/Route/ApiTypeTest.php @@ -0,0 +1,43 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Webapi + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_Webapi_Controller_Router_Route_WebapiTest extends PHPUnit_Framework_TestCase +{ + public function testMatch() + { + $route = new Mage_Webapi_Controller_Router_Route_Webapi( + Mage_Webapi_Controller_Router_Route_Webapi::getApiRoute()); + + $testApiType = 'test_api'; + $testUri = str_replace(':api_type', $testApiType, Mage_Webapi_Controller_Router_Route_Webapi::getApiRoute()); + $request = new Zend_Controller_Request_Http(); + $request->setRequestUri($testUri); + + $match = $route->match($request); + $this->assertEquals($testApiType, $match['api_type']); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Controller/Router/Route/RestTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Controller/Router/Route/RestTest.php new file mode 100644 index 0000000000000000000000000000000000000000..c3639bea1c49fb01339a8cb7edd7887a35b99f17 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Controller/Router/Route/RestTest.php @@ -0,0 +1,71 @@ +<?php +/** + * Test Rest router route. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Controller_Router_Route_RestTest extends PHPUnit_Framework_TestCase +{ + /** @var Mage_Webapi_Controller_Router_Route_Rest */ + protected $_restRoute; + + protected function setUp() + { + /** Init SUT. */ + $this->_restRoute = new Mage_Webapi_Controller_Router_Route_Rest('route'); + parent::setUp(); + } + + protected function tearDown() + { + unset($this->_restRoute); + parent::tearDown(); + } + + /** + * Test setResourceName and getResourceName methods. + */ + public function testResourceName() + { + /** Assert new object has no Resource name set. */ + $this->assertNull($this->_restRoute->getResourceName(), 'New object has an set Resource name.'); + /** Set Resource name. */ + $resourceName = 'Resource name'; + $this->_restRoute->setResourceName($resourceName); + /** Assert Resource name was set. */ + $this->assertEquals($resourceName, $this->_restRoute->getResourceName(), 'Resource name is wrong.'); + } + + /** + * Test setResourceType and getResourceType methods. + */ + public function testResourceType() + { + /** Assert new object has no Resource type set. */ + $this->assertNull($this->_restRoute->getResourceType(), 'New object has an set Resource type.'); + /** Set Resource type. */ + $resourceType = 'Resource type'; + $this->_restRoute->setResourceType($resourceType); + /** Assert Resource type was set. */ + $this->assertEquals($resourceType, $this->_restRoute->getResourceType(), 'Resource type is wrong.'); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/ExceptionTest.php b/dev/tests/unit/testsuite/Mage/Webapi/ExceptionTest.php new file mode 100644 index 0000000000000000000000000000000000000000..d899a5d4e6c47d46f7771e44b1e143c30d923d5e --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/ExceptionTest.php @@ -0,0 +1,96 @@ +<?php +/** + * Test Webapi module exception. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_ExceptionTest extends PHPUnit_Framework_TestCase +{ + /** + * Test Webapi exception construct. + */ + public function testConstruct() + { + $apiException = new Mage_Webapi_Exception('Message', Mage_Webapi_Exception::HTTP_UNAUTHORIZED); + /** Assert the set Exception code. */ + $this->assertEquals( + $apiException->getCode(), + Mage_Webapi_Exception::HTTP_UNAUTHORIZED, + 'Exception code is set incorrectly in construct.' + ); + /** Assert the set Exception message. */ + $this->assertEquals( + $apiException->getMessage(), + 'Message', + 'Exception message is set incorrectly in construct.' + ); + } + + /** + * Test Webapi exception construct with invalid data. + * + * @dataProvider providerForTestConstructInvalidCode + */ + public function testConstructInvalidCode($code) + { + $this->setExpectedException('InvalidArgumentException', 'The specified code "' . $code . '" is invalid.'); + /** Create Mage_Webapi_Exception object with invalid code. */ + /** Valid codes range is from 400 to 599. */ + new Mage_Webapi_Exception('Message', $code); + } + + public function testGetOriginatorSender() + { + $apiException = new Mage_Webapi_Exception('Message', Mage_Webapi_Exception::HTTP_UNAUTHORIZED); + /** Check that Webapi Exception object with code 401 matches Sender originator.*/ + $this->assertEquals( + Mage_Webapi_Exception::ORIGINATOR_SENDER, + $apiException->getOriginator(), + 'Wrong Sender originator detecting.' + ); + } + + public function testGetOriginatorReceiver() + { + $apiException = new Mage_Webapi_Exception('Message', Mage_Webapi_Exception::HTTP_INTERNAL_ERROR); + /** Check that Webapi Exception object with code 500 matches Receiver originator.*/ + $this->assertEquals( + Mage_Webapi_Exception::ORIGINATOR_RECEIVER, + $apiException->getOriginator(), + 'Wrong Receiver originator detecting.' + ); + } + + /** + * Data provider for testConstructInvalidCode. + * + * @return array + */ + public function providerForTestConstructInvalidCode() + { + return array( + //Each array contains invalid Exception code. + array(300), + array(600), + ); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Model/Acl/Role/FactoryTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Model/Acl/Role/FactoryTest.php new file mode 100644 index 0000000000000000000000000000000000000000..44132368a50c9a31f8054de067b1b1620f773732 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Model/Acl/Role/FactoryTest.php @@ -0,0 +1,73 @@ +<?php +/** + * Test class for Mage_Webapi_Model_Acl_Role_Factory + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Acl_Role_FactoryTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Webapi_Model_Acl_Role_Factory + */ + protected $_model; + + /** + * @var Magento_ObjectManager|PHPUnit_Framework_MockObject_MockObject + */ + protected $_objectManager; + + /** + * @var Mage_Webapi_Model_Acl_Role + */ + protected $_expectedObject; + + protected function setUp() + { + $helper = new Magento_Test_Helper_ObjectManager($this); + + $this->_objectManager = $this->getMockBuilder('Magento_ObjectManager') + ->disableOriginalConstructor() + ->setMethods(array('create')) + ->getMockForAbstractClass(); + + $this->_expectedObject = $this->getMockBuilder('Mage_Webapi_Model_Acl_Role') + ->disableOriginalConstructor() + ->getMock(); + + $this->_model = $helper->getModel('Mage_Webapi_Model_Acl_Role_Factory', array( + 'objectManager' => $this->_objectManager, + )); + } + + /** + * Test create method + */ + public function testCreate() + { + $arguments = array('property' => 'value'); + $this->_objectManager->expects($this->once()) + ->method('create') + ->with('Mage_Webapi_Model_Acl_Role', $arguments) + ->will($this->returnValue($this->_expectedObject)); + $this->assertEquals($this->_expectedObject, $this->_model->create($arguments)); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Model/Acl/Role/InRoleUserUpdaterTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Model/Acl/Role/InRoleUserUpdaterTest.php new file mode 100644 index 0000000000000000000000000000000000000000..072dc681c06eeb9439b3361f7b9c4261dd278ca9 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Model/Acl/Role/InRoleUserUpdaterTest.php @@ -0,0 +1,56 @@ +<?php +/** + * Test class for Mage_Webapi_Model_Acl_Role_InRoleUserUpdater + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Acl_Role_InRoleUserUpdaterTest extends PHPUnit_Framework_TestCase +{ + public function testUpdate() + { + $roleId = 5; + $expectedValues = array(7, 8, 9); + + $helper = new Magento_Test_Helper_ObjectManager($this); + + $request = $this->getMockBuilder('Mage_Core_Controller_Request_Http') + ->disableOriginalConstructor() + ->getMock(); + $request->expects($this->any())->method('getParam')->will($this->returnValueMap(array( + array('role_id', null, $roleId) + ))); + + $userResource = $this->getMockBuilder('Mage_Webapi_Model_Resource_Acl_User') + ->disableOriginalConstructor() + ->getMock(); + $userResource->expects($this->once())->method('getRoleUsers') + ->with($roleId)->will($this->returnValue($expectedValues)); + + /** @var Mage_Webapi_Model_Acl_Role_InRoleUserUpdater $model */ + $model = $helper->getModel('Mage_Webapi_Model_Acl_Role_InRoleUserUpdater', array( + 'request' => $request, + 'userResource' => $userResource + )); + + $this->assertEquals($expectedValues, $model->update(array())); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Model/Acl/Role/UsersUpdaterTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Model/Acl/Role/UsersUpdaterTest.php new file mode 100644 index 0000000000000000000000000000000000000000..baedbf883a794e1f81db1c784b68dfe82ec8c22b --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Model/Acl/Role/UsersUpdaterTest.php @@ -0,0 +1,136 @@ +<?php +/** + * Test class for Mage_Webapi_Model_Acl_Role_UsersUpdater + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Acl_Role_UsersUpdaterTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Magento_Test_Helper_ObjectManager + */ + protected $_helper; + + /** + * @var Mage_Backend_Helper_Data|PHPUnit_Framework_MockObject_MockObject + */ + protected $_backendHelper; + + /** + * @var Mage_Core_Controller_Request_Http|PHPUnit_Framework_MockObject_MockObject + */ + protected $_request; + + /** + * @var Mage_Webapi_Model_Resource_Acl_User_Collection|PHPUnit_Framework_MockObject_MockObject + */ + protected $_collection; + + protected function setUp() + { + $this->_helper = new Magento_Test_Helper_ObjectManager($this); + + $this->_backendHelper = $this->getMockBuilder('Mage_Backend_Helper_Data') + ->disableOriginalConstructor() + ->setMethods(array('prepareFilterString')) + ->getMock(); + $this->_backendHelper->expects($this->any())->method('prepareFilterString')->will($this->returnArgument(0)); + + $this->_request = $this->getMockBuilder('Mage_Core_Controller_Request_Http') + ->disableOriginalConstructor() + ->getMock(); + $this->_collection = $this->getMockBuilder('Mage_Webapi_Model_Resource_Acl_User_Collection') + ->disableOriginalConstructor() + ->getMock(); + } + + /** + * @dataProvider updateDataProvider + * @param int $roleId + * @param array $filters + * @param bool $isAjax + * @param mixed $param + */ + public function testUpdate($roleId, $filters, $isAjax, $param) + { + $this->_request->expects($this->any())->method('getParam')->will($this->returnValueMap(array( + array('role_id', null, $roleId), + array('filter', '', $filters), + ))); + $this->_request->expects($this->any())->method('isAjax')->will($this->returnValue($isAjax)); + + if ($param) { + $this->_collection->expects($this->once())->method('addFieldToFilter')->with('role_id', $param); + } else { + $this->_collection->expects($this->never())->method('addFieldToFilter'); + } + + /** @var Mage_Webapi_Model_Acl_Role_UsersUpdater $model */ + $model = $this->_helper->getModel('Mage_Webapi_Model_Acl_Role_UsersUpdater', array( + 'request' => $this->_request, + 'backendHelper' => $this->_backendHelper + )); + $this->assertEquals($this->_collection, $model->update($this->_collection)); + } + + /** + * @return array + */ + public function updateDataProvider() + { + return array( + 'Yes' => array( + 3, + array('in_role_users' => 1), + true, + 3 + ), + 'No' => array( + 4, + array('in_role_users' => 0), + true, + array( + array('neq' => 4), + array('is' => 'NULL') + ) + ), + 'Any' => array( + 5, + array(), + true, + null + ), + 'Yes_on_ajax' => array( + 6, + array(), + false, + 6 + ), + 'Any_without_role_id' => array( + null, + array('in_role_users' => 1), + true, + null + ) + ); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Model/Acl/RoleTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Model/Acl/RoleTest.php new file mode 100644 index 0000000000000000000000000000000000000000..1c50f484aa7d910a6dc8ede57af4e89b1bee2daf --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Model/Acl/RoleTest.php @@ -0,0 +1,118 @@ +<?php +/** + * Test class for Mage_Webapi_Model_Acl_User + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Acl_RoleTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Magento_Test_Helper_ObjectManager + */ + protected $_helper; + + /** + * @var Magento_ObjectManager|PHPUnit_Framework_MockObject_MockObject + */ + protected $_objectManager; + + /** + * @var Mage_Webapi_Model_Resource_Acl_Role|PHPUnit_Framework_MockObject_MockObject + */ + protected $_roleResource; + + protected function setUp() + { + $this->_helper = new Magento_Test_Helper_ObjectManager($this); + + $this->_objectManager = $this->getMockBuilder('Magento_ObjectManager') + ->disableOriginalConstructor() + ->setMethods(array('create')) + ->getMockForAbstractClass(); + + $this->_roleResource = $this->getMockBuilder('Mage_Webapi_Model_Resource_Acl_Role') + ->disableOriginalConstructor() + ->setMethods(array('getIdFieldName', 'getReadConnection')) + ->getMock(); + + $this->_roleResource->expects($this->any()) + ->method('getIdFieldName') + ->withAnyParameters() + ->will($this->returnValue('id')); + + $this->_roleResource->expects($this->any()) + ->method('getReadConnection') + ->withAnyParameters() + ->will($this->returnValue($this->getMock('Varien_Db_Adapter_Pdo_Mysql', array(), array(), '', false))); + } + + /** + * Create Role model + * + * @param Mage_Webapi_Model_Resource_Acl_Role $roleResource + * @param Mage_Webapi_Model_Resource_Acl_Role_Collection $resourceCollection + * @return Mage_Webapi_Model_Acl_Role + */ + protected function _createModel($roleResource, $resourceCollection = null) + { + return $this->_helper->getModel('Mage_Webapi_Model_Acl_Role', array( + 'eventDispatcher' => $this->getMock('Mage_Core_Model_Event_Manager', array(), array(), '', false), + 'cacheManager' => $this->getMock('Mage_Core_Model_Cache', array(), array(), '', false), + 'resource' => $roleResource, + 'resourceCollection' => $resourceCollection + )); + } + + /** + * Test constructor + */ + public function testConstructor() + { + $model = $this->_createModel($this->_roleResource); + + $this->assertAttributeEquals('Mage_Webapi_Model_Resource_Acl_Role', '_resourceName', $model); + $this->assertAttributeEquals('id', '_idFieldName', $model); + } + + /** + * Test get collection and _construct + */ + public function testGetCollection() + { + /** @var Mage_Webapi_Model_Resource_Acl_Role_Collection $collection */ + $collection = $this->getMockBuilder('Mage_Webapi_Model_Resource_Acl_Role_Collection') + ->setConstructorArgs(array('resource' => $this->_roleResource)) + ->setMethods(array('_initSelect')) + ->getMock(); + + $collection->expects($this->any()) + ->method('_initSelect') + ->withAnyParameters() + ->will($this->returnValue(null)); + + $model = $this->_createModel($this->_roleResource, $collection); + $result = $model->getCollection(); + + $this->assertAttributeEquals('Mage_Webapi_Model_Acl_Role', '_model', $result); + $this->assertAttributeEquals('Mage_Webapi_Model_Resource_Acl_Role', '_resourceModel', $result); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Model/Acl/RuleTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Model/Acl/RuleTest.php new file mode 100644 index 0000000000000000000000000000000000000000..0a2074843976505309122b09900a0291917a9016 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Model/Acl/RuleTest.php @@ -0,0 +1,144 @@ +<?php +/** + * Test class for Mage_Webapi_Model_Acl_Rule + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Acl_RuleTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Magento_Test_Helper_ObjectManager + */ + protected $_helper; + + /** + * @var Magento_ObjectManager|PHPUnit_Framework_MockObject_MockObject + */ + protected $_objectManager; + + /** + * @var Mage_Webapi_Model_Resource_Acl_Rule|PHPUnit_Framework_MockObject_MockObject + */ + protected $_ruleResource; + + protected function setUp() + { + $this->_helper = new Magento_Test_Helper_ObjectManager($this); + + $this->_objectManager = $this->getMockBuilder('Magento_ObjectManager') + ->disableOriginalConstructor() + ->setMethods(array('create')) + ->getMockForAbstractClass(); + + $this->_ruleResource = $this->getMockBuilder('Mage_Webapi_Model_Resource_Acl_Rule') + ->disableOriginalConstructor() + ->setMethods(array('saveResources', 'getIdFieldName', 'getReadConnection')) + ->getMock(); + + $this->_ruleResource->expects($this->any()) + ->method('getIdFieldName') + ->withAnyParameters() + ->will($this->returnValue('id')); + + $this->_ruleResource->expects($this->any()) + ->method('getReadConnection') + ->withAnyParameters() + ->will($this->returnValue($this->getMock('Varien_Db_Adapter_Pdo_Mysql', array(), array(), '', false))); + } + + /** + * Create Rule model + * + * @param Mage_Webapi_Model_Resource_Acl_Rule|PHPUnit_Framework_MockObject_MockObject $ruleResource + * @param Mage_Webapi_Model_Resource_Acl_User_Collection $resourceCollection + * @return Mage_Webapi_Model_Acl_Rule + */ + protected function _createModel($ruleResource, $resourceCollection = null) + { + return $this->_helper->getModel('Mage_Webapi_Model_Acl_Rule', array( + 'eventDispatcher' => $this->getMock('Mage_Core_Model_Event_Manager', array(), array(), '', false), + 'cacheManager' => $this->getMock('Mage_Core_Model_Cache', array(), array(), '', false), + 'resource' => $ruleResource, + 'resourceCollection' => $resourceCollection + )); + } + + /** + * Test constructor + */ + public function testConstructor() + { + $model = $this->_createModel($this->_ruleResource); + + $this->assertAttributeEquals('Mage_Webapi_Model_Resource_Acl_Rule', '_resourceName', $model); + $this->assertAttributeEquals('id', '_idFieldName', $model); + } + + /** + * Test method getRoleUsers() + */ + public function testGetRoleUsers() + { + $this->_ruleResource->expects($this->once()) + ->method('saveResources') + ->withAnyParameters() + ->will($this->returnSelf()); + + $model = $this->_createModel($this->_ruleResource); + $result = $model->saveResources(); + $this->assertInstanceOf('Mage_Webapi_Model_Acl_Rule', $result); + } + + /** + * Test get collection and _construct + */ + public function testGetCollection() + { + /** @var Mage_Webapi_Model_Resource_Acl_Rule_Collection $collection */ + $collection = $this->getMockBuilder('Mage_Webapi_Model_Resource_Acl_Rule_Collection') + ->setConstructorArgs(array('resource' => $this->_ruleResource)) + ->setMethods(array('_initSelect', 'getSelect')) + ->getMock(); + + $collection->expects($this->any()) + ->method('_initSelect') + ->withAnyParameters() + ->will($this->returnValue(null)); + + $collection->expects($this->any()) + ->method('getSelect') + ->withAnyParameters() + ->will($this->returnValue($this->getMock('Varien_Db_Select', array(), array(), '', false))); + + $model = $this->_createModel($this->_ruleResource, $collection); + + // test _construct + $result = $model->getCollection(); + + $this->assertAttributeEquals('Mage_Webapi_Model_Acl_Rule', '_model', $result); + $this->assertAttributeEquals('Mage_Webapi_Model_Resource_Acl_Rule', '_resourceModel', $result); + + // test getByRole + $resultColl = $result->getByRole(1); + $this->assertInstanceOf('Mage_Webapi_Model_Resource_Acl_Rule_Collection', $resultColl); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Model/Acl/User/FactoryTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Model/Acl/User/FactoryTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b99a3c009600da34ef9d276ef9cbeeef10cbb1a5 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Model/Acl/User/FactoryTest.php @@ -0,0 +1,73 @@ +<?php +/** + * Test class for Mage_Webapi_Model_Acl_User_Factory + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Acl_User_FactoryTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Webapi_Model_Acl_User_Factory + */ + protected $_model; + + /** + * @var Magento_ObjectManager|PHPUnit_Framework_MockObject_MockObject + */ + protected $_objectManager; + + /** + * @var Mage_Webapi_Model_Acl_User + */ + protected $_expectedObject; + + protected function setUp() + { + $helper = new Magento_Test_Helper_ObjectManager($this); + + $this->_objectManager = $this->getMockBuilder('Magento_ObjectManager') + ->disableOriginalConstructor() + ->setMethods(array('create')) + ->getMockForAbstractClass(); + + $this->_expectedObject = $this->getMockBuilder('Mage_Webapi_Model_Acl_User') + ->disableOriginalConstructor() + ->getMock(); + + $this->_model = $helper->getModel('Mage_Webapi_Model_Acl_User_Factory', array( + 'objectManager' => $this->_objectManager, + )); + } + + /** + * Test create method + */ + public function testCreate() + { + $arguments = array('property' => 'value'); + $this->_objectManager->expects($this->once()) + ->method('create') + ->with('Mage_Webapi_Model_Acl_User', $arguments) + ->will($this->returnValue($this->_expectedObject)); + $this->assertEquals($this->_expectedObject, $this->_model->create($arguments)); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Model/Acl/User/RoleUpdaterTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Model/Acl/User/RoleUpdaterTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b6617bf372d9d6244493b1aeb50b29b765764253 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Model/Acl/User/RoleUpdaterTest.php @@ -0,0 +1,66 @@ +<?php +/** + * Test class for Mage_Webapi_Model_Acl_User_RoleUpdater + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Acl_User_RoleUpdaterrTest extends PHPUnit_Framework_TestCase +{ + public function testUpdate() + { + $userId = 5; + $expectedRoleId = 3; + + $helper = new Magento_Test_Helper_ObjectManager($this); + + $request = $this->getMockBuilder('Mage_Core_Controller_Request_Http') + ->disableOriginalConstructor() + ->getMock(); + $request->expects($this->any())->method('getParam')->will($this->returnValueMap(array( + array('user_id', null, $userId) + ))); + + $userModel = $this->getMockBuilder('Mage_Webapi_Model_Acl_User') + ->setMethods(array('getRoleId', 'load')) + ->disableOriginalConstructor() + ->getMock(); + $userModel->expects($this->once())->method('load') + ->with($userId, null)->will($this->returnSelf()); + $userModel->expects($this->once())->method('getRoleId') + ->with()->will($this->returnValue($expectedRoleId)); + + $userFactory = $this->getMockBuilder('Mage_Webapi_Model_Acl_User_Factory') + ->setMethods(array('create')) + ->disableOriginalConstructor() + ->getMock(); + $userFactory->expects($this->once())->method('create') + ->with(array())->will($this->returnValue($userModel)); + + /** @var Mage_Webapi_Model_Acl_Role_InRoleUserUpdater $model */ + $model = $helper->getModel('Mage_Webapi_Model_Acl_User_RoleUpdater', array( + 'request' => $request, + 'userFactory' => $userFactory + )); + + $this->assertEquals($expectedRoleId, $model->update(array())); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Model/Acl/UserTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Model/Acl/UserTest.php new file mode 100644 index 0000000000000000000000000000000000000000..030676604c11c8d7fb8d3d2eca6380ac40234a0f --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Model/Acl/UserTest.php @@ -0,0 +1,164 @@ +<?php +/** + * Test class for Mage_Webapi_Model_Acl_User + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Acl_UserTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Magento_Test_Helper_ObjectManager + */ + protected $_helper; + + /** + * @var Magento_ObjectManager|PHPUnit_Framework_MockObject_MockObject + */ + protected $_objectManager; + + /** + * @var Mage_Webapi_Model_Resource_Acl_User|PHPUnit_Framework_MockObject_MockObject + */ + protected $_userResource; + + protected function setUp() + { + $this->_helper = new Magento_Test_Helper_ObjectManager($this); + + $this->_objectManager = $this->getMockBuilder('Magento_ObjectManager') + ->disableOriginalConstructor() + ->setMethods(array('create')) + ->getMockForAbstractClass(); + + $this->_userResource = $this->getMockBuilder('Mage_Webapi_Model_Resource_Acl_User') + ->disableOriginalConstructor() + ->setMethods(array('getIdFieldName', 'getRoleUsers', 'load', 'getReadConnection')) + ->getMock(); + + $this->_userResource->expects($this->any()) + ->method('getIdFieldName') + ->withAnyParameters() + ->will($this->returnValue('id')); + + $this->_userResource->expects($this->any()) + ->method('getReadConnection') + ->withAnyParameters() + ->will($this->returnValue($this->getMock('Varien_Db_Adapter_Pdo_Mysql', array(), array(), '', false))); + } + + /** + * Create User model + * + * @param Mage_Webapi_Model_Resource_Acl_User $userResource + * @param Mage_Webapi_Model_Resource_Acl_User_Collection $resourceCollection + * @return Mage_Webapi_Model_Acl_User + */ + protected function _createModel($userResource, $resourceCollection = null) + { + return $this->_helper->getModel('Mage_Webapi_Model_Acl_User', array( + 'eventDispatcher' => $this->getMock('Mage_Core_Model_Event_Manager', array(), array(), '', false), + 'cacheManager' => $this->getMock('Mage_Core_Model_Cache', array(), array(), '', false), + 'resource' => $userResource, + 'resourceCollection' => $resourceCollection + )); + } + + /** + * Test constructor + */ + public function testConstructor() + { + $model = $this->_createModel($this->_userResource); + + $this->assertAttributeEquals('Mage_Webapi_Model_Resource_Acl_User', '_resourceName', $model); + $this->assertAttributeEquals('id', '_idFieldName', $model); + } + + /** + * Test method getRoleUsers() + */ + public function testGetRoleUsers() + { + $this->_userResource->expects($this->once()) + ->method('getRoleUsers') + ->with(1) + ->will($this->returnValue(array(1))); + + $model = $this->_createModel($this->_userResource); + + $result = $model->getRoleUsers(1); + + $this->assertEquals(array(1), $result); + } + + /** + * Test method loadByKey() + */ + public function testLoadByKey() + { + $this->_userResource->expects($this->once()) + ->method('load') + ->with($this->anything(), 'key', 'api_key') + ->will($this->returnSelf()); + + $model = $this->_createModel($this->_userResource); + + $result = $model->loadByKey('key'); + $this->assertInstanceOf('Mage_Webapi_Model_Acl_User', $result); + } + + /** + * Test public getters + */ + public function testPublicGetters() + { + $model = $this->_createModel($this->_userResource); + + $model->setData('secret', 'secretKey'); + + $this->assertEquals('secretKey', $model->getSecret()); + $this->assertEquals('', $model->getCallBackUrl()); + } + + /** + * Test get collection and _construct + */ + public function testGetCollection() + { + /** @var Mage_Webapi_Model_Resource_Acl_User_Collection $collection */ + $collection = $this->getMockBuilder('Mage_Webapi_Model_Resource_Acl_User_Collection') + ->setConstructorArgs(array('resource' => $this->_userResource)) + ->setMethods(array('_initSelect')) + ->getMock(); + + $collection->expects($this->any()) + ->method('_initSelect') + ->withAnyParameters() + ->will($this->returnValue(null)); + + $model = $this->_createModel($this->_userResource, $collection); + $result = $model->getCollection(); + + $this->assertAttributeEquals('Mage_Webapi_Model_Acl_User', '_model', $result); + $this->assertAttributeEquals('Mage_Webapi_Model_Resource_Acl_User', '_resourceModel', $result); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Model/Authorization/Config/ReaderFactoryTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Model/Authorization/Config/ReaderFactoryTest.php new file mode 100644 index 0000000000000000000000000000000000000000..d329c6615ec61253e2ad5df7b49f2ae54709fcd1 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Model/Authorization/Config/ReaderFactoryTest.php @@ -0,0 +1,68 @@ +<?php +/** + * Test class for Mage_Webapi_Model_Authorization_Config_Reader_Factory + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Authorization_Config_Reader_FactoryTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Webapi_Model_Authorization_Config_Reader_Factory + */ + protected $_model; + + /** + * @var Magento_ObjectManager + */ + protected $_objectManager; + + /** + * @var Mage_Webapi_Model_Authorization_Config_Reader + */ + protected $_expectedObject; + + protected function setUp() + { + $helper = new Magento_Test_Helper_ObjectManager($this); + + $this->_objectManager = $this->getMockForAbstractClass('Magento_ObjectManager', array(), '', true, true, true, + array('create')); + + $this->_expectedObject = $this->getMock('Mage_Webapi_Model_Authorization_Config_Reader', array(), array(), '', + false); + + $this->_model = $helper->getModel('Mage_Webapi_Model_Authorization_Config_Reader_Factory', array( + 'objectManager' => $this->_objectManager, + )); + } + + public function testCreateReader() + { + $arguments = array('5', '6'); + + $this->_objectManager->expects($this->once()) + ->method('create') + ->with('Mage_Webapi_Model_Authorization_Config_Reader', $arguments, false) + ->will($this->returnValue($this->_expectedObject)); + $this->assertEquals($this->_expectedObject, $this->_model->createReader($arguments)); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Model/Authorization/Config/ReaderTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Model/Authorization/Config/ReaderTest.php new file mode 100644 index 0000000000000000000000000000000000000000..85933c95a6c10aab2c6eb13fea13960e95337fb7 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Model/Authorization/Config/ReaderTest.php @@ -0,0 +1,64 @@ +<?php +/** + * Test class for Mage_Webapi_Model_Authorization_Config_Reader + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Authorization_Config_ReaderTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Webapi_Model_Authorization_Config_Reader + */ + protected $_reader; + + /** + * Initialize reader instance + */ + protected function setUp() + { + $path = array(__DIR__, '..', '..', '_files', 'acl.xml'); + $path = realpath(implode(DIRECTORY_SEPARATOR, $path)); + $this->_reader = new Mage_Webapi_Model_Authorization_Config_Reader(array($path)); + } + + /** + * Unset reader instance + */ + protected function tearDown() + { + unset($this->_reader); + } + + /** + * Check that correct xsd file is provided + */ + public function testGetSchemaFile() + { + $xsdPath = array(__DIR__, '..', '..', '_files', 'acl.xsd'); + $xsdPath = realpath(implode(DIRECTORY_SEPARATOR, $xsdPath)); + $actualXsdPath = $this->_reader->getSchemaFile(); + + $this->assertInternalType('string', $actualXsdPath); + $this->assertFileExists($actualXsdPath); + $this->assertXmlFileEqualsXmlFile($xsdPath, $actualXsdPath); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Model/Authorization/ConfigTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Model/Authorization/ConfigTest.php new file mode 100644 index 0000000000000000000000000000000000000000..81678a4c3d0c5104ece8f60273c6769b0a853f4d --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Model/Authorization/ConfigTest.php @@ -0,0 +1,302 @@ +<?php +/** + * Test class for Mage_Webapi_Model_Authorization_Config + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Authorization_ConfigTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Webapi_Model_Authorization_Config + */ + protected $_model; + + /** + * @var Magento_Acl_Config_Reader|PHPUnit_Framework_MockObject_MockObject + */ + protected $_configReader; + + /** + * @var Mage_Webapi_Model_Authorization_Config_Reader_Factory|PHPUnit_Framework_MockObject_MockObject + */ + protected $_readerFactory; + + /** + * @var Mage_Core_Model_Config|PHPUnit_Framework_MockObject_MockObject + */ + protected $_config; + + /** + * Set up before test + */ + protected function setUp() + { + $helper = new Magento_Test_Helper_ObjectManager($this); + + $this->_config = $this->getMockBuilder('Mage_Core_Model_Config') + ->disableOriginalConstructor() + ->setMethods(array('getModuleConfigurationFiles')) + ->getMock(); + + $this->_readerFactory = $this->getMockBuilder('Mage_Webapi_Model_Authorization_Config_Reader_Factory') + ->disableOriginalConstructor() + ->setMethods(array('createReader')) + ->getMock(); + + $this->_configReader = $this->getMockBuilder('Magento_Acl_Config_Reader') + ->disableOriginalConstructor() + ->setMethods(array('getAclResources')) + ->getMock(); + + $this->_model = $helper->getModel('Mage_Webapi_Model_Authorization_Config', array( + 'config' => $this->_config, + 'readerFactory' => $this->_readerFactory + )); + + $this->_config->expects($this->any()) + ->method('getModuleConfigurationFiles') + ->will($this->returnValue(array())); + + $this->_readerFactory->expects($this->any()) + ->method('createReader') + ->will($this->returnValue($this->_configReader)); + } + + /** + * Test for Mage_Webapi_Model_Authorization_Config::getAclResources() + */ + public function testGetAclResources() + { + $aclResources = new DOMDocument(); + $aclResources->load(__DIR__ . DIRECTORY_SEPARATOR . '..' + . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'acl.xml'); + $this->_configReader->expects($this->once()) + ->method('getAclResources') + ->will($this->returnValue($aclResources)); + + $expectedResources = array( + 'Mage_Webapi', + 'customer', + 'customer/create', + 'customer/delete', + 'customer/get', + 'customer/update' + ); + $resources = $this->_model->getAclResources(); + + $this->assertInstanceOf('DOMNodeList', $resources); + $actualResources = $this->getResources($resources); + sort($expectedResources); + sort($actualResources); + $this->assertEquals($expectedResources, $actualResources); + } + + /** + * Get resources array recursively + * + * @param DOMNodeList $resources + * @return array + */ + public function getResources($resources) + { + $resourceArray = array(); + /** @var $resource DOMElement */ + foreach ($resources as $resource) { + if (!($resource instanceof DOMElement)) { + continue; + } + $resourceArray = array_merge($resourceArray, array($resource->getAttribute('id'))); + if ($resource->hasChildNodes()) { + $resourceArray = array_merge($resourceArray, $this->getResources($resource->childNodes)); + } + } + return $resourceArray; + } + + /** + * Test for Mage_Webapi_Model_Authorization_Config::getAclVirtualResources + */ + public function testGetAclVirtualResources() + { + $aclResources = new DOMDocument(); + $aclResources->load(__DIR__ . DIRECTORY_SEPARATOR . '..' + . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'acl.xml'); + $this->_configReader->expects($this->once()) + ->method('getAclResources') + ->will($this->returnValue($aclResources)); + + $expectedResources = array(array( + 'id' => 'customer/list', + 'parent' => 'customer/get' + )); + $resources = $this->_model->getAclVirtualResources(); + + $this->assertInstanceOf('DOMNodeList', $resources); + $actualResources = array(); + foreach ($resources as $resourceConfig) { + if (!($resourceConfig instanceof DOMElement)) { + continue; + } + $actualResources[] = array( + 'id' => $resourceConfig->getAttribute('id'), + 'parent' => $resourceConfig->getAttribute('parent') + ); + } + sort($expectedResources); + sort($actualResources); + $this->assertEquals($expectedResources, $actualResources); + } + + /** + * Test for Mage_Webapi_Model_Authorization_Config::getAclResourcesAsArray + * + * @dataProvider aclResourcesDataProvider + * @param string $actualXmlFile + * @param bool $includeRoot + * @param array $expectedResources + */ + public function testGetAclResourcesAsArray($actualXmlFile, $includeRoot, $expectedResources) + { + $actualAclResources = new DOMDocument(); + $actualAclResources->load($actualXmlFile); + + $this->_configReader->expects($this->once()) + ->method('getAclResources') + ->will($this->returnValue($actualAclResources)); + + $this->assertEquals($expectedResources, $this->_model->getAclResourcesAsArray($includeRoot)); + } + + /** + * @return array + */ + public function aclResourcesDataProvider() + { + $aclResourcesArray = array ( + 'id' => 'Mage_Webapi', + 'text' => '', + 'children' => array( + array( + 'id' => 'customer', + 'text' => 'Manage Customers', + 'sortOrder' => 20, + 'children' => array( + array( + 'id' => 'customer/update', + 'text' => 'Edit Customer', + 'sortOrder' => 10, + 'children' => array(), + ), + array( + 'id' => 'customer/get', + 'text' => 'Get Customer', + 'sortOrder' => 20, + 'children' => array(), + ), + array( + 'id' => 'customer/create', + 'text' => 'Create Customer', + 'sortOrder' => 30, + 'children' => array(), + ), + array( + 'id' => 'customer/delete', + 'text' => 'Delete Customer', + 'children' => array(), + ), + ), + ), + ), + ); + return array( + array( + 'actualXmlFile' => __DIR__ . DIRECTORY_SEPARATOR . '..' + . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'acl.xml', + 'includeRoot' => true, + 'expectedResources' => $aclResourcesArray + ), + array( + 'actualXmlFile' =>__DIR__ . DIRECTORY_SEPARATOR . '..' + . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'acl.xml', + 'includeRoot' => false, + 'expectedResources' => $aclResourcesArray['children'], + ) + ); + } + + /** + * Test for method _getSortedBySortOrder + * + * @dataProvider getSortedBySortOrderDataProvider + * @param array $originArray + * @param array $sortedArray + */ + public function testGetSortedBySortOrder($originArray, $sortedArray) + { + $methodReflection = new ReflectionMethod($this->_model, '_getSortedBySortOrder'); + $methodReflection->setAccessible(true); + $this->assertEquals($sortedArray, $methodReflection->invoke($this->_model, $originArray)); + } + + /** + * @return array + */ + public function getSortedBySortOrderDataProvider() + { + return array( + array( + array( + array('name' => 'A', 'sortOrder' => 2), + array('name' => 'B', 'sortOrder' => 1), + array('name' => 'C', 'sortOrder' => 1), + array('name' => 'D', 'sortOrder' => 1), + array('name' => 'E', 'sortOrder' => 0) + ), + array( + array('name' => 'E', 'sortOrder' => 0), + array('name' => 'B', 'sortOrder' => 1), + array('name' => 'C', 'sortOrder' => 1), + array('name' => 'D', 'sortOrder' => 1), + array('name' => 'A', 'sortOrder' => 2), + ) + ), + array( + array( + array('name' => 'A'), + array('name' => 'B'), + array('name' => 'C', 'sortOrder' => 1), + array('name' => 'D'), + array('name' => 'E'), + array('name' => 'F', 'sortOrder' => -1) + ), + array( + array('name' => 'F', 'sortOrder' => -1), + array('name' => 'C', 'sortOrder' => 1), + array('name' => 'A'), + array('name' => 'B'), + array('name' => 'D'), + array('name' => 'E'), + ) + ) + ); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Model/Authorization/Loader/ResourceTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Model/Authorization/Loader/ResourceTest.php new file mode 100644 index 0000000000000000000000000000000000000000..28265c8f6f0d54d8ebe8779d7c4d463fb95471f8 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Model/Authorization/Loader/ResourceTest.php @@ -0,0 +1,138 @@ +<?php +/** + * Test class for Mage_Webapi_Model_Authorization_Loader_Resource + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Authorization_Loader_ResourceTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Webapi_Model_Authorization_Loader_Resource + */ + protected $_model; + + /** + * @var Magento_Acl + */ + protected $_acl; + + /** + * @var Magento_Test_Helper_ObjectManager + */ + protected $_helper; + + /** + * @var Mage_Webapi_Model_Authorization_Config + */ + protected $_config; + + /** + * Set up before test + */ + protected function setUp() + { + $this->_helper = new Magento_Test_Helper_ObjectManager($this); + + $resource = new Magento_Acl_Resource('test resource'); + + /** @var $resourceFactory Magento_Acl_ResourceFactory */ + $resourceFactory = $this->getMock('Magento_Acl_ResourceFactory', + array('createResource'), array(), '', false); + $resourceFactory->expects($this->any()) + ->method('createResource') + ->will($this->returnValue($resource)); + + $this->_config = $this->getMock('Mage_Webapi_Model_Authorization_Config', + array('getAclResources', 'getAclVirtualResources'), array(), '', false); + $this->_config->expects($this->once()) + ->method('getAclResources') + ->will($this->returnValue($this->getResourceXPath()->query('/config/acl/resources/*'))); + + $this->_model = $this->_helper->getModel('Mage_Webapi_Model_Authorization_Loader_Resource', array( + 'resourceFactory' => $resourceFactory, + 'configuration' => $this->_config, + )); + + $this->_acl = $this->getMock('Magento_Acl', array('has', 'addResource', 'deny', 'getResources'), array(), '', + false); + } + + /** + * Test for Mage_Webapi_Model_Authorization_Loader_Resource::populateAcl + */ + public function testPopulateAcl() + { + $this->_config->expects($this->once()) + ->method('getAclVirtualResources') + ->will($this->returnValue($this->getResourceXPath()->query('/config/mapping/*'))); + + $this->_acl->expects($this->once()) + ->method('getResources') + ->will($this->returnValue(array('customer/get', 'customer/create'))); + $this->_acl->expects($this->exactly(2)) + ->method('deny') + ->with(null, $this->logicalOr('customer/get', 'customer/create')); + $this->_acl->expects($this->exactly(2)) + ->method('has') + ->with($this->logicalOr('customer/get', 'customer/list')) + ->will($this->returnValueMap(array( + array('customer/get', true), + array('customer/list', false) + ))); + $this->_acl->expects($this->exactly(7)) + ->method('addResource'); + + $this->_model->populateAcl($this->_acl); + } + + /** + * Test for Mage_Webapi_Model_Authorization_Loader_Resource::populateAcl with invalid Virtual resources DOM + */ + public function testPopulateAclWithInvalidDOM() + { + $this->_config->expects($this->once()) + ->method('getAclVirtualResources') + ->will($this->returnValue(array(3))); + + $this->_acl->expects($this->once()) + ->method('getResources') + ->will($this->returnValue(array('customer/get', 'customer/list'))); + $this->_acl->expects($this->exactly(2)) + ->method('deny') + ->with(null, $this->logicalOr('customer/get', 'customer/list')); + + $this->_model->populateAcl($this->_acl); + } + + /** + * Get Resources DOMXPath from fixture + * + * @return DOMXPath + */ + public function getResourceXPath() + { + $aclResources = new DOMDocument(); + $aclResources->load(__DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' + . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'acl.xml'); + return new DOMXPath($aclResources); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Model/Authorization/Loader/RoleTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Model/Authorization/Loader/RoleTest.php new file mode 100644 index 0000000000000000000000000000000000000000..0c07eab6bea437eff34e6090405dae05bbcba3f1 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Model/Authorization/Loader/RoleTest.php @@ -0,0 +1,125 @@ +<?php +/** + * Test class for Mage_Webapi_Model_Authorization_Loader_Role + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Authorization_Loader_RoleTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Webapi_Model_Resource_Acl_Role + */ + protected $_resourceModelMock; + + /** + * @var Mage_Webapi_Model_Authorization_Loader_Role + */ + protected $_model; + + /** + * @var Mage_Webapi_Model_Authorization_Role_Factory + */ + protected $_roleFactory; + + /** + * @var Magento_Acl + */ + protected $_acl; + + /** + * Set up before test + */ + protected function setUp() + { + $helper = new Magento_Test_Helper_ObjectManager($this); + + $this->_resourceModelMock = $this->getMock('Mage_Webapi_Model_Resource_Acl_Role', + array('getRolesIds'), array(), '', false); + + $this->_roleFactory = $this->getMock('Mage_Webapi_Model_Authorization_Role_Factory', + array('createRole'), array(), '', false); + + $this->_acl = $this->getMock('Magento_Acl', array('addRole', 'deny'), array(), '', + false); + + $this->_model = $helper->getModel('Mage_Webapi_Model_Authorization_Loader_Role', array( + 'roleResource' => $this->_resourceModelMock, + 'roleFactory' => $this->_roleFactory, + )); + } + + /** + * Test for Mage_Webapi_Model_Authorization_Loader_Role::populateAcl + * + * Test with existing role Ids + */ + public function testPopulateAclWithRoles() + { + $roleOne = new Mage_Webapi_Model_Authorization_Role(3); + $roleTwo = new Mage_Webapi_Model_Authorization_Role(4); + $roleIds = array(3, 4); + $createRoleMap = array( + array(array(3), $roleOne), + array(array(4), $roleTwo), + ); + $this->_resourceModelMock->expects($this->once()) + ->method('getRolesIds') + ->will($this->returnValue($roleIds)); + + $this->_roleFactory->expects($this->exactly(count($roleIds))) + ->method('createRole') + ->will($this->returnValueMap($createRoleMap)); + + $this->_acl->expects($this->exactly(count($roleIds))) + ->method('addRole') + ->with($this->logicalOr($roleOne, $roleTwo)); + + $this->_acl->expects($this->exactly(count($roleIds))) + ->method('deny') + ->with($this->logicalOr($roleOne, $roleTwo)); + + $this->_model->populateAcl($this->_acl); + } + + /** + * Test for Mage_Webapi_Model_Authorization_Loader_Role::populateAcl + * + * Test with No existing role Ids + */ + public function testPopulateAclWithNoRoles() + { + $this->_resourceModelMock->expects($this->once()) + ->method('getRolesIds') + ->will($this->returnValue(array())); + + $this->_roleFactory->expects($this->never()) + ->method('createRole'); + + $this->_acl->expects($this->never()) + ->method('addRole'); + + $this->_acl->expects($this->never()) + ->method('deny'); + + $this->_model->populateAcl($this->_acl); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Model/Authorization/Loader/RuleTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Model/Authorization/Loader/RuleTest.php new file mode 100644 index 0000000000000000000000000000000000000000..9a6ac9d9433c31cbeb5ce3100a6abadf39435f70 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Model/Authorization/Loader/RuleTest.php @@ -0,0 +1,117 @@ +<?php +/** + * Test class for Mage_Webapi_Model_Authorization_Loader_Rule + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Authorization_Loader_RuleTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Webapi_Model_Resource_Acl_Rule + */ + protected $_ruleResource; + + /** + * @var Mage_Webapi_Model_Authorization_Loader_Rule + */ + protected $_model; + + /** + * @var Magento_Acl + */ + protected $_acl; + + /** + * Set up before test + */ + protected function setUp() + { + $helper = new Magento_Test_Helper_ObjectManager($this); + + $this->_ruleResource = $this->getMock('Mage_Webapi_Model_Resource_Acl_Rule', + array('getRuleList'), array(), '', false); + + $this->_acl = $this->getMock('Magento_Acl', array('has', 'hasRole', 'allow'), array(), '', false); + + $this->_model = $helper->getModel('Mage_Webapi_Model_Authorization_Loader_Rule', array( + 'ruleResource' => $this->_ruleResource, + )); + } + + /** + * Test for Mage_Webapi_Model_Authorization_Loader_Rule::populateAcl + */ + public function testPopulateAcl() + { + $ruleList = array( + array('role_id' => 5, 'resource_id' => 7), + array('role_id' => 5, 'resource_id' => 8), + array('role_id' => 6, 'resource_id' => 7) + ); + $hasMap = array( + array(7, true), + array(8, false) + ); + $hasRoleMap = array( + array(5, true), + array(6, false), + array(5, true) + ); + + $this->_ruleResource->expects($this->once()) + ->method('getRuleList') + ->will($this->returnValue($ruleList)); + + $this->_acl->expects($this->exactly(count($hasMap))) + ->method('has') + ->with($this->logicalOr(7, 8)) + ->will($this->returnValueMap($hasMap)); + $this->_acl->expects($this->exactly(count($hasRoleMap))) + ->method('hasRole') + ->with($this->logicalOr(5, 6)) + ->will($this->returnValueMap($hasRoleMap)); + $this->_acl->expects($this->once()) + ->method('allow') + ->with(5, 7); + + $this->_model->populateAcl($this->_acl); + } + + /** + * Test for Mage_Webapi_Model_Authorization_Loader_Rule::populateAcl without rules + */ + public function testPopulateAclWithoutRules() + { + $this->_ruleResource->expects($this->once()) + ->method('getRuleList') + ->will($this->returnValue(array())); + + $this->_acl->expects($this->never()) + ->method('has'); + $this->_acl->expects($this->never()) + ->method('hasRole'); + $this->_acl->expects($this->never()) + ->method('allow'); + + $this->_model->populateAcl($this->_acl); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Model/Authorization/RoleFactoryTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Model/Authorization/RoleFactoryTest.php new file mode 100644 index 0000000000000000000000000000000000000000..368fbcb4f705c7e367055d04e4639167825a937c --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Model/Authorization/RoleFactoryTest.php @@ -0,0 +1,67 @@ +<?php +/** + * Test class for Mage_Webapi_Model_Authorization_Role_Factory + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Authorization_Role_FactoryTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Webapi_Model_Authorization_Role_Factory + */ + protected $_model; + + /** + * @var Magento_ObjectManager + */ + protected $_objectManager; + + /** + * @var Mage_Webapi_Model_Authorization_Role + */ + protected $_expectedObject; + + protected function setUp() + { + $helper = new Magento_Test_Helper_ObjectManager($this); + + $this->_objectManager = $this->getMockForAbstractClass('Magento_ObjectManager', array(), '', true, true, true, + array('create')); + + $this->_expectedObject = $this->getMock('Mage_Webapi_Model_Authorization_Role', array(), array(), '', false); + + $this->_model = $helper->getModel('Mage_Webapi_Model_Authorization_Role_Factory', array( + 'objectManager' => $this->_objectManager, + )); + } + + public function testCreateRole() + { + $arguments = array('5', '6'); + + $this->_objectManager->expects($this->once()) + ->method('create') + ->with('Mage_Webapi_Model_Authorization_Role', $arguments, false) + ->will($this->returnValue($this->_expectedObject)); + $this->assertEquals($this->_expectedObject, $this->_model->createRole($arguments)); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Model/Authorization/RoleLocatorTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Model/Authorization/RoleLocatorTest.php new file mode 100644 index 0000000000000000000000000000000000000000..7835a0f2d31cedc85d25fc5d8b30df5a87481ca0 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Model/Authorization/RoleLocatorTest.php @@ -0,0 +1,44 @@ +<?php +/** + * Test class for Mage_Webapi_Model_Authorization_RoleLoactor + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Authorization_RoleLocatorTest extends PHPUnit_Framework_TestCase +{ + public function testGetAclRoleId() + { + $expectedRoleId = '557'; + $roleLocator = new Mage_Webapi_Model_Authorization_RoleLocator(array( + 'roleId' => $expectedRoleId + )); + $this->assertEquals($expectedRoleId, $roleLocator->getAclRoleId()); + } + + public function testSetRoleId() + { + $roleLocator = new Mage_Webapi_Model_Authorization_RoleLocator; + $expectedRoleId = '557'; + $roleLocator->setRoleId($expectedRoleId); + $this->assertAttributeEquals($expectedRoleId, '_roleId', $roleLocator); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Model/AuthorizationTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Model/AuthorizationTest.php new file mode 100644 index 0000000000000000000000000000000000000000..c03aa6ab3ad2e7fea8291ce72883fa68211f9022 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Model/AuthorizationTest.php @@ -0,0 +1,77 @@ +<?php +/** + * Test Mage_Webapi_Model_Authorization + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_AuthorizationTest extends PHPUnit_Framework_TestCase +{ + /** @var PHPUnit_Framework_MockObject_MockObject */ + protected $_coreAuthorization; + + /** @var Mage_Webapi_Helper_Data */ + protected $_helperMock; + + /** @var Mage_Webapi_Model_Authorization */ + protected $_webapiAuthorization; + + protected function setUp() + { + /** Prepare mocks for SUT constructor. */ + $this->_coreAuthorization = $this->getMockBuilder('Mage_Core_Model_Authorization') + ->setMethods(array('isAllowed')) + ->disableOriginalConstructor() + ->getMock(); + $this->_helperMock = $this->getMockBuilder('Mage_Webapi_Helper_Data') + ->disableOriginalConstructor() + ->setMethods(array('__')) + ->getMock(); + /** Initialize SUT. */ + $this->_webapiAuthorization = new Mage_Webapi_Model_Authorization( + $this->_helperMock, + $this->_coreAuthorization + ); + parent::setUp(); + } + + protected function tearDown() + { + unset($this->_coreAuthorization); + unset($this->_helperMock); + unset($this->_webapiAuthorization); + parent::tearDown(); + } + + public function testCheckResourceAclMageWebapiException() + { + $this->_coreAuthorization->expects($this->exactly(2))->method('isAllowed')->will($this->returnValue(false)); + $this->_helperMock->expects($this->once())->method('__')->will($this->returnArgument(0)); + $this->setExpectedException('Mage_Webapi_Exception', 'Access to resource is forbidden.'); + $this->_webapiAuthorization->checkResourceAcl('invalidResource', 'invalidMethod'); + } + + public function testCheckResourceAcl() + { + $this->_coreAuthorization->expects($this->once())->method('isAllowed')->will($this->returnValue(true)); + $this->_webapiAuthorization->checkResourceAcl('validResource', 'validMethod'); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Model/Resource/Acl/RoleTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Model/Resource/Acl/RoleTest.php new file mode 100644 index 0000000000000000000000000000000000000000..5ae1ed76f284e1386c4797dad4f9d23ab2da11da --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Model/Resource/Acl/RoleTest.php @@ -0,0 +1,149 @@ +<?php +/** + * Test class for Mage_Webapi_Model_Resource_Acl_Role + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Resource_Acl_RoleTest extends Mage_Webapi_Model_Resource_Acl_TestAbstract +{ + /** + * Create resource model + * + * @param Varien_Db_Select $selectMock + * @return Mage_Webapi_Model_Resource_Acl_Role + */ + protected function _createModel($selectMock = null) + { + $this->_resource = $this->getMockBuilder('Mage_Core_Model_Resource') + ->disableOriginalConstructor() + ->setMethods(array('getConnection', 'getTableName')) + ->getMock(); + + $this->_resource->expects($this->any()) + ->method('getTableName') + ->withAnyParameters() + ->will($this->returnArgument(0)); + + $this->_adapter = $this->getMockBuilder('Varien_Db_Adapter_Pdo_Mysql') + ->disableOriginalConstructor() + ->setMethods(array('select', 'fetchCol', 'fetchPairs')) + ->getMock(); + + $this->_adapter->expects($this->any()) + ->method('fetchCol') + ->withAnyParameters() + ->will($this->returnValue(array(1))); + + $this->_adapter->expects($this->any()) + ->method('fetchPairs') + ->withAnyParameters() + ->will($this->returnValue(array('key' => 'value'))); + + if (!$selectMock) { + $selectMock = new Varien_Db_Select( + $this->getMock('Varien_Db_Adapter_Pdo_Mysql', array(), array(), '', false)); + } + + $this->_adapter->expects($this->any()) + ->method('select') + ->withAnyParameters() + ->will($this->returnValue($selectMock)); + + $this->_resource->expects($this->any()) + ->method('getConnection') + ->withAnyParameters() + ->will($this->returnValue($this->_adapter)); + + return $this->_helper->getModel('Mage_Webapi_Model_Resource_Acl_Role', array( + 'resource' => $this->_resource, + 'helper' => $this->_helperData + )); + } + + /** + * Test constructor + */ + public function testConstructor() + { + $model = $this->_createModel(); + + $this->assertAttributeEquals('webapi_role', '_mainTable', $model); + $this->assertAttributeEquals('role_id', '_idFieldName', $model); + } + + /** + * Test _initUniqueFields() + */ + public function testGetUniqueFields() + { + $model = $this->_createModel(); + $fields = $model->getUniqueFields(); + + $this->assertEquals(array(array('field' => 'role_name', 'title' => 'Role Name')), $fields); + } + + /** + * Test getRolesList() + */ + public function testGetRolesList() + { + $selectMock = $this->getMockBuilder('Varien_Db_Select') + ->setConstructorArgs(array($this->getMock('Varien_Db_Adapter_Pdo_Mysql', array(), array(), '', false))) + ->setMethods(array('from', 'order')) + ->getMock(); + + $selectMock->expects($this->once()) + ->method('from') + ->with('webapi_role', array('role_id', 'role_name')) + ->will($this->returnSelf()); + + $selectMock->expects($this->once()) + ->method('order') + ->with('role_name') + ->will($this->returnSelf()); + + $model = $this->_createModel($selectMock); + $result = $model->getRolesList(); + $this->assertEquals(array('key' => 'value'), $result); + } + + /** + * Test getRolesIds() + */ + public function testGetRolesIds() + { + $selectMock = $this->getMockBuilder('Varien_Db_Select') + ->setConstructorArgs(array($this->getMock('Varien_Db_Adapter_Pdo_Mysql', array(), array(), '', false))) + ->setMethods(array('from', 'order')) + ->getMock(); + + $selectMock->expects($this->once()) + ->method('from') + ->with('webapi_role', array('role_id')) + ->will($this->returnSelf()); + + $model = $this->_createModel($selectMock); + + $result = $model->getRolesIds(); + $this->assertEquals(array(1), $result); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Model/Resource/Acl/RuleTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Model/Resource/Acl/RuleTest.php new file mode 100644 index 0000000000000000000000000000000000000000..21cd020c17b2a47d40faca6c3780916a5811dc8f --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Model/Resource/Acl/RuleTest.php @@ -0,0 +1,206 @@ +<?php +/** + * Test class for Mage_Webapi_Model_Resource_Acl_Rule + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Resource_Acl_RuleTest extends Mage_Webapi_Model_Resource_Acl_TestAbstract +{ + /** + * Create resource model + * + * @param Varien_Db_Select $selectMock + * @return Mage_Webapi_Model_Resource_Acl_Rule + */ + protected function _createModel($selectMock = null) + { + $this->_resource = $this->getMockBuilder('Mage_Core_Model_Resource') + ->disableOriginalConstructor() + ->setMethods(array('getConnection', 'getTableName')) + ->getMock(); + + $this->_resource->expects($this->any()) + ->method('getTableName') + ->withAnyParameters() + ->will($this->returnArgument(0)); + + $this->_adapter = $this->getMockBuilder('Varien_Db_Adapter_Pdo_Mysql') + ->disableOriginalConstructor() + ->setMethods(array('select', 'fetchCol', 'fetchAll', + 'beginTransaction', 'commit', 'rollback', 'insertArray', 'delete')) + ->getMock(); + + $this->_adapter->expects($this->any()) + ->method('fetchCol') + ->withAnyParameters() + ->will($this->returnValue(array(1))); + + $this->_adapter->expects($this->any()) + ->method('fetchAll') + ->withAnyParameters() + ->will($this->returnValue(array(array('key' => 'value')))); + + if (!$selectMock) { + $selectMock = new Varien_Db_Select( + $this->getMock('Varien_Db_Adapter_Pdo_Mysql', array(), array(), '', false)); + } + + $this->_adapter->expects($this->any()) + ->method('select') + ->withAnyParameters() + ->will($this->returnValue($selectMock)); + + $this->_adapter->expects($this->any()) + ->method('beginTransaction') + ->withAnyParameters() + ->will($this->returnSelf()); + + $this->_resource->expects($this->any()) + ->method('getConnection') + ->withAnyParameters() + ->will($this->returnValue($this->_adapter)); + + return $this->_helper->getModel('Mage_Webapi_Model_Resource_Acl_Rule', array( + 'resource' => $this->_resource, + 'helper' => $this->_helperData + )); + } + + /** + * Test constructor + */ + public function testConstructor() + { + $model = $this->_createModel(); + + $this->assertAttributeEquals('webapi_rule', '_mainTable', $model); + $this->assertAttributeEquals('rule_id', '_idFieldName', $model); + } + + /** + * Test getRuleList() + */ + public function testGetRuleList() + { + $selectMock = $this->getMockBuilder('Varien_Db_Select') + ->setConstructorArgs(array($this->getMock('Varien_Db_Adapter_Pdo_Mysql', array(), array(), '', false))) + ->setMethods(array('from')) + ->getMock(); + + $selectMock->expects($this->once()) + ->method('from') + ->with('webapi_rule', array('resource_id', 'role_id')) + ->will($this->returnSelf()); + + $model = $this->_createModel($selectMock); + $result = $model->getRuleList(); + $this->assertEquals(array(array('key' => 'value')), $result); + } + + /** + * Test getResourceIdsByRole() + */ + public function testGetResourceIdsByRole() + { + $selectMock = $this->getMockBuilder('Varien_Db_Select') + ->setConstructorArgs(array($this->getMock('Varien_Db_Adapter_Pdo_Mysql', array(), array(), '', false))) + ->setMethods(array('from', 'where')) + ->getMock(); + + $selectMock->expects($this->once()) + ->method('from') + ->with('webapi_rule', array('resource_id')) + ->will($this->returnSelf()); + + $selectMock->expects($this->once()) + ->method('where') + ->with('role_id = ?', 1) + ->will($this->returnSelf()); + + $model = $this->_createModel($selectMock); + $result = $model->getResourceIdsByRole(1); + $this->assertEquals(array(1), $result); + } + + /** + * Test saveResources() + */ + public function testSaveResources() + { + // init rule resource + $ruleResource = $this->getMockBuilder('Mage_Webapi_Model_Resource_Acl_Rule') + ->disableOriginalConstructor() + ->setMethods(array('saveResources', 'getIdFieldName', 'getReadConnection', 'getResources')) + ->getMock(); + + $ruleResource->expects($this->any()) + ->method('getIdFieldName') + ->withAnyParameters() + ->will($this->returnValue('id')); + + $ruleResource->expects($this->any()) + ->method('getReadConnection') + ->withAnyParameters() + ->will($this->returnValue($this->getMock('Varien_Db_Adapter_Pdo_Mysql', array(), array(), '', false))); + + // init rule + $rule = $this->getMockBuilder('Mage_Webapi_Model_Acl_Rule') + ->setConstructorArgs(array( + 'eventDispatcher' => $this->getMock('Mage_Core_Model_Event_Manager', array(), array(), '', false), + 'cacheManager' => $this->getMock('Mage_Core_Model_Cache', array(), array(), '', false), + 'resource' => $ruleResource + )) + ->setMethods(array('getResources')) + ->getMock(); + + $rule->expects($this->once()) + ->method('getResources') + ->withAnyParameters() + ->will($this->returnValue(array('ResourceName'))); + + $model = $this->_createModel(); + + // init adapter + $this->_adapter->expects($this->any()) + ->method('delete') + ->withAnyParameters() + ->will($this->returnValue(array())); + + $this->_adapter->expects($this->once()) + ->method('insertArray') + ->with('webapi_rule', array('role_id', 'resource_id'), + array(array('role_id' => 1, 'resource_id' => 'ResourceName'))) + ->will($this->returnValue(1)); + + $rule->setRoleId(1); + $model->saveResources($rule); + + // init adapter + $this->_adapter->expects($this->any()) + ->method('delete') + ->withAnyParameters() + ->will($this->throwException(new Zend_Db_Adapter_Exception('DB Exception'))); + + $this->setExpectedException('Zend_Db_Adapter_Exception', 'DB Exception'); + $model->saveResources($rule); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Model/Resource/Acl/TestAbstract.php b/dev/tests/unit/testsuite/Mage/Webapi/Model/Resource/Acl/TestAbstract.php new file mode 100644 index 0000000000000000000000000000000000000000..315dcef3a7faeff7a6e248064cc2cb2e1c42274c --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Model/Resource/Acl/TestAbstract.php @@ -0,0 +1,68 @@ +<?php +/** + * Abstract test class for Mage_Webapi_Model_Resource_Acl. Added to eliminate copy-paste. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Resource_Acl_TestAbstract extends PHPUnit_Framework_TestCase +{ + /** + * @var Magento_Test_Helper_ObjectManager + */ + protected $_helper; + + /** + * @var Mage_Webapi_Helper_Data + */ + protected $_helperData; + + /** + * @var Magento_ObjectManager|PHPUnit_Framework_MockObject_MockObject + */ + protected $_objectManager; + + /** + * @var Mage_Core_Model_Resource|PHPUnit_Framework_MockObject_MockObject + */ + protected $_resource; + + /** + * @var Varien_Db_Adapter_Pdo_Mysql|PHPUnit_Framework_MockObject_MockObject + */ + protected $_adapter; + + protected function setUp() + { + $this->_helper = new Magento_Test_Helper_ObjectManager($this); + + $this->_helperData = $this->getMockBuilder('Mage_Webapi_Helper_Data') + ->disableOriginalConstructor() + ->setMethods(array('__')) + ->getMock(); + $this->_helperData->expects($this->any())->method('__')->will($this->returnArgument(0)); + + $this->_objectManager = $this->getMockBuilder('Magento_ObjectManager') + ->disableOriginalConstructor() + ->setMethods(array('create')) + ->getMockForAbstractClass(); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Model/Resource/Acl/UserTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Model/Resource/Acl/UserTest.php new file mode 100644 index 0000000000000000000000000000000000000000..0d3ad14e84c39f0b93a30f582177c731e3cfd582 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Model/Resource/Acl/UserTest.php @@ -0,0 +1,123 @@ +<?php +/** + * Test class for Mage_Webapi_Model_Resource_Acl_User + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Resource_Acl_UserTest extends Mage_Webapi_Model_Resource_Acl_TestAbstract +{ + /** + * Create resource model + * + * @param Varien_Db_Select $selectMock + * @return Mage_Webapi_Model_Resource_Acl_User + */ + protected function _createModel($selectMock = null) + { + $this->_resource = $this->getMockBuilder('Mage_Core_Model_Resource') + ->disableOriginalConstructor() + ->setMethods(array('getConnection', 'getTableName')) + ->getMock(); + + $this->_resource->expects($this->any()) + ->method('getTableName') + ->withAnyParameters() + ->will($this->returnArgument(0)); + + $this->_adapter = $this->getMockBuilder('Varien_Db_Adapter_Pdo_Mysql') + ->disableOriginalConstructor() + ->setMethods(array('select', 'fetchCol')) + ->getMock(); + + if (!$selectMock) { + $selectMock = new Varien_Db_Select( + $this->getMock('Varien_Db_Adapter_Pdo_Mysql', array(), array(), '', false)); + } + + $this->_adapter->expects($this->any()) + ->method('select') + ->withAnyParameters() + ->will($this->returnValue($selectMock)); + + $this->_adapter->expects($this->any()) + ->method('fetchCol') + ->withAnyParameters() + ->will($this->returnValue(array(1))); + + $this->_resource->expects($this->any()) + ->method('getConnection') + ->withAnyParameters() + ->will($this->returnValue($this->_adapter)); + + return $this->_helper->getModel('Mage_Webapi_Model_Resource_Acl_User', array( + 'resource' => $this->_resource, + 'helper' => $this->_helperData + )); + } + + /** + * Test constructor + */ + public function testConstructor() + { + $model = $this->_createModel(); + + $this->assertAttributeEquals('webapi_user', '_mainTable', $model); + $this->assertAttributeEquals('user_id', '_idFieldName', $model); + } + + /** + * Test _initUniqueFields() + */ + public function testGetUniqueFields() + { + $model = $this->_createModel(); + $fields = $model->getUniqueFields(); + + $this->assertEquals(array(array('field' => 'api_key', 'title' => 'API Key')), $fields); + } + + /** + * Test getRoleUsers() + */ + public function testGetRoleUsers() + { + $selectMock = $this->getMockBuilder('Varien_Db_Select') + ->setConstructorArgs(array($this->getMock('Varien_Db_Adapter_Pdo_Mysql', array(), array(), '', false))) + ->setMethods(array('from', 'where')) + ->getMock(); + + $selectMock->expects($this->once()) + ->method('from') + ->with('webapi_user', array('user_id')) + ->will($this->returnSelf()); + + $selectMock->expects($this->once()) + ->method('where') + ->with('role_id = ?', 1) + ->will($this->returnSelf()); + + $model = $this->_createModel($selectMock); + $result = $model->getRoleUsers(1); + $this->assertEquals(array(1), $result); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Model/Rest/Oauth/ServerTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Model/Rest/Oauth/ServerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..5fbdac36a27bbd9283d987ef894d128ccec7fa71 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Model/Rest/Oauth/ServerTest.php @@ -0,0 +1,137 @@ +<?php +/** + * Two-legged oAuth server test. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Rest_Oauth_ServerTest extends PHPUnit_Framework_TestCase +{ + /** @var Mage_Webapi_Model_Rest_Oauth_Server */ + protected $_server; + + /** @var PHPUnit_Framework_MockObject_MockObject */ + protected $_requestMock; + + /** @var PHPUnit_Framework_MockObject_MockObject */ + protected $_consumerFactoryMock; + + /** @var PHPUnit_Framework_MockObject_MockObject */ + protected $_nonceFactory; + + /** + * Set up mocks. + */ + protected function setUp() + { + $this->_requestMock = $this->getMockBuilder('Mage_Webapi_Controller_Request_Rest') + ->setMethods(array('getHeader', 'getScheme', 'getHttpHost', 'getRequestUri')) + ->disableOriginalConstructor() + ->getMock(); + $tokenFactory = $this->getMockBuilder('Mage_Oauth_Model_Token_Factory') + ->disableOriginalConstructor() + ->getMock(); + $this->_consumerFactoryMock = $this->getMockBuilder('Mage_Webapi_Model_Acl_User_Factory') + ->setMethods(array('create')) + ->disableOriginalConstructor() + ->getMock(); + $this->_nonceFactory = $this->getMockBuilder('Mage_Oauth_Model_Nonce_Factory') + ->disableOriginalConstructor() + ->getMock(); + + $this->_server = new Mage_Webapi_Model_Rest_Oauth_Server( + $this->_requestMock, + $tokenFactory, + $this->_consumerFactoryMock, + $this->_nonceFactory + ); + } + + /** + * Test two legged authentication + */ + public function testAuthenticateTwoLegged() + { + $testUserKey = 'foo_user'; + $testUserSecret = 'bar_secret'; + $testUrl = 'http://foo.bar/api/rest/v1/baz'; + // Prepare signature and oAuth parameters + $utility = new Zend_Oauth_Http_Utility(); + $params = array( + 'oauth_consumer_key' => $testUserKey, + 'oauth_nonce' => $utility->generateNonce(), + 'oauth_timestamp' => $utility->generateTimestamp(), + 'oauth_version' => '1.0', + 'oauth_signature_method' => Mage_Oauth_Model_Server::SIGNATURE_PLAIN, + ); + $params['oauth_signature'] = $utility->sign( + $params, + Mage_Oauth_Model_Server::SIGNATURE_PLAIN, + $testUserSecret, + '', + 'GET', + $testUrl + ); + $authHeader = $utility->toAuthorizationHeader($params); + $this->_requestMock->expects($this->at(0)) + ->method('getHeader') + ->with('Authorization') + ->will($this->returnValue($authHeader)); + $this->_requestMock->expects($this->at(1)) + ->method('getHeader') + ->with(Zend_Http_Client::CONTENT_TYPE) + ->will($this->returnValue('application/json')); + $this->_requestMock->expects($this->any()) + ->method('getScheme') + ->with() + ->will($this->returnValue(Zend_Controller_Request_Http::SCHEME_HTTP)); + $this->_requestMock->expects($this->any()) + ->method('getHttpHost') + ->with() + ->will($this->returnValue('foo.bar')); + $this->_requestMock->expects($this->any()) + ->method('getRequestUri') + ->with() + ->will($this->returnValue('/api/rest/v1/baz')); + + $userMock = $this->getMockBuilder('Mage_Webapi_Model_Acl_User') + ->setMethods(array('loadByKey', 'getId', 'getSecret')) + ->disableOriginalConstructor() + ->getMock(); + $this->_consumerFactoryMock->expects($this->once()) + ->method('create') + ->will($this->returnValue($userMock)); + $userMock->expects($this->once()) + ->method('loadByKey') + ->with($testUserKey) + ->will($this->returnSelf()); + $userMock->expects($this->once()) + ->method('getId') + ->with() + ->will($this->returnValue(1)); + $userMock->expects($this->once()) + ->method('getSecret') + ->with() + ->will($this->returnValue($testUserSecret)); + + $this->assertEquals($userMock, $this->_server->authenticateTwoLegged()); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Model/Soap/AutoDiscoverTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Model/Soap/AutoDiscoverTest.php new file mode 100644 index 0000000000000000000000000000000000000000..9d36eec8e42964e6dd08d64b9ea86b5f3eba9489 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Model/Soap/AutoDiscoverTest.php @@ -0,0 +1,287 @@ +<?php +use Zend\Soap\Wsdl; + +/** + * SOAP AutoDiscover tests. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Soap_AutoDiscoverTest extends PHPUnit_Framework_TestCase +{ + /** @var Mage_Webapi_Model_Soap_Wsdl */ + protected $_wsdlMock; + + /** @var Mage_Webapi_Model_Soap_AutoDiscover */ + protected $_autoDiscover; + + /** @var Mage_Core_Model_Cache */ + protected $_cacheMock; + + /** @var Mage_Webapi_Model_Config_Soap */ + protected $_resourceConfigMock; + + protected function setUp() + { + /** Prepare arguments for SUT constructor. */ + $this->_resourceConfigMock = $this->getMockBuilder('Mage_Webapi_Model_Config_Soap') + ->disableOriginalConstructor()->getMock(); + + $this->_wsdlMock = $this->getMockBuilder('Mage_Webapi_Model_Soap_Wsdl') + ->disableOriginalConstructor() + ->setMethods( + array( + 'addSchemaTypeSection', + 'addService', + 'addPortType', + 'addBinding', + 'addSoapBinding', + 'addElement', + 'addComplexType', + 'addMessage', + 'addPortOperation', + 'addBindingOperation', + 'addSoapOperation', + 'toXML' + ) + ) + ->getMock(); + $wsdlFactory = $this->getMock( + 'Mage_Webapi_Model_Soap_Wsdl_Factory', + array('create'), + array(new Magento_ObjectManager_Zend()) + ); + $wsdlFactory->expects($this->any())->method('create')->will($this->returnValue($this->_wsdlMock)); + $helper = $this->getMock('Mage_Webapi_Helper_Config', array('__')); + $helper->expects($this->any())->method('__')->will($this->returnArgument(0)); + $this->_cacheMock = $this->getMockBuilder('Mage_Core_Model_Cache')->disableOriginalConstructor()->getMock(); + /** Initialize SUT. */ + $this->_autoDiscover = new Mage_Webapi_Model_Soap_AutoDiscover( + $this->_resourceConfigMock, + $wsdlFactory, + $helper, + $this->_cacheMock + ); + parent::setUp(); + } + + protected function tearDown() + { + unset($this->_wsdlMock); + unset($this->_autoDiscover); + unset($this->_cacheMock); + unset($this->_resourceConfigMock); + parent::tearDown(); + } + + /** + * Positive test case. Generate simple resource WSDL. + * + * @dataProvider generateDataProvider() + */ + public function testGenerate($resourceName, $methodName, $interface) + { + $serviceDomMock = $this->_getDomElementMock(); + $this->_wsdlMock->expects($this->once())->method('addService')->will($this->returnValue($serviceDomMock)); + $portTypeDomMock = $this->_getDomElementMock(); + $portTypeName = $this->_autoDiscover->getPortTypeName($resourceName); + $this->_wsdlMock->expects($this->once()) + ->method('addPortType') + ->with($portTypeName) + ->will($this->returnValue($portTypeDomMock)); + $bindingDomMock = $this->_getDomElementMock(); + $bindingName = $this->_autoDiscover->getBindingName($resourceName); + $this->_wsdlMock->expects($this->once()) + ->method('addBinding') + ->with($bindingName, Wsdl::TYPES_NS . ':' . $portTypeName) + ->will($this->returnValue($bindingDomMock)); + $this->_wsdlMock->expects($this->once()) + ->method('addSoapBinding') + ->with($bindingDomMock); + $operationName = $this->_autoDiscover->getOperationName($resourceName, $methodName); + $inputMessageName = $this->_autoDiscover->getInputMessageName($operationName); + $outputMessageName = $this->_autoDiscover->getOutputMessageName($operationName); + $this->_wsdlMock->expects($this->once()) + ->method('addPortOperation') + ->with( + $portTypeDomMock, + $operationName, + Wsdl::TYPES_NS . ':' . $inputMessageName, + Wsdl::TYPES_NS . ':' . $outputMessageName + ); + $operationDomMock = $this->_getDomElementMock(); + $this->_wsdlMock->expects($this->once()) + ->method('addBindingOperation') + ->with( + $bindingDomMock, + $operationName, + array('use' => 'literal'), + array('use' => 'literal'), + false, + SOAP_1_2 + ) + ->will($this->returnValue($operationDomMock)); + $this->_wsdlMock->expects($this->once()) + ->method('addSoapOperation') + ->with($operationDomMock, $operationName, SOAP_1_2); + $this->_wsdlMock->expects($this->once()) + ->method('toXML'); + + $requestedResources = array( + $resourceName => array( + 'methods' => array( + $methodName => array( + 'interface' => $interface, + 'documentation' => 'test method A', + ), + ), + ), + ); + $endpointUrl = 'http://magento.host/api/soap/'; + $this->_autoDiscover->generate($requestedResources, $endpointUrl); + } + + /** + * Test handle method with loading wsdl from cache. + */ + public function testHandleLoadWsdlFromCache() + { + /** Mock cache canUse method to return true. */ + $this->_cacheMock->expects($this->once())->method('canUse')->will($this->returnValue(true)); + /** Mock cache load method to return cache Id. */ + $this->_cacheMock->expects($this->once())->method('load')->will($this->returnArgument(0)); + $requestedResources = array( + 'res1' => 'v1', + 'res2' => 'v2' + ); + $result = $this->_autoDiscover->handle($requestedResources, 'http://magento.host'); + /** Assert handle method will return string that starts with WSDL. */ + $this->assertStringStartsWith( + Mage_Webapi_Model_Soap_AutoDiscover::WSDL_CACHE_ID, + $result, + 'Wsdl is not loaded from cache.' + ); + } + + /** + * Test handle method with exception. + */ + public function testHandleWithException() + { + /** Mock cache canUse method to return false. */ + $this->_cacheMock->expects($this->once())->method('canUse')->will($this->returnValue(false)); + $requestedResources = array('res1' => 'v1'); + $exception = new LogicException('getResourceDataMerged Exception'); + $this->_resourceConfigMock->expects($this->once())->method('getResourceDataMerged')->will( + $this->throwException($exception) + ); + $this->setExpectedException( + 'Mage_Webapi_Exception', + 'getResourceDataMerged Exception', + Mage_Webapi_Exception::HTTP_BAD_REQUEST + ); + $this->_autoDiscover->handle($requestedResources, 'http://magento.host'); + } + + /** + * Data provider for generate() test + * + * @return array + */ + public static function generateDataProvider() + { + $simpleInterface = array( + 'in' => array( + 'parameters' => array( + 'resource_id' => array( + 'type' => 'int', + 'required' => true, + 'documentation' => 'Resource ID.{annotation:value}' + ), + 'optional' => array( + 'type' => 'boolean', + 'required' => false, + 'default' => true, + 'documentation' => 'Optional parameter.' + ), + ), + ), + 'out' => array( + 'parameters' => array( + 'result' => array( + 'type' => 'string', + 'required' => true, + 'documentation' => 'Operation result.' + ) + ), + ), + ); + $oneWayInterface = array( + 'out' => array( + 'parameters' => array( + 'result' => array( + 'type' => 'string', + 'required' => true, + 'documentation' => 'Operation result.' + ) + ), + ), + ); + $complexTypeInterface = array( + 'in' => array( + 'parameters' => array( + 'complex_param' => array( + 'type' => 'ComplexTypeA', + 'required' => true, + 'documentation' => 'Optional complex type param.' + ), + ), + ), + 'out' => array( + 'parameters' => array( + 'result' => array( + 'type' => 'ComplexTypeB', + 'required' => false, + 'documentation' => 'Operation result.' + ) + ), + ), + ); + + return array( + 'Method with simple parameters' => array('resource_a', 'methodB', $simpleInterface), + 'One-way method' => array('resource_a', 'methodC', $oneWayInterface), + 'Method with complex type in parameters' => array('resource_a', 'methodE', $complexTypeInterface), + ); + } + + /** + * Create mock for DOMElement + * + * @return PHPUnit_Framework_MockObject_MockObject + */ + protected function _getDomElementMock() + { + return $this->getMockBuilder('DOMElement') + ->disableOriginalConstructor() + ->getMock(); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Model/Soap/FaultTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Model/Soap/FaultTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b75bca46a56c4f871375f4397c16e960e29b0556 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Model/Soap/FaultTest.php @@ -0,0 +1,158 @@ +<?php +/** + * Test SOAP fault model. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Soap_FaultTest extends PHPUnit_Framework_TestCase +{ + /** @var Mage_Webapi_Model_Soap_Fault */ + protected $_soapFault; + + protected function setUp() + { + /** Initialize SUT. */ + $this->_soapFault = new Mage_Webapi_Model_Soap_Fault(); + parent::setUp(); + } + + protected function tearDown() + { + unset($this->_soapFault); + parent::tearDown(); + } + + public function testToXmlDeveloperModeOff() + { + $expectedResult = <<<XML +<?xml version="1.0" encoding="utf-8" ?> +<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"> + <env:Body> + <env:Fault> + <env:Code> + <env:Value>env:Receiver</env:Value> + </env:Code> + <env:Reason> + <env:Text xml:lang="en">Internal Error.</env:Text> + </env:Reason> + </env:Fault> + </env:Body> +</env:Envelope> +XML; + $actualXml = $this->_soapFault->toXml(false); + $this->assertXmlStringEqualsXmlString( + $expectedResult, + $actualXml, + 'Wrong soap fault message with default parameters.' + ); + } + + public function testToXmlDeveloperModeOn() + { + $actualXml = $this->_soapFault->toXml(true); + $this->assertContains('<ExceptionTrace>', $actualXml, 'Exception trace not found in XML.'); + } + + /** + * Test getSoapFaultMessage method. + * + * @dataProvider dataProviderForGetSoapFaultMessageTest + */ + public function testGetSoapFaultMessage( + $faultReason, + $faultCode, + $language, + $additionalParameters, + $expectedResult, + $assertMessage + ) { + $actualResult = $this->_soapFault->getSoapFaultMessage( + $faultReason, + $faultCode, + $language, + $additionalParameters + ); + $this->assertXmlStringEqualsXmlString($expectedResult, $actualResult, $assertMessage); + } + + /** + * Data provider for GetSoapFaultMessage test. + * + * @return array + */ + public function dataProviderForGetSoapFaultMessageTest() + { + /** Include file with all expected soap fault XMLs. */ + $expectedXmls = include __DIR__ . '/../../_files/soap_fault/soap_fault_expected_xmls.php'; + return array( + //Each array contains data for SOAP Fault Message, Expected XML and Assert Message. + array( + 'Fault reason', + 'Sender', + 'cn', + array('key1' => 'value1', 'key2' => 'value2'), + $expectedXmls['expectedResultArrayDataDetails'], + 'Wrong soap fault message with associated array data details.' + ), + array( + 'Fault reason', + 'Sender', + 'en', + array('value1', 'value2'), + $expectedXmls['expectedResultIndexArrayDetails'], + 'Wrong soap fault message with index array data details.' + ), + array( + 'Fault reason', + 'Sender', + 'en', + array(), + $expectedXmls['expectedResultEmptyArrayDetails'], + 'Wrong soap fault message with empty array data details.' + ), + array( + 'Fault reason', + 'Sender', + 'en', + (object)array('key' => 'value'), + $expectedXmls['expectedResultObjectDetails'], + 'Wrong soap fault message with object data details.' + ), + array( + 'Fault reason', + 'Sender', + 'en', + 'String details', + $expectedXmls['expectedResultStringDetails'], + 'Wrong soap fault message with string data details.' + ), + array( + 'Fault reason', + 'Sender', + 'en', + array('key' => array('sub_key' => 'value')), + $expectedXmls['expectedResultComplexDataDetails'], + 'Wrong soap fault message with complex data details.' + ), + ); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Model/Soap/Security/UsernameToken/NonceStorageTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Model/Soap/Security/UsernameToken/NonceStorageTest.php new file mode 100644 index 0000000000000000000000000000000000000000..712e38896c2db555a297c049042c48a15272ef3c --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Model/Soap/Security/UsernameToken/NonceStorageTest.php @@ -0,0 +1,134 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Webapi + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Test SOAP WS-Security UsernameToken nonce & timestamp storage implementation. + */ +class Mage_Webapi_Model_Soap_Security_UsernameToken_NonceStorageTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Webapi_Model_Soap_Security_UsernameToken_NonceStorage + */ + protected $_nonceStorage; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_cacheMock; + + /** + * Set up cache instance mock and nonce storage object to be tested. + */ + protected function setUp() + { + $this->_cacheMock = $this->getMockBuilder('Mage_Core_Model_Cache') + ->disableOriginalConstructor() + ->setMethods(array('load', 'save')) + ->getMock(); + $this->_nonceStorage = new Mage_Webapi_Model_Soap_Security_UsernameToken_NonceStorage($this->_cacheMock); + } + + /** + * Clean up. + */ + protected function tearDown() + { + unset($this->_cacheMock); + unset($this->_nonceStorage); + } + + /** + * @param int $timestamp + * @dataProvider invalidTimestampDataProvider + * @expectedException Mage_Webapi_Model_Soap_Security_UsernameToken_TimestampRefusedException + */ + public function testValidateNonceInvalidTimestamp($timestamp) + { + $this->_nonceStorage->validateNonce('', $timestamp); + } + + public static function invalidTimestampDataProvider() + { + return array( + 'Timestamp is zero' => array(0), + 'Timestamp is a string' => array('abcdef'), + 'Timestamp is negative' => array(-1), + ); + } + + public function testValidateNonceTimeStampIsTooOld() + { + $this->setExpectedException('Mage_Webapi_Model_Soap_Security_UsernameToken_TimestampRefusedException'); + $timestamp = time() - Mage_Webapi_Model_Soap_Security_UsernameToken_NonceStorage::NONCE_TTL; + $this->_nonceStorage->validateNonce('', $timestamp); + } + + public function testValidateNonceTimeStampFromFuture() + { + $this->setExpectedException('Mage_Webapi_Model_Soap_Security_UsernameToken_TimestampRefusedException'); + /** Timestamp is from future more far than 60 seconds must be prohibited */ + $this->_nonceStorage->validateNonce('', time() + 65); + } + + public function testValidateNonce() + { + $nonce = 'abc123'; + $timestamp = time(); + + $this->_cacheMock + ->expects($this->once()) + ->method('load') + ->with($this->_nonceStorage->getNonceCacheId($nonce)) + ->will($this->returnValue(false)); + $this->_cacheMock + ->expects($this->once()) + ->method('save') + ->with($timestamp, $this->_nonceStorage->getNonceCacheId($nonce), + array(Mage_Webapi_Model_ConfigAbstract::WEBSERVICE_CACHE_TAG), + Mage_Webapi_Model_Soap_Security_UsernameToken_NonceStorage::NONCE_TTL + + Mage_Webapi_Model_Soap_Security_UsernameToken_NonceStorage::NONCE_FROM_FUTURE_ACCEPTABLE_RANGE); + + $this->_nonceStorage->validateNonce($nonce, $timestamp); + } + + /** + * @expectedException Mage_Webapi_Model_Soap_Security_UsernameToken_NonceUsedException + */ + public function testValidateNonceUsed() + { + $nonce = 'abc123'; + $timestamp = time(); + + $this->_cacheMock + ->expects($this->once()) + ->method('load') + ->with($this->_nonceStorage->getNonceCacheId($nonce)) + ->will($this->returnValue($timestamp)); + + $this->_nonceStorage->validateNonce($nonce, $timestamp); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Model/Soap/Security/UsernameTokenTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Model/Soap/Security/UsernameTokenTest.php new file mode 100644 index 0000000000000000000000000000000000000000..5a40d70b9b7919bc0dd8c8128ee373593dfc1573 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Model/Soap/Security/UsernameTokenTest.php @@ -0,0 +1,267 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Webapi + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Test SOAP WS-Security UsernameToken implementation. + */ +class Mage_Webapi_Model_Soap_Security_UsernameTokenTest extends PHPUnit_Framework_TestCase +{ + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_nonceStorageMock; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_userFactoryMock; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_userMock; + + /** + * Set up nonce storage mock to be used in further tests. + */ + protected function setUp() + { + $this->_nonceStorageMock = $this->getMockBuilder('Mage_Webapi_Model_Soap_Security_UsernameToken_NonceStorage') + ->disableOriginalConstructor() + ->setConstructorArgs(array('validateNonce')) + ->getMock(); + $this->_userMock = $this->getMockBuilder('Mage_Webapi_Model_Acl_User') + ->disableOriginalConstructor() + ->setMethods(array('load', 'getId', 'getSecret')) + ->getMock(); + $this->_userFactoryMock = $this->getMockBuilder('Mage_Webapi_Model_Acl_User_Factory') + ->disableOriginalConstructor() + ->setMethods(array('create')) + ->getMock(); + } + + /** + * Clean up. + */ + protected function tearDown() + { + unset($this->_nonceStorageMock); + unset($this->_userMock); + unset($this->_userFactoryMock); + } + + /** + * Test construction of object with valid datetime input. + * + * @dataProvider validDateTimeProvider() + * @param string $validDateTime + */ + public function testAuthenticateUsernameToken($validDateTime) + { + $username = 'test_user'; + $password = 'test_password'; + $nonce = mt_rand(); + $tokenPassword = base64_encode(hash('sha1', $nonce . $validDateTime . $password, true)); + $tokenNonce = base64_encode($nonce); + $this->_nonceStorageMock + ->expects($this->once()) + ->method('validateNonce') + ->with($tokenNonce, strtotime($validDateTime)); + $this->_userFactoryMock->expects($this->once()) + ->method('create') + ->with() + ->will($this->returnValue($this->_userMock)); + $this->_userMock->expects($this->once()) + ->method('load') + ->with($username, 'api_key') + ->will($this->returnSelf()); + $this->_userMock->expects($this->once()) + ->method('getId') + ->with() + ->will($this->returnValue(1)); + $this->_userMock->expects($this->once()) + ->method('getSecret') + ->with() + ->will($this->returnValue($password)); + + $usernameToken = new Mage_Webapi_Model_Soap_Security_UsernameToken( + $this->_nonceStorageMock, + $this->_userFactoryMock + ); + $this->assertEquals( + $this->_userMock, + $usernameToken->authenticate($username, $tokenPassword, $validDateTime, $tokenNonce) + ); + } + + /** + * Data provider for testConstructNewUsernameToken + * + * @return array + */ + public static function validDateTimeProvider() + { + return array( + 'Valid ISO8601 date' => array(date('c')), + 'Date in UTC timezone "Z"' => array(date('Y-m-d\TH:i:s\Z')), + 'Date in +2 hours timezone' => array(date('Y-m-d\TH:i:s+02:00')), + 'Date in -2.5 hours timezone' => array(date('Y-m-d\TH:i:s-02:30')), + ); + } + + /** + * Test construction of object with invalid datetime input. + * + * @dataProvider invalidDateTimeProvider() + * @param string $invalidDateTime + * @expectedException Mage_Webapi_Model_Soap_Security_UsernameToken_InvalidDateException + */ + public function testAuthenticateUsernameTokenWithInvalidCreatedDate($invalidDateTime) + { + $username = 'test_user'; + $password = 'test_password'; + $nonce = mt_rand(); + + $usernameToken = new Mage_Webapi_Model_Soap_Security_UsernameToken( + $this->_nonceStorageMock, + $this->_userFactoryMock + ); + $usernameToken->authenticate($username, $password, $invalidDateTime, $nonce); + } + + /** + * Data provider for testConstructNewUsernameTokenWithInvalidCreatedDate + * + * @return array + */ + public static function invalidDateTimeProvider() + { + return array( + 'No time specified' => array(date('Y-m-d')), + 'No seconds specified' => array(date('Y-m-dTH:i')), + 'Hours value is out of range' => array(date('Y-m-dT25:00:52+02:00')), + ); + } + + /** + * Test construction of object with invalid password type. + * + * @expectedException Mage_Webapi_Model_Soap_Security_UsernameToken_InvalidPasswordTypeException + */ + public function testConstructNewUsernameTokenWithInvalidPasswordType() + { + new Mage_Webapi_Model_Soap_Security_UsernameToken( + $this->_nonceStorageMock, + $this->_userFactoryMock, + 'INVALID_TYPE' + ); + } + + /** + * Test negative token authentication - username is invalid. + * + * @expectedException Mage_Webapi_Model_Soap_Security_UsernameToken_InvalidCredentialException + */ + public function testAuthenticateWithInvalidUsername() + { + $username = 'test_user'; + $password = 'test_password'; + list($created, $tokenPassword, $tokenNonce) = $this->_getTokenData($password); + + $this->_nonceStorageMock + ->expects($this->once()) + ->method('validateNonce') + ->with($tokenNonce, strtotime($created)); + $this->_userFactoryMock->expects($this->once()) + ->method('create') + ->with() + ->will($this->returnValue($this->_userMock)); + $this->_userMock->expects($this->once()) + ->method('load') + ->with($username, 'api_key') + ->will($this->returnSelf()); + $this->_userMock->expects($this->once()) + ->method('getId') + ->with() + ->will($this->returnValue(false)); + + $usernameToken = new Mage_Webapi_Model_Soap_Security_UsernameToken( + $this->_nonceStorageMock, + $this->_userFactoryMock + ); + $usernameToken->authenticate($username, $tokenPassword, $created, $tokenNonce); + } + + /** + * Test negative token authentication - password is invalid. + * + * @expectedException Mage_Webapi_Model_Soap_Security_UsernameToken_InvalidCredentialException + */ + public function testAuthenticateWithInvalidPassword() + { + $username = 'test_user'; + $password = 'test_password'; + $invalidPassword = 'invalid_password'; + list($created, $tokenPassword, $tokenNonce) = $this->_getTokenData($password); + + $this->_nonceStorageMock + ->expects($this->once()) + ->method('validateNonce') + ->with($tokenNonce, strtotime($created)); + $this->_userFactoryMock->expects($this->once()) + ->method('create') + ->with() + ->will($this->returnValue($this->_userMock)); + $this->_userMock->expects($this->once()) + ->method('load') + ->with($username, 'api_key') + ->will($this->returnSelf()); + $this->_userMock->expects($this->once()) + ->method('getId') + ->with() + ->will($this->returnValue(1)); + $this->_userMock->expects($this->once()) + ->method('getSecret') + ->with() + ->will($this->returnValue($invalidPassword)); + + $usernameToken = new Mage_Webapi_Model_Soap_Security_UsernameToken( + $this->_nonceStorageMock, + $this->_userFactoryMock + ); + $usernameToken->authenticate($username, $tokenPassword, $created, $tokenNonce); + } + + protected function _getTokenData($password) + { + $nonce = mt_rand(); + $created = date('c'); + $tokenPassword = base64_encode(hash('sha1', $nonce . $created . $password, true)); + $tokenNonce = base64_encode($nonce); + return array($created, $tokenPassword, $tokenNonce); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Model/Soap/ServerTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Model/Soap/ServerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b8bdf6127b00ed47bce26a732a7213eded434751 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Model/Soap/ServerTest.php @@ -0,0 +1,193 @@ +<?php +/** + * Test SOAP server model. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Soap_ServerTest extends PHPUnit_Framework_TestCase +{ + /** @var Mage_Webapi_Model_Soap_Server */ + protected $_soapServer; + + /** @var Mage_Core_Model_App */ + protected $_applicationMock; + + /** @var Mage_Core_Model_Store */ + protected $_storeMock; + + /** @var Mage_Webapi_Controller_Request_Soap */ + protected $_requestMock; + + /** @var Magento_DomDocument_Factory */ + protected $_domDocumentFactory; + + protected function setUp() + { + /** Init all dependencies for SUT. */ + $this->_storeMock = $this->getMockBuilder('Mage_Core_Model_Store')->disableOriginalConstructor()->getMock(); + $this->_applicationMock = $this->getMockBuilder('Mage_Core_Model_App')->disableOriginalConstructor()->getMock(); + $this->_applicationMock->expects($this->any())->method('getStore')->will($this->returnValue($this->_storeMock)); + $this->_requestMock = $this->getMockBuilder('Mage_Webapi_Controller_Request_Soap')->disableOriginalConstructor() + ->getMock(); + $this->_domDocumentFactory = $this->getMockBuilder('Magento_DomDocument_Factory') + ->disableOriginalConstructor()->getMock(); + + /** Init SUT. */ + $this->_soapServer = new Mage_Webapi_Model_Soap_Server( + $this->_applicationMock, + $this->_requestMock, + $this->_domDocumentFactory + ); + + parent::setUp(); + } + + protected function tearDown() + { + unset($this->_soapServer); + unset($this->_applicationMock); + unset($this->_requestMock); + unset($this->_storeMock); + parent::tearDown(); + } + + /** + * Test getApiCharset method. + */ + public function testGetApiCharset() + { + $this->_storeMock->expects($this->once())->method('getConfig')->will($this->returnValue('Windows-1251')); + $this->assertEquals('Windows-1251', $this->_soapServer->getApiCharset(), 'Wrong API charset encoding getting.'); + } + + /** + * Test getApiCharset method with default encoding. + */ + public function testGetApiCharsetDefaultEncoding() + { + $this->_storeMock->expects($this->once())->method('getConfig')->will($this->returnValue(null)); + $this->assertEquals( + Mage_Webapi_Model_Soap_Server::SOAP_DEFAULT_ENCODING, + $this->_soapServer->getApiCharset(), + 'Wrong default API charset encoding getting.' + ); + } + + /** + * Test generateUri method with default parameter. + */ + public function testGenerateUriDefault() + { + $this->_storeMock->expects($this->once())->method('getBaseUrl')->will( + $this->returnValue('http://magento.com/') + ); + $this->_requestMock->expects($this->once())->method('getRequestedResources')->will( + $this->returnValue(array('res' => 'v1')) + ); + $actualResult = $this->_soapServer->generateUri(); + $expectedResult = 'http://magento.com/api/soap?resources%5Bres%5D=v1'; + $this->assertEquals($expectedResult, $actualResult, 'Wrong URI generation with default parameter.'); + } + + /** + * Test generateUri method. + * + * @dataProvider providerForGenerateUriTest + */ + public function testGenerateUri($isWsdl, $resources, $expectedUri, $assertMessage) + { + $this->_storeMock->expects($this->once())->method('getBaseUrl')->will( + $this->returnValue('http://magento.com/') + ); + $this->_requestMock->expects($this->once())->method('getRequestedResources')->will( + $this->returnValue($resources) + ); + $actualUri = $this->_soapServer->generateUri($isWsdl); + $this->assertEquals($expectedUri, $actualUri, $assertMessage); + } + + /** + * Test getEndpointUri method. + */ + public function testGetEndpointUri() + { + $this->_storeMock->expects($this->once())->method('getBaseUrl')->will( + $this->returnValue('http://magento.com/') + ); + $expectedResult = 'http://magento.com/' . Mage_Webapi_Controller_Router_Route_Webapi::API_AREA_NAME . '/' + . Mage_Webapi_Controller_Front::API_TYPE_SOAP; + $actualResult = $this->_soapServer->getEndpointUri(); + $this->assertEquals($expectedResult, $actualResult, 'Wrong endpoint URI building.'); + } + + /** + * Test fault method with Exception. + */ + public function testExceptionFault() + { + /** Init Exception. */ + $exception = new Exception(); + $faultResult = $this->_soapServer->fault($exception); + /** Assert returned object is instance of SoapFault class. */ + $this->assertInstanceOf('SoapFault', $faultResult, 'SoapFault was not returned.'); + } + + /** + * Test fault method with Mage_Webapi_Model_Soap_Fault. + */ + public function testWebapiSoapFault() + { + /** Mock Webapi Soap fault. */ + $apiFault = $this->getMockBuilder('Mage_Webapi_Model_Soap_Fault')->disableOriginalConstructor()->getMock(); + /** Assert mocked fault toXml method will be executed once. */ + $apiFault->expects($this->once())->method('toXml'); + $this->_soapServer->fault($apiFault); + } + + /** + * Data provider for generateUri test. + */ + public function providerForGenerateUriTest() + { + return array( + //Each array contains isWsdl flag, resources, expected URI and assert message. + 'Several resources' => array( + false, + array('customer' => 'v1', 'product' => 'v2'), + 'http://magento.com/api/soap?resources%5Bcustomer%5D=v1&resources%5Bproduct%5D=v2', + 'Wrong URI generation with several resources.' + ), + 'Several resources with WSDL' => array( + true, + array('customer' => 'v1', 'product' => 'v2'), + 'http://magento.com/api/soap?resources%5Bcustomer%5D=v1&resources%5Bproduct%5D=v2&wsdl=1', + 'Wrong URI generation with several resources and WSDL.' + ), + 'Empty resources list' => array( + true, + array(), + 'http://magento.com/api/soap?wsdl=1', + 'Wrong URI generation without resources.' + ), + ); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Model/Soap/Wsdl/ComplexTypeStrategy/ConfigBasedTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Model/Soap/Wsdl/ComplexTypeStrategy/ConfigBasedTest.php new file mode 100644 index 0000000000000000000000000000000000000000..935dde326c850b75788fd411dc11a5342fc71380 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Model/Soap/Wsdl/ComplexTypeStrategy/ConfigBasedTest.php @@ -0,0 +1,292 @@ +<?php +use Zend\Soap\Wsdl; + +/** + * Complex type strategy tests. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Soap_Wsdl_ComplexTypeStrategy_ConfigBasedTest extends PHPUnit_Framework_TestCase +{ + /** @var PHPUnit_Framework_MockObject_MockObject */ + protected $_resourceConfig; + + /** @var PHPUnit_Framework_MockObject_MockObject */ + protected $_wsdl; + + /** @var Mage_Webapi_Model_Soap_Wsdl_ComplexTypeStrategy_ConfigBased */ + protected $_strategy; + + /** + * Set up strategy for test. + */ + protected function setUp() + { + $this->_resourceConfig = $this->getMockBuilder('Mage_Webapi_Model_Config_Soap') + ->setMethods(array('getTypeData')) + ->disableOriginalConstructor() + ->getMock(); + $this->_wsdl = $this->getMockBuilder('Mage_Webapi_Model_Soap_Wsdl') + ->setMethods(array('toDomDocument', 'getTypes', 'getSchema')) + ->disableOriginalConstructor() + ->getMock(); + $helper = $this->getMock('Mage_Webapi_Helper_Config', array('__')); + $helper->expects($this->any())->method('__')->will($this->returnArgument(0)); + + $this->_strategy = new Mage_Webapi_Model_Soap_Wsdl_ComplexTypeStrategy_ConfigBased( + $this->_resourceConfig, + $helper + ); + $this->_strategy->setContext($this->_wsdl); + + parent::setUp(); + } + + /** + * Clean up. + */ + protected function tearDown() + { + unset($this->_resourceConfig); + unset($this->_strategy); + unset($this->_wsdl); + + parent::tearDown(); + } + + /** + * Test that addComplexType returns type wsdl name + * if it has already been processed (registered at includedTypes in WSDL) + */ + public function testCheckTypeName() + { + $testType = 'testComplexTypeName'; + $testTypeWsdlName = 'tns:' . $testType; + $includedTypes = array( + $testType => $testTypeWsdlName, + ); + $this->_wsdl->expects($this->exactly(2)) + ->method('getTypes') + ->will($this->returnValue($includedTypes)); + + $this->assertEquals($testTypeWsdlName, $this->_strategy->addComplexType($testType)); + } + + /** + * Test adding complex type with simple parameters. + * + * @param string $type + * @param array $data + * @dataProvider addComplexTypeDataProvider + */ + public function testAddComplexTypeSimpleParameters($type, $data) + { + $this->_wsdl->expects($this->any()) + ->method('getTypes') + ->will($this->returnValue(array())); + + $this->_wsdl->expects($this->any()) + ->method('toDomDocument') + ->will($this->returnValue(new DOMDocument())); + + $schemaMock = $this->_getDomElementMock(); + $schemaMock->expects($this->any()) + ->method('appendChild'); + $this->_wsdl->expects($this->any()) + ->method('getSchema') + ->will($this->returnValue($schemaMock)); + + $this->_resourceConfig->expects($this->at(0)) + ->method('getTypeData') + ->with($type) + ->will($this->returnValue($data)); + + $this->assertEquals(Wsdl::TYPES_NS . ':' . $type, $this->_strategy->addComplexType($type)); + } + + /** + * Data provider for testAddComplexTypeSimpleParameters() + * + * @return array + */ + public static function addComplexTypeDataProvider() + { + return array( + 'simple parameters' => array( + 'VendorModuleADataStructure', + array( + 'documentation' => 'test', + 'parameters' => array( + 'string_param' => array( + 'type' => 'string', + 'required' => true, + 'documentation' => 'Required string param.' + ), + 'int_param' => array( + 'type' => 'int', + 'required' => true, + 'documentation' => 'Required int param.' + ), + 'bool_param' => array( + 'type' => 'boolean', + 'required' => false, + 'documentation' => 'Optional complex type param.{annotation:test}' + ), + ), + ), + ), + 'type with call info' => array( + 'VendorModuleADataStructure', + array( + 'documentation' => 'test', + 'parameters' => array( + 'string_param' => array( + 'type' => 'string', + 'required' => false, + 'documentation' => '{callInfo:VendorModuleACreate:requiredInput:conditionally}', + ), + ), + 'callInfo' => array( + 'requiredInput' => array( + 'yes' => array( + 'calls' => array('VendorModuleACreate') + ) + ), + 'returned' => array( + 'always' => array( + 'calls' => array('VendorModuleAGet') + ) + ) + ), + ), + ), + 'parameter with call info' => array( + 'VendorModuleADataStructure', + array( + 'documentation' => 'test', + 'parameters' => array( + 'string_param' => array( + 'type' => 'string', + 'required' => false, + 'documentation' => '{callInfo:VendorModuleACreate:requiredInput:conditionally}' + . '{callInfo:allCallsExcept(VendorModuleAGet):returned:always}', + ), + ), + ), + ), + 'parameter with see link' => array( + 'VendorModuleADataStructure', + array( + 'documentation' => 'test', + 'parameters' => array( + 'string_param' => array( + 'type' => 'string', + 'required' => false, + 'documentation' => '{seeLink:http://google.com/:title:for}', + ), + ), + ), + ), + 'parameter with doc instructions' => array( + 'VendorModuleADataStructure', + array( + 'documentation' => 'test', + 'parameters' => array( + 'string_param' => array( + 'type' => 'string', + 'required' => false, + 'documentation' => '{docInstructions:output:noDoc}', + ), + ), + ), + ), + ); + } + + /** + * Test adding complex type with complex parameters and arrays. + */ + public function testAddComplexTypeComplexParameters() + { + $type = 'VendorModuleADataStructure'; + $parameterType = 'ComplexType'; + $typeData = array( + 'documentation' => 'test', + 'parameters' => array( + 'complex_param' => array( + 'type' => $parameterType, + 'required' => true, + 'documentation' => 'complex type param.' + ), + ), + ); + $parameterData = array( + 'documentation' => 'test', + 'parameters' => array( + 'string_param' => array( + 'type' => 'ComplexTypeB[]', + 'required' => true, + 'documentation' => 'string param.' + ), + ), + ); + + $this->_wsdl->expects($this->at(0)) + ->method('getTypes') + ->will($this->returnValue(array())); + $this->_wsdl->expects($this->any()) + ->method('getTypes') + ->will($this->returnValue(array($type => Wsdl::TYPES_NS . ':' . $type))); + + $this->_wsdl->expects($this->any()) + ->method('toDomDocument') + ->will($this->returnValue(new DOMDocument())); + $schemaMock = $this->_getDomElementMock(); + $schemaMock->expects($this->any()) + ->method('appendChild'); + $this->_wsdl->expects($this->any()) + ->method('getSchema') + ->will($this->returnValue($schemaMock)); + $this->_resourceConfig->expects($this->at(0)) + ->method('getTypeData') + ->with($type) + ->will($this->returnValue($typeData)); + $this->_resourceConfig->expects($this->at(1)) + ->method('getTypeData') + ->with($parameterType) + ->will($this->returnValue($parameterData)); + + $this->assertEquals(Wsdl::TYPES_NS . ':' . $type, $this->_strategy->addComplexType($type)); + } + + /** + * Create mock for DOMElement + * + * @return PHPUnit_Framework_MockObject_MockObject + */ + protected function _getDomElementMock() + { + return $this->getMockBuilder('DOMElement') + ->disableOriginalConstructor() + ->getMock(); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Model/Soap/Wsdl/FactoryTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Model/Soap/Wsdl/FactoryTest.php new file mode 100644 index 0000000000000000000000000000000000000000..588db4b8a90a349826c1918c984903e32b4e1f37 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Model/Soap/Wsdl/FactoryTest.php @@ -0,0 +1,61 @@ +<?php +/** + * Test Mage_Webapi_Model_Soap_Wsdl_Factory + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_Webapi_Model_Soap_Wsdl_FactoryTest extends PHPUnit_Framework_TestCase +{ + /** @var PHPUnit_Framework_MockObject_MockObject */ + protected $_objectManagerMock; + + /** @var Mage_Webapi_Model_Soap_Wsdl_Factory */ + protected $_soapWsdlFactory; + + protected function setUp() + { + $this->_objectManagerMock = $this->getMockBuilder('Magento_ObjectManager') + ->disableOriginalConstructor() + ->setMethods(array('create')) + ->getMockForAbstractClass(); + $this->_soapWsdlFactory = new Mage_Webapi_Model_Soap_Wsdl_Factory($this->_objectManagerMock); + parent::setUp(); + } + + protected function tearDown() + { + unset($this->_objectManagerMock); + unset($this->_soapWsdlFactory); + parent::tearDown(); + } + + public function testCreate() + { + $wsdlName = 'wsdlName'; + $endpointUrl = 'endpointUrl'; + $this->_objectManagerMock + ->expects($this->once()) + ->method('create') + ->with('Mage_Webapi_Model_Soap_Wsdl', array('name' => $wsdlName, 'uri' => $endpointUrl)); + $this->_soapWsdlFactory->create($wsdlName, $endpointUrl); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Model/Source/Acl/RoleTest.php b/dev/tests/unit/testsuite/Mage/Webapi/Model/Source/Acl/RoleTest.php new file mode 100644 index 0000000000000000000000000000000000000000..d2346635d43fbf43fb0ddb3a7fc6a4c8e3bd17ea --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Model/Source/Acl/RoleTest.php @@ -0,0 +1,76 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Webapi + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Test for Mage_Webapi_Model_Source_Acl_Role. + */ +class Mage_Webapi_Model_Source_Acl_RoleTest extends PHPUnit_Framework_TestCase +{ + /** + * Check output format + * + * @dataProvider toOptionsHashDataProvider + * + * @param bool $addEmpty + * @param array $data + * @param array $expected + */ + public function testToOptionHashFormat($addEmpty, $data, $expected) + { + $resourceMock = $this->getMockBuilder('Mage_Webapi_Model_Resource_Acl_Role') + ->setMethods(array('getRolesList')) + ->disableOriginalConstructor() + ->getMock(); + $resourceMock->expects($this->any()) + ->method('getRolesList') + ->will($this->returnValue($data)); + + $model = new Mage_Webapi_Model_Source_Acl_Role(array( + 'resource' => $resourceMock + )); + + $options = $model->toOptionHash($addEmpty); + $this->assertEquals($expected, $options); + } + + /** + * Data provider for testing toOptionHash + * + * @return array + */ + public function toOptionsHashDataProvider() + { + return array( + 'with empty' => array( + true, array('1' => 'role 1', '2' => 'role 2'), array('' => '', '1' => 'role 1', '2' => 'role 2') + ), + 'without empty' => array( + false, array('1' => 'role 1', '2' => 'role 2'), array('1' => 'role 1', '2' => 'role 2') + ), + ); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Model/_files/acl.xml b/dev/tests/unit/testsuite/Mage/Webapi/Model/_files/acl.xml new file mode 100644 index 0000000000000000000000000000000000000000..c9fc2d120beaee1667cc0ade3369fd6f85b85ca2 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Model/_files/acl.xml @@ -0,0 +1,45 @@ +<?xml version="1.0"?> +<!-- +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Academic Free License (AFL 3.0) + * that is bundled with this package in the file LICENSE_AFL.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/afl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Webapi + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ +--> +<config> + <acl> + <resources> + <resource id="Mage_Webapi"> + <resource id="customer" title="Manage Customers" module="Mage_Customer" sortOrder="20"> + <resource id="customer/create" title="Create Customer" sortOrder="30" /> + <resource id="customer/update" title="Edit Customer" sortOrder="10" /> + <resource id="customer/get" title="Get Customer" sortOrder="20" /> + <resource id="customer/delete" title="Delete Customer" /> + </resource> + </resource> + </resources> + </acl> + <mapping> + <resource id="customer/list" parent="customer/get" /> + </mapping> +</config> diff --git a/dev/tests/unit/testsuite/Mage/Webapi/Model/_files/acl.xsd b/dev/tests/unit/testsuite/Mage/Webapi/Model/_files/acl.xsd new file mode 100644 index 0000000000000000000000000000000000000000..5416737be4174827017ab4067080ed52258e253f --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/Model/_files/acl.xsd @@ -0,0 +1,140 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Structure description for acl.xml ACL resource files. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Academic Free License (AFL 3.0) + * that is bundled with this package in the file LICENSE_AFL.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/afl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ +--> +<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> + <xs:element name="config"> + <xs:complexType> + <xs:sequence> + <xs:element name="acl"> + <xs:complexType> + <xs:sequence> + <xs:element name="resources"> + <xs:complexType> + <xs:sequence> + <xs:element minOccurs="0" maxOccurs="unbounded" name="resource" type="aclResource" /> + </xs:sequence> + </xs:complexType> + + <xs:unique name="uniqueResourceId"> + <xs:annotation> + <xs:documentation> + Attribute ID is unique under all ACL resources + </xs:documentation> + </xs:annotation> + <xs:selector xpath=".//*"/> + <xs:field xpath="@id"/> + </xs:unique> + </xs:element> + </xs:sequence> + </xs:complexType> + </xs:element> + + <xs:element name="mapping"> + <xs:complexType> + <xs:sequence> + <xs:element minOccurs="0" maxOccurs="unbounded" name="resource" type="aclMapping"> + <xs:unique name="uniqueMappedResourceId"> + <xs:annotation> + <xs:documentation> + Attribute ID is unique under all mapped ACL resources + </xs:documentation> + </xs:annotation> + <xs:selector xpath=".//*"/> + <xs:field xpath="@id"/> + </xs:unique> + </xs:element> + </xs:sequence> + </xs:complexType> + </xs:element> + </xs:sequence> + </xs:complexType> + </xs:element> + + <xs:complexType name="aclResource"> + <xs:annotation> + <xs:documentation> + ACL Resource. Recursive complex type + </xs:documentation> + </xs:annotation> + + <xs:sequence> + <xs:element minOccurs="0" maxOccurs="unbounded" name="resource" type="aclResource" /> + </xs:sequence> + + <xs:attribute name="id" type="typeId" use="required" /> + <xs:attribute name="module" type="typeModule" use="optional" /> + <xs:attribute name="title" type="typeTitle" use="optional" /> + <xs:attribute name="sortOrder" type="xs:int" use="optional" /> + </xs:complexType> + + <xs:complexType name="aclMapping"> + <xs:annotation> + <xs:documentation> + ACL Resource mapping. + </xs:documentation> + </xs:annotation> + + <xs:attribute name="id" type="typeId" use="required" /> + <xs:attribute name="parent" type="typeId" use="required" /> + </xs:complexType> + + <xs:simpleType name="typeId"> + <xs:annotation> + <xs:documentation> + Item ID attribute can have only [A-Za-z0-9_]/[A-Za-z0-9_]. Minimal length is 3 symbols. Case insensitive. + </xs:documentation> + </xs:annotation> + + <xs:restriction base="xs:string"> + <xs:pattern value="[A-Za-z_0-9]+/?[A-Za-z_0-9]+" /> + </xs:restriction> + </xs:simpleType> + + <xs:simpleType name="typeTitle"> + <xs:annotation> + <xs:documentation> + Item title attribute minimal length is 3 symbols + </xs:documentation> + </xs:annotation> + + <xs:restriction base="xs:string"> + <xs:minLength value="3" /> + <xs:maxLength value="50" /> + </xs:restriction> + </xs:simpleType> + + <xs:simpleType name="typeModule"> + <xs:annotation> + <xs:documentation> + Item module attribute can have only [a-z0-9_]. Minimal length is 3 symbols. Case insensitive. + </xs:documentation> + </xs:annotation> + <xs:restriction base="xs:string"> + <xs:pattern value="[A-Z]+[a-z0-9]{1,}_[A-Z]+[A-Z0-9a-z]{1,}" /> + </xs:restriction> + </xs:simpleType> +</xs:schema> diff --git a/dev/tests/unit/testsuite/Mage/Webapi/_files/soap_fault/soap_fault_expected_xmls.php b/dev/tests/unit/testsuite/Mage/Webapi/_files/soap_fault/soap_fault_expected_xmls.php new file mode 100644 index 0000000000000000000000000000000000000000..6f78b1122653beb12d8c259ed296a13c296438c2 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Webapi/_files/soap_fault/soap_fault_expected_xmls.php @@ -0,0 +1,123 @@ +<?php +/** + * The list of all expected soap fault XMLs. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +return array( + 'expectedResultArrayDataDetails' => + '<?xml version="1.0" encoding="utf-8" ?> + <env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"> + <env:Body> + <env:Fault> + <env:Code> + <env:Value>env:Sender</env:Value> + </env:Code> + <env:Reason> + <env:Text xml:lang="cn">Fault reason</env:Text> + </env:Reason> + <env:Detail> + <key1>value1</key1> + <key2>value2</key2> + </env:Detail> + </env:Fault> + </env:Body> + </env:Envelope>', + 'expectedResultEmptyArrayDetails' => + '<?xml version="1.0" encoding="utf-8" ?> + <env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"> + <env:Body> + <env:Fault> + <env:Code> + <env:Value>env:Sender</env:Value> + </env:Code> + <env:Reason> + <env:Text xml:lang="en">Fault reason</env:Text> + </env:Reason> + <env:Detail></env:Detail> + </env:Fault> + </env:Body> + </env:Envelope>', + 'expectedResultObjectDetails' => + '<?xml version="1.0" encoding="utf-8" ?> + <env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"> + <env:Body> + <env:Fault> + <env:Code> + <env:Value>env:Sender</env:Value> + </env:Code> + <env:Reason> + <env:Text xml:lang="en">Fault reason</env:Text> + </env:Reason> + </env:Fault> + </env:Body> + </env:Envelope>', + 'expectedResultStringDetails' => + '<?xml version = "1.0" encoding = "utf-8" ?> + <env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"> + <env:Body> + <env:Fault> + <env:Code> + <env:Value>env:Sender</env:Value> + </env:Code> + <env:Reason> + <env:Text xml:lang="en">Fault reason</env:Text> + </env:Reason> + <env:Detail>String details</env:Detail> + </env:Fault> + </env:Body> + </env:Envelope>', + 'expectedResultIndexArrayDetails' => + '<?xml version = "1.0" encoding = "utf-8" ?> + <env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"> + <env:Body> + <env:Fault> + <env:Code> + <env:Value>env:Sender</env:Value> + </env:Code> + <env:Reason> + <env:Text xml:lang="en">Fault reason</env:Text> + </env:Reason> + <env:Detail></env:Detail> + </env:Fault> + </env:Body> + </env:Envelope>', + 'expectedResultComplexDataDetails' => + '<?xml version = "1.0" encoding = "utf-8" ?> + <env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"> + <env:Body> + <env:Fault> + <env:Code> + <env:Value>env:Sender</env:Value> + </env:Code> + <env:Reason> + <env:Text xml:lang="en">Fault reason</env:Text> + </env:Reason> + <env:Detail> + <key> + <sub_key>value</sub_key> + </key> + </env:Detail> + </env:Fault> + </env:Body> + </env:Envelope>' +); diff --git a/dev/tests/unit/testsuite/Magento/Acl/ResourceFactoryTest.php b/dev/tests/unit/testsuite/Magento/Acl/ResourceFactoryTest.php new file mode 100644 index 0000000000000000000000000000000000000000..9621b55010292371a3cce47f1db93a41a99b3afb --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Acl/ResourceFactoryTest.php @@ -0,0 +1,66 @@ +<?php +/** + * Test class for Magento_Acl_ResourceFactory + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Magento_Acl_ResourceFactoryTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Magento_Acl_ResourceFactory + */ + protected $_model; + + /** + * @var Magento_ObjectManager + */ + protected $_objectManager; + + /** + * @var Magento_Acl_Resource + */ + protected $_expectedObject; + + protected function setUp() + { + $helper = new Magento_Test_Helper_ObjectManager($this); + + $this->_objectManager = $this->getMockForAbstractClass('Magento_ObjectManager', array(), '', true, true, true, + array('create')); + + $this->_expectedObject = $this->getMock('Magento_Acl_Resource', array(), array(), '', false); + + $this->_model = $helper->getModel('Magento_Acl_ResourceFactory', array( + 'objectManager' => $this->_objectManager, + )); + } + + public function testCreateResource() + { + $arguments = array('5', '6'); + $this->_objectManager->expects($this->once()) + ->method('create') + ->with('Magento_Acl_Resource', $arguments, false) + ->will($this->returnValue($this->_expectedObject)); + $this->assertEquals($this->_expectedObject, $this->_model->createResource($arguments)); + } +} diff --git a/dev/tests/unit/testsuite/Magento/Autoload/IncludePathTest.php b/dev/tests/unit/testsuite/Magento/Autoload/IncludePathTest.php index ef9c8e5c29b3a46f290e95e63e40c05fe5bd42c7..1cff9c187d6fcc1521e255c6c660abea1791a8b9 100644 --- a/dev/tests/unit/testsuite/Magento/Autoload/IncludePathTest.php +++ b/dev/tests/unit/testsuite/Magento/Autoload/IncludePathTest.php @@ -68,7 +68,7 @@ class Magento_Autoload_IncludePathTest extends PHPUnit_Framework_TestCase $fixture = uniqid(); $this->assertNotContains($fixture, get_include_path()); Magento_Autoload_IncludePath::addIncludePath(array($fixture), true); - $this->assertStringEndsWith(PATH_SEPARATOR . $fixture, get_include_path()); + $this->assertStringStartsWith($fixture . PATH_SEPARATOR, get_include_path()); } /** diff --git a/dev/tests/unit/testsuite/Magento/Profiler/Driver/Standard/OutputAbstractTest.php b/dev/tests/unit/testsuite/Magento/Profiler/Driver/Standard/OutputAbstractTest.php new file mode 100644 index 0000000000000000000000000000000000000000..26a085db046ff12ec7d786becc2bced017c9eaca --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Profiler/Driver/Standard/OutputAbstractTest.php @@ -0,0 +1,64 @@ +<?php +/** + * Test class for Magento_Profiler_Driver_Standard_OutputAbstract + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Magento_Profiler_Driver_Standard_OutputAbstractStatTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Magento_Profiler_Driver_Standard_OutputAbstract + */ + protected $_output; + + protected function setUp() + { + $this->_output = $this->getMockForAbstractClass('Magento_Profiler_Driver_Standard_OutputAbstract'); + } + + /** + * Test setFilterPattern method + */ + public function testSetFilterPattern() + { + $this->assertAttributeEmpty('_filterPattern', $this->_output); + $filterPattern = '/test/'; + $this->_output->setFilterPattern($filterPattern); + $this->assertAttributeEquals($filterPattern, '_filterPattern', $this->_output); + } + + /** + * Test setThreshold method + */ + public function testSetThreshold() + { + $thresholdKey = Magento_Profiler_Driver_Standard_Stat::TIME; + $this->_output->setThreshold($thresholdKey, 100); + $thresholds = PHPUnit_Util_Class::getObjectAttribute($this->_output, '_thresholds'); + $this->assertArrayHasKey($thresholdKey, $thresholds); + $this->assertEquals(100, $thresholds[$thresholdKey]); + + $this->_output->setThreshold($thresholdKey, null); + $thresholds = PHPUnit_Util_Class::getObjectAttribute($this->_output, '_thresholds'); + $this->assertArrayNotHasKey($thresholdKey, $thresholds); + } +} diff --git a/dev/tests/unit/testsuite/Magento/Profiler/Driver/Standard/StatTest.php b/dev/tests/unit/testsuite/Magento/Profiler/Driver/Standard/StatTest.php new file mode 100644 index 0000000000000000000000000000000000000000..0fd852d8ed5e54e919e6f1bf07886709da8ba565 --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Profiler/Driver/Standard/StatTest.php @@ -0,0 +1,463 @@ +<?php +/** + * Test class for Magento_Profiler_Driver_Standard_Stat + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Magento_Profiler_Driver_Standard_StatTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Magento_Profiler_Driver_Standard_Stat + */ + protected $_stat; + + protected function setUp() + { + $this->_stat = new Magento_Profiler_Driver_Standard_Stat(); + } + + /** + * Test start and stop methods of Magento_Profiler_Driver_Standard_Stat + * + * @dataProvider actionsDataProvider + * @param array $actions + * @param array $expected + */ + public function testActions(array $actions, array $expected) + { + foreach ($actions as $actionData) { + list($action, $timerId, $time, $realMemory, $emallocMemory) = array_values($actionData); + $this->_executeTimerAction($action, $timerId, $time, $realMemory, $emallocMemory); + } + + if (empty($expected)) { + $this->fail("\$expected mustn't be empty"); + } + + foreach ($expected as $timerId => $expectedTimer) { + $actualTimer = $this->_stat->get($timerId); + $this->assertInternalType('array', $actualTimer, "Timer '$timerId' must be an array"); + $this->assertEquals($expectedTimer, $actualTimer, "Timer '$timerId' has unexpected value"); + } + } + + /** + * Data provider for testActions + * + * @return array + */ + public function actionsDataProvider() + { + return array( + 'Start only once' => array( + 'actions' => array( + array('start', 'timer1', 'time' => 25, 'realMemory' => 1500, 'emallocMemory' => 10), + ), + 'expected' => array( + 'timer1' => array( + Magento_Profiler_Driver_Standard_Stat::START => 25, + Magento_Profiler_Driver_Standard_Stat::TIME => 0, + Magento_Profiler_Driver_Standard_Stat::REALMEM => 0, + Magento_Profiler_Driver_Standard_Stat::EMALLOC => 0, + Magento_Profiler_Driver_Standard_Stat::REALMEM_START => 1500, + Magento_Profiler_Driver_Standard_Stat::EMALLOC_START => 10, + Magento_Profiler_Driver_Standard_Stat::COUNT => 1 + ) + ) + ), + 'Start only twice' => array( + 'actions' => array( + array('start', 'timer1', 'time' => 25, 'realMemory' => 1500, 'emallocMemory' => 10), + array('start', 'timer1', 'time' => 75, 'realMemory' => 2000, 'emallocMemory' => 20), + ), + 'expected' => array( + 'timer1' => array( + Magento_Profiler_Driver_Standard_Stat::START => 75, + Magento_Profiler_Driver_Standard_Stat::TIME => 0, + Magento_Profiler_Driver_Standard_Stat::REALMEM => 0, + Magento_Profiler_Driver_Standard_Stat::EMALLOC => 0, + Magento_Profiler_Driver_Standard_Stat::REALMEM_START => 2000, + Magento_Profiler_Driver_Standard_Stat::EMALLOC_START => 20, + Magento_Profiler_Driver_Standard_Stat::COUNT => 2 + ) + ) + ), + 'Start and stop consequentially' => array( + 'actions' => array( + array('start', 'timer1', 'time' => 25, 'realMemory' => 1500, 'emallocMemory' => 10), + array('stop', 'timer1', 'time' => 75, 'realMemory' => 2000, 'emallocMemory' => 20), + array('start', 'timer1', 'time' => 200, 'realMemory' => 3000, 'emallocMemory' => 50), + array('stop', 'timer1', 'time' => 250, 'realMemory' => 4000, 'emallocMemory' => 80), + ), + 'expected' => array( + 'timer1' => array( + Magento_Profiler_Driver_Standard_Stat::START => false, + Magento_Profiler_Driver_Standard_Stat::TIME => 100, + Magento_Profiler_Driver_Standard_Stat::REALMEM => 1500, + Magento_Profiler_Driver_Standard_Stat::EMALLOC => 40, + Magento_Profiler_Driver_Standard_Stat::REALMEM_START => 3000, + Magento_Profiler_Driver_Standard_Stat::EMALLOC_START => 50, + Magento_Profiler_Driver_Standard_Stat::COUNT => 2 + ) + ) + ), + 'Start and stop with inner timer' => array( + 'actions' => array( + array('start', 'timer1', 'time' => 25, 'realMemory' => 1500, 'emallocMemory' => 10), + array('start', 'timer2', 'time' => 50, 'realMemory' => 2000, 'emallocMemory' => 20), + array('stop', 'timer2', 'time' => 80, 'realMemory' => 2500, 'emallocMemory' => 25), + array('stop', 'timer1', 'time' => 100, 'realMemory' => 4200, 'emallocMemory' => 55), + ), + 'expected' => array( + 'timer1' => array( + Magento_Profiler_Driver_Standard_Stat::START => false, + Magento_Profiler_Driver_Standard_Stat::TIME => 75, + Magento_Profiler_Driver_Standard_Stat::REALMEM => 2700, + Magento_Profiler_Driver_Standard_Stat::EMALLOC => 45, + Magento_Profiler_Driver_Standard_Stat::REALMEM_START => 1500, + Magento_Profiler_Driver_Standard_Stat::EMALLOC_START => 10, + Magento_Profiler_Driver_Standard_Stat::COUNT => 1 + ), + 'timer2' => array( + Magento_Profiler_Driver_Standard_Stat::START => false, + Magento_Profiler_Driver_Standard_Stat::TIME => 30, + Magento_Profiler_Driver_Standard_Stat::REALMEM => 500, + Magento_Profiler_Driver_Standard_Stat::EMALLOC => 5, + Magento_Profiler_Driver_Standard_Stat::REALMEM_START => 2000, + Magento_Profiler_Driver_Standard_Stat::EMALLOC_START => 20, + Magento_Profiler_Driver_Standard_Stat::COUNT => 1 + ) + ) + ) + ); + } + + /** + * Test get method with invalid timer id + * + * @expectedException InvalidArgumentException + * @expectedExceptionMessage Timer "unknown_timer" doesn't exist. + */ + public function testGetWithInvalidTimer() + { + $this->_stat->get('unknown_timer'); + } + + /** + * Test stop method with invalid timer id + * + * @expectedException InvalidArgumentException + * @expectedExceptionMessage Timer "unknown_timer" doesn't exist. + */ + public function testStopWithInvalidTimer() + { + $this->_stat->stop('unknown_timer', 1, 2, 3); + } + + /** + * Test clear method + */ + public function testClear() + { + $this->_stat->start('timer1', 1, 20, 10); + $this->_stat->start('timer2', 2, 20, 10); + $this->_stat->start('timer3', 3, 20, 10); + $this->assertAttributeCount(3, '_timers', $this->_stat); + + $this->_stat->clear('timer1'); + $this->assertAttributeCount(2, '_timers', $this->_stat); + + $this->_stat->clear(); + $this->assertAttributeEmpty('_timers', $this->_stat); + } + + /** + * Test getFilteredTimerIds for sorting + * + * @dataProvider timersSortingDataProvider + * @param array $timers + * @param array $expectedTimerIds + */ + public function testTimersSorting($timers, $expectedTimerIds) + { + foreach ($timers as $timerData) { + list($action, $timerId) = $timerData; + $this->_executeTimerAction($action, $timerId); + } + + $this->assertEquals($expectedTimerIds, $this->_stat->getFilteredTimerIds()); + } + + /** + * @return array + */ + public function timersSortingDataProvider() + { + return array( + 'Without sorting' => array( + 'actions' => array( + array('start', 'root'), + array('start', 'root->init'), + array('stop', 'root->init'), + array('stop', 'root'), + ), + 'expected' => array( + 'root', + 'root->init', + ) + ), + 'Simple sorting' => array( + 'actions' => array( + array('start', 'root'), + array('start', 'root->di'), + array('stop', 'root->di'), + array('start', 'root->init'), + array('start', 'root->init->init_stores'), + array('start', 'root->init->init_stores->store_collection_load_after'), + array('stop', 'root->init->init_stores->store_collection_load_after'), + array('stop', 'root->init->init_stores'), + array('stop', 'root->init'), + array('start', 'root->dispatch'), + array('stop', 'root->dispatch'), + array('stop', 'root'), + ), + 'expected' => array( + 'root', + 'root->di', + 'root->init', + 'root->init->init_stores', + 'root->init->init_stores->store_collection_load_after', + 'root->dispatch', + ) + ), + 'Nested sorting' => array( + 'actions' => array( + array('start', 'root'), + array('start', 'root->init'), + array('start', 'root->system'), + array('stop', 'root->system'), + array('start', 'root->init->init_config'), + array('stop', 'root->init->init_config'), + array('stop', 'root->init'), + array('stop', 'root'), + ), + 'expected' => array( + 'root', + 'root->init', + 'root->init->init_config', + 'root->system', + ) + ) + ); + } + + /** + * Test getFilteredTimerIds for filtering + * + * @dataProvider timersFilteringDataProvider + * @param array $timers + * @param array $thresholds + * @param string $filterPattern + * @param array $expectedTimerIds + */ + public function testTimersFiltering($timers, $thresholds, $filterPattern, $expectedTimerIds) + { + foreach ($timers as $timerData) { + list($action, $timerId, $time, $realMemory, $emallocMemory) = array_pad(array_values($timerData), 5, 0); + $this->_executeTimerAction($action, $timerId, $time, $realMemory, $emallocMemory); + } + + $this->assertEquals($expectedTimerIds, $this->_stat->getFilteredTimerIds($thresholds, $filterPattern)); + } + + /** + * @return array + */ + public function timersFilteringDataProvider() + { + return array( + 'Filtering by pattern' => array( + 'actions' => array( + array('start', 'root'), + array('start', 'root->init'), + array('stop', 'root->init'), + array('stop', 'root'), + ), + 'thresholds' => array(), + 'filterPattern' => '/^root$/', + 'expected' => array( + 'root', + ) + ), + 'Filtering by thresholds' => array( + 'actions' => array( + array('start', 'root', 'time' => 0, 'realMemory' => 0, 'emallocMemory' => 0), + array('start', 'root->init', 0), + array('start', 'root->init->init_cache', 'time' => 50, 'realMemory' => 1000), + array('stop', 'root->init->init_cache', 'time' => 100, 'realMemory' => 21000), + array('stop', 'root->init', 999), + array('stop', 'root', 'time' => 1000, 'realMemory' => 500, 'emallocMemory' => 0), + ), + 'thresholds' => array( + Magento_Profiler_Driver_Standard_Stat::TIME => 1000, + Magento_Profiler_Driver_Standard_Stat::REALMEM => 20000, + ), + 'filterPattern' => null, + 'expected' => array( + 'root', // TIME >= 1000 + 'root->init->init_cache', // REALMEM >= 20000 + ) + ), + ); + } + + /** + * Test positive cases of fetch method + * + * @dataProvider fetchDataProvider + * @param array $timers + * @param array $expects + */ + public function testFetch($timers, $expects) + { + foreach ($timers as $timerData) { + list($action, $timerId, $time, $realMemory, $emallocMemory) = array_pad(array_values($timerData), 5, 0); + $this->_executeTimerAction($action, $timerId, $time, $realMemory, $emallocMemory); + } + foreach ($expects as $expectedData) { + /** @var bool|int|PHPUnit_Framework_Constraint $expectedValue */ + list($timerId, $key, $expectedValue) = array_values($expectedData); + if ($expectedValue instanceof PHPUnit_Framework_Constraint) { + $expectedValue->evaluate($this->_stat->fetch($timerId, $key)); + } else { + $this->assertEquals($expectedValue, $this->_stat->fetch($timerId, $key)); + } + } + } + + /** + * @return array + */ + public function fetchDataProvider() + { + return array( + array( + 'actions' => array( + array('start', 'root', 'time' => 0, 'realMemory' => 0, 'emallocMemory' => 0), + array('stop', 'root', 'time' => 1000, 'realMemory' => 500, 'emallocMemory' => 10), + ), + 'expects' => array( + array( + 'timerId' => 'root', + 'key' => Magento_Profiler_Driver_Standard_Stat::START, + 'expectedValue' => false + ), + array( + 'timerId' => 'root', + 'key' => Magento_Profiler_Driver_Standard_Stat::TIME, + 'expectedValue' => 1000 + ), + array( + 'timerId' => 'root', + 'key' => Magento_Profiler_Driver_Standard_Stat::REALMEM, + 'expectedValue' => 500 + ), + array( + 'timerId' => 'root', + 'key' => Magento_Profiler_Driver_Standard_Stat::EMALLOC, + 'expectedValue' => 10 + ), + ) + ), + array( + 'actions' => array( + array('start', 'root', 'time' => 0), + array('stop', 'root', 'time' => 10), + array('start', 'root', 'time' => 20), + array('stop', 'root', 'time' => 30), + ), + 'expects' => array(array( + 'timerId' => 'root', + 'key' => Magento_Profiler_Driver_Standard_Stat::AVG, + 'expectedValue' => 10 + )) + ), + array( + 'actions' => array( + array('start', 'root', 'time' => 0), + ), + 'expects' => array(array( + 'timerId' => 'root', + 'key' => Magento_Profiler_Driver_Standard_Stat::TIME, + 'expectedValue' => $this->greaterThan(microtime(true)) + ), array( + 'timerId' => 'root', + 'key' => Magento_Profiler_Driver_Standard_Stat::ID, + 'expectedValue' => 'root' + )) + ), + ); + } + + /** + * @expectedException InvalidArgumentException + * @expectedMessage Timer "foo" doesn't exist. + */ + public function testFetchInvalidTimer() + { + $this->_stat->fetch('foo', 'bar'); + } + + /** + * @expectedException InvalidArgumentException + * @expectedMessage Timer "foo" doesn't have value for "bar". + */ + public function testFetchInvalidKey() + { + $this->_stat->start('foo', 0, 0, 0); + $this->_stat->fetch('foo', 'bar'); + } + + /** + * Executes stop or start methods on $_stat object + * + * @param string $action + * @param string $timerId + * @param int $time + * @param int $realMemory + * @param int $emallocMemory + */ + protected function _executeTimerAction($action, $timerId, $time = 0, $realMemory = 0, $emallocMemory = 0) + { + switch ($action) { + case 'start': + $this->_stat->start($timerId, $time, $realMemory, $emallocMemory); + break; + case 'stop': + $this->_stat->stop($timerId, $time, $realMemory, $emallocMemory); + break; + default: + $this->fail("Unexpected action '$action'"); + break; + } + } +} diff --git a/dev/tests/unit/testsuite/Magento/Profiler/Driver/StandardTest.php b/dev/tests/unit/testsuite/Magento/Profiler/Driver/StandardTest.php new file mode 100644 index 0000000000000000000000000000000000000000..a281c7983cbf8f2ff716e398373a802dc2ba9bd0 --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Profiler/Driver/StandardTest.php @@ -0,0 +1,113 @@ +<?php +/** + * Test class for Magento_Profiler_Driver_Standard + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Magento_Profiler_Driver_StandardTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Magento_Profiler_Driver_Standard_Stat|PHPUnit_Framework_MockObject_MockObject + */ + protected $_stat; + + /** + * @var Magento_Profiler_Driver_Standard + */ + protected $_driver; + + protected function setUp() + { + $this->_stat = $this->getMock('Magento_Profiler_Driver_Standard_Stat'); + $this->_driver = new Magento_Profiler_Driver_Standard($this->_stat); + } + + protected function tearDown() + { + Magento_Profiler::reset(); + } + + /** + * Test __construct method + */ + public function testConstructor() + { + $this->assertAttributeEquals($this->_stat, '_stat', $this->_driver); + $this->_driver = new Magento_Profiler_Driver_Standard(); + $this->assertAttributeInstanceOf('Magento_Profiler_Driver_Standard_Stat', '_stat', $this->_driver); + } + + /** + * Test display method + */ + public function testDisplayAndRegisterOutput() + { + $outputOne = $this->getMock('Magento_Profiler_Driver_Standard_OutputInterface'); + $outputOne->expects($this->once())->method('display')->with($this->_stat); + $outputTwo = $this->getMock('Magento_Profiler_Driver_Standard_OutputInterface'); + $outputTwo->expects($this->once())->method('display')->with($this->_stat); + + $this->_driver->registerOutput($outputOne); + $this->_driver->registerOutput($outputTwo); + Magento_Profiler::enable(); + $this->_driver->display(); + Magento_Profiler::disable(); + $this->_driver->display(); + } + + /** + * Test clear method + */ + public function testClear() + { + $this->_stat->expects($this->once())->method('clear')->with('timer_id'); + $this->_driver->clear('timer_id'); + } + + /** + * Test start method + */ + public function testStart() + { + $this->_stat->expects($this->once())->method('start')->with( + 'timer_id', + $this->greaterThanOrEqual(microtime(true)), + $this->greaterThanOrEqual(0), + $this->greaterThanOrEqual(0) + ); + $this->_driver->start('timer_id'); + } + + /** + * Test stop method + */ + public function testStop() + { + $this->_stat->expects($this->once())->method('stop')->with( + 'timer_id', + $this->greaterThanOrEqual(microtime(true)), + $this->greaterThanOrEqual(0), + $this->greaterThanOrEqual(0) + ); + $this->_driver->stop('timer_id'); + } +} diff --git a/dev/tests/unit/testsuite/Magento/Profiler/Output/CsvfileTest.php b/dev/tests/unit/testsuite/Magento/Profiler/Output/CsvfileTest.php deleted file mode 100644 index 57a99b911f1c7bf7ab28b825ce4d7acbad0b719e..0000000000000000000000000000000000000000 --- a/dev/tests/unit/testsuite/Magento/Profiler/Output/CsvfileTest.php +++ /dev/null @@ -1,94 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Magento - * @package Magento_Profiler - * @subpackage unit_tests - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Test case for Magento_Profiler_Output_Csvfile - * - * @group profiler - */ -class Magento_Profiler_Output_CsvfileTest extends PHPUnit_Framework_TestCase -{ - /** - * @var Magento_Profiler_Output_Csvfile - */ - protected $_object; - - /** - * @var string - */ - protected $_actualCsvFile; - - public static function setUpBeforeClass() - { - Magento_Profiler::enable(); - /* Profiler measurements fixture */ - $timersProperty = new ReflectionProperty('Magento_Profiler', '_timers'); - $timersProperty->setAccessible(true); - $timersProperty->setValue(include __DIR__ . '/../_files/timers.php'); - $timersProperty->setAccessible(false); - } - - public static function tearDownAfterClass() - { - Magento_Profiler::reset(); - } - - protected function setUp() - { - do { - $this->_actualCsvFile = TESTS_TEMP_DIR . DIRECTORY_SEPARATOR . md5(time() + microtime(true)); - } while (file_exists($this->_actualCsvFile)); - } - - /** - * @dataProvider displayDataProvider - */ - public function testDisplay($delimiter, $enclosure, $expectedCsvFile) - { - $this->_object = new Magento_Profiler_Output_Csvfile($this->_actualCsvFile, null, $delimiter, $enclosure); - $this->_object->display(); - - $this->assertFileEquals($expectedCsvFile, $this->_actualCsvFile); - } - - public function displayDataProvider() - { - return array( - 'default delimiter & enclosure' => array(',', '"', __DIR__ . '/../_files/output_default.csv'), - 'custom delimiter & enclosure' => array('.', '`', __DIR__ . '/../_files/output_custom.csv'), - ); - } - - public function testDisplayDefaults() - { - $this->_object = new Magento_Profiler_Output_Csvfile($this->_actualCsvFile); - $this->_object->display(); - - $expectedCsvFile = __DIR__ . '/../_files/output_default.csv'; - $this->assertFileEquals($expectedCsvFile, $this->_actualCsvFile); - } -} diff --git a/dev/tests/unit/testsuite/Magento/Profiler/Output/HtmlTest.php b/dev/tests/unit/testsuite/Magento/Profiler/Output/HtmlTest.php deleted file mode 100644 index 73b2a04e8f3fa2e369c74eb2627fcea8ba3d0da9..0000000000000000000000000000000000000000 --- a/dev/tests/unit/testsuite/Magento/Profiler/Output/HtmlTest.php +++ /dev/null @@ -1,74 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Magento - * @package Magento_Profiler - * @subpackage unit_tests - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Test case for Magento_Profiler_Output_Html - * - * @group profiler - */ -class Magento_Profiler_Output_HtmlTest extends PHPUnit_Framework_TestCase -{ - /** - * @var Magento_Profiler_Output_Html|PHPUnit_Framework_MockObject_MockObject - */ - protected $_object; - - public static function setUpBeforeClass() - { - Magento_Profiler::enable(); - /* Profiler measurements fixture */ - $timersProperty = new ReflectionProperty('Magento_Profiler', '_timers'); - $timersProperty->setAccessible(true); - $timersProperty->setValue(include __DIR__ . '/../_files/timers.php'); - $timersProperty->setAccessible(false); - } - - public static function tearDownAfterClass() - { - Magento_Profiler::reset(); - } - - protected function setUp() - { - $this->_object = $this->getMock('Magento_Profiler_Output_Html', array('_renderCaption')); - $this->_object - ->expects($this->any()) - ->method('_renderCaption') - ->will($this->returnValue('Code Profiler Title')) - ; - } - - public function testDisplay() - { - ob_start(); - $this->_object->display(); - $actualHtml = ob_get_clean(); - $expectedString = file_get_contents(__DIR__ . '/../_files/output.html'); - $expectedString = ltrim(preg_replace('/^<!--.+?-->/s', '', $expectedString)); - $this->assertEquals($expectedString, $actualHtml); - } -} diff --git a/dev/tests/unit/testsuite/Magento/Profiler/OutputAbstractTest.php b/dev/tests/unit/testsuite/Magento/Profiler/OutputAbstractTest.php deleted file mode 100644 index ba61943d9a3c25a9dd460ac4c3fdde7860a99fab..0000000000000000000000000000000000000000 --- a/dev/tests/unit/testsuite/Magento/Profiler/OutputAbstractTest.php +++ /dev/null @@ -1,215 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Magento - * @package Magento_Profiler - * @subpackage unit_tests - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Test case for Magento_Profiler_OutputAbstract - * - * @group profiler - */ -class Magento_Profiler_OutputAbstractTest extends PHPUnit_Framework_TestCase -{ - /** - * @var Magento_Profiler_OutputAbstract|PHPUnit_Framework_MockObject_MockObject - */ - private $_object; - - /** - * @var ReflectionMethod - */ - private $_timersGetter; - - public static function setUpBeforeClass() - { - Magento_Profiler::enable(); - /* Profiler measurements fixture */ - $timersProperty = new ReflectionProperty('Magento_Profiler', '_timers'); - $timersProperty->setAccessible(true); - $timersProperty->setValue(include __DIR__ . '/_files/timers.php'); - $timersProperty->setAccessible(false); - } - - public static function tearDownAfterClass() - { - Magento_Profiler::reset(); - } - - protected function setUp() - { - $this->_object = $this->getMockForAbstractClass('Magento_Profiler_OutputAbstract'); - - $this->_timersGetter = new ReflectionMethod(get_class($this->_object), '_getTimers'); - $this->_timersGetter->setAccessible(true); - } - - protected function tearDown() - { - $this->_timersGetter->setAccessible(false); - } - - /** - * @dataProvider getTimersDataProvider - */ - public function testGetTimers($filter, $expectedTimers) - { - $this->_object->__construct($filter); - $actualTimers = $this->_timersGetter->invoke($this->_object); - $this->assertEquals($expectedTimers, $actualTimers); - } - - public function getTimersDataProvider() - { - return array( - 'null filter' => array( - null, - array( - 'some_root_timer', - 'some_root_timer->some_nested_timer', - 'some_root_timer->some_nested_timer->some_deeply_nested_timer', - 'one_more_root_timer' - ) - ), - 'exact timer filter' => array( - '/^some_root_timer->some_nested_timer$/', - array( - 'some_root_timer->some_nested_timer', - ) - ), - 'timer subtree filter' => array( - '/^some_root_timer->some_nested_timer/', - array( - 'some_root_timer->some_nested_timer', - 'some_root_timer->some_nested_timer->some_deeply_nested_timer' - ) - ), - 'timer strict subtree filter' => array( - '/^some_root_timer->some_nested_timer->/', - array( - 'some_root_timer->some_nested_timer->some_deeply_nested_timer' - ) - ), - ); - } - - /** - * @dataProvider thresholdDataProvider - */ - public function testSetThreshold(array $thresholds, $expectedTimers) - { - $this->_resetThresholds($this->_object); - foreach ($thresholds as $fetchKey => $thresholdValue) { - $this->_object->setThreshold($fetchKey, $thresholdValue); - } - $actualTimers = $this->_timersGetter->invoke($this->_object); - $this->assertEquals($expectedTimers, $actualTimers); - } - - public function thresholdDataProvider() - { - return array( - 'empty' => array( - array(), - array( - 'some_root_timer', - 'some_root_timer->some_nested_timer', - 'some_root_timer->some_nested_timer->some_deeply_nested_timer', - 'one_more_root_timer' - ), - ), - 'time' => array( - array( - Magento_Profiler::FETCH_TIME => 0.06, - ), - array( - 'some_root_timer', - 'some_root_timer->some_nested_timer', - ), - ), - 'avg' => array( - array( - Magento_Profiler::FETCH_AVG => 0.038, - ), - array( - 'some_root_timer', - ), - ), - 'count' => array( - array( - Magento_Profiler::FETCH_COUNT => 3, - ), - array( - 'some_root_timer->some_nested_timer', - 'some_root_timer->some_nested_timer->some_deeply_nested_timer', - ), - ), - 'avg & count' => array( - array( - Magento_Profiler::FETCH_AVG => 0.038, - Magento_Profiler::FETCH_COUNT => 3, - ), - array( - 'some_root_timer', - 'some_root_timer->some_nested_timer', - 'some_root_timer->some_nested_timer->some_deeply_nested_timer', - ), - ), - ); - } - - public function testSetThresholdReset() - { - $this->_resetThresholds($this->_object); - - $this->_object->setThreshold(Magento_Profiler::FETCH_COUNT, 4); - $actualTimers = $this->_timersGetter->invoke($this->_object); - $this->assertEmpty($actualTimers); - - $this->_object->setThreshold(Magento_Profiler::FETCH_COUNT, null); - $actualTimers = $this->_timersGetter->invoke($this->_object); - $expectedTimers = $this->thresholdDataProvider(); - $expectedTimers = $expectedTimers['empty'][1]; - $this->assertEquals($expectedTimers, $actualTimers); - } - - /** - * Reset threshold values for all profiler fetch keys - * - * @param Magento_Profiler_OutputAbstract $output - */ - protected function _resetThresholds(Magento_Profiler_OutputAbstract $output) - { - $fetchKeys = array( - Magento_Profiler::FETCH_TIME, - Magento_Profiler::FETCH_AVG, - Magento_Profiler::FETCH_COUNT, - Magento_Profiler::FETCH_EMALLOC, - Magento_Profiler::FETCH_REALMEM, - ); - foreach ($fetchKeys as $fetchKey) { - $output->setThreshold($fetchKey, null); - } - } -} diff --git a/dev/tests/unit/testsuite/Magento/Profiler/_files/output.html b/dev/tests/unit/testsuite/Magento/Profiler/_files/output.html deleted file mode 100644 index cf877b432079a14f92f95a9ea320528fbcff9aa0..0000000000000000000000000000000000000000 --- a/dev/tests/unit/testsuite/Magento/Profiler/_files/output.html +++ /dev/null @@ -1,70 +0,0 @@ -<!-- -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Academic Free License (AFL 3.0) - * that is bundled with this package in the file LICENSE_AFL.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/afl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Magento - * @package Mage_Core - * @subpackage integration_tests - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) - */ ---> -<table border="1" cellspacing="0" cellpadding="2"> -<caption>Code Profiler Title</caption> -<tr> -<th>Timer Id</th> -<th>Time</th> -<th>Avg</th> -<th>Cnt</th> -<th>Emalloc</th> -<th>RealMem</th> -</tr> -<tr> -<td title="some_root_timer">some_root_timer</td> -<td title="some_root_timer">0.080000</td> -<td title="some_root_timer">0.040000</td> -<td title="some_root_timer">2</td> -<td title="some_root_timer">51,000,000</td> -<td title="some_root_timer">50,000,000</td> -</tr> -<tr> -<td title="some_root_timer->some_nested_timer">· some_nested_timer</td> -<td title="some_root_timer->some_nested_timer">0.080000</td> -<td title="some_root_timer->some_nested_timer">0.026667</td> -<td title="some_root_timer->some_nested_timer">3</td> -<td title="some_root_timer->some_nested_timer">42,000,000</td> -<td title="some_root_timer->some_nested_timer">40,000,000</td> -</tr> -<tr> -<td title="some_root_timer->some_nested_timer->some_deeply_nested_timer">· · some_deeply_nested_timer</td> -<td title="some_root_timer->some_nested_timer->some_deeply_nested_timer">0.030000</td> -<td title="some_root_timer->some_nested_timer->some_deeply_nested_timer">0.010000</td> -<td title="some_root_timer->some_nested_timer->some_deeply_nested_timer">3</td> -<td title="some_root_timer->some_nested_timer->some_deeply_nested_timer">13,000,000</td> -<td title="some_root_timer->some_nested_timer->some_deeply_nested_timer">10,000,000</td> -</tr> -<tr> -<td title="one_more_root_timer">one_more_root_timer</td> -<td title="one_more_root_timer">0.010000</td> -<td title="one_more_root_timer">0.010000</td> -<td title="one_more_root_timer">1</td> -<td title="one_more_root_timer">23,456,789</td> -<td title="one_more_root_timer">12,345,678</td> -</tr> -</table> diff --git a/dev/tests/unit/testsuite/Magento/Profiler/_files/output_custom.csv b/dev/tests/unit/testsuite/Magento/Profiler/_files/output_custom.csv deleted file mode 100644 index 7108456bca8f7f2a7fa5f140914169e66561a6bc..0000000000000000000000000000000000000000 --- a/dev/tests/unit/testsuite/Magento/Profiler/_files/output_custom.csv +++ /dev/null @@ -1,4 +0,0 @@ -some_root_timer.`0.080000`.`0.040000`.2.51,000,000.50,000,000 -some_root_timer->some_nested_timer.`0.080000`.`0.026667`.3.42,000,000.40,000,000 -some_root_timer->some_nested_timer->some_deeply_nested_timer.`0.030000`.`0.010000`.3.13,000,000.10,000,000 -one_more_root_timer.`0.010000`.`0.010000`.1.23,456,789.12,345,678 diff --git a/dev/tests/unit/testsuite/Magento/Profiler/_files/output_default.csv b/dev/tests/unit/testsuite/Magento/Profiler/_files/output_default.csv deleted file mode 100644 index bb0ef1dece1d5ec1cc78d85d05569b320f4f4125..0000000000000000000000000000000000000000 --- a/dev/tests/unit/testsuite/Magento/Profiler/_files/output_default.csv +++ /dev/null @@ -1,4 +0,0 @@ -some_root_timer,0.080000,0.040000,2,"51,000,000","50,000,000" -some_root_timer->some_nested_timer,0.080000,0.026667,3,"42,000,000","40,000,000" -some_root_timer->some_nested_timer->some_deeply_nested_timer,0.030000,0.010000,3,"13,000,000","10,000,000" -one_more_root_timer,0.010000,0.010000,1,"23,456,789","12,345,678" diff --git a/dev/tests/unit/testsuite/Magento/Profiler/_files/timers.php b/dev/tests/unit/testsuite/Magento/Profiler/_files/timers.php deleted file mode 100644 index 0bb2dfcc302a480a158543e9659fa1740fb66373..0000000000000000000000000000000000000000 --- a/dev/tests/unit/testsuite/Magento/Profiler/_files/timers.php +++ /dev/null @@ -1,65 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Magento - * @package Mage_Core - * @subpackage integration_tests - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ -?> -<?php return array( - 'some_root_timer' => array( - 'start' => false, - 'sum' => 0.08, - 'count' => 2, - 'realmem' => 50000000, - 'emalloc' => 51000000, - 'realmem_start' => 0, - 'emalloc_start' => 0, - ), - 'some_root_timer->some_nested_timer' => array( - 'start' => false, - 'sum' => 0.08, - 'count' => 3, - 'realmem' => 40000000, - 'emalloc' => 42000000, - 'realmem_start' => 0, - 'emalloc_start' => 0, - ), - 'some_root_timer->some_nested_timer->some_deeply_nested_timer' => array( - 'start' => false, - 'sum' => 0.03, - 'count' => 3, - 'realmem' => 10000000, - 'emalloc' => 13000000, - 'realmem_start' => 0, - 'emalloc_start' => 0, - ), - 'one_more_root_timer' => array( - 'start' => false, - 'sum' => 0.01, - 'count' => 1, - 'realmem' => 12345678, - 'emalloc' => 23456789, - 'realmem_start' => 0, - 'emalloc_start' => 0, - ), -); diff --git a/dev/tests/unit/testsuite/Magento/ProfilerTest.php b/dev/tests/unit/testsuite/Magento/ProfilerTest.php index a369724ca0005523e7e1c73f9e38d568bd9d3d46..ec2c3cb5209a31c4efe1afd32347b093d36a7f79 100644 --- a/dev/tests/unit/testsuite/Magento/ProfilerTest.php +++ b/dev/tests/unit/testsuite/Magento/ProfilerTest.php @@ -1,5 +1,7 @@ <?php /** + * Unit Test for Magento_Profiler + * * Magento * * NOTICE OF LICENSE @@ -18,293 +20,331 @@ * versions in the future. If you wish to customize Magento for your * needs please refer to http://www.magentocommerce.com for more information. * - * @category Magento - * @package Magento_Profiler - * @subpackage unit_tests * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ - -/** - * Test case for Magento_Profiler - * - * @group profiler - */ class Magento_ProfilerTest extends PHPUnit_Framework_TestCase { - /** - * @var ReflectionProperty - */ - protected static $_timersProperty; - - public static function setUpBeforeClass() + protected function tearDown() { - self::$_timersProperty = new ReflectionProperty('Magento_Profiler', '_timers'); - self::$_timersProperty->setAccessible(true); + Magento_Profiler::reset(); } - public static function tearDownAfterClass() + public function testEnable() { - self::$_timersProperty->setAccessible(false); + Magento_Profiler::enable(); + $this->assertTrue(Magento_Profiler::isEnabled()); } - protected function setUp() + public function testDisable() { - Magento_Profiler::enable(); - /* Profiler measurements fixture */ - self::$_timersProperty->setValue(include __DIR__ . '/Profiler/_files/timers.php'); + Magento_Profiler::disable(); + $this->assertFalse(Magento_Profiler::isEnabled()); } - protected function tearDown() + public function testSetDefaultTags() { - Magento_Profiler::reset(); + $expected = array('tenantId' => '12345'); + Magento_Profiler::setDefaultTags($expected); + $this->assertAttributeEquals($expected, '_defaultTags', 'Magento_Profiler'); } - public function testEnableDisable() + public function testAddTagFilter() { - Magento_Profiler::start('another_root_level_timer'); - Magento_Profiler::stop('another_root_level_timer'); - Magento_Profiler::disable(); - Magento_Profiler::start('this_timer_should_be_ignored'); - Magento_Profiler::stop('this_timer_should_be_ignored'); - Magento_Profiler::enable(); - Magento_Profiler::start('another_root_level_timer'); - Magento_Profiler::start('another_nested_timer'); - Magento_Profiler::stop('another_nested_timer'); - Magento_Profiler::stop('another_root_level_timer'); - $expectedTimers = array( - 'some_root_timer', - 'some_root_timer->some_nested_timer', - 'some_root_timer->some_nested_timer->some_deeply_nested_timer', - 'one_more_root_timer', - 'another_root_level_timer', - 'another_root_level_timer->another_nested_timer', + Magento_Profiler::addTagFilter('tag1', 'value_1.1'); + Magento_Profiler::addTagFilter('tag2', 'value_2.1'); + Magento_Profiler::addTagFilter('tag1', 'value_1.2'); + + $expected = array( + 'tag1' => array('value_1.1', 'value_1.2'), + 'tag2' => array('value_2.1'), ); - $actualTimers = Magento_Profiler::getTimers(); - $this->assertEquals($expectedTimers, $actualTimers); + $this->assertAttributeEquals($expected, '_tagFilters', 'Magento_Profiler'); + $this->assertAttributeEquals(true, '_hasTagFilters', 'Magento_Profiler'); } - public function testEnableInitOnce() + public function testAdd() { - $reflectionProperty = new ReflectionProperty('Magento_Profiler', '_isInitialized'); - $reflectionProperty->setAccessible(true); - $reflectionProperty->setValue(false); - $reflectionProperty->setAccessible(false); - /** @var Magento_Profiler|PHPUnit_Framework_MockObject_MockObject $class */ - $class = $this->getMockClass('Magento_Profiler', array('_initialize')); - $class::staticExpects($this->once()) - ->method('_initialize') - ; - $class::enable(); - $class::enable(); - } + $mock = $this->_getDriverMock(); + Magento_Profiler::add($mock); - public function testResetProfiler() - { - $this->assertNotEmpty(Magento_Profiler::getTimers()); - Magento_Profiler::reset(); - $this->assertEmpty(Magento_Profiler::getTimers()); + $this->assertTrue(Magento_Profiler::isEnabled()); - Magento_Profiler::start('another_root_level_timer'); - Magento_Profiler::start('another_nested_timer'); - Magento_Profiler::reset(); - Magento_Profiler::start('timer_that_should_be_root_after_reset'); - $this->assertEquals( - array( - 'timer_that_should_be_root_after_reset', - ), - Magento_Profiler::getTimers() + $expected = array( + get_class($mock) => $mock ); + $this->assertAttributeEquals($expected, '_drivers', 'Magento_Profiler'); } /** - * @dataProvider resetTimerDataProvider + * @return PHPUnit_Framework_MockObject_MockObject */ - public function testResetTimer($timerId, $fetchKey) + protected function _getDriverMock() { - $this->assertNotEmpty(Magento_Profiler::fetch($timerId, $fetchKey)); - Magento_Profiler::reset($timerId); - $this->assertEmpty(Magento_Profiler::fetch($timerId, $fetchKey)); + return $this->getMockBuilder('Magento_Profiler_DriverInterface') + ->setMethods(array('start', 'stop', 'clear')) + ->getMockForAbstractClass(); } - public function resetTimerDataProvider() + /** + * @expectedException InvalidArgumentException + * @expectedExceptionMessage Timer name must not contain a nesting separator. + */ + public function testStartException() { - return array( - 'profiler time' => array('some_root_timer->some_nested_timer', Magento_Profiler::FETCH_TIME), - 'profiler count' => array('some_root_timer->some_nested_timer', Magento_Profiler::FETCH_COUNT), - 'profiler avg' => array('some_root_timer->some_nested_timer', Magento_Profiler::FETCH_AVG), - 'profiler emalloc' => array('some_root_timer->some_nested_timer', Magento_Profiler::FETCH_EMALLOC), - 'profiler realmem' => array('some_root_timer->some_nested_timer', Magento_Profiler::FETCH_REALMEM), - ); + Magento_Profiler::enable(); + Magento_Profiler::start('timer ' . Magento_Profiler::NESTING_SEPARATOR . ' name'); } - public function testStart() + public function testDisabledProfiler() { - Magento_Profiler::start('another_root_level_timer'); - Magento_Profiler::start('another_nested_timer'); - Magento_Profiler::stop('another_nested_timer'); - Magento_Profiler::stop('another_root_level_timer'); - $expectedTimers = array( - 'some_root_timer', - 'some_root_timer->some_nested_timer', - 'some_root_timer->some_nested_timer->some_deeply_nested_timer', - 'one_more_root_timer', - 'another_root_level_timer', - 'another_root_level_timer->another_nested_timer' - ); - $actualTimers = Magento_Profiler::getTimers(); - $this->assertEquals($expectedTimers, $actualTimers); + $driver = $this->_getDriverMock(); + $driver->expects($this->never()) + ->method('start'); + $driver->expects($this->never()) + ->method('stop'); + + Magento_Profiler::add($driver); + Magento_Profiler::disable(); + Magento_Profiler::start('test'); + Magento_Profiler::stop('test'); } - /** - * @expectedException Varien_Exception - */ - public function testStartException() + public function testStartStopSimple() { - Magento_Profiler::start('another_root_level_timer->another_nested_timer'); + $driver = $this->_getDriverMock(); + $driver->expects($this->once()) + ->method('start') + ->with('root_level_timer', null); + $driver->expects($this->once()) + ->method('stop') + ->with('root_level_timer'); + + Magento_Profiler::add($driver); + Magento_Profiler::start('root_level_timer'); + Magento_Profiler::stop('root_level_timer'); + } + + public function testStartNested() + { + $driver = $this->_getDriverMock(); + $driver->expects($this->at(0)) + ->method('start') + ->with('root_level_timer', null); + $driver->expects($this->at(1)) + ->method('start') + ->with('root_level_timer->some_other_timer', null); + + $driver->expects($this->at(2)) + ->method('stop') + ->with('root_level_timer->some_other_timer'); + $driver->expects($this->at(3)) + ->method('stop') + ->with('root_level_timer'); + + Magento_Profiler::add($driver); + Magento_Profiler::start('root_level_timer'); + Magento_Profiler::start('some_other_timer'); + Magento_Profiler::stop('some_other_timer'); + Magento_Profiler::stop('root_level_timer'); } /** - * @dataProvider stopDataProvider + * @expectedException InvalidArgumentException + * @expectedExceptionMessage Timer "unknown" has not been started. */ - public function testStop(array $stopArgumentSets) + public function testStopExceptionUnknown() { - $stopCallback = array('Magento_Profiler', 'stop'); + Magento_Profiler::enable(); + Magento_Profiler::start('timer'); + Magento_Profiler::stop('unknown'); + } - Magento_Profiler::start('another_root_level_timer'); - Magento_Profiler::start('another_nested_timer'); - foreach ($stopArgumentSets as $stopArguments) { - call_user_func_array($stopCallback, $stopArguments); - } - Magento_Profiler::start('one_more_root_timer'); - Magento_Profiler::stop('one_more_root_timer'); + public function testStopOrder() + { + $driver = $this->_getDriverMock(); + $driver->expects($this->at(0)) + ->method('start') + ->with('timer1', null); + $driver->expects($this->at(1)) + ->method('start') + ->with('timer1->timer2', null); + $driver->expects($this->at(2)) + ->method('start') + ->with('timer1->timer2->timer1', null); + $driver->expects($this->at(3)) + ->method('start') + ->with('timer1->timer2->timer1->timer3', null); - $expected = array( - 'some_root_timer', - 'some_root_timer->some_nested_timer', - 'some_root_timer->some_nested_timer->some_deeply_nested_timer', - 'one_more_root_timer', - 'another_root_level_timer', - 'another_root_level_timer->another_nested_timer', - ); + $driver->expects($this->at(4)) + ->method('stop') + ->with('timer1->timer2->timer1->timer3'); + $driver->expects($this->at(5)) + ->method('stop') + ->with('timer1->timer2->timer1'); - $actual = Magento_Profiler::getTimers(); - $this->assertEquals($expected, $actual); + $driver->expects($this->exactly(4)) + ->method('start'); + $driver->expects($this->exactly(2)) + ->method('stop'); + + Magento_Profiler::add($driver); + Magento_Profiler::start('timer1'); + Magento_Profiler::start('timer2'); + Magento_Profiler::start('timer1'); + Magento_Profiler::start('timer3'); + Magento_Profiler::stop('timer1'); } - public function stopDataProvider() + public function testStopSameName() { - return array( - 'omit timer name' => array( - array(array(), array()) - ), - 'null timer name' => array( - array(array(null), array(null)) - ), - 'pass timer name' => array( - array(array('another_nested_timer'), array('another_root_level_timer')) - ), - ); + $driver = $this->_getDriverMock(); + $driver->expects($this->at(0)) + ->method('start') + ->with('timer1', null); + $driver->expects($this->at(1)) + ->method('start') + ->with('timer1->timer1', null); + + $driver->expects($this->at(2)) + ->method('stop') + ->with('timer1->timer1'); + $driver->expects($this->at(3)) + ->method('stop') + ->with('timer1'); + + Magento_Profiler::add($driver); + Magento_Profiler::start('timer1'); + Magento_Profiler::start('timer1'); + Magento_Profiler::stop('timer1'); + Magento_Profiler::stop('timer1'); } - /** - * @dataProvider stopExceptionDataProvider - * @expectedException Varien_Exception - */ - public function testStopException(array $timersToStart, array $timersToStop) + public function testStopLatest() { - foreach ($timersToStart as $timerName) { - Magento_Profiler::start($timerName); - } - foreach ($timersToStop as $timerName) { - Magento_Profiler::stop($timerName); - } + $driver = $this->_getDriverMock(); + $driver->expects($this->at(0)) + ->method('start') + ->with('root_level_timer', null); + + $driver->expects($this->at(1)) + ->method('stop') + ->with('root_level_timer'); + + Magento_Profiler::add($driver); + Magento_Profiler::start('root_level_timer'); + Magento_Profiler::stop(); } - public function stopExceptionDataProvider() + public function testTags() { - return array( - 'stop non-started timer' => array( - array('another_root_level_timer'), array('non_started_timer') - ), - 'stop order violation' => array( - array('another_root_level_timer', 'another_nested_timer'), array('another_root_level_timer') - ), - ); + $driver = $this->_getDriverMock(); + $driver->expects($this->at(0)) + ->method('start') + ->with('root_level_timer', array('default_tag' => 'default')); + $driver->expects($this->at(1)) + ->method('start') + ->with('root_level_timer->some_other_timer', array('default_tag' => 'default', 'type' => 'test')); + + Magento_Profiler::add($driver); + Magento_Profiler::setDefaultTags(array('default_tag' => 'default')); + Magento_Profiler::start('root_level_timer'); + Magento_Profiler::start('some_other_timer', array('type' => 'test')); } - /** - * @dataProvider fetchDataProvider - */ - public function testFetch($timerId, $fetchKey, $expectedValue) + public function testClearTimer() { - $actualValue = Magento_Profiler::fetch($timerId, $fetchKey); - $this->assertEquals($expectedValue, $actualValue); + $driver = $this->_getDriverMock(); + $driver->expects($this->once()) + ->method('clear') + ->with('timer'); + + Magento_Profiler::add($driver); + Magento_Profiler::clear('timer'); } - public function fetchDataProvider() + /** + * @expectedException InvalidArgumentException + * @expectedExceptionMessage Timer name must not contain a nesting separator. + */ + public function testClearException() { - $timerId = 'some_root_timer->some_nested_timer'; - return array( - 'time' => array($timerId, Magento_Profiler::FETCH_TIME, 0.08), - 'count' => array($timerId, Magento_Profiler::FETCH_COUNT, 3), - 'avg' => array($timerId, Magento_Profiler::FETCH_AVG, 0.08 / 3), - 'emalloc' => array($timerId, Magento_Profiler::FETCH_EMALLOC, 42000000), - 'realmem' => array($timerId, Magento_Profiler::FETCH_REALMEM, 40000000), - ); + Magento_Profiler::enable(); + Magento_Profiler::clear('timer ' . Magento_Profiler::NESTING_SEPARATOR . ' name'); } - public function testFetchDefaults() + public function testResetProfiler() { - $timerId = 'some_root_timer->some_nested_timer'; - $expected = Magento_Profiler::fetch($timerId, Magento_Profiler::FETCH_TIME); - $actual = Magento_Profiler::fetch($timerId); - $this->assertEquals($expected, $actual); + $driver = $this->_getDriverMock(); + $driver->expects($this->once()) + ->method('clear') + ->with(null); + + Magento_Profiler::add($driver); + Magento_Profiler::reset(); + + $this->assertAttributeEquals(array(), '_currentPath', 'Magento_Profiler'); + $this->assertAttributeEquals(array(), '_tagFilters', 'Magento_Profiler'); + $this->assertAttributeEquals(array(), '_defaultTags', 'Magento_Profiler'); + $this->assertAttributeEquals(array(), '_drivers', 'Magento_Profiler'); + $this->assertAttributeEquals(false, '_hasTagFilters', 'Magento_Profiler'); + $this->assertAttributeEquals(0, '_pathCount', 'Magento_Profiler'); + $this->assertAttributeEquals(array(), '_pathIndex', 'Magento_Profiler'); } /** - * @dataProvider fetchExceptionDataProvider - * @expectedException Varien_Exception + * @param string $timerName + * @param array $tags + * @dataProvider skippedFilterDataProvider */ - public function testFetchException($timerId, $fetchKey) + public function testTagFilterSkip($timerName, array $tags = null) { - Magento_Profiler::fetch($timerId, $fetchKey); + $driver = $this->_getDriverMock(); + $driver->expects($this->never()) + ->method('start'); + + Magento_Profiler::add($driver); + Magento_Profiler::addTagFilter('type', 'test'); + Magento_Profiler::start($timerName, $tags); } - public function fetchExceptionDataProvider() + /** + * @return array + */ + public function skippedFilterDataProvider() { return array( - 'non-existing timer id' => array('some_non_existing_timer_id', Magento_Profiler::FETCH_TIME), - 'non-existing fetch key' => array('some_root_timer', 'some_non_existing_fetch_key'), + 'no tags' => array('timer', null), + 'no expected tags' => array('timer', array('tag' => 'value')), + 'no expected tag value' => array('timer', array('type' => 'db')), ); } - public function testGetTimers() + /** + * @param string $timerName + * @param array $tags + * @dataProvider passedFilterDataProvider + */ + public function testTagFilterPass($timerName, array $tags = null) { - $expectedTimers = array( - 'some_root_timer', - 'some_root_timer->some_nested_timer', - 'some_root_timer->some_nested_timer->some_deeply_nested_timer', - 'one_more_root_timer' - ); - $actualTimers = Magento_Profiler::getTimers(); - $this->assertEquals($expectedTimers, $actualTimers); + $driver = $this->_getDriverMock(); + $driver->expects($this->once()) + ->method('start') + ->with($timerName, $tags); + + Magento_Profiler::add($driver); + Magento_Profiler::addTagFilter('type', 'test'); + Magento_Profiler::start($timerName, $tags); } - public function testDisplay() + /** + * @return array + */ + public function passedFilterDataProvider() { - $profilerOutputOne = $this->getMockForAbstractClass('Magento_Profiler_OutputAbstract'); - $profilerOutputOne->expects($this->exactly(2)) - ->method('display') - ; - $profilerOutputTwo = $this->getMockForAbstractClass('Magento_Profiler_OutputAbstract'); - $profilerOutputTwo->expects($this->once()) - ->method('display') - ; - Magento_Profiler::registerOutput($profilerOutputOne); - Magento_Profiler::display(); - Magento_Profiler::disable(); - Magento_Profiler::registerOutput($profilerOutputTwo); - Magento_Profiler::display(); + return array( + 'one expected tag' => array('timer', array('type' => 'test')), + 'more than one tag with expected' => array('timer', array('tag' => 'value', 'type' => 'test')), + ); } } diff --git a/lib/Magento/Validator/ConstraintAbstract.php b/dev/tests/unit/testsuite/Magento/Translate/AdapterAbstractTest.php similarity index 51% rename from lib/Magento/Validator/ConstraintAbstract.php rename to dev/tests/unit/testsuite/Magento/Translate/AdapterAbstractTest.php index 92d3196a42394e9b949f89f11acf65ff8645dc3f..2c3ec554b6bd266f71b0f4d32c488070f83a196e 100644 --- a/lib/Magento/Validator/ConstraintAbstract.php +++ b/dev/tests/unit/testsuite/Magento/Translate/AdapterAbstractTest.php @@ -19,54 +19,45 @@ * needs please refer to http://www.magentocommerce.com for more information. * * @category Magento - * @package Magento_Validator + * @package unit_tests * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -/** - * Validator constraint interface. - */ -abstract class Magento_Validator_ConstraintAbstract +class Magento_Translate_AdapterAbstractTest extends PHPUnit_Framework_TestCase { - protected $_errors = array(); + /** + * @var Magento_Translate_AdapterAbstract + */ + protected $_model = null; + + protected function setUp() + { + $this->_model = $this->getMockBuilder('Magento_Translate_AdapterAbstract') + ->getMockForAbstractClass(); + } /** - * Validate field value in data. - * - * @param array $data - * @param string $field - * @return boolean + * Magento translate adapter should always return false to be used correctly be Zend Validate */ - abstract public function isValidData(array $data, $field = null); + public function testIsTranslated() + { + $this->assertFalse($this->_model->isTranslated('string')); + } /** - * Get constraint error messages. - * Errors should be stored in associative array grouped by field name, e.g. - * array( - * 'field_name_1' => array( - * 'Error message #1', - * 'Error message #2', - * ... - * ), - * 'field_name_2' => array( - * ) - * - * @return array + * Test set locale do nothing */ - public function getErrors() + public function testSetLocale() { - return $this->_errors; + $this->assertInstanceOf('Magento_Translate_AdapterAbstract', $this->_model->setLocale('en_US')); } /** - * Add error message - * - * @param string $field - * @param string $message + * Check that abstract method is implemented */ - public function addError($field, $message) + public function testToString() { - $this->_errors[$field][] = $message; + $this->assertEquals('Magento_Translate_Adapter', $this->_model->toString()); } } diff --git a/dev/tests/unit/testsuite/Magento/Translate/AdapterTest.php b/dev/tests/unit/testsuite/Magento/Translate/AdapterTest.php new file mode 100644 index 0000000000000000000000000000000000000000..c3f797495bb2e1e12d124447f90ba4061246663a --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Translate/AdapterTest.php @@ -0,0 +1,91 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Magento_Translate_AdapterTest extends PHPUnit_Framework_TestCase +{ + /** + * Check that translate calls are passed to given translator + * + * @param string $method + * @param string $strToTranslate + * @param string $translatedStr + * @dataProvider translateDataProvider + */ + public function testTranslate($method, $strToTranslate, $translatedStr) + { + $translatorMock = $this->getMockBuilder('stdClass') + ->setMethods(array('translate')) + ->getMock(); + $translatorMock->expects($this->once()) + ->method('translate') + ->with($strToTranslate) + ->will($this->returnValue($translatedStr)); + $translator = new Magento_Translate_Adapter(array( + 'translator' => array($translatorMock, 'translate') + )); + + $this->assertEquals($translatedStr, $translator->$method($strToTranslate)); + } + + /** + * @return array + */ + public function translateDataProvider() + { + return array( + array('translate', 'Translate me!', 'Translated string'), + array('__', 'Translate me!', 'Translated string') + ); + } + + /** + * Test that string is returned in any case + */ + public function testTranslateNoProxy() + { + $translator = new Magento_Translate_Adapter(); + $this->assertEquals('test string', $translator->translate('test string')); + } + + /** + * Test __() with more than one parameter passed + */ + public function testUnderscoresTranslation() + { + $translatorMock = $this->getMockBuilder('stdClass') + ->setMethods(array('translate')) + ->getMock(); + $translatorMock->expects($this->once()) + ->method('translate') + ->will($this->returnArgument(0)); + $translator = new Magento_Translate_Adapter(array( + 'translator' => array($translatorMock, 'translate') + )); + + $translatedString = $translator->__('Translated %s with %d placeholders', 'string', 2); + $this->assertEquals('Translated string with 2 placeholders', $translatedString); + } +} diff --git a/dev/tests/unit/testsuite/Magento/Validator/BuilderTest.php b/dev/tests/unit/testsuite/Magento/Validator/BuilderTest.php new file mode 100644 index 0000000000000000000000000000000000000000..6a686ac79e9c945c0c2f8f0fc94ac9cc534fdb4f --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Validator/BuilderTest.php @@ -0,0 +1,426 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Magento_Validator + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Test for Magento_Validator_Builder + */ +class Magento_Validator_BuilderTest extends PHPUnit_Framework_TestCase +{ + /** + * Test createValidator method + * + * @dataProvider createValidatorDataProvider + * + * @param array $constraints + * @param Magento_Validator_ValidatorInterface $expectedValidator + */ + public function testCreateValidator(array $constraints, $expectedValidator) + { + $builder = new Magento_Validator_Builder($constraints); + $actualValidator = $builder->createValidator(); + $this->assertEquals($expectedValidator, $actualValidator); + } + + /** + * Data provider for + * + * @return array + */ + public function createValidatorDataProvider() + { + $result = array(); + + /** @var Magento_Translate_AdapterAbstract $translator */ + $translator = $this->getMockBuilder('Magento_Translate_AdapterAbstract') + ->getMockForAbstractClass(); + Magento_Validator_ValidatorAbstract::setDefaultTranslator($translator); + + // Case 1. Check constructor with arguments + $actualConstraints = array(array( + 'alias' => 'name_alias', + 'class' => 'Magento_Validator_Test_StringLength', + 'options' => array( + 'arguments' => array(1, new Magento_Validator_Constraint_Option(20)) + ), + 'property' => 'name', + 'type' => 'property', + )); + + $expectedValidator = new Magento_Validator(); + $expectedValidator->addValidator( + new Magento_Validator_Constraint_Property( + new Magento_Validator_Test_StringLength(1, 20), 'name', 'name_alias' + ) + ); + + $result[] = array($actualConstraints, $expectedValidator); + + // Case 2. Check method calls + $actualConstraints = array(array( + 'alias' => 'description_alias', + 'class' => 'Magento_Validator_Test_StringLength', + 'options' => array( + 'methods' => array ( + array( + 'method' => 'setMin', + 'arguments' => array(10) + ), + array( + 'method' => 'setMax', + 'arguments' => array(1000) + ) + ), + ), + 'property' => 'description', + 'type' => 'property', + )); + + $expectedValidator = new Magento_Validator(); + $expectedValidator->addValidator( + new Magento_Validator_Constraint_Property( + new Magento_Validator_Test_StringLength(10, 1000), 'description', 'description_alias' + ) + ); + + $result[] = array($actualConstraints, $expectedValidator); + + // Case 3. Check callback on validator + $actualConstraints = array(array( + 'alias' => 'sku_alias', + 'class' => 'Magento_Validator_Test_StringLength', + 'options' => array( + 'callback' => array(new Magento_Validator_Constraint_Option_Callback( + function ($validator) { + $validator->setMin(20); + $validator->setMax(100); + } + )) + ), + 'property' => 'sku', + 'type' => 'property', + )); + + $expectedValidator = new Magento_Validator(); + $expectedValidator->addValidator( + new Magento_Validator_Constraint_Property( + new Magento_Validator_Test_StringLength(20, 100), 'sku', 'sku_alias' + ) + ); + + $result[] = array($actualConstraints, $expectedValidator); + + return $result; + } + + /** + * Check addConfiguration logic + * + * @dataProvider configurationDataProvider + * + * @param array $constraints + * @param string $alias + * @param array $configuration + * @param array $expected + */ + public function testAddConfiguration($constraints, $alias, $configuration, $expected) + { + $builder = new Magento_Validator_Builder($constraints); + $builder->addConfiguration($alias, $configuration); + $this->assertAttributeEquals($expected, '_constraints', $builder); + } + + /** + * Check addConfigurations logic + * + * @dataProvider configurationDataProvider + * + * @param array $constraints + * @param string $alias + * @param array $configuration + * @param array $expected + */ + public function testAddConfigurations($constraints, $alias, $configuration, $expected) + { + $builder = new Magento_Validator_Builder($constraints); + $configurations = array($alias => array($configuration)); + $builder->addConfigurations($configurations); + $this->assertAttributeEquals($expected, '_constraints', $builder); + } + + /** + * Builder configurations data provider + * + * @return array + */ + public function configurationDataProvider() + { + $callback = new Magento_Validator_Constraint_Option_Callback(array('Magento_Validator_Test_Callback', 'getId')); + $someMethod = array('method' => 'getMessages'); + $methodWithArgs = array('method' => 'setMax', 'arguments' => array(100)); + $constructorArgs = array('arguments' => array(array('max' => '50'))); + $callbackConfig = array('callback' => $callback); + + $configuredConstraint = array( + 'alias' => 'current_alias', + 'class' => 'Magento_Validator_Test_NotEmpty', + 'options' => array( + 'arguments' => array(array('min' => 1)), + 'callback' => array($callback), + 'methods' => array($someMethod) + ), + 'property' => 'int', + 'type' => 'property' + ); + $emptyConstraint = array( + 'alias' => 'current_alias', + 'class' => 'Magento_Validator_Test_NotEmpty', + 'options' => null, + 'property' => 'int', + 'type' => 'property' + ); + $constraintWithArgs = array( + 'alias' => 'current_alias', + 'class' => 'Magento_Validator_Test_NotEmpty', + 'options' => array('arguments' => array(array('min' => 1))), + 'property' => 'int', + 'type' => 'property' + ); + return array( + 'constraint is unchanged when alias not found' => array( + array($emptyConstraint), 'some_alias', $someMethod, array($emptyConstraint)), + + 'constraint options initialized with method' => array(array($emptyConstraint), 'current_alias', $someMethod, + array($this->_getExpectedConstraints($emptyConstraint, 'methods', array($someMethod)))), + + 'constraint options initialized with callback' => array(array($emptyConstraint), 'current_alias', + $callbackConfig, array($this->_getExpectedConstraints($emptyConstraint, 'callback', array($callback)))), + + 'constraint options initialized with arguments' => array( + array($emptyConstraint), 'current_alias', $constructorArgs, + array($this->_getExpectedConstraints($emptyConstraint, 'arguments', array(array('max' => '50')))) + ), + + 'methods initialized' => array( + array($constraintWithArgs), 'current_alias', $methodWithArgs, + array($this->_getExpectedConstraints($constraintWithArgs, 'methods', array($methodWithArgs))) + ), + + 'method added' => array( + array($configuredConstraint), 'current_alias', $methodWithArgs, + array($this->_getExpectedConstraints($configuredConstraint, 'methods', + array($someMethod, $methodWithArgs))) + ), + + 'callback initialized' => array( + array($constraintWithArgs), 'current_alias', $callbackConfig, + array($this->_getExpectedConstraints($constraintWithArgs, 'callback', array($callback))) + ), + + 'callback added' => array( + array($configuredConstraint), 'current_alias', $callbackConfig, + array($this->_getExpectedConstraints($configuredConstraint, 'callback', array($callback, $callback))) + ), + ); + } + + /** + * Get expected constraint configuration by actual and changes + * + * @param array $constraint + * @param string $optionKey + * @param mixed $optionValue + * @return array + */ + protected function _getExpectedConstraints($constraint, $optionKey, $optionValue) + { + if (!is_array($constraint['options'])) { + $constraint['options'] = array(); + } + $constraint['options'][$optionKey] = $optionValue; + return $constraint; + } + + /** + * Check arguments validation passed into constructor + * + * @dataProvider invalidArgumentsDataProvider + * + * @param array $options + * @param string $exception + * @param string $exceptionMessage + */ + public function testConstructorConfigValidation(array $options, $exception, $exceptionMessage) + { + $this->setExpectedException($exception, $exceptionMessage); + if (array_key_exists('method', $options)) { + $options = array( + 'methods' => array($options) + ); + } + $constraints = array(array( + 'alias' => 'alias', + 'class' => 'Magento_Validator_Test_True', + 'options' => $options, + 'type' => 'entity' + )); + new Magento_Validator_Builder($constraints); + } + + /** + * Check arguments validation passed into configuration + * + * @dataProvider invalidArgumentsDataProvider + * + * @param array $options + * @param string $exception + * @param string $exceptionMessage + */ + public function testAddConfigurationConfigValidation(array $options, $exception, $exceptionMessage) + { + $this->setExpectedException($exception, $exceptionMessage); + + $constraints = array(array( + 'alias' => 'alias', + 'class' => 'Magento_Validator_Test_True', + 'options' => null, + 'type' => 'entity' + )); + $builder = new Magento_Validator_Builder($constraints); + $builder->addConfiguration('alias', $options); + } + + /** + * Data provider for testing configuration validation + * + * @return array + */ + public function invalidArgumentsDataProvider() + { + return array( + 'constructor invalid arguments' => array( + array( + 'arguments' => 'invalid_argument' + ), + 'InvalidArgumentException', + 'Arguments must be an array' + ), + + 'methods invalid arguments' => array( + array( + 'method' => 'setValue', + 'arguments' => 'invalid_argument' + ), + 'InvalidArgumentException', + 'Method arguments must be an array' + ), + + 'methods invalid format' => array( + array( + 'method' => array('name' => 'setValue') + ), + 'InvalidArgumentException', + 'Method has to be passed as string' + ), + + 'constructor arguments invalid callback' => array( + array( + 'callback' => array('invalid', 'callback') + ), + 'InvalidArgumentException', + 'Callback must be instance of Magento_Validator_Constraint_Option_Callback' + ) + ); + } + + /** + * Check exception is thrown if validator is not an instance of Magento_Validator_ValidatorInterface + * + * @expectedException InvalidArgumentException + * @expectedExceptionMessage Constraint class "Varien_Object" must implement Magento_Validator_ValidatorInterface + */ + public function testCreateValidatorInvalidInstance() + { + $constraints = array(array( + 'alias' => 'alias', + 'class' => 'Varien_Object', + 'options' => null, + 'type' => 'entity' + )); + $builder = new Magento_Validator_Builder($constraints); + $builder->createValidator(); + } + + /** + * Test invalid configuration formats + * + * @dataProvider invalidConfigurationFormatDataProvider + * + * @expectedException InvalidArgumentException + * @expectedExceptionMessage Configuration has incorrect format + * + * @param mixed $configuration + */ + public function testAddConfigurationInvalidFormat($configuration) + { + $constraints = array(array( + 'alias' => 'alias', + 'class' => 'Magento_Validator_Test_True', + 'options' => null, + 'type' => 'entity' + )); + $builder = new Magento_Validator_Builder($constraints); + $builder->addConfigurations($configuration); + } + + /** + * Data provider for incorrect configurations + * + * @return array + */ + public function invalidConfigurationFormatDataProvider() + { + return array( + 'configuration incorrect method call' => array( + array( + 'alias' => array( + 'method' => array('name' => 'incorrectMethodCall') + ) + ) + ), + + 'configuration incorrect configuration' => array( + array( + 'alias' => array( + array( + 'data' => array('incorrectData') + ) + ) + ) + ) + ); + } +} diff --git a/dev/tests/unit/testsuite/Magento/Validator/ConfigTest.php b/dev/tests/unit/testsuite/Magento/Validator/ConfigTest.php index 89634ebf6422a108d79b0ac3cc50f0eabd078322..da2916501e71280561f484371421a97d92b7c4f1 100644 --- a/dev/tests/unit/testsuite/Magento/Validator/ConfigTest.php +++ b/dev/tests/unit/testsuite/Magento/Validator/ConfigTest.php @@ -1,5 +1,7 @@ <?php /** + * Unit Test for Magento_Validator_Config + * * Magento * * NOTICE OF LICENSE @@ -18,177 +20,290 @@ * versions in the future. If you wish to customize Magento for your * needs please refer to http://www.magentocommerce.com for more information. * - * @category Magento - * @package Magento_Validator - * @subpackage unit_tests * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ - class Magento_Validator_ConfigTest extends PHPUnit_Framework_TestCase { /** * @var Magento_Validator_Config */ - protected static $_model = null; + protected $_config = null; + + /** + * @expectedException InvalidArgumentException + * @expectedExceptionMessage There must be at least one configuration file specified. + */ + public function testConstructException() + { + $this->_initConfig(array()); + } - public static function setUpBeforeClass() + /** + * Inits $_config property with specific files or default valid configuration files + * + * @param array|null $files + */ + protected function _initConfig(array $files = null) { - self::$_model = new Magento_Validator_Config(glob(__DIR__ . '/_files/validation/positive/*/validation.xml')); + if (null === $files) { + $files = glob(__DIR__ . '/_files/validation/positive/*/validation.xml'); + } + $this->_config = new Magento_Validator_Config($files); } /** * @expectedException InvalidArgumentException + * @expectedExceptionMessage Unknown validation entity "invalid_entity" */ - public function testConstructException() + public function testCreateValidatorInvalidEntityName() { - new Magento_Validator_Config(array()); + $this->_initConfig(); + $this->_config->createValidatorBuilder('invalid_entity', null); } /** * @expectedException InvalidArgumentException + * @expectedExceptionMessage Unknown validation group "invalid_group" in entity "test_entity_a" */ - public function testGetValidationRulesInvalidEntityName() + public function testCreateValidatorInvalidGroupName() { - self::$_model->getValidationRules('invalid_entity', null); + $this->_initConfig(); + $this->_config->createValidatorBuilder('test_entity_a', 'invalid_group'); } /** * @expectedException InvalidArgumentException + * @expectedExceptionMessage Constraint class "stdClass" must implement Magento_Validator_ValidatorInterface */ - public function testGetValidationRulesInvalidGroupName() + public function testCreateValidatorInvalidConstraintClass() { - self::$_model->getValidationRules('test_entity', 'invalid_group'); + $this->_initConfig(array(__DIR__ . '/_files/validation/negative/invalid_constraint.xml')); + $this->_config->createValidator('test_entity', 'test_group'); } /** * @expectedException InvalidArgumentException + * @expectedExceptionMessage Builder class "UnknownBuilderClass" was not found */ - public function testGetValidationRulesInvalidZendConstraint() + public function testGetValidatorBuilderClassNotFound() { - $configFile = glob(__DIR__ . '/_files/validation/negative/invalid_zend_constraint.xml'); - $config = new Magento_Validator_Config($configFile); - $config->getValidationRules('test_entity', 'test_group_a'); + $this->_initConfig(array(__DIR__ . '/_files/validation/negative/invalid_builder_class.xml')); + $this->_config->createValidatorBuilder('catalog_product', 'create'); } /** * @expectedException InvalidArgumentException + * @expectedExceptionMessage Builder "stdClass" must extend Magento_Validator_Builder */ - public function testGetValidationRulesInvalidMagentoConstraint() + public function testGetValidatorBuilderInstanceInvalid() { - $configFile = glob(__DIR__ . '/_files/validation/negative/invalid_magento_constraint.xml'); - $config = new Magento_Validator_Config($configFile); - $config->getValidationRules('test_entity', 'test_group_a'); + $this->_initConfig(array(__DIR__ . '/_files/validation/negative/invalid_builder_instance.xml')); + $this->_config->createValidatorBuilder('catalog_product', 'create'); } /** - * @dataProvider getValidationRulesDataProvider - * @param string $entityName - * @param string $groupName - * @param array $expectedRules + * Test for getValidatorBuilder */ - public function testGetValidationRules($entityName, $groupName, $expectedRules) + public function testGetValidatorBuilderInstance() { - $actualRules = self::$_model->getValidationRules($entityName, $groupName); - $this->assertRulesEqual($expectedRules, $actualRules); + $this->_initConfig(); + $builder = $this->_config->createValidatorBuilder('test_entity_a', 'check_alnum'); + $this->assertInstanceOf('Magento_Validator_Builder', $builder); } /** - * Assert that all expected validation rules are present with correct constraint objects. + * @dataProvider getValidationRulesDataProvider * - * @param array $expectedRules - * @param array $actualRules + * @param string $entityName + * @param string $groupName + * @param mixed $value + * @param bool $expectedResult + * @param array $expectedMessages */ - public function assertRulesEqual(array $expectedRules, array $actualRules) + public function testCreateValidator($entityName, $groupName, $value, $expectedResult, $expectedMessages) { - foreach ($expectedRules as $expectedRule => $expectedConstraints) { - $this->assertArrayHasKey($expectedRule, $actualRules); - - foreach ($expectedConstraints as $expectedConstraint) { - $constraintFound = false; - foreach ($actualRules[$expectedRule] as $actualConstraint) { - if ($expectedConstraint['constraint'] instanceof $actualConstraint['constraint']) { - $constraintFound = true; - if (isset($expectedConstraint['field'])) { - $this->assertArrayHasKey('field', $actualConstraint); - $this->assertEquals($expectedConstraint['field'], $actualConstraint['field']); - } - break; - } - } - if (!$constraintFound) { - $this->fail(sprintf('Expected constraint "%s" was not found in the rule "%"', - get_class($expectedConstraint['constraint']), $expectedRule)); - } - } - } + $this->_initConfig(); + $validator = $this->_config->createValidator($entityName, $groupName); + $actualResult = $validator->isValid($value); + $this->assertEquals($expectedMessages, $validator->getMessages()); + $this->assertEquals($expectedResult, $actualResult); } + /** + * Data provider for testCreateConfigForInvalidXml + * + * @return array + */ public function getValidationRulesDataProvider() { - $groupARules = array( - 'test_rule_zend' => array( - array( - 'constraint' => $this->getMock('Zend_Validate_Alnum'), - 'field' => 'test_field' - ), + $result = array(); + + // Case 1. Pass check alnum and int properties are not empty and have valid value + $entityName = 'test_entity_a'; + $groupName = 'check_alnum_and_int_not_empty_and_have_valid_value'; + $value = new Varien_Object(array( + 'int' => 1, + 'alnum' => 'abc123' + )); + $expectedResult = true; + $expectedMessages = array(); + $result[] = array($entityName, $groupName, $value, $expectedResult, $expectedMessages); + + // Case 2. Fail check alnum is not empty + $value = new Varien_Object(array( + 'int' => 'abc123', + 'alnum' => null + )); + $expectedResult = false; + $expectedMessages = array( + 'alnum' => array( + 'isEmpty' => 'Value is required and can\'t be empty', + 'alnumInvalid' => 'Invalid type given. String, integer or float expected', ), - 'test_rule_constraint' => array( - array( - 'constraint' => $this->getMock('Magento_Validator_Test'), - ), + 'int' => array( + 'notInt' => '\'abc123\' does not appear to be an integer', ), ); - $groupBRules = array( - 'test_rule_constraint' => array( - array( - 'constraint' => $this->getMock('Magento_Validator_Test'), - ), - ), - 'test_rule_constraint_2' => array( - array( - 'constraint' => $this->getMock('Magento_Validator_Test'), - 'field' => 'constraint_field' - ), - ), + $result[] = array($entityName, $groupName, $value, $expectedResult, $expectedMessages); + + // Case 3. Pass check alnum has valid value + $groupName = 'check_alnum'; + $value = new Varien_Object(array( + 'int' => 'abc123', + 'alnum' => 'abc123' + )); + $expectedResult = true; + $expectedMessages = array(); + $result[] = array($entityName, $groupName, $value, $expectedResult, $expectedMessages); + + // Case 4. Fail check alnum has valid value + $value = new Varien_Object(array( + 'int' => 'abc123', + 'alnum' => '[abc123]' + )); + $expectedResult = false; + $expectedMessages = array( + 'alnum' => array( + 'notAlnum' => '\'[abc123]\' contains characters which are non alphabetic and no digits' + ) ); - $groupCRules = array( - 'test_rule' => array( - array( - 'constraint' => $this->getMock('Zend_Validate_Int'), - 'field' => 'test_field' + $result[] = array($entityName, $groupName, $value, $expectedResult, $expectedMessages); + + return $result; + } + + /** + * Check builder configuration format + */ + public function testBuilderConfiguration() + { + $this->getMockBuilder('Magento_Validator_Builder') + ->setMockClassName('Magento_Validator_Test_Builder') + ->disableOriginalConstructor() + ->getMock(); + + $this->_initConfig(array(__DIR__ . '/_files/validation/positive/builder/validation.xml')); + $builder = $this->_config->createValidatorBuilder('test_entity_a', 'check_builder'); + $this->assertInstanceOf('Magento_Validator_Test_Builder', $builder); + + $expected = array( + array( + 'alias' => '', + 'class' => 'Magento_Validator_Test_NotEmpty', + 'options' => null, + 'property' => 'int', + 'type' => 'property' + ), + array( + 'alias' => 'stub', + 'class' => 'Validator_Stub', + 'options' => array( + 'arguments' => array( + new Magento_Validator_Constraint_Option('test_string_argument'), + new Magento_Validator_Constraint_Option(array( + 'option1' => 'value1', + 'option2' => 'value2' + )), + new Magento_Validator_Constraint_Option_Callback(array( + 'Magento_Validator_Test_Callback', + 'getId' + ), null, true) + ), + 'callback' => array( + new Magento_Validator_Constraint_Option_Callback(array( + 'Magento_Validator_Test_Callback', + 'configureValidator' + ), null, true) + ), + 'methods' => array( + 'setOptionThree' => array( + 'method' => 'setOptionThree', + 'arguments' => array( + new Magento_Validator_Constraint_Option(array('argOption' => 'argOptionValue')), + new Magento_Validator_Constraint_Option_Callback(array( + 'Magento_Validator_Test_Callback', + 'getId' + ), null, true), + new Magento_Validator_Constraint_Option('10') + ) + ), + 'enableOptionFour' => array( + 'method' => 'enableOptionFour', + ) + ) ), + 'property' => 'int', + 'type' => 'property' ), ); - - return array( - array('test_entity', 'test_group_a', $groupARules), - array('test_entity', 'test_group_b', $groupBRules), - array('test_entity_b', 'test_group_c', $groupCRules), - ); + $this->assertAttributeEquals($expected, '_constraints', $builder); } - public function testGetSchemaFile() + /** + * Check XSD schema validates invalid config files + * + * @dataProvider getInvalidXmlFiles + * @expectedException Magento_Exception + * + * @param array|string $configFile + */ + public function testValidateInvalidConfigFiles($configFile) { - $this->assertFileExists(self::$_model->getSchemaFile()); + $this->_initConfig((array)$configFile); } -} -/** Dummy classes to test that constraint classes extend correct abstract. */ -class Magento_Validator_Invalid_Abstract -{ -} -class Magento_Validator_Test extends Magento_Validator_ConstraintAbstract -{ /** - * @param array $data - * @param null $field - * @return bool + * Data provider for testValidateInvalidConfigFiles * - * @SuppressWarnings(PHPMD.UnusedFormalParameter) + * @return array */ - public function isValidData(array $data, $field = null) + public function getInvalidXmlFiles() + { + // TODO: add case There are no "entity_constraints" and "property_constraints" elements inside "rule" element + return array( + array(__DIR__ . '/_files/validation/negative/no_constraint.xml'), + array(__DIR__ . '/_files/validation/negative/not_unique_use.xml'), + array(__DIR__ . '/_files/validation/negative/no_rule_for_reference.xml'), + array(__DIR__ . '/_files/validation/negative/no_name_for_entity.xml'), + array(__DIR__ . '/_files/validation/negative/no_name_for_rule.xml'), + array(__DIR__ . '/_files/validation/negative/no_name_for_group.xml'), + array(__DIR__ . '/_files/validation/negative/no_class_for_constraint.xml'), + array(__DIR__ . '/_files/validation/negative/invalid_method.xml'), + array(__DIR__ . '/_files/validation/negative/invalid_method_callback.xml'), + array(__DIR__ . '/_files/validation/negative/invalid_entity_callback.xml'), + array(__DIR__ . '/_files/validation/negative/invalid_child_for_option.xml'), + array(__DIR__ . '/_files/validation/negative/invalid_content_for_callback.xml'), + array(__DIR__ . '/_files/validation/negative/multiple_callback_in_argument.xml'), + ); + } + + /** + * Test schema file exists + */ + public function testGetSchemaFile() { - return true; + $this->_initConfig(); + $this->assertFileExists($this->_config->getSchemaFile()); } } diff --git a/dev/tests/unit/testsuite/Magento/Validator/Constraint/Option/CallbackTest.php b/dev/tests/unit/testsuite/Magento/Validator/Constraint/Option/CallbackTest.php new file mode 100644 index 0000000000000000000000000000000000000000..e0b25d0e178e1b805488367749ccd66ea3c45db2 --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Validator/Constraint/Option/CallbackTest.php @@ -0,0 +1,178 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Magento_Validator + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Test case for Magento_Validator_Constraint_Option_Callback + */ +class Magento_Validator_Constraint_Option_CallbackTest extends PHPUnit_Framework_TestCase +{ + /** + * Value for test + */ + const TEST_VALUE = 'test'; + + /** + * Test getValue method + * + * @dataProvider getValueDataProvider + * + * @param callable $callback + * @param mixed $expectedResult + * @param null $arguments + * @param bool $createInstance + */ + public function testGetValue($callback, $expectedResult, $arguments = null, $createInstance = false) + { + $option = new Magento_Validator_Constraint_Option_Callback($callback, $arguments, $createInstance); + $this->assertEquals($expectedResult, $option->getValue()); + } + + /** + * Data provider for testGetValue + */ + public function getValueDataProvider() + { + $functionName = create_function('', 'return "Value from function";'); + $closure = function () { + return 'Value from closure'; + }; + + $mock = $this->getMockBuilder('Foo') + ->setMethods(array('getValue')) + ->getMock(); + $mock->expects($this->once()) + ->method('getValue') + ->with('arg1', 'arg2') + ->will($this->returnValue('Value from mock')); + + return array( + array($functionName, 'Value from function'), + array($closure, 'Value from closure'), + array(array($this, 'getTestValue'), self::TEST_VALUE), + array(array(__CLASS__, 'getTestValueStatically'), self::TEST_VALUE), + array(array($mock, 'getValue'), 'Value from mock', array('arg1', 'arg2')), + array(array('Magento_Validator_Test_Callback', 'getId'), Magento_Validator_Test_Callback::ID, null, true) + ); + } + + /** + * Get TEST_VALUE from static scope + */ + static public function getTestValueStatically() + { + return self::TEST_VALUE; + } + + /** + * Get TEST_VALUE + */ + public function getTestValue() + { + return self::TEST_VALUE; + } + + /** + * Test setArguments method + * + * @dataProvider setArgumentsDataProvider + * + * @param mixed $value + * @param mixed $expectedValue + */ + public function testSetArguments($value, $expectedValue) + { + $option = new Magento_Validator_Constraint_Option_Callback( + function () { + } + ); + $option->setArguments($value); + $this->assertAttributeEquals($expectedValue, '_arguments', $option); + } + + /** + * Data provider for testGetValue + */ + public function setArgumentsDataProvider() + { + return array( + array('baz', array('baz')), + array(array('foo', 'bar'), array('foo', 'bar')) + ); + } + + /** + * Test getValue method raises InvalidArgumentException + * + * @dataProvider getValueExceptionDataProvider + * + * @param mixed $callback + * @param string $expectedMessage + * @param bool $createInstance + */ + public function testGetValueException($callback, $expectedMessage, $createInstance = false) + { + $option = new Magento_Validator_Constraint_Option_Callback($callback, null, $createInstance); + $this->setExpectedException('InvalidArgumentException', $expectedMessage); + $option->getValue(); + } + + /** + * Data provider for testGetValueException + * + * @return array + */ + public function getValueExceptionDataProvider() + { + return array( + array( + array('Not_Existing_Callback_Class', 'someMethod'), + 'Class "Not_Existing_Callback_Class" was not found' + ), + array( + array($this, 'notExistingMethod'), + 'Callback does not callable' + ), + array( + array('object' => $this, 'method' => 'getTestValue'), + 'Callback does not callable' + ), + array( + 'unknown_function', + 'Callback does not callable' + ), + array( + new stdClass(), + 'Callback does not callable' + ), + array( + array($this, 'getTestValue'), + 'Callable expected to be an array with class name as first element', + true, + ) + ); + } +} diff --git a/app/code/core/Mage/Api/Model/Resource/Acl/Role/Collection.php b/dev/tests/unit/testsuite/Magento/Validator/Constraint/OptionTest.php old mode 100755 new mode 100644 similarity index 67% rename from app/code/core/Mage/Api/Model/Resource/Acl/Role/Collection.php rename to dev/tests/unit/testsuite/Magento/Validator/Constraint/OptionTest.php index 69b4adff04d022e585218497613e7853725eaaee..8c6628796cc5b5eceba3723201cc19e18c6e1519 --- a/app/code/core/Mage/Api/Model/Resource/Acl/Role/Collection.php +++ b/dev/tests/unit/testsuite/Magento/Validator/Constraint/OptionTest.php @@ -18,28 +18,25 @@ * versions in the future. If you wish to customize Magento for your * needs please refer to http://www.magentocommerce.com for more information. * - * @category Mage - * @package Mage_Api + * @category Magento + * @package Magento_Validator + * @subpackage unit_tests * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ - /** - * Acl Role Resource Collection - * - * @category Mage - * @package Mage_Api - * @author Magento Core Team <core@magentocommerce.com> + * Test case for Magento_Validator_Constraint_Option */ -class Mage_Api_Model_Resource_Acl_Role_Collection extends Mage_Core_Model_Resource_Db_Collection_Abstract +class Magento_Validator_Constraint_OptionTest extends PHPUnit_Framework_TestCase { /** - * Resource collection initialization - * + * Test getValue */ - protected function _construct() + public function testGetValue() { - $this->_init('Mage_Api_Model_Role', 'Mage_Api_Model_Resource_Role'); + $expected = 'test_value'; + $option = new Magento_Validator_Constraint_Option($expected); + $this->assertEquals($expected, $option->getValue()); } } diff --git a/dev/tests/unit/testsuite/Magento/Validator/Constraint/PropertyTest.php b/dev/tests/unit/testsuite/Magento/Validator/Constraint/PropertyTest.php new file mode 100644 index 0000000000000000000000000000000000000000..e3058c414584ff2fd8bc57e1d2350793cf409ce4 --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Validator/Constraint/PropertyTest.php @@ -0,0 +1,141 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Magento_Validator + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Test case for Magento_Validator_Constraint_Property + */ +class Magento_Validator_Constraint_PropertyTest extends PHPUnit_Framework_TestCase +{ + const PROPERTY_NAME = 'test'; + + /** + * @var Magento_Validator_Constraint_Property + */ + protected $_constraint; + + /** + * @var Magento_Validator_ValidatorInterface|PHPUnit_Framework_MockObject_MockObject + */ + protected $_validatorMock; + + /** + * Set up + */ + protected function setUp() + { + $this->_validatorMock = $this->getMock('Magento_Validator_ValidatorInterface'); + $this->_constraint = new Magento_Validator_Constraint_Property($this->_validatorMock, self::PROPERTY_NAME); + } + + /** + * Test getAlias method + */ + public function testGetAlias() + { + $this->assertEmpty($this->_constraint->getAlias()); + $alias = 'foo'; + $constraint = new Magento_Validator_Constraint_Property($this->_validatorMock, self::PROPERTY_NAME, $alias); + $this->assertEquals($alias, $constraint->getAlias()); + } + + /** + * Test isValid method + * + * @dataProvider isValidDataProvider + * + * @param mixed $value + * @param mixed $validateValue + * @param bool $expectedResult + * @param array $validatorMessages + * @param array $expectedMessages + */ + public function testIsValid($value, $validateValue, $expectedResult, $validatorMessages = array(), + $expectedMessages = array() + ) { + $this->_validatorMock + ->expects($this->once())->method('isValid') + ->with($validateValue)->will($this->returnValue($expectedResult)); + + if ($expectedResult) { + $this->_validatorMock->expects($this->never())->method('getMessages'); + } else { + $this->_validatorMock + ->expects($this->once())->method('getMessages') + ->will($this->returnValue($validatorMessages)); + } + + $this->assertEquals($expectedResult, $this->_constraint->isValid($value)); + $this->assertEquals($expectedMessages, $this->_constraint->getMessages()); + } + + /** + * Data provider for testIsValid + * + * @return array + */ + public function isValidDataProvider() + { + return array( + array( + array(self::PROPERTY_NAME => 'Property value', 'foo' => 'Foo value'), + 'Property value', + true + ), + array( + new Varien_Object(array(self::PROPERTY_NAME => 'Property value')), + 'Property value', + true + ), + array( + new ArrayObject(array(self::PROPERTY_NAME => 'Property value')), + 'Property value', + true + ), + array( + array(self::PROPERTY_NAME => 'Property value', 'foo' => 'Foo value'), + 'Property value', + false, + array('Error message 1', 'Error message 2'), + array(self::PROPERTY_NAME => array('Error message 1', 'Error message 2')), + ), + array( + array('foo' => 'Foo value'), + null, + false, + array('Error message 1'), + array(self::PROPERTY_NAME => array('Error message 1')), + ), + array( + 'scalar', + null, + false, + array('Error message 1'), + array(self::PROPERTY_NAME => array('Error message 1')), + ) + ); + } +} diff --git a/dev/tests/unit/testsuite/Magento/Validator/ConstraintTest.php b/dev/tests/unit/testsuite/Magento/Validator/ConstraintTest.php new file mode 100644 index 0000000000000000000000000000000000000000..223a33132b33431a0143df75db415c8ee7024618 --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Validator/ConstraintTest.php @@ -0,0 +1,122 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Magento_Validator + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Test case for Magento_Validator_Constraint + */ +class Magento_Validator_ConstraintTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Magento_Validator_Constraint + */ + protected $_constraint; + + /** + * @var Magento_Validator_ValidatorInterface|PHPUnit_Framework_MockObject_MockObject + */ + protected $_validatorMock; + + /** + * Set up + */ + protected function setUp() + { + $this->_validatorMock = $this->getMockBuilder('Magento_Validator_ValidatorAbstract') + ->setMethods(array('isValid', 'getMessages')) + ->getMock(); + $this->_constraint = new Magento_Validator_Constraint($this->_validatorMock); + } + + /** + * Test getAlias method + */ + public function testGetAlias() + { + $this->assertEmpty($this->_constraint->getAlias()); + $alias = 'foo'; + $constraint = new Magento_Validator_Constraint($this->_validatorMock, $alias); + $this->assertEquals($alias, $constraint->getAlias()); + } + + /** + * Test isValid method + * + * @dataProvider isValidDataProvider + * + * @param mixed $value + * @param bool $expectedResult + * @param array $expectedMessages + */ + public function testIsValid($value, $expectedResult, $expectedMessages = array()) + { + $this->_validatorMock + ->expects($this->once()) + ->method('isValid') + ->with($value) + ->will($this->returnValue($expectedResult)); + + if ($expectedResult) { + $this->_validatorMock + ->expects($this->never()) + ->method('getMessages'); + } else { + $this->_validatorMock + ->expects($this->once()) + ->method('getMessages') + ->will($this->returnValue($expectedMessages)); + } + + $this->assertEquals($expectedResult, $this->_constraint->isValid($value)); + $this->assertEquals($expectedMessages, $this->_constraint->getMessages()); + } + + /** + * Data provider for testIsValid + * + * @return array + */ + public function isValidDataProvider() + { + return array( + array('test', true), + array('test', false, array('foo')) + ); + } + + /** + * Check translator was set into wrapped validator + */ + public function testSetTranslator() + { + /** @var Magento_Translate_AdapterAbstract $translator */ + $translator = $this->getMockBuilder('Magento_Translate_AdapterInterface') + ->getMockForAbstractClass(); + $this->_constraint->setTranslator($translator); + $this->assertEquals($translator, $this->_validatorMock->getTranslator()); + $this->assertEquals($translator, $this->_constraint->getTranslator()); + } +} diff --git a/dev/tests/unit/testsuite/Magento/Validator/Entity/PropertiesTest.php b/dev/tests/unit/testsuite/Magento/Validator/Entity/PropertiesTest.php new file mode 100644 index 0000000000000000000000000000000000000000..78da0bdf5f56f90a9ea53c76d9745aa7568eed54 --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Validator/Entity/PropertiesTest.php @@ -0,0 +1,107 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Magento_Validator + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Test for Magento_Validator_Entity_Properties + */ +class Magento_Validator_Entity_PropertiesTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Varien_Object + */ + protected $_object; + + protected function setUp() + { + $this->_object = $this->getMock('Varien_Object', array('hasDataChanges', 'getData', 'getOrigData')); + } + + protected function tearDown() + { + unset($this->_object); + } + + /** + * Testing Magento_Validator_Entity_Properties::isValid on invalid argument passed + * + * @expectedException InvalidArgumentException + * @expectedExceptionMessage Instance of Varien_Object is expected. + */ + public function testIsValidException() + { + $validator = new Magento_Validator_Entity_Properties(); + $validator->isValid(array()); + } + + /** + * Testing Magento_Validator_Entity_Properties::isValid with hasDataChanges and invoked setter + */ + public function testIsValidSuccessWithInvokedSetter() + { + $this->_object->expects($this->once())->method('hasDataChanges')->will($this->returnValue(true)); + $this->_object->expects($this->once())->method('getData')->with('attr1')->will($this->returnValue(1)); + $this->_object->expects($this->once())->method('getOrigData')->with('attr1')->will($this->returnValue(1)); + + $validator = new Magento_Validator_Entity_Properties(); + $validator->setReadOnlyProperties(array('attr1')); + $this->assertTrue($validator->isValid($this->_object)); + } + + /** + * Testing Magento_Validator_Entity_Properties::isValid without invoked setter + */ + public function testIsValidSuccessWithoutInvokedSetter() + { + $validator = new Magento_Validator_Entity_Properties(); + $this->assertTrue($validator->isValid($this->_object)); + } + + /** + * Testing Magento_Validator_Entity_Properties::isValid with unchanged data + */ + public function testIsValidSuccessWithoutHasDataChanges() + { + $this->_object->expects($this->once())->method('hasDataChanges')->will($this->returnValue(false)); + $validator = new Magento_Validator_Entity_Properties(); + $validator->setReadOnlyProperties(array('attr1')); + $this->assertTrue($validator->isValid($this->_object)); + } + + /** + * Testing Magento_Validator_Entity_Properties::isValid with changed data and invoked setter + */ + public function testIsValidFailed() + { + $this->_object->expects($this->once())->method('hasDataChanges')->will($this->returnValue(true)); + $this->_object->expects($this->once())->method('getData')->with('attr1')->will($this->returnValue(1)); + $this->_object->expects($this->once())->method('getOrigData')->with('attr1')->will($this->returnValue(2)); + + $validator = new Magento_Validator_Entity_Properties(); + $validator->setReadOnlyProperties(array('attr1')); + $this->assertFalse($validator->isValid($this->_object)); + } +} diff --git a/dev/tests/unit/testsuite/Magento/Validator/ConstraintAbstractTest.php b/dev/tests/unit/testsuite/Magento/Validator/ExceptionTest.php similarity index 62% rename from dev/tests/unit/testsuite/Magento/Validator/ConstraintAbstractTest.php rename to dev/tests/unit/testsuite/Magento/Validator/ExceptionTest.php index 4d6709344c20f6aef3ef11a37cd04f17aefb7014..7a8e69b8d95c74df1597eeafb240837e7b641903 100644 --- a/dev/tests/unit/testsuite/Magento/Validator/ConstraintAbstractTest.php +++ b/dev/tests/unit/testsuite/Magento/Validator/ExceptionTest.php @@ -25,21 +25,27 @@ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -class Magento_Validator_ConstraintAbstractTest extends PHPUnit_Framework_TestCase +/** + * Test case for Magento_Validator_Exception + */ +class Magento_Validator_ExceptionTest extends PHPUnit_Framework_TestCase { - public function testAddGetErrors() + /** + * Testing Magento_Validator_Exception::getMessage + */ + public function testGetMessage() { - $expectedErrors = array( - 'test_field' => array( - 'test error #1', - 'test error #2', + $expectedMessage = 'error1' . PHP_EOL . 'error2' . PHP_EOL . 'error3'; + $messages = array( + 'field1' => array( + 'error1', + 'error2' + ), + 'field2' => array( + 'error3' ) ); - /** @var Magento_Validator_ConstraintAbstract $constraint */ - $constraint = $this->getMockForAbstractClass('Magento_Validator_ConstraintAbstract'); - $constraint->addError('test_field', 'test error #1'); - $constraint->addError('test_field', 'test error #2'); - - $this->assertEquals($expectedErrors, $constraint->getErrors()); + $exception = new Magento_Validator_Exception($messages); + $this->assertEquals($expectedMessage, $exception->getMessage()); } } diff --git a/dev/tests/unit/testsuite/Magento/Validator/StringLengthTest.php b/dev/tests/unit/testsuite/Magento/Validator/StringLengthTest.php new file mode 100644 index 0000000000000000000000000000000000000000..93335bce8077a9e8cc5dfdfe58828ffb571b7428 --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Validator/StringLengthTest.php @@ -0,0 +1,72 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Magento_Validator + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Test case for Magento_Validator_StringLength + */ +class Magento_Validator_StringLengthTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Magento_Validator_StringLength + */ + protected $_validator; + + protected function setUp() + { + $this->_validator = new Magento_Validator_StringLength(); + } + + public function testDefaultEncoding() + { + $this->assertEquals('UTF-8', $this->_validator->getEncoding()); + } + + /** + * @dataProvider isValidDataProvider + * @param string $value + * @param int $maxLength + * @param bool $isValid + */ + public function testIsValid($value, $maxLength, $isValid) + { + $this->_validator->setMax($maxLength); + $this->assertEquals($isValid, $this->_validator->isValid($value)); + } + + /** + * @return array + */ + public function isValidDataProvider() + { + return array( + array('Ñтрока', 6, true), + array('Ñтрока', 5, false), + array('string', 6, true), + array('string', 5, false), + ); + } +} diff --git a/app/code/core/Mage/Sales/Model/Order/Api/V2.php b/dev/tests/unit/testsuite/Magento/Validator/Test/Alnum.php similarity index 79% rename from app/code/core/Mage/Sales/Model/Order/Api/V2.php rename to dev/tests/unit/testsuite/Magento/Validator/Test/Alnum.php index 4bae55cb241e315f4855e96c2ffb66a092bd77ed..8aa435485168bb905fd0da508220953890936a45 100644 --- a/app/code/core/Mage/Sales/Model/Order/Api/V2.php +++ b/dev/tests/unit/testsuite/Magento/Validator/Test/Alnum.php @@ -18,19 +18,16 @@ * versions in the future. If you wish to customize Magento for your * needs please refer to http://www.magentocommerce.com for more information. * - * @category Mage - * @package Mage_Sales + * @category Magento + * @package Magento_Validator + * @subpackage unit_tests * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ /** - * Order API V2 - * - * @category Mage - * @package Mage_Sales - * @author Magento Core Team <core@magentocommerce.com> + * Alphanumerical test validator */ -class Mage_Sales_Model_Order_Api_V2 extends Mage_Sales_Model_Order_Api +class Magento_Validator_Test_Alnum extends Zend_Validate_Alnum implements Magento_Validator_ValidatorInterface { } diff --git a/dev/tests/unit/testsuite/Magento/Validator/Test/Callback.php b/dev/tests/unit/testsuite/Magento/Validator/Test/Callback.php new file mode 100644 index 0000000000000000000000000000000000000000..15b2a00278494b53911f5e0638fab6d36f67abcd --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Validator/Test/Callback.php @@ -0,0 +1,49 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Magento_Validator + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Class with callback for testing callbacks + */ +class Magento_Validator_Test_Callback +{ + const ID = 3; + + /** + * @return int + */ + public function getId() + { + return self::ID; + } + + /** + * Fake method for testing callbacks + */ + public function configureValidator() + { + } +} diff --git a/app/code/core/Mage/Api/Model/Acl/Role/User.php b/dev/tests/unit/testsuite/Magento/Validator/Test/Int.php similarity index 78% rename from app/code/core/Mage/Api/Model/Acl/Role/User.php rename to dev/tests/unit/testsuite/Magento/Validator/Test/Int.php index 494b0b56a5a84adcc9d6590eaaa7ce52e3a7d145..da5b08aacad2aa47915d2d52f2aa6fb304dd8284 100644 --- a/app/code/core/Mage/Api/Model/Acl/Role/User.php +++ b/dev/tests/unit/testsuite/Magento/Validator/Test/Int.php @@ -18,21 +18,16 @@ * versions in the future. If you wish to customize Magento for your * needs please refer to http://www.magentocommerce.com for more information. * - * @category Mage - * @package Mage_Api + * @category Magento + * @package Magento_Validator + * @subpackage unit_tests * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ - /** - * User acl role - * - * @category Mage - * @package Mage_Api - * @author Magento Core Team <core@magentocommerce.com> + * Integer test validator */ -class Mage_Api_Model_Acl_Role_User extends Mage_Api_Model_Acl_Role_Generic +class Magento_Validator_Test_Int extends Zend_Validate_Int implements Magento_Validator_ValidatorInterface { - } diff --git a/dev/tests/unit/testsuite/Magento/Validator/Test/NotEmpty.php b/dev/tests/unit/testsuite/Magento/Validator/Test/NotEmpty.php new file mode 100644 index 0000000000000000000000000000000000000000..8cbba28a084c2afd8eb2d10f5cfa6f0f79753b76 --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Validator/Test/NotEmpty.php @@ -0,0 +1,33 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Magento_Validator + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Not empty test validator + */ +class Magento_Validator_Test_NotEmpty extends Zend_Validate_NotEmpty implements Magento_Validator_ValidatorInterface +{ +} diff --git a/dev/tests/unit/testsuite/Magento/Validator/Test/StringLength.php b/dev/tests/unit/testsuite/Magento/Validator/Test/StringLength.php new file mode 100644 index 0000000000000000000000000000000000000000..24c7001245a297f3edb4f1ca790246ff935649b7 --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Validator/Test/StringLength.php @@ -0,0 +1,34 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Magento_Validator + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * String length test validator + */ +class Magento_Validator_Test_StringLength extends Zend_Validate_StringLength + implements Magento_Validator_ValidatorInterface +{ +} diff --git a/dev/tests/unit/testsuite/Magento/Validator/Test/True.php b/dev/tests/unit/testsuite/Magento/Validator/Test/True.php new file mode 100644 index 0000000000000000000000000000000000000000..d436ca747a9e74ddd7444a058035cec9b1715d14 --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Validator/Test/True.php @@ -0,0 +1,45 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Magento_Validator + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Test validator that always returns TRUE + */ +class Magento_Validator_Test_True extends Magento_Validator_ValidatorAbstract +{ + /** + * Validate value + * + * @param mixed $value + * @return bool + * + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function isValid($value) + { + return true; + } +} diff --git a/dev/tests/unit/testsuite/Magento/Validator/ValidatorAbstractTest.php b/dev/tests/unit/testsuite/Magento/Validator/ValidatorAbstractTest.php new file mode 100644 index 0000000000000000000000000000000000000000..c65c6e206bfe630740c6fe6c4c809252e68ab430 --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Validator/ValidatorAbstractTest.php @@ -0,0 +1,96 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Magento_Validator + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Test case for Magento_Validator_ValidatorAbstract + */ +class Magento_Validator_ValidatorAbstractTest extends PHPUnit_Framework_TestCase +{ + /** + * @var null|Magento_Translate_AdapterInterface + */ + protected $_defaultTranslator = null; + + protected function setUp() + { + $this->_defaultTranslator = Magento_Validator_ValidatorAbstract::getDefaultTranslator(); + } + + protected function tearDown() + { + Magento_Validator_ValidatorAbstract::setDefaultTranslator($this->_defaultTranslator); + } + + /** + * Get translator object + * + * @return PHPUnit_Framework_MockObject_MockObject|Magento_Translate_AdapterAbstract + */ + protected function _getTranslator() + { + return $this->getMockBuilder('Magento_Translate_AdapterInterface') + ->getMockForAbstractClass(); + } + + /** + * Test default translator get/set + */ + public function testDefaultTranslatorGetSet() + { + $translator = $this->_getTranslator(); + Magento_Validator_ValidatorAbstract::setDefaultTranslator($translator); + $this->assertEquals($translator, Magento_Validator_ValidatorAbstract::getDefaultTranslator()); + } + + /** + * Test get/set/has translator + */ + public function testTranslatorGetSetHas() + { + /** @var Magento_Validator_ValidatorAbstract $validator */ + $validator = $this->getMockBuilder('Magento_Validator_ValidatorAbstract') + ->getMockForAbstractClass(); + $translator = $this->_getTranslator(); + $validator->setTranslator($translator); + $this->assertEquals($translator, $validator->getTranslator()); + $this->assertTrue($validator->hasTranslator()); + } + + /** + * Check that default translator returned if set and no translator set + */ + public function testGetTranslatorDefault() + { + /** @var Magento_Validator_ValidatorAbstract $validator */ + $validator = $this->getMockBuilder('Magento_Validator_ValidatorAbstract') + ->getMockForAbstractClass(); + $translator = $this->_getTranslator(); + Magento_Validator_ValidatorAbstract::setDefaultTranslator($translator); + $this->assertEquals($translator, $validator->getTranslator()); + $this->assertFalse($validator->hasTranslator()); + } +} diff --git a/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/invalid_builder_class.xml b/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/invalid_builder_class.xml new file mode 100644 index 0000000000000000000000000000000000000000..16e32915eb682dad257c3fc270f56f5a2f3fef7e --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/invalid_builder_class.xml @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Academic Free License (AFL 3.0) + * that is bundled with this package in the file LICENSE_AFL.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/afl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Magento_Validator + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ +--> +<validation> + <entity name="catalog_product"> + <rules> + <rule name="name_sku_and_price"> + <property_constraints> + <property name="name"> + <constraint alias="some_validator" class="Magento_Validator_StringLenght"/> + </property> + </property_constraints> + </rule> + </rules> + <groups> + <!-- builder with class UnknownBuilderClass is not exists --> + <group name="create" builder="UnknownBuilderClass"> + <uses> + <use rule="name_sku_and_price"/> + </uses> + </group> + </groups> + </entity> +</validation> diff --git a/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/invalid_builder_instance.xml b/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/invalid_builder_instance.xml new file mode 100644 index 0000000000000000000000000000000000000000..6491835d19cba401d5b478d5d4a03e8a29178679 --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/invalid_builder_instance.xml @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Academic Free License (AFL 3.0) + * that is bundled with this package in the file LICENSE_AFL.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/afl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Magento_Validator + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ +--> +<validation> + <entity name="catalog_product"> + <rules> + <rule name="name_sku_and_price"> + <property_constraints> + <property name="name"> + <constraint alias="some_validator" class="Magento_Validator_StringLenght"/> + </property> + </property_constraints> + </rule> + </rules> + <groups> + <!-- builder class must implement Magento_Validator_Builder --> + <group name="create" builder="stdClass"> + <uses> + <use rule="name_sku_and_price"/> + </uses> + </group> + </groups> + </entity> +</validation> diff --git a/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/invalid_child_for_option.xml b/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/invalid_child_for_option.xml new file mode 100644 index 0000000000000000000000000000000000000000..5ff6b80f553f0b7af1812756f952e6f22576ebeb --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/invalid_child_for_option.xml @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Academic Free License (AFL 3.0) + * that is bundled with this package in the file LICENSE_AFL.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/afl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Magento_Validator + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ +--> +<validation> + <entity name="catalog_product"> + <rules> + <rule name="name_sku_and_price"> + <property_constraints> + <property name="name"> + <constraint alias="some_validator" class="Magento_Validator_StringLenght"> + <argument> + <option name="min" > + <!-- option can contain only text --> + <option name="1">5</option> + </option> + </argument> + </constraint> + </property> + </property_constraints> + </rule> + </rules> + <groups> + <group name="create"> + <uses> + <use rule="name_sku_and_price"/> + </uses> + </group> + </groups> + </entity> +</validation> diff --git a/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/invalid_magento_constraint.xml b/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/invalid_constraint.xml similarity index 83% rename from dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/invalid_magento_constraint.xml rename to dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/invalid_constraint.xml index 5e2d57e671ae2b8c060785493a315b4e3c76db3c..582dd80ac344a4cfd8f604bedfac4403a6ce8d2d 100644 --- a/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/invalid_magento_constraint.xml +++ b/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/invalid_constraint.xml @@ -29,17 +29,17 @@ <validation> <entity name="test_entity"> <rules> - <rule name="test_rule_zend"> - <constraints> + <rule name="test_rule"> + <entity_constraints> <!-- Class that does not implements any of valid interfaces --> - <constraint class="Magento_Validator_Invalid_Abstract"/> - </constraints> + <constraint class="stdClass"/> + </entity_constraints> </rule> </rules> <groups> - <group name="test_group_a"> + <group name="test_group"> <uses> - <use rule="test_rule_zend"/> + <use rule="test_rule"/> </uses> </group> </groups> diff --git a/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/invalid_content_for callback.xml b/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/invalid_content_for callback.xml new file mode 100644 index 0000000000000000000000000000000000000000..c5a52b07d315c83ddc78a643b64de0a60984f43b --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/invalid_content_for callback.xml @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Academic Free License (AFL 3.0) + * that is bundled with this package in the file LICENSE_AFL.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/afl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Magento_Validator + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ +--> +<validation> + <entity name="catalog_product"> + <rules> + <rule name="name_sku_and_price"> + <entity_constraints> + <constraint alias="eav_validator" class="Mage_Catalog_Model_Validator_Eav" > + <!-- callback element should be empty --> + <callback method="someMethod" class="Mage_Catalog_Model_Validator_Eav" >some test</callback> + </constraint> + </entity_constraints> + </rule> + </rules> + <groups> + <group name="create"> + <uses> + <use rule="name_sku_and_price"/> + </uses> + </group> + </groups> + </entity> +</validation> diff --git a/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/invalid_entity_callback.xml b/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/invalid_entity_callback.xml new file mode 100644 index 0000000000000000000000000000000000000000..00ba519b8f5bb6f13ea7fcf116d751ce4a443f29 --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/invalid_entity_callback.xml @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Academic Free License (AFL 3.0) + * that is bundled with this package in the file LICENSE_AFL.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/afl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Magento_Validator + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ +--> +<validation> + <entity name="catalog_product"> + <rules> + <rule name="name_sku_and_price"> + <entity_constraints> + <constraint alias="eav_validator" class="Mage_Catalog_Model_Validator_Eav" > + <!-- attribute class is required for callback element --> + <callback method="someMethod" /> + </constraint> + </entity_constraints> + </rule> + </rules> + <groups> + <group name="create"> + <uses> + <use rule="name_sku_and_price"/> + </uses> + </group> + </groups> + </entity> +</validation> diff --git a/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/invalid_method.xml b/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/invalid_method.xml new file mode 100644 index 0000000000000000000000000000000000000000..a1adda646013fd8700e737bbb7d547a12c316893 --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/invalid_method.xml @@ -0,0 +1,56 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Academic Free License (AFL 3.0) + * that is bundled with this package in the file LICENSE_AFL.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/afl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Magento_Validator + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ +--> +<validation> + <entity name="catalog_product"> + <rules> + <rule name="name_sku_and_price"> + <property_constraints> + <property name="name"> + <constraint alias="some_validator" class="Magento_Validator_StringLenght"> + <!-- attribute class is not allowed for method element --> + <method name="setOptions" class="Object"> + </method> + <!-- attribute name is required for method element --> + <method > + <argument>7</argument> + </method> + </constraint> + </property> + </property_constraints> + </rule> + </rules> + <groups> + <group name="create"> + <uses> + <use rule="name_sku_and_price"/> + </uses> + </group> + </groups> + </entity> +</validation> diff --git a/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/invalid_method_callback.xml b/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/invalid_method_callback.xml new file mode 100644 index 0000000000000000000000000000000000000000..7e92483cd9df95e1dc8fbccfb502b832fe0f9498 --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/invalid_method_callback.xml @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Academic Free License (AFL 3.0) + * that is bundled with this package in the file LICENSE_AFL.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/afl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Magento_Validator + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ +--> +<validation> + <entity name="catalog_product"> + <rules> + <rule name="name_sku_and_price"> + <property_constraints> + <property name="name"> + <constraint alias="some_validator" class="Magento_Validator_StringLenght"> + <method name="setOptions"> + <argument> + <!-- attribute class is required for callback element --> + <callback method="getSomeValue"/> + </argument> + </method> + </constraint> + </property> + </property_constraints> + </rule> + </rules> + <groups> + <group name="create"> + <uses> + <use rule="name_sku_and_price"/> + </uses> + </group> + </groups> + </entity> +</validation> diff --git a/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/multiple_callback_in_argument.xml b/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/multiple_callback_in_argument.xml new file mode 100644 index 0000000000000000000000000000000000000000..a0ad53eb6358ac0383ef36b10408aefb0f64d921 --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/multiple_callback_in_argument.xml @@ -0,0 +1,56 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Academic Free License (AFL 3.0) + * that is bundled with this package in the file LICENSE_AFL.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/afl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Magento_Validator + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ +--> +<validation> + <entity name="catalog_product"> + <rules> + <rule name="name_sku_and_price"> + <property_constraints> + <property name="name"> + <constraint alias="some_validator" class="Magento_Validator_StringLenght"> + <method name="setOptions"> + <argument> + <!-- argument element can contain only one callback element --> + <callback method="getSomeValue" class="Magento_Validator_StringLenght"/> + <callback method="getMethod" class="Magento_Validator_StringLenght"/> + </argument> + </method> + </constraint> + </property> + </property_constraints> + </rule> + </rules> + <groups> + <group name="create"> + <uses> + <use rule="name_sku_and_price"/> + </uses> + </group> + </groups> + </entity> +</validation> diff --git a/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/no_class_for_constraint.xml b/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/no_class_for_constraint.xml new file mode 100644 index 0000000000000000000000000000000000000000..344622e16d0b406bf6f538daede7527fc08c4704 --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/no_class_for_constraint.xml @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Academic Free License (AFL 3.0) + * that is bundled with this package in the file LICENSE_AFL.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/afl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Magento_Validator + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ +--> +<validation> + <entity name="test_entity"> + <rules> + <rule name="test_rule_constraint"> + <entity_constraints> + <!-- attribute class is required for tag element --> + <constraint alias="eav_validator"/> + </entity_constraints> + </rule> + </rules> + <groups> + <group name="test_group"> + <uses> + <use rule="test_rule_constraint"/> + </uses> + </group> + </groups> + </entity> +</validation> diff --git a/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/invalid_zend_constraint.xml b/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/no_constraint.xml similarity index 82% rename from dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/invalid_zend_constraint.xml rename to dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/no_constraint.xml index 4d4c2cecc5020e94aa476e1c62f465502a0303bc..0167bbdb0f9735ab5a4759fdce1c0b0253709db4 100644 --- a/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/invalid_zend_constraint.xml +++ b/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/no_constraint.xml @@ -29,17 +29,16 @@ <validation> <entity name="test_entity"> <rules> - <rule name="test_rule_zend"> - <constraints> - <!-- Zend constraint must have field attribute --> - <constraint class="Zend_Validate_Alnum"/> - </constraints> + <rule name="test_rule_a"> + <entity_constraints> + <!-- constraint element is expected here --> + </entity_constraints> </rule> </rules> <groups> <group name="test_group_a"> <uses> - <use rule="test_rule_zend"/> + <use rule="test_rule_a"/> </uses> </group> </groups> diff --git a/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/no_name_for_entity.xml b/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/no_name_for_entity.xml new file mode 100644 index 0000000000000000000000000000000000000000..e681adf52b9c467c8cd3d33a12a1b051bf97328e --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/no_name_for_entity.xml @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Academic Free License (AFL 3.0) + * that is bundled with this package in the file LICENSE_AFL.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/afl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Magento_Validator + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ +--> +<validation> + <entity> + <rules> + <rule name="test_rule_b"> + <!-- constraints element is not allowed here, expected entity_constraints or property_constraints --> + <constraints> + <constraint class="Magento_Validator_Test_True"/> + </constraints> + </rule> + </rules> + <groups> + <group name="test_group_b"> + <uses> + <use rule="test_rule_b"/> + </uses> + </group> + </groups> + </entity> +</validation> diff --git a/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/no_name_for_group.xml b/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/no_name_for_group.xml new file mode 100644 index 0000000000000000000000000000000000000000..ca6da799fc460c471d9d596f2ac03c62f5c33ec0 --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/no_name_for_group.xml @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Academic Free License (AFL 3.0) + * that is bundled with this package in the file LICENSE_AFL.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/afl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Magento_Validator + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ +--> +<validation> + <entity name="test_entity"> + <rules> + <rule name="test_rule_entity"> + <property_constraints> + <property name="sku"> + <constraint class="Magento_Validator_Test_NotEmpty"/> + </property> + </property_constraints> + </rule> + </rules> + <groups> + <!-- attribute name is required for group element --> + <group> + <uses> + <use rule="test_rule_entity"/> + </uses> + </group> + </groups> + </entity> +</validation> diff --git a/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/no_name_for_rule.xml b/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/no_name_for_rule.xml new file mode 100644 index 0000000000000000000000000000000000000000..74b96f66d781561b573fa48185b37ae7a6d0d002 --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/no_name_for_rule.xml @@ -0,0 +1,56 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Academic Free License (AFL 3.0) + * that is bundled with this package in the file LICENSE_AFL.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/afl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Magento_Validator + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ +--> +<validation> + <entity name="test_entity"> + <rules> + <!-- attribute name is required for rule element --> + <rule> + <property_constraints> + <property name="sku"> + <constraint class="Magento_Validator_Test_Alnum"/> + </property> + </property_constraints> + </rule> + <rule name="test_rule_sku"> + <property_constraints> + <property name="sku"> + <constraint class="Magento_Validator_Test_NotEmpty"/> + </property> + </property_constraints> + </rule> + </rules> + <groups> + <group name="test_group"> + <uses> + <use rule="test_rule_sku"/> + </uses> + </group> + </groups> + </entity> +</validation> diff --git a/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/no_rule_for_reference.xml b/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/no_rule_for_reference.xml new file mode 100644 index 0000000000000000000000000000000000000000..44a16a1053a6c44284d6586874a6b872fb10078b --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/no_rule_for_reference.xml @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Academic Free License (AFL 3.0) + * that is bundled with this package in the file LICENSE_AFL.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/afl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Magento_Validator + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ +--> +<validation> + <entity name="test_entity"> + <rules> + <rule name="test_rule_sku_and_name"> + <property_constraints> + <property name="sku"> + <constraint class="Magento_Validator_Test_NotEmpty"/> + </property> + </property_constraints> + </rule> + </rules> + <groups> + <group name="test_group_a"> + <uses> + <!-- declaration of test_invalid_rule is absent in the file --> + <use rule="test_invalid_rule"/> + <use rule="test_rule_sku_and_name"/> + </uses> + </group> + <group name="test_group_b"> + <uses> + <use rule="test_rule_sku_and_name"/> + </uses> + </group> + </groups> + </entity> +</validation> diff --git a/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/not_unique_use.xml b/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/not_unique_use.xml new file mode 100644 index 0000000000000000000000000000000000000000..ac2e38c81d16ed2c205da50bf219874ae5dd2832 --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Validator/_files/validation/negative/not_unique_use.xml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Academic Free License (AFL 3.0) + * that is bundled with this package in the file LICENSE_AFL.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/afl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Magento_Validator + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ +--> +<validation> + <entity name="test_entity"> + <rules> + <rule name="test_rule_sku"> + <entity_constraints> + <constraint class="Magento_Validator_Test_NotEmpty"/> + </entity_constraints> + </rule> + </rules> + <groups> + <group name="test_group_a"> + <uses> + <!-- reference to rule must be unique in one group --> + <use rule="test_rule_sku"/> + <use rule="test_rule_sku"/> + </uses> + </group> + </groups> + </entity> +</validation> diff --git a/dev/tests/unit/testsuite/Magento/Validator/_files/validation/positive/builder/validation.xml b/dev/tests/unit/testsuite/Magento/Validator/_files/validation/positive/builder/validation.xml new file mode 100644 index 0000000000000000000000000000000000000000..c1382e34be26e34206a2a658d0f3228f8fb8d032 --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Validator/_files/validation/positive/builder/validation.xml @@ -0,0 +1,75 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Academic Free License (AFL 3.0) + * that is bundled with this package in the file LICENSE_AFL.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/afl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Magento_Validator + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ +--> +<validation> + <entity name="test_entity_a"> + <rules> + <rule name="rules_for_builder"> + <property_constraints> + <property name="int"> + <constraint class="Magento_Validator_Test_NotEmpty"/> + <constraint class="Validator_Stub" alias="stub"> + <argument> + test_string_argument + </argument> + <argument> + <option name="option1"> + value1 + </option> + <option name="option2">value2</option> + </argument> + <argument> + <callback class="Magento_Validator_Test_Callback" method="getId"/> + </argument> + + <method name="setOptionThree"> + <argument> + <option name="argOption">argOptionValue</option> + </argument> + <argument> + <callback class="Magento_Validator_Test_Callback" method="getId"/> + </argument> + <argument>10</argument> + </method> + <method name="enableOptionFour"/> + + <callback class="Magento_Validator_Test_Callback" method="configureValidator"/> + </constraint> + </property> + </property_constraints> + </rule> + </rules> + <groups> + <group name="check_builder" builder="Magento_Validator_Test_Builder"> + <uses> + <use rule="rules_for_builder"/> + </uses> + </group> + </groups> + </entity> +</validation> diff --git a/dev/tests/unit/testsuite/Magento/Validator/_files/validation/positive/module_a/validation.xml b/dev/tests/unit/testsuite/Magento/Validator/_files/validation/positive/module_a/validation.xml index 4796ceb1d57643918e38e1a41458ba216b407be3..65c150d833e5f8a02950300d691ad4ef5c705e98 100644 --- a/dev/tests/unit/testsuite/Magento/Validator/_files/validation/positive/module_a/validation.xml +++ b/dev/tests/unit/testsuite/Magento/Validator/_files/validation/positive/module_a/validation.xml @@ -27,29 +27,38 @@ */ --> <validation> - <entity name="test_entity"> + <entity name="test_entity_a"> <rules> - <rule name="test_rule_zend"> - <constraints> - <constraint class="Zend_Validate_Alnum" field="test_field"/> - </constraints> + <rule name="check_alnum_and_int_not_empty_and_have_valid_value"> + <property_constraints > + <property name="alnum"> + <constraint class="Magento_Validator_Test_NotEmpty"/> + <constraint class="Magento_Validator_Test_Alnum"/> + </property> + <property name="int"> + <constraint class="Magento_Validator_Test_Int"/> + </property> + </property_constraints> + <entity_constraints> + <constraint class="Magento_Validator_Test_True"/> + </entity_constraints> </rule> - <rule name="test_rule_constraint"> - <constraints> - <constraint class="Magento_Validator_Test"/> - </constraints> + <rule name="always_true"> + <entity_constraints> + <constraint alias="alias" class="Magento_Validator_Test_True"/> + </entity_constraints> </rule> </rules> <groups> - <group name="test_group_a"> + <group name="check_alnum_and_int_not_empty_and_have_valid_value"> <uses> - <use rule="test_rule_zend"/> - <use rule="test_rule_constraint"/> + <use rule="check_alnum_and_int_not_empty_and_have_valid_value"/> + <use rule="always_true"/> </uses> </group> - <group name="test_group_b"> + <group name="check_alnum"> <uses> - <use rule="test_rule_constraint"/> + <use rule="always_true"/> </uses> </group> </groups> diff --git a/dev/tests/unit/testsuite/Magento/Validator/_files/validation/positive/module_b/validation.xml b/dev/tests/unit/testsuite/Magento/Validator/_files/validation/positive/module_b/validation.xml index bbdea43aa3d236335a92db1aa2f5164ceb16afe6..e9e76658fa0903009693945283c9d093e8bee55b 100644 --- a/dev/tests/unit/testsuite/Magento/Validator/_files/validation/positive/module_b/validation.xml +++ b/dev/tests/unit/testsuite/Magento/Validator/_files/validation/positive/module_b/validation.xml @@ -27,34 +27,27 @@ */ --> <validation> - <entity name="test_entity"> + <entity name="test_entity_a"> <rules> - <rule name="test_rule_constraint_2"> - <constraints> - <constraint class="Magento_Validator_Test" field="constraint_field"/> - </constraints> + <rule name="check_alnum_and_int_not_empty_and_have_valid_value"> + <property_constraints> + <property name="int"> + <constraint class="Magento_Validator_Test_NotEmpty"/> + </property> + </property_constraints> </rule> - </rules> - <groups> - <group name="test_group_b"> - <uses> - <use rule="test_rule_constraint_2"/> - </uses> - </group> - </groups> - </entity> - <entity name="test_entity_b"> - <rules> - <rule name="test_rule"> - <constraints> - <constraint class="Zend_Validate_Int" field="test_field"/> - </constraints> + <rule name="check_alnum_has_valid_value"> + <property_constraints> + <property name="alnum"> + <constraint class="Magento_Validator_Test_Alnum"/> + </property> + </property_constraints> </rule> </rules> <groups> - <group name="test_group_c"> + <group name="check_alnum"> <uses> - <use rule="test_rule"/> + <use rule="check_alnum_has_valid_value"/> </uses> </group> </groups> diff --git a/dev/tests/unit/testsuite/Magento/ValidatorTest.php b/dev/tests/unit/testsuite/Magento/ValidatorTest.php index 4697a63817ec9c7bf1922354c018d98ecd041d32..58ce30e6764defe037147e7bf349c8748d60b1df 100644 --- a/dev/tests/unit/testsuite/Magento/ValidatorTest.php +++ b/dev/tests/unit/testsuite/Magento/ValidatorTest.php @@ -27,122 +27,151 @@ /** * Test case for Magento_Validator - * - * @group validator */ class Magento_ValidatorTest extends PHPUnit_Framework_TestCase { + /** + * @var Magento_Validator + */ + protected $_validator; /** - * @expectedException InvalidArgumentException + * Set up */ - public function testConstructException() + protected function setUp() { - /** @var Magento_Validator_Config $configMock */ - $configMock = $this->getMockBuilder('Magento_Validator_Config')->disableOriginalConstructor()->getMock(); - new Magento_Validator(null, null, $configMock); + $this->_validator = new Magento_Validator(); } /** - * @expectedException InvalidArgumentException + * Cleanup validator instance to unset default translator if any */ - public function testConstructEmptyGroupNameException() + protected function tearDown() { - /** @var Magento_Validator_Config $configMock */ - $configMock = $this->getMockBuilder('Magento_Validator_Config')->disableOriginalConstructor()->getMock(); - new Magento_Validator('test_entity', null, $configMock); + unset($this->_validator); } /** - * @param array $dataToValidate - * @param PHPUnit_Framework_MockObject_MockObject $zendConstraintMock - * @param PHPUnit_Framework_MockObject_MockObject $mageConstraintMock - * @param Magento_Validator_Config $configMock - * @dataProvider dataProviderForValidator + * Test isValid method + * + * @dataProvider isValidDataProvider + * + * @param mixed $value + * @param Magento_Validator_ValidatorInterface[] $validators + * @param boolean $expectedResult + * @param array $expectedMessages + * @param boolean $breakChainOnFailure */ - public function testIsValid($dataToValidate, $zendConstraintMock, $mageConstraintMock, $configMock) - { - $zendConstraintMock->expects($this->once()) - ->method('isValid') - ->with($dataToValidate['test_field']) - ->will($this->returnValue(true)); - - $mageConstraintMock->expects($this->once()) - ->method('isValidData') - ->with($dataToValidate, 'test_field_constraint') - ->will($this->returnValue(true)); - - $validator = new Magento_Validator('test_entity', 'test_group_a', $configMock); - $this->assertTrue($validator->isValid($dataToValidate)); + public function testIsValid($value, $validators, $expectedResult, $expectedMessages = array(), + $breakChainOnFailure = false + ) { + foreach ($validators as $validator) { + $this->_validator->addValidator($validator, $breakChainOnFailure); + } + + $this->assertEquals($expectedResult, $this->_validator->isValid($value)); + $this->assertEquals($expectedMessages, $this->_validator->getMessages($value)); } /** - * @param array $dataToValidate - * @param PHPUnit_Framework_MockObject_MockObject $zendConstraintMock - * @param PHPUnit_Framework_MockObject_MockObject $mageConstraintMock - * @param Magento_Validator_Config $configMock - * @dataProvider dataProviderForValidator + * Data provider for testIsValid + * + * @return array */ - public function testGetErrors($dataToValidate, $zendConstraintMock, $mageConstraintMock, $configMock) + public function isValidDataProvider() { - $expectedZendErrors = array('Test Zend_Validate_Interface constraint error.'); - $zendConstraintMock->expects($this->once()) - ->method('isValid') - ->with($dataToValidate['test_field']) - ->will($this->returnValue(false)); - $zendConstraintMock->expects($this->once()) - ->method('getMessages') - ->will($this->returnValue($expectedZendErrors)); + $result = array(); + $value = 'test'; - $expectedMageErrors = array( - 'test_field_constraint' => array('Test Magento_Validator_ConstraintInterface constraint error.') - ); - $mageConstraintMock->expects($this->once()) - ->method('isValidData') - ->with($dataToValidate, 'test_field_constraint') + // Case 1. Validators fails without breaking chain + $validatorA = $this->getMock('Magento_Validator_ValidatorInterface'); + $validatorA->expects($this->once())->method('isValid') + ->with($value)->will($this->returnValue(false)); + $validatorA->expects($this->once())->method('getMessages') + ->will($this->returnValue(array('foo' => array('Foo message 1'), 'bar' => array('Foo message 2')))); + + $validatorB = $this->getMock('Magento_Validator_ValidatorInterface'); + $validatorB->expects($this->once())->method('isValid') + ->with($value)->will($this->returnValue(false)); + $validatorB->expects($this->once())->method('getMessages') + ->will($this->returnValue(array('foo' => array('Bar message 1'), 'bar' => array('Bar message 2')))); + + $result[] = array($value, array($validatorA, $validatorB), false, array( + 'foo' => array('Foo message 1', 'Bar message 1'), + 'bar' => array('Foo message 2', 'Bar message 2') + )); + + // Case 2. Validators fails with breaking chain + $validatorA = $this->getMock('Magento_Validator_ValidatorInterface'); + $validatorA->expects($this->once())->method('isValid') + ->with($value) ->will($this->returnValue(false)); - $mageConstraintMock->expects($this->once()) - ->method('getErrors') - ->will($this->returnValue($expectedMageErrors)); - - $validator = new Magento_Validator('test_entity', 'test_group_a', $configMock); - $this->assertFalse($validator->isValid($dataToValidate)); - $expectedErrors = array_merge(array('test_field' => $expectedZendErrors), - $expectedMageErrors); - $actualErrors = $validator->getMessages(); - $this->assertEquals($expectedErrors, $actualErrors); + $validatorA->expects($this->once())->method('getMessages') + ->will($this->returnValue(array('field' => 'Error message'))); + + $validatorB = $this->getMock('Magento_Validator_ValidatorInterface'); + $validatorB->expects($this->never())->method('isValid'); + + $result[] = array($value, array($validatorA, $validatorB), false, array('field' => 'Error message'), true); + + // Case 3. Validators succeed + $validatorA = $this->getMock('Magento_Validator_ValidatorInterface'); + $validatorA->expects($this->once())->method('isValid') + ->with($value)->will($this->returnValue(true)); + $validatorA->expects($this->never())->method('getMessages'); + + $validatorB = $this->getMock('Magento_Validator_ValidatorInterface'); + $validatorB->expects($this->once())->method('isValid') + ->with($value)->will($this->returnValue(true)); + $validatorB->expects($this->never())->method('getMessages'); + + $result[] = array($value, array($validatorA, $validatorB), true); + + return $result; } - public function dataProviderForValidator() + /** + * Test addValidator + */ + public function testAddValidator() { - $dataToValidate = array( - 'test_field' => 'test_value', - 'test_field_constraint' => 'test value constraint', - ); + $fooValidator = new Magento_Validator_Test_True(); + $classConstraint = new Magento_Validator_Constraint($fooValidator, 'id'); + $propertyValidator = new Magento_Validator_Constraint_Property($classConstraint, 'name', 'id'); + + /** @var Magento_Translate_AdapterAbstract $translator */ + $translator= $this->getMockBuilder('Magento_Translate_AdapterAbstract') + ->getMockForAbstractClass(); + Magento_Validator_ValidatorAbstract::setDefaultTranslator($translator); - $zendConstraintMock = $this->getMock('Zend_Validate_Alnum', array('isValid', 'getMessages')); - $mageConstraintMock = $this->getMock('Magento_Validator_Constraint', array('isValidData', 'getErrors')); - $validationRules = array( - 'test_rule' => array( - array( - 'constraint' => $zendConstraintMock, - 'field' => 'test_field' - ), - array( - 'constraint' => $mageConstraintMock, - 'field' => 'test_field_constraint' - ), + $this->_validator->addValidator($classConstraint); + $this->_validator->addValidator($propertyValidator); + $expected = array( + array( + 'instance' => $classConstraint, + 'breakChainOnFailure' => false ), + array( + 'instance' => $propertyValidator, + 'breakChainOnFailure' => false + ) ); + $this->assertAttributeEquals($expected, '_validators', $this->_validator); + $this->assertEquals($translator, $fooValidator->getTranslator(), 'Translator was not set'); + } - $configMock = $this->getMockBuilder('Magento_Validator_Config')->disableOriginalConstructor()->getMock(); - $configMock->expects($this->once()) - ->method('getValidationRules') - ->with('test_entity', 'test_group_a') - ->will($this->returnValue($validationRules)); - - return array( - array($dataToValidate, $zendConstraintMock, $mageConstraintMock, $configMock) - ); + /** + * Check that translator passed into validator in chain + */ + public function testSetTranslator() + { + $fooValidator = new Magento_Validator_Test_True(); + $this->_validator->addValidator($fooValidator); + /** @var Magento_Translate_AdapterAbstract $translator */ + $translator= $this->getMockBuilder('Magento_Translate_AdapterAbstract') + ->getMockForAbstractClass(); + $this->_validator->setTranslator($translator); + $this->assertEquals($translator, $fooValidator->getTranslator()); + $this->assertEquals($translator, $this->_validator->getTranslator()); } } diff --git a/dev/tests/unit/testsuite/Varien/Data/Collection/DbTest.php b/dev/tests/unit/testsuite/Varien/Data/Collection/DbTest.php index fc0ce6a0ca8a47fad424b94ff02577487dda49e6..4fdddfacff4e363865473bc9ccc2831c77e41573 100644 --- a/dev/tests/unit/testsuite/Varien/Data/Collection/DbTest.php +++ b/dev/tests/unit/testsuite/Varien/Data/Collection/DbTest.php @@ -114,11 +114,11 @@ class Varien_Data_Collection_DbTest extends PHPUnit_Framework_TestCase $adapter = $this->getMock('Zend_Db_Adapter_Pdo_Mysql', array('prepareSqlCondition'), array(), '', false); $adapter->expects($this->at(0)) ->method('prepareSqlCondition') - ->with('weight', array('in' => array(1, 3))) + ->with('`weight`', array('in' => array(1, 3))) ->will($this->returnValue('weight in (1, 3)')); $adapter->expects($this->at(1)) ->method('prepareSqlCondition') - ->with('name', array('like' => 'M%')) + ->with('`name`', array('like' => 'M%')) ->will($this->returnValue("name like 'M%'")); $this->_collection->setConnection($adapter); $select = $this->_collection->getSelect()->from("test"); @@ -136,7 +136,7 @@ class Varien_Data_Collection_DbTest extends PHPUnit_Framework_TestCase $adapter->expects($this->at(0)) ->method('prepareSqlCondition') ->with( - 'is_imported', + '`is_imported`', $this->anything() ) ->will($this->returnValue('is_imported = 1')); @@ -158,7 +158,7 @@ class Varien_Data_Collection_DbTest extends PHPUnit_Framework_TestCase ); $adapter->expects($this->once()) ->method('prepareSqlCondition') - ->with('email', array('like' => 'value?')) + ->with('`email`', array('like' => 'value?')) ->will($this->returnValue('email LIKE \'%value?%\'')); $adapter->expects($this->once()) ->method('select') @@ -170,6 +170,28 @@ class Varien_Data_Collection_DbTest extends PHPUnit_Framework_TestCase $this->assertEquals("SELECT `test`.* FROM `test` WHERE (email LIKE '%value?%')", $select->assemble()); } + /** + * Test that field is quoted when added to SQL via addFieldToFilter() + */ + public function testAddFieldToFilterFieldIsQuoted() + { + $adapter = $this->getMock('Zend_Db_Adapter_Pdo_Mysql', + array('quoteIdentifier', 'prepareSqlCondition'), array(), '', false); + $adapter->expects($this->once()) + ->method('quoteIdentifier') + ->with('email') + ->will($this->returnValue('`email`')); + $adapter->expects($this->any()) + ->method('prepareSqlCondition') + ->with($this->stringContains('`email`'), $this->anything()) + ->will($this->returnValue('`email` = "foo@example.com"')); + $this->_collection->setConnection($adapter); + $select = $this->_collection->getSelect()->from('test'); + + $this->_collection->addFieldToFilter('email', array('eq' => 'foo@example.com')); + $this->assertEquals('SELECT `test`.* FROM `test` WHERE (`email` = "foo@example.com")', $select->assemble()); + } + /** * Test that after cloning collection $this->_select in initial and cloned collections * do not reference the same object diff --git a/dev/tests/unit/testsuite/Varien/Db/ProfilerTest.php b/dev/tests/unit/testsuite/Varien/Db/ProfilerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..d9edec8ece3ee9d45b80ab5ebc17155eb9a3756e --- /dev/null +++ b/dev/tests/unit/testsuite/Varien/Db/ProfilerTest.php @@ -0,0 +1,78 @@ +<?php +/** + * Varien_Db_Profiler test case + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Varien_Db_ProfilerTest extends PHPUnit_Framework_TestCase +{ + /** + * Profiler instance for test + * @var Varien_Db_Profiler + */ + protected $_profiler; + + /** + * Setup + */ + protected function setUp() + { + $this->_profiler = new Varien_Db_Profiler(true); + } + + public function testSetHost() + { + $this->_profiler->setHost('localhost'); + $this->assertAttributeEquals('localhost', '_host', $this->_profiler); + } + + public function testSetType() + { + $this->_profiler->setType('mysql'); + $this->assertAttributeEquals('mysql', '_type', $this->_profiler); + } + + public function testQueryStart() + { + $lastQueryId = $this->_profiler->queryStart('SELECT * FROM table'); + $this->assertEquals(null, $lastQueryId); + } + + public function testQueryEnd() + { + $lastQueryId = $this->_profiler->queryStart('SELECT * FROM table'); + $endResult = $this->_profiler->queryEnd($lastQueryId); + $this->assertAttributeEquals(null, '_lastQueryId', $this->_profiler); + $this->assertEquals(Varien_Db_Profiler::STORED, $endResult); + } + + public function testQueryEndLast() + { + $this->_profiler->queryStart('SELECT * FROM table'); + $endResult = $this->_profiler->queryEndLast(); + $this->assertAttributeEquals(null, '_lastQueryId', $this->_profiler); + $this->assertEquals(Varien_Db_Profiler::STORED, $endResult); + + $endResult = $this->_profiler->queryEndLast(); + $this->assertEquals(Varien_Db_Profiler::IGNORED, $endResult); + } +} diff --git a/dev/tools/migration/Acl/log/AclXPathToAclId.log b/dev/tools/migration/Acl/log/AclXPathToAclId.log index 8b0a9da3dfda76121838cef2c3d5fda4736eb29e..c25f7313440293cd6e408d098c998de61546e3a1 100644 --- a/dev/tools/migration/Acl/log/AclXPathToAclId.log +++ b/dev/tools/migration/Acl/log/AclXPathToAclId.log @@ -1 +1 @@ -{"config\/acl\/resources\/admin\/catalog\/feed":"Find_Feed::feed","config\/acl\/resources\/admin\/catalog\/feed\/import_products":"Find_Feed::import_products","config\/acl\/resources\/admin\/catalog\/feed\/import_items":"Find_Feed::import_items","config\/acl\/resources\/admin\/system\/config\/feed":"Find_Feed::config_feed","config\/acl\/resources\/admin\/system\/config\/moneybookers":"Phoenix_Moneybookers::moneybookers","config\/acl\/resources\/admin\/system\/config\/facebook":"Social_Facebook::facebook","config\/acl\/resources\/admin\/cms\/enterprise_banner":"Enterprise_Banner::enterprise_banner","config\/acl\/resources\/admin\/catalog\/events":"Enterprise_CatalogEvent::events","config\/acl\/resources\/admin\/system\/config\/enterprise_catalogpermissions":"Enterprise_CatalogPermissions::enterprise_catalogpermissions","config\/acl\/resources\/admin\/catalog\/enterprise_catalogpermissions":"Enterprise_CatalogPermissions::catalog_enterprise_catalogpermissions","config\/acl\/resources\/admin\/sales\/enterprise_checkout":"Enterprise_Checkout::enterprise_checkout","config\/acl\/resources\/admin\/sales\/enterprise_checkout\/view":"Enterprise_Checkout::view","config\/acl\/resources\/admin\/sales\/enterprise_checkout\/update":"Enterprise_Checkout::update","config\/acl\/resources\/admin\/cms\/page\/save_revision":"Enterprise_Cms::save_revision","config\/acl\/resources\/admin\/cms\/page\/delete_revision":"Enterprise_Cms::delete_revision","config\/acl\/resources\/admin\/cms\/page\/publish_revision":"Enterprise_Cms::publish_revision","config\/acl\/resources\/admin\/cms\/hierarchy":"Enterprise_Cms::hierarchy","config\/acl\/resources\/admin\/customer\/customersegment":"Enterprise_CustomerSegment::customersegment","config\/acl\/resources\/admin\/report\/customers\/segment":"Enterprise_CustomerSegment::segment","config\/acl\/resources\/admin\/customer\/attributes":"Enterprise_Customer::attributes","config\/acl\/resources\/admin\/customer\/attributes\/customer_attributes":"Enterprise_Customer::customer_attributes","config\/acl\/resources\/admin\/customer\/attributes\/customer_address_attributes":"Enterprise_Customer::customer_address_attributes","config\/acl\/resources\/admin\/system\/config\/giftcardaccount":"Enterprise_GiftCardAccount::giftcardaccount","config\/acl\/resources\/admin\/customer\/giftcardaccount":"Enterprise_GiftCardAccount::customer_giftcardaccount","config\/acl\/resources\/admin\/system\/config\/giftcard":"Enterprise_GiftCard::giftcard","config\/acl\/resources\/admin\/system\/config\/enterprise_giftregistry":"Enterprise_GiftRegistry::enterprise_giftregistry","config\/acl\/resources\/admin\/customer\/enterprise_giftregistry":"Enterprise_GiftRegistry::customer_enterprise_giftregistry","config\/acl\/resources\/admin\/sales\/enterprise_giftwrapping":"Enterprise_GiftWrapping::enterprise_giftwrapping","config\/acl\/resources\/admin\/system\/convert\/enterprise_scheduled_operation":"Enterprise_ImportExport::enterprise_scheduled_operation","config\/acl\/resources\/admin\/customer\/enterprise_invitation":"Enterprise_Invitation::enterprise_invitation","config\/acl\/resources\/admin\/report\/enterprise_invitation":"Enterprise_Invitation::report_enterprise_invitation","config\/acl\/resources\/admin\/report\/enterprise_invitation\/general":"Enterprise_Invitation::general","config\/acl\/resources\/admin\/report\/enterprise_invitation\/customer":"Enterprise_Invitation::enterprise_invitation_customer","config\/acl\/resources\/admin\/report\/enterprise_invitation\/order":"Enterprise_Invitation::order","config\/acl\/resources\/admin\/system\/config\/enterprise_invitation":"Enterprise_Invitation::config_enterprise_invitation","config\/acl\/resources\/admin\/system\/config\/logging":"Enterprise_Logging::logging","config\/acl\/resources\/admin\/system\/enterprise_logging":"Enterprise_Logging::enterprise_logging","config\/acl\/resources\/admin\/system\/enterprise_logging\/events":"Enterprise_Logging::enterprise_logging_events","config\/acl\/resources\/admin\/system\/enterprise_logging\/backups":"Enterprise_Logging::backups","config\/acl\/resources\/admin\/system\/crypt_key":"Enterprise_Pci::crypt_key","config\/acl\/resources\/admin\/system\/acl\/locks":"Enterprise_Pci::locks","config\/acl\/resources\/admin\/catalog\/products\/read_product_price":"Enterprise_PricePermissions::read_product_price","config\/acl\/resources\/admin\/catalog\/products\/read_product_price\/edit_product_price":"Enterprise_PricePermissions::edit_product_price","config\/acl\/resources\/admin\/catalog\/products\/edit_product_status":"Enterprise_PricePermissions::edit_product_status","config\/acl\/resources\/admin\/promo\/catalog\/edit":"Enterprise_PromotionPermissions::edit","config\/acl\/resources\/admin\/promo\/quote\/edit":"Enterprise_PromotionPermissions::quote_edit","config\/acl\/resources\/admin\/promo\/enterprise_reminder\/edit":"Enterprise_PromotionPermissions::enterprise_reminder_edit","config\/acl\/resources\/admin\/promo\/enterprise_reminder":"Enterprise_Reminder::enterprise_reminder","config\/acl\/resources\/admin\/system\/config\/promo":"Mage_SalesRule::config_promo","config\/acl\/resources\/admin\/customer\/manage\/reward_balance":"Enterprise_Reward::reward_balance","config\/acl\/resources\/admin\/sales\/order\/actions\/create\/reward_spend":"Enterprise_Reward::reward_spend","config\/acl\/resources\/admin\/customer\/rates":"Enterprise_Reward::rates","config\/acl\/resources\/admin\/system\/config\/enterprise_reward":"Enterprise_Reward::enterprise_reward","config\/acl\/resources\/admin\/sales\/enterprise_rma":"Enterprise_Rma::enterprise_rma","config\/acl\/resources\/admin\/sales\/enterprise_rma\/rma_manage":"Enterprise_Rma::rma_manage","config\/acl\/resources\/admin\/sales\/enterprise_rma\/rma_attribute":"Enterprise_Rma::rma_attribute","config\/acl\/resources\/admin\/sales\/archive":"Enterprise_SalesArchive::archive","config\/acl\/resources\/admin\/sales\/archive\/orders":"Enterprise_SalesArchive::orders","config\/acl\/resources\/admin\/sales\/archive\/orders\/add":"Enterprise_SalesArchive::add","config\/acl\/resources\/admin\/sales\/archive\/orders\/remove":"Enterprise_SalesArchive::remove","config\/acl\/resources\/admin\/sales\/archive\/invoices":"Enterprise_SalesArchive::invoices","config\/acl\/resources\/admin\/sales\/archive\/shipments":"Enterprise_SalesArchive::shipments","config\/acl\/resources\/admin\/sales\/archive\/creditmemos":"Enterprise_SalesArchive::creditmemos","config\/acl\/resources\/admin\/catalog\/targetrule":"Enterprise_TargetRule::targetrule","config\/acl\/resources\/admin\/report\/customers\/wishlist":"Enterprise_Wishlist::wishlist","config\/acl\/resources\/admin\/system\/adminnotification":"Mage_AdminNotification::adminnotification","config\/acl\/resources\/admin\/system\/adminnotification\/show_toolbar":"Mage_AdminNotification::show_toolbar","config\/acl\/resources\/admin\/system\/adminnotification\/show_list":"Mage_AdminNotification::show_list","config\/acl\/resources\/admin\/system\/adminnotification\/mark_as_read":"Mage_AdminNotification::mark_as_read","config\/acl\/resources\/admin\/system\/adminnotification\/remove":"Mage_AdminNotification::adminnotification_remove","config\/acl\/resources\/all":"Mage_Adminhtml::all","config\/acl\/resources\/admin":"Mage_Adminhtml::admin","config\/acl\/resources\/admin\/dashboard":"Mage_Adminhtml::dashboard","config\/acl\/resources\/admin\/system":"Mage_Adminhtml::system","config\/acl\/resources\/admin\/system\/store":"Mage_Adminhtml::store","config\/acl\/resources\/admin\/system\/design":"Mage_Adminhtml::design","config\/acl\/resources\/admin\/system\/design\/schedule":"Mage_Adminhtml::schedule","config\/acl\/resources\/admin\/system\/config":"Mage_Adminhtml::config","config\/acl\/resources\/admin\/system\/config\/general":"Mage_Adminhtml::config_general","config\/acl\/resources\/admin\/system\/config\/web":"Mage_Adminhtml::web","config\/acl\/resources\/admin\/system\/config\/design":"Mage_Adminhtml::config_design","config\/acl\/resources\/admin\/system\/config\/system":"Mage_Adminhtml::config_system","config\/acl\/resources\/admin\/system\/config\/advanced":"Mage_Adminhtml::advanced","config\/acl\/resources\/admin\/system\/config\/trans_email":"Mage_Adminhtml::trans_email","config\/acl\/resources\/admin\/system\/config\/dev":"Mage_Adminhtml::dev","config\/acl\/resources\/admin\/system\/config\/currency":"Mage_Adminhtml::currency","config\/acl\/resources\/admin\/system\/config\/sendfriend":"Mage_Adminhtml::sendfriend","config\/acl\/resources\/admin\/system\/config\/admin":"Mage_Adminhtml::config_admin","config\/acl\/resources\/admin\/system\/currency":"Mage_CurrencySymbol::system_currency","config\/acl\/resources\/admin\/system\/email_template":"Mage_Adminhtml::email_template","config\/acl\/resources\/admin\/system\/variable":"Mage_Adminhtml::variable","config\/acl\/resources\/admin\/system\/myaccount":"Mage_Adminhtml::myaccount","config\/acl\/resources\/admin\/system\/tools":"Mage_Adminhtml::tools","config\/acl\/resources\/admin\/system\/convert":"Mage_Adminhtml::convert","config\/acl\/resources\/admin\/system\/cache":"Mage_Adminhtml::cache","config\/acl\/resources\/admin\/system\/extensions":"Mage_Adminhtml::extensions","config\/acl\/resources\/admin\/system\/extensions\/local":"Mage_Adminhtml::local","config\/acl\/resources\/admin\/system\/extensions\/custom":"Mage_Adminhtml::custom","config\/acl\/resources\/admin\/global_search":"Mage_Adminhtml::global_search","config\/acl\/resources\/admin\/system\/api\/rest_roles":"Mage_Api2::rest_roles","config\/acl\/resources\/admin\/system\/api\/rest_roles\/add":"Mage_Api2::rest_roles_add","config\/acl\/resources\/admin\/system\/api\/rest_roles\/edit":"Mage_Api2::rest_roles_edit","config\/acl\/resources\/admin\/system\/api\/rest_roles\/delete":"Mage_Api2::delete","config\/acl\/resources\/admin\/system\/api\/rest_attributes":"Mage_Api2::rest_attributes","config\/acl\/resources\/admin\/system\/api\/rest_attributes\/edit":"Mage_Api2::rest_attributes_edit","config\/acl\/resources\/admin\/system\/api":"Mage_Api::api","config\/acl\/resources\/admin\/system\/api\/users":"Mage_Api::users","config\/acl\/resources\/admin\/system\/api\/roles":"Mage_Api::roles","config\/acl\/resources\/admin\/system\/config\/api":"Mage_Api::config_api","config\/acl\/resources\/admin\/system\/tools\/backup":"Mage_Backup::backup","config\/acl\/resources\/admin\/system\/tools\/backup\/rollback":"Mage_Backup::rollback","config\/acl\/resources\/admin\/system\/config\/cataloginventory":"Mage_CatalogInventory::cataloginventory","config\/acl\/resources\/admin\/promo":"Mage_CatalogRule::promo","config\/acl\/resources\/admin\/promo\/catalog":"Mage_CatalogRule::promo_catalog","config\/acl\/resources\/admin\/catalog\/search":"Mage_CatalogSearch::search","config\/acl\/resources\/admin\/system\/config\/catalog":"Mage_Catalog::config_catalog","config\/acl\/resources\/admin\/catalog":"Mage_Catalog::catalog","config\/acl\/resources\/admin\/catalog\/attributes":"Mage_Catalog::catalog_attributes","config\/acl\/resources\/admin\/catalog\/attributes\/attributes":"Mage_Catalog::attributes_attributes","config\/acl\/resources\/admin\/catalog\/attributes\/sets":"Mage_Catalog::sets","config\/acl\/resources\/admin\/catalog\/categories":"Mage_Catalog::categories","config\/acl\/resources\/admin\/catalog\/products":"Mage_Catalog::products","config\/acl\/resources\/admin\/catalog\/update_attributes":"Mage_Catalog::update_attributes","config\/acl\/resources\/admin\/catalog\/urlrewrite":"Mage_Catalog::urlrewrite","config\/acl\/resources\/admin\/sales\/checkoutagreement":"Mage_Checkout::checkoutagreement","config\/acl\/resources\/admin\/system\/config\/checkout":"Mage_Checkout::checkout","config\/acl\/resources\/admin\/cms":"Mage_Cms::cms","config\/acl\/resources\/admin\/cms\/block":"Mage_Cms::block","config\/acl\/resources\/admin\/cms\/page":"Mage_Cms::page","config\/acl\/resources\/admin\/cms\/page\/save":"Mage_Cms::save","config\/acl\/resources\/admin\/cms\/page\/delete":"Mage_Cms::page_delete","config\/acl\/resources\/admin\/cms\/media_gallery":"Mage_Cms::media_gallery","config\/acl\/resources\/admin\/system\/config\/cms":"Mage_Cms::config_cms","config\/acl\/resources\/admin\/system\/config\/contacts":"Mage_Contacts::contacts","config\/acl\/resources\/admin\/system\/currency\/rates":"Mage_CurrencySymbol::currency_rates","config\/acl\/resources\/admin\/system\/currency\/symbols":"Mage_CurrencySymbol::symbols","config\/acl\/resources\/admin\/customer":"Mage_Customer::customer","config\/acl\/resources\/admin\/customer\/group":"Mage_Customer::group","config\/acl\/resources\/admin\/customer\/manage":"Mage_Customer::manage","config\/acl\/resources\/admin\/customer\/online":"Mage_Customer::online","config\/acl\/resources\/admin\/system\/config\/customer":"Mage_Customer::config_customer","config\/acl\/resources\/admin\/system\/design\/editor":"Mage_DesignEditor::editor","config\/acl\/resources\/admin\/system\/config\/downloadable":"Mage_Downloadable::downloadable","config\/acl\/resources\/admin\/system\/config\/google":"Mage_GoogleCheckout::google","config\/acl\/resources\/admin\/catalog\/googleshopping":"Mage_GoogleShopping::googleshopping","config\/acl\/resources\/admin\/catalog\/googleshopping\/types":"Mage_GoogleShopping::types","config\/acl\/resources\/admin\/catalog\/googleshopping\/items":"Mage_GoogleShopping::items","config\/acl\/resources\/admin\/system\/convert\/import":"Mage_ImportExport::import","config\/acl\/resources\/admin\/system\/convert\/export":"Mage_ImportExport::export","config\/acl\/resources\/admin\/system\/index":"Mage_Index::index","config\/acl\/resources\/admin\/system\/config\/newsletter":"Mage_Newsletter::newsletter","config\/acl\/resources\/admin\/newsletter":"Mage_Newsletter::admin_newsletter","config\/acl\/resources\/admin\/newsletter\/problem":"Mage_Newsletter::problem","config\/acl\/resources\/admin\/newsletter\/queue":"Mage_Newsletter::queue","config\/acl\/resources\/admin\/newsletter\/subscriber":"Mage_Newsletter::subscriber","config\/acl\/resources\/admin\/newsletter\/template":"Mage_Newsletter::template","config\/acl\/resources\/admin\/system\/api\/consumer":"Mage_Oauth::consumer","config\/acl\/resources\/admin\/system\/api\/consumer\/edit":"Mage_Oauth::consumer_edit","config\/acl\/resources\/admin\/system\/api\/consumer\/delete":"Mage_Oauth::consumer_delete","config\/acl\/resources\/admin\/system\/api\/authorizedTokens":"Mage_Oauth::authorizedTokens","config\/acl\/resources\/admin\/system\/api\/oauth_admin_token":"Mage_Oauth::oauth_admin_token","config\/acl\/resources\/admin\/system\/config\/oauth":"Mage_Oauth::oauth","config\/acl\/resources\/admin\/page_cache":"Mage_PageCache::page_cache","config\/acl\/resources\/admin\/system\/config\/payment":"Mage_Payment::payment","config\/acl\/resources\/admin\/system\/config\/payment_services":"Mage_Payment::payment_services","config\/acl\/resources\/admin\/system\/config\/paypal":"Mage_Paypal::paypal","config\/acl\/resources\/admin\/report\/salesroot\/paypal_settlement_reports":"Mage_Paypal::paypal_settlement_reports","config\/acl\/resources\/admin\/report\/salesroot\/paypal_settlement_reports\/view":"Mage_Paypal::paypal_settlement_reports_view","config\/acl\/resources\/admin\/report\/salesroot\/paypal_settlement_reports\/fetch":"Mage_Paypal::fetch","config\/acl\/resources\/admin\/system\/config\/persistent":"Mage_Persistent::persistent","config\/acl\/resources\/admin\/cms\/poll":"Mage_Poll::poll","config\/acl\/resources\/admin\/catalog\/reviews_ratings\/ratings":"Mage_Rating::ratings","config\/acl\/resources\/admin\/report":"Mage_Reports::report","config\/acl\/resources\/admin\/report\/salesroot":"Mage_Reports::salesroot","config\/acl\/resources\/admin\/report\/salesroot\/sales":"Mage_Reports::salesroot_sales","config\/acl\/resources\/admin\/report\/salesroot\/tax":"Mage_Reports::tax","config\/acl\/resources\/admin\/report\/salesroot\/shipping":"Mage_Reports::shipping","config\/acl\/resources\/admin\/report\/salesroot\/invoiced":"Mage_Reports::invoiced","config\/acl\/resources\/admin\/report\/salesroot\/refunded":"Mage_Reports::refunded","config\/acl\/resources\/admin\/report\/salesroot\/coupons":"Mage_Reports::coupons","config\/acl\/resources\/admin\/report\/shopcart":"Mage_Reports::shopcart","config\/acl\/resources\/admin\/report\/shopcart\/product":"Mage_Reports::product","config\/acl\/resources\/admin\/report\/shopcart\/abandoned":"Mage_Reports::abandoned","config\/acl\/resources\/admin\/report\/products":"Mage_Reports::report_products","config\/acl\/resources\/admin\/report\/products\/bestsellers":"Mage_Reports::bestsellers","config\/acl\/resources\/admin\/report\/products\/sold":"Mage_Reports::sold","config\/acl\/resources\/admin\/report\/products\/viewed":"Mage_Reports::viewed","config\/acl\/resources\/admin\/report\/products\/lowstock":"Mage_Reports::lowstock","config\/acl\/resources\/admin\/report\/products\/downloads":"Mage_Reports::downloads","config\/acl\/resources\/admin\/report\/customers":"Mage_Reports::customers","config\/acl\/resources\/admin\/report\/customers\/accounts":"Mage_Reports::accounts","config\/acl\/resources\/admin\/report\/customers\/totals":"Mage_Reports::totals","config\/acl\/resources\/admin\/report\/customers\/orders":"Mage_Reports::customers_orders","config\/acl\/resources\/admin\/report\/review":"Mage_Reports::review","config\/acl\/resources\/admin\/report\/review\/customer":"Mage_Reports::review_customer","config\/acl\/resources\/admin\/report\/review\/product":"Mage_Reports::review_product","config\/acl\/resources\/admin\/report\/tags":"Mage_Reports::tags","config\/acl\/resources\/admin\/report\/tags\/customer":"Mage_Reports::tags_customer","config\/acl\/resources\/admin\/report\/tags\/popular":"Mage_Reports::popular","config\/acl\/resources\/admin\/report\/tags\/product":"Mage_Reports::tags_product","config\/acl\/resources\/admin\/report\/search":"Mage_Reports::report_search","config\/acl\/resources\/admin\/report\/statistics":"Mage_Reports::statistics","config\/acl\/resources\/admin\/system\/config\/reports":"Mage_Reports::reports","config\/acl\/resources\/admin\/catalog\/reviews_ratings":"Mage_Review::reviews_ratings","config\/acl\/resources\/admin\/catalog\/reviews_ratings\/reviews":"Mage_Review::reviews","config\/acl\/resources\/admin\/catalog\/reviews_ratings\/reviews\/all":"Mage_Review::reviews_all","config\/acl\/resources\/admin\/catalog\/reviews_ratings\/reviews\/pending":"Mage_Review::pending","config\/acl\/resources\/admin\/system\/config\/rss":"Mage_Rss::rss","config\/acl\/resources\/admin\/promo\/quote":"Mage_SalesRule::quote","config\/acl\/resources\/admin\/sales":"Mage_Sales::sales","config\/acl\/resources\/admin\/sales\/order":"Mage_Sales::sales_order","config\/acl\/resources\/admin\/sales\/order\/actions":"Mage_Sales::actions","config\/acl\/resources\/admin\/sales\/order\/actions\/create":"Mage_Sales::create","config\/acl\/resources\/admin\/sales\/order\/actions\/view":"Mage_Sales::actions_view","config\/acl\/resources\/admin\/sales\/order\/actions\/email":"Mage_Sales::email","config\/acl\/resources\/admin\/sales\/order\/actions\/reorder":"Mage_Sales::reorder","config\/acl\/resources\/admin\/sales\/order\/actions\/edit":"Mage_Sales::actions_edit","config\/acl\/resources\/admin\/sales\/order\/actions\/cancel":"Mage_Sales::cancel","config\/acl\/resources\/admin\/sales\/order\/actions\/review_payment":"Mage_Sales::review_payment","config\/acl\/resources\/admin\/sales\/order\/actions\/capture":"Mage_Sales::capture","config\/acl\/resources\/admin\/sales\/order\/actions\/invoice":"Mage_Sales::invoice","config\/acl\/resources\/admin\/sales\/order\/actions\/creditmemo":"Mage_Sales::creditmemo","config\/acl\/resources\/admin\/sales\/order\/actions\/hold":"Mage_Sales::hold","config\/acl\/resources\/admin\/sales\/order\/actions\/unhold":"Mage_Sales::unhold","config\/acl\/resources\/admin\/sales\/order\/actions\/ship":"Mage_Sales::ship","config\/acl\/resources\/admin\/sales\/order\/actions\/comment":"Mage_Sales::comment","config\/acl\/resources\/admin\/sales\/order\/actions\/emails":"Mage_Sales::emails","config\/acl\/resources\/admin\/sales\/invoice":"Mage_Sales::sales_invoice","config\/acl\/resources\/admin\/sales\/shipment":"Mage_Sales::shipment","config\/acl\/resources\/admin\/sales\/creditmemo":"Mage_Sales::sales_creditmemo","config\/acl\/resources\/admin\/sales\/transactions":"Mage_Sales::transactions","config\/acl\/resources\/admin\/sales\/transactions\/fetch":"Mage_Sales::transactions_fetch","config\/acl\/resources\/admin\/sales\/recurring_profile":"Mage_Sales::recurring_profile","config\/acl\/resources\/admin\/sales\/billing_agreement":"Mage_Sales::billing_agreement","config\/acl\/resources\/admin\/sales\/billing_agreement\/actions":"Mage_Sales::billing_agreement_actions","config\/acl\/resources\/admin\/sales\/billing_agreement\/actions\/view":"Mage_Sales::billing_agreement_actions_view","config\/acl\/resources\/admin\/sales\/billing_agreement\/actions\/manage":"Mage_Sales::actions_manage","config\/acl\/resources\/admin\/sales\/billing_agreement\/actions\/use":"Mage_Sales::use","config\/acl\/resources\/admin\/system\/order_statuses":"Mage_Sales::order_statuses","config\/acl\/resources\/admin\/system\/config\/sales":"Mage_Sales::config_sales","config\/acl\/resources\/admin\/system\/config\/sales_email":"Mage_Sales::sales_email","config\/acl\/resources\/admin\/system\/config\/sales_pdf":"Mage_Sales::sales_pdf","config\/acl\/resources\/admin\/system\/config\/shipping":"Mage_Shipping::config_shipping","config\/acl\/resources\/admin\/system\/config\/carriers":"Mage_Shipping::carriers","config\/acl\/resources\/admin\/catalog\/sitemap":"Mage_Sitemap::sitemap","config\/acl\/resources\/admin\/system\/config\/sitemap":"Mage_Sitemap::config_sitemap","config\/acl\/resources\/admin\/catalog\/tag":"Mage_Tag::tag","config\/acl\/resources\/admin\/catalog\/tag\/all":"Mage_Tag::tag_all","config\/acl\/resources\/admin\/catalog\/tag\/pending":"Mage_Tag::tag_pending","config\/acl\/resources\/admin\/sales\/tax":"Mage_Tax::sales_tax","config\/acl\/resources\/admin\/sales\/tax\/classes_customer":"Mage_Tax::classes_customer","config\/acl\/resources\/admin\/sales\/tax\/classes_product":"Mage_Tax::classes_product","config\/acl\/resources\/admin\/sales\/tax\/import_export":"Mage_Tax::import_export","config\/acl\/resources\/admin\/sales\/tax\/rates":"Mage_Tax::tax_rates","config\/acl\/resources\/admin\/sales\/tax\/rules":"Mage_Tax::rules","config\/acl\/resources\/admin\/system\/config\/tax":"Mage_Tax::config_tax","config\/acl\/resources\/admin\/system\/acl":"Mage_User::acl","config\/acl\/resources\/admin\/system\/acl\/roles":"Mage_User::acl_roles","config\/acl\/resources\/admin\/system\/acl\/users":"Mage_User::acl_users","config\/acl\/resources\/admin\/cms\/widget_instance":"Mage_Widget::widget_instance","config\/acl\/resources\/admin\/system\/config\/wishlist":"Mage_Wishlist::config_wishlist"} +{"config\/acl\/resources\/admin\/catalog\/feed":"Find_Feed::feed","config\/acl\/resources\/admin\/catalog\/feed\/import_products":"Find_Feed::import_products","config\/acl\/resources\/admin\/catalog\/feed\/import_items":"Find_Feed::import_items","config\/acl\/resources\/admin\/system\/config\/feed":"Find_Feed::config_feed","config\/acl\/resources\/admin\/system\/config\/moneybookers":"Phoenix_Moneybookers::moneybookers","config\/acl\/resources\/admin\/system\/config\/facebook":"Social_Facebook::facebook","config\/acl\/resources\/admin\/cms\/enterprise_banner":"Enterprise_Banner::enterprise_banner","config\/acl\/resources\/admin\/catalog\/events":"Enterprise_CatalogEvent::events","config\/acl\/resources\/admin\/system\/config\/enterprise_catalogpermissions":"Enterprise_CatalogPermissions::enterprise_catalogpermissions","config\/acl\/resources\/admin\/catalog\/enterprise_catalogpermissions":"Enterprise_CatalogPermissions::catalog_enterprise_catalogpermissions","config\/acl\/resources\/admin\/sales\/enterprise_checkout":"Enterprise_Checkout::enterprise_checkout","config\/acl\/resources\/admin\/sales\/enterprise_checkout\/view":"Enterprise_Checkout::view","config\/acl\/resources\/admin\/sales\/enterprise_checkout\/update":"Enterprise_Checkout::update","config\/acl\/resources\/admin\/cms\/page\/save_revision":"Enterprise_Cms::save_revision","config\/acl\/resources\/admin\/cms\/page\/delete_revision":"Enterprise_Cms::delete_revision","config\/acl\/resources\/admin\/cms\/page\/publish_revision":"Enterprise_Cms::publish_revision","config\/acl\/resources\/admin\/cms\/hierarchy":"Enterprise_Cms::hierarchy","config\/acl\/resources\/admin\/customer\/customersegment":"Enterprise_CustomerSegment::customersegment","config\/acl\/resources\/admin\/report\/customers\/segment":"Enterprise_CustomerSegment::segment","config\/acl\/resources\/admin\/customer\/attributes":"Enterprise_Customer::attributes","config\/acl\/resources\/admin\/customer\/attributes\/customer_attributes":"Enterprise_Customer::customer_attributes","config\/acl\/resources\/admin\/customer\/attributes\/customer_address_attributes":"Enterprise_Customer::customer_address_attributes","config\/acl\/resources\/admin\/system\/config\/giftcardaccount":"Enterprise_GiftCardAccount::giftcardaccount","config\/acl\/resources\/admin\/customer\/giftcardaccount":"Enterprise_GiftCardAccount::customer_giftcardaccount","config\/acl\/resources\/admin\/system\/config\/giftcard":"Enterprise_GiftCard::giftcard","config\/acl\/resources\/admin\/system\/config\/enterprise_giftregistry":"Enterprise_GiftRegistry::enterprise_giftregistry","config\/acl\/resources\/admin\/customer\/enterprise_giftregistry":"Enterprise_GiftRegistry::customer_enterprise_giftregistry","config\/acl\/resources\/admin\/sales\/enterprise_giftwrapping":"Enterprise_GiftWrapping::enterprise_giftwrapping","config\/acl\/resources\/admin\/system\/convert\/enterprise_scheduled_operation":"Enterprise_ImportExport::enterprise_scheduled_operation","config\/acl\/resources\/admin\/customer\/enterprise_invitation":"Enterprise_Invitation::enterprise_invitation","config\/acl\/resources\/admin\/report\/enterprise_invitation":"Enterprise_Invitation::report_enterprise_invitation","config\/acl\/resources\/admin\/report\/enterprise_invitation\/general":"Enterprise_Invitation::general","config\/acl\/resources\/admin\/report\/enterprise_invitation\/customer":"Enterprise_Invitation::enterprise_invitation_customer","config\/acl\/resources\/admin\/report\/enterprise_invitation\/order":"Enterprise_Invitation::order","config\/acl\/resources\/admin\/system\/config\/enterprise_invitation":"Enterprise_Invitation::config_enterprise_invitation","config\/acl\/resources\/admin\/system\/config\/logging":"Enterprise_Logging::logging","config\/acl\/resources\/admin\/system\/enterprise_logging":"Enterprise_Logging::enterprise_logging","config\/acl\/resources\/admin\/system\/enterprise_logging\/events":"Enterprise_Logging::enterprise_logging_events","config\/acl\/resources\/admin\/system\/enterprise_logging\/backups":"Enterprise_Logging::backups","config\/acl\/resources\/admin\/system\/crypt_key":"Enterprise_Pci::crypt_key","config\/acl\/resources\/admin\/system\/acl\/locks":"Enterprise_Pci::locks","config\/acl\/resources\/admin\/catalog\/products\/read_product_price":"Enterprise_PricePermissions::read_product_price","config\/acl\/resources\/admin\/catalog\/products\/read_product_price\/edit_product_price":"Enterprise_PricePermissions::edit_product_price","config\/acl\/resources\/admin\/catalog\/products\/edit_product_status":"Enterprise_PricePermissions::edit_product_status","config\/acl\/resources\/admin\/promo\/catalog\/edit":"Enterprise_PromotionPermissions::edit","config\/acl\/resources\/admin\/promo\/quote\/edit":"Enterprise_PromotionPermissions::quote_edit","config\/acl\/resources\/admin\/promo\/enterprise_reminder\/edit":"Enterprise_PromotionPermissions::enterprise_reminder_edit","config\/acl\/resources\/admin\/promo\/enterprise_reminder":"Enterprise_Reminder::enterprise_reminder","config\/acl\/resources\/admin\/system\/config\/promo":"Mage_SalesRule::config_promo","config\/acl\/resources\/admin\/customer\/manage\/reward_balance":"Enterprise_Reward::reward_balance","config\/acl\/resources\/admin\/sales\/order\/actions\/create\/reward_spend":"Enterprise_Reward::reward_spend","config\/acl\/resources\/admin\/customer\/rates":"Enterprise_Reward::rates","config\/acl\/resources\/admin\/system\/config\/enterprise_reward":"Enterprise_Reward::enterprise_reward","config\/acl\/resources\/admin\/sales\/enterprise_rma":"Enterprise_Rma::enterprise_rma","config\/acl\/resources\/admin\/sales\/enterprise_rma\/rma_manage":"Enterprise_Rma::rma_manage","config\/acl\/resources\/admin\/sales\/enterprise_rma\/rma_attribute":"Enterprise_Rma::rma_attribute","config\/acl\/resources\/admin\/sales\/archive":"Enterprise_SalesArchive::archive","config\/acl\/resources\/admin\/sales\/archive\/orders":"Enterprise_SalesArchive::orders","config\/acl\/resources\/admin\/sales\/archive\/orders\/add":"Enterprise_SalesArchive::add","config\/acl\/resources\/admin\/sales\/archive\/orders\/remove":"Enterprise_SalesArchive::remove","config\/acl\/resources\/admin\/sales\/archive\/invoices":"Enterprise_SalesArchive::invoices","config\/acl\/resources\/admin\/sales\/archive\/shipments":"Enterprise_SalesArchive::shipments","config\/acl\/resources\/admin\/sales\/archive\/creditmemos":"Enterprise_SalesArchive::creditmemos","config\/acl\/resources\/admin\/catalog\/targetrule":"Enterprise_TargetRule::targetrule","config\/acl\/resources\/admin\/report\/customers\/wishlist":"Enterprise_Wishlist::wishlist","config\/acl\/resources\/admin\/system\/adminnotification":"Mage_AdminNotification::adminnotification","config\/acl\/resources\/admin\/system\/adminnotification\/show_toolbar":"Mage_AdminNotification::show_toolbar","config\/acl\/resources\/admin\/system\/adminnotification\/show_list":"Mage_AdminNotification::show_list","config\/acl\/resources\/admin\/system\/adminnotification\/mark_as_read":"Mage_AdminNotification::mark_as_read","config\/acl\/resources\/admin\/system\/adminnotification\/remove":"Mage_AdminNotification::adminnotification_remove","config\/acl\/resources\/all":"Mage_Adminhtml::all","config\/acl\/resources\/admin":"Mage_Adminhtml::admin","config\/acl\/resources\/admin\/dashboard":"Mage_Adminhtml::dashboard","config\/acl\/resources\/admin\/system":"Mage_Adminhtml::system","config\/acl\/resources\/admin\/system\/store":"Mage_Adminhtml::store","config\/acl\/resources\/admin\/system\/design":"Mage_Adminhtml::design","config\/acl\/resources\/admin\/system\/design\/schedule":"Mage_Adminhtml::schedule","config\/acl\/resources\/admin\/system\/config":"Mage_Adminhtml::config","config\/acl\/resources\/admin\/system\/config\/general":"Mage_Adminhtml::config_general","config\/acl\/resources\/admin\/system\/config\/web":"Mage_Adminhtml::web","config\/acl\/resources\/admin\/system\/config\/design":"Mage_Adminhtml::config_design","config\/acl\/resources\/admin\/system\/config\/system":"Mage_Adminhtml::config_system","config\/acl\/resources\/admin\/system\/config\/advanced":"Mage_Adminhtml::advanced","config\/acl\/resources\/admin\/system\/config\/trans_email":"Mage_Adminhtml::trans_email","config\/acl\/resources\/admin\/system\/config\/dev":"Mage_Adminhtml::dev","config\/acl\/resources\/admin\/system\/config\/currency":"Mage_Adminhtml::currency","config\/acl\/resources\/admin\/system\/config\/sendfriend":"Mage_Adminhtml::sendfriend","config\/acl\/resources\/admin\/system\/config\/admin":"Mage_Adminhtml::config_admin","config\/acl\/resources\/admin\/system\/currency":"Mage_CurrencySymbol::system_currency","config\/acl\/resources\/admin\/system\/email_template":"Mage_Adminhtml::email_template","config\/acl\/resources\/admin\/system\/variable":"Mage_Adminhtml::variable","config\/acl\/resources\/admin\/system\/myaccount":"Mage_Adminhtml::myaccount","config\/acl\/resources\/admin\/system\/tools":"Mage_Adminhtml::tools","config\/acl\/resources\/admin\/system\/convert":"Mage_Adminhtml::convert","config\/acl\/resources\/admin\/system\/cache":"Mage_Adminhtml::cache","config\/acl\/resources\/admin\/system\/extensions":"Mage_Adminhtml::extensions","config\/acl\/resources\/admin\/system\/extensions\/local":"Mage_Adminhtml::local","config\/acl\/resources\/admin\/system\/extensions\/custom":"Mage_Adminhtml::custom","config\/acl\/resources\/admin\/global_search":"Mage_Adminhtml::global_search","config\/acl\/resources\/admin\/system\/api":"Mage_Api::api","config\/acl\/resources\/admin\/system\/api\/users":"Mage_Api::users","config\/acl\/resources\/admin\/system\/api\/roles":"Mage_Api::roles","config\/acl\/resources\/admin\/system\/config\/api":"Mage_Api::config_api","config\/acl\/resources\/admin\/system\/tools\/backup":"Mage_Backup::backup","config\/acl\/resources\/admin\/system\/tools\/backup\/rollback":"Mage_Backup::rollback","config\/acl\/resources\/admin\/system\/config\/cataloginventory":"Mage_CatalogInventory::cataloginventory","config\/acl\/resources\/admin\/promo":"Mage_CatalogRule::promo","config\/acl\/resources\/admin\/promo\/catalog":"Mage_CatalogRule::promo_catalog","config\/acl\/resources\/admin\/catalog\/search":"Mage_CatalogSearch::search","config\/acl\/resources\/admin\/system\/config\/catalog":"Mage_Catalog::config_catalog","config\/acl\/resources\/admin\/catalog":"Mage_Catalog::catalog","config\/acl\/resources\/admin\/catalog\/attributes":"Mage_Catalog::catalog_attributes","config\/acl\/resources\/admin\/catalog\/attributes\/attributes":"Mage_Catalog::attributes_attributes","config\/acl\/resources\/admin\/catalog\/attributes\/sets":"Mage_Catalog::sets","config\/acl\/resources\/admin\/catalog\/categories":"Mage_Catalog::categories","config\/acl\/resources\/admin\/catalog\/products":"Mage_Catalog::products","config\/acl\/resources\/admin\/catalog\/update_attributes":"Mage_Catalog::update_attributes","config\/acl\/resources\/admin\/catalog\/urlrewrite":"Mage_Catalog::urlrewrite","config\/acl\/resources\/admin\/sales\/checkoutagreement":"Mage_Checkout::checkoutagreement","config\/acl\/resources\/admin\/system\/config\/checkout":"Mage_Checkout::checkout","config\/acl\/resources\/admin\/cms":"Mage_Cms::cms","config\/acl\/resources\/admin\/cms\/block":"Mage_Cms::block","config\/acl\/resources\/admin\/cms\/page":"Mage_Cms::page","config\/acl\/resources\/admin\/cms\/page\/save":"Mage_Cms::save","config\/acl\/resources\/admin\/cms\/page\/delete":"Mage_Cms::page_delete","config\/acl\/resources\/admin\/cms\/media_gallery":"Mage_Cms::media_gallery","config\/acl\/resources\/admin\/system\/config\/cms":"Mage_Cms::config_cms","config\/acl\/resources\/admin\/system\/config\/contacts":"Mage_Contacts::contacts","config\/acl\/resources\/admin\/system\/currency\/rates":"Mage_CurrencySymbol::currency_rates","config\/acl\/resources\/admin\/system\/currency\/symbols":"Mage_CurrencySymbol::symbols","config\/acl\/resources\/admin\/customer":"Mage_Customer::customer","config\/acl\/resources\/admin\/customer\/group":"Mage_Customer::group","config\/acl\/resources\/admin\/customer\/manage":"Mage_Customer::manage","config\/acl\/resources\/admin\/customer\/online":"Mage_Customer::online","config\/acl\/resources\/admin\/system\/config\/customer":"Mage_Customer::config_customer","config\/acl\/resources\/admin\/system\/design\/editor":"Mage_DesignEditor::editor","config\/acl\/resources\/admin\/system\/config\/downloadable":"Mage_Downloadable::downloadable","config\/acl\/resources\/admin\/system\/config\/google":"Mage_GoogleCheckout::google","config\/acl\/resources\/admin\/catalog\/googleshopping":"Mage_GoogleShopping::googleshopping","config\/acl\/resources\/admin\/catalog\/googleshopping\/types":"Mage_GoogleShopping::types","config\/acl\/resources\/admin\/catalog\/googleshopping\/items":"Mage_GoogleShopping::items","config\/acl\/resources\/admin\/system\/convert\/import":"Mage_ImportExport::import","config\/acl\/resources\/admin\/system\/convert\/export":"Mage_ImportExport::export","config\/acl\/resources\/admin\/system\/index":"Mage_Index::index","config\/acl\/resources\/admin\/system\/config\/newsletter":"Mage_Newsletter::newsletter","config\/acl\/resources\/admin\/newsletter":"Mage_Newsletter::admin_newsletter","config\/acl\/resources\/admin\/newsletter\/problem":"Mage_Newsletter::problem","config\/acl\/resources\/admin\/newsletter\/queue":"Mage_Newsletter::queue","config\/acl\/resources\/admin\/newsletter\/subscriber":"Mage_Newsletter::subscriber","config\/acl\/resources\/admin\/newsletter\/template":"Mage_Newsletter::template","config\/acl\/resources\/admin\/system\/api\/consumer":"Mage_Oauth::consumer","config\/acl\/resources\/admin\/system\/api\/consumer\/edit":"Mage_Oauth::consumer_edit","config\/acl\/resources\/admin\/system\/api\/consumer\/delete":"Mage_Oauth::consumer_delete","config\/acl\/resources\/admin\/system\/api\/authorizedTokens":"Mage_Oauth::authorizedTokens","config\/acl\/resources\/admin\/system\/api\/oauth_admin_token":"Mage_Oauth::oauth_admin_token","config\/acl\/resources\/admin\/system\/config\/oauth":"Mage_Oauth::oauth","config\/acl\/resources\/admin\/page_cache":"Mage_PageCache::page_cache","config\/acl\/resources\/admin\/system\/config\/payment":"Mage_Payment::payment","config\/acl\/resources\/admin\/system\/config\/payment_services":"Mage_Payment::payment_services","config\/acl\/resources\/admin\/system\/config\/paypal":"Mage_Paypal::paypal","config\/acl\/resources\/admin\/report\/salesroot\/paypal_settlement_reports":"Mage_Paypal::paypal_settlement_reports","config\/acl\/resources\/admin\/report\/salesroot\/paypal_settlement_reports\/view":"Mage_Paypal::paypal_settlement_reports_view","config\/acl\/resources\/admin\/report\/salesroot\/paypal_settlement_reports\/fetch":"Mage_Paypal::fetch","config\/acl\/resources\/admin\/system\/config\/persistent":"Mage_Persistent::persistent","config\/acl\/resources\/admin\/cms\/poll":"Mage_Poll::poll","config\/acl\/resources\/admin\/catalog\/reviews_ratings\/ratings":"Mage_Rating::ratings","config\/acl\/resources\/admin\/report":"Mage_Reports::report","config\/acl\/resources\/admin\/report\/salesroot":"Mage_Reports::salesroot","config\/acl\/resources\/admin\/report\/salesroot\/sales":"Mage_Reports::salesroot_sales","config\/acl\/resources\/admin\/report\/salesroot\/tax":"Mage_Reports::tax","config\/acl\/resources\/admin\/report\/salesroot\/shipping":"Mage_Reports::shipping","config\/acl\/resources\/admin\/report\/salesroot\/invoiced":"Mage_Reports::invoiced","config\/acl\/resources\/admin\/report\/salesroot\/refunded":"Mage_Reports::refunded","config\/acl\/resources\/admin\/report\/salesroot\/coupons":"Mage_Reports::coupons","config\/acl\/resources\/admin\/report\/shopcart":"Mage_Reports::shopcart","config\/acl\/resources\/admin\/report\/shopcart\/product":"Mage_Reports::product","config\/acl\/resources\/admin\/report\/shopcart\/abandoned":"Mage_Reports::abandoned","config\/acl\/resources\/admin\/report\/products":"Mage_Reports::report_products","config\/acl\/resources\/admin\/report\/products\/bestsellers":"Mage_Reports::bestsellers","config\/acl\/resources\/admin\/report\/products\/sold":"Mage_Reports::sold","config\/acl\/resources\/admin\/report\/products\/viewed":"Mage_Reports::viewed","config\/acl\/resources\/admin\/report\/products\/lowstock":"Mage_Reports::lowstock","config\/acl\/resources\/admin\/report\/products\/downloads":"Mage_Reports::downloads","config\/acl\/resources\/admin\/report\/customers":"Mage_Reports::customers","config\/acl\/resources\/admin\/report\/customers\/accounts":"Mage_Reports::accounts","config\/acl\/resources\/admin\/report\/customers\/totals":"Mage_Reports::totals","config\/acl\/resources\/admin\/report\/customers\/orders":"Mage_Reports::customers_orders","config\/acl\/resources\/admin\/report\/review":"Mage_Reports::review","config\/acl\/resources\/admin\/report\/review\/customer":"Mage_Reports::review_customer","config\/acl\/resources\/admin\/report\/review\/product":"Mage_Reports::review_product","config\/acl\/resources\/admin\/report\/tags":"Mage_Reports::tags","config\/acl\/resources\/admin\/report\/tags\/customer":"Mage_Reports::tags_customer","config\/acl\/resources\/admin\/report\/tags\/popular":"Mage_Reports::popular","config\/acl\/resources\/admin\/report\/tags\/product":"Mage_Reports::tags_product","config\/acl\/resources\/admin\/report\/search":"Mage_Reports::report_search","config\/acl\/resources\/admin\/report\/statistics":"Mage_Reports::statistics","config\/acl\/resources\/admin\/system\/config\/reports":"Mage_Reports::reports","config\/acl\/resources\/admin\/catalog\/reviews_ratings":"Mage_Review::reviews_ratings","config\/acl\/resources\/admin\/catalog\/reviews_ratings\/reviews":"Mage_Review::reviews","config\/acl\/resources\/admin\/catalog\/reviews_ratings\/reviews\/all":"Mage_Review::reviews_all","config\/acl\/resources\/admin\/catalog\/reviews_ratings\/reviews\/pending":"Mage_Review::pending","config\/acl\/resources\/admin\/system\/config\/rss":"Mage_Rss::rss","config\/acl\/resources\/admin\/promo\/quote":"Mage_SalesRule::quote","config\/acl\/resources\/admin\/sales":"Mage_Sales::sales","config\/acl\/resources\/admin\/sales\/order":"Mage_Sales::sales_order","config\/acl\/resources\/admin\/sales\/order\/actions":"Mage_Sales::actions","config\/acl\/resources\/admin\/sales\/order\/actions\/create":"Mage_Sales::create","config\/acl\/resources\/admin\/sales\/order\/actions\/view":"Mage_Sales::actions_view","config\/acl\/resources\/admin\/sales\/order\/actions\/email":"Mage_Sales::email","config\/acl\/resources\/admin\/sales\/order\/actions\/reorder":"Mage_Sales::reorder","config\/acl\/resources\/admin\/sales\/order\/actions\/edit":"Mage_Sales::actions_edit","config\/acl\/resources\/admin\/sales\/order\/actions\/cancel":"Mage_Sales::cancel","config\/acl\/resources\/admin\/sales\/order\/actions\/review_payment":"Mage_Sales::review_payment","config\/acl\/resources\/admin\/sales\/order\/actions\/capture":"Mage_Sales::capture","config\/acl\/resources\/admin\/sales\/order\/actions\/invoice":"Mage_Sales::invoice","config\/acl\/resources\/admin\/sales\/order\/actions\/creditmemo":"Mage_Sales::creditmemo","config\/acl\/resources\/admin\/sales\/order\/actions\/hold":"Mage_Sales::hold","config\/acl\/resources\/admin\/sales\/order\/actions\/unhold":"Mage_Sales::unhold","config\/acl\/resources\/admin\/sales\/order\/actions\/ship":"Mage_Sales::ship","config\/acl\/resources\/admin\/sales\/order\/actions\/comment":"Mage_Sales::comment","config\/acl\/resources\/admin\/sales\/order\/actions\/emails":"Mage_Sales::emails","config\/acl\/resources\/admin\/sales\/invoice":"Mage_Sales::sales_invoice","config\/acl\/resources\/admin\/sales\/shipment":"Mage_Sales::shipment","config\/acl\/resources\/admin\/sales\/creditmemo":"Mage_Sales::sales_creditmemo","config\/acl\/resources\/admin\/sales\/transactions":"Mage_Sales::transactions","config\/acl\/resources\/admin\/sales\/transactions\/fetch":"Mage_Sales::transactions_fetch","config\/acl\/resources\/admin\/sales\/recurring_profile":"Mage_Sales::recurring_profile","config\/acl\/resources\/admin\/sales\/billing_agreement":"Mage_Sales::billing_agreement","config\/acl\/resources\/admin\/sales\/billing_agreement\/actions":"Mage_Sales::billing_agreement_actions","config\/acl\/resources\/admin\/sales\/billing_agreement\/actions\/view":"Mage_Sales::billing_agreement_actions_view","config\/acl\/resources\/admin\/sales\/billing_agreement\/actions\/manage":"Mage_Sales::actions_manage","config\/acl\/resources\/admin\/sales\/billing_agreement\/actions\/use":"Mage_Sales::use","config\/acl\/resources\/admin\/system\/order_statuses":"Mage_Sales::order_statuses","config\/acl\/resources\/admin\/system\/config\/sales":"Mage_Sales::config_sales","config\/acl\/resources\/admin\/system\/config\/sales_email":"Mage_Sales::sales_email","config\/acl\/resources\/admin\/system\/config\/sales_pdf":"Mage_Sales::sales_pdf","config\/acl\/resources\/admin\/system\/config\/shipping":"Mage_Shipping::config_shipping","config\/acl\/resources\/admin\/system\/config\/carriers":"Mage_Shipping::carriers","config\/acl\/resources\/admin\/catalog\/sitemap":"Mage_Sitemap::sitemap","config\/acl\/resources\/admin\/system\/config\/sitemap":"Mage_Sitemap::config_sitemap","config\/acl\/resources\/admin\/catalog\/tag":"Mage_Tag::tag","config\/acl\/resources\/admin\/catalog\/tag\/all":"Mage_Tag::tag_all","config\/acl\/resources\/admin\/catalog\/tag\/pending":"Mage_Tag::tag_pending","config\/acl\/resources\/admin\/sales\/tax":"Mage_Tax::sales_tax","config\/acl\/resources\/admin\/sales\/tax\/classes_customer":"Mage_Tax::classes_customer","config\/acl\/resources\/admin\/sales\/tax\/classes_product":"Mage_Tax::classes_product","config\/acl\/resources\/admin\/sales\/tax\/import_export":"Mage_Tax::import_export","config\/acl\/resources\/admin\/sales\/tax\/rates":"Mage_Tax::tax_rates","config\/acl\/resources\/admin\/sales\/tax\/rules":"Mage_Tax::rules","config\/acl\/resources\/admin\/system\/config\/tax":"Mage_Tax::config_tax","config\/acl\/resources\/admin\/system\/acl":"Mage_User::acl","config\/acl\/resources\/admin\/system\/acl\/roles":"Mage_User::acl_roles","config\/acl\/resources\/admin\/system\/acl\/users":"Mage_User::acl_users","config\/acl\/resources\/admin\/cms\/widget_instance":"Mage_Widget::widget_instance","config\/acl\/resources\/admin\/system\/config\/wishlist":"Mage_Wishlist::config_wishlist"} diff --git a/dev/tools/migration/Acl/log/MenuIdToAclId.log b/dev/tools/migration/Acl/log/MenuIdToAclId.log index 7474faaeba588517379df9efc258d0bc4ec707f9..898873617502dd2630a18008d61545edc7f3ba51 100644 --- a/dev/tools/migration/Acl/log/MenuIdToAclId.log +++ b/dev/tools/migration/Acl/log/MenuIdToAclId.log @@ -1 +1 @@ -{"Find_Feed::catalog_feed":"Find_Feed::feed","Find_Feed::catalog_feed_import_products":"Find_Feed::import_products","Find_Feed::catalog_feed_import_items":"Find_Feed::import_items","Enterprise_Banner::cms_enterprise_banner":"Enterprise_Banner::enterprise_banner","Enterprise_CatalogEvent::catalog_enterprise_catalogevent":"Mage_Catalog::categories","Enterprise_CatalogEvent::catalog_enterprise_catalogevent_events":"Enterprise_CatalogEvent::events","Enterprise_Cms::cms_enterprise_page":"Mage_Cms::page","Enterprise_Cms::cms_enterprise_page_page":"Mage_Cms::page","Enterprise_Cms::cms_enterprise_page_hierarchy":"Enterprise_Cms::hierarchy","Enterprise_CustomerSegment::customer_customersegment":"Enterprise_CustomerSegment::customersegment","Enterprise_CustomerSegment::report_customers_segment":"Enterprise_CustomerSegment::segment","Enterprise_Customer::customer_attributes":"Enterprise_Customer::attributes","Enterprise_Customer::customer_attributes_customer_attributes":"Enterprise_Customer::customer_attributes","Enterprise_Customer::customer_attributes_customer_address_attributes":"Enterprise_Customer::customer_address_attributes","Enterprise_GiftCardAccount::customer_giftcardaccount":"Enterprise_GiftCardAccount::customer_giftcardaccount","Enterprise_GiftRegistry::customer_enterprise_giftregistry":"Enterprise_GiftRegistry::customer_enterprise_giftregistry","Enterprise_GiftWrapping::sales_enterprise_giftwrapping":"Enterprise_GiftWrapping::enterprise_giftwrapping","Enterprise_ImportExport::system_convert_enterprise_scheduled_operation":"Enterprise_ImportExport::enterprise_scheduled_operation","Enterprise_Invitation::customer_enterprise_invitation":"Enterprise_Invitation::enterprise_invitation","Enterprise_Invitation::report_enterprise_invitation":"Enterprise_Invitation::report_enterprise_invitation","Enterprise_Invitation::report_enterprise_invitation_general":"Enterprise_Invitation::report_enterprise_invitation","Enterprise_Invitation::report_enterprise_invitation_customer":"Enterprise_Invitation::report_enterprise_invitation","Enterprise_Invitation::report_enterprise_invitation_order":"Enterprise_Invitation::report_enterprise_invitation","Enterprise_Logging::system_enterprise_logging":"Enterprise_Logging::enterprise_logging","Enterprise_Logging::system_enterprise_logging_events":"Enterprise_Logging::enterprise_logging_events","Enterprise_Logging::system_enterprise_logging_backups":"Enterprise_Logging::backups","Enterprise_Pci::system_crypt_key":"Enterprise_Pci::crypt_key","Enterprise_Pci::system_acl_locks":"Enterprise_Pci::locks","Enterprise_Reminder::promo_reminder":"Enterprise_Reminder::enterprise_reminder","Enterprise_Reward::customer_reward":"Enterprise_Reward::rates","Enterprise_Rma::sales_enterprise_rma":"Enterprise_Rma::enterprise_rma","Enterprise_Rma::sales_enterprise_rma_rma":"Enterprise_Rma::enterprise_rma","Enterprise_Rma::sales_enterprise_rma_rma_item_attribute":"Enterprise_Rma::enterprise_rma","Enterprise_SalesArchive::sales_archive":"Enterprise_SalesArchive::archive","Enterprise_SalesArchive::sales_archive_orders":"Enterprise_SalesArchive::orders","Enterprise_SalesArchive::sales_archive_invoices":"Enterprise_SalesArchive::invoices","Enterprise_SalesArchive::sales_archive_shipments":"Enterprise_SalesArchive::shipments","Enterprise_SalesArchive::sales_archive_creditmemos":"Enterprise_SalesArchive::creditmemos","Enterprise_TargetRule::catalog_targetrule":"Enterprise_TargetRule::targetrule","Enterprise_Wishlist::report_customers_wishlist":"Enterprise_Wishlist::wishlist","Mage_AdminNotification::system_adminnotification":"Mage_AdminNotification::adminnotification","Mage_Adminhtml::dashboard":"Mage_Adminhtml::dashboard","Mage_Adminhtml::system":"Mage_Adminhtml::system","Mage_Adminhtml::system_myaccount":"Mage_Adminhtml::myaccount","Mage_Adminhtml::system_tools":"Mage_Adminhtml::tools","Mage_Adminhtml::system_design":"Mage_Adminhtml::design","Mage_Adminhtml::system_design_schedule":"Mage_Adminhtml::schedule","Mage_Adminhtml::system_currency":"Mage_CurrencySymbol::system_currency","Mage_Adminhtml::system_email_template":"Mage_Adminhtml::email_template","Mage_Adminhtml::system_variable":"Mage_Adminhtml::variable","Mage_Adminhtml::system_cache":"Mage_Adminhtml::cache","Mage_Adminhtml::system_store":"Mage_Adminhtml::store","Mage_Adminhtml::system_config":"Mage_Adminhtml::config","Mage_Api2::system_api_rest_roles":"Mage_Api2::rest_roles","Mage_Api2::system_api_rest_attributes":"Mage_Api2::rest_attributes","Mage_Api::system_api":"Mage_Api::api","Mage_Api::system_api_users":"Mage_Api::users","Mage_Api::system_api_roles":"Mage_Api::roles","Mage_Backup::system_tools_backup":"Mage_Backup::backup","Mage_CatalogRule::promo":"Mage_CatalogRule::promo","Mage_CatalogRule::promo_catalog":"Mage_CatalogRule::promo_catalog","Mage_CatalogSearch::catalog_search":"Mage_CatalogSearch::search","Mage_Catalog::catalog":"Mage_Catalog::catalog","Mage_Catalog::catalog_products":"Mage_Catalog::products","Mage_Catalog::catalog_categories":"Mage_Catalog::categories","Mage_Catalog::catalog_attributes":"Mage_Catalog::catalog_attributes","Mage_Catalog::catalog_attributes_attributes":"Mage_Catalog::attributes_attributes","Mage_Catalog::catalog_attributes_sets":"Mage_Catalog::sets","Mage_Catalog::catalog_urlrewrite":"Mage_Catalog::urlrewrite","Mage_Checkout::sales_checkoutagreement":"Mage_Checkout::checkoutagreement","Mage_Cms::cms":"Mage_Cms::cms","Mage_Cms::cms_page":"Mage_Cms::page","Mage_Cms::cms_block":"Mage_Cms::block","Mage_Connect::system_extensions":"Mage_Adminhtml::extensions","Mage_Connect::system_extensions_local":"Mage_Adminhtml::local","Mage_Connect::system_extensions_custom":"Mage_Adminhtml::custom","Mage_CurrencySymbol::system_currency_rates":"Mage_CurrencySymbol::currency_rates","Mage_CurrencySymbol::system_currency_symbols":"Mage_CurrencySymbol::symbols","Mage_Customer::customer":"Mage_Customer::customer","Mage_Customer::customer_manage":"Mage_Customer::manage","Mage_Customer::customer_group":"Mage_Customer::group","Mage_Customer::customer_online":"Mage_Customer::online","Mage_DesignEditor::system_design_editor":"Mage_DesignEditor::editor","Mage_Downloadable::report_products_downloads":"Mage_Reports::downloads","Mage_GoogleShopping::catalog_googleshopping":"Mage_GoogleShopping::googleshopping","Mage_GoogleShopping::catalog_googleshopping_types":"Mage_GoogleShopping::types","Mage_GoogleShopping::catalog_googleshopping_items":"Mage_GoogleShopping::items","Mage_ImportExport::system_convert_import":"Mage_ImportExport::import","Mage_ImportExport::system_convert_export":"Mage_ImportExport::export","Mage_Index::system_index":"Mage_Index::index","Mage_Newsletter::newsletter":"Mage_Newsletter::admin_newsletter","Mage_Newsletter::newsletter_template":"Mage_Newsletter::template","Mage_Newsletter::newsletter_queue":"Mage_Newsletter::queue","Mage_Newsletter::newsletter_subscriber":"Mage_Newsletter::subscriber","Mage_Newsletter::newsletter_problem":"Mage_Newsletter::problem","Mage_Oauth::system_api_oauth_admin_token":"Mage_Oauth::oauth_admin_token","Mage_Paypal::report_salesroot_paypal_settlement_reports":"Mage_Paypal::paypal_settlement_reports","Mage_Poll::cms_poll":"Mage_Poll::poll","Mage_Reports::report":"Mage_Reports::report","Mage_Reports::report_salesroot":"Mage_Reports::salesroot","Mage_Reports::report_salesroot_sales":"Mage_Reports::salesroot_sales","Mage_Reports::report_salesroot_tax":"Mage_Reports::tax","Mage_Reports::report_salesroot_invoiced":"Mage_Reports::invoiced","Mage_Reports::report_salesroot_shipping":"Mage_Reports::shipping","Mage_Reports::report_salesroot_refunded":"Mage_Reports::refunded","Mage_Reports::report_salesroot_coupons":"Mage_Reports::coupons","Mage_Reports::report_shopcart":"Mage_Reports::shopcart","Mage_Reports::report_shopcart_product":"Mage_Reports::product","Mage_Reports::report_shopcart_abandoned":"Mage_Reports::abandoned","Mage_Reports::report_products":"Mage_Reports::report_products","Mage_Reports::report_products_bestsellers":"Mage_Reports::bestsellers","Mage_Reports::report_products_sold":"Mage_Reports::sold","Mage_Reports::report_products_viewed":"Mage_Reports::viewed","Mage_Reports::report_products_lowstock":"Mage_Reports::lowstock","Mage_Reports::report_customers":"Mage_Reports::customers","Mage_Reports::report_customers_accounts":"Mage_Reports::accounts","Mage_Reports::report_customers_totals":"Mage_Reports::totals","Mage_Reports::report_customers_orders":"Mage_Reports::customers_orders","Mage_Reports::report_search":"Mage_Reports::report_search","Mage_Reports::report_statistics":"Mage_Reports::statistics","Mage_Review::catalog_reviews_ratings":"Mage_Review::reviews_ratings","Mage_Review::catalog_reviews_ratings_reviews":"Mage_Review::reviews","Mage_Review::catalog_reviews_ratings_ratings":"Mage_Rating::ratings","Mage_Review::catalog_reviews_ratings_reviews_pending":"Mage_Review::pending","Mage_Review::catalog_reviews_ratings_reviews_all":"Mage_Review::reviews_all","Mage_Review::report_review":"Mage_Reports::review","Mage_Review::report_review_customer":"Mage_Reports::review_customer","Mage_Review::report_review_product":"Mage_Reports::review_product","Mage_SalesRule::promo_quote":"Mage_SalesRule::quote","Mage_Sales::sales":"Mage_Sales::sales","Mage_Sales::sales_order":"Mage_Sales::sales_order","Mage_Sales::sales_invoice":"Mage_Sales::sales_invoice","Mage_Sales::sales_shipment":"Mage_Sales::shipment","Mage_Sales::sales_creditmemo":"Mage_Sales::sales_creditmemo","Mage_Sales::sales_transactions":"Mage_Sales::transactions","Mage_Sales::sales_recurring_profile":"Mage_Sales::recurring_profile","Mage_Sales::sales_billing_agreement":"Mage_Sales::billing_agreement","Mage_Sales::system_order_statuses":"Mage_Sales::order_statuses","Mage_Sitemap::catalog_sitemap":"Mage_Sitemap::sitemap","Mage_Tag::catalog_tag":"Mage_Tag::tag","Mage_Tag::catalog_tag_all":"Mage_Tag::tag_all","Mage_Tag::catalog_tag_pending":"Mage_Tag::tag_pending","Mage_Tag::report_tags":"Mage_Reports::tags","Mage_Tag::report_tags_customer":"Mage_Reports::tags_customer","Mage_Tag::report_tags_product":"Mage_Reports::tags_product","Mage_Tag::report_tags_popular":"Mage_Reports::popular","Mage_Tax::sales_tax":"Mage_Tax::sales_tax","Mage_Tax::sales_tax_rules":"Mage_Tax::rules","Mage_Tax::sales_tax_rates":"Mage_Tax::tax_rates","Mage_Tax::sales_tax_import_export":"Mage_Tax::import_export","Mage_Tax::sales_tax_classes_customer":"Mage_Tax::classes_customer","Mage_Tax::sales_tax_classes_product":"Mage_Tax::classes_product","Mage_User::system_acl":"Mage_User::acl","Mage_User::system_acl_users":"Mage_User::acl_users","Mage_User::system_acl_roles":"Mage_User::acl_roles","Mage_Widget::cms_widget_instance":"Mage_Widget::widget_instance"} +{"Find_Feed::catalog_feed":"Find_Feed::feed","Find_Feed::catalog_feed_import_products":"Find_Feed::import_products","Find_Feed::catalog_feed_import_items":"Find_Feed::import_items","Enterprise_Banner::cms_enterprise_banner":"Enterprise_Banner::enterprise_banner","Enterprise_CatalogEvent::catalog_enterprise_catalogevent":"Mage_Catalog::categories","Enterprise_CatalogEvent::catalog_enterprise_catalogevent_events":"Enterprise_CatalogEvent::events","Enterprise_Cms::cms_enterprise_page":"Mage_Cms::page","Enterprise_Cms::cms_enterprise_page_page":"Mage_Cms::page","Enterprise_Cms::cms_enterprise_page_hierarchy":"Enterprise_Cms::hierarchy","Enterprise_CustomerSegment::customer_customersegment":"Enterprise_CustomerSegment::customersegment","Enterprise_CustomerSegment::report_customers_segment":"Enterprise_CustomerSegment::segment","Enterprise_Customer::customer_attributes":"Enterprise_Customer::attributes","Enterprise_Customer::customer_attributes_customer_attributes":"Enterprise_Customer::customer_attributes","Enterprise_Customer::customer_attributes_customer_address_attributes":"Enterprise_Customer::customer_address_attributes","Enterprise_GiftCardAccount::customer_giftcardaccount":"Enterprise_GiftCardAccount::customer_giftcardaccount","Enterprise_GiftRegistry::customer_enterprise_giftregistry":"Enterprise_GiftRegistry::customer_enterprise_giftregistry","Enterprise_GiftWrapping::sales_enterprise_giftwrapping":"Enterprise_GiftWrapping::enterprise_giftwrapping","Enterprise_ImportExport::system_convert_enterprise_scheduled_operation":"Enterprise_ImportExport::enterprise_scheduled_operation","Enterprise_Invitation::customer_enterprise_invitation":"Enterprise_Invitation::enterprise_invitation","Enterprise_Invitation::report_enterprise_invitation":"Enterprise_Invitation::report_enterprise_invitation","Enterprise_Invitation::report_enterprise_invitation_general":"Enterprise_Invitation::report_enterprise_invitation","Enterprise_Invitation::report_enterprise_invitation_customer":"Enterprise_Invitation::report_enterprise_invitation","Enterprise_Invitation::report_enterprise_invitation_order":"Enterprise_Invitation::report_enterprise_invitation","Enterprise_Logging::system_enterprise_logging":"Enterprise_Logging::enterprise_logging","Enterprise_Logging::system_enterprise_logging_events":"Enterprise_Logging::enterprise_logging_events","Enterprise_Logging::system_enterprise_logging_backups":"Enterprise_Logging::backups","Enterprise_Pci::system_crypt_key":"Enterprise_Pci::crypt_key","Enterprise_Pci::system_acl_locks":"Enterprise_Pci::locks","Enterprise_Reminder::promo_reminder":"Enterprise_Reminder::enterprise_reminder","Enterprise_Reward::customer_reward":"Enterprise_Reward::rates","Enterprise_Rma::sales_enterprise_rma":"Enterprise_Rma::enterprise_rma","Enterprise_Rma::sales_enterprise_rma_rma":"Enterprise_Rma::enterprise_rma","Enterprise_Rma::sales_enterprise_rma_rma_item_attribute":"Enterprise_Rma::enterprise_rma","Enterprise_SalesArchive::sales_archive":"Enterprise_SalesArchive::archive","Enterprise_SalesArchive::sales_archive_orders":"Enterprise_SalesArchive::orders","Enterprise_SalesArchive::sales_archive_invoices":"Enterprise_SalesArchive::invoices","Enterprise_SalesArchive::sales_archive_shipments":"Enterprise_SalesArchive::shipments","Enterprise_SalesArchive::sales_archive_creditmemos":"Enterprise_SalesArchive::creditmemos","Enterprise_TargetRule::catalog_targetrule":"Enterprise_TargetRule::targetrule","Enterprise_Wishlist::report_customers_wishlist":"Enterprise_Wishlist::wishlist","Mage_AdminNotification::system_adminnotification":"Mage_AdminNotification::adminnotification","Mage_Adminhtml::dashboard":"Mage_Adminhtml::dashboard","Mage_Adminhtml::system":"Mage_Adminhtml::system","Mage_Adminhtml::system_myaccount":"Mage_Adminhtml::myaccount","Mage_Adminhtml::system_tools":"Mage_Adminhtml::tools","Mage_Adminhtml::system_design":"Mage_Adminhtml::design","Mage_Adminhtml::system_design_schedule":"Mage_Adminhtml::schedule","Mage_Adminhtml::system_currency":"Mage_CurrencySymbol::system_currency","Mage_Adminhtml::system_email_template":"Mage_Adminhtml::email_template","Mage_Adminhtml::system_variable":"Mage_Adminhtml::variable","Mage_Adminhtml::system_cache":"Mage_Adminhtml::cache","Mage_Adminhtml::system_store":"Mage_Adminhtml::store","Mage_Adminhtml::system_config":"Mage_Adminhtml::config","Mage_Api::system_api":"Mage_Api::api","Mage_Api::system_api_users":"Mage_Api::users","Mage_Api::system_api_roles":"Mage_Api::roles","Mage_Backup::system_tools_backup":"Mage_Backup::backup","Mage_CatalogRule::promo":"Mage_CatalogRule::promo","Mage_CatalogRule::promo_catalog":"Mage_CatalogRule::promo_catalog","Mage_CatalogSearch::catalog_search":"Mage_CatalogSearch::search","Mage_Catalog::catalog":"Mage_Catalog::catalog","Mage_Catalog::catalog_products":"Mage_Catalog::products","Mage_Catalog::catalog_categories":"Mage_Catalog::categories","Mage_Catalog::catalog_attributes":"Mage_Catalog::catalog_attributes","Mage_Catalog::catalog_attributes_attributes":"Mage_Catalog::attributes_attributes","Mage_Catalog::catalog_attributes_sets":"Mage_Catalog::sets","Mage_Catalog::catalog_urlrewrite":"Mage_Catalog::urlrewrite","Mage_Checkout::sales_checkoutagreement":"Mage_Checkout::checkoutagreement","Mage_Cms::cms":"Mage_Cms::cms","Mage_Cms::cms_page":"Mage_Cms::page","Mage_Cms::cms_block":"Mage_Cms::block","Mage_Connect::system_extensions":"Mage_Adminhtml::extensions","Mage_Connect::system_extensions_local":"Mage_Adminhtml::local","Mage_Connect::system_extensions_custom":"Mage_Adminhtml::custom","Mage_CurrencySymbol::system_currency_rates":"Mage_CurrencySymbol::currency_rates","Mage_CurrencySymbol::system_currency_symbols":"Mage_CurrencySymbol::symbols","Mage_Customer::customer":"Mage_Customer::customer","Mage_Customer::customer_manage":"Mage_Customer::manage","Mage_Customer::customer_group":"Mage_Customer::group","Mage_Customer::customer_online":"Mage_Customer::online","Mage_DesignEditor::system_design_editor":"Mage_DesignEditor::editor","Mage_Downloadable::report_products_downloads":"Mage_Reports::downloads","Mage_GoogleShopping::catalog_googleshopping":"Mage_GoogleShopping::googleshopping","Mage_GoogleShopping::catalog_googleshopping_types":"Mage_GoogleShopping::types","Mage_GoogleShopping::catalog_googleshopping_items":"Mage_GoogleShopping::items","Mage_ImportExport::system_convert_import":"Mage_ImportExport::import","Mage_ImportExport::system_convert_export":"Mage_ImportExport::export","Mage_Index::system_index":"Mage_Index::index","Mage_Newsletter::newsletter":"Mage_Newsletter::admin_newsletter","Mage_Newsletter::newsletter_template":"Mage_Newsletter::template","Mage_Newsletter::newsletter_queue":"Mage_Newsletter::queue","Mage_Newsletter::newsletter_subscriber":"Mage_Newsletter::subscriber","Mage_Newsletter::newsletter_problem":"Mage_Newsletter::problem","Mage_Oauth::system_api_oauth_admin_token":"Mage_Oauth::oauth_admin_token","Mage_Paypal::report_salesroot_paypal_settlement_reports":"Mage_Paypal::paypal_settlement_reports","Mage_Poll::cms_poll":"Mage_Poll::poll","Mage_Reports::report":"Mage_Reports::report","Mage_Reports::report_salesroot":"Mage_Reports::salesroot","Mage_Reports::report_salesroot_sales":"Mage_Reports::salesroot_sales","Mage_Reports::report_salesroot_tax":"Mage_Reports::tax","Mage_Reports::report_salesroot_invoiced":"Mage_Reports::invoiced","Mage_Reports::report_salesroot_shipping":"Mage_Reports::shipping","Mage_Reports::report_salesroot_refunded":"Mage_Reports::refunded","Mage_Reports::report_salesroot_coupons":"Mage_Reports::coupons","Mage_Reports::report_shopcart":"Mage_Reports::shopcart","Mage_Reports::report_shopcart_product":"Mage_Reports::product","Mage_Reports::report_shopcart_abandoned":"Mage_Reports::abandoned","Mage_Reports::report_products":"Mage_Reports::report_products","Mage_Reports::report_products_bestsellers":"Mage_Reports::bestsellers","Mage_Reports::report_products_sold":"Mage_Reports::sold","Mage_Reports::report_products_viewed":"Mage_Reports::viewed","Mage_Reports::report_products_lowstock":"Mage_Reports::lowstock","Mage_Reports::report_customers":"Mage_Reports::customers","Mage_Reports::report_customers_accounts":"Mage_Reports::accounts","Mage_Reports::report_customers_totals":"Mage_Reports::totals","Mage_Reports::report_customers_orders":"Mage_Reports::customers_orders","Mage_Reports::report_search":"Mage_Reports::report_search","Mage_Reports::report_statistics":"Mage_Reports::statistics","Mage_Review::catalog_reviews_ratings":"Mage_Review::reviews_ratings","Mage_Review::catalog_reviews_ratings_reviews":"Mage_Review::reviews","Mage_Review::catalog_reviews_ratings_ratings":"Mage_Rating::ratings","Mage_Review::catalog_reviews_ratings_reviews_pending":"Mage_Review::pending","Mage_Review::catalog_reviews_ratings_reviews_all":"Mage_Review::reviews_all","Mage_Review::report_review":"Mage_Reports::review","Mage_Review::report_review_customer":"Mage_Reports::review_customer","Mage_Review::report_review_product":"Mage_Reports::review_product","Mage_SalesRule::promo_quote":"Mage_SalesRule::quote","Mage_Sales::sales":"Mage_Sales::sales","Mage_Sales::sales_order":"Mage_Sales::sales_order","Mage_Sales::sales_invoice":"Mage_Sales::sales_invoice","Mage_Sales::sales_shipment":"Mage_Sales::shipment","Mage_Sales::sales_creditmemo":"Mage_Sales::sales_creditmemo","Mage_Sales::sales_transactions":"Mage_Sales::transactions","Mage_Sales::sales_recurring_profile":"Mage_Sales::recurring_profile","Mage_Sales::sales_billing_agreement":"Mage_Sales::billing_agreement","Mage_Sales::system_order_statuses":"Mage_Sales::order_statuses","Mage_Sitemap::catalog_sitemap":"Mage_Sitemap::sitemap","Mage_Tag::catalog_tag":"Mage_Tag::tag","Mage_Tag::catalog_tag_all":"Mage_Tag::tag_all","Mage_Tag::catalog_tag_pending":"Mage_Tag::tag_pending","Mage_Tag::report_tags":"Mage_Reports::tags","Mage_Tag::report_tags_customer":"Mage_Reports::tags_customer","Mage_Tag::report_tags_product":"Mage_Reports::tags_product","Mage_Tag::report_tags_popular":"Mage_Reports::popular","Mage_Tax::sales_tax":"Mage_Tax::sales_tax","Mage_Tax::sales_tax_rules":"Mage_Tax::rules","Mage_Tax::sales_tax_rates":"Mage_Tax::tax_rates","Mage_Tax::sales_tax_import_export":"Mage_Tax::import_export","Mage_Tax::sales_tax_classes_customer":"Mage_Tax::classes_customer","Mage_Tax::sales_tax_classes_product":"Mage_Tax::classes_product","Mage_User::system_acl":"Mage_User::acl","Mage_User::system_acl_users":"Mage_User::acl_users","Mage_User::system_acl_roles":"Mage_User::acl_roles","Mage_Widget::cms_widget_instance":"Mage_Widget::widget_instance"} diff --git a/dev/tools/migration/factory_table_names/replace_ce.php b/dev/tools/migration/factory_table_names/replace_ce.php index 6926f76e31c317a70e6b0a8e8a19ee6192bd1003..346b47965a49b636c946cc477710cd28204a6254 100644 --- a/dev/tools/migration/factory_table_names/replace_ce.php +++ b/dev/tools/migration/factory_table_names/replace_ce.php @@ -42,10 +42,10 @@ return array( 'api/rule' => 'api_rule', 'api/session' => 'api_session', 'api/user' => 'api_user', - 'api2/acl_attribute' => 'api2_acl_attribute', - 'api2/acl_role' => 'api2_acl_role', - 'api2/acl_rule' => 'api2_acl_rule', - 'api2/acl_user' => 'api2_acl_user', + 'webapi/acl_attribute' => 'webapi_acl_attribute', + 'webapi/acl_role' => 'webapi_acl_role', + 'webapi/acl_rule' => 'webapi_acl_rule', + 'webapi/acl_user' => 'webapi_acl_user', 'array(\'catalog/category\', \'datetime\')' => 'catalog_category_entity_datetime', 'array(\'catalog/category\', \'decimal\')' => 'catalog_category_entity_decimal', 'array(\'catalog/category\', \'int\')' => 'catalog_category_entity_int', diff --git a/downloader/lib/Mage/HTTP/Client/Curl.php b/downloader/lib/Mage/HTTP/Client/Curl.php index 29e024c36813d1730b7e5b75706292f5dcea7881..49a59e81a67930b0f48d5d15e82e11d63cc4332a 100644 --- a/downloader/lib/Mage/HTTP/Client/Curl.php +++ b/downloader/lib/Mage/HTTP/Client/Curl.php @@ -378,7 +378,7 @@ implements Mage_HTTP_IClient } $this->curlOption(CURLOPT_URL, $uri); - $this->curlOption(CURLOPT_SSL_VERIFYPEER, FALSE); + $this->curlOption(CURLOPT_SSL_VERIFYPEER, true); $this->curlOption(CURLOPT_SSL_VERIFYHOST, 2); // force method to POST if secured diff --git a/downloader/lib/Mage/Xml/Generator.php b/downloader/lib/Mage/Xml/Generator.php index 99e655da0990bc62256c61b48cfa69b8c5914770..6a847b377e98284b163030adba5e33bc66e7a071 100644 --- a/downloader/lib/Mage/Xml/Generator.php +++ b/downloader/lib/Mage/Xml/Generator.php @@ -25,9 +25,17 @@ */ class Mage_Xml_Generator { + /** + * This value is used to replace numeric keys while formatting data for xml output. + */ + const DEFAULT_ENTITY_ITEM_NAME = 'item'; + protected $_dom = null; protected $_currentDom; + /** @var string */ + protected $_defaultIndexedArrayItemName; + public function __construct() { $this->_dom = new DOMDocument('1.0'); @@ -60,7 +68,7 @@ class Mage_Xml_Generator $parentNode = $this->_getCurrentDom(); if(!$content || !count($content)) { return $this; - } + } foreach ($content as $_key=>$_item) { try{ $node = $this->getDom()->createElement($_key); @@ -93,7 +101,7 @@ class Mage_Xml_Generator $this->_setCurrentDom($node)->arrayToXml($_item); } elseif (is_array($_item) && isset($_item[0])) { foreach($_item as $k=>$v) { - $this->_setCurrentDom($node)->arrayToXml($v); + $this->_setCurrentDom($node)->arrayToXml(array($this->_getIndexedArrayItemName() => $v)); } } } @@ -111,4 +119,27 @@ class Mage_Xml_Generator return $this; } + /** + * Set xml node name to use instead of numeric index during numeric arrays conversion. + * + * @param $name + * @return Mage_Xml_Generator + */ + public function setIndexedArrayItemName($name) + { + $this->_defaultIndexedArrayItemName = $name; + return $this; + } + + /** + * Get xml node name to use instead of numeric index during numeric arrays conversion. + * + * @return string + */ + protected function _getIndexedArrayItemName() + { + return isset($this->_defaultIndexedArrayItemName) + ? $this->_defaultIndexedArrayItemName + : self::DEFAULT_ENTITY_ITEM_NAME; + } } diff --git a/lib/Mage/Xml/Generator.php b/lib/Mage/Xml/Generator.php index 7c9267b11ca1f4074c03a18ad3afe0cb1867b135..6a847b377e98284b163030adba5e33bc66e7a071 100644 --- a/lib/Mage/Xml/Generator.php +++ b/lib/Mage/Xml/Generator.php @@ -23,12 +23,19 @@ * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ - class Mage_Xml_Generator { + /** + * This value is used to replace numeric keys while formatting data for xml output. + */ + const DEFAULT_ENTITY_ITEM_NAME = 'item'; + protected $_dom = null; protected $_currentDom; + /** @var string */ + protected $_defaultIndexedArrayItemName; + public function __construct() { $this->_dom = new DOMDocument('1.0'); @@ -61,7 +68,7 @@ class Mage_Xml_Generator $parentNode = $this->_getCurrentDom(); if(!$content || !count($content)) { return $this; - } + } foreach ($content as $_key=>$_item) { try{ $node = $this->getDom()->createElement($_key); @@ -94,7 +101,7 @@ class Mage_Xml_Generator $this->_setCurrentDom($node)->arrayToXml($_item); } elseif (is_array($_item) && isset($_item[0])) { foreach($_item as $k=>$v) { - $this->_setCurrentDom($node)->arrayToXml($v); + $this->_setCurrentDom($node)->arrayToXml(array($this->_getIndexedArrayItemName() => $v)); } } } @@ -112,4 +119,27 @@ class Mage_Xml_Generator return $this; } -} \ No newline at end of file + /** + * Set xml node name to use instead of numeric index during numeric arrays conversion. + * + * @param $name + * @return Mage_Xml_Generator + */ + public function setIndexedArrayItemName($name) + { + $this->_defaultIndexedArrayItemName = $name; + return $this; + } + + /** + * Get xml node name to use instead of numeric index during numeric arrays conversion. + * + * @return string + */ + protected function _getIndexedArrayItemName() + { + return isset($this->_defaultIndexedArrayItemName) + ? $this->_defaultIndexedArrayItemName + : self::DEFAULT_ENTITY_ITEM_NAME; + } +} diff --git a/lib/Magento/Acl/Config/ReaderInterface.php b/lib/Magento/Acl/Config/ReaderInterface.php index acea402968e9a60a12d7fa4891bbeaf2859e5eea..5232f1854e1ebf59a12655433540b031492bcde7 100644 --- a/lib/Magento/Acl/Config/ReaderInterface.php +++ b/lib/Magento/Acl/Config/ReaderInterface.php @@ -37,8 +37,9 @@ interface Magento_Acl_Config_ReaderInterface { /** * Retrieve ACL resources + * * @abstract * @return mixed */ - function getAclResources(); + public function getAclResources(); } diff --git a/lib/Magento/Acl/ResourceFactory.php b/lib/Magento/Acl/ResourceFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..308a7001c0d33f92720e4b9563787152aa86a2ba --- /dev/null +++ b/lib/Magento/Acl/ResourceFactory.php @@ -0,0 +1,53 @@ +<?php +/** + * Factory for Acl resource + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Magento_Acl_ResourceFactory +{ + const RESOURCE_CLASS_NAME = 'Magento_Acl_Resource'; + + /** + * @var Magento_ObjectManager + */ + protected $_objectManager; + + /** + * @param Magento_ObjectManager $objectManager + */ + public function __construct(Magento_ObjectManager $objectManager) + { + $this->_objectManager = $objectManager; + } + + /** + * Return new ACL resource model + * + * @param array $arguments + * @return Magento_Acl_Resource + */ + public function createResource(array $arguments = array()) + { + return $this->_objectManager->create(self::RESOURCE_CLASS_NAME, $arguments, false); + } +} diff --git a/lib/Magento/Acl/Role/Registry.php b/lib/Magento/Acl/Role/Registry.php index 55451ed868cd1d192ac719c44d621c7dad48885b..bd9d3c26cc3bf525155c8bb3a4b8cc99cba23580 100644 --- a/lib/Magento/Acl/Role/Registry.php +++ b/lib/Magento/Acl/Role/Registry.php @@ -38,7 +38,7 @@ class Magento_Acl_Role_Registry extends Zend_Acl_Role_Registry * @return Magento_Acl_Role_Registry * @throws Zend_Acl_Role_Registry_Exception */ - function addParent($role, $parents) + public function addParent($role, $parents) { try { if ($role instanceof Zend_Acl_Role_Interface) { diff --git a/lib/Magento/Autoload/IncludePath.php b/lib/Magento/Autoload/IncludePath.php index a5b9a5845ca37e063e572cb572d7a565c654a844..c0741e7f86bb2074b66d1f40bfaef716b25b4ad5 100644 --- a/lib/Magento/Autoload/IncludePath.php +++ b/lib/Magento/Autoload/IncludePath.php @@ -55,7 +55,7 @@ class Magento_Autoload_IncludePath $result = implode(PATH_SEPARATOR, (array)$path); $includePath = get_include_path(); if ($includePath) { - $result = $includePath . PATH_SEPARATOR . $result; + $result = $result . PATH_SEPARATOR . $includePath; } set_include_path($result); } diff --git a/lib/Magento/Config/Dom.php b/lib/Magento/Config/Dom.php index 4cb6640276ab42248a400f0b8daedd3bc9633c20..7938e80a2231a9a48e94576185667a775d2d6815 100644 --- a/lib/Magento/Config/Dom.php +++ b/lib/Magento/Config/Dom.php @@ -167,6 +167,7 @@ class Magento_Config_Dom { $dom = new DOMDocument(); $dom->loadXML($xml); + $rr = $dom->saveXML(); return $dom; } diff --git a/lib/Magento/Controller/Router/Route/Factory.php b/lib/Magento/Controller/Router/Route/Factory.php new file mode 100644 index 0000000000000000000000000000000000000000..69b4e69dfbf2f1c86a4742d8dc187f64b1611dac --- /dev/null +++ b/lib/Magento/Controller/Router/Route/Factory.php @@ -0,0 +1,55 @@ +<?php +/** + * Router route factory. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + */ +class Magento_Controller_Router_Route_Factory +{ + /** + * @var Magento_ObjectManager + */ + protected $_objectManager; + + /** + * @param Magento_ObjectManager $objectManager + */ + public function __construct(Magento_ObjectManager $objectManager) + { + $this->_objectManager = $objectManager; + } + + /** + * Create route instance. + * + * @param $routeClass + * @param string $route Map used to match with later submitted URL path + * @param array $defaults Defaults for map variables with keys as variable names + * @param array $reqs Regular expression requirements for variables (keys as variable names) + * @param mixed $locale + * @return Zend_Controller_Router_Route_Interface + * @throws LogicException If specified route class does not implement proper interface. + */ + public function createRoute( + $routeClass, + $route, + $defaults = array(), + $reqs = array(), + $locale = null + ) { + $route = $this->_objectManager->create( + $routeClass, + array( + 'route' => $route, + 'defaults' => $defaults, + 'regs' => $reqs, + 'locale' => $locale + ), + false + ); + if (!$route instanceof Zend_Controller_Router_Route_Interface) { + throw new LogicException('Route must implement "Zend_Controller_Router_Route_Interface".'); + } + return $route; + } +} diff --git a/lib/Magento/DomDocument/Factory.php b/lib/Magento/DomDocument/Factory.php new file mode 100644 index 0000000000000000000000000000000000000000..d1b94e4aaf95a1eacd603910714eb7afe1102b23 --- /dev/null +++ b/lib/Magento/DomDocument/Factory.php @@ -0,0 +1,31 @@ +<?php +/** + * DOM document factory. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + */ +class Magento_DomDocument_Factory +{ + /** + * @var Magento_ObjectManager + */ + protected $_objectManager; + + /** + * @param Magento_ObjectManager $objectManager + */ + public function __construct(Magento_ObjectManager $objectManager) + { + $this->_objectManager = $objectManager; + } + + /** + * Create empty DOM document instance. + * + * @return DOMDocument + */ + public function createDomDocument() + { + return $this->_objectManager->create('DOMDocument', array(), false); + } +} diff --git a/lib/Magento/Profiler.php b/lib/Magento/Profiler.php index 7acb9cba6640cbe624b822027596e63c6645b702..ab1cc7769af618123ae4e54ca4a246e4cedfe8eb 100644 --- a/lib/Magento/Profiler.php +++ b/lib/Magento/Profiler.php @@ -1,5 +1,7 @@ <?php /** + * Static class that represents profiling tool + * * Magento * * NOTICE OF LICENSE @@ -18,15 +20,9 @@ * versions in the future. If you wish to customize Magento for your * needs please refer to http://www.magentocommerce.com for more information. * - * @category Magento - * @package Magento_Profiler * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ - -/** - * Static class that represents profiling tool - */ class Magento_Profiler { /** @@ -35,61 +31,120 @@ class Magento_Profiler const NESTING_SEPARATOR = '->'; /** - * FETCH_* constants represent keys to retrieve profiling results + * Whether profiling is active or not + * + * @var bool */ - const FETCH_TIME = 'sum'; - const FETCH_COUNT = 'count'; - const FETCH_AVG = 'avg'; - const FETCH_REALMEM = 'realmem'; - const FETCH_EMALLOC = 'emalloc'; + static private $_enabled = false; /** - * Storage for timers statistics + * Nesting path that represents namespace to resolve timer names * * @var array */ - static private $_timers = array(); + static private $_currentPath = array(); /** - * Whether profiling is active or not + * Count of elements in $_currentPath * - * @var bool + * @var int */ - static private $_enabled = false; + static private $_pathCount = 0; /** - * Nesting path that represents namespace to resolve timer names + * Index for counting of $_pathCount for timer names * * @var array */ - static private $_currentPath = array(); + static private $_pathIndex = array(); /** - * Collection of profiler outputs + * Collection for profiler drivers. * * @var array */ - static private $_outputs = array(); + static private $_drivers = array(); /** - * Whether an initialization is done or not + * List of default tags. * - * @var bool + * @var array */ - static protected $_isInitialized = false; + static private $_defaultTags = array(); /** - * Supported timer statistics keys + * Collection of tag filters. * * @var array */ - private static $_supportedFetchKeys = array( - self::FETCH_TIME, - self::FETCH_AVG, - self::FETCH_COUNT, - self::FETCH_EMALLOC, - self::FETCH_REALMEM, - ); + static private $_tagFilters = array(); + + /** + * Has tag filters flag to faster checks of filters availability. + * + * @var bool + */ + static private $_hasTagFilters = false; + + /** + * Set default tags + * + * @param array $tags + */ + public static function setDefaultTags(array $tags) + { + self::$_defaultTags = $tags; + } + + /** + * Add tag filter. + * + * @param string $tagName + * @param string $tagValue + */ + public static function addTagFilter($tagName, $tagValue) + { + if (!isset(self::$_tagFilters[$tagName])) { + self::$_tagFilters[$tagName] = array(); + } + self::$_tagFilters[$tagName][] = $tagValue; + self::$_hasTagFilters = true; + } + + /** + * Check tags with tag filters. + * + * @param array|null $tags + * @return bool + */ + private static function _checkTags(array $tags = null) + { + if (self::$_hasTagFilters) { + if (is_array($tags)) { + $keysToCheck = array_intersect(array_keys(self::$_tagFilters), array_keys($tags)); + if ($keysToCheck) { + foreach ($keysToCheck as $keyToCheck) { + if (in_array($tags[$keyToCheck], self::$_tagFilters[$keyToCheck])) { + return true; + } + } + } + } + return false; + } + return true; + } + + /** + * Add profiler driver. + * + * @param Magento_Profiler_DriverInterface $driver + */ + public static function add(Magento_Profiler_DriverInterface $driver) + { + self::$_drivers[get_class($driver)] = $driver; + self::enable(); + } /** * Retrieve unique identifier among all timers @@ -99,36 +154,43 @@ class Magento_Profiler */ private static function _getTimerId($timerName = null) { - $currentPath = self::$_currentPath; - if ($timerName) { - $currentPath[] = $timerName; + if (!self::$_currentPath) { + return (string)$timerName; + } elseif ($timerName) { + return implode(self::NESTING_SEPARATOR, self::$_currentPath) . self::NESTING_SEPARATOR . $timerName; + } else { + return implode(self::NESTING_SEPARATOR, self::$_currentPath); } - return implode(self::NESTING_SEPARATOR, $currentPath); } /** - * Initialize the profiler before the first enabling + * Get tags list. + * + * @param array|null $tags + * @return array|null */ - protected static function _initialize() + private static function _getTags(array $tags = null) { - register_shutdown_function(array(__CLASS__, 'display')); + if (self::$_defaultTags) { + return (array)$tags + self::$_defaultTags; + } else { + return $tags; + } } /** * Enable profiling. + * * Any call to profiler does nothing until profiler is enabled. */ public static function enable() { - if (!self::$_isInitialized) { - static::_initialize(); - self::$_isInitialized = true; - } self::$_enabled = true; } /** * Disable profiling. + * * Any call to profiler is silently ignored while profiler is disabled. */ public static function disable() @@ -137,168 +199,122 @@ class Magento_Profiler } /** - * Reset collected statistics for specified timer or for whole profiler if timer name is omitted + * Get profiler enable status. * - * @param string|null $timerId + * @return bool */ - public static function reset($timerId = null) + public static function isEnabled() { - if ($timerId === null) { - self::$_timers = array(); - self::$_currentPath = array(); - return; + return self::$_enabled; + } + + /** + * Clear collected statistics for specified timer or for whole profiler if timer id is omitted + * + * @param string|null $timerName + * @throws InvalidArgumentException + */ + public static function clear($timerName = null) + { + if (strpos($timerName, self::NESTING_SEPARATOR) !== false) { + throw new InvalidArgumentException('Timer name must not contain a nesting separator.'); + } + $timerId = self::_getTimerId($timerName); + /** @var Magento_Profiler_DriverInterface $driver */ + foreach (self::$_drivers as $driver) { + $driver->clear($timerId); } - self::$_timers[$timerId] = array( - 'start' => false, - self::FETCH_TIME => 0, - self::FETCH_COUNT => 0, - self::FETCH_REALMEM => 0, - self::FETCH_EMALLOC => 0, - ); + } + + /** + * Reset profiler to initial state + */ + public static function reset() + { + self::clear(); + self::$_enabled = false; + self::$_currentPath = array(); + self::$_tagFilters = array(); + self::$_defaultTags = array(); + self::$_hasTagFilters = false; + self::$_drivers = array(); + self::$_pathCount = 0; + self::$_pathIndex = array(); } /** * Start collecting statistics for specified timer * * @param string $timerName - * @throws Varien_Exception + * @param array|null $tags + * @throws InvalidArgumentException */ - public static function start($timerName) + public static function start($timerName, array $tags = null) { if (!self::$_enabled) { return; } + $tags = self::_getTags($tags); + if (!self::_checkTags($tags)) { + return; + } + if (strpos($timerName, self::NESTING_SEPARATOR) !== false) { - throw new Varien_Exception('Timer name must not contain a nesting separator.'); + throw new InvalidArgumentException('Timer name must not contain a nesting separator.'); } $timerId = self::_getTimerId($timerName); - - /* - * Timer can be already initialized, for example: - * self::start('timer'); // <- initialization - * self::stop('timer'); - * self::start('timer'); // <- already initialized - * self::stop('timer'); - */ - if (empty(self::$_timers[$timerId])) { - self::reset($timerId); + /** @var Magento_Profiler_DriverInterface $driver */ + foreach (self::$_drivers as $driver) { + $driver->start($timerId, $tags); } - /* Continue collecting timers statistics under the latest started one */ self::$_currentPath[] = $timerName; - - self::$_timers[$timerId]['realmem_start'] = memory_get_usage(true); - self::$_timers[$timerId]['emalloc_start'] = memory_get_usage(); - self::$_timers[$timerId]['start'] = microtime(true); - self::$_timers[$timerId][self::FETCH_COUNT]++; + self::$_pathCount++; + self::$_pathIndex[$timerName][] = self::$_pathCount; } /** * Stop recording statistics for specified timer. + * * Call with no arguments to stop the recently started timer. * Only the latest started timer can be stopped. * - * @param string|null $timerName - * @throws Varien_Exception + * @param string|null $timerName + * @throws InvalidArgumentException */ public static function stop($timerName = null) { - if (!self::$_enabled) { + if (!self::$_enabled || !self::_checkTags(self::_getTags())) { return; } - /* Get current time as quick as possible to make more accurate calculations */ - $time = microtime(true); - - $latestTimerName = end(self::$_currentPath); - if ($timerName !== null && $timerName !== $latestTimerName) { - if (in_array($timerName, self::$_currentPath)) { - $exceptionMsg = sprintf('Timer "%s" should be stopped before "%s".', $latestTimerName, $timerName); + if ($timerName === null) { + $timersToStop = 1; + } else { + $timerPosition = false; + if (!empty(self::$_pathIndex[$timerName])) { + $timerPosition = array_pop(self::$_pathIndex[$timerName]); + } + if ($timerPosition === false) { + throw new InvalidArgumentException(sprintf('Timer "%s" has not been started.', $timerName)); + } elseif ($timerPosition === 1) { + $timersToStop = 1; } else { - $exceptionMsg = sprintf('Timer "%s" has not been started.', $timerName); + $timersToStop = self::$_pathCount + 1 - $timerPosition; } - throw new Varien_Exception($exceptionMsg); } - $timerId = self::_getTimerId(); - - self::$_timers[$timerId][self::FETCH_TIME] += ($time - self::$_timers[$timerId]['start']); - self::$_timers[$timerId]['start'] = false; - self::$_timers[$timerId][self::FETCH_REALMEM] += memory_get_usage(true); - self::$_timers[$timerId][self::FETCH_REALMEM] -= self::$_timers[$timerId]['realmem_start']; - self::$_timers[$timerId][self::FETCH_EMALLOC] += memory_get_usage(); - self::$_timers[$timerId][self::FETCH_EMALLOC] -= self::$_timers[$timerId]['emalloc_start']; - - /* Move one level up in timers nesting tree */ - array_pop(self::$_currentPath); - } - - /** - * Retrieve statistics on specified timer - * - * @param string $timerId - * @param string $key Information to return - * @return int|float - * @throws Varien_Exception - */ - public static function fetch($timerId, $key = self::FETCH_TIME) - { - if (empty(self::$_timers[$timerId])) { - throw new Varien_Exception(sprintf('Timer "%s" does not exist.', $timerId)); - } - if (!in_array($key, self::$_supportedFetchKeys)) { - throw new Varien_Exception(sprintf('Requested key "%s" is not supported.', $key)); - } - /* FETCH_AVG = FETCH_TIME / FETCH_COUNT */ - $isAvg = ($key == self::FETCH_AVG); - if ($isAvg) { - $key = self::FETCH_TIME; - } - $result = self::$_timers[$timerId][$key]; - if ($key == self::FETCH_TIME && self::$_timers[$timerId]['start'] !== false) { - $result += (microtime(true) - self::$_timers[$timerId]['start']); - } - if ($isAvg) { - $count = self::$_timers[$timerId][self::FETCH_COUNT]; - $result = ($count ? $result / $count : 0); - } - return $result; - } - - /** - * Retrieve the list of unique timer identifiers - * - * @return array - */ - public static function getTimers() - { - return array_keys(self::$_timers); - } - - /** - * Register profiler output instance to display profiling result at the end of execution - * - * @param Magento_Profiler_OutputAbstract $output - */ - public static function registerOutput(Magento_Profiler_OutputAbstract $output) - { - self::enable(); - self::$_outputs[] = $output; - } - - /** - * Display collected statistics with registered outputs - */ - public static function display() - { - if (!self::$_enabled) { - return; - } - /** @var $output Magento_Profiler_OutputAbstract */ - foreach (self::$_outputs as $output) { - $output->display(); + for ($i = 0; $i < $timersToStop; $i++) { + $timerId = self::_getTimerId(); + /** @var Magento_Profiler_DriverInterface $driver */ + foreach (self::$_drivers as $driver) { + $driver->stop($timerId); + } + /* Move one level up in timers nesting tree */ + array_pop(self::$_currentPath); + self::$_pathCount--; } } } diff --git a/lib/Magento/Profiler/Driver/Standard.php b/lib/Magento/Profiler/Driver/Standard.php new file mode 100644 index 0000000000000000000000000000000000000000..8aad62a2c071c068a875ddab6b0000eecabb5d34 --- /dev/null +++ b/lib/Magento/Profiler/Driver/Standard.php @@ -0,0 +1,110 @@ +<?php +/** + * Standard profiler driver that uses outputs for displaying profiling results. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Magento_Profiler_Driver_Standard implements Magento_Profiler_DriverInterface +{ + /** + * Storage for timers statistics + * + * @var Magento_Profiler_Driver_Standard_Stat + */ + protected $_stat; + + /** + * List of profiler driver outputs + * + * @var Magento_Profiler_Driver_Standard_OutputInterface[] + */ + protected $_outputs = array(); + + /** + * Constructor + * + * @param Magento_Profiler_Driver_Standard_Stat|null $stat + */ + public function __construct(Magento_Profiler_Driver_Standard_Stat $stat = null) + { + if (!$stat) { + $stat = new Magento_Profiler_Driver_Standard_Stat(); + } + $this->_stat = $stat; + register_shutdown_function(array($this, 'display')); + } + + /** + * Clear collected statistics for specified timer or for whole profiler if timer id is omitted + * + * @param string|null $timerId + */ + public function clear($timerId = null) + { + $this->_stat->clear($timerId); + } + + /** + * Start collecting statistics for specified timer + * + * @param string $timerId + * @param array|null $tags + * @return void + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function start($timerId, array $tags = null) + { + $this->_stat->start($timerId, microtime(true), memory_get_usage(true), memory_get_usage()); + } + + /** + * Stop recording statistics for specified timer. + * + * @param string $timerId + */ + public function stop($timerId) + { + $this->_stat->stop($timerId, microtime(true), memory_get_usage(true), memory_get_usage()); + } + + /** + * Register profiler output instance to display profiling result at the end of execution + * + * @param Magento_Profiler_Driver_Standard_OutputInterface $output + */ + public function registerOutput(Magento_Profiler_Driver_Standard_OutputInterface $output) + { + $this->_outputs[] = $output; + } + + /** + * Display collected statistics with registered outputs + */ + public function display() + { + if (Magento_Profiler::isEnabled()) { + foreach ($this->_outputs as $output) { + $output->display($this->_stat); + } + } + } +} diff --git a/lib/Magento/Profiler/Output/Csvfile.php b/lib/Magento/Profiler/Driver/Standard/Output/Csvfile.php similarity index 58% rename from lib/Magento/Profiler/Output/Csvfile.php rename to lib/Magento/Profiler/Driver/Standard/Output/Csvfile.php index b66e4513e94fa63a5ac05d9280bf961bc7c1cb36..81041a56ccbd5c4c584c9a0892faefe3c769a562 100644 --- a/lib/Magento/Profiler/Output/Csvfile.php +++ b/lib/Magento/Profiler/Driver/Standard/Output/Csvfile.php @@ -1,5 +1,7 @@ <?php /** + * Class that represents profiler output in CSV-file format + * * Magento * * NOTICE OF LICENSE @@ -18,18 +20,13 @@ * versions in the future. If you wish to customize Magento for your * needs please refer to http://www.magentocommerce.com for more information. * - * @category Magento - * @package Magento_Profiler * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ - -/** - * Class that represents profiler output in Html format - */ -class Magento_Profiler_Output_Csvfile extends Magento_Profiler_OutputAbstract +class Magento_Profiler_Driver_Standard_Output_Csvfile extends Magento_Profiler_Driver_Standard_OutputAbstract { /** + * * @var string */ protected $_filename; @@ -45,40 +42,38 @@ class Magento_Profiler_Output_Csvfile extends Magento_Profiler_OutputAbstract protected $_enclosure; /** - * Start output buffering + * Constructor * - * @param string $filename Target file to save CSV data - * @param string|null $filter Pattern to filter timers by their identifiers (SQL LIKE syntax) - * @param string $delimiter Delimiter for CSV format - * @param string $enclosure Enclosure for CSV format + * @param string $filename Target file to save CSV data + * @param string $delimiter Delimiter for CSV format + * @param string $enclosure Enclosure for CSV format */ - public function __construct($filename, $filter = null, $delimiter = ',', $enclosure = '"') + public function __construct($filename, $delimiter = ',', $enclosure = '"') { - parent::__construct($filter); - $this->_filename = $filename; $this->_delimiter = $delimiter; $this->_enclosure = $enclosure; } /** - * Display profiling results + * Write profiling results to CSV-file + * + * @param Magento_Profiler_Driver_Standard_Stat $stat + * @throws RuntimeException if output file cannot be opened */ - public function display() + public function display(Magento_Profiler_Driver_Standard_Stat $stat) { $fileHandle = fopen($this->_filename, 'w'); if (!$fileHandle) { - throw new Varien_Exception(sprintf('Can not open a file "%s".', $this->_filename)); + throw new RuntimeException(sprintf('Can not open a file "%s".', $this->_filename)); } - $needLock = (strpos($this->_filename, 'php://') !== 0); + $lockRequired = (strpos($this->_filename, 'php://') !== 0); $isLocked = false; - while ($needLock && !$isLocked) { + while ($lockRequired && !$isLocked) { $isLocked = flock($fileHandle, LOCK_EX); } - - $this->_writeFileContent($fileHandle); - + $this->_writeFileContent($fileHandle, $stat); if ($isLocked) { flock($fileHandle, LOCK_UN); } @@ -89,13 +84,14 @@ class Magento_Profiler_Output_Csvfile extends Magento_Profiler_OutputAbstract * Write content into an opened file handle * * @param resource $fileHandle + * @param Magento_Profiler_Driver_Standard_Stat $stat */ - protected function _writeFileContent($fileHandle) + protected function _writeFileContent($fileHandle, Magento_Profiler_Driver_Standard_Stat $stat) { - foreach ($this->_getTimers() as $timerId) { + foreach ($this->_getTimerIds($stat) as $timerName) { $row = array(); - foreach ($this->_getColumns() as $columnId) { - $row[] = $this->_renderColumnValue($timerId, $columnId); + foreach ($this->_columns as $column) { + $row[] = $this->_renderColumnValue($stat->fetch($timerName, $column), $column); } fputcsv($fileHandle, $row, $this->_delimiter, $this->_enclosure); } diff --git a/lib/Magento/Profiler/Output/Firebug.php b/lib/Magento/Profiler/Driver/Standard/Output/Firebug.php similarity index 77% rename from lib/Magento/Profiler/Output/Firebug.php rename to lib/Magento/Profiler/Driver/Standard/Output/Firebug.php index b2980016ecd3061f87d080772b05ff4428affc21..aef5952b582aa2170321fcf43de73d7d2aa68b88 100644 --- a/lib/Magento/Profiler/Output/Firebug.php +++ b/lib/Magento/Profiler/Driver/Standard/Output/Firebug.php @@ -1,5 +1,7 @@ <?php /** + * Class that uses Firebug for output profiling results + * * Magento * * NOTICE OF LICENSE @@ -18,75 +20,48 @@ * versions in the future. If you wish to customize Magento for your * needs please refer to http://www.magentocommerce.com for more information. * - * @category Magento - * @package Magento_Profiler * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ - -/** - * Class that outputs profiling results to Firebug - */ -class Magento_Profiler_Output_Firebug extends Magento_Profiler_OutputAbstract +class Magento_Profiler_Driver_Standard_Output_Firebug extends Magento_Profiler_Driver_Standard_OutputAbstract { /** * @var Zend_Controller_Request_Abstract */ - private $_request; + protected $_request; /** * @var Zend_Controller_Response_Abstract */ - private $_response; + protected $_response; /** * Start output buffering - * - * @param string|null $filter Pattern to filter timers by their identifiers (SQL LIKE syntax) */ - public function __construct($filter = null) + public function __construct() { - parent::__construct($filter); ob_start(); } - /** - * Request setter - * - * @param Zend_Controller_Request_Abstract $request - */ - public function setRequest(Zend_Controller_Request_Abstract $request) - { - $this->_request = $request; - } - - /** - * Response setter - * - * @param Zend_Controller_Response_Abstract $response - */ - public function setResponse(Zend_Controller_Response_Abstract $response) - { - $this->_response = $response; - } - /** * Display profiling results and flush output buffer + * + * @param Magento_Profiler_Driver_Standard_Stat $stat */ - public function display() + public function display(Magento_Profiler_Driver_Standard_Stat $stat) { $firebugMessage = new Zend_Wildfire_Plugin_FirePhp_TableMessage($this->_renderCaption()); - $firebugMessage->setHeader(array_keys($this->_getColumns())); + $firebugMessage->setHeader(array_keys($this->_columns)); - foreach ($this->_getTimers() as $timerId) { + foreach ($this->_getTimerIds($stat) as $timerId) { $row = array(); - foreach ($this->_getColumns() as $columnId) { - $row[] = $this->_renderColumnValue($timerId, $columnId); + foreach ($this->_columns as $column) { + $row[] = $this->_renderColumnValue($stat->fetch($timerId, $column), $column); } $firebugMessage->addRow($row); } - Zend_Wildfire_Plugin_FirePhp::getInstance()->send($firebugMessage); + Zend_Wildfire_Plugin_FirePhp::send($firebugMessage); // setup the wildfire channel $firebugChannel = Zend_Wildfire_Channel_HttpHeaders::getInstance(); @@ -113,4 +88,24 @@ class Magento_Profiler_Output_Firebug extends Magento_Profiler_OutputAbstract $nestingSep = preg_quote(Magento_Profiler::NESTING_SEPARATOR, '/'); return preg_replace('/.+?' . $nestingSep . '/', '. ', $timerId); } + + /** + * Request setter + * + * @param Zend_Controller_Request_Abstract $request + */ + public function setRequest(Zend_Controller_Request_Abstract $request) + { + $this->_request = $request; + } + + /** + * Response setter + * + * @param Zend_Controller_Response_Abstract $response + */ + public function setResponse(Zend_Controller_Response_Abstract $response) + { + $this->_response = $response; + } } diff --git a/lib/Magento/Profiler/Output/Html.php b/lib/Magento/Profiler/Driver/Standard/Output/Html.php similarity index 73% rename from lib/Magento/Profiler/Output/Html.php rename to lib/Magento/Profiler/Driver/Standard/Output/Html.php index 0d9c8a680fbcc0d050dd26b23e0c7a052e8190dc..681765856e5c5575334f48544cc8f7d50879e3c9 100644 --- a/lib/Magento/Profiler/Output/Html.php +++ b/lib/Magento/Profiler/Driver/Standard/Output/Html.php @@ -1,5 +1,7 @@ <?php /** + * Class that represents profiler output in HTML format + * * Magento * * NOTICE OF LICENSE @@ -18,34 +20,32 @@ * versions in the future. If you wish to customize Magento for your * needs please refer to http://www.magentocommerce.com for more information. * - * @category Magento - * @package Magento_Profiler * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ - -/** - * Class that represents profiler output in Html format - */ -class Magento_Profiler_Output_Html extends Magento_Profiler_OutputAbstract +class Magento_Profiler_Driver_Standard_Output_Html extends Magento_Profiler_Driver_Standard_OutputAbstract { /** * Display profiling results + * + * @param Magento_Profiler_Driver_Standard_Stat $stat */ - public function display() + public function display(Magento_Profiler_Driver_Standard_Stat $stat) { $out = array(); $out[] = '<table border="1" cellspacing="0" cellpadding="2">'; $out[] = '<caption>' . $this->_renderCaption() . '</caption>'; $out[] = '<tr>'; - foreach (array_keys($this->_getColumns()) as $columnLabel) { + foreach (array_keys($this->_columns) as $columnLabel) { $out[] = '<th>' . $columnLabel . '</th>'; } $out[] = '</tr>'; - foreach ($this->_getTimers() as $timerId) { + foreach ($this->_getTimerIds($stat) as $timerId) { $out[] = '<tr>'; - foreach ($this->_getColumns() as $columnId) { - $out[] = '<td title="' . $timerId . '">' . $this->_renderColumnValue($timerId, $columnId) . '</td>'; + foreach ($this->_columns as $column) { + $out[] = '<td title="' . $timerId . '">' + . $this->_renderColumnValue($stat->fetch($timerId, $column), $column) + . '</td>'; } $out[] = '</tr>'; } diff --git a/lib/Magento/Profiler/Driver/Standard/OutputAbstract.php b/lib/Magento/Profiler/Driver/Standard/OutputAbstract.php new file mode 100644 index 0000000000000000000000000000000000000000..c6d9d9bb97c24c18cde1e3274ff0e74af6b7a3bf --- /dev/null +++ b/lib/Magento/Profiler/Driver/Standard/OutputAbstract.php @@ -0,0 +1,148 @@ +<?php +/** + * Abstract class that represents profiler standard driver output + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +abstract class Magento_Profiler_Driver_Standard_OutputAbstract + implements Magento_Profiler_Driver_Standard_OutputInterface +{ + /** + * PCRE Regular Expression for filter timer by id + * + * @var null|string + */ + protected $_filterPattern; + + /** + * List of threshold (minimal allowed) values for profiler data + * + * @var array + */ + protected $_thresholds = array( + Magento_Profiler_Driver_Standard_Stat::TIME => 0.001, + Magento_Profiler_Driver_Standard_Stat::COUNT => 10, + Magento_Profiler_Driver_Standard_Stat::EMALLOC => 10000, + ); + + /** + * List of columns to output + * + * @var array + */ + protected $_columns = array( + 'Timer Id' => Magento_Profiler_Driver_Standard_Stat::ID, + 'Time' => Magento_Profiler_Driver_Standard_Stat::TIME, + 'Avg' => Magento_Profiler_Driver_Standard_Stat::AVG, + 'Cnt' => Magento_Profiler_Driver_Standard_Stat::COUNT, + 'Emalloc' => Magento_Profiler_Driver_Standard_Stat::EMALLOC, + 'RealMem' => Magento_Profiler_Driver_Standard_Stat::REALMEM, + ); + + /** + * Set profiler output with timer identifiers filter. + * + * @param string $filterPattern PCRE pattern to filter timers by their identifiers + */ + public function setFilterPattern($filterPattern) + { + $this->_filterPattern = $filterPattern; + } + + /** + * Set threshold (minimal allowed) value for timer column. + * + * Timer is being rendered if at least one of its columns is not less than the minimal allowed value. + * + * @param string $fetchKey + * @param int|float|null $minAllowedValue + */ + public function setThreshold($fetchKey, $minAllowedValue) + { + if ($minAllowedValue === null) { + unset($this->_thresholds[$fetchKey]); + } else { + $this->_thresholds[$fetchKey] = $minAllowedValue; + } + } + + /** + * Render statistics column value for specified timer + * + * @param mixed $value + * @param string $columnKey + * @return string + */ + protected function _renderColumnValue($value, $columnKey) + { + switch ($columnKey) { + case Magento_Profiler_Driver_Standard_Stat::ID: + $result = $this->_renderTimerId($value); + break; + case Magento_Profiler_Driver_Standard_Stat::TIME: + case Magento_Profiler_Driver_Standard_Stat::AVG: + $result = number_format($value, 6); + break; + default: + $result = number_format((string)$value); + } + return $result; + } + + /** + * Render timer id + * + * @param string $timerId + * @return string + */ + protected function _renderTimerId($timerId) + { + return $timerId; + } + + /** + * Render a caption for the profiling results + * + * @return string + */ + protected function _renderCaption() + { + return sprintf( + 'Code Profiler (Memory usage: real - %s, emalloc - %s)', + memory_get_usage(true), + memory_get_usage() + ); + } + + /** + * Retrieve the list of timer ids from timer statistics object. + * + * Timer ids will be ordered and filtered by thresholds and filter pattern. + * + * @param Magento_Profiler_Driver_Standard_Stat $stat + * @return array + */ + protected function _getTimerIds(Magento_Profiler_Driver_Standard_Stat $stat) + { + return $stat->getFilteredTimerIds($this->_thresholds, $this->_filterPattern); + } +} diff --git a/lib/Magento/Profiler/Driver/Standard/OutputInterface.php b/lib/Magento/Profiler/Driver/Standard/OutputInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..a1bed70db45b12e4616d0c65f00019ce02232925 --- /dev/null +++ b/lib/Magento/Profiler/Driver/Standard/OutputInterface.php @@ -0,0 +1,34 @@ +<?php +/** + * Interface for output class of standard profiler driver. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +interface Magento_Profiler_Driver_Standard_OutputInterface +{ + /** + * Display profiling results in appropriate format + * + * @param Magento_Profiler_Driver_Standard_Stat $stat + */ + public function display(Magento_Profiler_Driver_Standard_Stat $stat); +} diff --git a/lib/Magento/Profiler/Driver/Standard/Stat.php b/lib/Magento/Profiler/Driver/Standard/Stat.php new file mode 100644 index 0000000000000000000000000000000000000000..03df13a7c365bf3001028b8e8e2daead200be847 --- /dev/null +++ b/lib/Magento/Profiler/Driver/Standard/Stat.php @@ -0,0 +1,249 @@ +<?php +/** + * Storage for timers statistics + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Magento_Profiler_Driver_Standard_Stat +{ + /** + * #@+ Timer statistics data keys + */ + const ID = 'id'; + const START = 'start'; + const TIME = 'sum'; + const COUNT = 'count'; + const AVG = 'avg'; + const REALMEM = 'realmem'; + const REALMEM_START = 'realmem_start'; + const EMALLOC = 'emalloc'; + const EMALLOC_START = 'emalloc_start'; + /**#@-*/ + + /** + * Array of timers statistics data + * + * @var array + */ + protected $_timers = array(); + + /** + * Starts timer + * + * @param string $timerId + * @param int $time + * @param int $realMemory Real size of memory allocated from system + * @param int $emallocMemory Memory used by emalloc() + */ + public function start($timerId, $time, $realMemory, $emallocMemory) + { + if (empty($this->_timers[$timerId])) { + $this->_timers[$timerId] = array( + self::START => false, + self::TIME => 0, + self::COUNT => 0, + self::REALMEM => 0, + self::EMALLOC => 0, + ); + } + + $this->_timers[$timerId][self::REALMEM_START] = $realMemory; + $this->_timers[$timerId][self::EMALLOC_START] = $emallocMemory; + $this->_timers[$timerId][self::START] = $time; + $this->_timers[$timerId][self::COUNT]++; + } + + /** + * Stops timer + * + * @param string $timerId + * @param int $time + * @param int $realMemory Real size of memory allocated from system + * @param int $emallocMemory Memory used by emalloc() + * @throws InvalidArgumentException if timer doesn't exist + */ + public function stop($timerId, $time, $realMemory, $emallocMemory) + { + if (empty($this->_timers[$timerId])) { + throw new InvalidArgumentException(sprintf('Timer "%s" doesn\'t exist.', $timerId)); + } + + $this->_timers[$timerId][self::TIME] += ($time - $this->_timers[$timerId]['start']); + $this->_timers[$timerId][self::START] = false; + $this->_timers[$timerId][self::REALMEM] += $realMemory; + $this->_timers[$timerId][self::REALMEM] -= $this->_timers[$timerId][self::REALMEM_START]; + $this->_timers[$timerId][self::EMALLOC] += $emallocMemory; + $this->_timers[$timerId][self::EMALLOC] -= $this->_timers[$timerId][self::EMALLOC_START]; + } + + /** + * Get timer statistics data by timer id + * + * @param string $timerId + * @return array + * @throws InvalidArgumentException if timer doesn't exist + */ + public function get($timerId) + { + if (empty($this->_timers[$timerId])) { + throw new InvalidArgumentException(sprintf('Timer "%s" doesn\'t exist.', $timerId)); + } + return $this->_timers[$timerId]; + } + + /** + * Retrieve statistics on specified timer + * + * @param $timerId + * @param string $key Information to return + * @return int|float + * @throws InvalidArgumentException + */ + public function fetch($timerId, $key) + { + if ($key === self::ID) { + return $timerId; + } + if (empty($this->_timers[$timerId])) { + throw new InvalidArgumentException(sprintf('Timer "%s" doesn\'t exist.', $timerId)); + } + /* AVG = TIME / COUNT */ + $isAvg = ($key == self::AVG); + if ($isAvg) { + $key = self::TIME; + } + if (!isset($this->_timers[$timerId][$key])) { + throw new InvalidArgumentException(sprintf('Timer "%s" doesn\'t have value for "%s".', $timerId, $key)); + } + $result = $this->_timers[$timerId][$key]; + if ($key == self::TIME && $this->_timers[$timerId][self::START] !== false) { + $result += (microtime(true) - $this->_timers[$timerId][self::START]); + } + if ($isAvg) { + $count = $this->_timers[$timerId][self::COUNT]; + if ($count) { + $result = $result / $count; + } + } + return $result; + } + + /** + * Clear collected statistics for specified timer or for all timers if timer id is omitted + * + * @param string|null $timerId + */ + public function clear($timerId = null) + { + if ($timerId) { + unset($this->_timers[$timerId]); + } else { + $this->_timers = array(); + } + } + + /** + * Get ordered list of timer ids filtered by thresholds and pcre pattern + * + * @param array|null $thresholds + * @param string|null $filterPattern + * @return array + */ + public function getFilteredTimerIds(array $thresholds = null, $filterPattern = null) + { + $timerIds = $this->_getOrderedTimerIds(); + if (!$thresholds && !$filterPattern) { + return $timerIds; + } + $thresholds = (array)$thresholds; + $result = array(); + foreach ($timerIds as $timerId) { + /* Filter by pattern */ + if ($filterPattern && !preg_match($filterPattern, $timerId)) { + continue; + } + /* Filter by thresholds */ + $match = true; + foreach ($thresholds as $fetchKey => $minMatchValue) { + $match = ($this->fetch($timerId, $fetchKey) >= $minMatchValue); + if ($match) { + break; + } + } + if ($match) { + $result[] = $timerId; + } + } + return $result; + } + + /** + * Get ordered list of timer ids + * + * @return array + */ + protected function _getOrderedTimerIds() + { + $timerIds = array_keys($this->_timers); + if (count($timerIds) <= 2) { + /* No sorting needed */ + return $timerIds; + } + + /* Prepare PCRE once to use it inside the loop body */ + $nestingSep = preg_quote(Magento_Profiler::NESTING_SEPARATOR, '/'); + $patternLastTimerId = '/' . $nestingSep . '(?:.(?!' . $nestingSep . '))+$/'; + + $prevTimerId = $timerIds[0]; + $result = array($prevTimerId); + for ($i = 1; $i < count($timerIds); $i++) { + $timerId = $timerIds[$i]; + /* Skip already added timer */ + if (!$timerId) { + continue; + } + /* Loop over all timers that need to be closed under previous timer */ + while (strpos($timerId, $prevTimerId . Magento_Profiler::NESTING_SEPARATOR) !== 0) { + /* Add to result all timers nested in the previous timer */ + for ($j = $i + 1; $j < count($timerIds); $j++) { + if (strpos($timerIds[$j], $prevTimerId . Magento_Profiler::NESTING_SEPARATOR) === 0) { + $result[] = $timerIds[$j]; + /* Mark timer as already added */ + $timerIds[$j] = null; + } + } + /* Go to upper level timer */ + $count = 0; + $prevTimerId = preg_replace($patternLastTimerId, '', $prevTimerId, -1, $count); + /* Break the loop if no replacements was done. It is possible when we are */ + /* working with top level (root) item */ + if (!$count) { + break; + } + } + /* Add current timer to the result */ + $result[] = $timerId; + $prevTimerId = $timerId; + } + return $result; + } +} diff --git a/lib/Magento/Profiler/DriverInterface.php b/lib/Magento/Profiler/DriverInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..a79fda8bb0cdd8765bbaaba446b9d452a4f61ef3 --- /dev/null +++ b/lib/Magento/Profiler/DriverInterface.php @@ -0,0 +1,51 @@ +<?php +/** + * Interface for profiler driver. + * + * Implementation of this interface is responsible for logic of profiling. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +interface Magento_Profiler_DriverInterface +{ + /** + * Start timer + * + * @param string $timerId + * @param array|null $tags + */ + public function start($timerId, array $tags = null); + + /** + * Stop timer + * + * @param string $timerId + */ + public function stop($timerId); + + /** + * Clear collected statistics for specified timer or for whole profiler if timer name is omitted. + * + * @param string|null $timerId + */ + public function clear($timerId = null); +} diff --git a/lib/Magento/Profiler/OutputAbstract.php b/lib/Magento/Profiler/OutputAbstract.php deleted file mode 100644 index 773b9600890c6653f564a269cec7a934652af439..0000000000000000000000000000000000000000 --- a/lib/Magento/Profiler/OutputAbstract.php +++ /dev/null @@ -1,222 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Magento - * @package Magento_Profiler - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Abstract class that represents profiler output - */ -abstract class Magento_Profiler_OutputAbstract -{ - /** - * PCRE Regular Expression for filter - * - * @var null|string - */ - private $_filter; - - /** - * List of threshold (minimal allowed) values for profiler data - * - * @var array - */ - private $_thresholds = array( - Magento_Profiler::FETCH_TIME => 0.001, - Magento_Profiler::FETCH_COUNT => 10, - Magento_Profiler::FETCH_EMALLOC => 10000, - ); - - /** - * Initialize profiler output with timer identifiers filter - * - * @param string|null $filter PCRE pattern to filter timers by their identifiers - */ - public function __construct($filter = null) - { - $this->_filter = $filter; - } - - /** - * Override in descendants to display profiling results in appropriate format - */ - abstract public function display(); - - /** - * Retrieve the list of (column_label; column_id) pairs - * - * @return array - */ - protected function _getColumns() - { - return array( - 'Timer Id' => 'timer_id', - 'Time' => Magento_Profiler::FETCH_TIME, - 'Avg' => Magento_Profiler::FETCH_AVG, - 'Cnt' => Magento_Profiler::FETCH_COUNT, - 'Emalloc' => Magento_Profiler::FETCH_EMALLOC, - 'RealMem' => Magento_Profiler::FETCH_REALMEM, - ); - } - - /** - * Render statistics column value for specified timer - * - * @param string $timerId - * @param string $columnId - */ - protected function _renderColumnValue($timerId, $columnId) - { - if ($columnId == 'timer_id') { - return $this->_renderTimerId($timerId); - } - $value = (string)Magento_Profiler::fetch($timerId, $columnId); - if (in_array($columnId, array(Magento_Profiler::FETCH_TIME, Magento_Profiler::FETCH_AVG))) { - $value = number_format($value, 6); - } else { - $value = number_format($value); - } - return $value; - } - - /** - * Render timer id column value - * - * @param string $timerId - * @return string - */ - protected function _renderTimerId($timerId) - { - return $timerId; - } - - /** - * Retrieve timer ids sorted to correspond the nesting - * - * @return array - */ - private function _getSortedTimers() - { - $timerIds = Magento_Profiler::getTimers(); - if (count($timerIds) <= 2) { - /* No sorting needed */ - return $timerIds; - } - - /* Prepare PCRE once to use it inside the loop body */ - $nestingSep = preg_quote(Magento_Profiler::NESTING_SEPARATOR, '/'); - $patternLastTimerName = '/' . $nestingSep . '(?:.(?!' . $nestingSep . '))+$/'; - - $prevTimerId = $timerIds[0]; - $result = array($prevTimerId); - for ($i = 1; $i < count($timerIds); $i++) { - $timerId = $timerIds[$i]; - /* Skip already added timer */ - if (!$timerId) { - continue; - } - /* Loop over all timers that need to be closed under previous timer */ - while (strpos($timerId, $prevTimerId . Magento_Profiler::NESTING_SEPARATOR) !== 0) { - /* Add to result all timers nested in the previous timer */ - for ($j = $i + 1; $j < count($timerIds); $j++) { - if (strpos($timerIds[$j], $prevTimerId . Magento_Profiler::NESTING_SEPARATOR) === 0) { - $result[] = $timerIds[$j]; - /* Mark timer as already added */ - $timerIds[$j] = null; - } - } - /* Go to upper level timer */ - $count = 0; - $prevTimerId = preg_replace($patternLastTimerName, '', $prevTimerId, -1, $count); - /* Break the loop if no replacements was done. It is possible when we are */ - /* working with top level (root) item */ - if (!$count) { - break; - } - } - /* Add current timer to the result */ - $result[] = $timerId; - $prevTimerId = $timerId; - } - return $result; - } - - /** - * Retrieve the list of timer Ids - * - * @return array - */ - protected function _getTimers() - { - $pattern = $this->_filter; - $timerIds = $this->_getSortedTimers(); - $result = array(); - foreach ($timerIds as $timerId) { - /* Filter by timer id pattern */ - if ($pattern && !preg_match($pattern, $timerId)) { - continue; - } - /* Filter by column value thresholds */ - $skip = false; - foreach ($this->_thresholds as $fetchKey => $minAllowedValue) { - $skip = (Magento_Profiler::fetch($timerId, $fetchKey) < $minAllowedValue); - /* First value not less than the allowed one forces to include timer to the result */ - if (!$skip) { - break; - } - } - if (!$skip) { - $result[] = $timerId; - } - } - return $result; - } - - /** - * Render a caption for the profiling results - * - * @return string - */ - protected function _renderCaption() - { - $result = 'Code Profiler (Memory usage: real - %s, emalloc - %s)'; - $result = sprintf($result, memory_get_usage(true), memory_get_usage()); - return $result; - } - - /** - * Set threshold (minimal allowed) value for timer column. - * Timer is being rendered if at least one of its columns is not less than the minimal allowed value. - * - * @param string $fetchKey - * @param int|float|null $minAllowedValue - */ - public function setThreshold($fetchKey, $minAllowedValue) - { - if ($minAllowedValue === null) { - unset($this->_thresholds[$fetchKey]); - } else { - $this->_thresholds[$fetchKey] = $minAllowedValue; - } - } -} diff --git a/lib/Magento/Translate/Adapter.php b/lib/Magento/Translate/Adapter.php new file mode 100644 index 0000000000000000000000000000000000000000..bd96498c56164d8d0d7a47b59fe23eada1c4f7dd --- /dev/null +++ b/lib/Magento/Translate/Adapter.php @@ -0,0 +1,67 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Framework + * @subpackage Translate + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Magento translate adapter + */ +class Magento_Translate_Adapter extends Magento_Translate_AdapterAbstract +{ + /** + * Translate message string. + * + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + * @param array|string $messageId + * @param null|string $locale + * @return string + */ + public function translate($messageId, $locale = null) + { + $translator = $this->getOptions('translator'); + if (is_callable($translator)) { + return call_user_func($translator, $messageId); + } else { + return $messageId; + } + } + + /** + * Translate message string. + * + * @SuppressWarnings(PHPMD.ShortMethodName) + * @return string + */ + public function __() + { + $args = func_get_args(); + $messageId = array_shift($args); + $string = $this->translate($messageId); + if (count($args) > 0) { + $string = vsprintf($string, $args); + } + return $string; + } +} diff --git a/lib/Magento/Translate/AdapterAbstract.php b/lib/Magento/Translate/AdapterAbstract.php new file mode 100644 index 0000000000000000000000000000000000000000..0c1eccf7b649219e0458bbff10c2835299f035b2 --- /dev/null +++ b/lib/Magento/Translate/AdapterAbstract.php @@ -0,0 +1,86 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Framework + * @subpackage Translate + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Magento translate abstract adapter + */ +abstract class Magento_Translate_AdapterAbstract extends Zend_Translate_Adapter + implements Magento_Translate_AdapterInterface +{ + /** + * Load translation data + * + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + * @param mixed $data + * @param string|Zend_Locale $locale + * @param array $options (optional) + * @return array + */ + protected function _loadTranslationData($data, $locale, array $options = array()) + { + return array(); + } + + /** + * Is translation available. + * + * Return false, as Zend_Validate pass message into translator only when isTranslated is false + * + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + * @param string $messageId + * @param boolean $original + * @param null $locale + * @return boolean + */ + public function isTranslated($messageId, $original = false, $locale = null) + { + return false; + } + + /** + * Stub for setLocale functionality + * + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + * @param string|Zend_Locale $locale + * @return Zend_Translate_Adapter + */ + public function setLocale($locale) + { + return $this; + } + + + /** + * Returns the adapter name + * + * @return string + */ + public function toString() + { + return 'Magento_Translate_Adapter'; + } +} diff --git a/lib/Magento/Translate/AdapterInterface.php b/lib/Magento/Translate/AdapterInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..053954aecf980fe27c04614c1520cb75e3c3a0c1 --- /dev/null +++ b/lib/Magento/Translate/AdapterInterface.php @@ -0,0 +1,49 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Framework + * @subpackage Translate + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Magento translate adapter interface + */ +interface Magento_Translate_AdapterInterface +{ + /** + * Translate string + * + * @param string|array $messageId + * @param null $locale + * @return string + */ + public function translate($messageId, $locale = null); + + /** + * Translate string + * + * @return string + * @SuppressWarnings(PHPMD.ShortMethodName) + */ + public function __(); +} diff --git a/lib/Magento/Validator.php b/lib/Magento/Validator.php index ae029ae1424eadf8079c2937070c1d99b0ebae6a..e0c1c8a33ea26abe838eab7ba2444a4ffc78a12f 100644 --- a/lib/Magento/Validator.php +++ b/lib/Magento/Validator.php @@ -25,90 +25,74 @@ */ /** - * Presentation layer validator class. + * Validator class that represents chain of validators. */ -class Magento_Validator +class Magento_Validator extends Magento_Validator_ValidatorAbstract { - /** @var string */ - protected $_entityName; - /** @var string */ - protected $_groupName; - /** @var Magento_Validator_Config */ - protected $_config; - /** @var array */ - protected $_messages = array(); + /** + * Validator chain + * + * @var array + */ + protected $_validators = array(); /** - * Set validation entity and group names, load validator config. + * Adds a validator to the end of the chain * - * @param string $entityName - * @param string $groupName - * @param Magento_Validator_Config $config - * @throws InvalidArgumentException + * @param Magento_Validator_ValidatorInterface $validator + * @param boolean $breakChainOnFailure + * @return Magento_Validator */ - public function __construct($entityName, $groupName, Magento_Validator_Config $config) + public function addValidator(Magento_Validator_ValidatorInterface $validator, $breakChainOnFailure = false) { - if (!$entityName) { - throw new InvalidArgumentException('Validation entity name is required.'); - } - $this->_entityName = $entityName; - - if (!$groupName) { - throw new InvalidArgumentException('Validation group name is required.'); + if (!$validator->hasTranslator()) { + $validator->setTranslator($this->getTranslator()); } - $this->_groupName = $groupName; - - $this->_config = $config; + $this->_validators[] = array( + 'instance' => $validator, + 'breakChainOnFailure' => (boolean)$breakChainOnFailure + ); + return $this; } /** - * Validate input data against validation rules, defined in config group. + * Returns true if and only if $value passes all validations in the chain * - * @param array $data - * @throws Magento_Exception - * @return bool + * @param mixed $value + * @return boolean */ - public function isValid(array $data) + public function isValid($value) { - $isValid = true; - $rules = $this->_config->getValidationRules($this->_entityName, $this->_groupName); - foreach ($rules as $rule) { - foreach ($rule as $constraintConfig) { - $constraint = $constraintConfig['constraint']; - $field = isset($constraintConfig['field']) ? $constraintConfig['field'] : null; - if ($constraint instanceof Zend_Validate_Interface) { - /** @var Zend_Validate_Interface $constraint */ - $value = isset($data[$field]) ? $data[$field] : null; - if (!$constraint->isValid($value)) { - foreach ($constraint->getMessages() as $error) { - $this->_messages[$field][] = $error; - } - $isValid = false; - } - } else { - /** @var Magento_Validator_ConstraintAbstract $constraint */ - if (!$constraint->isValidData($data, $field)) { - foreach ($constraint->getErrors() as $errorFieldName => $errors) { - foreach ($errors as $error) { - $this->_messages[$errorFieldName][] = $error; - } - } - $isValid = false; - } - } + $result = true; + $this->_clearMessages(); + + /** @var $validator Zend_Validate_Interface */ + foreach ($this->_validators as $element) { + $validator = $element['instance']; + if ($validator->isValid($value)) { + continue; + } + $result = false; + $this->_addMessages($validator->getMessages()); + if ($element['breakChainOnFailure']) { + break; } } - return $isValid; + return $result; } /** - * Get validation messages. + * Set translator to chain. * - * @return array + * @param Magento_Translate_AdapterInterface|null $translator + * @return Magento_Validator_ValidatorAbstract */ - public function getMessages() + public function setTranslator($translator = null) { - return $this->_messages; + foreach ($this->_validators as $validator) { + $validator['instance']->setTranslator($translator); + } + return parent::setTranslator($translator); } } diff --git a/lib/Magento/Validator/Alnum.php b/lib/Magento/Validator/Alnum.php new file mode 100644 index 0000000000000000000000000000000000000000..ca44a78765214f5262820f31620b7a356f9fccaf --- /dev/null +++ b/lib/Magento/Validator/Alnum.php @@ -0,0 +1,29 @@ +<?php +/** + * Alphanumerical validator + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Magento_Validator_Alnum extends Zend_Validate_Alnum implements Magento_Validator_ValidatorInterface +{ + +} diff --git a/lib/Magento/Validator/Builder.php b/lib/Magento/Validator/Builder.php new file mode 100644 index 0000000000000000000000000000000000000000..7c5fb18d2f20aa99feccb26e0b6749e43a664379 --- /dev/null +++ b/lib/Magento/Validator/Builder.php @@ -0,0 +1,325 @@ +<?php +/** + * Magento Validator Builder + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Magento_Validator_Builder +{ + /** + * @var array + */ + protected $_constraints; + + /** + * Set constraints + * + * @param array $constraints + */ + public function __construct(array $constraints) + { + foreach ($constraints as $constraint) { + if (array_key_exists('options', $constraint) && is_array($constraint['options'])) { + $this->_checkConfigurationArguments($constraint['options'], true); + $this->_checkConfigurationCallback($constraint['options'], true); + } + } + $this->_constraints = $constraints; + } + + /** + * Check configuration arguments + * + * @param array $configuration + * @param bool $argumentsIsArray + * @throws InvalidArgumentException + */ + protected function _checkConfigurationArguments(array $configuration, $argumentsIsArray) + { + $allowedKeys = array('arguments', 'callback', 'method', 'methods'); + if (!array_intersect($allowedKeys, array_keys($configuration))) { + throw new InvalidArgumentException('Configuration has incorrect format'); + } + // Check method arguments + if ($argumentsIsArray) { + if (array_key_exists('methods', $configuration)) { + foreach ($configuration['methods'] as $method) { + $this->_checkMethodArguments($method); + } + } + } elseif (array_key_exists('method', $configuration)) { + $this->_checkMethodArguments($configuration); + } + + // Check constructor arguments + if (array_key_exists('arguments', $configuration) && !is_array($configuration['arguments'])) { + throw new InvalidArgumentException('Arguments must be an array'); + } + } + + /** + * Check configuration method arguments + * + * @param array $configuration + * @throws InvalidArgumentException + */ + protected function _checkMethodArguments(array $configuration) + { + if (!is_string($configuration['method'])) { + throw new InvalidArgumentException('Method has to be passed as string'); + } + if (array_key_exists('arguments', $configuration) && !is_array($configuration['arguments'])) { + throw new InvalidArgumentException('Method arguments must be an array'); + } + } + + /** + * Check configuration callbacks + * + * @param array $configuration + * @param bool $callbackIsArray + * @throws InvalidArgumentException + */ + protected function _checkConfigurationCallback(array $configuration, $callbackIsArray) + { + if (array_key_exists('callback', $configuration)) { + if ($callbackIsArray) { + $callbacks = $configuration['callback']; + } else { + $callbacks = array($configuration['callback']); + } + foreach ($callbacks as $callback) { + if (!($callback instanceof Magento_Validator_Constraint_Option_Callback)) { + throw new InvalidArgumentException( + 'Callback must be instance of Magento_Validator_Constraint_Option_Callback'); + } + } + } + } + + /** + * Create validator instance and configure it + * + * @return Magento_Validator + */ + public function createValidator() + { + return $this->_createValidatorInstance(); + } + + /** + * Get validator instance + * + * @return Magento_Validator + */ + protected function _createValidatorInstance() + { + $validator = new Magento_Validator(); + foreach ($this->_constraints as $constraintData) { + $validator->addValidator($this->_createConstraint($constraintData)); + } + return $validator; + } + + /** + * Add constraint configuration + * + * @param string $alias + * @param array $configuration + * @throws InvalidArgumentException + * @return Magento_Validator_Builder + */ + public function addConfiguration($alias, array $configuration) + { + $this->_checkConfigurationArguments($configuration, false); + $this->_checkConfigurationCallback($configuration, false); + foreach ($this->_constraints as &$constraint) { + if ($constraint['alias'] != $alias) { + continue; + } + if (!array_key_exists('options', $constraint) || !is_array($constraint['options'])) { + $constraint['options'] = array(); + } + if (!array_key_exists('method', $configuration)) { + if (array_key_exists('arguments', $configuration)) { + $constraint['options']['arguments'] = $configuration['arguments']; + } elseif (array_key_exists('callback', $configuration)) { + $constraint = $this->_addConstraintCallback($constraint, $configuration['callback']); + } + } else { + $constraint = $this->_addConstraintMethod($constraint, $configuration); + } + } + + return $this; + } + + /** + * Add callback to constraint configuration + * + * @param array $constraint + * @param Magento_Validator_Constraint_Option_Callback $callback + * @return array + */ + protected function _addConstraintCallback(array $constraint, Magento_Validator_Constraint_Option_Callback $callback) + { + if (!array_key_exists('callback', $constraint['options'])) { + $constraint['options']['callback'] = array(); + } + $constraint['options']['callback'][] = $callback; + return $constraint; + } + + /** + * Add method to constraint configuration + * + * @param array $constraint + * @param array $configuration + * @return array + */ + protected function _addConstraintMethod(array $constraint, array $configuration) + { + if (!array_key_exists('methods', $constraint['options'])) { + $constraint['options']['methods'] = array(); + } + $constraint['options']['methods'][] = $configuration; + return $constraint; + } + + /** + * Add constraints configuration + * + * @param array $configurations + * @return Magento_Validator_Builder + */ + public function addConfigurations(array $configurations) + { + foreach ($configurations as $alias => $concreteConfigs) { + foreach ($concreteConfigs as $configuration) { + $this->addConfiguration($alias, $configuration); + } + } + return $this; + } + + /** + * Create constraint from data + * + * @param array $data + * @return Magento_Validator_Constraint + */ + protected function _createConstraint(array $data) + { + // Create validator instance + $validator = $this->_createConstraintValidator($data); + if (array_key_exists('options', $data) && is_array($data['options'])) { + $this->_configureConstraintValidator($validator, $data['options']); + } + + if (Magento_Validator_Config::CONSTRAINT_TYPE_PROPERTY == $data['type']) { + $result = new Magento_Validator_Constraint_Property($validator, $data['property'], $data['alias']); + } else { + $result = new Magento_Validator_Constraint($validator, $data['alias']); + } + + return $result; + } + + /** + * Create constraint validator instance + * + * @param array $data + * @throws InvalidArgumentException + * @return Magento_Validator_ValidatorInterface + */ + protected function _createConstraintValidator(array $data) + { + if (array_key_exists('options', $data) + && is_array($data['options']) && array_key_exists('arguments', $data['options']) + ) { + $arguments = $this->_applyArgumentsCallback($data['options']['arguments']); + $class = new ReflectionClass($data['class']); + $validator = $class->newInstanceArgs($arguments); + } else { + $validator = new $data['class']; + } + + // Check validator type + if (!($validator instanceof Magento_Validator_ValidatorInterface)) { + throw new InvalidArgumentException(sprintf( + 'Constraint class "%s" must implement Magento_Validator_ValidatorInterface', $data['class'] + )); + } + + return $validator; + } + + /** + * Configure validator + * + * @param Magento_Validator_ValidatorInterface $validator + * @param array $options + */ + protected function _configureConstraintValidator(Magento_Validator_ValidatorInterface $validator, array $options) + { + // Call all validator methods according to configuration + if (array_key_exists('methods', $options)) { + foreach ($options['methods'] as $methodData) { + $methodName = $methodData['method']; + if (method_exists($validator, $methodName)) { + if (array_key_exists('arguments', $methodData)) { + $arguments = $this->_applyArgumentsCallback($methodData['arguments']); + call_user_func_array(array($validator, $methodName), $arguments); + } else { + call_user_func(array($validator, $methodName)); + } + } + } + } + + // Call validator configurators if any + if (array_key_exists('callback', $options)) { + /** @var $callback Magento_Validator_Constraint_Option_Callback */ + foreach ($options['callback'] as $callback) { + $callback->setArguments($validator); + $callback->getValue(); + } + } + } + + /** + * Apply all argument callback + * + * @param array $arguments + * @return array + */ + protected function _applyArgumentsCallback(array $arguments) + { + foreach ($arguments as &$argument) { + if ($argument instanceof Magento_Validator_Constraint_OptionInterface) { + /** @var $argument Magento_Validator_Constraint_OptionInterface */ + $argument = $argument->getValue(); + } + } + return $arguments; + } +} diff --git a/lib/Magento/Validator/Config.php b/lib/Magento/Validator/Config.php index 77774c6cb8085775d79ee5bbe56b84b350fa9ddc..4dd9b21a73b2406d626431abc0fcf94ecc100790 100644 --- a/lib/Magento/Validator/Config.php +++ b/lib/Magento/Validator/Config.php @@ -1,5 +1,7 @@ <?php /** + * Validation configuration files handler + * * Magento * * NOTICE OF LICENSE @@ -18,116 +20,388 @@ * versions in the future. If you wish to customize Magento for your * needs please refer to http://www.magentocommerce.com for more information. * - * @category Magento - * @package Magento_Validator * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ - -/** - * Validation configuration files handler - */ class Magento_Validator_Config extends Magento_Config_XmlAbstract { + /**#@+ + * Constraints types + */ + const CONSTRAINT_TYPE_ENTITY = 'entity'; + const CONSTRAINT_TYPE_PROPERTY = 'property'; + /**#@-*/ + /** - * Get absolute path to validation.xsd - * - * @return string + * @var string */ - public function getSchemaFile() - { - return __DIR__ . '/validation.xsd'; - } + protected $_defaultBuilderClass = 'Magento_Validator_Builder'; /** - * Get validation rules for specified entity and group. + * Create validator builder instance based on entity and group. * * @param string $entityName * @param string $groupName + * @param array|null $builderConfig * @throws InvalidArgumentException - * @return array + * @return Magento_Validator_Builder */ - public function getValidationRules($entityName, $groupName) + public function createValidatorBuilder($entityName, $groupName, array $builderConfig = null) { if (!isset($this->_data[$entityName])) { throw new InvalidArgumentException(sprintf('Unknown validation entity "%s"', $entityName)); } - if (!isset($this->_data[$entityName]['groups'][$groupName])) { + + if (!isset($this->_data[$entityName][$groupName])) { throw new InvalidArgumentException(sprintf('Unknown validation group "%s" in entity "%s"', $groupName, $entityName)); } - $result = array(); - $groupRules = $this->_data[$entityName]['groups'][$groupName]; - foreach ($groupRules as $ruleName) { - $rule = $this->_data[$entityName]['rules'][$ruleName]; - foreach ($rule['constraints'] as $constraintConfig) { - $className = $constraintConfig['class']; - $constraint = new $className(); - if (!($constraint instanceof Zend_Validate_Interface - || $constraint instanceof Magento_Validator_ConstraintAbstract)) { - throw new InvalidArgumentException(sprintf('Constraint "%s" must implement either ' - . 'Zend_Validate_Interface or Magento_Validator_ConstraintAbstract', $className)); - } - if ($constraint instanceof Zend_Validate_Interface && empty($constraintConfig['field'])) { - throw new InvalidArgumentException(sprintf('Constraint "%s" must have "field" attribute defined.', - $className)); - } - $result[$ruleName][] = array( - 'constraint' => $constraint, - 'field' => $constraintConfig['field'], - ); - } + if (array_key_exists('builder', $this->_data[$entityName][$groupName])) { + $builderClass = $this->_data[$entityName][$groupName]['builder']; + } else { + $builderClass = $this->_defaultBuilderClass; } - return $result; + if (!class_exists($builderClass)) { + throw new InvalidArgumentException(sprintf('Builder class "%s" was not found', $builderClass)); + } + + $builder = new $builderClass($this->_data[$entityName][$groupName]['constraints']); + if (!$builder instanceof Magento_Validator_Builder) { + throw new InvalidArgumentException( + sprintf('Builder "%s" must extend Magento_Validator_Builder', $builderClass)); + } + if ($builderConfig) { + $builder->addConfigurations($builderConfig); + } + return $builder; + } + + /** + * Create validator based on entity and group. + * + * @param string $entityName + * @param string $groupName + * @param array|null $builderConfig + * @return Magento_Validator + */ + public function createValidator($entityName, $groupName, array $builderConfig = null) + { + return $this + ->createValidatorBuilder($entityName, $groupName, $builderConfig) + ->createValidator(); } /** * Extract configuration data from the DOM structure * * @param DOMDocument $dom - * @throws Magento_Exception * @return array */ protected function _extractData(DOMDocument $dom) { $result = array(); + /** @var DOMElement $entity */ foreach ($dom->getElementsByTagName('entity') as $entity) { - $entityName = $entity->getAttribute('name'); - $result[$entityName]['rules'] = array(); - /** @var DOMElement $rule */ - foreach ($entity->getElementsByTagName('rule') as $rule) { - $ruleName = $rule->getAttribute('name'); - $result[$entityName]['rules'][$ruleName] = array(); + $result[$entity->getAttribute('name')] = $this->_extractEntityGroupsConstraintsData($entity); + } + return $result; + } + + /** + * Extract constraints associated with entity group using rules + * + * @param DOMElement $entity + * @return array + */ + protected function _extractEntityGroupsConstraintsData(DOMElement $entity) + { + $result = array(); + $rulesConstraints = $this->_extractRulesConstraintsData($entity); + + /** @var DOMElement $group */ + foreach ($entity->getElementsByTagName('group') as $group) { + $groupConstraints = array(); + + /** @var DOMElement $use */ + foreach ($group->getElementsByTagName('use') as $use) { + $ruleName = $use->getAttribute('rule'); + if (isset($rulesConstraints[$ruleName])) { + $groupConstraints = array_merge($groupConstraints, $rulesConstraints[$ruleName]); + } + } + + $result[$group->getAttribute('name')] = array( + 'constraints' => $groupConstraints + ); + if ($group->hasAttribute('builder')) { + $result[$group->getAttribute('name')]['builder'] = $group->getAttribute('builder'); + } + } + + unset($groupConstraints); + unset($rulesConstraints); + + return $result; + } + + /** + * Extract constraints associated with rules + * + * @param DOMElement $entity + * @return array + */ + protected function _extractRulesConstraintsData(DOMElement $entity) + { + $rules = array(); + /** @var DOMElement $rule */ + foreach ($entity->getElementsByTagName('rule') as $rule) { + $ruleName = $rule->getAttribute('name'); + + /** @var DOMElement $propertyConstraints */ + foreach ($rule->getElementsByTagName('property_constraints') as $propertyConstraints) { + /** @var DOMElement $property */ + foreach ($propertyConstraints->getElementsByTagName('property') as $property) { + /** @var DOMElement $constraint */ + foreach ($property->getElementsByTagName('constraint') as $constraint) { + $rules[$ruleName][] = array( + 'alias' => $constraint->getAttribute('alias'), + 'class' => $constraint->getAttribute('class'), + 'options' => $this->_extractConstraintOptions($constraint), + 'property' => $property->getAttribute('name'), + 'type' => self::CONSTRAINT_TYPE_PROPERTY, + ); + } + } + } + + /** @var DOMElement $entityConstraints */ + foreach ($rule->getElementsByTagName('entity_constraints') as $entityConstraints) { /** @var DOMElement $constraint */ - foreach ($rule->getElementsByTagName('constraint') as $constraint) { - $result[$entityName]['rules'][$ruleName]['constraints'][] = array( + foreach ($entityConstraints->getElementsByTagName('constraint') as $constraint) { + $rules[$ruleName][] = array( + 'alias' => $constraint->getAttribute('alias'), 'class' => $constraint->getAttribute('class'), - 'field' => $constraint->getAttribute('field'), + 'options' => $this->_extractConstraintOptions($constraint), + 'type' => self::CONSTRAINT_TYPE_ENTITY, ); } } + } + + return $rules; + } + + /** + * Extract constraint options. + * + * @param DOMElement $constraint + * @return array|null + */ + protected function _extractConstraintOptions(DOMElement $constraint) + { + if (!$constraint->hasChildNodes()) { + return null; + } + $options = array(); + $children = $this->_collectChildren($constraint); + + /** + * Read constructor arguments + * + * <constraint class="Constraint"> + * <argument> + * <option name="minValue">123</option> + * <option name="maxValue">234</option> + * </argument> + * <argument>0</argument> + * <argument> + * <callback class="Class" method="method" /> + * </argument> + * </constraint> + */ + $arguments = $this->_readArguments($children); + if ($arguments) { + $options['arguments'] = $arguments; + } + + /** + * Read constraint configurator callback + * + * <constraint class="Constraint"> + * <callback class="Mage_Customer_Helper_Data" method="configureValidator"/> + * </constraint> + */ + $callback = $this->_readCallback($children); + if ($callback) { + $options['callback'] = $callback; + } + + /** + * Read constraint method configuration + */ + $methods = $this->_readMethods($children); + if ($methods) { + $options['methods'] = $methods; + } + return $options; + } + + /** + * Get element children. + * + * @param DOMElement $element + * @return array + */ + protected function _collectChildren($element) + { + $children = array(); + /** @var $node DOMElement */ + foreach ($element->childNodes as $node) { + if (!$node instanceof DOMElement) { + continue; + } + $nodeName = strtolower($node->nodeName); + if (!array_key_exists($nodeName, $children)) { + $children[$nodeName] = array(); + } + $children[$nodeName][] = $node; + } + return $children; + } + + /** + * Get arguments. + * + * @param array $children + * @return array|null + */ + protected function _readArguments($children) + { + if (array_key_exists('argument', $children)) { + $arguments = array(); + /** @var $node DOMElement */ + foreach ($children['argument'] as $node) { + $nodeChildren = $this->_collectChildren($node); + $callback = $this->_readCallback($nodeChildren); + $options = $this->_readOptions($nodeChildren); + if ($callback) { + $arguments[] = $callback[0]; + } elseif ($options) { + $arguments[] = $options; + } else { + $argument = $node->textContent; + $arguments[] = new Magento_Validator_Constraint_Option(trim($argument)); + } + + } + return $arguments; + } + return null; + } + + /** + * Get callback rules. + * + * @param array $children + * @return array|null + */ + protected function _readCallback($children) + { + if (array_key_exists('callback', $children)) { + $callbacks = array(); + /** @var $callbackData DOMElement */ + foreach ($children['callback'] as $callbackData) { + $callbacks[] = new Magento_Validator_Constraint_Option_Callback(array( + trim($callbackData->getAttribute('class')), + trim($callbackData->getAttribute('method')) + ), null, true); + } + return $callbacks; + } + return null; + } + + /** + * Get options array. + * + * @param array $children + * @return array|null + */ + protected function _readOptions($children) + { + if (array_key_exists('option', $children)) { + $data = array(); + /** @var $option DOMElement */ + foreach ($children['option'] as $option) { + $value = trim($option->textContent); + if ($option->hasAttribute('name')) { + $data[$option->getAttribute('name')] = $value; + } else { + $data[] = $value; + } + } + return new Magento_Validator_Constraint_Option($data); + } + return null; + } - $result[$entityName]['groups'] = array(); - /** @var DOMElement $group */ - foreach ($entity->getElementsByTagName('group') as $group) { - $groupName = $group->getAttribute('name'); - $result[$entityName]['groups'][$groupName] = array(); - /** @var DOMElement $use */ - foreach ($group->getElementsByTagName('use') as $use) { - $usesRuleName = $use->getAttribute('rule'); - $result[$entityName]['groups'][$groupName][] = $usesRuleName; + /** + * Get methods configuration. + * + * Example of method configuration: + * <constraint class="Constraint"> + * <method name="setMaxValue"> + * <argument> + * <option name="minValue">123</option> + * <option name="maxValue">234</option> + * </argument> + * <argument>0</argument> + * <argument> + * <callback class="Class" method="method" /> + * </argument> + * </method> + * </constraint> + * + * @param array $children + * @return array|null + */ + protected function _readMethods($children) + { + if (array_key_exists('method', $children)) { + $methods = array(); + /** @var $method DOMElement */ + foreach ($children['method'] as $method) { + $children = $this->_collectChildren($method); + $methodName = $method->getAttribute('name'); + $methodOptions = array( + 'method' => $methodName + ); + $arguments = $this->_readArguments($children); + if ($arguments) { + $methodOptions['arguments'] = $arguments; } + $methods[$methodName] = $methodOptions; } + return $methods; } + return null; + } - return $result; + /** + * Get absolute path to validation.xsd + * + * @return string + */ + public function getSchemaFile() + { + return __DIR__ . '/validation.xsd'; } /** - * Get initial XML of a valid document + * Get initial XML of a valid document. * * @return string */ @@ -146,7 +420,9 @@ class Magento_Validator_Config extends Magento_Config_XmlAbstract return array( '/validation/entity' => 'name', '/validation/entity/rules/rule' => 'name', - '/validation/entity/rules/rule/constraints/constraint' => 'class', + '/validation/entity/rules/rule/entity_constraints/constraint' => 'class', + '/validation/entity/rules/rule/property_constraints/property/constraint' => 'class', + '/validation/entity/rules/rule/property_constraints/property' => 'name', '/validation/entity/groups/group' => 'name', '/validation/entity/groups/group/uses/use' => 'rule', ); diff --git a/lib/Magento/Validator/Constraint.php b/lib/Magento/Validator/Constraint.php new file mode 100644 index 0000000000000000000000000000000000000000..495fbdf5c3d0f59a2d78f2becedf74c470c321ec --- /dev/null +++ b/lib/Magento/Validator/Constraint.php @@ -0,0 +1,118 @@ +<?php +/** + * Validator constraint delegates validation to wrapped validator. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Magento_Validator_Constraint extends Magento_Validator_ValidatorAbstract +{ + /** + * Wrapped validator + * + * @var Magento_Validator_ValidatorInterface + */ + protected $_wrappedValidator; + + /** + * Alias can be used for search + * + * @var string + */ + protected $_alias; + + /** + * Constructor + * + * @param Magento_Validator_ValidatorInterface $validator + * @param string $alias + */ + public function __construct(Magento_Validator_ValidatorInterface $validator, $alias = null) + { + $this->_wrappedValidator = $validator; + $this->_alias = $alias; + } + + /** + * Delegate validation to wrapped validator + * + * @param mixed $value + * @return boolean + */ + public function isValid($value) + { + $result = true; + $this->_clearMessages(); + + if (!$this->_wrappedValidator->isValid($this->_getValidatorValue($value))) { + $this->_addMessages($this->_wrappedValidator->getMessages()); + $result = false; + } + + return $result; + } + + /** + * Get value that should be validated. + * + * @param mixed $value + * @return mixed + */ + protected function _getValidatorValue($value) + { + if (is_array($value)) { + $value = new Varien_Object($value); + } + return $value; + } + + /** + * Get constraint alias + * + * @return string + */ + public function getAlias() + { + return $this->_alias; + } + + /** + * Set translator to wrapped validator. + * + * @param Magento_Translate_AdapterInterface|null $translator + * @return Magento_Validator_ValidatorAbstract + */ + public function setTranslator($translator = null) + { + $this->_wrappedValidator->setTranslator($translator); + return $this; + } + + /** + * Get translator instance of wrapped validator + * + * @return Magento_Translate_AdapterInterface|null + */ + public function getTranslator() + { + return $this->_wrappedValidator->getTranslator(); + } +} diff --git a/app/code/core/Mage/Api/Model/Resource/User/Collection.php b/lib/Magento/Validator/Constraint/Option.php old mode 100755 new mode 100644 similarity index 68% rename from app/code/core/Mage/Api/Model/Resource/User/Collection.php rename to lib/Magento/Validator/Constraint/Option.php index 565fcd733a633b723f8dd9be684d99297aa51d68..3a57b0457e052d27578bbcb9cf2c46415d1a3172 --- a/app/code/core/Mage/Api/Model/Resource/User/Collection.php +++ b/lib/Magento/Validator/Constraint/Option.php @@ -1,5 +1,7 @@ <?php /** + * Constraint option + * * Magento * * NOTICE OF LICENSE @@ -18,28 +20,33 @@ * versions in the future. If you wish to customize Magento for your * needs please refer to http://www.magentocommerce.com for more information. * - * @category Mage - * @package Mage_Api * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ +class Magento_Validator_Constraint_Option implements Magento_Validator_Constraint_OptionInterface +{ + /** + * @var mixed + */ + protected $_value; + /** + * Set value + * + * @param mixed $value + */ + public function __construct($value) + { + $this->_value = $value; + } -/** - * Api User Resource Collection - * - * @category Mage - * @package Mage_Api - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Api_Model_Resource_User_Collection extends Mage_Core_Model_Resource_Db_Collection_Abstract -{ /** - * Resource collection initialization + * Get value * + * @return mixed */ - protected function _construct() + public function getValue() { - $this->_init('Mage_Api_Model_User', 'Mage_Api_Model_Resource_User'); + return $this->_value; } } diff --git a/lib/Magento/Validator/Constraint/Option/Callback.php b/lib/Magento/Validator/Constraint/Option/Callback.php new file mode 100644 index 0000000000000000000000000000000000000000..6372386dde140d9eab2aed3212c19f956a5ca2f6 --- /dev/null +++ b/lib/Magento/Validator/Constraint/Option/Callback.php @@ -0,0 +1,104 @@ +<?php +/** + * Constraint callback option + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Magento_Validator_Constraint_Option_Callback implements Magento_Validator_Constraint_OptionInterface +{ + /** + * @var callable + */ + protected $_callable; + + /** + * @var array + */ + protected $_arguments; + + /** + * @var bool + */ + protected $_createInstance; + + /** + * Create callback + * + * @param callable $callable + * @param mixed $arguments + * @param bool $createInstance If true than $callable[0] will be evaluated to new instance of class when get value + */ + public function __construct($callable, $arguments = null, $createInstance = false) + { + $this->_callable = $callable; + $this->setArguments($arguments); + $this->_createInstance = $createInstance; + } + + /** + * Set callback arguments + * + * @param mixed $arguments + */ + public function setArguments($arguments = null) + { + if (is_array($arguments)) { + $this->_arguments = $arguments; + } elseif (null !== $arguments) { + $this->_arguments = array($arguments); + } else { + $this->_arguments = null; + } + } + + /** + * Get callback value + * + * @return mixed + * @throws InvalidArgumentException + */ + public function getValue() + { + $callable = $this->_callable; + + if (is_array($callable) && isset($callable[0]) && is_string($callable[0])) { + if (!class_exists($callable[0])) { + throw new InvalidArgumentException(sprintf('Class "%s" was not found', $callable[0])); + } + if ($this->_createInstance) { + $callable[0] = new $callable[0](); + } + } elseif ($this->_createInstance) { + throw new InvalidArgumentException('Callable expected to be an array with class name as first element'); + } + + if (!is_callable($callable)) { + throw new InvalidArgumentException('Callback does not callable'); + } + + if ($this->_arguments) { + return call_user_func_array($callable, $this->_arguments); + } else { + return call_user_func($callable); + } + } +} diff --git a/lib/Magento/Validator/Constraint/OptionInterface.php b/lib/Magento/Validator/Constraint/OptionInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..db8aecf0824d69fa7bf124f57d6cf73945259b76 --- /dev/null +++ b/lib/Magento/Validator/Constraint/OptionInterface.php @@ -0,0 +1,34 @@ +<?php +/** + * Validator Constraint Option interface + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +interface Magento_Validator_Constraint_OptionInterface +{ + /** + * Get option value + * + * @return mixed + */ + public function getValue(); +} diff --git a/lib/Magento/Validator/Constraint/Property.php b/lib/Magento/Validator/Constraint/Property.php new file mode 100644 index 0000000000000000000000000000000000000000..a73cdacdcad911f4115274a3ab973edba4614f04 --- /dev/null +++ b/lib/Magento/Validator/Constraint/Property.php @@ -0,0 +1,77 @@ +<?php +/** + * Validator constraint delegates validation of value's property to wrapped validator. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Magento_Validator_Constraint_Property extends Magento_Validator_Constraint +{ + /** + * Property name + * + * @var string + */ + protected $_property; + + /** + * Constructor + * + * @param Magento_Validator_ValidatorInterface $validator + * @param string $property + * @param string $alias + */ + public function __construct(Magento_Validator_ValidatorInterface $validator, $property, $alias = null) + { + parent::__construct($validator, $alias); + $this->_property = $property; + } + + /** + * Get value that should be validated. Tries to extract value's property if Varien_Object or ArrayAccess or array + * is passed + * + * @param mixed $value + * @return mixed + */ + protected function _getValidatorValue($value) + { + $result = null; + + if ($value instanceof Varien_Object) { + $result = $value->getDataUsingMethod($this->_property); + } elseif ((is_array($value) || $value instanceof ArrayAccess) && isset($value[$this->_property])) { + $result = $value[$this->_property]; + } + + return $result; + } + + /** + * Add messages with code of property name + * + * @param array $messages + */ + protected function _addMessages(array $messages) + { + $this->_messages[$this->_property] = $messages; + } +} diff --git a/lib/Magento/Validator/EmailAddress.php b/lib/Magento/Validator/EmailAddress.php new file mode 100644 index 0000000000000000000000000000000000000000..78a23b931191cddb1735a5c91abcd03d65b5e321 --- /dev/null +++ b/lib/Magento/Validator/EmailAddress.php @@ -0,0 +1,30 @@ +<?php +/** + * E-mail address validator + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Magento_Validator_EmailAddress extends Zend_Validate_EmailAddress + implements Magento_Validator_ValidatorInterface +{ + +} diff --git a/lib/Magento/Validator/Entity/Properties.php b/lib/Magento/Validator/Entity/Properties.php new file mode 100644 index 0000000000000000000000000000000000000000..2f9b6e804531ddcea4cfc630689fadf5a9a9077c --- /dev/null +++ b/lib/Magento/Validator/Entity/Properties.php @@ -0,0 +1,90 @@ +<?php +/** + * Validates properties of entity (Varien_Object). + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Magento_Validator_Entity_Properties extends Magento_Validator_ValidatorAbstract +{ + /** + * @var array + */ + protected $_readOnlyProperties = array(); + + /** + * Set read-only properties. + * + * @param array $readOnlyProperties + */ + public function setReadOnlyProperties(array $readOnlyProperties) + { + $this->_readOnlyProperties = $readOnlyProperties; + } + + /** + * Successful if $value is Varien_Object an all condition are fulfilled. + * + * If read-only properties are set than $value mustn't have changes in them. + * + * @param Varien_Object|mixed $value + * @return bool + * @throws InvalidArgumentException when $value is not instanceof Varien_Object + */ + public function isValid($value) + { + $this->_clearMessages(); + if (!($value instanceof Varien_Object)) { + throw new InvalidArgumentException('Instance of Varien_Object is expected.'); + } + if ($this->_readOnlyProperties) { + if (!$value->hasDataChanges()) { + return true; + } + foreach ($this->_readOnlyProperties as $property) { + if ($this->_hasChanges($value->getData($property), $value->getOrigData($property))) { + $this->_messages[__CLASS__] = array( + $this->getTranslator()->__("Read-only property cannot be changed.") + ); + break; + } + } + } + return !count($this->_messages); + } + + /** + * Compare two values as numbers and as other types + * + * @param mixed $firstValue + * @param mixed $secondValue + * @return bool + */ + protected function _hasChanges($firstValue, $secondValue) + { + if ($firstValue === $secondValue + || ($firstValue == $secondValue && is_numeric($firstValue) && is_numeric($secondValue)) + ) { + return false; + } + return true; + } +} diff --git a/lib/Magento/Validator/Exception.php b/lib/Magento/Validator/Exception.php new file mode 100644 index 0000000000000000000000000000000000000000..70acfd698f4d6acba006ec049cfc1b3f4e7c09a9 --- /dev/null +++ b/lib/Magento/Validator/Exception.php @@ -0,0 +1,64 @@ +<?php +/** + * Exception class for validator + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Magento_Validator_Exception extends Exception +{ + /** + * @var array + */ + protected $_messages; + + /** + * Constructor + * + * @param array $messages Validation error messages + */ + public function __construct(array $messages) + { + $this->_messages = $messages; + + $message = ''; + foreach ($this->_messages as $propertyMessages) { + foreach ($propertyMessages as $propertyMessage) { + if ($message) { + $message .= PHP_EOL; + } + $message .= $propertyMessage; + } + } + + parent::__construct($message); + } + + /** + * Get validation error messages + * + * @return array + */ + public function getMessages() + { + return $this->_messages; + } +} diff --git a/lib/Magento/Validator/Int.php b/lib/Magento/Validator/Int.php new file mode 100644 index 0000000000000000000000000000000000000000..906a35544273b298567ff5ec6dd75bcbe529dfd3 --- /dev/null +++ b/lib/Magento/Validator/Int.php @@ -0,0 +1,29 @@ +<?php +/** + * Integer validator + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Magento_Validator_Int extends Zend_Validate_Int implements Magento_Validator_ValidatorInterface +{ + +} diff --git a/lib/Magento/Validator/NotEmpty.php b/lib/Magento/Validator/NotEmpty.php new file mode 100644 index 0000000000000000000000000000000000000000..6b553714cc092bc4d43ad610883adad66e5b1c1d --- /dev/null +++ b/lib/Magento/Validator/NotEmpty.php @@ -0,0 +1,29 @@ +<?php +/** + * Not empty validator + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Magento_Validator_NotEmpty extends Zend_Validate_NotEmpty implements Magento_Validator_ValidatorInterface +{ + +} diff --git a/lib/Magento/Validator/StringLength.php b/lib/Magento/Validator/StringLength.php new file mode 100644 index 0000000000000000000000000000000000000000..7091709fde3dac794d0543a06d4ca1abacecbcda --- /dev/null +++ b/lib/Magento/Validator/StringLength.php @@ -0,0 +1,32 @@ +<?php +/** + * String length validator + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Magento_Validator_StringLength extends Zend_Validate_StringLength implements Magento_Validator_ValidatorInterface +{ + /** + * @var string + */ + protected $_encoding = 'UTF-8'; +} diff --git a/lib/Magento/Validator/ValidatorAbstract.php b/lib/Magento/Validator/ValidatorAbstract.php new file mode 100644 index 0000000000000000000000000000000000000000..065dc2ea64824d4122ba2eeffc29cff69a580f15 --- /dev/null +++ b/lib/Magento/Validator/ValidatorAbstract.php @@ -0,0 +1,127 @@ +<?php +/** + * Abstract validator class. + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +abstract class Magento_Validator_ValidatorAbstract implements Magento_Validator_ValidatorInterface +{ + /** + * @var Magento_Translate_AdapterInterface|null + */ + protected static $_defaultTranslator = null; + + /** + * @var Magento_Translate_AdapterInterface|null + */ + protected $_translator = null; + + /** + * Array of validation failure messages + * + * @var array + */ + protected $_messages = array(); + + /** + * Set default translator instance + * + * @param Magento_Translate_AdapterInterface|null $translator + */ + public static function setDefaultTranslator(Magento_Translate_AdapterInterface $translator = null) + { + self::$_defaultTranslator = $translator; + } + + /** + * Get default translator + * + * @return Magento_Translate_AdapterInterface|null + */ + public static function getDefaultTranslator() + { + return self::$_defaultTranslator; + } + + /** + * Set translator instance + * + * @param Magento_Translate_AdapterInterface|null $translator + * @return Magento_Validator_ValidatorAbstract + */ + public function setTranslator($translator = null) + { + $this->_translator = $translator; + return $this; + } + + /** + * Get translator + * + * @return Magento_Translate_AdapterInterface|null + */ + public function getTranslator() + { + if (is_null($this->_translator)) { + return self::getDefaultTranslator(); + } + return $this->_translator; + } + + /** + * Check that translator is set. + * + * @return boolean + */ + public function hasTranslator() + { + return !is_null($this->_translator); + } + + /** + * Get validation failure messages + * + * @return array + */ + public function getMessages() + { + return $this->_messages; + } + + /** + * Clear messages + */ + protected function _clearMessages() + { + $this->_messages = array(); + } + + /** + * Add messages + * + * @param array $messages + */ + protected function _addMessages(array $messages) + { + $this->_messages = array_merge_recursive($this->_messages, $messages); + } +} diff --git a/lib/Magento/Validator/ValidatorInterface.php b/lib/Magento/Validator/ValidatorInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..eb48f88433a9a4dab82efb2c4869bc326ddc855f --- /dev/null +++ b/lib/Magento/Validator/ValidatorInterface.php @@ -0,0 +1,49 @@ +<?php +/** + * Validator interface + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +interface Magento_Validator_ValidatorInterface extends Zend_Validate_Interface +{ + /** + * Set translator instance. + * + * @param Magento_Translate_AdapterInterface|null $translator + * @return Magento_Validator_ValidatorInterface + */ + public function setTranslator($translator = null); + + /** + * Get translator. + * + * @return Magento_Translate_AdapterInterface|null + */ + public function getTranslator(); + + /** + * Check that translator is set. + * + * @return boolean + */ + public function hasTranslator(); +} diff --git a/lib/Magento/Validator/validation.xsd b/lib/Magento/Validator/validation.xsd index 0ac023313bf7859c1d29bde9e6f4ae12ee161f34..05ff65fcd9aef4866ef206793e762db4b4a7eb4c 100644 --- a/lib/Magento/Validator/validation.xsd +++ b/lib/Magento/Validator/validation.xsd @@ -1,6 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- /** + * Structure definition of validation.xml Validation files + * * Magento * * NOTICE OF LICENSE @@ -19,9 +21,6 @@ * versions in the future. If you wish to customize Magento for your * needs please refer to http://www.magentocommerce.com for more information. * - * @category Magento - * @package Magento_Validator - * @subpackage Config * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) */ @@ -57,8 +56,8 @@ <xs:complexType name="entity"> <xs:sequence> - <xs:element name="rules" type="rules"/> - <xs:element name="groups" type="groups"/> + <xs:element name="rules" type="rules" maxOccurs="1" minOccurs="0"/> + <xs:element name="groups" type="groups" maxOccurs="1" minOccurs="0"/> </xs:sequence> <xs:attribute name="name" type="xs:string" use="required"/> </xs:complexType> @@ -68,22 +67,73 @@ <xs:element name="rule" maxOccurs="unbounded"> <xs:complexType> <xs:sequence> - <xs:element name="constraints" type="constraints"/> + <xs:element name="property_constraints" maxOccurs="unbounded" minOccurs="0"> + <xs:complexType> + <xs:sequence> + <xs:element name="property" maxOccurs="unbounded" minOccurs="1"> + <xs:complexType> + <xs:sequence> + <xs:element name="constraint" type="constraint" maxOccurs="unbounded" minOccurs="1"/> + </xs:sequence> + <xs:attribute name="name" type="xs:string" use="required"/> + </xs:complexType> + </xs:element> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="entity_constraints" maxOccurs="unbounded" minOccurs="0"> + <xs:complexType> + <xs:sequence> + <xs:element name="constraint" type="constraint" maxOccurs="unbounded" minOccurs="1"/> + </xs:sequence> + </xs:complexType> + </xs:element> </xs:sequence> <xs:attribute name="name" type="xs:string" use="required"/> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> - <xs:complexType name="constraints"> - <xs:sequence> - <xs:element name="constraint" maxOccurs="unbounded"> - <xs:complexType> - <xs:attribute name="class" type="xs:string" use="required"/> - <xs:attribute name="field" type="xs:string"/> - </xs:complexType> - </xs:element> + + <xs:complexType name="constraint"> + <xs:sequence minOccurs="0" maxOccurs="unbounded"> + <xs:choice> + <xs:element name="argument" type="argument" /> + <xs:element name="method"> + <xs:complexType> + <xs:sequence> + <xs:element name="argument" type="argument" maxOccurs="unbounded" minOccurs="0" /> + </xs:sequence> + <xs:attribute name="name" type="xs:string" use="required"/> + </xs:complexType> + </xs:element> + <xs:element name="callback" type="callback" /> + </xs:choice> </xs:sequence> + <xs:attribute name="class" type="xs:string" use="required"/> + <xs:attribute name="alias" type="xs:string"/> + </xs:complexType> + + <xs:complexType name="argument" mixed="true"> + <xs:choice> + <xs:sequence> + <xs:element name="option" maxOccurs="unbounded" minOccurs="0"> + <xs:complexType> + <xs:simpleContent> + <xs:extension base="xs:string"> + <xs:attribute name="name" type="xs:string"/> + </xs:extension> + </xs:simpleContent> + </xs:complexType> + </xs:element> + </xs:sequence> + <xs:element name="callback" type="callback" /> + </xs:choice> + </xs:complexType> + + <xs:complexType name="callback"> + <xs:attribute name="class" type="xs:string" use="required"/> + <xs:attribute name="method" type="xs:string" use="required"/> </xs:complexType> <xs:complexType name="groups"> @@ -94,6 +144,7 @@ <xs:element name="uses" type="uses"/> </xs:sequence> <xs:attribute name="name" type="xs:string" use="required"/> + <xs:attribute name="builder" type="xs:string"/> </xs:complexType> <xs:unique name="groupUse"> <xs:selector xpath="uses/use"/> diff --git a/lib/Varien/Data/Collection/Db.php b/lib/Varien/Data/Collection/Db.php index 388a04359624fe1c50ea665a79d30dddf002c42e..5c891927438f6e0010c2f13143b920c06b91b45b 100644 --- a/lib/Varien/Data/Collection/Db.php +++ b/lib/Varien/Data/Collection/Db.php @@ -411,7 +411,7 @@ class Varien_Data_Collection_Db extends Varien_Data_Collection protected function _translateCondition($field, $condition) { $field = $this->_getMappedField($field); - return $this->_getConditionSql($field, $condition); + return $this->_getConditionSql($this->getConnection()->quoteIdentifier($field), $condition); } /** diff --git a/lib/Varien/Db/Adapter/Pdo/Mysql.php b/lib/Varien/Db/Adapter/Pdo/Mysql.php index a5709fc73aafc1b104fec557b593ee01c00ed59b..ba09d85d4d90597ea678c2137f86f4379cdd7fa7 100644 --- a/lib/Varien/Db/Adapter/Pdo/Mysql.php +++ b/lib/Varien/Db/Adapter/Pdo/Mysql.php @@ -1,5 +1,7 @@ <?php /** + * Mysql PDO DB adapter + * * Magento * * NOTICE OF LICENSE @@ -18,14 +20,8 @@ * versions in the future. If you wish to customize Magento for your * needs please refer to http://www.magentocommerce.com for more information. * - * @category Varien - * @package Varien_Db - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Mysql PDO DB adapter + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ class Varien_Db_Adapter_Pdo_Mysql extends Zend_Db_Adapter_Pdo_Mysql implements Varien_Db_Adapter_Interface { @@ -442,6 +438,13 @@ class Varien_Db_Adapter_Pdo_Mysql extends Zend_Db_Adapter_Pdo_Mysql implements V $this->_debugStat(self::DEBUG_QUERY, $sql, $bind, $result); return $result; } catch (Exception $e) { + // Finalize broken query + $profiler = $this->getProfiler(); + if ($profiler instanceof Varien_Db_Profiler) { + /** @var Varien_Db_Profiler $profiler */ + $profiler->queryEndLast(); + } + /** @var $pdoException PDOException */ $pdoException = null; if ($e instanceof PDOException) { diff --git a/lib/Varien/Db/Profiler.php b/lib/Varien/Db/Profiler.php new file mode 100644 index 0000000000000000000000000000000000000000..0737dc14e21762839eb834e24daec284d0fee89c --- /dev/null +++ b/lib/Varien/Db/Profiler.php @@ -0,0 +1,111 @@ +<?php +/** + * Varien profiler for requests to database + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Varien_Db_Profiler extends Zend_Db_Profiler +{ + /** + * Host IP whereto a request is sent + * + * @var string + */ + protected $_host = ''; + + /** + * Database connection type + * + * @var string + */ + protected $_type = ''; + + /** + * Last query Id + * + * @var string|null + */ + private $_lastQueryId = null; + + /** + * Setter for host IP + * + * @param string $host + * @return Varien_Db_Profiler + */ + public function setHost($host) + { + $this->_host = $host; + return $this; + } + + /** + * Setter for database connection type + * + * @param string $type + * @return Varien_Db_Profiler + */ + public function setType($type) + { + $this->_type = $type; + return $this; + } + + /** + * Starts a query. Creates a new query profile object (Zend_Db_Profiler_Query) + * + * @param string $queryText SQL statement + * @param integer|null $queryType OPTIONAL Type of query, one of the Zend_Db_Profiler::* constants + * @return integer|null + */ + public function queryStart($queryText, $queryType = null) + { + $this->_lastQueryId = parent::queryStart($queryText, $queryType); + return $this->_lastQueryId; + } + + /** + * Ends a query. Pass it the handle that was returned by queryStart(). + * + * @param int $queryId + * @return string|void + */ + public function queryEnd($queryId) + { + $this->_lastQueryId = null; + return parent::queryEnd($queryId); + } + + /** + * Ends the last query if exists. Used for finalize broken queries. + * + * @return string|void + */ + public function queryEndLast() + { + if ($this->_lastQueryId !== null) { + return $this->queryEnd($this->_lastQueryId); + } + + return self::IGNORED; + } +} diff --git a/lib/Zend/Escaper/Escaper.php b/lib/Zend/Escaper/Escaper.php new file mode 100644 index 0000000000000000000000000000000000000000..4e1dd7928ea190c765b6803a0609bf41d22ad192 --- /dev/null +++ b/lib/Zend/Escaper/Escaper.php @@ -0,0 +1,393 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Escaper + */ + +namespace Zend\Escaper; + +use Zend\Escaper\Exception; + +/** + * Context specific methods for use in secure output escaping + * + * @package Zend_Escaper + */ +class Escaper +{ + /** + * Entity Map mapping Unicode codepoints to any available named HTML entities. + * + * While HTML supports far more named entities, the lowest common denominator + * has become HTML5's XML Serialisation which is restricted to the those named + * entities that XML supports. Using HTML entities would result in this error: + * XML Parsing Error: undefined entity + * + * @var array + */ + protected static $htmlNamedEntityMap = array( + 34 => 'quot', // quotation mark + 38 => 'amp', // ampersand + 60 => 'lt', // less-than sign + 62 => 'gt', // greater-than sign + ); + + /** + * Current encoding for escaping. If not UTF-8, we convert strings from this encoding + * pre-escaping and back to this encoding post-escaping. + * + * @var string + */ + protected $encoding = 'utf-8'; + + /** + * Holds the value of the special flags passed as second parameter to + * htmlspecialchars(). We modify these for PHP 5.4 to take advantage + * of the new ENT_SUBSTITUTE flag for correctly dealing with invalid + * UTF-8 sequences. + * + * @var string + */ + protected $htmlSpecialCharsFlags = \ENT_QUOTES; + + /** + * Static Matcher which escapes characters for HTML Attribute contexts + * + * @var callable + */ + protected $htmlAttrMatcher; + + /** + * Static Matcher which escapes characters for Javascript contexts + * + * @var callable + */ + protected $jsMatcher; + + /** + * Static Matcher which escapes characters for CSS Attribute contexts + * + * @var callable + */ + protected $cssMatcher; + + /** + * List of all encoding supported by this class + * + * @var array + */ + protected $supportedEncodings = array( + 'iso-8859-1', 'iso8859-1', 'iso-8859-5', 'iso8859-5', + 'iso-8859-15', 'iso8859-15', 'utf-8', 'cp866', + 'ibm866', '866', 'cp1251', 'windows-1251', + 'win-1251', '1251', 'cp1252', 'windows-1252', + '1252', 'koi8-r', 'koi8-ru', 'koi8r', + 'big5', '950', 'gb2312', '936', + 'big5-hkscs', 'shift_jis', 'sjis', 'sjis-win', + 'cp932', '932', 'euc-jp', 'eucjp', + 'eucjp-win', 'macroman' + ); + + /** + * Constructor: Single parameter allows setting of global encoding for use by + * the current object. If PHP 5.4 is detected, additional ENT_SUBSTITUTE flag + * is set for htmlspecialchars() calls. + * + * @param string $encoding + * @throws Exception\InvalidArgumentException + */ + public function __construct($encoding = null) + { + if ($encoding !== null) { + $encoding = (string) $encoding; + if ($encoding === '') { + throw new Exception\InvalidArgumentException( + get_called_class() . ' constructor parameter does not allow a blank value' + ); + } + + $encoding = strtolower($encoding); + if (!in_array($encoding, $this->supportedEncodings)) { + throw new Exception\InvalidArgumentException( + 'Value of \'' . $encoding . '\' passed to ' . get_called_class() + . ' constructor parameter is invalid. Provide an encoding supported by htmlspecialchars()' + ); + } + + $this->encoding = $encoding; + } + + if (defined('ENT_SUBSTITUTE')) { + $this->htmlSpecialCharsFlags|= \ENT_SUBSTITUTE; + } + + // set matcher callbacks + $this->htmlAttrMatcher = array($this, 'htmlAttrMatcher'); + $this->jsMatcher = array($this, 'jsMatcher'); + $this->cssMatcher = array($this, 'cssMatcher'); + } + + /** + * Return the encoding that all output/input is expected to be encoded in. + * + * @return string + */ + public function getEncoding() + { + return $this->encoding; + } + + /** + * Escape a string for the HTML Body context where there are very few characters + * of special meaning. Internally this will use htmlspecialchars(). + * + * @param string $string + * @return string + */ + public function escapeHtml($string) + { + $result = htmlspecialchars($string, $this->htmlSpecialCharsFlags, $this->encoding); + return $result; + } + + /** + * Escape a string for the HTML Attribute context. We use an extended set of characters + * to escape that are not covered by htmlspecialchars() to cover cases where an attribute + * might be unquoted or quoted illegally (e.g. backticks are valid quotes for IE). + * + * @param string $string + * @return string + */ + public function escapeHtmlAttr($string) + { + $string = $this->toUtf8($string); + if ($string === '' || ctype_digit($string)) { + return $string; + } + + $result = preg_replace_callback('/[^a-z0-9,\.\-_]/iSu', $this->htmlAttrMatcher, $string); + return $this->fromUtf8($result); + } + + /** + * Escape a string for the Javascript context. This does not use json_encode(). An extended + * set of characters are escaped beyond ECMAScript's rules for Javascript literal string + * escaping in order to prevent misinterpretation of Javascript as HTML leading to the + * injection of special characters and entities. The escaping used should be tolerant + * of cases where HTML escaping was not applied on top of Javascript escaping correctly. + * Backslash escaping is not used as it still leaves the escaped character as-is and so + * is not useful in a HTML context. + * + * @param string $string + * @return string + */ + public function escapeJs($string) + { + $string = $this->toUtf8($string); + if ($string === '' || ctype_digit($string)) { + return $string; + } + + $result = preg_replace_callback('/[^a-z0-9,\._]/iSu', $this->jsMatcher, $string); + return $this->fromUtf8($result); + } + + /** + * Escape a string for the URI or Parameter contexts. This should not be used to escape + * an entire URI - only a subcomponent being inserted. The function is a simple proxy + * to rawurlencode() which now implements RFC 3986 since PHP 5.3 completely. + * + * @param string $string + * @return string + */ + public function escapeUrl($string) + { + return rawurlencode($string); + } + + /** + * Escape a string for the CSS context. CSS escaping can be applied to any string being + * inserted into CSS and escapes everything except alphanumerics. + * + * @param string $string + * @return string + */ + public function escapeCss($string) + { + $string = $this->toUtf8($string); + if ($string === '' || ctype_digit($string)) { + return $string; + } + + $result = preg_replace_callback('/[^a-z0-9]/iSu', $this->cssMatcher, $string); + return $this->fromUtf8($result); + } + + /** + * Callback function for preg_replace_callback that applies HTML Attribute + * escaping to all matches. + * + * @param array $matches + * @return string + */ + protected function htmlAttrMatcher($matches) + { + $chr = $matches[0]; + $ord = ord($chr); + + /** + * The following replaces characters undefined in HTML with the + * hex entity for the Unicode replacement character. + */ + if (($ord <= 0x1f && $chr != "\t" && $chr != "\n" && $chr != "\r") + || ($ord >= 0x7f && $ord <= 0x9f) + ) { + return '�'; + } + + /** + * Check if the current character to escape has a name entity we should + * replace it with while grabbing the integer value of the character. + */ + if (strlen($chr) > 1) { + $chr = $this->convertEncoding($chr, 'UTF-16BE', 'UTF-8'); + } + + $hex = bin2hex($chr); + $ord = hexdec($hex); + if (isset(static::$htmlNamedEntityMap[$ord])) { + return '&' . static::$htmlNamedEntityMap[$ord] . ';'; + } + + /** + * Per OWASP recommendations, we'll use upper hex entities + * for any other characters where a named entity does not exist. + */ + if ($ord > 255) { + return sprintf('&#x%04X;', $ord); + } + return sprintf('&#x%02X;', $ord); + } + + /** + * Callback function for preg_replace_callback that applies Javascript + * escaping to all matches. + * + * @param array $matches + * @return string + */ + protected function jsMatcher($matches) + { + $chr = $matches[0]; + if (strlen($chr) == 1) { + return sprintf('\\x%02X', ord($chr)); + } + $chr = $this->convertEncoding($chr, 'UTF-16BE', 'UTF-8'); + return sprintf('\\u%04s', strtoupper(bin2hex($chr))); + } + + /** + * Callback function for preg_replace_callback that applies CSS + * escaping to all matches. + * + * @param array $matches + * @return string + */ + protected function cssMatcher($matches) + { + $chr = $matches[0]; + if (strlen($chr) == 1) { + $ord = ord($chr); + } else { + $chr = $this->convertEncoding($chr, 'UTF-16BE', 'UTF-8'); + $ord = hexdec(bin2hex($chr)); + } + return sprintf('\\%X ', $ord); + } + + /** + * Converts a string to UTF-8 from the base encoding. The base encoding is set via this + * class' constructor. + * + * @param string $string + * @throws Exception\RuntimeException + * @return string + */ + protected function toUtf8($string) + { + if ($this->getEncoding() === 'utf-8') { + $result = $string; + } else { + $result = $this->convertEncoding($string, 'UTF-8', $this->getEncoding()); + } + + if (!$this->isUtf8($result)) { + throw new Exception\RuntimeException(sprintf( + 'String to be escaped was not valid UTF-8 or could not be converted: %s', $result + )); + } + + return $result; + } + + /** + * Converts a string from UTF-8 to the base encoding. The base encoding is set via this + * class' constructor. + * @param string $string + * @return string + */ + protected function fromUtf8($string) + { + if ($this->getEncoding() === 'utf-8') { + return $string; + } + + return $this->convertEncoding($string, $this->getEncoding(), 'UTF-8'); + } + + /** + * Checks if a given string appears to be valid UTF-8 or not. + * + * @param string $string + * @return bool + */ + protected function isUtf8($string) + { + return ($string === '' || preg_match('/^./su', $string)); + } + + /** + * Encoding conversion helper which wraps iconv and mbstring where they exist or throws + * and exception where neither is available. + * + * @param string $string + * @param string $to + * @param array|string $from + * @throws Exception\RuntimeException + * @return string + */ + protected function convertEncoding($string, $to, $from) + { + $result = ''; + if (function_exists('iconv')) { + $result = iconv($from, $to, $string); + } elseif (function_exists('mb_convert_encoding')) { + $result = mb_convert_encoding($string, $to, $from); + } else { + throw new Exception\RuntimeException( + get_called_class() + . ' requires either the iconv or mbstring extension to be installed' + . ' when escaping for non UTF-8 strings.' + ); + } + + if ($result === false) { + return ''; // return non-fatal blank string on encoding errors from users + } + return $result; + } +} diff --git a/lib/Zend/Escaper/Exception/ExceptionInterface.php b/lib/Zend/Escaper/Exception/ExceptionInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..65a818e08804d1957c0c2754b4da5f59bcaab2d8 --- /dev/null +++ b/lib/Zend/Escaper/Exception/ExceptionInterface.php @@ -0,0 +1,18 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Escaper + */ + +namespace Zend\Escaper\Exception; + +/** + * @category Zend + * @package Zend_Escaper + */ +interface ExceptionInterface +{} diff --git a/lib/Zend/Escaper/Exception/InvalidArgumentException.php b/lib/Zend/Escaper/Exception/InvalidArgumentException.php new file mode 100644 index 0000000000000000000000000000000000000000..bc760e5d279b254e3aa4caedf0d4a0a5ac7ae5a1 --- /dev/null +++ b/lib/Zend/Escaper/Exception/InvalidArgumentException.php @@ -0,0 +1,22 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Escaper + */ + +namespace Zend\Escaper\Exception; + +/** + * Invalid argument exception + * + * @category Zend + * @package Zend_Escaper + */ +class InvalidArgumentException extends \InvalidArgumentException implements + ExceptionInterface +{ +} diff --git a/lib/Zend/Escaper/Exception/RuntimeException.php b/lib/Zend/Escaper/Exception/RuntimeException.php new file mode 100644 index 0000000000000000000000000000000000000000..a31f3e7442b0bd462483e5e2e4f003aa60821a2d --- /dev/null +++ b/lib/Zend/Escaper/Exception/RuntimeException.php @@ -0,0 +1,22 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Escaper + */ + +namespace Zend\Escaper\Exception; + +/** + * Invalid argument exception + * + * @category Zend + * @package Zend_Escaper + */ +class RuntimeException extends \RuntimeException implements + ExceptionInterface +{ +} diff --git a/lib/Zend/Escaper/composer.json b/lib/Zend/Escaper/composer.json new file mode 100644 index 0000000000000000000000000000000000000000..7df2296c42d37b843961283a572d85f9ab802a16 --- /dev/null +++ b/lib/Zend/Escaper/composer.json @@ -0,0 +1,18 @@ +{ + "name": "zendframework/zend-escaper", + "description": " ", + "license": "BSD-3-Clause", + "keywords": [ + "zf2", + "escaper" + ], + "autoload": { + "psr-0": { + "Zend\\Escaper": "" + } + }, + "target-dir": "Zend/Escaper", + "require": { + "php": ">=5.3.3" + } +} \ No newline at end of file diff --git a/lib/Zend/I18n/Exception/ExceptionInterface.php b/lib/Zend/I18n/Exception/ExceptionInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..a13a9c0a1337715567b835f97eea0b41db309289 --- /dev/null +++ b/lib/Zend/I18n/Exception/ExceptionInterface.php @@ -0,0 +1,19 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_I18n + */ + +namespace Zend\I18n\Exception; + +/** + * @category Zend + * @package Zend_I18n + * @subpackage Translator + */ +interface ExceptionInterface +{} diff --git a/lib/Zend/I18n/Exception/InvalidArgumentException.php b/lib/Zend/I18n/Exception/InvalidArgumentException.php new file mode 100644 index 0000000000000000000000000000000000000000..bdbdf667d951f37098451224faabaae3a96ca491 --- /dev/null +++ b/lib/Zend/I18n/Exception/InvalidArgumentException.php @@ -0,0 +1,20 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_I18n + */ + +namespace Zend\I18n\Exception; + +/** + * @category Zend + * @package Zend_I18n + * @subpackage Translator + */ +class InvalidArgumentException extends \InvalidArgumentException implements + ExceptionInterface +{} diff --git a/lib/Zend/I18n/Exception/OutOfBoundsException.php b/lib/Zend/I18n/Exception/OutOfBoundsException.php new file mode 100644 index 0000000000000000000000000000000000000000..8122fc97b6c9bfae3336c0f30974f477cf42b704 --- /dev/null +++ b/lib/Zend/I18n/Exception/OutOfBoundsException.php @@ -0,0 +1,20 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_I18n + */ + +namespace Zend\I18n\Exception; + +/** + * @category Zend + * @package Zend_I18n + * @subpackage Translator + */ +class OutOfBoundsException extends \OutOfBoundsException implements + ExceptionInterface +{} diff --git a/lib/Zend/I18n/Exception/ParseException.php b/lib/Zend/I18n/Exception/ParseException.php new file mode 100644 index 0000000000000000000000000000000000000000..73857be73469a8713bec145c725e91d6e594c7bc --- /dev/null +++ b/lib/Zend/I18n/Exception/ParseException.php @@ -0,0 +1,19 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_I18n + */ + +namespace Zend\I18n\Exception; + +/** + * @category Zend + * @package Zend_I18n + * @subpackage Translator + */ +class ParseException extends RuntimeException implements ExceptionInterface +{} diff --git a/lib/Zend/I18n/Exception/RangeException.php b/lib/Zend/I18n/Exception/RangeException.php new file mode 100644 index 0000000000000000000000000000000000000000..a534c9721879a815969dfc5120645a325418e583 --- /dev/null +++ b/lib/Zend/I18n/Exception/RangeException.php @@ -0,0 +1,19 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_I18n + */ + +namespace Zend\I18n\Exception; + +/** + * @category Zend + * @package Zend_I18n + * @subpackage Translator + */ +class RangeException extends \RangeException implements ExceptionInterface +{} diff --git a/lib/Zend/I18n/Exception/RuntimeException.php b/lib/Zend/I18n/Exception/RuntimeException.php new file mode 100644 index 0000000000000000000000000000000000000000..024d6e55297b575514d153e19b8b2f901e365cff --- /dev/null +++ b/lib/Zend/I18n/Exception/RuntimeException.php @@ -0,0 +1,19 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_I18n + */ + +namespace Zend\I18n\Exception; + +/** + * @category Zend + * @package Zend_I18n + * @subpackage Translator + */ +class RuntimeException extends \RuntimeException implements ExceptionInterface +{} diff --git a/lib/Zend/I18n/Filter/AbstractLocale.php b/lib/Zend/I18n/Filter/AbstractLocale.php new file mode 100644 index 0000000000000000000000000000000000000000..e74dee77e216950367f44f112435ceee379f8124 --- /dev/null +++ b/lib/Zend/I18n/Filter/AbstractLocale.php @@ -0,0 +1,46 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_I18n + */ + +namespace Zend\I18n\Filter; + +use Locale; +use Zend\Filter\AbstractFilter; + +/** + * @category Zend + * @package Zend_Filter + */ +abstract class AbstractLocale extends AbstractFilter +{ + /** + * Sets the locale option + * + * @param string|null $locale + * @return AbstractLocale + */ + public function setLocale($locale = null) + { + $this->options['locale'] = $locale; + return $this; + } + + /** + * Returns the locale option + * + * @return string + */ + public function getLocale() + { + if (!isset($this->options['locale'])) { + $this->options['locale'] = Locale::getDefault(); + } + return $this->options['locale']; + } +} diff --git a/lib/Zend/I18n/Filter/Alnum.php b/lib/Zend/I18n/Filter/Alnum.php new file mode 100644 index 0000000000000000000000000000000000000000..305e767d6ce0f6bd63c07e428f631ff09be50509 --- /dev/null +++ b/lib/Zend/I18n/Filter/Alnum.php @@ -0,0 +1,97 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_I18n + */ + +namespace Zend\I18n\Filter; + +use Locale; +use Traversable; +use Zend\Stdlib\ArrayUtils; + +/** + * @category Zend + * @package Zend_Filter + */ +class Alnum extends AbstractLocale +{ + /** + * @var array + */ + protected $options = array( + 'locale' => null, + 'allow_white_space' => false, + ); + + /** + * Sets default option values for this instance + * + * @param array|Traversable|boolean|null $allowWhiteSpaceOrOptions + * @param string|null $locale + */ + public function __construct($allowWhiteSpaceOrOptions = null, $locale = null) + { + if ($allowWhiteSpaceOrOptions !== null) { + if (static::isOptions($allowWhiteSpaceOrOptions)) { + $this->setOptions($allowWhiteSpaceOrOptions); + } else { + $this->setAllowWhiteSpace($allowWhiteSpaceOrOptions); + $this->setLocale($locale); + } + } + } + + /** + * Sets the allowWhiteSpace option + * + * @param boolean $flag + * @return Alnum Provides a fluent interface + */ + public function setAllowWhiteSpace($flag = true) + { + $this->options['allow_white_space'] = (boolean) $flag; + return $this; + } + + /** + * Whether white space is allowed + * + * @return boolean + */ + public function getAllowWhiteSpace() + { + return $this->options['allow_white_space']; + } + + /** + * Defined by Zend\Filter\FilterInterface + * + * Returns $value as string with all non-alphanumeric characters removed + * + * @param mixed $value + * @return string + */ + public function filter($value) + { + $whiteSpace = $this->options['allow_white_space'] ? '\s' : ''; + $language = Locale::getPrimaryLanguage($this->getLocale()); + + if (!static::hasPcreUnicodeSupport()) { + // POSIX named classes are not supported, use alternative a-zA-Z0-9 match + $pattern = '/[^a-zA-Z0-9' . $whiteSpace . ']/'; + } elseif ($language == 'ja'|| $language == 'ko' || $language == 'zh') { + // Use english alphabet + $pattern = '/[^a-zA-Z0-9' . $whiteSpace . ']/u'; + } else { + // Use native language alphabet + $pattern = '/[^\p{L}\p{N}' . $whiteSpace . ']/u'; + } + + return preg_replace($pattern, '', (string) $value); + } +} diff --git a/lib/Zend/I18n/Filter/Alpha.php b/lib/Zend/I18n/Filter/Alpha.php new file mode 100644 index 0000000000000000000000000000000000000000..8c619305acbcac2376801bcca5f183614894f3d5 --- /dev/null +++ b/lib/Zend/I18n/Filter/Alpha.php @@ -0,0 +1,47 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_I18n + */ + +namespace Zend\I18n\Filter; + +use Locale; + +/** + * @category Zend + * @package Zend_Filter + */ +class Alpha extends Alnum +{ + /** + * Defined by Zend\Filter\FilterInterface + * + * Returns the string $value, removing all but alphabetic characters + * + * @param string $value + * @return string + */ + public function filter($value) + { + $whiteSpace = $this->options['allow_white_space'] ? '\s' : ''; + $language = Locale::getPrimaryLanguage($this->getLocale()); + + if (!static::hasPcreUnicodeSupport()) { + // POSIX named classes are not supported, use alternative [a-zA-Z] match + $pattern = '/[^a-zA-Z' . $whiteSpace . ']/'; + } elseif ($language == 'ja' || $language == 'ko' || $language == 'zh') { + // Use english alphabet + $pattern = '/[^a-zA-Z' . $whiteSpace . ']/u'; + } else { + // Use native language alphabet + $pattern = '/[^\p{L}' . $whiteSpace . ']/u'; + } + + return preg_replace($pattern, '', (string) $value); + } +} diff --git a/lib/Zend/I18n/Filter/NumberFormat.php b/lib/Zend/I18n/Filter/NumberFormat.php new file mode 100644 index 0000000000000000000000000000000000000000..fc26ece31926eca1c9891b2b4a540c16c54e7b55 --- /dev/null +++ b/lib/Zend/I18n/Filter/NumberFormat.php @@ -0,0 +1,163 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_I18n + */ + +namespace Zend\I18n\Filter; + +use NumberFormatter; +use Traversable; +use Zend\I18n\Exception; +use Zend\Stdlib\ErrorHandler; + +class NumberFormat extends AbstractLocale +{ + protected $options = array( + 'locale' => null, + 'style' => NumberFormatter::DEFAULT_STYLE, + 'type' => NumberFormatter::TYPE_DOUBLE + ); + + /** + * @var NumberFormatter + */ + protected $formatter = null; + + /** + * @param array|Traversable|string|null $localeOrOptions + * @param int $style + * @param int $type + */ + public function __construct( + $localeOrOptions = null, + $style = NumberFormatter::DEFAULT_STYLE, + $type = NumberFormatter::TYPE_DOUBLE) + { + if ($localeOrOptions !== null) { + if ($localeOrOptions instanceof Traversable) { + $localeOrOptions = iterator_to_array($localeOrOptions); + } + + if (!is_array($localeOrOptions)) { + $this->setLocale($localeOrOptions); + $this->setStyle($style); + $this->setType($type); + } else { + $this->setOptions($localeOrOptions); + } + } + } + + /** + * @param string|null $locale + * @return NumberFormat + */ + public function setLocale($locale = null) + { + $this->options['locale'] = $locale; + $this->formatter = null; + return $this; + } + + /** + * @param int $style + * @return NumberFormat + */ + public function setStyle($style) + { + $this->options['style'] = (int) $style; + $this->formatter = null; + return $this; + } + + /** + * @return int + */ + public function getStyle() + { + return $this->options['style']; + } + + /** + * @param int $type + * @return NumberFormat + */ + public function setType($type) + { + $this->options['type'] = (int) $type; + return $this; + } + + /** + * @return int + */ + public function getType() + { + return $this->options['type']; + } + + /** + * @param NumberFormatter $formatter + * @return NumberFormat + */ + public function setFormatter(NumberFormatter $formatter) + { + $this->formatter = $formatter; + return $this; + } + + /** + * @return NumberFormatter + * @throws Exception\RuntimeException + */ + public function getFormatter() + { + if ($this->formatter === null) { + $formatter = NumberFormatter::create($this->getLocale(), $this->getStyle()); + if (!$formatter) { + throw new Exception\RuntimeException( + 'Can not create NumberFormatter instance; ' . intl_get_error_message() + ); + } + + $this->formatter = $formatter; + } + + return $this->formatter; + } + + /** + * Defined by Zend\Filter\FilterInterface + * + * @see Zend\Filter\FilterInterface::filter() + * @param mixed $value + * @return mixed + */ + public function filter($value) + { + $formatter = $this->getFormatter(); + $type = $this->getType(); + + if (is_int($value) || is_float($value)) { + ErrorHandler::start(); + $result = $formatter->format($value, $type); + ErrorHandler::stop(); + } else { + $value = str_replace(array("\xC2\xA0", ' '), '', $value); + ErrorHandler::start(); + $result = $formatter->parse($value, $type); + ErrorHandler::stop(); + } + + if ($result === false) { + return $value; + } + + return str_replace("\xC2\xA0", ' ', $result); + } +} diff --git a/lib/Zend/I18n/Translator/Loader/FileLoaderInterface.php b/lib/Zend/I18n/Translator/Loader/FileLoaderInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..6fb00e2cdfd2b1193feaf6ee9f2e48857f4710cb --- /dev/null +++ b/lib/Zend/I18n/Translator/Loader/FileLoaderInterface.php @@ -0,0 +1,30 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_I18n + */ + +namespace Zend\I18n\Translator\Loader; + +/** + * File loader interface. + * + * @category Zend + * @package Zend_I18n + * @subpackage Translator + */ +interface FileLoaderInterface +{ + /** + * Load translations from a file. + * + * @param string $locale + * @param string $filename + * @return \Zend\I18n\Translator\TextDomain|null + */ + public function load($locale, $filename); +} diff --git a/lib/Zend/I18n/Translator/Loader/Gettext.php b/lib/Zend/I18n/Translator/Loader/Gettext.php new file mode 100644 index 0000000000000000000000000000000000000000..4651741fd3212683624bcc479c39fdbadebc946b --- /dev/null +++ b/lib/Zend/I18n/Translator/Loader/Gettext.php @@ -0,0 +1,193 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_I18n + */ + +namespace Zend\I18n\Translator\Loader; + +use Zend\I18n\Exception; +use Zend\I18n\Translator\Plural\Rule as PluralRule; +use Zend\I18n\Translator\TextDomain; +use Zend\Stdlib\ErrorHandler; + +/** + * Gettext loader. + * + * @category Zend + * @package Zend_I18n + * @subpackage Translator + */ +class Gettext implements FileLoaderInterface +{ + /** + * Current file pointer. + * + * @var resource + */ + protected $file; + + /** + * Whether the current file is little endian. + * + * @var boolean + */ + protected $littleEndian; + + /** + * load(): defined by FileLoaderInterface. + * + * @see FileLoaderInterface::load() + * @param string $locale + * @param string $filename + * @return TextDomain + * @throws Exception\InvalidArgumentException + */ + public function load($locale, $filename) + { + if (!is_file($filename) || !is_readable($filename)) { + throw new Exception\InvalidArgumentException(sprintf( + 'Could not open file %s for reading', + $filename + )); + } + + $textDomain = new TextDomain(); + + ErrorHandler::start(); + $this->file = fopen($filename, 'rb'); + $error = ErrorHandler::stop(); + if (false === $this->file) { + throw new Exception\InvalidArgumentException(sprintf( + 'Could not open file %s for reading', + $filename + ), 0, $error); + } + + // Verify magic number + $magic = fread($this->file, 4); + + if ($magic == "\x95\x04\x12\xde") { + $this->littleEndian = false; + } elseif ($magic == "\xde\x12\x04\x95") { + $this->littleEndian = true; + } else { + fclose($this->file); + throw new Exception\InvalidArgumentException(sprintf( + '%s is not a valid gettext file', + $filename + )); + } + + // Verify major revision (only 0 and 1 supported) + $majorRevision = ($this->readInteger() >> 16); + + if ($majorRevision !== 0 && $majorRevision !== 1) { + fclose($this->file); + throw new Exception\InvalidArgumentException(sprintf( + '%s has an unknown major revision', + $filename + )); + } + + // Gather main information + $numStrings = $this->readInteger(); + $originalStringTableOffset = $this->readInteger(); + $translationStringTableOffset = $this->readInteger(); + + // Usually there follow size and offset of the hash table, but we have + // no need for it, so we skip them. + fseek($this->file, $originalStringTableOffset); + $originalStringTable = $this->readIntegerList(2 * $numStrings); + + fseek($this->file, $translationStringTableOffset); + $translationStringTable = $this->readIntegerList(2 * $numStrings); + + // Read in all translations + for ($current = 0; $current < $numStrings; $current++) { + $sizeKey = $current * 2 + 1; + $offsetKey = $current * 2 + 2; + $originalStringSize = $originalStringTable[$sizeKey]; + $originalStringOffset = $originalStringTable[$offsetKey]; + $translationStringSize = $translationStringTable[$sizeKey]; + $translationStringOffset = $translationStringTable[$offsetKey]; + + $originalString = array(''); + if ($originalStringSize > 0) { + fseek($this->file, $originalStringOffset); + $originalString = explode("\0", fread($this->file, $originalStringSize)); + } + + if ($translationStringSize > 0) { + fseek($this->file, $translationStringOffset); + $translationString = explode("\0", fread($this->file, $translationStringSize)); + + if (count($originalString) > 1 && count($translationString) > 1) { + $textDomain[$originalString[0]] = $translationString; + + array_shift($originalString); + + foreach ($originalString as $string) { + $textDomain[$string] = ''; + } + } else { + $textDomain[$originalString[0]] = $translationString[0]; + } + } + } + + // Read header entries + if (array_key_exists('', $textDomain)) { + $rawHeaders = explode("\n", trim($textDomain[''])); + + foreach ($rawHeaders as $rawHeader) { + list($header, $content) = explode(':', $rawHeader, 2); + + if (trim(strtolower($header)) === 'plural-forms') { + $textDomain->setPluralRule(PluralRule::fromString($content)); + } + } + + unset($textDomain['']); + } + + fclose($this->file); + + return $textDomain; + } + + /** + * Read a single integer from the current file. + * + * @return integer + */ + protected function readInteger() + { + if ($this->littleEndian) { + $result = unpack('Vint', fread($this->file, 4)); + } else { + $result = unpack('Nint', fread($this->file, 4)); + } + + return $result['int']; + } + + /** + * Read an integer from the current file. + * + * @param integer $num + * @return integer + */ + protected function readIntegerList($num) + { + if ($this->littleEndian) { + return unpack('V' . $num, fread($this->file, 4 * $num)); + } else { + return unpack('N' . $num, fread($this->file, 4 * $num)); + } + } +} diff --git a/lib/Zend/I18n/Translator/Loader/PhpArray.php b/lib/Zend/I18n/Translator/Loader/PhpArray.php new file mode 100644 index 0000000000000000000000000000000000000000..05e96ef5720948c21e75926cbdb40a3f9165678e --- /dev/null +++ b/lib/Zend/I18n/Translator/Loader/PhpArray.php @@ -0,0 +1,67 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_I18n + */ + +namespace Zend\I18n\Translator\Loader; + +use Zend\I18n\Exception; +use Zend\I18n\Translator\Plural\Rule as PluralRule; +use Zend\I18n\Translator\TextDomain; + +/** + * PHP array loader. + * + * @category Zend + * @package Zend_I18n + * @subpackage Translator + */ +class PhpArray implements FileLoaderInterface +{ + /** + * load(): defined by FileLoaderInterface. + * + * @see FileLoaderInterface::load() + * @param string $locale + * @param string $filename + * @return TextDomain|null + * @throws Exception\InvalidArgumentException + */ + public function load($locale, $filename) + { + if (!is_file($filename) || !is_readable($filename)) { + throw new Exception\InvalidArgumentException(sprintf( + 'Could not open file %s for reading', + $filename + )); + } + + $messages = include $filename; + + if (!is_array($messages)) { + throw new Exception\InvalidArgumentException(sprintf( + 'Expected an array, but received %s', + gettype($messages) + )); + } + + $textDomain = new TextDomain($messages); + + if (array_key_exists('', $textDomain)) { + if (isset($textDomain['']['plural_forms'])) { + $textDomain->setPluralRule( + PluralRule::fromString($textDomain['']['plural_forms']) + ); + } + + unset($textDomain['']); + } + + return $textDomain; + } +} diff --git a/lib/Zend/I18n/Translator/Loader/RemoteLoaderInterface.php b/lib/Zend/I18n/Translator/Loader/RemoteLoaderInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..576a75838495d0414bc4e9f92ca9f8f0c66e1240 --- /dev/null +++ b/lib/Zend/I18n/Translator/Loader/RemoteLoaderInterface.php @@ -0,0 +1,30 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_I18n + */ + +namespace Zend\I18n\Translator\Loader; + +/** + * Remote loader interface. + * + * @category Zend + * @package Zend_I18n + * @subpackage Translator + */ +interface RemoteLoaderInterface +{ + /** + * Load translations from a remote source. + * + * @param string $locale + * @param string $textDomain + * @return \Zend\I18n\Translator\TextDomain|null + */ + public function load($locale, $textDomain); +} diff --git a/lib/Zend/I18n/Translator/LoaderPluginManager.php b/lib/Zend/I18n/Translator/LoaderPluginManager.php new file mode 100644 index 0000000000000000000000000000000000000000..437e906477e535663b8574a156cd15aa23884b16 --- /dev/null +++ b/lib/Zend/I18n/Translator/LoaderPluginManager.php @@ -0,0 +1,62 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_I18n + */ + +namespace Zend\I18n\Translator; + +use Zend\I18n\Exception; +use Zend\ServiceManager\AbstractPluginManager; + +/** + * Plugin manager implementation for translation loaders. + * + * Enforces that loaders retrieved are either instances of + * Loader\FileLoaderInterface or Loader\RemoteLoaderInterface. Additionally, + * it registers a number of default loaders. + * + * @category Zend + * @package Zend_I18n + * @subpackage Translator + */ +class LoaderPluginManager extends AbstractPluginManager +{ + /** + * Default set of loaders. + * + * @var array + */ + protected $invokableClasses = array( + 'phparray' => 'Zend\I18n\Translator\Loader\PhpArray', + 'gettext' => 'Zend\I18n\Translator\Loader\Gettext', + ); + + /** + * Validate the plugin. + * + * Checks that the filter loaded is an instance of + * Loader\FileLoaderInterface or Loader\RemoteLoaderInterface. + * + * @param mixed $plugin + * @return void + * @throws Exception\RuntimeException if invalid + */ + public function validatePlugin($plugin) + { + if ($plugin instanceof Loader\FileLoaderInterface || $plugin instanceof Loader\RemoteLoaderInterface) { + // we're okay + return; + } + + throw new Exception\RuntimeException(sprintf( + 'Plugin of type %s is invalid; must implement %s\Loader\FileLoaderInterface or %s\Loader\RemoteLoaderInterface', + (is_object($plugin) ? get_class($plugin) : gettype($plugin)), + __NAMESPACE__ + )); + } +} diff --git a/lib/Zend/I18n/Translator/Plural/Parser.php b/lib/Zend/I18n/Translator/Plural/Parser.php new file mode 100644 index 0000000000000000000000000000000000000000..7ee947188c15af1f2f2efb10635dd47391d6a39f --- /dev/null +++ b/lib/Zend/I18n/Translator/Plural/Parser.php @@ -0,0 +1,370 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_I18n + */ + +namespace Zend\I18n\Translator\Plural; + +use Zend\I18n\Exception; + +/** + * Plural rule parser. + * + * This plural rule parser is implemented after the article "Top Down Operator + * Precedence" described in <http://javascript.crockford.com/tdop/tdop.html>. + * + * @category Zend + * @package Zend_I18n + * @subpackage Translator + */ +class Parser +{ + /** + * String to parse. + * + * @var string + */ + protected $string; + + /** + * Current lexer position in the string. + * + * @var integer + */ + protected $currentPos; + + /** + * Current token. + * + * @var Symbol + */ + protected $currentToken; + + /** + * Table of symbols. + * + * @var array + */ + protected $symbolTable = array(); + + /** + * Create a new plural parser. + * + */ + public function __construct() + { + $this->populateSymbolTable(); + } + + /** + * Populate the symbol table. + * + * @return void + */ + protected function populateSymbolTable() + { + // Ternary operators + $this->registerSymbol('?', 20)->setLeftDenotationGetter( + function (Symbol $self, Symbol $left) { + $self->first = $left; + $self->second = $self->parser->expression(); + $self->parser->advance(':'); + $self->third = $self->parser->expression(); + return $self; + } + ); + $this->registerSymbol(':'); + + // Boolean operators + $this->registerLeftInfixSymbol('||', 30); + $this->registerLeftInfixSymbol('&&', 40); + + // Equal operators + $this->registerLeftInfixSymbol('==', 50); + $this->registerLeftInfixSymbol('!=', 50); + + // Compare operators + $this->registerLeftInfixSymbol('>', 50); + $this->registerLeftInfixSymbol('<', 50); + $this->registerLeftInfixSymbol('>=', 50); + $this->registerLeftInfixSymbol('<=', 50); + + // Add operators + $this->registerLeftInfixSymbol('-', 60); + $this->registerLeftInfixSymbol('+', 60); + + // Multiply operators + $this->registerLeftInfixSymbol('*', 70); + $this->registerLeftInfixSymbol('/', 70); + $this->registerLeftInfixSymbol('%', 70); + + // Not operator + $this->registerPrefixSymbol('!', 80); + + // Literals + $this->registerSymbol('n')->setNullDenotationGetter( + function (Symbol $self) { + return $self; + } + ); + $this->registerSymbol('number')->setNullDenotationGetter( + function (Symbol $self) { + return $self; + } + ); + + // Parentheses + $this->registerSymbol('(')->setNullDenotationGetter( + function (Symbol $self) { + $expression = $self->parser->expression(); + $self->parser->advance(')'); + return $expression; + } + ); + $this->registerSymbol(')'); + + // Eof + $this->registerSymbol('eof'); + } + + /** + * Register a left infix symbol. + * + * @param string $id + * @param integer $leftBindingPower + * @return void + */ + protected function registerLeftInfixSymbol($id, $leftBindingPower) + { + $this->registerSymbol($id, $leftBindingPower)->setLeftDenotationGetter( + function (Symbol $self, Symbol $left) use ($leftBindingPower) { + $self->first = $left; + $self->second = $self->parser->expression($leftBindingPower); + return $self; + } + ); + } + + /** + * Register a right infix symbol. + * + * @param string $id + * @param integer $leftBindingPower + * @return void + */ + protected function registerRightInfixSymbol($id, $leftBindingPower) + { + $this->registerSymbol($id, $leftBindingPower)->setLeftDenotationGetter( + function (Symbol $self, Symbol $left) use ($leftBindingPower) { + $self->first = $left; + $self->second = $self->parser->expression($leftBindingPower - 1); + return $self; + } + ); + } + + /** + * Register a prefix symbol. + * + * @param string $id + * @param integer $leftBindingPower + * @return void + */ + protected function registerPrefixSymbol($id, $leftBindingPower) + { + $this->registerSymbol($id, $leftBindingPower)->setNullDenotationGetter( + function (Symbol $self) use ($leftBindingPower) { + $self->first = $self->parser->expression($leftBindingPower); + $self->second = null; + return $self; + } + ); + } + + /** + * Register a symbol. + * + * @param string $id + * @param integer $leftBindingPower + * @return Symbol + */ + protected function registerSymbol($id, $leftBindingPower = 0) + { + if (isset($this->symbolTable[$id])) { + $symbol = $this->symbolTable[$id]; + $symbol->leftBindingPower = max( + $symbol->leftBindingPower, + $leftBindingPower + ); + } else { + $symbol = new Symbol($this, $id, $leftBindingPower); + $this->symbolTable[$id] = $symbol; + } + + return $symbol; + } + + /** + * Get a new symbol. + * + * @param string $id + */ + protected function getSymbol($id) + { + if (!isset($this->symbolTable[$id])) { + // Unkown symbol exception + } + + return clone $this->symbolTable[$id]; + } + + /** + * Parse a string. + * + * @param string $string + * @return array + */ + public function parse($string) + { + $this->string = $string . "\0"; + $this->currentPos = 0; + $this->currentToken = $this->getNextToken(); + + return $this->expression(); + } + + /** + * Parse an expression. + * + * @param integer $rightBindingPower + * @return Symbol + */ + public function expression($rightBindingPower = 0) + { + $token = $this->currentToken; + $this->currentToken = $this->getNextToken(); + $left = $token->getNullDenotation(); + + while ($rightBindingPower < $this->currentToken->leftBindingPower) { + $token = $this->currentToken; + $this->currentToken = $this->getNextToken(); + $left = $token->getLeftDenotation($left); + } + + return $left; + } + + /** + * Advance the current token and optionally check the old token id. + * + * @param string $id + * @return void + * @throws Exception\ParseException + */ + public function advance($id = null) + { + if ($id !== null && $this->currentToken->id !== $id) { + throw new Exception\ParseException(sprintf( + 'Expected token with id %s but received %s', + $id, $this->currentToken->id + )); + } + + $this->currentToken = $this->getNextToken(); + } + + /** + * Get the next token. + * + * @return array + * @throws Exception\ParseException + */ + protected function getNextToken() + { + while ($this->string[$this->currentPos] === ' ' || $this->string[$this->currentPos] === "\t") { + $this->currentPos++; + } + + $result = $this->string[$this->currentPos++]; + $value = null; + + switch ($result) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + while (ctype_digit($this->string[$this->currentPos])) { + $result .= $this->string[$this->currentPos++]; + } + + $id = 'number'; + $value = (int) $result; + break; + + case '=': + case '&': + case '|': + if ($this->string[$this->currentPos] === $result) { + $this->currentPos++; + $id = $result . $result; + } else { + // Yield error + } + break; + + case '!': + case '<': + case '>': + if ($this->string[$this->currentPos] === '=') { + $this->currentPos++; + $result .= '='; + } + + $id = $result; + break; + + case '*': + case '/': + case '%': + case '+': + case '-': + case 'n': + case '?': + case ':': + case '(': + case ')': + $id = $result; + break; + + case ';': + case "\n": + case "\0": + $id = 'eof'; + $this->currentPos--; + break; + + default: + throw new Exception\ParseException(sprintf( + 'Found invalid character "%s" in input stream', + $result + )); + break; + } + + $token = $this->getSymbol($id); + $token->value = $value; + + return $token; + } +} diff --git a/lib/Zend/I18n/Translator/Plural/Rule.php b/lib/Zend/I18n/Translator/Plural/Rule.php new file mode 100644 index 0000000000000000000000000000000000000000..05becd5123b7dd9b6b85a5c995e2a6e534941848 --- /dev/null +++ b/lib/Zend/I18n/Translator/Plural/Rule.php @@ -0,0 +1,250 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_I18n + */ + +namespace Zend\I18n\Translator\Plural; + +use Zend\I18n\Exception; + +/** + * Plural rule evaluator. + * + * @category Zend + * @package Zend_I18n + * @subpackage Translator + */ +class Rule +{ + /** + * Parser instance. + * + * @var Parser + */ + protected static $parser; + + /** + * Abstract syntax tree. + * + * @var array + */ + protected $ast; + + /** + * Number of plurals in this rule. + * + * @var integer + */ + protected $numPlurals; + + /** + * Create a new plural rule. + * + * @param integer $numPlurals + * @param array $ast + * @return Rule + */ + protected function __construct($numPlurals, array $ast) + { + $this->numPlurals = $numPlurals; + $this->ast = $ast; + } + + /** + * Evaluate a number and return the plural index. + * + * @param integer $number + * @return integer + * @throws Exception\RangeException + */ + public function evaluate($number) + { + $result = $this->evaluateAstPart($this->ast, abs((int) $number)); + + if ($result < 0 || $result >= $this->numPlurals) { + throw new Exception\RangeException(sprintf( + 'Calculated result %s is between 0 and %d', + $result, ($this->numPlurals - 1) + )); + } + + return $result; + } + + /** + * Evaluate a part of an ast. + * + * @param array $ast + * @param integer $number + * @return integer + * @throws Exception\ParseException + */ + protected function evaluateAstPart(array $ast, $number) + { + switch ($ast['id']) { + case 'number': + return $ast['arguments'][0]; + + case 'n': + return $number; + + case '+': + return $this->evaluateAstPart($ast['arguments'][0], $number) + + $this->evaluateAstPart($ast['arguments'][1], $number); + + case '-': + return $this->evaluateAstPart($ast['arguments'][0], $number) + - $this->evaluateAstPart($ast['arguments'][1], $number); + + case '/': + // Integer division + return floor( + $this->evaluateAstPart($ast['arguments'][0], $number) + / $this->evaluateAstPart($ast['arguments'][1], $number) + ); + + case '*': + return $this->evaluateAstPart($ast['arguments'][0], $number) + * $this->evaluateAstPart($ast['arguments'][1], $number); + + case '%': + return $this->evaluateAstPart($ast['arguments'][0], $number) + % $this->evaluateAstPart($ast['arguments'][1], $number); + + case '>': + return $this->evaluateAstPart($ast['arguments'][0], $number) + > $this->evaluateAstPart($ast['arguments'][1], $number) + ? 1 : 0; + + case '>=': + return $this->evaluateAstPart($ast['arguments'][0], $number) + >= $this->evaluateAstPart($ast['arguments'][1], $number) + ? 1 : 0; + + case '<': + return $this->evaluateAstPart($ast['arguments'][0], $number) + < $this->evaluateAstPart($ast['arguments'][1], $number) + ? 1 : 0; + + case '<=': + return $this->evaluateAstPart($ast['arguments'][0], $number) + <= $this->evaluateAstPart($ast['arguments'][1], $number) + ? 1 : 0; + + case '==': + return $this->evaluateAstPart($ast['arguments'][0], $number) + == $this->evaluateAstPart($ast['arguments'][1], $number) + ? 1 : 0; + + case '!=': + return $this->evaluateAstPart($ast['arguments'][0], $number) + != $this->evaluateAstPart($ast['arguments'][1], $number) + ? 1 : 0; + + case '&&': + return $this->evaluateAstPart($ast['arguments'][0], $number) + && $this->evaluateAstPart($ast['arguments'][1], $number) + ? 1 : 0; + + case '||': + return $this->evaluateAstPart($ast['arguments'][0], $number) + || $this->evaluateAstPart($ast['arguments'][1], $number) + ? 1 : 0; + + case '!': + return !$this->evaluateAstPart($ast['arguments'][0], $number) + ? 1 : 0; + + case '?': + return $this->evaluateAstPart($ast['arguments'][0], $number) + ? $this->evaluateAstPart($ast['arguments'][1], $number) + : $this->evaluateAstPart($ast['arguments'][2], $number); + + default: + throw new Exception\ParseException(sprintf( + 'Unknown token: %s', + $ast['id'] + )); + } + } + + /** + * Create a new rule from a string. + * + * @param string $string + * @throws Exception\ParseException + * @return Rule + */ + public static function fromString($string) + { + if (self::$parser === null) { + self::$parser = new Parser(); + } + + if (!preg_match('(nplurals=(?P<nplurals>\d+))', $string, $match)) { + throw new Exception\ParseException(sprintf( + 'Unknown or invalid parser rule: %s', + $string + )); + } + + $numPlurals = (int) $match['nplurals']; + + if (!preg_match('(plural=(?P<plural>[^;\n]+))', $string, $match)) { + throw new Exception\ParseException(sprintf( + 'Unknown or invalid parser rule: %s', + $string + )); + } + + $tree = self::$parser->parse($match['plural']); + $ast = self::createAst($tree); + + return new self($numPlurals, $ast); + } + + /** + * Create an AST from a tree. + * + * Theoretically we could just use the given Symbol, but that one is not + * so easy to serialize and also takes up more memory. + * + * @param Symbol $symbol + * @return array + */ + protected static function createAst(Symbol $symbol) + { + $ast = array('id' => $symbol->id, 'arguments' => array()); + + switch ($symbol->id) { + case 'n': + break; + + case 'number': + $ast['arguments'][] = $symbol->value; + break; + + case '!': + $ast['arguments'][] = self::createAst($symbol->first); + break; + + case '?': + $ast['arguments'][] = self::createAst($symbol->first); + $ast['arguments'][] = self::createAst($symbol->second); + $ast['arguments'][] = self::createAst($symbol->third); + break; + + default: + $ast['arguments'][] = self::createAst($symbol->first); + $ast['arguments'][] = self::createAst($symbol->second); + break; + } + + return $ast; + } +} diff --git a/lib/Zend/I18n/Translator/Plural/Symbol.php b/lib/Zend/I18n/Translator/Plural/Symbol.php new file mode 100644 index 0000000000000000000000000000000000000000..65b01a088461c2b8ef787294f6980079703e08c4 --- /dev/null +++ b/lib/Zend/I18n/Translator/Plural/Symbol.php @@ -0,0 +1,169 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_I18n + */ + +namespace Zend\I18n\Translator\Plural; + +use Closure; +use Zend\I18n\Exception; + +/** + * Parser symbol. + * + * All properties in the symbol are defined as public for easier and faster + * access from the applied closures. An exception are the closure properties + * themselves, as they have to be accessed via the appropriate getter and + * setter methods. + * + * @category Zend + * @package Zend_I18n + * @subpackage Translator + */ +class Symbol +{ + /** + * Parser instance. + * + * @var Parser + */ + public $parser; + + /** + * Node or token type name. + * + * @var string + */ + public $id; + + /** + * Left binding power (precedence). + * + * @var integer + */ + public $leftBindingPower; + + /** + * Getter for null denotation. + * + * @var callable + */ + protected $nullDenotationGetter; + + /** + * Getter for left denotation. + * + * @var callable + */ + protected $leftDenotationGetter; + + /** + * Value used by literals. + * + * @var mixed + */ + public $value; + + /** + * First node value. + * + * @var Symbol + */ + public $first; + + /** + * Second node value. + * + * @var Symbol + */ + public $second; + + /** + * Third node value. + * + * @var Symbol + */ + public $third; + + /** + * Create a new symbol. + * + * @param Parser $parser + * @param string $id + * @param integer $leftBindingPower + */ + public function __construct(Parser $parser, $id, $leftBindingPower) + { + $this->parser = $parser; + $this->id = $id; + $this->leftBindingPower = $leftBindingPower; + } + + /** + * Set the null denotation getter. + * + * @param Closure $getter + * @return Symbol + */ + public function setNullDenotationGetter(Closure $getter) + { + $this->nullDenotationGetter = $getter; + return $this; + } + + /** + * Set the left denotation getter. + * + * @param Closure $getter + * @return Symbol + */ + public function setLeftDenotationGetter(Closure $getter) + { + $this->leftDenotationGetter = $getter; + return $this; + } + + /** + * Get null denotation. + * + * @throws Exception\ParseException + * @return Symbol + */ + public function getNullDenotation() + { + if ($this->nullDenotationGetter === null) { + throw new Exception\ParseException(sprintf( + 'Syntax error: %s', $this->id + )); + } + + /** @var callable $function */ + $function = $this->nullDenotationGetter; + return $function($this); + } + + /** + * Get left denotation. + * + * @param Symbol $left + * @throws Exception\ParseException + * @return Symbol + */ + public function getLeftDenotation($left) + { + if ($this->leftDenotationGetter === null) { + throw new Exception\ParseException(sprintf( + 'Unknown operator: %s', $this->id + )); + } + + /** @var callable $function */ + $function = $this->leftDenotationGetter; + return $function($this, $left); + } +} diff --git a/lib/Zend/I18n/Translator/TextDomain.php b/lib/Zend/I18n/Translator/TextDomain.php new file mode 100644 index 0000000000000000000000000000000000000000..c2c34cf3488aad137d39a9847fcfc50045383d8f --- /dev/null +++ b/lib/Zend/I18n/Translator/TextDomain.php @@ -0,0 +1,59 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_I18n + */ + +namespace Zend\I18n\Translator; + +use ArrayObject; +use Zend\I18n\Translator\Plural\Rule as PluralRule; + +/** + * Text domain. + * + * @category Zend + * @package Zend_I18n + * @subpackage Translator + */ +class TextDomain extends ArrayObject +{ + /** + * Plural rule. + * + * @var PluralRule + */ + protected $pluralRule; + + /** + * Set the plural rule + * + * @param PluralRule $rule + * @return TextDomain + */ + public function setPluralRule(PluralRule $rule) + { + $this->pluralRule = $rule; + return $this; + } + + /** + * Get the plural rule. + * + * Lazy loads a default rule if none already registered + * + * @return PluralRule + */ + public function getPluralRule() + { + if ($this->pluralRule === null) { + $this->setPluralRule(PluralRule::fromString('nplurals=2; plural=n==1')); + } + + return $this->pluralRule; + } +} diff --git a/lib/Zend/I18n/Translator/Translator.php b/lib/Zend/I18n/Translator/Translator.php new file mode 100644 index 0000000000000000000000000000000000000000..8e35c5ec9c938bb8c34f87af4be8876e509f74f3 --- /dev/null +++ b/lib/Zend/I18n/Translator/Translator.php @@ -0,0 +1,565 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_I18n + */ + +namespace Zend\I18n\Translator; + +use Locale; +use Traversable; +use Zend\Cache; +use Zend\Cache\Storage\StorageInterface as CacheStorage; +use Zend\I18n\Exception; +use Zend\I18n\Translator\Loader\FileLoaderInterface; +use Zend\I18n\Translator\Loader\RemoteLoaderInterface; +use Zend\Stdlib\ArrayUtils; + +/** + * Translator. + * + * @category Zend + * @package Zend_I18n + * @subpackage Translator + */ +class Translator +{ + /** + * Messages loaded by the translator. + * + * @var array + */ + protected $messages = array(); + + /** + * Files used for loading messages. + * + * @var array + */ + protected $files = array(); + + /** + * Patterns used for loading messages. + * + * @var array + */ + protected $patterns = array(); + + /** + * Remote locations for loading messages. + * + * @var array + */ + protected $remote = array(); + + /** + * Default locale. + * + * @var string + */ + protected $locale; + + /** + * Locale to use as fallback if there is no translation. + * + * @var string + */ + protected $fallbackLocale; + + /** + * Translation cache. + * + * @var CacheStorage + */ + protected $cache; + + /** + * Plugin manager for translation loaders. + * + * @var LoaderPluginManager + */ + protected $pluginManager; + + /** + * Instantiate a translator + * + * @param array|Traversable $options + * @return Translator + * @throws Exception\InvalidArgumentException + */ + public static function factory($options) + { + if ($options instanceof Traversable) { + $options = ArrayUtils::iteratorToArray($options); + } elseif (!is_array($options)) { + throw new Exception\InvalidArgumentException(sprintf( + '%s expects an array or Traversable object; received "%s"', + __METHOD__, + (is_object($options) ? get_class($options) : gettype($options)) + )); + } + + $translator = new static(); + + // locales + if (isset($options['locale'])) { + $locales = (array) $options['locale']; + $translator->setLocale(array_shift($locales)); + if (count($locales) > 0) { + $translator->setFallbackLocale(array_shift($locales)); + } + } + + // file patterns + if (isset($options['translation_file_patterns'])) { + if (!is_array($options['translation_file_patterns'])) { + throw new Exception\InvalidArgumentException( + '"translation_file_patterns" should be an array' + ); + } + + $requiredKeys = array('type', 'base_dir', 'pattern'); + foreach ($options['translation_file_patterns'] as $pattern) { + foreach ($requiredKeys as $key) { + if (!isset($pattern[$key])) { + throw new Exception\InvalidArgumentException( + "'{$key}' is missing for translation pattern options" + ); + } + } + + $translator->addTranslationFilePattern( + $pattern['type'], + $pattern['base_dir'], + $pattern['pattern'], + isset($pattern['text_domain']) ? $pattern['text_domain'] : 'default' + ); + } + } + + // files + if (isset($options['translation_files'])) { + if (!is_array($options['translation_files'])) { + throw new Exception\InvalidArgumentException( + '"translation_files" should be an array' + ); + } + + $requiredKeys = array('type', 'filename'); + foreach ($options['translation_files'] as $file) { + foreach ($requiredKeys as $key) { + if (!isset($file[$key])) { + throw new Exception\InvalidArgumentException( + "'{$key}' is missing for translation file options" + ); + } + } + + $translator->addTranslationFile( + $file['type'], + $file['filename'], + isset($file['text_domain']) ? $file['text_domain'] : 'default', + isset($file['locale']) ? $file['locale'] : null + ); + } + } + + // remote + if (isset($options['remote_translation'])) { + if (!is_array($options['remote_translation'])) { + throw new Exception\InvalidArgumentException( + '"remote_translation" should be an array' + ); + } + + $requiredKeys = array('type'); + foreach ($options['remote_translation'] as $remote) { + foreach ($requiredKeys as $key) { + if (!isset($remote[$key])) { + throw new Exception\InvalidArgumentException( + "'{$key}' is missing for remote translation options" + ); + } + } + + $translator->addRemoteTranslations( + $remote['type'], + isset($remote['text_domain']) ? $remote['text_domain'] : 'default' + ); + } + } + + // cache + if (isset($options['cache'])) { + if ($options['cache'] instanceof CacheStorage) { + $translator->setCache($options['cache']); + } else { + $translator->setCache(Cache\StorageFactory::factory($options['cache'])); + } + } + + return $translator; + } + + /** + * Set the default locale. + * + * @param string $locale + * @return Translator + */ + public function setLocale($locale) + { + $this->locale = $locale; + return $this; + } + + /** + * Get the default locale. + * + * @return string + */ + public function getLocale() + { + if ($this->locale === null) { + $this->locale = Locale::getDefault(); + } + + return $this->locale; + } + + /** + * Set the fallback locale. + * + * @param string $locale + * @return Translator + */ + public function setFallbackLocale($locale) + { + $this->fallbackLocale = $locale; + return $this; + } + + /** + * Get the fallback locale. + * + * @return string + */ + public function getFallbackLocale() + { + return $this->fallbackLocale; + } + + /** + * Sets a cache + * + * @param CacheStorage $cache + * @return Translator + */ + public function setCache(CacheStorage $cache = null) + { + $this->cache = $cache; + return $this; + } + + /** + * Returns the set cache + * + * @return CacheStorage The set cache + */ + public function getCache() + { + return $this->cache; + } + + /** + * Set the plugin manager for translation loaders + * + * @param LoaderPluginManager $pluginManager + * @return Translator + */ + public function setPluginManager(LoaderPluginManager $pluginManager) + { + $this->pluginManager = $pluginManager; + return $this; + } + + /** + * Retrieve the plugin manager for translation loaders. + * + * Lazy loads an instance if none currently set. + * + * @return LoaderPluginManager + */ + public function getPluginManager() + { + if (!$this->pluginManager instanceof LoaderPluginManager) { + $this->setPluginManager(new LoaderPluginManager()); + } + + return $this->pluginManager; + } + + /** + * Translate a message. + * + * @param string $message + * @param string $textDomain + * @param string $locale + * @return string + */ + public function translate($message, $textDomain = 'default', $locale = null) + { + $locale = ($locale ?: $this->getLocale()); + $translation = $this->getTranslatedMessage($message, $locale, $textDomain); + + if ($translation !== null && $translation !== '') { + return $translation; + } + + if (null !== ($fallbackLocale = $this->getFallbackLocale()) + && $locale !== $fallbackLocale + ) { + return $this->translate($message, $textDomain, $fallbackLocale); + } + + return $message; + } + + /** + * Translate a plural message. + * + * @param string $singular + * @param string $plural + * @param int $number + * @param string $textDomain + * @param string|null $locale + * @return string + * @throws Exception\OutOfBoundsException + */ + public function translatePlural( + $singular, + $plural, + $number, + $textDomain = 'default', + $locale = null + ) { + $locale = $locale ?: $this->getLocale(); + $translation = $this->getTranslatedMessage($singular, $locale, $textDomain); + + if ($translation === null || $translation === '') { + if (null !== ($fallbackLocale = $this->getFallbackLocale()) + && $locale !== $fallbackLocale + ) { + return $this->translatePlural( + $singular, + $plural, + $number, + $textDomain, + $fallbackLocale + ); + } + + return ($number == 1 ? $singular : $plural); + } + + $index = $this->messages[$textDomain][$locale] + ->getPluralRule() + ->evaluate($number); + + if (!isset($translation[$index])) { + throw new Exception\OutOfBoundsException(sprintf( + 'Provided index %d does not exist in plural array', $index + )); + } + + return $translation[$index]; + } + + /** + * Get a translated message. + * + * @param string $message + * @param string $locale + * @param string $textDomain + * @return string|null + */ + protected function getTranslatedMessage( + $message, + $locale = null, + $textDomain = 'default' + ) { + if ($message === '') { + return ''; + } + + if (!isset($this->messages[$textDomain][$locale])) { + $this->loadMessages($textDomain, $locale); + } + + if (!isset($this->messages[$textDomain][$locale][$message])) { + return null; + } + + return $this->messages[$textDomain][$locale][$message]; + } + + /** + * Add a translation file. + * + * @param string $type + * @param string $filename + * @param string $textDomain + * @param string $locale + * @return Translator + */ + public function addTranslationFile( + $type, + $filename, + $textDomain = 'default', + $locale = null + ) { + $locale = $locale ?: '*'; + + if (!isset($this->files[$textDomain])) { + $this->files[$textDomain] = array(); + } + + $this->files[$textDomain][$locale] = array( + 'type' => $type, + 'filename' => $filename, + ); + + return $this; + } + + /** + * Add multiple translations with a file pattern. + * + * @param string $type + * @param string $baseDir + * @param string $pattern + * @param string $textDomain + * @return Translator + */ + public function addTranslationFilePattern( + $type, + $baseDir, + $pattern, + $textDomain = 'default' + ) { + if (!isset($this->patterns[$textDomain])) { + $this->patterns[$textDomain] = array(); + } + + $this->patterns[$textDomain][] = array( + 'type' => $type, + 'baseDir' => rtrim($baseDir, '/'), + 'pattern' => $pattern, + ); + + return $this; + } + + /** + * Add remote translations. + * + * @param string $type + * @param string $textDomain + * @return Translator + */ + public function addRemoteTranslations($type, $textDomain = 'default') + { + if (!isset($this->remote[$textDomain])) { + $this->remote[$textDomain] = array(); + } + + $this->remote[$textDomain][] = $type; + + return $this; + } + + /** + * Load messages for a given language and domain. + * + * @param string $textDomain + * @param string $locale + * @throws Exception\RuntimeException + * @return void + */ + protected function loadMessages($textDomain, $locale) + { + if (!isset($this->messages[$textDomain])) { + $this->messages[$textDomain] = array(); + } + + if (null !== ($cache = $this->getCache())) { + $cacheId = 'Zend_I18n_Translator_Messages_' . md5($textDomain . $locale); + + if (null !== ($result = $cache->getItem($cacheId))) { + $this->messages[$textDomain][$locale] = $result; + return; + } + } + + // Try to load from remote sources + if (isset($this->remote[$textDomain])) { + foreach ($this->remote[$textDomain] as $loaderType) { + $loader = $this->getPluginManager()->get($loaderType); + + if (!$loader instanceof RemoteLoaderInterface) { + throw new Exception\RuntimeException('Specified loader is not a remote loader'); + } + + $this->messages[$textDomain][$locale] = $loader->load($locale, $textDomain); + goto cache; + } + } + + // Try to load from pattern + if (isset($this->patterns[$textDomain])) { + foreach ($this->patterns[$textDomain] as $pattern) { + $filename = $pattern['baseDir'] . '/' . sprintf($pattern['pattern'], $locale); + + if (is_file($filename)) { + $loader = $this->getPluginManager()->get($pattern['type']); + + if (!$loader instanceof FileLoaderInterface) { + throw new Exception\RuntimeException('Specified loader is not a file loader'); + } + + $this->messages[$textDomain][$locale] = $loader->load($locale, $filename); + goto cache; + } + } + } + + // Try to load from concrete files + foreach (array($locale, '*') as $currentLocale) { + if (!isset($this->files[$textDomain][$currentLocale])) { + continue; + } + + $file = $this->files[$textDomain][$currentLocale]; + $loader = $this->getPluginManager()->get($file['type']); + + if (!$loader instanceof FileLoaderInterface) { + throw new Exception\RuntimeException('Specified loader is not a file loader'); + } + + $this->messages[$textDomain][$locale] = $loader->load($locale, $file['filename']); + + unset($this->files[$textDomain][$currentLocale]); + goto cache; + } + + // Cache the loaded text domain + cache: + if ($cache !== null) { + $cache->setItem($cacheId, $this->messages[$textDomain][$locale]); + } + } +} diff --git a/lib/Zend/I18n/Translator/TranslatorAwareInterface.php b/lib/Zend/I18n/Translator/TranslatorAwareInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..3427a9a5bfa9daa2e1c45dbb1c0dbd9849d14d26 --- /dev/null +++ b/lib/Zend/I18n/Translator/TranslatorAwareInterface.php @@ -0,0 +1,76 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_View + */ + +namespace Zend\I18n\Translator; + +/** + * @category Zend + * @package Zend_I18n + * @subpackage Translator + */ +interface TranslatorAwareInterface +{ + /** + * Sets translator to use in helper + * + * @param Translator $translator [optional] translator. + * Default is null, which sets no translator. + * @param string $textDomain [optional] text domain + * Default is null, which skips setTranslatorTextDomain + * @return TranslatorAwareInterface + */ + public function setTranslator(Translator $translator = null, $textDomain = null); + + /** + * Returns translator used in object + * + * @return Translator|null + */ + public function getTranslator(); + + /** + * Checks if the object has a translator + * + * @return bool + */ + public function hasTranslator(); + + /** + * Sets whether translator is enabled and should be used + * + * @param bool $enabled [optional] whether translator should be used. + * Default is true. + * @return TranslatorAwareInterface + */ + public function setTranslatorEnabled($enabled = true); + + /** + * Returns whether translator is enabled and should be used + * + * @return bool + */ + public function isTranslatorEnabled(); + + /** + * Set translation text domain + * + * @param string $textDomain + * @return TranslatorAwareInterface + */ + public function setTranslatorTextDomain($textDomain = 'default'); + + /** + * Return the translation text domain + * + * @return string + */ + public function getTranslatorTextDomain(); + +} diff --git a/lib/Zend/I18n/Translator/TranslatorServiceFactory.php b/lib/Zend/I18n/Translator/TranslatorServiceFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..b2cd93a092ecb29c610c49455ebde6e1522b552f --- /dev/null +++ b/lib/Zend/I18n/Translator/TranslatorServiceFactory.php @@ -0,0 +1,33 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_I18n + */ + +namespace Zend\I18n\Translator; + +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; + +/** + * Translator. + * + * @category Zend + * @package Zend_I18n + * @subpackage Translator + */ +class TranslatorServiceFactory implements FactoryInterface +{ + public function createService(ServiceLocatorInterface $serviceLocator) + { + // Configure the translator + $config = $serviceLocator->get('Configuration'); + $trConfig = isset($config['translator']) ? $config['translator'] : array(); + $translator = Translator::factory($trConfig); + return $translator; + } +} diff --git a/lib/Zend/I18n/Validator/Alnum.php b/lib/Zend/I18n/Validator/Alnum.php new file mode 100644 index 0000000000000000000000000000000000000000..ad1dc3d1e1f0f8847336a32a13f84513c9124d72 --- /dev/null +++ b/lib/Zend/I18n/Validator/Alnum.php @@ -0,0 +1,122 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_I18n + */ + +namespace Zend\I18n\Validator; + +use Zend\I18n\Filter\Alnum as AlnumFilter; +use Zend\Validator\AbstractValidator; + +/** + * @category Zend + * @package Zend_Validate + */ +class Alnum extends AbstractValidator +{ + const INVALID = 'alnumInvalid'; + const NOT_ALNUM = 'notAlnum'; + const STRING_EMPTY = 'alnumStringEmpty'; + + /** + * Alphanumeric filter used for validation + * + * @var AlnumFilter + */ + protected static $filter = null; + + /** + * Validation failure message template definitions + * + * @var array + */ + protected $messageTemplates = array( + self::INVALID => "Invalid type given. String, integer or float expected", + self::NOT_ALNUM => "The input contains characters which are non alphabetic and no digits", + self::STRING_EMPTY => "The input is an empty string", + ); + + /** + * Options for this validator + * + * @var array + */ + protected $options = array( + 'allowWhiteSpace' => false, // Whether to allow white space characters; off by default + ); + + /** + * Sets default option values for this instance + * + * @param bool $allowWhiteSpace + */ + public function __construct($allowWhiteSpace = false) + { + $options = is_array($allowWhiteSpace) ? $allowWhiteSpace : null; + parent::__construct($options); + + if (is_scalar($allowWhiteSpace)) { + $this->options['allowWhiteSpace'] = (boolean) $allowWhiteSpace; + } + } + + /** + * Returns the allowWhiteSpace option + * + * @return boolean + */ + public function getAllowWhiteSpace() + { + return $this->options['allowWhiteSpace']; + } + + /** + * Sets the allowWhiteSpace option + * + * @param boolean $allowWhiteSpace + * @return AlnumFilter Provides a fluent interface + */ + public function setAllowWhiteSpace($allowWhiteSpace) + { + $this->options['allowWhiteSpace'] = (boolean) $allowWhiteSpace; + return $this; + } + + /** + * Returns true if and only if $value contains only alphabetic and digit characters + * + * @param string $value + * @return boolean + */ + public function isValid($value) + { + if (!is_string($value) && !is_int($value) && !is_float($value)) { + $this->error(self::INVALID); + return false; + } + + $this->setValue($value); + if ('' === $value) { + $this->error(self::STRING_EMPTY); + return false; + } + + if (null === self::$filter) { + self::$filter = new AlnumFilter(); + } + + self::$filter->setAllowWhiteSpace($this->options['allowWhiteSpace']); + + if ($value != self::$filter->filter($value)) { + $this->error(self::NOT_ALNUM); + return false; + } + + return true; + } +} diff --git a/lib/Zend/I18n/Validator/Alpha.php b/lib/Zend/I18n/Validator/Alpha.php new file mode 100644 index 0000000000000000000000000000000000000000..4dfdd1395f12e366b4e174261b6a35e05beed4e3 --- /dev/null +++ b/lib/Zend/I18n/Validator/Alpha.php @@ -0,0 +1,88 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_I18n + */ + +namespace Zend\I18n\Validator; + +use Zend\I18n\Filter\Alpha as AlphaFilter; +use Zend\Validator\AbstractValidator; + +/** + * @category Zend + * @package Zend_Validate + */ +class Alpha extends Alnum +{ + const INVALID = 'alphaInvalid'; + const NOT_ALPHA = 'notAlpha'; + const STRING_EMPTY = 'alphaStringEmpty'; + + /** + * Alphabetic filter used for validation + * + * @var AlphaFilter + */ + protected static $filter = null; + + /** + * Validation failure message template definitions + * + * @var array + */ + protected $messageTemplates = array( + self::INVALID => "Invalid type given. String expected", + self::NOT_ALPHA => "The input contains non alphabetic characters", + self::STRING_EMPTY => "The input is an empty string" + ); + + /** + * Options for this validator + * + * @var array + */ + protected $options = array( + 'allowWhiteSpace' => false, // Whether to allow white space characters; off by default + ); + + /** + * Returns true if and only if $value contains only alphabetic characters + * + * @param string $value + * @return boolean + */ + public function isValid($value) + { + if (!is_string($value)) { + $this->error(self::INVALID); + return false; + } + + $this->setValue($value); + + if ('' === $value) { + $this->error(self::STRING_EMPTY); + return false; + } + + if (null === self::$filter) { + self::$filter = new AlphaFilter(); + } + + //self::$filter->setAllowWhiteSpace($this->allowWhiteSpace); + self::$filter->setAllowWhiteSpace($this->options['allowWhiteSpace']); + + if ($value !== self::$filter->filter($value)) { + $this->error(self::NOT_ALPHA); + return false; + } + + return true; + } + +} diff --git a/lib/Zend/I18n/Validator/Float.php b/lib/Zend/I18n/Validator/Float.php new file mode 100644 index 0000000000000000000000000000000000000000..010a7d8446fe270049226ea721db6e9f16814b2b --- /dev/null +++ b/lib/Zend/I18n/Validator/Float.php @@ -0,0 +1,139 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_I18n + */ + +namespace Zend\I18n\Validator; + +use Locale; +use NumberFormatter; +use Traversable; +use Zend\Stdlib\ArrayUtils; +use Zend\Validator\AbstractValidator; +use Zend\Validator\Exception; + +/** + * @category Zend + * @package Zend_Validate + */ +class Float extends AbstractValidator +{ + const INVALID = 'floatInvalid'; + const NOT_FLOAT = 'notFloat'; + + /** + * @var array + */ + protected $messageTemplates = array( + self::INVALID => "Invalid type given. String, integer or float expected", + self::NOT_FLOAT => "The input does not appear to be a float", + ); + + /** + * Optional locale + * + * @var string|null + */ + protected $locale; + + /** + * Constructor for the integer validator + * + * @param array|Traversable $options + */ + public function __construct($options = array()) + { + if ($options instanceof Traversable) { + $options = ArrayUtils::iteratorToArray($options); + } + + if (array_key_exists('locale', $options)) { + $this->setLocale($options['locale']); + } + + parent::__construct($options); + } + + /** + * Returns the set locale + * + * @return string + */ + public function getLocale() + { + if (null === $this->locale) { + $this->locale = Locale::getDefault(); + } + return $this->locale; + } + + /** + * Sets the locale to use + * + * @param string|null $locale + * @return Float + */ + public function setLocale($locale) + { + $this->locale = $locale; + return $this; + } + + + /** + * Returns true if and only if $value is a floating-point value + * + * @param string $value + * @return boolean + * @throws Exception\InvalidArgumentException + */ + public function isValid($value) + { + if (!is_string($value) && !is_int($value) && !is_float($value)) { + $this->error(self::INVALID); + return false; + } + + $this->setValue($value); + + if (is_float($value)) { + return true; + } + + $locale = $this->getLocale(); + $format = new NumberFormatter($locale, NumberFormatter::DECIMAL); + if (intl_is_failure($format->getErrorCode())) { + throw new Exception\InvalidArgumentException("Invalid locale string given"); + } + + $parsedFloat = $format->parse($value, NumberFormatter::TYPE_DOUBLE); + if (intl_is_failure($format->getErrorCode())) { + $this->error(self::NOT_FLOAT); + return false; + } + + $decimalSep = $format->getSymbol(NumberFormatter::DECIMAL_SEPARATOR_SYMBOL); + $groupingSep = $format->getSymbol(NumberFormatter::GROUPING_SEPARATOR_SYMBOL); + + $valueFiltered = str_replace($groupingSep, '', $value); + $valueFiltered = str_replace($decimalSep, '.', $valueFiltered); + + while (strpos($valueFiltered, '.') !== false + && (substr($valueFiltered, -1) == '0' || substr($valueFiltered, -1) == '.') + ) { + $valueFiltered = substr($valueFiltered, 0, strlen($valueFiltered) - 1); + } + + if (strval($parsedFloat) !== $valueFiltered) { + $this->error(self::NOT_FLOAT); + return false; + } + + return true; + } +} diff --git a/lib/Zend/I18n/Validator/Int.php b/lib/Zend/I18n/Validator/Int.php new file mode 100644 index 0000000000000000000000000000000000000000..83a2f91db997edfb2a3a7532a548e085ebc657a5 --- /dev/null +++ b/lib/Zend/I18n/Validator/Int.php @@ -0,0 +1,130 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_I18n + */ + +namespace Zend\I18n\Validator; + +use Locale; +use NumberFormatter; +use Traversable; +use Zend\Stdlib\ArrayUtils; +use Zend\Validator\AbstractValidator; +use Zend\Validator\Exception; + +/** + * @category Zend + * @package Zend_Validate + */ +class Int extends AbstractValidator +{ + const INVALID = 'intInvalid'; + const NOT_INT = 'notInt'; + + /** + * @var array + */ + protected $messageTemplates = array( + self::INVALID => "Invalid type given. String or integer expected", + self::NOT_INT => "The input does not appear to be an integer", + ); + + /** + * Optional locale + * + * @var string|null + */ + protected $locale; + + /** + * Constructor for the integer validator + * + * @param array|Traversable $options + */ + public function __construct($options = array()) + { + if ($options instanceof Traversable) { + $options = ArrayUtils::iteratorToArray($options); + } + + if (array_key_exists('locale', $options)) { + $this->setLocale($options['locale']); + } + + parent::__construct($options); + } + + /** + * Returns the set locale + */ + public function getLocale() + { + if (null === $this->locale) { + $this->locale = Locale::getDefault(); + } + return $this->locale; + } + + /** + * Sets the locale to use + * + * @param string $locale + * @return Int + */ + public function setLocale($locale) + { + $this->locale = $locale; + return $this; + } + + /** + * Returns true if and only if $value is a valid integer + * + * @param string|integer $value + * @return boolean + * @throws Exception\InvalidArgumentException + */ + public function isValid($value) + { + if (!is_string($value) && !is_int($value) && !is_float($value)) { + $this->error(self::INVALID); + return false; + } + + if (is_int($value)) { + return true; + } + + $this->setValue($value); + + $locale = $this->getLocale(); + $format = new NumberFormatter($locale, NumberFormatter::DECIMAL); + if (intl_is_failure($format->getErrorCode())) { + throw new Exception\InvalidArgumentException("Invalid locale string given"); + } + + $parsedInt = $format->parse($value, NumberFormatter::TYPE_INT64); + if (intl_is_failure($format->getErrorCode())) { + $this->error(self::NOT_INT); + return false; + } + + $decimalSep = $format->getSymbol(NumberFormatter::DECIMAL_SEPARATOR_SYMBOL); + $groupingSep = $format->getSymbol(NumberFormatter::GROUPING_SEPARATOR_SYMBOL); + + $valueFiltered = str_replace($groupingSep, '', $value); + $valueFiltered = str_replace($decimalSep, '.', $valueFiltered); + + if (strval($parsedInt) !== $valueFiltered) { + $this->error(self::NOT_INT); + return false; + } + + return true; + } +} diff --git a/lib/Zend/I18n/Validator/PostCode.php b/lib/Zend/I18n/Validator/PostCode.php new file mode 100644 index 0000000000000000000000000000000000000000..0f4dfa34e8c56d62d929b6969ea775c5e26a794a --- /dev/null +++ b/lib/Zend/I18n/Validator/PostCode.php @@ -0,0 +1,389 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_I18n + */ + +namespace Zend\I18n\Validator; + +use Locale; +use Traversable; +use Zend\Stdlib\ArrayUtils; +use Zend\Validator\AbstractValidator; +use Zend\Validator\Callback; +use Zend\Validator\Exception; + +/** + * @category Zend + * @package Zend_Validate + */ +class PostCode extends AbstractValidator +{ + const INVALID = 'postcodeInvalid'; + const NO_MATCH = 'postcodeNoMatch'; + const SERVICE = 'postcodeService'; + const SERVICEFAILURE = 'postcodeServiceFailure'; + + /** + * @var array + */ + protected $messageTemplates = array( + self::INVALID => "Invalid type given. String or integer expected", + self::NO_MATCH => "The input does not appear to be a postal code", + self::SERVICE => "The input does not appear to be a postal code", + self::SERVICEFAILURE => "An exception has been raised while validating the input", + ); + + /** + * Optional Locale to use + * + * @var string|null + */ + protected $locale; + + /** + * Optional Manual postal code format + * + * @var string|null + */ + protected $format; + + /** + * Optional Service callback for additional validation + * + * @var mixed|null + */ + protected $service; + + /** + * Postal Code regexes by territory + * + * @var array + */ + protected static $postCodeRegex = array( + 'GB' => 'GIR[ ]?0AA|((AB|AL|B|BA|BB|BD|BH|BL|BN|BR|BS|BT|CA|CB|CF|CH|CM|CO|CR|CT|CV|CW|DA|DD|DE|DG|DH|DL|DN|DT|DY|E|EC|EH|EN|EX|FK|FY|G|GL|GY|GU|HA|HD|HG|HP|HR|HS|HU|HX|IG|IM|IP|IV|JE|KA|KT|KW|KY|L|LA|LD|LE|LL|LN|LS|LU|M|ME|MK|ML|N|NE|NG|NN|NP|NR|NW|OL|OX|PA|PE|PH|PL|PO|PR|RG|RH|RM|S|SA|SE|SG|SK|SL|SM|SN|SO|SP|SR|SS|ST|SW|SY|TA|TD|TF|TN|TQ|TR|TS|TW|UB|W|WA|WC|WD|WF|WN|WR|WS|WV|YO|ZE)(\d[\dA-Z]?[ ]?\d[ABD-HJLN-UW-Z]{2}))|BFPO[ ]?\d{1,4}', + 'JE' => 'JE\d[\dA-Z]?[ ]?\d[ABD-HJLN-UW-Z]{2}', + 'GG' => 'GY\d[\dA-Z]?[ ]?\d[ABD-HJLN-UW-Z]{2}', + 'IM' => 'IM\d[\dA-Z]?[ ]?\d[ABD-HJLN-UW-Z]{2}', + 'US' => '\d{5}([ \-]\d{4})?', + 'CA' => '[ABCEGHJKLMNPRSTVXY]\d[ABCEGHJ-NPRSTV-Z][ ]?\d[ABCEGHJ-NPRSTV-Z]\d', + 'DE' => '\d{5}', + 'JP' => '\d{3}-\d{4}', + 'FR' => '\d{2}[ ]?\d{3}', + 'AU' => '\d{4}', + 'IT' => '\d{5}', + 'CH' => '\d{4}', + 'AT' => '\d{4}', + 'ES' => '\d{5}', + 'NL' => '\d{4}[ ]?[A-Z]{2}', + 'BE' => '\d{4}', + 'DK' => '\d{4}', + 'SE' => '\d{3}[ ]?\d{2}', + 'NO' => '\d{4}', + 'BR' => '\d{5}[\-]?\d{3}', + 'PT' => '\d{4}([\-]\d{3})?', + 'FI' => '\d{5}', + 'AX' => '22\d{3}', + 'KR' => '\d{3}[\-]\d{3}', + 'CN' => '\d{6}', + 'TW' => '\d{3}(\d{2})?', + 'SG' => '\d{6}', + 'DZ' => '\d{5}', + 'AD' => 'AD\d{3}', + 'AR' => '([A-HJ-NP-Z])?\d{4}([A-Z]{3})?', + 'AM' => '(37)?\d{4}', + 'AZ' => '\d{4}', + 'BH' => '((1[0-2]|[2-9])\d{2})?', + 'BD' => '\d{4}', + 'BB' => '(BB\d{5})?', + 'BY' => '\d{6}', + 'BM' => '[A-Z]{2}[ ]?[A-Z0-9]{2}', + 'BA' => '\d{5}', + 'IO' => 'BBND 1ZZ', + 'BN' => '[A-Z]{2}[ ]?\d{4}', + 'BG' => '\d{4}', + 'KH' => '\d{5}', + 'CV' => '\d{4}', + 'CL' => '\d{7}', + 'CR' => '\d{4,5}|\d{3}-\d{4}', + 'HR' => '\d{5}', + 'CY' => '\d{4}', + 'CZ' => '\d{3}[ ]?\d{2}', + 'DO' => '\d{5}', + 'EC' => '([A-Z]\d{4}[A-Z]|(?:[A-Z]{2})?\d{6})?', + 'EG' => '\d{5}', + 'EE' => '\d{5}', + 'FO' => '\d{3}', + 'GE' => '\d{4}', + 'GR' => '\d{3}[ ]?\d{2}', + 'GL' => '39\d{2}', + 'GT' => '\d{5}', + 'HT' => '\d{4}', + 'HN' => '(?:\d{5})?', + 'HU' => '\d{4}', + 'IS' => '\d{3}', + 'IN' => '\d{6}', + 'ID' => '\d{5}', + 'IE' => '((D|DUBLIN)?([1-9]|6[wW]|1[0-8]|2[024]))?', + 'IL' => '\d{5}', + 'JO' => '\d{5}', + 'KZ' => '\d{6}', + 'KE' => '\d{5}', + 'KW' => '\d{5}', + 'LA' => '\d{5}', + 'LV' => '\d{4}', + 'LB' => '(\d{4}([ ]?\d{4})?)?', + 'LI' => '(948[5-9])|(949[0-7])', + 'LT' => '\d{5}', + 'LU' => '\d{4}', + 'MK' => '\d{4}', + 'MY' => '\d{5}', + 'MV' => '\d{5}', + 'MT' => '[A-Z]{3}[ ]?\d{2,4}', + 'MU' => '(\d{3}[A-Z]{2}\d{3})?', + 'MX' => '\d{5}', + 'MD' => '\d{4}', + 'MC' => '980\d{2}', + 'MA' => '\d{5}', + 'NP' => '\d{5}', + 'NZ' => '\d{4}', + 'NI' => '((\d{4}-)?\d{3}-\d{3}(-\d{1})?)?', + 'NG' => '(\d{6})?', + 'OM' => '(PC )?\d{3}', + 'PK' => '\d{5}', + 'PY' => '\d{4}', + 'PH' => '\d{4}', + 'PL' => '\d{2}-\d{3}', + 'PR' => '00[679]\d{2}([ \-]\d{4})?', + 'RO' => '\d{6}', + 'RU' => '\d{6}', + 'SM' => '4789\d', + 'SA' => '\d{5}', + 'SN' => '\d{5}', + 'SK' => '\d{3}[ ]?\d{2}', + 'SI' => '\d{4}', + 'ZA' => '\d{4}', + 'LK' => '\d{5}', + 'TJ' => '\d{6}', + 'TH' => '\d{5}', + 'TN' => '\d{4}', + 'TR' => '\d{5}', + 'TM' => '\d{6}', + 'UA' => '\d{5}', + 'UY' => '\d{5}', + 'UZ' => '\d{6}', + 'VA' => '00120', + 'VE' => '\d{4}', + 'ZM' => '\d{5}', + 'AS' => '96799', + 'CC' => '6799', + 'CK' => '\d{4}', + 'RS' => '\d{6}', + 'ME' => '8\d{4}', + 'CS' => '\d{5}', + 'YU' => '\d{5}', + 'CX' => '6798', + 'ET' => '\d{4}', + 'FK' => 'FIQQ 1ZZ', + 'NF' => '2899', + 'FM' => '(9694[1-4])([ \-]\d{4})?', + 'GF' => '9[78]3\d{2}', + 'GN' => '\d{3}', + 'GP' => '9[78][01]\d{2}', + 'GS' => 'SIQQ 1ZZ', + 'GU' => '969[123]\d([ \-]\d{4})?', + 'GW' => '\d{4}', + 'HM' => '\d{4}', + 'IQ' => '\d{5}', + 'KG' => '\d{6}', + 'LR' => '\d{4}', + 'LS' => '\d{3}', + 'MG' => '\d{3}', + 'MH' => '969[67]\d([ \-]\d{4})?', + 'MN' => '\d{6}', + 'MP' => '9695[012]([ \-]\d{4})?', + 'MQ' => '9[78]2\d{2}', + 'NC' => '988\d{2}', + 'NE' => '\d{4}', + 'VI' => '008(([0-4]\d)|(5[01]))([ \-]\d{4})?', + 'PF' => '987\d{2}', + 'PG' => '\d{3}', + 'PM' => '9[78]5\d{2}', + 'PN' => 'PCRN 1ZZ', + 'PW' => '96940', + 'RE' => '9[78]4\d{2}', + 'SH' => '(ASCN|STHL) 1ZZ', + 'SJ' => '\d{4}', + 'SO' => '\d{5}', + 'SZ' => '[HLMS]\d{3}', + 'TC' => 'TKCA 1ZZ', + 'WF' => '986\d{2}', + 'YT' => '976\d{2}', + ); + + /** + * Constructor for the PostCode validator + * + * Accepts a string locale and/or "format". + * + * @param array|Traversable $options + */ + public function __construct($options = array()) + { + if ($options instanceof Traversable) { + $options = ArrayUtils::iteratorToArray($options); + } + + if (array_key_exists('locale', $options)) { + $this->setLocale($options['locale']); + } else { + $this->setLocale(Locale::getDefault()); + } + if (array_key_exists('format', $options)) { + $this->setFormat($options['format']); + } + if (array_key_exists('service', $options)) { + $this->setService($options['service']); + } + + parent::__construct($options); + } + + /** + * Returns the set locale + * + * @return string|null The set locale + */ + public function getLocale() + { + return $this->locale; + } + + /** + * Sets the locale to use + * + * @param string|null $locale + * @return PostCode Provides fluid interface + */ + public function setLocale($locale) + { + $this->locale = $locale; + return $this; + } + + /** + * Returns the set postal code format + * + * @return string|null + */ + public function getFormat() + { + return $this->format; + } + + /** + * Sets a self defined postal format as regex + * + * @param string $format + * @return PostCode Provides fluid interface + */ + public function setFormat($format) + { + $this->format = $format; + return $this; + } + + /** + * Returns the actual set service + * + * @return mixed|null + */ + public function getService() + { + return $this->service; + } + + /** + * Sets a new callback for service validation + * + * @param mixed $service + * @return PostCode Provides fluid interface + */ + public function setService($service) + { + $this->service = $service; + return $this; + } + + /** + * Returns true if and only if $value is a valid postalcode + * + * @param string $value + * @return boolean + * @throws Exception\InvalidArgumentException + */ + public function isValid($value) + { + if (!is_string($value) && !is_int($value)) { + $this->error(self::INVALID); + return false; + } + + $this->setValue($value); + + $service = $this->getService(); + $locale = $this->getLocale(); + $format = $this->getFormat(); + if ((null === $format || '' === $format) && !empty($locale)) { + $region = Locale::getRegion($locale); + if ('' === $region) { + throw new Exception\InvalidArgumentException("Locale must contain a region"); + } + if (isset(self::$postCodeRegex[$region])) { + $format = self::$postCodeRegex[$region]; + } + } + if (null === $format || '' === $format) { + throw new Exception\InvalidArgumentException("A postcode-format string has to be given for validation"); + } + + if ($format[0] !== '/') { + $format = '/^' . $format; + } + if ($format[strlen($format) - 1] !== '/') { + $format .= '$/'; + } + + if (!empty($service)) { + if (!is_callable($service)) { + throw new Exception\InvalidArgumentException('Invalid callback given'); + } + + try { + $callback = new Callback($service); + $callback->setOptions(array( + 'format' => $format, + 'locale' => $locale, + )); + if (!$callback->isValid($value)) { + $this->error(self::SERVICE, $value); + return false; + } + } catch (\Exception $e) { + $this->error(self::SERVICEFAILURE, $value); + return false; + } + } + + if (!preg_match($format, $value)) { + $this->error(self::NO_MATCH); + return false; + } + + return true; + } +} diff --git a/lib/Zend/I18n/View/Helper/AbstractTranslatorHelper.php b/lib/Zend/I18n/View/Helper/AbstractTranslatorHelper.php new file mode 100644 index 0000000000000000000000000000000000000000..f1e9ddb33b4f3a05921c8abc3a540d9eed2b98e5 --- /dev/null +++ b/lib/Zend/I18n/View/Helper/AbstractTranslatorHelper.php @@ -0,0 +1,132 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_View + */ + +namespace Zend\I18n\View\Helper; + +use Zend\I18n\Translator\Translator; +use Zend\I18n\Translator\TranslatorAwareInterface; +use Zend\View\Helper\AbstractHelper; + +/** + * @category Zend + * @package Zend_View + * @subpackage Helper + */ +abstract class AbstractTranslatorHelper extends AbstractHelper implements + TranslatorAwareInterface +{ + /** + * Translator (optional) + * + * @var Translator + */ + protected $translator; + + /** + * Translator text domain (optional) + * + * @var string + */ + protected $translatorTextDomain = 'default'; + + /** + * Whether translator should be used + * + * @var bool + */ + protected $translatorEnabled = true; + + /** + * Sets translator to use in helper + * + * @param Translator $translator [optional] translator. + * Default is null, which sets no translator. + * @param string $textDomain [optional] text domain + * Default is null, which skips setTranslatorTextDomain + * @return AbstractTranslatorHelper + */ + public function setTranslator(Translator $translator = null, $textDomain = null) + { + $this->translator = $translator; + if (null !== $textDomain) { + $this->setTranslatorTextDomain($textDomain); + } + return $this; + } + + /** + * Returns translator used in helper + * + * @return Translator|null + */ + public function getTranslator() + { + if (! $this->isTranslatorEnabled()) { + return null; + } + + return $this->translator; + } + + /** + * Checks if the helper has a translator + * + * @return bool + */ + public function hasTranslator() + { + return (bool) $this->getTranslator(); + } + + /** + * Sets whether translator is enabled and should be used + * + * @param bool $enabled [optional] whether translator should be used. + * Default is true. + * @return AbstractTranslatorHelper + */ + public function setTranslatorEnabled($enabled = true) + { + $this->translatorEnabled = (bool) $enabled; + return $this; + } + + /** + * Returns whether translator is enabled and should be used + * + * @return bool + */ + public function isTranslatorEnabled() + { + return $this->translatorEnabled; + } + + /** + * Set translation text domain + * + * @param string $textDomain + * @return AbstractTranslatorHelper + */ + public function setTranslatorTextDomain($textDomain = 'default') + { + $this->translatorTextDomain = $textDomain; + return $this; + } + + /** + * Return the translation text domain + * + * @return string + */ + public function getTranslatorTextDomain() + { + return $this->translatorTextDomain; + } +} diff --git a/lib/Zend/I18n/View/Helper/CurrencyFormat.php b/lib/Zend/I18n/View/Helper/CurrencyFormat.php new file mode 100644 index 0000000000000000000000000000000000000000..75f7a0949ced867741d646a66d4fe5b25fb9fec7 --- /dev/null +++ b/lib/Zend/I18n/View/Helper/CurrencyFormat.php @@ -0,0 +1,128 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_I18n + */ + +namespace Zend\I18n\View\Helper; + +use Locale; +use NumberFormatter; +use Zend\View\Helper\AbstractHelper; + +/** + * View helper for formatting dates. + * + * @category Zend + * @package Zend_I18n + * @subpackage View + */ +class CurrencyFormat extends AbstractHelper +{ + /** + * Locale to use instead of the default. + * + * @var string + */ + protected $locale; + + /** + * The 3-letter ISO 4217 currency code indicating the currency to use. + * + * @var string + */ + protected $currencyCode; + + /** + * Formatter instances. + * + * @var array + */ + protected $formatters = array(); + + /** + * The 3-letter ISO 4217 currency code indicating the currency to use. + * + * @param string $currencyCode + * @return CurrencyFormat + */ + public function setCurrencyCode($currencyCode) + { + $this->currencyCode = $currencyCode; + return $this; + } + + /** + * Get the 3-letter ISO 4217 currency code indicating the currency to use. + * + * @return string + */ + public function getCurrencyCode() + { + return $this->currencyCode; + } + + /** + * Set locale to use instead of the default. + * + * @param string $locale + * @return CurrencyFormat + */ + public function setLocale($locale) + { + $this->locale = (string) $locale; + return $this; + } + + /** + * Get the locale to use. + * + * @return string|null + */ + public function getLocale() + { + if ($this->locale === null) { + $this->locale = Locale::getDefault(); + } + + return $this->locale; + } + + /** + * Format a number. + * + * @param float $number + * @param string $currencyCode + * @param string $locale + * @return string + */ + public function __invoke( + $number, + $currencyCode = null, + $locale = null + ) { + if (null === $locale) { + $locale = $this->getLocale(); + } + if (null === $currencyCode) { + $currencyCode = $this->getCurrencyCode(); + } + + $formatterId = md5($locale); + + if (!isset($this->formatters[$formatterId])) { + $this->formatters[$formatterId] = new NumberFormatter( + $locale, + NumberFormatter::CURRENCY + ); + } + + return $this->formatters[$formatterId]->formatCurrency( + $number, $currencyCode + ); + } +} diff --git a/lib/Zend/I18n/View/Helper/DateFormat.php b/lib/Zend/I18n/View/Helper/DateFormat.php new file mode 100644 index 0000000000000000000000000000000000000000..279f0b5c6f0c3d3cbafd81e7ff5a399bca5adf65 --- /dev/null +++ b/lib/Zend/I18n/View/Helper/DateFormat.php @@ -0,0 +1,144 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_I18n + */ + +namespace Zend\I18n\View\Helper; + +use DateTime; +use IntlDateFormatter; +use Locale; +use Zend\I18n\Exception; +use Zend\View\Helper\AbstractHelper; + +/** + * View helper for formatting dates. + * + * @category Zend + * @package Zend_I18n + * @subpackage View + */ +class DateFormat extends AbstractHelper +{ + /** + * Locale to use instead of the default. + * + * @var string + */ + protected $locale; + + /** + * Timezone to use. + * + * @var string + */ + protected $timezone; + + /** + * Formatter instances. + * + * @var array + */ + protected $formatters = array(); + + /** + * Set timezone to use instead of the default. + * + * @param string $timezone + * @return DateFormat + */ + public function setTimezone($timezone) + { + $this->timezone = (string) $timezone; + + foreach ($this->formatters as $formatter) { + $formatter->setTimeZoneId($this->timezone); + } + return $this; + } + + /** + * Get the timezone to use. + * + * @return string|null + */ + public function getTimezone() + { + if (!$this->timezone) { + return date_default_timezone_get(); + } + + return $this->timezone; + } + + /** + * Set locale to use instead of the default. + * + * @param string $locale + * @return DateFormat + */ + public function setlocale($locale) + { + $this->locale = (string) $locale; + return $this; + } + + /** + * Get the locale to use. + * + * @return string|null + */ + public function getlocale() + { + if ($this->locale === null) { + $this->locale = Locale::getDefault(); + } + + return $this->locale; + } + + /** + * Format a date. + * + * @param DateTime|integer|array $date + * @param integer $dateType + * @param integer $timeType + * @param string $locale + * @return string + * @throws Exception\RuntimeException + */ + public function __invoke( + $date, + $dateType = IntlDateFormatter::NONE, + $timeType = IntlDateFormatter::NONE, + $locale = null + ) { + if ($locale === null) { + $locale = $this->getlocale(); + } + + $timezone = $this->getTimezone(); + $formatterId = md5($dateType . "\0" . $timeType . "\0" . $locale); + + if (!isset($this->formatters[$formatterId])) { + $this->formatters[$formatterId] = new IntlDateFormatter( + $locale, + $dateType, + $timeType, + $timezone + ); + } + + // DateTime support for IntlDateFormatter::format() was only added in 5.3.4 + if ($date instanceof DateTime && version_compare(PHP_VERSION, '5.3.4', '<')) { + $date = $date->getTimestamp(); + } + + return $this->formatters[$formatterId]->format($date); + } +} diff --git a/lib/Zend/I18n/View/Helper/NumberFormat.php b/lib/Zend/I18n/View/Helper/NumberFormat.php new file mode 100644 index 0000000000000000000000000000000000000000..c1af3371db3bc0713c873699fb83b59f83b3aa4b --- /dev/null +++ b/lib/Zend/I18n/View/Helper/NumberFormat.php @@ -0,0 +1,166 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_I18n + */ + +namespace Zend\I18n\View\Helper; + +use Locale; +use NumberFormatter; +use Zend\View\Helper\AbstractHelper; + +/** + * View helper for formatting dates. + * + * @category Zend + * @package Zend_I18n + * @subpackage View + */ +class NumberFormat extends AbstractHelper +{ + /** + * Locale to use instead of the default. + * + * @var string + */ + protected $locale; + + /** + * NumberFormat style to use. + * + * @var integer + */ + protected $formatStyle; + + /** + * NumberFormat type to use. + * + * @var integer + */ + protected $formatType; + + /** + * Formatter instances. + * + * @var array + */ + protected $formatters = array(); + + /** + * Set format style to use instead of the default. + * + * @param integer $formatStyle + * @return NumberFormat + */ + public function setFormatStyle($formatStyle) + { + $this->formatStyle = (int) $formatStyle; + return $this; + } + + /** + * Get the format style to use. + * + * @return integer + */ + public function getFormatStyle() + { + if (null === $this->formatStyle) { + $this->formatStyle = NumberFormatter::DECIMAL; + } + return $this->formatStyle; + } + + /** + * Set format type to use instead of the default. + * + * @param integer $formatType + * @return NumberFormat + */ + public function setFormatType($formatType) + { + $this->formatType = (int) $formatType; + return $this; + } + + /** + * Get the format type to use. + * + * @return integer + */ + public function getFormatType() + { + if (null === $this->formatType) { + $this->formatType = NumberFormatter::TYPE_DEFAULT; + } + return $this->formatType; + } + + /** + * Set locale to use instead of the default. + * + * @param string $locale + * @return NumberFormat + */ + public function setLocale($locale) + { + $this->locale = (string) $locale; + return $this; + } + + /** + * Get the locale to use. + * + * @return string|null + */ + public function getLocale() + { + if ($this->locale === null) { + $this->locale = Locale::getDefault(); + } + + return $this->locale; + } + + /** + * Format a number. + * + * @param integer|float $number + * @param integer $formatStyle + * @param integer $formatType + * @param string $locale + * @return string + */ + public function __invoke( + $number, + $formatStyle = null, + $formatType = null, + $locale = null + ) { + if (null === $locale) { + $locale = $this->getLocale(); + } + if (null === $formatStyle) { + $formatStyle = $this->getFormatStyle(); + } + if (null === $formatType) { + $formatType = $this->getFormatType(); + } + + $formatterId = md5($formatStyle . "\0" . $locale); + + if (!isset($this->formatters[$formatterId])) { + $this->formatters[$formatterId] = new NumberFormatter( + $locale, + $formatStyle + ); + } + + return $this->formatters[$formatterId]->format($number, $formatType); + } +} diff --git a/lib/Zend/I18n/View/Helper/Translate.php b/lib/Zend/I18n/View/Helper/Translate.php new file mode 100644 index 0000000000000000000000000000000000000000..3c3c514aa463c03e337536b283cfcb45130ffddf --- /dev/null +++ b/lib/Zend/I18n/View/Helper/Translate.php @@ -0,0 +1,44 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_I18n + */ + +namespace Zend\I18n\View\Helper; + +use Zend\I18n\Exception; + +/** + * View helper for translating messages. + * + * @category Zend + * @package Zend_I18n + * @subpackage View + */ +class Translate extends AbstractTranslatorHelper +{ + /** + * Translate a message. + * + * @param string $message + * @param string $textDomain + * @param string $locale + * @return string + * @throws Exception\RuntimeException + */ + public function __invoke($message, $textDomain = null, $locale = null) + { + $translator = $this->getTranslator(); + if (null === $translator) { + throw new Exception\RuntimeException('Translator has not been set'); + } + if (null === $textDomain) { + $textDomain = $this->getTranslatorTextDomain(); + } + return $translator->translate($message, $textDomain, $locale); + } +} diff --git a/lib/Zend/I18n/View/Helper/TranslatePlural.php b/lib/Zend/I18n/View/Helper/TranslatePlural.php new file mode 100644 index 0000000000000000000000000000000000000000..45a3aea514167ba7ee0332e1b172b05c72773514 --- /dev/null +++ b/lib/Zend/I18n/View/Helper/TranslatePlural.php @@ -0,0 +1,52 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_I18n + */ + +namespace Zend\I18n\View\Helper; + +use Zend\I18n\Exception; + +/** + * View helper for translating plural messages. + * + * @category Zend + * @package Zend_I18n + * @subpackage View + */ +class TranslatePlural extends AbstractTranslatorHelper +{ + /** + * Translate a plural message. + * + * @param string $singular + * @param string $plural + * @param integer $number + * @param string $textDomain + * @param string $locale + * @return string + * @throws Exception\RuntimeException + */ + public function __invoke( + $singular, + $plural, + $number, + $textDomain = null, + $locale = null + ) + { + $translator = $this->getTranslator(); + if (null === $translator) { + throw new Exception\RuntimeException('Translator has not been set'); + } + if (null === $textDomain) { + $textDomain = $this->getTranslatorTextDomain(); + } + return $translator->translatePlural($singular, $plural, $number, $textDomain, $locale); + } +} diff --git a/lib/Zend/I18n/View/HelperConfig.php b/lib/Zend/I18n/View/HelperConfig.php new file mode 100644 index 0000000000000000000000000000000000000000..3dfe2782411b48d2014159ee14a38d0c218c9398 --- /dev/null +++ b/lib/Zend/I18n/View/HelperConfig.php @@ -0,0 +1,49 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_I18n + */ + +namespace Zend\I18n\View; + +use Zend\ServiceManager\ConfigInterface; +use Zend\ServiceManager\ServiceManager; + +/** + * Service manager configuration for i18n view helpers. + * + * @category Zend + * @package Zend_I18n + * @subpackage View + */ +class HelperConfig implements ConfigInterface +{ + /** + * @var array Pre-aliased view helpers + */ + protected $invokables = array( + 'currencyformat' => 'Zend\I18n\View\Helper\CurrencyFormat', + 'dateformat' => 'Zend\I18n\View\Helper\DateFormat', + 'numberformat' => 'Zend\I18n\View\Helper\NumberFormat', + 'translate' => 'Zend\I18n\View\Helper\Translate', + 'translateplural' => 'Zend\I18n\View\Helper\TranslatePlural', + ); + + /** + * Configure the provided service manager instance with the configuration + * in this class. + * + * @param ServiceManager $serviceManager + * @return void + */ + public function configureServiceManager(ServiceManager $serviceManager) + { + foreach ($this->invokables as $name => $service) { + $serviceManager->setInvokableClass($name, $service); + } + } +} diff --git a/lib/Zend/I18n/composer.json b/lib/Zend/I18n/composer.json new file mode 100644 index 0000000000000000000000000000000000000000..c93238275c7dcabbe5b70c1c04c9d1c082e5ae86 --- /dev/null +++ b/lib/Zend/I18n/composer.json @@ -0,0 +1,20 @@ +{ + "name": "zendframework/zend-i18n", + "description": " ", + "license": "BSD-3-Clause", + "keywords": [ + "zf2", + "i18n" + ], + "autoload": { + "psr-0": { + "Zend\\I18n": "" + } + }, + "target-dir": "Zend/I18n", + "require": { + "php": ">=5.3.3", + "ext-intl": "*", + "zendframework/zend-stdlib": "self.version" + } +} diff --git a/lib/Zend/Server/Abstract.php b/lib/Zend/Server/Abstract.php deleted file mode 100644 index 76a204da2bfd23d65d9bc4282c31e317f7a0621a..0000000000000000000000000000000000000000 --- a/lib/Zend/Server/Abstract.php +++ /dev/null @@ -1,242 +0,0 @@ -<?php -/** - * Zend Framework - * - * LICENSE - * - * This source file is subject to the new BSD license that is bundled - * with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://framework.zend.com/license/new-bsd - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@zend.com so we can send you a copy immediately. - * - * @category Zend - * @package Zend_Server - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - */ - -/** Zend_Server_Interface */ -#require_once 'Zend/Server/Interface.php'; - -/** - * Zend_Server_Definition - */ -#require_once 'Zend/Server/Definition.php'; - -/** - * Zend_Server_Method_Definition - */ -#require_once 'Zend/Server/Method/Definition.php'; - -/** - * Zend_Server_Method_Callback - */ -#require_once 'Zend/Server/Method/Callback.php'; - -/** - * Zend_Server_Method_Prototype - */ -#require_once 'Zend/Server/Method/Prototype.php'; - -/** - * Zend_Server_Method_Parameter - */ -#require_once 'Zend/Server/Method/Parameter.php'; - -/** - * Zend_Server_Abstract - * - * @category Zend - * @package Zend_Server - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - * @version $Id: Abstract.php 20096 2010-01-06 02:05:09Z bkarwin $ - */ -abstract class Zend_Server_Abstract implements Zend_Server_Interface -{ - /** - * @deprecated - * @var array List of PHP magic methods (lowercased) - */ - protected static $magic_methods = array( - '__call', - '__clone', - '__construct', - '__destruct', - '__get', - '__isset', - '__set', - '__set_state', - '__sleep', - '__tostring', - '__unset', - '__wakeup', - ); - - /** - * @var bool Flag; whether or not overwriting existing methods is allowed - */ - protected $_overwriteExistingMethods = false; - - /** - * @var Zend_Server_Definition - */ - protected $_table; - - /** - * Constructor - * - * Setup server description - * - * @return void - */ - public function __construct() - { - $this->_table = new Zend_Server_Definition(); - $this->_table->setOverwriteExistingMethods($this->_overwriteExistingMethods); - } - - /** - * Returns a list of registered methods - * - * Returns an array of method definitions. - * - * @return Zend_Server_Definition - */ - public function getFunctions() - { - return $this->_table; - } - - /** - * Lowercase a string - * - * Lowercase's a string by reference - * - * @deprecated - * @param string $string value - * @param string $key - * @return string Lower cased string - */ - public static function lowerCase(&$value, &$key) - { - trigger_error(__CLASS__ . '::' . __METHOD__ . '() is deprecated and will be removed in a future version', E_USER_NOTICE); - return $value = strtolower($value); - } - - /** - * Build callback for method signature - * - * @param Zend_Server_Reflection_Function_Abstract $reflection - * @return Zend_Server_Method_Callback - */ - protected function _buildCallback(Zend_Server_Reflection_Function_Abstract $reflection) - { - $callback = new Zend_Server_Method_Callback(); - if ($reflection instanceof Zend_Server_Reflection_Method) { - $callback->setType($reflection->isStatic() ? 'static' : 'instance') - ->setClass($reflection->getDeclaringClass()->getName()) - ->setMethod($reflection->getName()); - } elseif ($reflection instanceof Zend_Server_Reflection_Function) { - $callback->setType('function') - ->setFunction($reflection->getName()); - } - return $callback; - } - - /** - * Build a method signature - * - * @param Zend_Server_Reflection_Function_Abstract $reflection - * @param null|string|object $class - * @return Zend_Server_Method_Definition - * @throws Zend_Server_Exception on duplicate entry - */ - protected function _buildSignature(Zend_Server_Reflection_Function_Abstract $reflection, $class = null) - { - $ns = $reflection->getNamespace(); - $name = $reflection->getName(); - $method = empty($ns) ? $name : $ns . '.' . $name; - - if (!$this->_overwriteExistingMethods && $this->_table->hasMethod($method)) { - #require_once 'Zend/Server/Exception.php'; - throw new Zend_Server_Exception('Duplicate method registered: ' . $method); - } - - $definition = new Zend_Server_Method_Definition(); - $definition->setName($method) - ->setCallback($this->_buildCallback($reflection)) - ->setMethodHelp($reflection->getDescription()) - ->setInvokeArguments($reflection->getInvokeArguments()); - - foreach ($reflection->getPrototypes() as $proto) { - $prototype = new Zend_Server_Method_Prototype(); - $prototype->setReturnType($this->_fixType($proto->getReturnType())); - foreach ($proto->getParameters() as $parameter) { - $param = new Zend_Server_Method_Parameter(array( - 'type' => $this->_fixType($parameter->getType()), - 'name' => $parameter->getName(), - 'optional' => $parameter->isOptional(), - )); - if ($parameter->isDefaultValueAvailable()) { - $param->setDefaultValue($parameter->getDefaultValue()); - } - $prototype->addParameter($param); - } - $definition->addPrototype($prototype); - } - if (is_object($class)) { - $definition->setObject($class); - } - $this->_table->addMethod($definition); - return $definition; - } - - /** - * Dispatch method - * - * @param Zend_Server_Method_Definition $invocable - * @param array $params - * @return mixed - */ - protected function _dispatch(Zend_Server_Method_Definition $invocable, array $params) - { - $callback = $invocable->getCallback(); - $type = $callback->getType(); - - if ('function' == $type) { - $function = $callback->getFunction(); - return call_user_func_array($function, $params); - } - - $class = $callback->getClass(); - $method = $callback->getMethod(); - - if ('static' == $type) { - return call_user_func_array(array($class, $method), $params); - } - - $object = $invocable->getObject(); - if (!is_object($object)) { - $invokeArgs = $invocable->getInvokeArguments(); - if (!empty($invokeArgs)) { - $reflection = new ReflectionClass($class); - $object = $reflection->newInstanceArgs($invokeArgs); - } else { - $object = new $class; - } - } - return call_user_func_array(array($object, $method), $params); - } - - /** - * Map PHP type to protocol type - * - * @param string $type - * @return string - */ - abstract protected function _fixType($type); -} diff --git a/lib/Zend/Server/AbstractServer.php b/lib/Zend/Server/AbstractServer.php new file mode 100644 index 0000000000000000000000000000000000000000..c951dc9c443166716c418be1088ad486b73dc8aa --- /dev/null +++ b/lib/Zend/Server/AbstractServer.php @@ -0,0 +1,168 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Server + */ + +namespace Zend\Server; + +use ReflectionClass; + +/** + * Abstract Server implementation + * + * @category Zend + * @package Zend_Server + */ +abstract class AbstractServer implements Server +{ + /** + * @var bool Flag; whether or not overwriting existing methods is allowed + */ + protected $overwriteExistingMethods = false; + + /** + * @var Definition + */ + protected $table; + + /** + * Constructor + * + * Setup server description + * + */ + public function __construct() + { + $this->table = new Definition(); + $this->table->setOverwriteExistingMethods($this->overwriteExistingMethods); + } + + /** + * Returns a list of registered methods + * + * Returns an array of method definitions. + * + * @return Definition + */ + public function getFunctions() + { + return $this->table; + } + + /** + * Build callback for method signature + * + * @param Reflection\AbstractFunction $reflection + * @return Method\Callback + */ + protected function _buildCallback(Reflection\AbstractFunction $reflection) + { + $callback = new Method\Callback(); + if ($reflection instanceof Reflection\ReflectionMethod) { + $callback->setType($reflection->isStatic() ? 'static' : 'instance') + ->setClass($reflection->getDeclaringClass()->getName()) + ->setMethod($reflection->getName()); + } elseif ($reflection instanceof Reflection\ReflectionFunction) { + $callback->setType('function') + ->setFunction($reflection->getName()); + } + return $callback; + } + + /** + * Build a method signature + * + * @param Reflection\AbstractFunction $reflection + * @param null|string|object $class + * @return Method\Definition + * @throws Exception\RuntimeException on duplicate entry + */ + protected function _buildSignature(Reflection\AbstractFunction $reflection, $class = null) + { + $ns = $reflection->getNamespace(); + $name = $reflection->getName(); + $method = empty($ns) ? $name : $ns . '.' . $name; + + if (!$this->overwriteExistingMethods && $this->table->hasMethod($method)) { + throw new Exception\RuntimeException('Duplicate method registered: ' . $method); + } + + $definition = new Method\Definition(); + $definition->setName($method) + ->setCallback($this->_buildCallback($reflection)) + ->setMethodHelp($reflection->getDescription()) + ->setInvokeArguments($reflection->getInvokeArguments()); + + foreach ($reflection->getPrototypes() as $proto) { + $prototype = new Method\Prototype(); + $prototype->setReturnType($this->_fixType($proto->getReturnType())); + foreach ($proto->getParameters() as $parameter) { + $param = new Method\Parameter(array( + 'type' => $this->_fixType($parameter->getType()), + 'name' => $parameter->getName(), + 'optional' => $parameter->isOptional(), + )); + if ($parameter->isDefaultValueAvailable()) { + $param->setDefaultValue($parameter->getDefaultValue()); + } + $prototype->addParameter($param); + } + $definition->addPrototype($prototype); + } + if (is_object($class)) { + $definition->setObject($class); + } + $this->table->addMethod($definition); + return $definition; + } + + /** + * Dispatch method + * + * @param Method\Definition $invocable + * @param array $params + * @return mixed + */ + protected function _dispatch(Method\Definition $invocable, array $params) + { + $callback = $invocable->getCallback(); + $type = $callback->getType(); + + if ('function' == $type) { + $function = $callback->getFunction(); + return call_user_func_array($function, $params); + } + + $class = $callback->getClass(); + $method = $callback->getMethod(); + + if ('static' == $type) { + return call_user_func_array(array($class, $method), $params); + } + + $object = $invocable->getObject(); + if (!is_object($object)) { + $invokeArgs = $invocable->getInvokeArguments(); + if (!empty($invokeArgs)) { + $reflection = new ReflectionClass($class); + $object = $reflection->newInstanceArgs($invokeArgs); + } else { + $object = new $class; + } + } + return call_user_func_array(array($object, $method), $params); + } + + /** + * Map PHP type to protocol type + * + * @param string $type + * @return string + */ + abstract protected function _fixType($type); +} diff --git a/lib/Zend/Server/Cache.php b/lib/Zend/Server/Cache.php index a03b902e5838978cfd16411c25541ef3b687ae2c..34cfdd6584e4edc4c1c07078bd81b26b7c836b88 100644 --- a/lib/Zend/Server/Cache.php +++ b/lib/Zend/Server/Cache.php @@ -1,38 +1,29 @@ <?php /** - * Zend Framework + * Zend Framework (http://framework.zend.com/) * - * LICENSE - * - * This source file is subject to the new BSD license that is bundled - * with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://framework.zend.com/license/new-bsd - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@zend.com so we can send you a copy immediately. - * - * @category Zend - * @package Zend_Server - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - * @version $Id: Cache.php 20096 2010-01-06 02:05:09Z bkarwin $ + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Server */ +namespace Zend\Server; + +use Zend\Stdlib\ErrorHandler; + /** - * Zend_Server_Cache: cache server definitions + * \Zend\Server\Cache: cache server definitions * * @category Zend * @package Zend_Server - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License */ -class Zend_Server_Cache +class Cache { /** * @var array Methods to skip when caching server */ - protected static $_skipMethods = array(); + protected static $skipMethods = array(); /** * Cache a file containing the dispatch list. @@ -44,10 +35,10 @@ class Zend_Server_Cache * on success. * * @param string $filename - * @param Zend_Server_Interface $server + * @param \Zend\Server\Server $server * @return bool */ - public static function save($filename, Zend_Server_Interface $server) + public static function save($filename, Server $server) { if (!is_string($filename) || (!file_exists($filename) && !is_writable(dirname($filename)))) @@ -57,10 +48,10 @@ class Zend_Server_Cache $methods = $server->getFunctions(); - if ($methods instanceof Zend_Server_Definition) { - $definition = new Zend_Server_Definition(); + if ($methods instanceof Definition) { + $definition = new Definition(); foreach ($methods as $method) { - if (in_array($method->getName(), self::$_skipMethods)) { + if (in_array($method->getName(), self::$skipMethods)) { continue; } $definition->addMethod($method); @@ -68,7 +59,10 @@ class Zend_Server_Cache $methods = $definition; } - if (0 === @file_put_contents($filename, serialize($methods))) { + ErrorHandler::start(); + $test = file_put_contents($filename, serialize($methods)); + ErrorHandler::stop(); + if (0 === $test) { return false; } @@ -85,17 +79,17 @@ class Zend_Server_Cache * request. Sample usage: * * <code> - * if (!Zend_Server_Cache::get($filename, $server)) { - * #require_once 'Some/Service/Class.php'; - * #require_once 'Another/Service/Class.php'; + * if (!Zend\Server\Cache::get($filename, $server)) { + * require_once 'Some/Service/ServiceClass.php'; + * require_once 'Another/Service/ServiceClass.php'; * - * // Attach Some_Service_Class with namespace 'some' - * $server->attach('Some_Service_Class', 'some'); + * // Attach Some\Service\ServiceClass with namespace 'some' + * $server->attach('Some\Service\ServiceClass', 'some'); * - * // Attach Another_Service_Class with namespace 'another' - * $server->attach('Another_Service_Class', 'another'); + * // Attach Another\Service\ServiceClass with namespace 'another' + * $server->attach('Another\Service\ServiceClass', 'another'); * - * Zend_Server_Cache::save($filename, $server); + * Zend\Server\Cache::save($filename, $server); * } * * $response = $server->handle(); @@ -103,10 +97,10 @@ class Zend_Server_Cache * </code> * * @param string $filename - * @param Zend_Server_Interface $server + * @param \Zend\Server\Server $server * @return bool */ - public static function get($filename, Zend_Server_Interface $server) + public static function get($filename, Server $server) { if (!is_string($filename) || !file_exists($filename) @@ -115,12 +109,17 @@ class Zend_Server_Cache return false; } - - if (false === ($dispatch = @file_get_contents($filename))) { + ErrorHandler::start(); + $dispatch = file_get_contents($filename); + ErrorHandler::stop(); + if (false === $dispatch) { return false; } - if (false === ($dispatchArray = @unserialize($dispatch))) { + ErrorHandler::start(E_NOTICE); + $dispatchArray = unserialize($dispatch); + ErrorHandler::stop(); + if (false === $dispatchArray) { return false; } diff --git a/lib/Zend/Server/Client.php b/lib/Zend/Server/Client.php new file mode 100644 index 0000000000000000000000000000000000000000..9044dda1195aebbe6b3ab20fc3d53b5d97385cbd --- /dev/null +++ b/lib/Zend/Server/Client.php @@ -0,0 +1,31 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Server + */ + +namespace Zend\Server; + +/** + * Client Interface + * + * @category Zend + * @package Zend_Server + */ +interface Client +{ + /** + * Executes remote call + * + * Unified interface for calling custom remote methods. + * + * @param string $method Remote call name. + * @param array $params Call parameters. + * @return mixed Remote call results. + */ + public function call($method, $params = array()); +} diff --git a/lib/Zend/Server/Definition.php b/lib/Zend/Server/Definition.php index bff074f0c61dd422f8c03f8acd915bfee22de6e6..fa3864be1194289c4545d7b62069ee34b8168edc 100644 --- a/lib/Zend/Server/Definition.php +++ b/lib/Zend/Server/Definition.php @@ -1,50 +1,37 @@ <?php /** - * Zend Framework + * Zend Framework (http://framework.zend.com/) * - * LICENSE - * - * This source file is subject to the new BSD license that is bundled - * with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://framework.zend.com/license/new-bsd - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@zend.com so we can send you a copy immediately. - * - * @category Zend - * @package Zend_Server - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - * @version $Id: Definition.php 20096 2010-01-06 02:05:09Z bkarwin $ + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Server */ +namespace Zend\Server; + /** * Server methods metadata * - * @todo Implement iterator * @category Zend * @package Zend_Server - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License */ -class Zend_Server_Definition implements Countable, Iterator +class Definition implements \Countable, \Iterator { /** - * @var array Array of Zend_Server_Method_Definition objects + * @var array Array of \Zend\Server\Method\Definition objects */ - protected $_methods = array(); + protected $methods = array(); /** * @var bool Whether or not overwriting existing methods is allowed */ - protected $_overwriteExistingMethods = false; + protected $overwriteExistingMethods = false; /** * Constructor * * @param null|array $methods - * @return void */ public function __construct($methods = null) { @@ -57,30 +44,28 @@ class Zend_Server_Definition implements Countable, Iterator * Set flag indicating whether or not overwriting existing methods is allowed * * @param mixed $flag - * @return void + * @return \Zend\Server\Definition */ public function setOverwriteExistingMethods($flag) { - $this->_overwriteExistingMethods = (bool) $flag; + $this->overwriteExistingMethods = (bool) $flag; return $this; } /** * Add method to definition * - * @param array|Zend_Server_Method_Definition $method + * @param array|\Zend\Server\Method\Definition $method * @param null|string $name - * @return Zend_Server_Definition - * @throws Zend_Server_Exception if duplicate or invalid method provided + * @return \Zend\Server\Definition + * @throws \Zend\Server\Exception\ExceptionInterface if duplicate or invalid method provided */ public function addMethod($method, $name = null) { if (is_array($method)) { - #require_once 'Zend/Server/Method/Definition.php'; - $method = new Zend_Server_Method_Definition($method); - } elseif (!$method instanceof Zend_Server_Method_Definition) { - #require_once 'Zend/Server/Exception.php'; - throw new Zend_Server_Exception('Invalid method provided'); + $method = new Method\Definition($method); + } elseif (!$method instanceof Method\Definition) { + throw new Exception\InvalidArgumentException('Invalid method provided'); } if (is_numeric($name)) { @@ -92,23 +77,21 @@ class Zend_Server_Definition implements Countable, Iterator $name = $method->getName(); } if (null === $name) { - #require_once 'Zend/Server/Exception.php'; - throw new Zend_Server_Exception('No method name provided'); + throw new Exception\InvalidArgumentException('No method name provided'); } - if (!$this->_overwriteExistingMethods && array_key_exists($name, $this->_methods)) { - #require_once 'Zend/Server/Exception.php'; - throw new Zend_Server_Exception(sprintf('Method by name of "%s" already exists', $name)); + if (!$this->overwriteExistingMethods && array_key_exists($name, $this->methods)) { + throw new Exception\InvalidArgumentException(sprintf('Method by name of "%s" already exists', $name)); } - $this->_methods[$name] = $method; + $this->methods[$name] = $method; return $this; } /** * Add multiple methods * - * @param array $methods Array of Zend_Server_Method_Definition objects or arrays - * @return Zend_Server_Definition + * @param array $methods Array of \Zend\Server\Method\Definition objects or arrays + * @return \Zend\Server\Definition */ public function addMethods(array $methods) { @@ -121,8 +104,8 @@ class Zend_Server_Definition implements Countable, Iterator /** * Set all methods at once (overwrite) * - * @param array $methods Array of Zend_Server_Method_Definition objects or arrays - * @return Zend_Server_Definition + * @param array $methods Array of \Zend\Server\Method\Definition objects or arrays + * @return \Zend\Server\Definition */ public function setMethods(array $methods) { @@ -139,19 +122,19 @@ class Zend_Server_Definition implements Countable, Iterator */ public function hasMethod($method) { - return array_key_exists($method, $this->_methods); + return array_key_exists($method, $this->methods); } /** * Get a given method definition * * @param string $method - * @return null|Zend_Server_Method_Definition + * @return null|\Zend\Server\Method\Definition */ public function getMethod($method) { if ($this->hasMethod($method)) { - return $this->_methods[$method]; + return $this->methods[$method]; } return false; } @@ -159,23 +142,23 @@ class Zend_Server_Definition implements Countable, Iterator /** * Get all method definitions * - * @return array Array of Zend_Server_Method_Definition objects + * @return array Array of \Zend\Server\Method\Definition objects */ public function getMethods() { - return $this->_methods; + return $this->methods; } /** * Remove a method definition * * @param string $method - * @return Zend_Server_Definition + * @return \Zend\Server\Definition */ public function removeMethod($method) { if ($this->hasMethod($method)) { - unset($this->_methods[$method]); + unset($this->methods[$method]); } return $this; } @@ -183,11 +166,11 @@ class Zend_Server_Definition implements Countable, Iterator /** * Clear all method definitions * - * @return Zend_Server_Definition + * @return \Zend\Server\Definition */ public function clearMethods() { - $this->_methods = array(); + $this->methods = array(); return $this; } @@ -212,17 +195,17 @@ class Zend_Server_Definition implements Countable, Iterator */ public function count() { - return count($this->_methods); + return count($this->methods); } /** * Iterator: current item * - * @return mixed + * @return Method\Definition */ public function current() { - return current($this->_methods); + return current($this->methods); } /** @@ -232,17 +215,17 @@ class Zend_Server_Definition implements Countable, Iterator */ public function key() { - return key($this->_methods); + return key($this->methods); } /** * Iterator: advance to next method * - * @return void + * @return Method\Definition */ public function next() { - return next($this->_methods); + return next($this->methods); } /** @@ -252,7 +235,7 @@ class Zend_Server_Definition implements Countable, Iterator */ public function rewind() { - return reset($this->_methods); + return reset($this->methods); } /** diff --git a/lib/Zend/Server/Exception.php b/lib/Zend/Server/Exception.php deleted file mode 100644 index efef2638ac5dcba45ea463027ee23d839f439fd2..0000000000000000000000000000000000000000 --- a/lib/Zend/Server/Exception.php +++ /dev/null @@ -1,35 +0,0 @@ -<?php -/** - * Zend Framework - * - * LICENSE - * - * This source file is subject to the new BSD license that is bundled - * with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://framework.zend.com/license/new-bsd - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@zend.com so we can send you a copy immediately. - * - * @category Zend - * @package Zend_Server - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - */ - -/** - * Zend_Exception - */ -#require_once 'Zend/Exception.php'; - -/** - * Zend_Server_Reflection exceptions - * - * @package Zend_Server - * @subpackage Reflection - * @version $Id: Exception.php 20096 2010-01-06 02:05:09Z bkarwin $ - */ -class Zend_Server_Exception extends Zend_Exception -{ -} diff --git a/lib/Zend/Server/Exception/BadMethodCallException.php b/lib/Zend/Server/Exception/BadMethodCallException.php new file mode 100644 index 0000000000000000000000000000000000000000..36cff7aa3c2d370a01e2835ce87d02265f487a14 --- /dev/null +++ b/lib/Zend/Server/Exception/BadMethodCallException.php @@ -0,0 +1,16 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Server + */ + +namespace Zend\Server\Exception; + +class BadMethodCallException + extends \BadMethodCallException + implements ExceptionInterface +{} diff --git a/lib/Zend/Server/Exception/ExceptionInterface.php b/lib/Zend/Server/Exception/ExceptionInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..9d8e038a927fda9717939b30356983a80d8efeed --- /dev/null +++ b/lib/Zend/Server/Exception/ExceptionInterface.php @@ -0,0 +1,21 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Server + */ + +namespace Zend\Server\Exception; + +/** + * Zend_Server exceptions + * + * @category Zend + * @package Zend_Server + */ +interface ExceptionInterface +{ +} diff --git a/lib/Zend/Server/Exception/InvalidArgumentException.php b/lib/Zend/Server/Exception/InvalidArgumentException.php new file mode 100644 index 0000000000000000000000000000000000000000..2f5420f3634d0f72488542c8d168ea27b2b4149c --- /dev/null +++ b/lib/Zend/Server/Exception/InvalidArgumentException.php @@ -0,0 +1,16 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Server + */ + +namespace Zend\Server\Exception; + +class InvalidArgumentException + extends \InvalidArgumentException + implements ExceptionInterface +{} diff --git a/lib/Zend/Server/Exception/RuntimeException.php b/lib/Zend/Server/Exception/RuntimeException.php new file mode 100644 index 0000000000000000000000000000000000000000..7fd74a3819208257c2cc1c734855e7cccf3bc30b --- /dev/null +++ b/lib/Zend/Server/Exception/RuntimeException.php @@ -0,0 +1,16 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Server + */ + +namespace Zend\Server\Exception; + +class RuntimeException + extends \RuntimeException + implements ExceptionInterface +{} diff --git a/lib/Zend/Server/Interface.php b/lib/Zend/Server/Interface.php deleted file mode 100644 index f40caa5d21b59f7219bb8fd3359cfacf173684b0..0000000000000000000000000000000000000000 --- a/lib/Zend/Server/Interface.php +++ /dev/null @@ -1,118 +0,0 @@ -<?php -/** - * Zend Framework - * - * LICENSE - * - * This source file is subject to the new BSD license that is bundled - * with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://framework.zend.com/license/new-bsd - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@zend.com so we can send you a copy immediately. - * - * @category Zend - * @package Zend_Server - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - */ - -/** - * Zend_Server_Interface - * - * @category Zend - * @package Zend_Server - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - * @version $Id: Interface.php 20096 2010-01-06 02:05:09Z bkarwin $ - */ -interface Zend_Server_Interface -{ - /** - * Attach a function as a server method - * - * Namespacing is primarily for xmlrpc, but may be used with other - * implementations to prevent naming collisions. - * - * @param string $function - * @param string $namespace - * @param null|array Optional array of arguments to pass to callbacks at - * dispatch. - * @return void - */ - public function addFunction($function, $namespace = ''); - - /** - * Attach a class to a server - * - * The individual implementations should probably allow passing a variable - * number of arguments in, so that developers may define custom runtime - * arguments to pass to server methods. - * - * Namespacing is primarily for xmlrpc, but could be used for other - * implementations as well. - * - * @param mixed $class Class name or object instance to examine and attach - * to the server. - * @param string $namespace Optional namespace with which to prepend method - * names in the dispatch table. - * methods in the class will be valid callbacks. - * @param null|array Optional array of arguments to pass to callbacks at - * dispatch. - * @return void - */ - public function setClass($class, $namespace = '', $argv = null); - - /** - * Generate a server fault - * - * @param mixed $fault - * @param int $code - * @return mixed - */ - public function fault($fault = null, $code = 404); - - /** - * Handle a request - * - * Requests may be passed in, or the server may automagically determine the - * request based on defaults. Dispatches server request to appropriate - * method and returns a response - * - * @param mixed $request - * @return mixed - */ - public function handle($request = false); - - /** - * Return a server definition array - * - * Returns a server definition array as created using - * {@link * Zend_Server_Reflection}. Can be used for server introspection, - * documentation, or persistence. - * - * @access public - * @return array - */ - public function getFunctions(); - - /** - * Load server definition - * - * Used for persistence; loads a construct as returned by {@link getFunctions()}. - * - * @param array $array - * @return void - */ - public function loadFunctions($definition); - - /** - * Set server persistence - * - * @todo Determine how to implement this - * @param int $mode - * @return void - */ - public function setPersistence($mode); -} diff --git a/lib/Zend/Server/Method/Callback.php b/lib/Zend/Server/Method/Callback.php index cb2f658fc1492e214aa6393f7ec69faa6ee19f77..f936b0de575aee9d14d3f7ee6beb413a255ae2c6 100644 --- a/lib/Zend/Server/Method/Callback.php +++ b/lib/Zend/Server/Method/Callback.php @@ -1,66 +1,55 @@ <?php /** - * Zend Framework + * Zend Framework (http://framework.zend.com/) * - * LICENSE - * - * This source file is subject to the new BSD license that is bundled - * with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://framework.zend.com/license/new-bsd - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@zend.com so we can send you a copy immediately. - * - * @category Zend - * @package Zend_Server - * @subpackage Method - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - * @version $Id: Callback.php 20096 2010-01-06 02:05:09Z bkarwin $ + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Server */ +namespace Zend\Server\Method; + +use Zend\Server; + /** * Method callback metadata * * @category Zend * @package Zend_Server - * @subpackage Method - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License + * @subpackage Zend_Server_Method */ -class Zend_Server_Method_Callback +class Callback { /** * @var string Class name for class method callback */ - protected $_class; + protected $class; /** * @var string Function name for function callback */ - protected $_function; + protected $function; /** * @var string Method name for class method callback */ - protected $_method; + protected $method; /** * @var string Callback type */ - protected $_type; + protected $type; /** * @var array Valid callback types */ - protected $_types = array('function', 'static', 'instance'); + protected $types = array('function', 'static', 'instance'); /** * Constructor * * @param null|array $options - * @return void */ public function __construct($options = null) { @@ -73,7 +62,7 @@ class Zend_Server_Method_Callback * Set object state from array of options * * @param array $options - * @return Zend_Server_Method_Callback + * @return \Zend\Server\Method\Callback */ public function setOptions(array $options) { @@ -90,14 +79,14 @@ class Zend_Server_Method_Callback * Set callback class * * @param string $class - * @return Zend_Server_Method_Callback + * @return \Zend\Server\Method\Callback */ public function setClass($class) { if (is_object($class)) { $class = get_class($class); } - $this->_class = $class; + $this->class = $class; return $this; } @@ -108,18 +97,18 @@ class Zend_Server_Method_Callback */ public function getClass() { - return $this->_class; + return $this->class; } /** * Set callback function * * @param string $function - * @return Zend_Server_Method_Callback + * @return \Zend\Server\Method\Callback */ public function setFunction($function) { - $this->_function = (string) $function; + $this->function = (string) $function; $this->setType('function'); return $this; } @@ -131,18 +120,18 @@ class Zend_Server_Method_Callback */ public function getFunction() { - return $this->_function; + return $this->function; } /** * Set callback class method * * @param string $method - * @return Zend_Server_Method_Callback + * @return \Zend\Server\Method\Callback */ public function setMethod($method) { - $this->_method = $method; + $this->method = $method; return $this; } @@ -153,23 +142,22 @@ class Zend_Server_Method_Callback */ public function getMethod() { - return $this->_method; + return $this->method; } /** * Set callback type * * @param string $type - * @return Zend_Server_Method_Callback - * @throws Zend_Server_Exception + * @return Callback + * @throws Server\Exception\InvalidArgumentException */ public function setType($type) { - if (!in_array($type, $this->_types)) { - #require_once 'Zend/Server/Exception.php'; - throw new Zend_Server_Exception('Invalid method callback type passed to ' . __CLASS__ . '::' . __METHOD__); + if (!in_array($type, $this->types)) { + throw new Server\Exception\InvalidArgumentException('Invalid method callback type "' . $type . '" passed to ' . __CLASS__ . '::' . __METHOD__); } - $this->_type = $type; + $this->type = $type; return $this; } @@ -180,7 +168,7 @@ class Zend_Server_Method_Callback */ public function getType() { - return $this->_type; + return $this->type; } /** diff --git a/lib/Zend/Server/Method/Definition.php b/lib/Zend/Server/Method/Definition.php index 694dd4696fba44839e6efe65efe67fa8780c03d5..1fc62d02039c103b707376e9cff9d49c0d3e74e3 100644 --- a/lib/Zend/Server/Method/Definition.php +++ b/lib/Zend/Server/Method/Definition.php @@ -1,71 +1,60 @@ <?php /** - * Zend Framework + * Zend Framework (http://framework.zend.com/) * - * LICENSE - * - * This source file is subject to the new BSD license that is bundled - * with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://framework.zend.com/license/new-bsd - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@zend.com so we can send you a copy immediately. - * - * @category Zend - * @package Zend_Server - * @subpackage Method - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - * @version $Id: Definition.php 20096 2010-01-06 02:05:09Z bkarwin $ + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Server */ +namespace Zend\Server\Method; + +use Zend\Server; + /** * Method definition metadata * * @category Zend * @package Zend_Server - * @subpackage Method - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License + * @subpackage Zend_Server_Method */ -class Zend_Server_Method_Definition +class Definition { /** - * @var Zend_Server_Method_Callback + * @var \Zend\Server\Method\Callback */ - protected $_callback; + protected $callback; /** * @var array */ - protected $_invokeArguments = array(); + protected $invokeArguments = array(); /** * @var string */ - protected $_methodHelp = ''; + protected $methodHelp = ''; /** * @var string */ - protected $_name; + protected $name; /** * @var null|object */ - protected $_object; + protected $object; /** - * @var array Array of Zend_Server_Method_Prototype objects + * @var array Array of \Zend\Server\Method\Prototype objects */ - protected $_prototypes = array(); + protected $prototypes = array(); /** * Constructor * * @param null|array $options - * @return void */ public function __construct($options = null) { @@ -78,7 +67,7 @@ class Zend_Server_Method_Definition * Set object state from options * * @param array $options - * @return Zend_Server_Method_Definition + * @return \Zend\Server\Method\Definition */ public function setOptions(array $options) { @@ -95,11 +84,11 @@ class Zend_Server_Method_Definition * Set method name * * @param string $name - * @return Zend_Server_Method_Definition + * @return \Zend\Server\Method\Definition */ public function setName($name) { - $this->_name = (string) $name; + $this->name = (string) $name; return $this; } @@ -110,62 +99,60 @@ class Zend_Server_Method_Definition */ public function getName() { - return $this->_name; + return $this->name; } /** * Set method callback * - * @param array|Zend_Server_Method_Callback $callback - * @return Zend_Server_Method_Definition + * @param array|\Zend\Server\Method\Callback $callback + * @throws Server\Exception\InvalidArgumentException + * @return \Zend\Server\Method\Definition */ public function setCallback($callback) { if (is_array($callback)) { - #require_once 'Zend/Server/Method/Callback.php'; - $callback = new Zend_Server_Method_Callback($callback); - } elseif (!$callback instanceof Zend_Server_Method_Callback) { - #require_once 'Zend/Server/Exception.php'; - throw new Zend_Server_Exception('Invalid method callback provided'); + $callback = new Callback($callback); + } elseif (!$callback instanceof Callback) { + throw new Server\Exception\InvalidArgumentException('Invalid method callback provided'); } - $this->_callback = $callback; + $this->callback = $callback; return $this; } /** * Get method callback * - * @return Zend_Server_Method_Callback + * @return \Zend\Server\Method\Callback */ public function getCallback() { - return $this->_callback; + return $this->callback; } /** * Add prototype to method definition * - * @param array|Zend_Server_Method_Prototype $prototype - * @return Zend_Server_Method_Definition + * @param array|\Zend\Server\Method\Prototype $prototype + * @throws Server\Exception\InvalidArgumentException + * @return \Zend\Server\Method\Definition */ public function addPrototype($prototype) { if (is_array($prototype)) { - #require_once 'Zend/Server/Method/Prototype.php'; - $prototype = new Zend_Server_Method_Prototype($prototype); - } elseif (!$prototype instanceof Zend_Server_Method_Prototype) { - #require_once 'Zend/Server/Exception.php'; - throw new Zend_Server_Exception('Invalid method prototype provided'); + $prototype = new Prototype($prototype); + } elseif (!$prototype instanceof Prototype) { + throw new Server\Exception\InvalidArgumentException('Invalid method prototype provided'); } - $this->_prototypes[] = $prototype; + $this->prototypes[] = $prototype; return $this; } /** * Add multiple prototypes at once * - * @param array $prototypes Array of Zend_Server_Method_Prototype objects or arrays - * @return Zend_Server_Method_Definition + * @param array $prototypes Array of \Zend\Server\Method\Prototype objects or arrays + * @return \Zend\Server\Method\Definition */ public function addPrototypes(array $prototypes) { @@ -178,12 +165,12 @@ class Zend_Server_Method_Definition /** * Set all prototypes at once (overwrites) * - * @param array $prototypes Array of Zend_Server_Method_Prototype objects or arrays - * @return Zend_Server_Method_Definition + * @param array $prototypes Array of \Zend\Server\Method\Prototype objects or arrays + * @return \Zend\Server\Method\Definition */ public function setPrototypes(array $prototypes) { - $this->_prototypes = array(); + $this->prototypes = array(); $this->addPrototypes($prototypes); return $this; } @@ -191,22 +178,22 @@ class Zend_Server_Method_Definition /** * Get all prototypes * - * @return array $prototypes Array of Zend_Server_Method_Prototype objects or arrays + * @return array $prototypes Array of \Zend\Server\Method\Prototype objects or arrays */ public function getPrototypes() { - return $this->_prototypes; + return $this->prototypes; } /** * Set method help * * @param string $methodHelp - * @return Zend_Server_Method_Definition + * @return \Zend\Server\Method\Definition */ public function setMethodHelp($methodHelp) { - $this->_methodHelp = (string) $methodHelp; + $this->methodHelp = (string) $methodHelp; return $this; } @@ -217,22 +204,22 @@ class Zend_Server_Method_Definition */ public function getMethodHelp() { - return $this->_methodHelp; + return $this->methodHelp; } /** * Set object to use with method calls * * @param object $object - * @return Zend_Server_Method_Definition + * @throws Server\Exception\InvalidArgumentException + * @return \Zend\Server\Method\Definition */ public function setObject($object) { if (!is_object($object) && (null !== $object)) { - #require_once 'Zend/Server/Exception.php'; - throw new Zend_Server_Exception('Invalid object passed to ' . __CLASS__ . '::' . __METHOD__); + throw new Server\Exception\InvalidArgumentException('Invalid object passed to ' . __CLASS__ . '::' . __METHOD__); } - $this->_object = $object; + $this->object = $object; return $this; } @@ -243,18 +230,18 @@ class Zend_Server_Method_Definition */ public function getObject() { - return $this->_object; + return $this->object; } /** * Set invoke arguments * * @param array $invokeArguments - * @return Zend_Server_Method_Definition + * @return \Zend\Server\Method\Definition */ public function setInvokeArguments(array $invokeArguments) { - $this->_invokeArguments = $invokeArguments; + $this->invokeArguments = $invokeArguments; return $this; } @@ -265,7 +252,7 @@ class Zend_Server_Method_Definition */ public function getInvokeArguments() { - return $this->_invokeArguments; + return $this->invokeArguments; } /** diff --git a/lib/Zend/Server/Method/Parameter.php b/lib/Zend/Server/Method/Parameter.php index 6163b0bc07fc74ba8edc626b0d18895ef51c40e1..bcecbc0211f4d70536b2fd15bb8e19fbc12d7881 100644 --- a/lib/Zend/Server/Method/Parameter.php +++ b/lib/Zend/Server/Method/Parameter.php @@ -1,66 +1,63 @@ <?php /** - * Zend Framework + * Zend Framework (http://framework.zend.com/) * - * LICENSE - * - * This source file is subject to the new BSD license that is bundled - * with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://framework.zend.com/license/new-bsd - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@zend.com so we can send you a copy immediately. - * - * @category Zend - * @package Zend_Server - * @subpackage Method - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - * @version $Id: Parameter.php 20096 2010-01-06 02:05:09Z bkarwin $ + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Server */ +namespace Zend\Server\Method; + /** * Method parameter metadata * * @category Zend * @package Zend_Server - * @subpackage Method - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License + * @subpackage Zend_Server_Method */ -class Zend_Server_Method_Parameter +class Parameter { /** - * @var mixed Default parameter value + * Default parameter value + * + * @var mixed */ - protected $_defaultValue; + protected $defaultValue; /** - * @var string Parameter description + * Parameter description + * + * @var string */ - protected $_description = ''; + protected $description = ''; /** - * @var string Parameter variable name + * Parameter variable name + * + * @var string */ - protected $_name; + protected $name; /** - * @var bool Is parameter optional? + * Is parameter optional? + * + * @var bool */ - protected $_optional = false; + protected $optional = false; /** - * @var string Parameter type + * Parameter type + * + * @var string */ - protected $_type = 'mixed'; + protected $type = 'mixed'; /** * Constructor * * @param null|array $options - * @return void */ public function __construct($options = null) { @@ -73,7 +70,7 @@ class Zend_Server_Method_Parameter * Set object state from array of options * * @param array $options - * @return Zend_Server_Method_Parameter + * @return \Zend\Server\Method\Parameter */ public function setOptions(array $options) { @@ -90,11 +87,11 @@ class Zend_Server_Method_Parameter * Set default value * * @param mixed $defaultValue - * @return Zend_Server_Method_Parameter + * @return \Zend\Server\Method\Parameter */ public function setDefaultValue($defaultValue) { - $this->_defaultValue = $defaultValue; + $this->defaultValue = $defaultValue; return $this; } @@ -105,18 +102,18 @@ class Zend_Server_Method_Parameter */ public function getDefaultValue() { - return $this->_defaultValue; + return $this->defaultValue; } /** * Set description * * @param string $description - * @return Zend_Server_Method_Parameter + * @return \Zend\Server\Method\Parameter */ public function setDescription($description) { - $this->_description = (string) $description; + $this->description = (string) $description; return $this; } @@ -127,18 +124,18 @@ class Zend_Server_Method_Parameter */ public function getDescription() { - return $this->_description; + return $this->description; } /** * Set name * * @param string $name - * @return Zend_Server_Method_Parameter + * @return \Zend\Server\Method\Parameter */ public function setName($name) { - $this->_name = (string) $name; + $this->name = (string) $name; return $this; } @@ -149,18 +146,18 @@ class Zend_Server_Method_Parameter */ public function getName() { - return $this->_name; + return $this->name; } /** * Set optional flag * * @param bool $flag - * @return Zend_Server_Method_Parameter + * @return \Zend\Server\Method\Parameter */ public function setOptional($flag) { - $this->_optional = (bool) $flag; + $this->optional = (bool) $flag; return $this; } @@ -171,18 +168,18 @@ class Zend_Server_Method_Parameter */ public function isOptional() { - return $this->_optional; + return $this->optional; } /** * Set parameter type * * @param string $type - * @return Zend_Server_Method_Parameter + * @return \Zend\Server\Method\Parameter */ public function setType($type) { - $this->_type = (string) $type; + $this->type = (string) $type; return $this; } @@ -193,7 +190,7 @@ class Zend_Server_Method_Parameter */ public function getType() { - return $this->_type; + return $this->type; } /** diff --git a/lib/Zend/Server/Method/Prototype.php b/lib/Zend/Server/Method/Prototype.php index 3e36a1ad10051a89eb563792ae21df9f394907fc..00a1e017276b3fc2f5284c08786c3d722844f2c9 100644 --- a/lib/Zend/Server/Method/Prototype.php +++ b/lib/Zend/Server/Method/Prototype.php @@ -1,56 +1,43 @@ <?php /** - * Zend Framework + * Zend Framework (http://framework.zend.com/) * - * LICENSE - * - * This source file is subject to the new BSD license that is bundled - * with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://framework.zend.com/license/new-bsd - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@zend.com so we can send you a copy immediately. - * - * @category Zend - * @package Zend_Server - * @subpackage Method - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - * @version $Id: Prototype.php 20096 2010-01-06 02:05:09Z bkarwin $ + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Server */ +namespace Zend\Server\Method; + /** * Method prototype metadata * * @category Zend * @package Zend_Server - * @subpackage Method - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License + * @subpackage Zend_Server_Method */ -class Zend_Server_Method_Prototype +class Prototype { /** * @var string Return type */ - protected $_returnType = 'void'; + protected $returnType = 'void'; /** * @var array Map parameter names to parameter index */ - protected $_parameterNameMap = array(); + protected $parameterNameMap = array(); /** * @var array Method parameters */ - protected $_parameters = array(); + protected $parameters = array(); /** * Constructor * * @param null|array $options - * @return void */ public function __construct($options = null) { @@ -63,11 +50,11 @@ class Zend_Server_Method_Prototype * Set return value * * @param string $returnType - * @return Zend_Server_Method_Prototype + * @return \Zend\Server\Method\Prototype */ public function setReturnType($returnType) { - $this->_returnType = $returnType; + $this->returnType = $returnType; return $this; } @@ -78,28 +65,27 @@ class Zend_Server_Method_Prototype */ public function getReturnType() { - return $this->_returnType; + return $this->returnType; } /** * Add a parameter * * @param string $parameter - * @return Zend_Server_Method_Prototype + * @return \Zend\Server\Method\Prototype */ public function addParameter($parameter) { - if ($parameter instanceof Zend_Server_Method_Parameter) { - $this->_parameters[] = $parameter; + if ($parameter instanceof Parameter) { + $this->parameters[] = $parameter; if (null !== ($name = $parameter->getName())) { - $this->_parameterNameMap[$name] = count($this->_parameters) - 1; + $this->parameterNameMap[$name] = count($this->parameters) - 1; } } else { - #require_once 'Zend/Server/Method/Parameter.php'; - $parameter = new Zend_Server_Method_Parameter(array( + $parameter = new Parameter(array( 'type' => (string) $parameter, )); - $this->_parameters[] = $parameter; + $this->parameters[] = $parameter; } return $this; } @@ -107,8 +93,8 @@ class Zend_Server_Method_Prototype /** * Add parameters * - * @param array $parameter - * @return Zend_Server_Method_Prototype + * @param array $parameters + * @return \Zend\Server\Method\Prototype */ public function addParameters(array $parameters) { @@ -122,12 +108,12 @@ class Zend_Server_Method_Prototype * Set parameters * * @param array $parameters - * @return Zend_Server_Method_Prototype + * @return \Zend\Server\Method\Prototype */ public function setParameters(array $parameters) { - $this->_parameters = array(); - $this->_parameterNameMap = array(); + $this->parameters = array(); + $this->parameterNameMap = array(); $this->addParameters($parameters); return $this; } @@ -140,7 +126,7 @@ class Zend_Server_Method_Prototype public function getParameters() { $types = array(); - foreach ($this->_parameters as $parameter) { + foreach ($this->parameters as $parameter) { $types[] = $parameter->getType(); } return $types; @@ -153,25 +139,25 @@ class Zend_Server_Method_Prototype */ public function getParameterObjects() { - return $this->_parameters; + return $this->parameters; } /** * Retrieve a single parameter by name or index * * @param string|int $index - * @return null|Zend_Server_Method_Parameter + * @return null|\Zend\Server\Method\Parameter */ public function getParameter($index) { if (!is_string($index) && !is_numeric($index)) { return null; } - if (array_key_exists($index, $this->_parameterNameMap)) { - $index = $this->_parameterNameMap[$index]; + if (array_key_exists($index, $this->parameterNameMap)) { + $index = $this->parameterNameMap[$index]; } - if (array_key_exists($index, $this->_parameters)) { - return $this->_parameters[$index]; + if (array_key_exists($index, $this->parameters)) { + return $this->parameters[$index]; } return null; } @@ -180,7 +166,7 @@ class Zend_Server_Method_Prototype * Set object state from array * * @param array $options - * @return Zend_Server_Method_Prototype + * @return \Zend\Server\Method\Prototype */ public function setOptions(array $options) { diff --git a/lib/Zend/Server/Reflection.php b/lib/Zend/Server/Reflection.php index d7fa8ef32429bef5a5792912d5e93ce3f812bf25..7566297044551fec745c1065f08c0f49016b0163 100644 --- a/lib/Zend/Server/Reflection.php +++ b/lib/Zend/Server/Reflection.php @@ -1,111 +1,87 @@ <?php /** - * Zend Framework + * Zend Framework (http://framework.zend.com/) * - * LICENSE - * - * This source file is subject to the new BSD license that is bundled - * with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://framework.zend.com/license/new-bsd - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@zend.com so we can send you a copy immediately. - * - * @category Zend - * @package Zend_Server - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Server */ -/** - * Zend_Server_Reflection_Function - */ -#require_once 'Zend/Server/Reflection/Function.php'; +namespace Zend\Server; -/** - * Zend_Server_Reflection_Class - */ -#require_once 'Zend/Server/Reflection/Class.php'; +use Zend\Server\Reflection\ReflectionClass; +use Zend\Server\Reflection\ReflectionFunction; /** * Reflection for determining method signatures to use with server classes * * @category Zend * @package Zend_Server - * @subpackage Reflection - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - * @version $Id: Reflection.php 20096 2010-01-06 02:05:09Z bkarwin $ */ -class Zend_Server_Reflection +class Reflection { /** * Perform class reflection to create dispatch signatures * - * Creates a {@link Zend_Server_Reflection_Class} object for the class or + * Creates a {@link \Zend\Server\Reflection\ClassReflection} object for the class or * object provided. * * If extra arguments should be passed to dispatchable methods, these may * be provided as an array to $argv. * * @param string|object $class Class name or object - * @param null|array $argv Optional arguments to be used during the method call + * @param boolean|array $argv Optional arguments to be used during the method call * @param string $namespace Optional namespace with which to prefix the * method name (used for the signature key). Primarily to avoid collisions, * also for XmlRpc namespacing - * @return Zend_Server_Reflection_Class - * @throws Zend_Server_Reflection_Exception + * @return \Zend\Server\Reflection\ReflectionClass + * @throws \Zend\Server\Reflection\Exception\ExceptionInterface */ public static function reflectClass($class, $argv = false, $namespace = '') { if (is_object($class)) { - $reflection = new ReflectionObject($class); + $reflection = new \ReflectionObject($class); } elseif (class_exists($class)) { - $reflection = new ReflectionClass($class); + $reflection = new \ReflectionClass($class); } else { - #require_once 'Zend/Server/Reflection/Exception.php'; - throw new Zend_Server_Reflection_Exception('Invalid class or object passed to attachClass()'); + throw new Reflection\Exception\InvalidArgumentException('Invalid class or object passed to attachClass()'); } if ($argv && !is_array($argv)) { - #require_once 'Zend/Server/Reflection/Exception.php'; - throw new Zend_Server_Reflection_Exception('Invalid argv argument passed to reflectClass'); + throw new Reflection\Exception\InvalidArgumentException('Invalid argv argument passed to reflectClass'); } - return new Zend_Server_Reflection_Class($reflection, $namespace, $argv); + return new ReflectionClass($reflection, $namespace, $argv); } /** * Perform function reflection to create dispatch signatures * * Creates dispatch prototypes for a function. It returns a - * {@link Zend_Server_Reflection_Function} object. + * {@link Zend\Server\Reflection\FunctionReflection} object. * * If extra arguments should be passed to the dispatchable function, these * may be provided as an array to $argv. * * @param string $function Function name - * @param null|array $argv Optional arguments to be used during the method call + * @param boolean|array $argv Optional arguments to be used during the method call * @param string $namespace Optional namespace with which to prefix the * function name (used for the signature key). Primarily to avoid * collisions, also for XmlRpc namespacing - * @return Zend_Server_Reflection_Function - * @throws Zend_Server_Reflection_Exception + * @return \Zend\Server\Reflection\ReflectionFunction + * @throws \Zend\Server\Reflection\Exception\ExceptionInterface */ public static function reflectFunction($function, $argv = false, $namespace = '') { if (!is_string($function) || !function_exists($function)) { - #require_once 'Zend/Server/Reflection/Exception.php'; - throw new Zend_Server_Reflection_Exception('Invalid function "' . $function . '" passed to reflectFunction'); + throw new Reflection\Exception\InvalidArgumentException('Invalid function "' . $function . '" passed to reflectFunction'); } - if ($argv && !is_array($argv)) { - #require_once 'Zend/Server/Reflection/Exception.php'; - throw new Zend_Server_Reflection_Exception('Invalid argv argument passed to reflectClass'); + throw new Reflection\Exception\InvalidArgumentException('Invalid argv argument passed to reflectClass'); } - return new Zend_Server_Reflection_Function(new ReflectionFunction($function), $namespace, $argv); + return new ReflectionFunction(new \ReflectionFunction($function), $namespace, $argv); } } diff --git a/lib/Zend/Server/Reflection/Function/Abstract.php b/lib/Zend/Server/Reflection/AbstractFunction.php similarity index 64% rename from lib/Zend/Server/Reflection/Function/Abstract.php rename to lib/Zend/Server/Reflection/AbstractFunction.php index fc00463e2d8e60ff091d5752bef6d3cc0475de93..1a9c44f83591298aeecfba0b784538ed96093f65 100644 --- a/lib/Zend/Server/Reflection/Function/Abstract.php +++ b/lib/Zend/Server/Reflection/AbstractFunction.php @@ -1,37 +1,14 @@ <?php /** - * Zend Framework + * Zend Framework (http://framework.zend.com/) * - * LICENSE - * - * This source file is subject to the new BSD license that is bundled - * with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://framework.zend.com/license/new-bsd - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@zend.com so we can send you a copy immediately. - * - * @category Zend - * @package Zend_Server - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - */ - -/** - * Zend_Server_Reflection_Node + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Server */ -#require_once 'Zend/Server/Reflection/Node.php'; -/** - * Zend_Server_Reflection_Parameter - */ -#require_once 'Zend/Server/Reflection/Parameter.php'; - -/** - * Zend_Server_Reflection_Prototype - */ -#require_once 'Zend/Server/Reflection/Prototype.php'; +namespace Zend\Server\Reflection; /** * Function/Method Reflection @@ -41,27 +18,24 @@ * setting and retrieving the description (originally set using the docblock * contents), retrieving the callback and callback type, retrieving additional * method invocation arguments, and retrieving the - * method {@link Zend_Server_Reflection_Prototype prototypes}. + * method {@link \Zend\Server\Reflection\Prototype prototypes}. * * @category Zend * @package Zend_Server - * @subpackage Reflection - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - * @version $Id: Abstract.php 23320 2010-11-12 21:57:29Z alexander $ + * @subpackage Zend_Server_Reflection */ -abstract class Zend_Server_Reflection_Function_Abstract +abstract class AbstractFunction { /** * @var ReflectionFunction */ - protected $_reflection; + protected $reflection; /** * Additional arguments to pass to method on invocation * @var array */ - protected $_argv = array(); + protected $argv = array(); /** * Used to store extra configuration for the method (typically done by the @@ -70,69 +44,72 @@ abstract class Zend_Server_Reflection_Function_Abstract * {@link __set()} * @var array */ - protected $_config = array(); + protected $config = array(); /** * Declaring class (needed for when serialization occurs) * @var string */ - protected $_class; + protected $class; /** * Function/method description * @var string */ - protected $_description = ''; + protected $description = ''; /** * Namespace with which to prefix function/method name * @var string */ - protected $_namespace; + protected $namespace; /** * Prototypes * @var array */ - protected $_prototypes = array(); + protected $prototypes = array(); - private $_return; - private $_returnDesc; - private $_paramDesc; - private $_sigParams; - private $_sigParamsDepth; + private $return; + private $returnDesc; + private $paramDesc; + private $sigParams; + private $sigParamsDepth; /** * Constructor * - * @param ReflectionFunction $r + * @param \Reflector $r + * @param null|string $namespace + * @param null|array $argv + * @throws Exception\InvalidArgumentException + * @throws Exception\RuntimeException */ - public function __construct(Reflector $r, $namespace = null, $argv = array()) + public function __construct(\Reflector $r, $namespace = null, $argv = array()) { // In PHP 5.1.x, ReflectionMethod extends ReflectionFunction. In 5.2.x, // both extend ReflectionFunctionAbstract. So, we can't do normal type // hinting in the prototype, but instead need to do some explicit // testing here. - if ((!$r instanceof ReflectionFunction) - && (!$r instanceof ReflectionMethod)) { - #require_once 'Zend/Server/Reflection/Exception.php'; - throw new Zend_Server_Reflection_Exception('Invalid reflection class'); + if ((!$r instanceof \ReflectionFunction) + && (!$r instanceof \ReflectionMethod)) { + throw new Exception\InvalidArgumentException('Invalid reflection class'); } - $this->_reflection = $r; + $this->reflection = $r; // Determine namespace - if (null !== $namespace){ + if (null !== $namespace) { $this->setNamespace($namespace); } // Determine arguments if (is_array($argv)) { - $this->_argv = $argv; + $this->argv = $argv; } // If method call, need to store some info on the class - if ($r instanceof ReflectionMethod) { - $this->_class = $r->getDeclaringClass()->getName(); + if ($r instanceof \ReflectionMethod) { + $this->class = $r->getDeclaringClass()->getName(); } // Perform some introspection @@ -143,22 +120,22 @@ abstract class Zend_Server_Reflection_Function_Abstract * Create signature node tree * * Recursive method to build the signature node tree. Increments through - * each array in {@link $_sigParams}, adding every value of the next level + * each array in {@link $sigParams}, adding every value of the next level * to the current value (unless the current value is null). * - * @param Zend_Server_Reflection_Node $parent + * @param \Zend\Server\Reflection\Node $parent * @param int $level * @return void */ - protected function _addTree(Zend_Server_Reflection_Node $parent, $level = 0) + protected function _addTree(Node $parent, $level = 0) { - if ($level >= $this->_sigParamsDepth) { + if ($level >= $this->sigParamsDepth) { return; } - foreach ($this->_sigParams[$level] as $value) { - $node = new Zend_Server_Reflection_Node($value, $parent); - if ((null !== $value) && ($this->_sigParamsDepth > $level + 1)) { + foreach ($this->sigParams[$level] as $value) { + $node = new Node($value, $parent); + if ((null !== $value) && ($this->sigParamsDepth > $level + 1)) { $this->_addTree($node, $level + 1); } } @@ -169,15 +146,15 @@ abstract class Zend_Server_Reflection_Function_Abstract * * Builds a signature tree starting at the return values and descending * through each method argument. Returns an array of - * {@link Zend_Server_Reflection_Node}s. + * {@link \Zend\Server\Reflection\Node}s. * * @return array */ protected function _buildTree() { $returnTree = array(); - foreach ((array) $this->_return as $value) { - $node = new Zend_Server_Reflection_Node($value); + foreach ((array) $this->return as $value) { + $node = new Node($value); $this->_addTree($node); $returnTree[] = $node; } @@ -193,17 +170,17 @@ abstract class Zend_Server_Reflection_Function_Abstract * * @param array $return Array of return types * @param string $returnDesc Return value description - * @param array $params Array of arguments (each an array of types) + * @param array $paramTypes Array of arguments (each an array of types) * @param array $paramDesc Array of parameter descriptions * @return array */ protected function _buildSignatures($return, $returnDesc, $paramTypes, $paramDesc) { - $this->_return = $return; - $this->_returnDesc = $returnDesc; - $this->_paramDesc = $paramDesc; - $this->_sigParams = $paramTypes; - $this->_sigParamsDepth = count($paramTypes); + $this->return = $return; + $this->returnDesc = $returnDesc; + $this->paramDesc = $paramDesc; + $this->sigParams = $paramTypes; + $this->sigParamsDepth = count($paramTypes); $signatureTrees = $this->_buildTree(); $signatures = array(); @@ -218,7 +195,7 @@ abstract class Zend_Server_Reflection_Function_Abstract } foreach ($endPoints as $node) { - if (!$node instanceof Zend_Server_Reflection_Node) { + if (!$node instanceof Node) { continue; } @@ -226,23 +203,23 @@ abstract class Zend_Server_Reflection_Function_Abstract do { array_unshift($signature, $node->getValue()); $node = $node->getParent(); - } while ($node instanceof Zend_Server_Reflection_Node); + } while ($node instanceof Node); $signatures[] = $signature; } // Build prototypes - $params = $this->_reflection->getParameters(); + $params = $this->reflection->getParameters(); foreach ($signatures as $signature) { - $return = new Zend_Server_Reflection_ReturnValue(array_shift($signature), $this->_returnDesc); + $return = new ReflectionReturnValue(array_shift($signature), $this->returnDesc); $tmp = array(); foreach ($signature as $key => $type) { - $param = new Zend_Server_Reflection_Parameter($params[$key], $type, (isset($this->_paramDesc[$key]) ? $this->_paramDesc[$key] : null)); + $param = new ReflectionParameter($params[$key], $type, (isset($this->paramDesc[$key]) ? $this->paramDesc[$key] : null)); $param->setPosition($key); $tmp[] = $param; } - $this->_prototypes[] = new Zend_Server_Reflection_Prototype($return, $tmp); + $this->prototypes[] = new Prototype($return, $tmp); } } @@ -253,12 +230,12 @@ abstract class Zend_Server_Reflection_Function_Abstract * comment. Determines method signatures using a combination of * ReflectionFunction and parsing of DocBlock @param and @return values. * - * @param ReflectionFunction $function + * @throws Exception\RuntimeException * @return array */ protected function _reflect() { - $function = $this->_reflection; + $function = $this->reflection; $helpText = ''; $signatures = array(); $returnDesc = ''; @@ -269,8 +246,7 @@ abstract class Zend_Server_Reflection_Function_Abstract if (!empty($docBlock)) { // Get help text - if (preg_match(':/\*\*\s*\r?\n\s*\*\s(.*?)\r?\n\s*\*(\s@|/):s', $docBlock, $matches)) - { + if (preg_match(':/\*\*\s*\r?\n\s*\*\s(.*?)\r?\n\s*\*(\s@|/):s', $docBlock, $matches)) { $helpText = $matches[1]; $helpText = preg_replace('/(^\s*\*\s)/m', '', $helpText); $helpText = preg_replace('/\r?\n\s*\*\s*(\r?\n)*/s', "\n", $helpText); @@ -281,8 +257,7 @@ abstract class Zend_Server_Reflection_Function_Abstract $return = 'void'; if (preg_match('/@return\s+(\S+)/', $docBlock, $matches)) { $return = explode('|', $matches[1]); - if (preg_match('/@return\s+\S+\s+(.*?)(@|\*\/)/s', $docBlock, $matches)) - { + if (preg_match('/@return\s+\S+\s+(.*?)(@|\*\/)/s', $docBlock, $matches)) { $value = $matches[1]; $value = preg_replace('/\s?\*\s/m', '', $value); $value = preg_replace('/\s{2,}/', ' ', $value); @@ -293,8 +268,7 @@ abstract class Zend_Server_Reflection_Function_Abstract // Get param types and description if (preg_match_all('/@param\s+([^\s]+)/m', $docBlock, $matches)) { $paramTypesTmp = $matches[1]; - if (preg_match_all('/@param\s+\S+\s+(\$\S+)\s+(.*?)(?=@|\*\/)/s', $docBlock, $matches)) - { + if (preg_match_all('/@param\s+\S+\s+(\$\S+)\s+(.*?)(?=@|\*\/)/s', $docBlock, $matches)) { $paramDesc = $matches[2]; foreach ($paramDesc as $key => $value) { $value = preg_replace('/\s?\*\s/m', '', $value); @@ -346,12 +320,9 @@ abstract class Zend_Server_Reflection_Function_Abstract } if (count($paramTypesTmp) != $paramCount) { - #require_once 'Zend/Server/Reflection/Exception.php'; - throw new Zend_Server_Reflection_Exception( + throw new Exception\RuntimeException( 'Variable number of arguments is not supported for services (except optional parameters). ' - . 'Number of function arguments in ' . $function->getDeclaringClass()->getName() . '::' - . $function->getName() . '() must correspond to actual number of arguments described in the ' - . 'docblock.'); + . 'Number of function arguments must correspond to actual number of arguments described in a docblock.'); } $paramTypes = array(); @@ -372,22 +343,22 @@ abstract class Zend_Server_Reflection_Function_Abstract * * @param string $method * @param array $args + * @throws Exception\BadMethodCallException * @return mixed */ public function __call($method, $args) { - if (method_exists($this->_reflection, $method)) { - return call_user_func_array(array($this->_reflection, $method), $args); + if (method_exists($this->reflection, $method)) { + return call_user_func_array(array($this->reflection, $method), $args); } - #require_once 'Zend/Server/Reflection/Exception.php'; - throw new Zend_Server_Reflection_Exception('Invalid reflection method ("' .$method. '")'); + throw new Exception\BadMethodCallException('Invalid reflection method ("' . $method . '")'); } /** * Retrieve configuration parameters * - * Values are retrieved by key from {@link $_config}. Returns null if no + * Values are retrieved by key from {@link $config}. Returns null if no * value found. * * @param string $key @@ -395,8 +366,8 @@ abstract class Zend_Server_Reflection_Function_Abstract */ public function __get($key) { - if (isset($this->_config[$key])) { - return $this->_config[$key]; + if (isset($this->config[$key])) { + return $this->config[$key]; } return null; @@ -405,7 +376,7 @@ abstract class Zend_Server_Reflection_Function_Abstract /** * Set configuration parameters * - * Values are stored by $key in {@link $_config}. + * Values are stored by $key in {@link $config}. * * @param string $key * @param mixed $value @@ -413,28 +384,28 @@ abstract class Zend_Server_Reflection_Function_Abstract */ public function __set($key, $value) { - $this->_config[$key] = $value; + $this->config[$key] = $value; } /** * Set method's namespace * * @param string $namespace + * @throws Exception\InvalidArgumentException * @return void */ public function setNamespace($namespace) { if (empty($namespace)) { - $this->_namespace = ''; + $this->namespace = ''; return; } if (!is_string($namespace) || !preg_match('/[a-z0-9_\.]+/i', $namespace)) { - #require_once 'Zend/Server/Reflection/Exception.php'; - throw new Zend_Server_Reflection_Exception('Invalid namespace'); + throw new Exception\InvalidArgumentException('Invalid namespace'); } - $this->_namespace = $namespace; + $this->namespace = $namespace; } /** @@ -444,44 +415,44 @@ abstract class Zend_Server_Reflection_Function_Abstract */ public function getNamespace() { - return $this->_namespace; + return $this->namespace; } /** * Set the description * * @param string $string + * @throws Exception\InvalidArgumentException * @return void */ public function setDescription($string) { if (!is_string($string)) { - #require_once 'Zend/Server/Reflection/Exception.php'; - throw new Zend_Server_Reflection_Exception('Invalid description'); + throw new Exception\InvalidArgumentException('Invalid description'); } - $this->_description = $string; + $this->description = $string; } /** * Retrieve the description * - * @return void + * @return string */ public function getDescription() { - return $this->_description; + return $this->description; } /** * Retrieve all prototypes as array of - * {@link Zend_Server_Reflection_Prototype Zend_Server_Reflection_Prototypes} + * {@link \Zend\Server\Reflection\Prototype}s * * @return array */ public function getPrototypes() { - return $this->_prototypes; + return $this->prototypes; } /** @@ -491,7 +462,7 @@ abstract class Zend_Server_Reflection_Function_Abstract */ public function getInvokeArguments() { - return $this->_argv; + return $this->argv; } /** @@ -504,11 +475,11 @@ abstract class Zend_Server_Reflection_Function_Abstract */ public function __wakeup() { - if ($this->_reflection instanceof ReflectionMethod) { - $class = new ReflectionClass($this->_class); - $this->_reflection = new ReflectionMethod($class->newInstance(), $this->getName()); + if ($this->reflection instanceof \ReflectionMethod) { + $class = new \ReflectionClass($this->class); + $this->reflection = new \ReflectionMethod($class->newInstance(), $this->getName()); } else { - $this->_reflection = new ReflectionFunction($this->getName()); + $this->reflection = new \ReflectionFunction($this->getName()); } } } diff --git a/lib/Zend/Server/Reflection/Class.php b/lib/Zend/Server/Reflection/Class.php deleted file mode 100644 index f936657d2d105a8efec610815c1983183d90a627..0000000000000000000000000000000000000000 --- a/lib/Zend/Server/Reflection/Class.php +++ /dev/null @@ -1,198 +0,0 @@ -<?php -/** - * Zend Framework - * - * LICENSE - * - * This source file is subject to the new BSD license that is bundled - * with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://framework.zend.com/license/new-bsd - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@zend.com so we can send you a copy immediately. - * - * @category Zend - * @package Zend_Server - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - */ - -/** - * Zend_Server_Reflection_Method - */ -#require_once 'Zend/Server/Reflection/Method.php'; - -/** - * Class/Object reflection - * - * Proxies calls to a ReflectionClass object, and decorates getMethods() by - * creating its own list of {@link Zend_Server_Reflection_Method}s. - * - * @category Zend - * @package Zend_Server - * @subpackage Reflection - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - * @version $Id: Class.php 20096 2010-01-06 02:05:09Z bkarwin $ - */ -class Zend_Server_Reflection_Class -{ - /** - * Optional configuration parameters; accessible via {@link __get} and - * {@link __set()} - * @var array - */ - protected $_config = array(); - - /** - * Array of {@link Zend_Server_Reflection_Method}s - * @var array - */ - protected $_methods = array(); - - /** - * Namespace - * @var string - */ - protected $_namespace = null; - - /** - * ReflectionClass object - * @var ReflectionClass - */ - protected $_reflection; - - /** - * Constructor - * - * Create array of dispatchable methods, each a - * {@link Zend_Server_Reflection_Method}. Sets reflection object property. - * - * @param ReflectionClass $reflection - * @param string $namespace - * @param mixed $argv - * @return void - */ - public function __construct(ReflectionClass $reflection, $namespace = null, $argv = false) - { - $this->_reflection = $reflection; - $this->setNamespace($namespace); - - foreach ($reflection->getMethods() as $method) { - // Don't aggregate magic methods - if ('__' == substr($method->getName(), 0, 2)) { - continue; - } - - if ($method->isPublic()) { - // Get signatures and description - $this->_methods[] = new Zend_Server_Reflection_Method($this, $method, $this->getNamespace(), $argv); - } - } - } - - /** - * Proxy reflection calls - * - * @param string $method - * @param array $args - * @return mixed - */ - public function __call($method, $args) - { - if (method_exists($this->_reflection, $method)) { - return call_user_func_array(array($this->_reflection, $method), $args); - } - - #require_once 'Zend/Server/Reflection/Exception.php'; - throw new Zend_Server_Reflection_Exception('Invalid reflection method'); - } - - /** - * Retrieve configuration parameters - * - * Values are retrieved by key from {@link $_config}. Returns null if no - * value found. - * - * @param string $key - * @return mixed - */ - public function __get($key) - { - if (isset($this->_config[$key])) { - return $this->_config[$key]; - } - - return null; - } - - /** - * Set configuration parameters - * - * Values are stored by $key in {@link $_config}. - * - * @param string $key - * @param mixed $value - * @return void - */ - public function __set($key, $value) - { - $this->_config[$key] = $value; - } - - /** - * Return array of dispatchable {@link Zend_Server_Reflection_Method}s. - * - * @access public - * @return array - */ - public function getMethods() - { - return $this->_methods; - } - - /** - * Get namespace for this class - * - * @return string - */ - public function getNamespace() - { - return $this->_namespace; - } - - /** - * Set namespace for this class - * - * @param string $namespace - * @return void - */ - public function setNamespace($namespace) - { - if (empty($namespace)) { - $this->_namespace = ''; - return; - } - - if (!is_string($namespace) || !preg_match('/[a-z0-9_\.]+/i', $namespace)) { - #require_once 'Zend/Server/Reflection/Exception.php'; - throw new Zend_Server_Reflection_Exception('Invalid namespace'); - } - - $this->_namespace = $namespace; - } - - /** - * Wakeup from serialization - * - * Reflection needs explicit instantiation to work correctly. Re-instantiate - * reflection object on wakeup. - * - * @return void - */ - public function __wakeup() - { - $this->_reflection = new ReflectionClass($this->getName()); - } -} diff --git a/lib/Zend/Server/Reflection/Exception.php b/lib/Zend/Server/Reflection/Exception.php deleted file mode 100644 index d7dadcb0ec1a98d7ae933cc59f417eeb4eb52b66..0000000000000000000000000000000000000000 --- a/lib/Zend/Server/Reflection/Exception.php +++ /dev/null @@ -1,38 +0,0 @@ -<?php -/** - * Zend Framework - * - * LICENSE - * - * This source file is subject to the new BSD license that is bundled - * with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://framework.zend.com/license/new-bsd - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@zend.com so we can send you a copy immediately. - * - * @category Zend - * @package Zend_Server - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - */ - -/** - * @see Zend_Server_Exception - */ -#require_once 'Zend/Server/Exception.php'; - -/** - * Zend_Server_Reflection exceptions - * - * @category Zend - * @package Zend_Server - * @subpackage Reflection - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - * @version $Id: Exception.php 20096 2010-01-06 02:05:09Z bkarwin $ - */ -class Zend_Server_Reflection_Exception extends Zend_Server_Exception -{ -} diff --git a/lib/Zend/Server/Reflection/Exception/BadMethodCallException.php b/lib/Zend/Server/Reflection/Exception/BadMethodCallException.php new file mode 100644 index 0000000000000000000000000000000000000000..a772109e21c24bf25aafe86e0dc3f44c94411ac2 --- /dev/null +++ b/lib/Zend/Server/Reflection/Exception/BadMethodCallException.php @@ -0,0 +1,18 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Server + */ + +namespace Zend\Server\Reflection\Exception; + +use Zend\Server\Exception; + +class BadMethodCallException + extends Exception\BadMethodCallException + implements ExceptionInterface +{} diff --git a/lib/Zend/Server/Reflection/Exception/ExceptionInterface.php b/lib/Zend/Server/Reflection/Exception/ExceptionInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..bd90428dfde2fa4a89914b71c4b8302bd46123c5 --- /dev/null +++ b/lib/Zend/Server/Reflection/Exception/ExceptionInterface.php @@ -0,0 +1,23 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Server + */ + +namespace Zend\Server\Reflection\Exception; + +use Zend\Server\Exception\ExceptionInterface as Exception; + +/** + * Zend_Server_Reflection exceptions + * + * @category Zend + * @package Zend_Server + * @subpackage Zend_Server_Reflection + */ +interface ExceptionInterface extends Exception +{} diff --git a/lib/Zend/Server/Reflection/Exception/InvalidArgumentException.php b/lib/Zend/Server/Reflection/Exception/InvalidArgumentException.php new file mode 100644 index 0000000000000000000000000000000000000000..700f843d588a3cd4abf4a274b5bd241f8d2529dd --- /dev/null +++ b/lib/Zend/Server/Reflection/Exception/InvalidArgumentException.php @@ -0,0 +1,18 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Server + */ + +namespace Zend\Server\Reflection\Exception; + +use Zend\Server\Exception; + +class InvalidArgumentException + extends Exception\InvalidArgumentException + implements ExceptionInterface +{} diff --git a/lib/Zend/Server/Reflection/Exception/RuntimeException.php b/lib/Zend/Server/Reflection/Exception/RuntimeException.php new file mode 100644 index 0000000000000000000000000000000000000000..3cfd951fbd5b31990f0dfdea1b7336bc338f6996 --- /dev/null +++ b/lib/Zend/Server/Reflection/Exception/RuntimeException.php @@ -0,0 +1,18 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Server + */ + +namespace Zend\Server\Reflection\Exception; + +use Zend\Server\Exception; + +class RuntimeException + extends Exception\RuntimeException + implements ExceptionInterface +{} diff --git a/lib/Zend/Server/Reflection/Function.php b/lib/Zend/Server/Reflection/Function.php deleted file mode 100644 index 7ae12493aa6c9af631ca47d0c9d6d11a6bf405c7..0000000000000000000000000000000000000000 --- a/lib/Zend/Server/Reflection/Function.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php -/** - * Zend Framework - * - * LICENSE - * - * This source file is subject to the new BSD license that is bundled - * with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://framework.zend.com/license/new-bsd - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@zend.com so we can send you a copy immediately. - * - * @category Zend - * @package Zend_Server - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - */ - -/** - * Zend_Server_Reflection_Function_Abstract - */ -#require_once 'Zend/Server/Reflection/Function/Abstract.php'; - -/** - * Function Reflection - * - * @uses Zend_Server_Reflection_Function_Abstract - * @category Zend - * @package Zend_Server - * @subpackage Reflection - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - * @version $Id: Function.php 20096 2010-01-06 02:05:09Z bkarwin $ - */ -class Zend_Server_Reflection_Function extends Zend_Server_Reflection_Function_Abstract -{ -} diff --git a/lib/Zend/Server/Reflection/Method.php b/lib/Zend/Server/Reflection/Method.php deleted file mode 100644 index f40631660105d86749849a71be6ec6c16d11986c..0000000000000000000000000000000000000000 --- a/lib/Zend/Server/Reflection/Method.php +++ /dev/null @@ -1,110 +0,0 @@ -<?php -/** - * Zend Framework - * - * LICENSE - * - * This source file is subject to the new BSD license that is bundled - * with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://framework.zend.com/license/new-bsd - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@zend.com so we can send you a copy immediately. - * - * @category Zend - * @package Zend_Server - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - */ - -/** - * Zend_Server_Reflection_Function_Abstract - */ -#require_once 'Zend/Server/Reflection/Function/Abstract.php'; - -/** - * Method Reflection - * - * @uses Zend_Server_Reflection_Function_Abstract - * @category Zend - * @package Zend_Server - * @subpackage Reflection - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - * @version $Id: Method.php 20096 2010-01-06 02:05:09Z bkarwin $ - */ -class Zend_Server_Reflection_Method extends Zend_Server_Reflection_Function_Abstract -{ - /** - * Parent class name - * @var string - */ - protected $_class; - - /** - * Parent class reflection - * @var Zend_Server_Reflection_Class - */ - protected $_classReflection; - - /** - * Constructor - * - * @param Zend_Server_Reflection_Class $class - * @param ReflectionMethod $r - * @param string $namespace - * @param array $argv - * @return void - */ - public function __construct(Zend_Server_Reflection_Class $class, ReflectionMethod $r, $namespace = null, $argv = array()) - { - $this->_classReflection = $class; - $this->_reflection = $r; - - $classNamespace = $class->getNamespace(); - - // Determine namespace - if (!empty($namespace)) { - $this->setNamespace($namespace); - } elseif (!empty($classNamespace)) { - $this->setNamespace($classNamespace); - } - - // Determine arguments - if (is_array($argv)) { - $this->_argv = $argv; - } - - // If method call, need to store some info on the class - $this->_class = $class->getName(); - - // Perform some introspection - $this->_reflect(); - } - - /** - * Return the reflection for the class that defines this method - * - * @return Zend_Server_Reflection_Class - */ - public function getDeclaringClass() - { - return $this->_classReflection; - } - - /** - * Wakeup from serialization - * - * Reflection needs explicit instantiation to work correctly. Re-instantiate - * reflection object on wakeup. - * - * @return void - */ - public function __wakeup() - { - $this->_classReflection = new Zend_Server_Reflection_Class(new ReflectionClass($this->_class), $this->getNamespace(), $this->getInvokeArguments()); - $this->_reflection = new ReflectionMethod($this->_classReflection->getName(), $this->getName()); - } - -} diff --git a/lib/Zend/Server/Reflection/Node.php b/lib/Zend/Server/Reflection/Node.php index 6c902053a8843dd2fe7b092be9c4f713d9c0964d..f8038f15f623ed1e0021cec43df2005cc2d33158 100644 --- a/lib/Zend/Server/Reflection/Node.php +++ b/lib/Zend/Server/Reflection/Node.php @@ -1,63 +1,52 @@ <?php /** - * Zend Framework + * Zend Framework (http://framework.zend.com/) * - * LICENSE - * - * This source file is subject to the new BSD license that is bundled - * with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://framework.zend.com/license/new-bsd - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@zend.com so we can send you a copy immediately. - * - * @category Zend - * @package Zend_Server - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Server */ +namespace Zend\Server\Reflection; + /** * Node Tree class for Zend_Server reflection operations * * @category Zend * @package Zend_Server - * @subpackage Reflection - * @version $Id: Node.php 20096 2010-01-06 02:05:09Z bkarwin $ - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License + * @subpackage Zend_Server_Reflection */ -class Zend_Server_Reflection_Node +class Node { /** * Node value * @var mixed */ - protected $_value = null; + protected $value = null; /** * Array of child nodes (if any) * @var array */ - protected $_children = array(); + protected $children = array(); /** * Parent node (if any) - * @var Zend_Server_Reflection_Node + * @var \Zend\Server\Reflection\Node */ - protected $_parent = null; + protected $parent = null; /** * Constructor * * @param mixed $value - * @param Zend_Server_Reflection_Node $parent Optional - * @return Zend_Server_Reflection_Node + * @param \Zend\Server\Reflection\Node $parent Optional + * @return \Zend\Server\Reflection\Node */ - public function __construct($value, Zend_Server_Reflection_Node $parent = null) + public function __construct($value, Node $parent = null) { - $this->_value = $value; + $this->value = $value; if (null !== $parent) { $this->setParent($parent, true); } @@ -68,14 +57,14 @@ class Zend_Server_Reflection_Node /** * Set parent node * - * @param Zend_Server_Reflection_Node $node + * @param \Zend\Server\Reflection\Node $node * @param boolean $new Whether or not the child node is newly created * and should always be attached * @return void */ - public function setParent(Zend_Server_Reflection_Node $node, $new = false) + public function setParent(Node $node, $new = false) { - $this->_parent = $node; + $this->parent = $node; if ($new) { $node->attachChild($this); @@ -88,7 +77,7 @@ class Zend_Server_Reflection_Node * * @param mixed $value * @access public - * @return Zend_Server_Reflection_Node New child node + * @return \Zend\Server\Reflection\Node New child node */ public function createChild($value) { @@ -100,12 +89,12 @@ class Zend_Server_Reflection_Node /** * Attach a child node * - * @param Zend_Server_Reflection_Node $node + * @param \Zend\Server\Reflection\Node $node * @return void */ - public function attachChild(Zend_Server_Reflection_Node $node) + public function attachChild(Node $node) { - $this->_children[] = $node; + $this->children[] = $node; if ($node->getParent() !== $this) { $node->setParent($this); @@ -119,7 +108,7 @@ class Zend_Server_Reflection_Node */ public function getChildren() { - return $this->_children; + return $this->children; } /** @@ -129,17 +118,17 @@ class Zend_Server_Reflection_Node */ public function hasChildren() { - return count($this->_children) > 0; + return count($this->children) > 0; } /** * Return the parent node * - * @return null|Zend_Server_Reflection_Node + * @return null|\Zend\Server\Reflection\Node */ public function getParent() { - return $this->_parent; + return $this->parent; } /** @@ -149,7 +138,7 @@ class Zend_Server_Reflection_Node */ public function getValue() { - return $this->_value; + return $this->value; } /** @@ -160,7 +149,7 @@ class Zend_Server_Reflection_Node */ public function setValue($value) { - $this->_value = $value; + $this->value = $value; } /** @@ -179,7 +168,7 @@ class Zend_Server_Reflection_Node return $endPoints; } - foreach ($this->_children as $child) { + foreach ($this->children as $child) { $value = $child->getValue(); if (null === $value) { diff --git a/lib/Zend/Server/Reflection/Parameter.php b/lib/Zend/Server/Reflection/Parameter.php deleted file mode 100644 index 6a0e3a8a162ea9dab11003c0698ea4b6cbf3d884..0000000000000000000000000000000000000000 --- a/lib/Zend/Server/Reflection/Parameter.php +++ /dev/null @@ -1,161 +0,0 @@ -<?php -/** - * Zend Framework - * - * LICENSE - * - * This source file is subject to the new BSD license that is bundled - * with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://framework.zend.com/license/new-bsd - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@zend.com so we can send you a copy immediately. - * - * @category Zend - * @package Zend_Server - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - */ - -/** - * Parameter Reflection - * - * Decorates a ReflectionParameter to allow setting the parameter type - * - * @category Zend - * @package Zend_Server - * @subpackage Reflection - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - * @version $Id: Parameter.php 20096 2010-01-06 02:05:09Z bkarwin $ - */ -class Zend_Server_Reflection_Parameter -{ - /** - * @var ReflectionParameter - */ - protected $_reflection; - - /** - * Parameter position - * @var int - */ - protected $_position; - - /** - * Parameter type - * @var string - */ - protected $_type; - - /** - * Parameter description - * @var string - */ - protected $_description; - - /** - * Constructor - * - * @param ReflectionParameter $r - * @param string $type Parameter type - * @param string $description Parameter description - */ - public function __construct(ReflectionParameter $r, $type = 'mixed', $description = '') - { - $this->_reflection = $r; - $this->setType($type); - $this->setDescription($description); - } - - /** - * Proxy reflection calls - * - * @param string $method - * @param array $args - * @return mixed - */ - public function __call($method, $args) - { - if (method_exists($this->_reflection, $method)) { - return call_user_func_array(array($this->_reflection, $method), $args); - } - - #require_once 'Zend/Server/Reflection/Exception.php'; - throw new Zend_Server_Reflection_Exception('Invalid reflection method'); - } - - /** - * Retrieve parameter type - * - * @return string - */ - public function getType() - { - return $this->_type; - } - - /** - * Set parameter type - * - * @param string|null $type - * @return void - */ - public function setType($type) - { - if (!is_string($type) && (null !== $type)) { - #require_once 'Zend/Server/Reflection/Exception.php'; - throw new Zend_Server_Reflection_Exception('Invalid parameter type'); - } - - $this->_type = $type; - } - - /** - * Retrieve parameter description - * - * @return string - */ - public function getDescription() - { - return $this->_description; - } - - /** - * Set parameter description - * - * @param string|null $description - * @return void - */ - public function setDescription($description) - { - if (!is_string($description) && (null !== $description)) { - #require_once 'Zend/Server/Reflection/Exception.php'; - throw new Zend_Server_Reflection_Exception('Invalid parameter description'); - } - - $this->_description = $description; - } - - /** - * Set parameter position - * - * @param int $index - * @return void - */ - public function setPosition($index) - { - $this->_position = (int) $index; - } - - /** - * Return parameter position - * - * @return int - */ - public function getPosition() - { - return $this->_position; - } -} diff --git a/lib/Zend/Server/Reflection/Prototype.php b/lib/Zend/Server/Reflection/Prototype.php index 6ec1a1cf1d6bd6939f304b6c201b37814745ad89..8c363f279fa1fe31fa666631ec4583891f65c66c 100644 --- a/lib/Zend/Server/Reflection/Prototype.php +++ b/lib/Zend/Server/Reflection/Prototype.php @@ -1,32 +1,14 @@ <?php /** - * Zend Framework + * Zend Framework (http://framework.zend.com/) * - * LICENSE - * - * This source file is subject to the new BSD license that is bundled - * with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://framework.zend.com/license/new-bsd - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@zend.com so we can send you a copy immediately. - * - * @category Zend - * @package Zend_Server - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Server */ -/** - * Zend_Server_Reflection_ReturnValue - */ -#require_once 'Zend/Server/Reflection/ReturnValue.php'; - -/** - * Zend_Server_Reflection_Parameter - */ -#require_once 'Zend/Server/Reflection/Parameter.php'; +namespace Zend\Server\Reflection; /** * Method/Function prototypes @@ -35,39 +17,34 @@ * * @category Zend * @package Zend_Server - * @subpackage Reflection - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - * @version $Id: Prototype.php 20096 2010-01-06 02:05:09Z bkarwin $ + * @subpackage Zend_Server_Reflection */ -class Zend_Server_Reflection_Prototype +class Prototype { /** * Constructor * - * @param Zend_Server_Reflection_ReturnValue $return + * @param ReflectionReturnValue $return * @param array $params - * @return void + * @throws Exception\InvalidArgumentException */ - public function __construct(Zend_Server_Reflection_ReturnValue $return, $params = null) + public function __construct(ReflectionReturnValue $return, $params = null) { - $this->_return = $return; + $this->return = $return; if (!is_array($params) && (null !== $params)) { - #require_once 'Zend/Server/Reflection/Exception.php'; - throw new Zend_Server_Reflection_Exception('Invalid parameters'); + throw new Exception\InvalidArgumentException('Invalid parameters'); } if (is_array($params)) { foreach ($params as $param) { - if (!$param instanceof Zend_Server_Reflection_Parameter) { - #require_once 'Zend/Server/Reflection/Exception.php'; - throw new Zend_Server_Reflection_Exception('One or more params are invalid'); + if (!$param instanceof ReflectionParameter) { + throw new Exception\InvalidArgumentException('One or more params are invalid'); } } } - $this->_params = $params; + $this->params = $params; } /** @@ -77,27 +54,27 @@ class Zend_Server_Reflection_Prototype */ public function getReturnType() { - return $this->_return->getType(); + return $this->return->getType(); } /** * Retrieve the return value object * * @access public - * @return Zend_Server_Reflection_ReturnValue + * @return \Zend\Server\Reflection\ReflectionReturnValue */ public function getReturnValue() { - return $this->_return; + return $this->return; } /** * Retrieve method parameters * - * @return array Array of {@link Zend_Server_Reflection_Parameter}s + * @return array Array of {@link \Zend\Server\Reflection\ReflectionParameter}s */ public function getParameters() { - return $this->_params; + return $this->params; } } diff --git a/lib/Zend/Server/Reflection/ReflectionClass.php b/lib/Zend/Server/Reflection/ReflectionClass.php new file mode 100644 index 0000000000000000000000000000000000000000..d6e1d0c813b6f260c6f802695332012d66c4158f --- /dev/null +++ b/lib/Zend/Server/Reflection/ReflectionClass.php @@ -0,0 +1,181 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Server + */ + +namespace Zend\Server\Reflection; + +/** + * Class/Object reflection + * + * Proxies calls to a ReflectionClass object, and decorates getMethods() by + * creating its own list of {@link Zend_Server_Reflection_Method}s. + * + * @category Zend + * @package Zend_Server + * @subpackage Zend_Server_Reflection + */ +class ReflectionClass +{ + /** + * Optional configuration parameters; accessible via {@link __get} and + * {@link __set()} + * @var array + */ + protected $config = array(); + + /** + * Array of {@link \Zend\Server\Reflection\Method}s + * @var array + */ + protected $methods = array(); + + /** + * Namespace + * @var string + */ + protected $namespace = null; + + /** + * ReflectionClass object + * @var ReflectionClass + */ + protected $reflection; + + /** + * Constructor + * + * Create array of dispatchable methods, each a + * {@link Zend\Server\Reflection\ReflectionMethod}. Sets reflection object property. + * + * @param \ReflectionClass $reflection + * @param string $namespace + * @param mixed $argv + */ + public function __construct(\ReflectionClass $reflection, $namespace = null, $argv = false) + { + $this->reflection = $reflection; + $this->setNamespace($namespace); + + foreach ($reflection->getMethods() as $method) { + // Don't aggregate magic methods + if ('__' == substr($method->getName(), 0, 2)) { + continue; + } + + if ($method->isPublic()) { + // Get signatures and description + $this->methods[] = new ReflectionMethod($this, $method, $this->getNamespace(), $argv); + } + } + } + + /** + * Proxy reflection calls + * + * @param string $method + * @param array $args + * @throws Exception\BadMethodCallException + * @return mixed + */ + public function __call($method, $args) + { + if (method_exists($this->reflection, $method)) { + return call_user_func_array(array($this->reflection, $method), $args); + } + + throw new Exception\BadMethodCallException('Invalid reflection method'); + } + + /** + * Retrieve configuration parameters + * + * Values are retrieved by key from {@link $config}. Returns null if no + * value found. + * + * @param string $key + * @return mixed + */ + public function __get($key) + { + if (isset($this->config[$key])) { + return $this->config[$key]; + } + + return null; + } + + /** + * Set configuration parameters + * + * Values are stored by $key in {@link $config}. + * + * @param string $key + * @param mixed $value + * @return void + */ + public function __set($key, $value) + { + $this->config[$key] = $value; + } + + /** + * Return array of dispatchable {@link \Zend\Server\Reflection\Method}s. + * + * @access public + * @return array + */ + public function getMethods() + { + return $this->methods; + } + + /** + * Get namespace for this class + * + * @return string + */ + public function getNamespace() + { + return $this->namespace; + } + + /** + * Set namespace for this class + * + * @param string $namespace + * @throws Exception\InvalidArgumentException + * @return void + */ + public function setNamespace($namespace) + { + if (empty($namespace)) { + $this->namespace = ''; + return; + } + + if (!is_string($namespace) || !preg_match('/[a-z0-9_\.]+/i', $namespace)) { + throw new Exception\InvalidArgumentException('Invalid namespace'); + } + + $this->namespace = $namespace; + } + + /** + * Wakeup from serialization + * + * Reflection needs explicit instantiation to work correctly. Re-instantiate + * reflection object on wakeup. + * + * @return void + */ + public function __wakeup() + { + $this->reflection = new \ReflectionClass($this->getName()); + } +} diff --git a/lib/Zend/Server/Reflection/ReflectionFunction.php b/lib/Zend/Server/Reflection/ReflectionFunction.php new file mode 100644 index 0000000000000000000000000000000000000000..f39ceb8ae91894b361d15788148ac33d9e49a201 --- /dev/null +++ b/lib/Zend/Server/Reflection/ReflectionFunction.php @@ -0,0 +1,22 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Server + */ + +namespace Zend\Server\Reflection; + +/** + * Function Reflection + * + * @category Zend + * @package Zend_Server + * @subpackage Zend_Server_Reflection + */ +class ReflectionFunction extends AbstractFunction +{ +} diff --git a/lib/Zend/Server/Reflection/ReflectionMethod.php b/lib/Zend/Server/Reflection/ReflectionMethod.php new file mode 100644 index 0000000000000000000000000000000000000000..5df095db482a4c65dcb1ce02d9ffbb9384c4db33 --- /dev/null +++ b/lib/Zend/Server/Reflection/ReflectionMethod.php @@ -0,0 +1,92 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Server + */ + +namespace Zend\Server\Reflection; + +/** + * Method Reflection + * + * @category Zend + * @package Zend_Server + * @subpackage Zend_Server_Reflection + */ +class ReflectionMethod extends AbstractFunction +{ + /** + * Parent class name + * @var string + */ + protected $class; + + /** + * Parent class reflection + * @var ReflectionClass + */ + protected $classReflection; + + /** + * Constructor + * + * @param ReflectionClass $class + * @param \ReflectionMethod $r + * @param string $namespace + * @param array $argv + */ + public function __construct(ReflectionClass $class, \ReflectionMethod $r, $namespace = null, $argv = array()) + { + $this->classReflection = $class; + $this->reflection = $r; + + $classNamespace = $class->getNamespace(); + + // Determine namespace + if (!empty($namespace)) { + $this->setNamespace($namespace); + } elseif (!empty($classNamespace)) { + $this->setNamespace($classNamespace); + } + + // Determine arguments + if (is_array($argv)) { + $this->argv = $argv; + } + + // If method call, need to store some info on the class + $this->class = $class->getName(); + + // Perform some introspection + $this->_reflect(); + } + + /** + * Return the reflection for the class that defines this method + * + * @return \Zend\Server\Reflection\ReflectionClass + */ + public function getDeclaringClass() + { + return $this->classReflection; + } + + /** + * Wakeup from serialization + * + * Reflection needs explicit instantiation to work correctly. Re-instantiate + * reflection object on wakeup. + * + * @return void + */ + public function __wakeup() + { + $this->classReflection = new ReflectionClass(new \ReflectionClass($this->class), $this->getNamespace(), $this->getInvokeArguments()); + $this->reflection = new \ReflectionMethod($this->classReflection->getName(), $this->getName()); + } + +} diff --git a/lib/Zend/Server/Reflection/ReflectionParameter.php b/lib/Zend/Server/Reflection/ReflectionParameter.php new file mode 100644 index 0000000000000000000000000000000000000000..647172a458e7b862b62a7c85ef89f45448dfab2c --- /dev/null +++ b/lib/Zend/Server/Reflection/ReflectionParameter.php @@ -0,0 +1,150 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Server + */ + +namespace Zend\Server\Reflection; + +/** + * Parameter Reflection + * + * Decorates a ReflectionParameter to allow setting the parameter type + * + * @category Zend + * @package Zend_Server + * @subpackage Zend_Server_Reflection + */ +class ReflectionParameter +{ + /** + * @var ReflectionParameter + */ + protected $reflection; + + /** + * Parameter position + * @var int + */ + protected $position; + + /** + * Parameter type + * @var string + */ + protected $type; + + /** + * Parameter description + * @var string + */ + protected $description; + + /** + * Constructor + * + * @param \ReflectionParameter $r + * @param string $type Parameter type + * @param string $description Parameter description + */ + public function __construct(\ReflectionParameter $r, $type = 'mixed', $description = '') + { + $this->reflection = $r; + $this->setType($type); + $this->setDescription($description); + } + + /** + * Proxy reflection calls + * + * @param string $method + * @param array $args + * @throws Exception\BadMethodCallException + * @return mixed + */ + public function __call($method, $args) + { + if (method_exists($this->reflection, $method)) { + return call_user_func_array(array($this->reflection, $method), $args); + } + + throw new Exception\BadMethodCallException('Invalid reflection method'); + } + + /** + * Retrieve parameter type + * + * @return string + */ + public function getType() + { + return $this->type; + } + + /** + * Set parameter type + * + * @param string|null $type + * @throws Exception\InvalidArgumentException + * @return void + */ + public function setType($type) + { + if (!is_string($type) && (null !== $type)) { + throw new Exception\InvalidArgumentException('Invalid parameter type'); + } + + $this->type = $type; + } + + /** + * Retrieve parameter description + * + * @return string + */ + public function getDescription() + { + return $this->description; + } + + /** + * Set parameter description + * + * @param string|null $description + * @throws Exception\InvalidArgumentException + * @return void + */ + public function setDescription($description) + { + if (!is_string($description) && (null !== $description)) { + throw new Exception\InvalidArgumentException('Invalid parameter description'); + } + + $this->description = $description; + } + + /** + * Set parameter position + * + * @param int $index + * @return void + */ + public function setPosition($index) + { + $this->position = (int) $index; + } + + /** + * Return parameter position + * + * @return int + */ + public function getPosition() + { + return $this->position; + } +} diff --git a/lib/Zend/Server/Reflection/ReflectionReturnValue.php b/lib/Zend/Server/Reflection/ReflectionReturnValue.php new file mode 100644 index 0000000000000000000000000000000000000000..ef7fc68f2801b972f4450dc96506a3cf8c413307 --- /dev/null +++ b/lib/Zend/Server/Reflection/ReflectionReturnValue.php @@ -0,0 +1,99 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Server + */ + +namespace Zend\Server\Reflection; + +/** + * Return value reflection + * + * Stores the return value type and description + * + * @category Zend + * @package Zend_Server + * @subpackage Zend_Server_Reflection + */ +class ReflectionReturnValue +{ + /** + * Return value type + * @var string + */ + protected $type; + + /** + * Return value description + * @var string + */ + protected $description; + + /** + * Constructor + * + * @param string $type Return value type + * @param string $description Return value type + */ + public function __construct($type = 'mixed', $description = '') + { + $this->setType($type); + $this->setDescription($description); + } + + /** + * Retrieve parameter type + * + * @return string + */ + public function getType() + { + return $this->type; + } + + /** + * Set parameter type + * + * @param string|null $type + * @throws Exception\InvalidArgumentException + * @return void + */ + public function setType($type) + { + if (!is_string($type) && (null !== $type)) { + throw new Exception\InvalidArgumentException('Invalid parameter type'); + } + + $this->type = $type; + } + + /** + * Retrieve parameter description + * + * @return string + */ + public function getDescription() + { + return $this->description; + } + + /** + * Set parameter description + * + * @param string|null $description + * @throws Exception\InvalidArgumentException + * @return void + */ + public function setDescription($description) + { + if (!is_string($description) && (null !== $description)) { + throw new Exception\InvalidArgumentException('Invalid parameter description'); + } + + $this->description = $description; + } +} diff --git a/lib/Zend/Server/Reflection/ReturnValue.php b/lib/Zend/Server/Reflection/ReturnValue.php deleted file mode 100644 index 4943dc894accd1a4b42405876a049136414e7453..0000000000000000000000000000000000000000 --- a/lib/Zend/Server/Reflection/ReturnValue.php +++ /dev/null @@ -1,110 +0,0 @@ -<?php -/** - * Zend Framework - * - * LICENSE - * - * This source file is subject to the new BSD license that is bundled - * with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://framework.zend.com/license/new-bsd - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@zend.com so we can send you a copy immediately. - * - * @category Zend - * @package Zend_Server - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - */ - -/** - * Return value reflection - * - * Stores the return value type and description - * - * @category Zend - * @package Zend_Server - * @subpackage Reflection - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - * @version $Id: ReturnValue.php 20096 2010-01-06 02:05:09Z bkarwin $ - */ -class Zend_Server_Reflection_ReturnValue -{ - /** - * Return value type - * @var string - */ - protected $_type; - - /** - * Return value description - * @var string - */ - protected $_description; - - /** - * Constructor - * - * @param string $type Return value type - * @param string $description Return value type - */ - public function __construct($type = 'mixed', $description = '') - { - $this->setType($type); - $this->setDescription($description); - } - - /** - * Retrieve parameter type - * - * @return string - */ - public function getType() - { - return $this->_type; - } - - /** - * Set parameter type - * - * @param string|null $type - * @return void - */ - public function setType($type) - { - if (!is_string($type) && (null !== $type)) { - #require_once 'Zend/Server/Reflection/Exception.php'; - throw new Zend_Server_Reflection_Exception('Invalid parameter type'); - } - - $this->_type = $type; - } - - /** - * Retrieve parameter description - * - * @return string - */ - public function getDescription() - { - return $this->_description; - } - - /** - * Set parameter description - * - * @param string|null $description - * @return void - */ - public function setDescription($description) - { - if (!is_string($description) && (null !== $description)) { - #require_once 'Zend/Server/Reflection/Exception.php'; - throw new Zend_Server_Reflection_Exception('Invalid parameter description'); - } - - $this->_description = $description; - } -} diff --git a/lib/Zend/Server/Server.php b/lib/Zend/Server/Server.php new file mode 100644 index 0000000000000000000000000000000000000000..f25a05ca2248e46cc871792d088a69dfb6412163 --- /dev/null +++ b/lib/Zend/Server/Server.php @@ -0,0 +1,131 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Server + */ + +namespace Zend\Server; + +/** + * Server Interface + * + * @category Zend + * @package Zend_Server + */ +interface Server +{ + /** + * Attach a function as a server method + * + * Namespacing is primarily for xmlrpc, but may be used with other + * implementations to prevent naming collisions. + * + * @param string $function + * @param string $namespace + * @param null|array Optional array of arguments to pass to callback at + * dispatch. + * @return void + */ + public function addFunction($function, $namespace = ''); + + /** + * Attach a class to a server + * + * The individual implementations should probably allow passing a variable + * number of arguments in, so that developers may define custom runtime + * arguments to pass to server methods. + * + * Namespacing is primarily for xmlrpc, but could be used for other + * implementations as well. + * + * @param mixed $class Class name or object instance to examine and attach + * to the server. + * @param string $namespace Optional namespace with which to prepend method + * names in the dispatch table. + * methods in the class will be valid callbacks. + * @param null|array Optional array of arguments to pass to callbacks at + * dispatch. + * @return void + */ + public function setClass($class, $namespace = '', $argv = null); + + /** + * Generate a server fault + * + * @param mixed $fault + * @param int $code + * @return mixed + */ + public function fault($fault = null, $code = 404); + + /** + * Handle a request + * + * Requests may be passed in, or the server may automagically determine the + * request based on defaults. Dispatches server request to appropriate + * method and returns a response + * + * @param mixed $request + * @return mixed + */ + public function handle($request = false); + + /** + * Return a server definition array + * + * Returns a server definition array as created using + * {@link Reflection}. Can be used for server introspection, + * documentation, or persistence. + * + * @return array + */ + public function getFunctions(); + + /** + * Load server definition + * + * Used for persistence; loads a construct as returned by {@link getFunctions()}. + * + * @param array $definition + * @return void + */ + public function loadFunctions($definition); + + /** + * Set server persistence + * + * @todo Determine how to implement this + * @param int $mode + * @return void + */ + public function setPersistence($mode); + + /** + * Sets auto-response flag for the server. + * + * To unify all servers, default behavior should be to auto-emit response. + * + * @param bool $flag + * @return Server Self instance. + */ + public function setReturnResponse($flag = true); + + /** + * Returns auto-response flag of the server. + * + * @return bool $flag Current status. + */ + public function getReturnResponse(); + + /** + * Returns last produced response. + * + * @return string|object Content of last response, or response object that + * implements __toString() methods. + */ + public function getResponse(); +} diff --git a/lib/Zend/Server/composer.json b/lib/Zend/Server/composer.json new file mode 100644 index 0000000000000000000000000000000000000000..69400a24eb786e2a9af0184ffb368be5cd469ecc --- /dev/null +++ b/lib/Zend/Server/composer.json @@ -0,0 +1,19 @@ +{ + "name": "zendframework/zend-server", + "description": " ", + "license": "BSD-3-Clause", + "keywords": [ + "zf2", + "server" + ], + "autoload": { + "psr-0": { + "Zend\\Server": "" + } + }, + "target-dir": "Zend/Server", + "require": { + "php": ">=5.3.3", + "zendframework/zend-stdlib": "self.version" + } +} diff --git a/lib/Zend/Soap/AutoDiscover.php b/lib/Zend/Soap/AutoDiscover.php index 8a7cdea107c79d785b5c20129070349ca3b6ff98..b6af97ff305fbc854718f0616c3de9ebeaa5d192 100644 --- a/lib/Zend/Soap/AutoDiscover.php +++ b/lib/Zend/Soap/AutoDiscover.php @@ -1,144 +1,220 @@ <?php /** - * Zend Framework + * Zend Framework (http://framework.zend.com/) * - * LICENSE - * - * This source file is subject to the new BSD license that is bundled - * with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://framework.zend.com/license/new-bsd - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@zend.com so we can send you a copy immediately. - * - * @category Zend - * @package Zend_Soap - * @subpackage AutoDiscover - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - * @version $Id: AutoDiscover.php 23338 2010-11-15 14:59:33Z alexander $ + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Soap */ -/** - * @see Zend_Server_Interface - */ -#require_once 'Zend/Server/Interface.php'; -/** - * @see Zend_Soap_Wsdl - */ -#require_once 'Zend/Soap/Wsdl.php'; -/** - * @see Zend_Server_Reflection - */ -#require_once 'Zend/Server/Reflection.php'; -/** - * @see Zend_Server_Abstract - */ -#require_once 'Zend/Server/Abstract.php'; -/** - * @see Zend_Uri - */ -#require_once 'Zend/Uri.php'; +namespace Zend\Soap; + +use Zend\Server\Reflection; +use Zend\Server\Reflection\AbstractFunction; +use Zend\Server\Reflection\Prototype; +use Zend\Server\Reflection\ReflectionParameter; +use Zend\Soap\AutoDiscover\DiscoveryStrategy\DiscoveryStrategyInterface as DiscoveryStrategy; +use Zend\Soap\AutoDiscover\DiscoveryStrategy\ReflectionDiscovery; +use Zend\Soap\Wsdl; +use Zend\Soap\Wsdl\ComplexTypeStrategy\ComplexTypeStrategyInterface as ComplexTypeStrategy; +use Zend\Uri; /** - * Zend_Soap_AutoDiscover + * \Zend\Soap\AutoDiscover * * @category Zend * @package Zend_Soap * @subpackage AutoDiscover */ -class Zend_Soap_AutoDiscover implements Zend_Server_Interface +class AutoDiscover { /** - * @var Zend_Soap_Wsdl + * @var string */ - protected $_wsdl = null; + protected $serviceName; /** - * @var Zend_Server_Reflection + * @var \Zend\Server\Reflection */ - protected $_reflection = null; + protected $reflection = null; /** + * Service function names + * * @var array */ - protected $_functions = array(); + protected $functions = array(); + + /** + * Service class name + * + * @var string + */ + protected $class; /** * @var boolean */ - protected $_strategy; + protected $strategy; /** * Url where the WSDL file will be available at. * * @var WSDL Uri */ - protected $_uri; + protected $uri; /** * soap:body operation style options * * @var array */ - protected $_operationBodyStyle = array('use' => 'encoded', 'encodingStyle' => "http://schemas.xmlsoap.org/soap/encoding/"); + protected $operationBodyStyle = array('use' => 'encoded', 'encodingStyle' => "http://schemas.xmlsoap.org/soap/encoding/"); /** * soap:operation style * * @var array */ - protected $_bindingStyle = array('style' => 'rpc', 'transport' => 'http://schemas.xmlsoap.org/soap/http'); + protected $bindingStyle = array('style' => 'rpc', 'transport' => 'http://schemas.xmlsoap.org/soap/http'); /** * Name of the class to handle the WSDL creation. * * @var string */ - protected $_wsdlClass = 'Zend_Soap_Wsdl'; + protected $wsdlClass = 'Zend\Soap\Wsdl'; + + /** + * Class Map of PHP to WSDL types. + * + * @var array + */ + protected $classMap = array(); + + /** + * Discovery strategy for types and other method details. + * + * @var DiscoveryStrategy + */ + protected $discoveryStrategy; /** * Constructor * - * @param boolean|string|Zend_Soap_Wsdl_Strategy_Interface $strategy - * @param string|Zend_Uri $uri + * @param ComplexTypeStrategy $strategy + * @param string|Uri\Uri $endpointUri * @param string $wsdlClass + * @param array $classMap */ - public function __construct($strategy = true, $uri=null, $wsdlClass=null) + public function __construct(ComplexTypeStrategy $strategy = null, $endpointUri=null, $wsdlClass=null, array $classMap = array()) { - $this->_reflection = new Zend_Server_Reflection(); - $this->setComplexTypeStrategy($strategy); + $this->reflection = new Reflection(); + $this->discoveryStrategy = new ReflectionDiscovery(); + + if ($strategy !== null) { + $this->setComplexTypeStrategy($strategy); + } - if($uri !== null) { - $this->setUri($uri); + if ($endpointUri !== null) { + $this->setUri($endpointUri); } - if($wsdlClass !== null) { + if ($wsdlClass !== null) { $this->setWsdlClass($wsdlClass); } } /** - * Set the location at which the WSDL file will be availabe. + * Set the discovery strategy for method type and other information. * - * @see Zend_Soap_Exception - * @param Zend_Uri|string $uri - * @return Zend_Soap_AutoDiscover - * @throws Zend_Soap_AutoDiscover_Exception + * @param DiscoveryStrategy $discoveryStrategy + * @return AutoDiscover */ - public function setUri($uri) + public function setDiscoveryStrategy(DiscoveryStrategy $discoveryStrategy) { - if (!is_string($uri) && !($uri instanceof Zend_Uri)) { - #require_once "Zend/Soap/AutoDiscover/Exception.php"; - throw new Zend_Soap_AutoDiscover_Exception("No uri given to Zend_Soap_AutoDiscover::setUri as string or Zend_Uri instance."); + $this->discoveryStrategy = $discoveryStrategy; + return $this; + } + + /** + * @return DiscoveryStrategy + */ + public function getDiscoveryStrategy() + { + return $this->discoveryStrategy; + } + + /** + * Get the class map of php to wsdl qname types. + * + * @return array + */ + public function getClassMap() + { + return $this->classMap; + } + + /** + * Set the class map of php to wsdl qname types. + */ + public function setClassMap($classMap) + { + $this->classMap = $classMap; + return $this; + } + + /** + * Set service name + * + * @param string $serviceName + * @return AutoDiscover + */ + public function setServiceName($serviceName) + { + $this->serviceName = $serviceName; + return $this; + } + + /** + * Get service name + * + * @return string + * @throws Exception\RuntimeException + */ + public function getServiceName() + { + if (!$this->serviceName) { + if ($this->class) { + return $this->reflection->reflectClass($this->class) + ->getShortName(); + } else { + throw new Exception\RuntimeException( + "No service name given. Call Autodiscover#setServiceName()." + ); + } } - $this->_uri = $uri; - // change uri in WSDL file also if existant - if ($this->_wsdl instanceof Zend_Soap_Wsdl) { - $this->_wsdl->setUri($uri); + return $this->serviceName; + } + + + /** + * Set the location at which the WSDL file will be availabe. + * + * @param Uri\Uri|string $uri + * @return AutoDiscover + * @throws Exception\InvalidArgumentException + */ + public function setUri($uri) + { + if (!is_string($uri) && !($uri instanceof Uri\Uri)) { + throw new Exception\InvalidArgumentException( + 'No uri given to \Zend\Soap\AutoDiscover::setUri as string or \Zend\Uri\Uri instance.' + ); } + $this->uri = $uri; return $this; } @@ -146,38 +222,36 @@ class Zend_Soap_AutoDiscover implements Zend_Server_Interface /** * Return the current Uri that the SOAP WSDL Service will be located at. * - * @return Zend_Uri + * @return Uri\Uri + * @throws Exception\RuntimeException */ public function getUri() { - if($this->_uri !== null) { - $uri = $this->_uri; - } else { - $schema = $this->getSchema(); - $host = $this->getHostName(); - $scriptName = $this->getRequestUriWithoutParameters(); - $uri = Zend_Uri::factory($schema . '://' . $host . $scriptName); - $this->setUri($uri); + if ($this->uri === null) { + throw new Exception\RuntimeException("Missing uri. You have to explicitly configure the Endpoint Uri by calling AutoDiscover#setUri()."); } - return $uri; + if (is_string($this->uri)) { + $this->uri = Uri\UriFactory::factory($this->uri); + } + + return $this->uri; } /** * Set the name of the WSDL handling class. * - * @see Zend_Soap_Exception - * @see Zend_Soap_Exception * @param string $wsdlClass - * @return Zend_Soap_AutoDiscover - * @throws Zend_Soap_AutoDiscover_Exception + * @return AutoDiscover + * @throws Exception\InvalidArgumentException */ public function setWsdlClass($wsdlClass) { - if (!is_string($wsdlClass) && !is_subclass_of($wsdlClass, 'Zend_Soap_Wsdl')) { - #require_once "Zend/Soap/AutoDiscover/Exception.php"; - throw new Zend_Soap_AutoDiscover_Exception("No Zend_Soap_Wsdl subclass given to Zend_Soap_AutoDiscover::setWsdlClass as string."); + if (!is_string($wsdlClass) && !is_subclass_of($wsdlClass, 'Zend\Soap\Wsdl')) { + throw new Exception\InvalidArgumentException( + 'No \Zend\Soap\Wsdl subclass given to Zend\Soap\AutoDiscover::setWsdlClass as string.' + ); } - $this->_wsdlClass = $wsdlClass; + $this->wsdlClass = $wsdlClass; return $this; } @@ -189,7 +263,7 @@ class Zend_Soap_AutoDiscover implements Zend_Server_Interface */ public function getWsdlClass() { - return $this->_wsdlClass; + return $this->wsdlClass; } /** @@ -198,18 +272,16 @@ class Zend_Soap_AutoDiscover implements Zend_Server_Interface * By default the options are set to 'use' => 'encoded' and * 'encodingStyle' => "http://schemas.xmlsoap.org/soap/encoding/". * - * @see Zend_Soap_AutoDiscover_Exception * @param array $operationStyle - * @return Zend_Soap_AutoDiscover - * @throws Zend_Soap_AutoDiscover_Exception + * @return AutoDiscover + * @throws Exception\InvalidArgumentException */ public function setOperationBodyStyle(array $operationStyle=array()) { - if(!isset($operationStyle['use'])) { - #require_once "Zend/Soap/AutoDiscover/Exception.php"; - throw new Zend_Soap_AutoDiscover_Exception("Key 'use' is required in Operation soap:body style."); + if (!isset($operationStyle['use'])) { + throw new Exception\InvalidArgumentException("Key 'use' is required in Operation soap:body style."); } - $this->_operationBodyStyle = $operationStyle; + $this->operationBodyStyle = $operationStyle; return $this; } @@ -219,169 +291,118 @@ class Zend_Soap_AutoDiscover implements Zend_Server_Interface * By default 'style' is 'rpc' and 'transport' is 'http://schemas.xmlsoap.org/soap/http'. * * @param array $bindingStyle - * @return Zend_Soap_AutoDiscover + * @return AutoDiscover */ public function setBindingStyle(array $bindingStyle=array()) { - if(isset($bindingStyle['style'])) { - $this->_bindingStyle['style'] = $bindingStyle['style']; + if (isset($bindingStyle['style'])) { + $this->bindingStyle['style'] = $bindingStyle['style']; } - if(isset($bindingStyle['transport'])) { - $this->_bindingStyle['transport'] = $bindingStyle['transport']; + if (isset($bindingStyle['transport'])) { + $this->bindingStyle['transport'] = $bindingStyle['transport']; } return $this; } /** - * Detect and returns the current HTTP/HTTPS Schema + * Set the strategy that handles functions and classes that are added AFTER this call. * - * @return string + * @param ComplexTypeStrategy $strategy + * @return AutoDiscover */ - protected function getSchema() + public function setComplexTypeStrategy(ComplexTypeStrategy $strategy) { - $schema = "http"; - if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') { - $schema = 'https'; - } - return $schema; + $this->strategy = $strategy; + + return $this; } /** - * Detect and return the current hostname + * Set the Class the SOAP server will use * - * @return string + * @param string $class Class Name + * @return AutoDiscover */ - protected function getHostName() + public function setClass($class) { - if(isset($_SERVER['HTTP_HOST'])) { - $host = $_SERVER['HTTP_HOST']; - } else { - $host = $_SERVER['SERVER_NAME']; - } - return $host; + $this->class = $class; + return $this; } /** - * Detect and return the current script name without parameters + * Add a Single or Multiple Functions to the WSDL * - * @return string + * @param string $function Function Name + * @return AutoDiscover */ - protected function getRequestUriWithoutParameters() + public function addFunction($function) { - if (isset($_SERVER['HTTP_X_REWRITE_URL'])) { // check this first so IIS will catch - $requestUri = $_SERVER['HTTP_X_REWRITE_URL']; - } elseif (isset($_SERVER['REQUEST_URI'])) { - $requestUri = $_SERVER['REQUEST_URI']; - } elseif (isset($_SERVER['ORIG_PATH_INFO'])) { // IIS 5.0, PHP as CGI - $requestUri = $_SERVER['ORIG_PATH_INFO']; - } else { - $requestUri = $_SERVER['SCRIPT_NAME']; - } - if( ($pos = strpos($requestUri, "?")) !== false) { - $requestUri = substr($requestUri, 0, $pos); - } - - return $requestUri; + $this->functions[] = $function; + return $this; } /** - * Set the strategy that handles functions and classes that are added AFTER this call. + * Generate the WSDL for a service class. * - * @param boolean|string|Zend_Soap_Wsdl_Strategy_Interface $strategy - * @return Zend_Soap_AutoDiscover + * @return Wsdl */ - public function setComplexTypeStrategy($strategy) + protected function _generateClass() { - $this->_strategy = $strategy; - if($this->_wsdl instanceof Zend_Soap_Wsdl) { - $this->_wsdl->setComplexTypeStrategy($strategy); - } - - return $this; + return $this->_generateWsdl($this->reflection->reflectClass($this->class)->getMethods()); } /** - * Set the Class the SOAP server will use + * Generate the WSDL for a set of functions. * - * @param string $class Class Name - * @param string $namespace Class Namspace - Not Used - * @param array $argv Arguments to instantiate the class - Not Used - * @return Zend_Soap_AutoDiscover + * @return Wsdl */ - public function setClass($class, $namespace = '', $argv = null) + protected function _generateFunctions() { - $uri = $this->getUri(); - - $wsdl = new $this->_wsdlClass($class, $uri, $this->_strategy); - - // The wsdl:types element must precede all other elements (WS-I Basic Profile 1.1 R2023) - $wsdl->addSchemaTypeSection(); - - $port = $wsdl->addPortType($class . 'Port'); - $binding = $wsdl->addBinding($class . 'Binding', 'tns:' .$class. 'Port'); - - $wsdl->addSoapBinding($binding, $this->_bindingStyle['style'], $this->_bindingStyle['transport']); - $wsdl->addService($class . 'Service', $class . 'Port', 'tns:' . $class . 'Binding', $uri); - foreach ($this->_reflection->reflectClass($class)->getMethods() as $method) { - $this->_addFunctionToWsdl($method, $wsdl, $port, $binding); + $methods = array(); + foreach (array_unique($this->functions) as $func) { + $methods[] = $this->reflection->reflectFunction($func); } - $this->_wsdl = $wsdl; - return $this; + return $this->_generateWsdl($methods); } /** - * Add a Single or Multiple Functions to the WSDL + * Generate the WSDL for a set of reflection method instances. * - * @param string $function Function Name - * @param string $namespace Function namespace - Not Used - * @return Zend_Soap_AutoDiscover + * @param array $reflectionMethods + * @return Wsdl */ - public function addFunction($function, $namespace = '') + protected function _generateWsdl(array $reflectionMethods) { - static $port; - static $operation; - static $binding; - - if (!is_array($function)) { - $function = (array) $function; - } - $uri = $this->getUri(); - if (!($this->_wsdl instanceof Zend_Soap_Wsdl)) { - $parts = explode('.', basename($_SERVER['SCRIPT_NAME'])); - $name = $parts[0]; - $wsdl = new Zend_Soap_Wsdl($name, $uri, $this->_strategy); + $serviceName = $this->getServiceName(); + $wsdl = new $this->wsdlClass($serviceName, $uri, $this->strategy, $this->classMap); - // The wsdl:types element must precede all other elements (WS-I Basic Profile 1.1 R2023) - $wsdl->addSchemaTypeSection(); + // The wsdl:types element must precede all other elements (WS-I Basic Profile 1.1 R2023) + $wsdl->addSchemaTypeSection(); - $port = $wsdl->addPortType($name . 'Port'); - $binding = $wsdl->addBinding($name . 'Binding', 'tns:' .$name. 'Port'); + $port = $wsdl->addPortType($serviceName . 'Port'); + $binding = $wsdl->addBinding($serviceName . 'Binding', 'tns:' . $serviceName . 'Port'); - $wsdl->addSoapBinding($binding, $this->_bindingStyle['style'], $this->_bindingStyle['transport']); - $wsdl->addService($name . 'Service', $name . 'Port', 'tns:' . $name . 'Binding', $uri); - } else { - $wsdl = $this->_wsdl; - } + $wsdl->addSoapBinding($binding, $this->bindingStyle['style'], $this->bindingStyle['transport']); + $wsdl->addService($serviceName . 'Service', $serviceName . 'Port', 'tns:' . $serviceName . 'Binding', $uri); - foreach ($function as $func) { - $method = $this->_reflection->reflectFunction($func); + foreach ($reflectionMethods as $method) { $this->_addFunctionToWsdl($method, $wsdl, $port, $binding); } - $this->_wsdl = $wsdl; - return $this; + return $wsdl; } /** * Add a function to the WSDL document. * - * @param $function Zend_Server_Reflection_Function_Abstract function to add - * @param $wsdl Zend_Soap_Wsdl WSDL document + * @param $function \Zend\Server\Reflection\AbstractFunction function to add + * @param $wsdl \Zend\Soap\Wsdl WSDL document * @param $port object wsdl:portType * @param $binding object wsdl:binding + * @throws Exception\InvalidArgumentException * @return void */ protected function _addFunctionToWsdl($function, $wsdl, $port, $binding) @@ -399,19 +420,20 @@ class Zend_Soap_AutoDiscover implements Zend_Server_Interface } } if ($prototype === null) { - #require_once "Zend/Soap/AutoDiscover/Exception.php"; - throw new Zend_Soap_AutoDiscover_Exception("No prototypes could be found for the '" . $function->getName() . "' function"); + throw new Exception\InvalidArgumentException("No prototypes could be found for the '" . $function->getName() . "' function"); } + $functionName = $wsdl->translateType($function->getName()); + // Add the input message (parameters) $args = array(); - if ($this->_bindingStyle['style'] == 'document') { + if ($this->bindingStyle['style'] == 'document') { // Document style: wrap all parameters in a sequence element $sequence = array(); foreach ($prototype->getParameters() as $param) { $sequenceElement = array( 'name' => $param->getName(), - 'type' => $wsdl->getType($param->getType()) + 'type' => $wsdl->getType($this->discoveryStrategy->getFunctionParameterType($param)) ); if ($param->isOptional()) { $sequenceElement['nillable'] = 'true'; @@ -419,7 +441,7 @@ class Zend_Soap_AutoDiscover implements Zend_Server_Interface $sequence[] = $sequenceElement; } $element = array( - 'name' => $function->getName(), + 'name' => $functionName, 'sequence' => $sequence ); // Add the wrapper element part, which must be named 'parameters' @@ -427,183 +449,105 @@ class Zend_Soap_AutoDiscover implements Zend_Server_Interface } else { // RPC style: add each parameter as a typed part foreach ($prototype->getParameters() as $param) { - $args[$param->getName()] = array('type' => $wsdl->getType($param->getType())); + $args[$param->getName()] = array('type' => $wsdl->getType($this->discoveryStrategy->getFunctionParameterType($param))); } } - $wsdl->addMessage($function->getName() . 'In', $args); + $wsdl->addMessage($functionName . 'In', $args); - $isOneWayMessage = false; - if($prototype->getReturnType() == "void") { - $isOneWayMessage = true; - } + $isOneWayMessage = $this->discoveryStrategy->isFunctionOneWay($function, $prototype); - if($isOneWayMessage == false) { + if ($isOneWayMessage == false) { // Add the output message (return value) $args = array(); - if ($this->_bindingStyle['style'] == 'document') { + if ($this->bindingStyle['style'] == 'document') { // Document style: wrap the return value in a sequence element $sequence = array(); if ($prototype->getReturnType() != "void") { $sequence[] = array( - 'name' => $function->getName() . 'Result', - 'type' => $wsdl->getType($prototype->getReturnType()) + 'name' => $functionName . 'Result', + 'type' => $wsdl->getType($this->discoveryStrategy->getFunctionReturnType($function, $prototype)) ); } $element = array( - 'name' => $function->getName() . 'Response', + 'name' => $functionName . 'Response', 'sequence' => $sequence ); // Add the wrapper element part, which must be named 'parameters' $args['parameters'] = array('element' => $wsdl->addElement($element)); - } else if ($prototype->getReturnType() != "void") { + } elseif ($prototype->getReturnType() != "void") { // RPC style: add the return value as a typed part - $args['return'] = array('type' => $wsdl->getType($prototype->getReturnType())); + $args['return'] = array('type' => $wsdl->getType($this->discoveryStrategy->getFunctionReturnType($function, $prototype))); } - $wsdl->addMessage($function->getName() . 'Out', $args); + $wsdl->addMessage($functionName . 'Out', $args); } // Add the portType operation - if($isOneWayMessage == false) { - $portOperation = $wsdl->addPortOperation($port, $function->getName(), 'tns:' . $function->getName() . 'In', 'tns:' . $function->getName() . 'Out'); + if ($isOneWayMessage == false) { + $portOperation = $wsdl->addPortOperation($port, $functionName, 'tns:' . $functionName . 'In', 'tns:' . $functionName . 'Out'); } else { - $portOperation = $wsdl->addPortOperation($port, $function->getName(), 'tns:' . $function->getName() . 'In', false); + $portOperation = $wsdl->addPortOperation($port, $functionName, 'tns:' . $functionName . 'In', false); } - $desc = $function->getDescription(); + $desc = $this->discoveryStrategy->getFunctionDocumentation($function); if (strlen($desc) > 0) { $wsdl->addDocumentation($portOperation, $desc); } // When using the RPC style, make sure the operation style includes a 'namespace' attribute (WS-I Basic Profile 1.1 R2717) - if ($this->_bindingStyle['style'] == 'rpc' && !isset($this->_operationBodyStyle['namespace'])) { - $this->_operationBodyStyle['namespace'] = ''.$uri; + $operationBodyStyle = $this->operationBodyStyle; + if ($this->bindingStyle['style'] == 'rpc' && !isset($operationBodyStyle['namespace'])) { + $operationBodyStyle['namespace'] = '' . $uri; } // Add the binding operation - if($isOneWayMessage == false) { - $operation = $wsdl->addBindingOperation($binding, $function->getName(), $this->_operationBodyStyle, $this->_operationBodyStyle); + if ($isOneWayMessage == false) { + $operation = $wsdl->addBindingOperation($binding, $functionName, $operationBodyStyle, $operationBodyStyle); } else { - $operation = $wsdl->addBindingOperation($binding, $function->getName(), $this->_operationBodyStyle); + $operation = $wsdl->addBindingOperation($binding, $functionName, $operationBodyStyle); } - $wsdl->addSoapOperation($operation, $uri . '#' .$function->getName()); - - // Add the function name to the list - $this->_functions[] = $function->getName(); + $wsdl->addSoapOperation($operation, $uri . '#' . $functionName); } /** - * Action to take when an error occurs + * Generate the WSDL file from the configured input. * - * @param string $fault - * @param string|int $code - * @throws Zend_Soap_AutoDiscover_Exception + * @throws Exception\RuntimeException + * @return Wsdl */ - public function fault($fault = null, $code = null) + public function generate() { - #require_once "Zend/Soap/AutoDiscover/Exception.php"; - throw new Zend_Soap_AutoDiscover_Exception("Function has no use in AutoDiscover."); - } + if ($this->class && $this->functions) { + throw new Exception\RuntimeException("Can either dump functions or a class as a service, not both."); + } - /** - * Handle the Request - * - * @param string $request A non-standard request - Not Used - */ - public function handle($request = false) - { - if (!headers_sent()) { - header('Content-Type: text/xml'); + if ($this->class) { + $wsdl = $this->_generateClass(); + } else { + $wsdl = $this->_generateFunctions(); } - $this->_wsdl->dump(); + + return $wsdl; } /** * Proxy to WSDL dump function * * @param string $filename - * @return boolean - * @throws Zend_Soap_AutoDiscover_Exception + * @return bool + * @throws \Zend\Soap\Exception\RuntimeException */ public function dump($filename) { - if($this->_wsdl !== null) { - return $this->_wsdl->dump($filename); - } else { - /** - * @see Zend_Soap_AutoDiscover_Exception - */ - #require_once "Zend/Soap/AutoDiscover/Exception.php"; - throw new Zend_Soap_AutoDiscover_Exception("Cannot dump autodiscovered contents, WSDL file has not been generated yet."); - } + return $this->generate()->dump($filename); } /** * Proxy to WSDL toXml() function * * @return string - * @throws Zend_Soap_AutoDiscover_Exception + * @throws \Zend\Soap\Exception\RuntimeException */ public function toXml() { - if($this->_wsdl !== null) { - return $this->_wsdl->toXml(); - } else { - /** - * @see Zend_Soap_AutoDiscover_Exception - */ - #require_once "Zend/Soap/AutoDiscover/Exception.php"; - throw new Zend_Soap_AutoDiscover_Exception("Cannot return autodiscovered contents, WSDL file has not been generated yet."); - } - } - - /** - * Return an array of functions in the WSDL - * - * @return array - */ - public function getFunctions() - { - return $this->_functions; - } - - /** - * Load Functions - * - * @param unknown_type $definition - * @throws Zend_Soap_AutoDiscover_Exception - */ - public function loadFunctions($definition) - { - #require_once "Zend/Soap/AutoDiscover/Exception.php"; - throw new Zend_Soap_AutoDiscover_Exception("Function has no use in AutoDiscover."); - } - - /** - * Set Persistance - * - * @param int $mode - * @throws Zend_Soap_AutoDiscover_Exception - */ - public function setPersistence($mode) - { - #require_once "Zend/Soap/AutoDiscover/Exception.php"; - throw new Zend_Soap_AutoDiscover_Exception("Function has no use in AutoDiscover."); - } - - /** - * Returns an XSD Type for the given PHP type - * - * @param string $type PHP Type to get the XSD type for - * @return string - */ - public function getType($type) - { - if (!($this->_wsdl instanceof Zend_Soap_Wsdl)) { - /** @todo Exception throwing may be more correct */ - - // WSDL is not defined yet, so we can't recognize type in context of current service - return ''; - } else { - return $this->_wsdl->getType($type); - } + return $this->generate()->toXml(); } } diff --git a/lib/Zend/Soap/AutoDiscover/DiscoveryStrategy/DiscoveryStrategyInterface.php b/lib/Zend/Soap/AutoDiscover/DiscoveryStrategy/DiscoveryStrategyInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..e02ff7f8e0232f6e8c0bdd7eb474323a45f7bbfc --- /dev/null +++ b/lib/Zend/Soap/AutoDiscover/DiscoveryStrategy/DiscoveryStrategyInterface.php @@ -0,0 +1,67 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Soap + */ + +namespace Zend\Soap\AutoDiscover\DiscoveryStrategy; + +use Zend\Server\Reflection\AbstractFunction; +use Zend\Server\Reflection\Prototype; +use Zend\Server\Reflection\ReflectionParameter; + +/** + * Describes how types, return values and method details are detected during AutoDiscovery of a WSDL. + * + * @category Zend + * @package Zend_Soap + * @subpackage WSDL + */ +interface DiscoveryStrategyInterface +{ + /** + * Get the function parameters php type. + * + * Default implementation assumes the default param doc-block tag. + * + * @param ReflectionParameter $param + * @return string + */ + public function getFunctionParameterType(ReflectionParameter $param); + + /** + * Get the functions return php type. + * + * Default implementation assumes the value of the return doc-block tag. + * + * @param AbstractFunction $function + * @param Prototype $prototype + * @return string + */ + public function getFunctionReturnType(AbstractFunction $function, Prototype $prototype); + + /** + * Detect if the function is a one-way or two-way operation. + * + * Default implementation assumes one-way, when return value is "void". + * + * @param AbstractFunction $function + * @param Prototype $prototype + * @return bool + */ + public function isFunctionOneWay(AbstractFunction $function, Prototype $prototype); + + /** + * Detect the functions documentation. + * + * Default implementation uses docblock description. + * + * @param AbstractFunction $function + * @return string + */ + public function getFunctionDocumentation(AbstractFunction $function); +} diff --git a/lib/Zend/Soap/AutoDiscover/DiscoveryStrategy/ReflectionDiscovery.php b/lib/Zend/Soap/AutoDiscover/DiscoveryStrategy/ReflectionDiscovery.php new file mode 100644 index 0000000000000000000000000000000000000000..bc025d2bc521d6a316e87fa1072509337fcbd7f7 --- /dev/null +++ b/lib/Zend/Soap/AutoDiscover/DiscoveryStrategy/ReflectionDiscovery.php @@ -0,0 +1,46 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Soap + */ + +namespace Zend\Soap\AutoDiscover\DiscoveryStrategy; + +use Zend\Server\Reflection\AbstractFunction; +use Zend\Server\Reflection\Prototype; +use Zend\Server\Reflection\ReflectionParameter; + +/** + * Describes how types, return values and method details are detected during AutoDiscovery of a WSDL. + * + * @category Zend + * @package Zend_Soap + * @subpackage WSDL + */ + +class ReflectionDiscovery implements DiscoveryStrategyInterface +{ + public function getFunctionDocumentation(AbstractFunction $function) + { + return $function->getDescription(); + } + + public function getFunctionParameterType(ReflectionParameter $param) + { + return $param->getType(); + } + + public function getFunctionReturnType(AbstractFunction $function, Prototype $prototype) + { + return $prototype->getReturnType(); + } + + public function isFunctionOneWay(AbstractFunction $function, Prototype $prototype) + { + return $prototype->getReturnType() == 'void'; + } +} diff --git a/lib/Zend/Soap/AutoDiscover/Exception.php b/lib/Zend/Soap/AutoDiscover/Exception.php deleted file mode 100644 index d4b41481961989c04191b374ad3ffd7f924a66d1..0000000000000000000000000000000000000000 --- a/lib/Zend/Soap/AutoDiscover/Exception.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php -/** - * Zend Framework - * - * LICENSE - * - * This source file is subject to the new BSD license that is bundled - * with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://framework.zend.com/license/new-bsd - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@zend.com so we can send you a copy immediately. - * - * @category Zend - * @package Zend_Soap - * @subpackage AutoDiscover - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - * @version $Id: Exception.php 20096 2010-01-06 02:05:09Z bkarwin $ - */ - -/** - * @see Zend_Exception - */ -#require_once "Zend/Exception.php"; - -/** - * @package Zend_Soap - * @subpackage AutoDiscover - */ -class Zend_Soap_AutoDiscover_Exception extends Zend_Exception -{ -} diff --git a/lib/Zend/Soap/Client.php b/lib/Zend/Soap/Client.php index 96bcc006aa573e6c068fda3618eb044d70499268..5d137fc2becf7c8eeccb17727d30d2d3f1c6b54c 100644 --- a/lib/Zend/Soap/Client.php +++ b/lib/Zend/Soap/Client.php @@ -1,116 +1,93 @@ <?php /** - * Zend Framework + * Zend Framework (http://framework.zend.com/) * - * LICENSE - * - * This source file is subject to the new BSD license that is bundled - * with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://framework.zend.com/license/new-bsd - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@zend.com so we can send you a copy immediately. - * - * @category Zend - * @package Zend_Soap - * @subpackage Client - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - * @version $Id: Client.php 23453 2010-11-28 13:56:14Z ramon $ + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Soap */ -/** - * @see Zend_Soap_Server - */ -#require_once 'Zend/Soap/Server.php'; +namespace Zend\Soap; -/** - * @see Zend_Soap_Client_Local - */ -#require_once 'Zend/Soap/Client/Local.php'; - -/** - * @see Zend_Soap_Client_Common - */ -#require_once 'Zend/Soap/Client/Common.php'; +use Traversable; +use Zend\Server\Client as ServerClient; +use Zend\Stdlib\ArrayUtils; /** - * Zend_Soap_Client + * \Zend\Soap\Client * * @category Zend * @package Zend_Soap * @subpackage Client - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License */ -class Zend_Soap_Client +class Client implements ServerClient { /** * Encoding * @var string */ - protected $_encoding = 'UTF-8'; + protected $encoding = 'UTF-8'; /** * Array of SOAP type => PHP class pairings for handling return/incoming values * @var array */ - protected $_classmap = null; + protected $classmap = null; /** * Registered fault exceptions * @var array */ - protected $_faultExceptions = array(); + protected $faultExceptions = array(); /** * SOAP version to use; SOAP_1_2 by default, to allow processing of headers * @var int */ - protected $_soapVersion = SOAP_1_2; + protected $soapVersion = SOAP_1_2; /** Set of other SoapClient options */ - protected $_uri = null; - protected $_location = null; - protected $_style = null; - protected $_use = null; - protected $_login = null; - protected $_password = null; - protected $_proxy_host = null; - protected $_proxy_port = null; - protected $_proxy_login = null; - protected $_proxy_password = null; - protected $_local_cert = null; - protected $_passphrase = null; - protected $_compression = null; - protected $_connection_timeout = null; - protected $_stream_context = null; - protected $_features = null; - protected $_cache_wsdl = null; - protected $_user_agent = null; + protected $uri = null; + protected $location = null; + protected $style = null; + protected $use = null; + protected $login = null; + protected $password = null; + protected $proxy_host = null; + protected $proxy_port = null; + protected $proxy_login = null; + protected $proxy_password = null; + protected $local_cert = null; + protected $passphrase = null; + protected $compression = null; + protected $connection_timeout = null; + protected $stream_context = null; + protected $features = null; + protected $cache_wsdl = null; + protected $user_agent = null; /** * WSDL used to access server - * It also defines Zend_Soap_Client working mode (WSDL vs non-WSDL) + * It also defines \Zend\Soap\Client working mode (WSDL vs non-WSDL) * * @var string */ - protected $_wsdl = null; + protected $wsdl = null; /** * SoapClient object * - * @var SoapClient + * @var \SoapClient */ - protected $_soapClient; + protected $soapClient; /** * Last invoked method * * @var string */ - protected $_lastMethod = ''; + protected $lastMethod = ''; /** * SOAP request headers. @@ -119,7 +96,7 @@ class Zend_Soap_Client * * @var array */ - protected $_soapInputHeaders = array(); + protected $soapInputHeaders = array(); /** * Permanent SOAP request headers (shared between requests). @@ -128,7 +105,7 @@ class Zend_Soap_Client * * @var array */ - protected $_permanentSoapInputHeaders = array(); + protected $permanentSoapInputHeaders = array(); /** * Output SOAP headers. @@ -137,23 +114,23 @@ class Zend_Soap_Client * * @var array */ - protected $_soapOutputHeaders = array(); + protected $soapOutputHeaders = array(); /** * Constructor * - * @param string $wsdl - * @param array $options + * @param string $wsdl + * @param array|Traversable $options + * @throws Exception\ExtensionNotLoadedException */ public function __construct($wsdl = null, $options = null) { if (!extension_loaded('soap')) { - #require_once 'Zend/Soap/Client/Exception.php'; - throw new Zend_Soap_Client_Exception('SOAP extension is not loaded.'); + throw new Exception\ExtensionNotLoadedException('SOAP extension is not loaded.'); } if ($wsdl !== null) { - $this->setWsdl($wsdl); + $this->setWSDL($wsdl); } if ($options !== null) { $this->setOptions($options); @@ -164,12 +141,12 @@ class Zend_Soap_Client * Set wsdl * * @param string $wsdl - * @return Zend_Soap_Client + * @return \Zend\Soap\Client */ - public function setWsdl($wsdl) + public function setWSDL($wsdl) { - $this->_wsdl = $wsdl; - $this->_soapClient = null; + $this->wsdl = $wsdl; + $this->soapClient = null; return $this; } @@ -179,9 +156,9 @@ class Zend_Soap_Client * * @return string */ - public function getWsdl() + public function getWSDL() { - return $this->_wsdl; + return $this->wsdl; } /** @@ -189,14 +166,14 @@ class Zend_Soap_Client * * Allows setting options as an associative array of option => value pairs. * - * @param array|Zend_Config $options - * @return Zend_Soap_Client - * @throws Zend_SoapClient_Exception + * @param array|Traversable $options + * @return \Zend\Soap\Client + * @throws Exception\InvalidArgumentException */ public function setOptions($options) { - if($options instanceof Zend_Config) { - $options = $options->toArray(); + if ($options instanceof Traversable) { + $options = ArrayUtils::iteratorToArray($options); } foreach ($options as $key => $value) { @@ -213,7 +190,7 @@ class Zend_Soap_Client $this->setSoapVersion($value); break; case 'wsdl': - $this->setWsdl($value); + $this->setWSDL($value); break; case 'uri': $this->setUri($value); @@ -261,7 +238,7 @@ class Zend_Soap_Client $this->setSoapFeatures($value); break; case 'cache_wsdl': - $this->setWsdlCache($value); + $this->setWSDLCache($value); break; case 'useragent': case 'userAgent': @@ -271,12 +248,11 @@ class Zend_Soap_Client // Not used now // case 'connection_timeout': - // $this->_connection_timeout = $value; + // $this->connection_timeout = $value; // break; default: - #require_once 'Zend/Soap/Client/Exception.php'; - throw new Zend_Soap_Client_Exception('Unknown SOAP client option'); + throw new Exception\InvalidArgumentException('Unknown SOAP client option'); break; } } @@ -296,7 +272,7 @@ class Zend_Soap_Client $options['classmap'] = $this->getClassmap(); $options['encoding'] = $this->getEncoding(); $options['soap_version'] = $this->getSoapVersion(); - $options['wsdl'] = $this->getWsdl(); + $options['wsdl'] = $this->getWSDL(); $options['uri'] = $this->getUri(); $options['location'] = $this->getLocation(); $options['style'] = $this->getStyle(); @@ -310,9 +286,9 @@ class Zend_Soap_Client $options['local_cert'] = $this->getHttpsCertificate(); $options['passphrase'] = $this->getHttpsCertPassphrase(); $options['compression'] = $this->getCompressionOptions(); - //$options['connection_timeout'] = $this->_connection_timeout; + //$options['connection_timeout'] = $this->connection_timeout; $options['stream_context'] = $this->getStreamContext(); - $options['cache_wsdl'] = $this->getWsdlCache(); + $options['cache_wsdl'] = $this->getWSDLCache(); $options['features'] = $this->getSoapFeatures(); $options['user_agent'] = $this->getUserAgent(); @@ -339,18 +315,17 @@ class Zend_Soap_Client * Set SOAP version * * @param int $version One of the SOAP_1_1 or SOAP_1_2 constants - * @return Zend_Soap_Client - * @throws Zend_Soap_Client_Exception with invalid soap version argument + * @return \Zend\Soap\Client + * @throws \Zend\Soap\Exception\ExceptionInterface with invalid soap version argument */ public function setSoapVersion($version) { if (!in_array($version, array(SOAP_1_1, SOAP_1_2))) { - #require_once 'Zend/Soap/Client/Exception.php'; - throw new Zend_Soap_Client_Exception('Invalid soap version specified. Use SOAP_1_1 or SOAP_1_2 constants.'); + throw new Exception\InvalidArgumentException('Invalid soap version specified. Use SOAP_1_1 or SOAP_1_2 constants.'); } - $this->_soapVersion = $version; + $this->soapVersion = $version; - $this->_soapClient = null; + $this->soapClient = null; return $this; } @@ -362,28 +337,27 @@ class Zend_Soap_Client */ public function getSoapVersion() { - return $this->_soapVersion; + return $this->soapVersion; } /** * Set classmap * * @param array $classmap - * @return Zend_Soap_Client - * @throws Zend_Soap_Client_Exception for any invalid class in the class map + * @return \Zend\Soap\Client + * @throws \Zend\Soap\Exception\ExceptionInterface for any invalid class in the class map */ public function setClassmap(array $classmap) { - foreach ($classmap as $type => $class) { + foreach ($classmap as $class) { if (!class_exists($class)) { - #require_once 'Zend/Soap/Client/Exception.php'; - throw new Zend_Soap_Client_Exception('Invalid class in class map'); + throw new Exception\InvalidArgumentException('Invalid class in class map'); } } - $this->_classmap = $classmap; + $this->classmap = $classmap; - $this->_soapClient = null; + $this->soapClient = null; return $this; } @@ -395,26 +369,25 @@ class Zend_Soap_Client */ public function getClassmap() { - return $this->_classmap; + return $this->classmap; } /** * Set encoding * * @param string $encoding - * @return Zend_Soap_Client - * @throws Zend_Soap_Client_Exception with invalid encoding argument + * @return \Zend\Soap\Client + * @throws \Zend\Soap\Exception\ExceptionInterface with invalid encoding argument */ public function setEncoding($encoding) { if (!is_string($encoding)) { - #require_once 'Zend/Soap/Client/Exception.php'; - throw new Zend_Soap_Client_Exception('Invalid encoding specified'); + throw new Exception\InvalidArgumentException('Invalid encoding specified'); } - $this->_encoding = $encoding; + $this->encoding = $encoding; - $this->_soapClient = null; + $this->soapClient = null; return $this; } @@ -426,22 +399,21 @@ class Zend_Soap_Client */ public function getEncoding() { - return $this->_encoding; + return $this->encoding; } /** * Check for valid URN * * @param string $urn - * @return true - * @throws Zend_Soap_Client_Exception on invalid URN + * @return boolean + * @throws \Zend\Soap\Exception\ExceptionInterface on invalid URN */ public function validateUrn($urn) { $scheme = parse_url($urn, PHP_URL_SCHEME); if ($scheme === false || $scheme === null) { - #require_once 'Zend/Soap/Client/Exception.php'; - throw new Zend_Soap_Client_Exception('Invalid URN'); + throw new Exception\InvalidArgumentException('Invalid URN'); } return true; @@ -454,15 +426,15 @@ class Zend_Soap_Client * URI in Web Service the target namespace * * @param string $uri - * @return Zend_Soap_Client - * @throws Zend_Soap_Client_Exception with invalid uri argument + * @return \Zend\Soap\Client + * @throws \Zend\Soap\Exception\ExceptionInterface with invalid uri argument */ public function setUri($uri) { $this->validateUrn($uri); - $this->_uri = $uri; + $this->uri = $uri; - $this->_soapClient = null; + $this->soapClient = null; return $this; } @@ -474,7 +446,7 @@ class Zend_Soap_Client */ public function getUri() { - return $this->_uri; + return $this->uri; } /** @@ -483,15 +455,15 @@ class Zend_Soap_Client * URI in Web Service the target namespace * * @param string $location - * @return Zend_Soap_Client - * @throws Zend_Soap_Client_Exception with invalid uri argument + * @return \Zend\Soap\Client + * @throws \Zend\Soap\Exception\ExceptionInterface with invalid uri argument */ public function setLocation($location) { $this->validateUrn($location); - $this->_location = $location; + $this->location = $location; - $this->_soapClient = null; + $this->soapClient = null; return $this; } @@ -503,26 +475,25 @@ class Zend_Soap_Client */ public function getLocation() { - return $this->_location; + return $this->location; } /** * Set request style * * @param int $style One of the SOAP_RPC or SOAP_DOCUMENT constants - * @return Zend_Soap_Client - * @throws Zend_Soap_Client_Exception with invalid style argument + * @return \Zend\Soap\Client + * @throws \Zend\Soap\Exception\ExceptionInterface with invalid style argument */ public function setStyle($style) { if (!in_array($style, array(SOAP_RPC, SOAP_DOCUMENT))) { - #require_once 'Zend/Soap/Client/Exception.php'; - throw new Zend_Soap_Client_Exception('Invalid request style specified. Use SOAP_RPC or SOAP_DOCUMENT constants.'); + throw new Exception\InvalidArgumentException('Invalid request style specified. Use SOAP_RPC or SOAP_DOCUMENT constants.'); } - $this->_style = $style; + $this->style = $style; - $this->_soapClient = null; + $this->soapClient = null; return $this; } @@ -534,26 +505,25 @@ class Zend_Soap_Client */ public function getStyle() { - return $this->_style; + return $this->style; } /** * Set message encoding method * * @param int $use One of the SOAP_ENCODED or SOAP_LITERAL constants - * @return Zend_Soap_Client - * @throws Zend_Soap_Client_Exception with invalid message encoding method argument + * @return \Zend\Soap\Client + * @throws \Zend\Soap\Exception\ExceptionInterface with invalid message encoding method argument */ public function setEncodingMethod($use) { if (!in_array($use, array(SOAP_ENCODED, SOAP_LITERAL))) { - #require_once 'Zend/Soap/Client/Exception.php'; - throw new Zend_Soap_Client_Exception('Invalid message encoding method. Use SOAP_ENCODED or SOAP_LITERAL constants.'); + throw new Exception\InvalidArgumentException('Invalid message encoding method. Use SOAP_ENCODED or SOAP_LITERAL constants.'); } - $this->_use = $use; + $this->use = $use; - $this->_soapClient = null; + $this->soapClient = null; return $this; } @@ -565,20 +535,20 @@ class Zend_Soap_Client */ public function getEncodingMethod() { - return $this->_use; + return $this->use; } /** * Set HTTP login * * @param string $login - * @return Zend_Soap_Client + * @return \Zend\Soap\Client */ public function setHttpLogin($login) { - $this->_login = $login; + $this->login = $login; - $this->_soapClient = null; + $this->soapClient = null; return $this; } @@ -590,20 +560,20 @@ class Zend_Soap_Client */ public function getHttpLogin() { - return $this->_login; + return $this->login; } /** * Set HTTP password * * @param string $password - * @return Zend_Soap_Client + * @return \Zend\Soap\Client */ public function setHttpPassword($password) { - $this->_password = $password; + $this->password = $password; - $this->_soapClient = null; + $this->soapClient = null; return $this; } @@ -615,20 +585,20 @@ class Zend_Soap_Client */ public function getHttpPassword() { - return $this->_password; + return $this->password; } /** * Set proxy host * * @param string $proxyHost - * @return Zend_Soap_Client + * @return \Zend\Soap\Client */ public function setProxyHost($proxyHost) { - $this->_proxy_host = $proxyHost; + $this->proxy_host = $proxyHost; - $this->_soapClient = null; + $this->soapClient = null; return $this; } @@ -640,20 +610,20 @@ class Zend_Soap_Client */ public function getProxyHost() { - return $this->_proxy_host; + return $this->proxy_host; } /** * Set proxy port * * @param int $proxyPort - * @return Zend_Soap_Client + * @return \Zend\Soap\Client */ public function setProxyPort($proxyPort) { - $this->_proxy_port = (int)$proxyPort; + $this->proxy_port = (int)$proxyPort; - $this->_soapClient = null; + $this->soapClient = null; return $this; } @@ -665,20 +635,20 @@ class Zend_Soap_Client */ public function getProxyPort() { - return $this->_proxy_port; + return $this->proxy_port; } /** * Set proxy login * * @param string $proxyLogin - * @return Zend_Soap_Client + * @return \Zend\Soap\Client */ public function setProxyLogin($proxyLogin) { - $this->_proxy_login = $proxyLogin; + $this->proxy_login = $proxyLogin; - $this->_soapClient = null; + $this->soapClient = null; return $this; } @@ -690,20 +660,20 @@ class Zend_Soap_Client */ public function getProxyLogin() { - return $this->_proxy_login; + return $this->proxy_login; } /** * Set proxy password * - * @param string $proxyLogin - * @return Zend_Soap_Client + * @param string $proxyPassword + * @return \Zend\Soap\Client */ public function setProxyPassword($proxyPassword) { - $this->_proxy_password = $proxyPassword; + $this->proxy_password = $proxyPassword; - $this->_soapClient = null; + $this->soapClient = null; return $this; } @@ -712,19 +682,18 @@ class Zend_Soap_Client * Set HTTPS client certificate path * * @param string $localCert local certificate path - * @return Zend_Soap_Client - * @throws Zend_Soap_Client_Exception with invalid local certificate path argument + * @return \Zend\Soap\Client + * @throws \Zend\Soap\Exception\ExceptionInterface with invalid local certificate path argument */ public function setHttpsCertificate($localCert) { if (!is_readable($localCert)) { - #require_once 'Zend/Soap/Client/Exception.php'; - throw new Zend_Soap_Client_Exception('Invalid HTTPS client certificate path.'); + throw new Exception\InvalidArgumentException('Invalid HTTPS client certificate path.'); } - $this->_local_cert = $localCert; + $this->local_cert = $localCert; - $this->_soapClient = null; + $this->soapClient = null; return $this; } @@ -736,20 +705,20 @@ class Zend_Soap_Client */ public function getHttpsCertificate() { - return $this->_local_cert; + return $this->local_cert; } /** * Set HTTPS client certificate passphrase * * @param string $passphrase - * @return Zend_Soap_Client + * @return \Zend\Soap\Client */ public function setHttpsCertPassphrase($passphrase) { - $this->_passphrase = $passphrase; + $this->passphrase = $passphrase; - $this->_soapClient = null; + $this->soapClient = null; return $this; } @@ -761,23 +730,24 @@ class Zend_Soap_Client */ public function getHttpsCertPassphrase() { - return $this->_passphrase; + return $this->passphrase; } /** * Set compression options * * @param int|null $compressionOptions - * @return Zend_Soap_Client + * @return \Zend\Soap\Client */ public function setCompressionOptions($compressionOptions) { if ($compressionOptions === null) { - $this->_compression = null; + $this->compression = null; } else { - $this->_compression = (int)$compressionOptions; + $this->compression = (int)$compressionOptions; } - $this->_soapClient = null; + $this->soapClient = null; + return $this; } @@ -788,7 +758,7 @@ class Zend_Soap_Client */ public function getCompressionOptions() { - return $this->_compression; + return $this->compression; } /** @@ -798,27 +768,22 @@ class Zend_Soap_Client */ public function getProxyPassword() { - return $this->_proxy_password; + return $this->proxy_password; } /** * Set Stream Context * - * @return Zend_Soap_Client + * @param resource $context + * @return \Zend\Soap\Client */ public function setStreamContext($context) { - if(!is_resource($context) || get_resource_type($context) !== "stream-context") { - /** - * @see Zend_Soap_Client_Exception - */ - #require_once "Zend/Soap/Client/Exception.php"; - throw new Zend_Soap_Client_Exception( - "Invalid stream context resource given." - ); + if (!is_resource($context) || get_resource_type($context) !== "stream-context") { + throw new Exception\InvalidArgumentException('Invalid stream context resource given.'); } - $this->_stream_context = $context; + $this->stream_context = $context; return $this; } @@ -829,20 +794,20 @@ class Zend_Soap_Client */ public function getStreamContext() { - return $this->_stream_context; + return $this->stream_context; } /** * Set the SOAP Feature options. * * @param string|int $feature - * @return Zend_Soap_Client + * @return \Zend\Soap\Client */ public function setSoapFeatures($feature) { - $this->_features = $feature; + $this->features = $feature; - $this->_soapClient = null; + $this->soapClient = null; return $this; } @@ -853,47 +818,47 @@ class Zend_Soap_Client */ public function getSoapFeatures() { - return $this->_features; + return $this->features; } /** - * Set the SOAP Wsdl Caching Options + * Set the SOAP WSDL Caching Options * * @param string|int|boolean|null $caching - * @return Zend_Soap_Client + * @return \Zend\Soap\Client */ - public function setWsdlCache($caching) + public function setWSDLCache($caching) { if ($caching === null) { - $this->_cache_wsdl = null; + $this->cache_wsdl = null; } else { - $this->_cache_wsdl = (int)$caching; + $this->cache_wsdl = (int)$caching; } return $this; } /** - * Get current SOAP Wsdl Caching option + * Get current SOAP WSDL Caching option * * @return int */ - public function getWsdlCache() + public function getWSDLCache() { - return $this->_cache_wsdl; + return $this->cache_wsdl; } /** * Set the string to use in User-Agent header * * @param string|null $userAgent - * @return Zend_Soap_Client + * @return \Zend\Soap\Client */ public function setUserAgent($userAgent) { if ($userAgent === null) { - $this->_user_agent = null; + $this->user_agent = null; } else { - $this->_user_agent = (string)$userAgent; + $this->user_agent = (string)$userAgent; } return $this; } @@ -905,7 +870,7 @@ class Zend_Soap_Client */ public function getUserAgent() { - return $this->_user_agent; + return $this->user_agent; } /** @@ -915,8 +880,8 @@ class Zend_Soap_Client */ public function getLastRequest() { - if ($this->_soapClient !== null) { - return $this->_soapClient->__getLastRequest(); + if ($this->soapClient !== null) { + return $this->soapClient->__getLastRequest(); } return ''; @@ -929,8 +894,8 @@ class Zend_Soap_Client */ public function getLastResponse() { - if ($this->_soapClient !== null) { - return $this->_soapClient->__getLastResponse(); + if ($this->soapClient !== null) { + return $this->soapClient->__getLastResponse(); } return ''; @@ -943,8 +908,8 @@ class Zend_Soap_Client */ public function getLastRequestHeaders() { - if ($this->_soapClient !== null) { - return $this->_soapClient->__getLastRequestHeaders(); + if ($this->soapClient !== null) { + return $this->soapClient->__getLastRequestHeaders(); } return ''; @@ -957,8 +922,8 @@ class Zend_Soap_Client */ public function getLastResponseHeaders() { - if ($this->_soapClient !== null) { - return $this->_soapClient->__getLastResponseHeaders(); + if ($this->soapClient !== null) { + return $this->soapClient->__getLastResponseHeaders(); } return ''; @@ -971,7 +936,7 @@ class Zend_Soap_Client */ public function getLastMethod() { - return $this->_lastMethod; + return $this->lastMethod; } /** @@ -980,7 +945,7 @@ class Zend_Soap_Client * May be overridden in subclasses * * @internal - * @param Zend_Soap_Client_Common $client + * @param \Zend\Soap\Client\Common $client * @param string $request * @param string $location * @param string $action @@ -988,48 +953,43 @@ class Zend_Soap_Client * @param int $one_way * @return mixed */ - public function _doRequest(Zend_Soap_Client_Common $client, $request, $location, $action, $version, $one_way = null) + public function _doRequest(Client\Common $client, $request, $location, $action, $version, $one_way = null) { // Perform request as is - if ($one_way == null) { + if ($one_way === null) { return call_user_func(array($client,'SoapClient::__doRequest'), $request, $location, $action, $version); - } else { - return call_user_func(array($client,'SoapClient::__doRequest'), $request, $location, $action, $version, $one_way); } + return call_user_func(array($client, 'SoapClient::__doRequest'), $request, $location, $action, $version, $one_way); } /** * Initialize SOAP Client object * - * @throws Zend_Soap_Client_Exception + * @throws \Zend\Soap\Exception\ExceptionInterface */ protected function _initSoapClientObject() { - $wsdl = $this->getWsdl(); + $wsdl = $this->getWSDL(); $options = array_merge($this->getOptions(), array('trace' => true)); if ($wsdl == null) { if (!isset($options['location'])) { - #require_once 'Zend/Soap/Client/Exception.php'; - throw new Zend_Soap_Client_Exception('\'location\' parameter is required in non-WSDL mode.'); + throw new Exception\UnexpectedValueException('\'location\' parameter is required in non-WSDL mode.'); } if (!isset($options['uri'])) { - #require_once 'Zend/Soap/Client/Exception.php'; - throw new Zend_Soap_Client_Exception('\'uri\' parameter is required in non-WSDL mode.'); + throw new Exception\UnexpectedValueException('\'uri\' parameter is required in non-WSDL mode.'); } } else { if (isset($options['use'])) { - #require_once 'Zend/Soap/Client/Exception.php'; - throw new Zend_Soap_Client_Exception('\'use\' parameter only works in non-WSDL mode.'); + throw new Exception\UnexpectedValueException('\'use\' parameter only works in non-WSDL mode.'); } if (isset($options['style'])) { - #require_once 'Zend/Soap/Client/Exception.php'; - throw new Zend_Soap_Client_Exception('\'style\' parameter only works in non-WSDL mode.'); + throw new Exception\UnexpectedValueException('\'style\' parameter only works in non-WSDL mode.'); } } unset($options['wsdl']); - $this->_soapClient = new Zend_Soap_Client_Common(array($this, '_doRequest'), $wsdl, $options); + $this->soapClient = new Client\Common(array($this, '_doRequest'), $wsdl, $options); } @@ -1039,6 +999,7 @@ class Zend_Soap_Client * My be overridden in descendant classes * * @param array $arguments + * @return array */ protected function _preProcessArguments($arguments) { @@ -1051,7 +1012,8 @@ class Zend_Soap_Client * * My be overridden in descendant classes * - * @param array $arguments + * @param array $result + * @return array */ protected function _preProcessResult($result) { @@ -1062,16 +1024,16 @@ class Zend_Soap_Client /** * Add SOAP input header * - * @param SoapHeader $header + * @param \SoapHeader $header * @param boolean $permanent - * @return Zend_Soap_Client + * @return \Zend\Soap\Client */ - public function addSoapInputHeader(SoapHeader $header, $permanent = false) + public function addSoapInputHeader(\SoapHeader $header, $permanent = false) { if ($permanent) { - $this->_permanentSoapInputHeaders[] = $header; + $this->permanentSoapInputHeaders[] = $header; } else { - $this->_soapInputHeaders[] = $header; + $this->soapInputHeaders[] = $header; } return $this; @@ -1080,12 +1042,12 @@ class Zend_Soap_Client /** * Reset SOAP input headers * - * @return Zend_Soap_Client + * @return \Zend\Soap\Client */ public function resetSoapInputHeaders() { - $this->_permanentSoapInputHeaders = array(); - $this->_soapInputHeaders = array(); + $this->permanentSoapInputHeaders = array(); + $this->soapInputHeaders = array(); return $this; } @@ -1097,7 +1059,7 @@ class Zend_Soap_Client */ public function getLastSoapOutputHeaderObjects() { - return $this->_soapOutputHeaders; + return $this->soapOutputHeaders; } /** @@ -1111,33 +1073,43 @@ class Zend_Soap_Client { $soapClient = $this->getSoapClient(); - $this->_lastMethod = $name; + $this->lastMethod = $name; - $soapHeaders = array_merge($this->_permanentSoapInputHeaders, $this->_soapInputHeaders); + $soapHeaders = array_merge($this->permanentSoapInputHeaders, $this->soapInputHeaders); $result = $soapClient->__soapCall($name, - $this->_preProcessArguments($arguments), - null, /* Options are already set to the SOAP client object */ - (count($soapHeaders) > 0)? $soapHeaders : null, - $this->_soapOutputHeaders); + $this->_preProcessArguments($arguments), + null, /* Options are already set to the SOAP client object */ + (count($soapHeaders) > 0)? $soapHeaders : null, + $this->soapOutputHeaders); // Reset non-permanent input headers - $this->_soapInputHeaders = array(); + $this->soapInputHeaders = array(); return $this->_preProcessResult($result); } + /** + * Send an RPC request to the service for a specific method. + * + * @param string $method Name of the method we want to call. + * @param array $params List of parameters for the method. + * @return mixed Returned results. + */ + public function call($method, $params = array()) + { + return call_user_func_array(array($this, '__call'), $params); + } /** * Return a list of available functions * * @return array - * @throws Zend_Soap_Client_Exception + * @throws \Zend\Soap\Exception\ExceptionInterface */ public function getFunctions() { - if ($this->getWsdl() == null) { - #require_once 'Zend/Soap/Client/Exception.php'; - throw new Zend_Soap_Client_Exception('\'getFunctions\' method is available only in WSDL mode.'); + if ($this->getWSDL() == null) { + throw new Exception\UnexpectedValueException(__METHOD__ . ' is available only in WSDL mode.'); } $soapClient = $this->getSoapClient(); @@ -1155,13 +1127,12 @@ class Zend_Soap_Client * Return a list of SOAP types * * @return array - * @throws Zend_Soap_Client_Exception + * @throws \Zend\Soap\Exception\ExceptionInterface */ public function getTypes() { - if ($this->getWsdl() == null) { - #require_once 'Zend/Soap/Client/Exception.php'; - throw new Zend_Soap_Client_Exception('\'getTypes\' method is available only in WSDL mode.'); + if ($this->getWSDL() == null) { + throw new Exception\UnexpectedValueException(__METHOD__ . ' method is available only in WSDL mode.'); } $soapClient = $this->getSoapClient(); @@ -1170,30 +1141,30 @@ class Zend_Soap_Client } /** - * @param SoapClient $soapClient - * @return Zend_Soap_Client + * @param \SoapClient $soapClient + * @return \Zend\Soap\Client */ - public function setSoapClient(SoapClient $soapClient) + public function setSoapClient(\SoapClient $soapClient) { - $this->_soapClient = $soapClient; + $this->soapClient = $soapClient; return $this; } /** - * @return SoapClient + * @return \SoapClient */ public function getSoapClient() { - if ($this->_soapClient == null) { + if ($this->soapClient == null) { $this->_initSoapClientObject(); } - return $this->_soapClient; + return $this->soapClient; } /** - * @param string $name - * @param string $value - * @return Zend_Soap_Client + * @param string $cookieName + * @param string $cookieValue + * @return \Zend\Soap\Client */ public function setCookie($cookieName, $cookieValue=null) { diff --git a/lib/Zend/Soap/Client/Common.php b/lib/Zend/Soap/Client/Common.php index 0319c08dd858d5827a2f7caac71df73aa2a3291d..779264da757d698d62753e8e726fe5a6a552239d 100644 --- a/lib/Zend/Soap/Client/Common.php +++ b/lib/Zend/Soap/Client/Common.php @@ -1,25 +1,14 @@ <?php /** - * Zend Framework + * Zend Framework (http://framework.zend.com/) * - * LICENSE - * - * This source file is subject to the new BSD license that is bundled - * with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://framework.zend.com/license/new-bsd - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@zend.com so we can send you a copy immediately. - * - * @category Zend - * @package Zend_Soap - * @subpackage Client - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - * @version $Id: Common.php 20096 2010-01-06 02:05:09Z bkarwin $ + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Soap */ +namespace Zend\Soap\Client; if (extension_loaded('soap')) { @@ -28,25 +17,25 @@ if (extension_loaded('soap')) { * @package Zend_Soap * @subpackage Client */ -class Zend_Soap_Client_Common extends SoapClient +class Common extends \SoapClient { /** * doRequest() pre-processing method * - * @var callback + * @var callable */ - protected $_doRequestCallback; + protected $doRequestCallback; /** * Common Soap Client constructor * - * @param callback $doRequestMethod + * @param callable $doRequestCallback * @param string $wsdl * @param array $options */ - function __construct($doRequestCallback, $wsdl, $options) + public function __construct($doRequestCallback, $wsdl, $options) { - $this->_doRequestCallback = $doRequestCallback; + $this->doRequestCallback = $doRequestCallback; parent::__construct($wsdl, $options); } @@ -62,12 +51,12 @@ class Zend_Soap_Client_Common extends SoapClient * @param int $one_way * @return mixed */ - function __doRequest($request, $location, $action, $version, $one_way = null) + public function __doRequest($request, $location, $action, $version, $one_way = null) { if ($one_way === null) { - return call_user_func($this->_doRequestCallback, $this, $request, $location, $action, $version); + return call_user_func($this->doRequestCallback, $this, $request, $location, $action, $version); } else { - return call_user_func($this->_doRequestCallback, $this, $request, $location, $action, $version, $one_way); + return call_user_func($this->doRequestCallback, $this, $request, $location, $action, $version, $one_way); } } diff --git a/lib/Zend/Soap/Client/DotNet.php b/lib/Zend/Soap/Client/DotNet.php index 6f8f8788cff0c44ebce0f572d6eea2143abfab6e..112968cc167ffb7cbef71692fc58afdc60e9a88b 100644 --- a/lib/Zend/Soap/Client/DotNet.php +++ b/lib/Zend/Soap/Client/DotNet.php @@ -1,44 +1,32 @@ <?php /** - * Zend Framework + * Zend Framework (http://framework.zend.com/) * - * LICENSE - * - * This source file is subject to the new BSD license that is bundled - * with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://framework.zend.com/license/new-bsd - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@zend.com so we can send you a copy immediately. - * - * @category Zend - * @package Zend_Soap - * @subpackage Client - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - * @version $Id: DotNet.php 20096 2010-01-06 02:05:09Z bkarwin $ + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Soap */ -/** Zend_Soap_Client */ -#require_once 'Zend/Soap/Client.php'; +namespace Zend\Soap\Client; -if (extension_loaded('soap')) { +use Zend\Soap\Client as SOAPClient; +use Zend\Soap\Exception; /** - * Zend_Soap_Client_Local + * .NET SOAP client * * Class is intended to be used with .Net Web Services. * * Important! Class is at experimental stage now. - * Please leave your notes, compatiblity issues reports or + * Please leave your notes, compatibility issues reports or * suggestions in fw-webservices@lists.zend.com or fw-general@lists.com * * @category Zend * @package Zend_Soap * @subpackage Client */ -class Zend_Soap_Client_DotNet extends Zend_Soap_Client +class DotNet extends SOAPClient { /** * Constructor @@ -61,15 +49,15 @@ class Zend_Soap_Client_DotNet extends Zend_Soap_Client * My be overridden in descendant classes * * @param array $arguments - * @throws Zend_Soap_Client_Exception + * @throws Exception\RuntimeException + * @return array */ protected function _preProcessArguments($arguments) { if (count($arguments) > 1 || (count($arguments) == 1 && !is_array(reset($arguments))) ) { - #require_once 'Zend/Soap/Client/Exception.php'; - throw new Zend_Soap_Client_Exception('.Net webservice arguments have to be grouped into array: array(\'a\' => $a, \'b\' => $b, ...).'); + throw new Exception\RuntimeException('.Net webservice arguments have to be grouped into array: array(\'a\' => $a, \'b\' => $b, ...).'); } // Do nothing @@ -81,7 +69,8 @@ class Zend_Soap_Client_DotNet extends Zend_Soap_Client * * My be overridden in descendant classes * - * @param array $arguments + * @param object $result + * @return mixed */ protected function _preProcessResult($result) { @@ -91,5 +80,3 @@ class Zend_Soap_Client_DotNet extends Zend_Soap_Client } } - -} // end if (extension_loaded('soap') diff --git a/lib/Zend/Soap/Client/Exception.php b/lib/Zend/Soap/Client/Exception.php deleted file mode 100644 index d641994af2b5aef301bc896177f3690460647772..0000000000000000000000000000000000000000 --- a/lib/Zend/Soap/Client/Exception.php +++ /dev/null @@ -1,35 +0,0 @@ -<?php -/** - * Zend Framework - * - * LICENSE - * - * This source file is subject to the new BSD license that is bundled - * with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://framework.zend.com/license/new-bsd - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@zend.com so we can send you a copy immediately. - * - * @category Zend - * @package Zend_Soap - * @subpackage Client - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - */ - -/** Zend_Exception */ -#require_once 'Zend/Exception.php'; - -/** - * @category Zend - * @package Zend_Soap - * @subpackage Client - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - * @version $Id: Exception.php 20096 2010-01-06 02:05:09Z bkarwin $ - */ -class Zend_Soap_Client_Exception extends Zend_Exception -{} - diff --git a/lib/Zend/Soap/Client/Local.php b/lib/Zend/Soap/Client/Local.php index 0cea2db645bd42c7313c0175735b959df14d86bf..380ddf66929dfecfbb5c28e37da2ae2b1a7fc3c2 100644 --- a/lib/Zend/Soap/Client/Local.php +++ b/lib/Zend/Soap/Client/Local.php @@ -1,35 +1,20 @@ <?php /** - * Zend Framework + * Zend Framework (http://framework.zend.com/) * - * LICENSE - * - * This source file is subject to the new BSD license that is bundled - * with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://framework.zend.com/license/new-bsd - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@zend.com so we can send you a copy immediately. - * - * @category Zend - * @package Zend_Soap - * @subpackage Client - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - * @version $Id: Local.php 20096 2010-01-06 02:05:09Z bkarwin $ + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Soap */ -/** Zend_Soap_Server */ -#require_once 'Zend/Soap/Server.php'; - -/** Zend_Soap_Client */ -#require_once 'Zend/Soap/Client.php'; +namespace Zend\Soap\Client; -if (extension_loaded('soap')) { +use Zend\Soap\Client as SOAPClient; +use Zend\Soap\Server as SOAPServer; /** - * Zend_Soap_Client_Local + * \Zend\Soap\Client\Local * * Class is intended to be used as local SOAP client which works * with a provided Server object. @@ -40,25 +25,25 @@ if (extension_loaded('soap')) { * @package Zend_Soap * @subpackage Client */ -class Zend_Soap_Client_Local extends Zend_Soap_Client +class Local extends SOAPClient { /** * Server object * - * @var Zend_Soap_Server + * @var \Zend\Soap\Server */ - protected $_server; + protected $server; /** * Local client constructor * - * @param Zend_Soap_Server $server + * @param \Zend\Soap\Server $server * @param string $wsdl * @param array $options */ - function __construct(Zend_Soap_Server $server, $wsdl, $options = null) + public function __construct(SOAPServer $server, $wsdl, $options = null) { - $this->_server = $server; + $this->server = $server; // Use Server specified SOAP version as default $this->setSoapVersion($server->getSoapVersion()); @@ -70,7 +55,7 @@ class Zend_Soap_Client_Local extends Zend_Soap_Client * Actual "do request" method. * * @internal - * @param Zend_Soap_Client_Common $client + * @param \Zend\Soap\Client\Common $client * @param string $request * @param string $location * @param string $action @@ -78,16 +63,20 @@ class Zend_Soap_Client_Local extends Zend_Soap_Client * @param int $one_way * @return mixed */ - public function _doRequest(Zend_Soap_Client_Common $client, $request, $location, $action, $version, $one_way = null) + public function _doRequest(Common $client, $request, $location, $action, $version, $one_way = null) { // Perform request as is ob_start(); - $this->_server->handle($request); - $response = ob_get_contents(); - ob_end_clean(); + $this->server->handle($request); + $response = ob_get_clean(); + + if ($response === null || $response === '') { + $serverResponse = $this->server->getResponse(); + if ($serverResponse !== null) { + $response = $serverResponse; + } + } return $response; } } - -} // end if (extension_loaded('soap') diff --git a/lib/Zend/Soap/Exception/BadMethodCallException.php b/lib/Zend/Soap/Exception/BadMethodCallException.php new file mode 100644 index 0000000000000000000000000000000000000000..432500d66d889dbba8ba88bd0bc736e6bc0bc1ea --- /dev/null +++ b/lib/Zend/Soap/Exception/BadMethodCallException.php @@ -0,0 +1,16 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Soap + */ + +namespace Zend\Soap\Exception; + +class BadMethodCallException + extends \BadMethodCallException + implements ExceptionInterface +{} diff --git a/lib/Zend/Soap/Exception/ExceptionInterface.php b/lib/Zend/Soap/Exception/ExceptionInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..74767761a98392550332881abc3e5ab32d7fdb4e --- /dev/null +++ b/lib/Zend/Soap/Exception/ExceptionInterface.php @@ -0,0 +1,19 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Soap + */ + +namespace Zend\Soap\Exception; + +/** + * @category Zend + * @package Zend_Soap + * @subpackage AutoDiscover + */ +interface ExceptionInterface +{} diff --git a/lib/Zend/Soap/Exception/ExtensionNotLoadedException.php b/lib/Zend/Soap/Exception/ExtensionNotLoadedException.php new file mode 100644 index 0000000000000000000000000000000000000000..4af12ffe9dbd81badd704a51ba31ef26d7e9a07f --- /dev/null +++ b/lib/Zend/Soap/Exception/ExtensionNotLoadedException.php @@ -0,0 +1,14 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Soap + */ + +namespace Zend\Soap\Exception; + +class ExtensionNotLoadedException extends RuntimeException +{} diff --git a/lib/Zend/Soap/Exception/InvalidArgumentException.php b/lib/Zend/Soap/Exception/InvalidArgumentException.php new file mode 100644 index 0000000000000000000000000000000000000000..c4a92c9af394f32be367e455c14ce2eb5987dd24 --- /dev/null +++ b/lib/Zend/Soap/Exception/InvalidArgumentException.php @@ -0,0 +1,16 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Soap + */ + +namespace Zend\Soap\Exception; + +class InvalidArgumentException + extends \InvalidArgumentException + implements ExceptionInterface +{} diff --git a/lib/Zend/Soap/Exception/RuntimeException.php b/lib/Zend/Soap/Exception/RuntimeException.php new file mode 100644 index 0000000000000000000000000000000000000000..1fde750e77954355ce7168ad61ed0b93ef04ba4a --- /dev/null +++ b/lib/Zend/Soap/Exception/RuntimeException.php @@ -0,0 +1,16 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Soap + */ + +namespace Zend\Soap\Exception; + +class RuntimeException + extends \RuntimeException + implements ExceptionInterface +{} diff --git a/lib/Zend/Soap/Exception/UnexpectedValueException.php b/lib/Zend/Soap/Exception/UnexpectedValueException.php new file mode 100644 index 0000000000000000000000000000000000000000..44472bb165980b2c23368a0729deed123ebf178e --- /dev/null +++ b/lib/Zend/Soap/Exception/UnexpectedValueException.php @@ -0,0 +1,16 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Soap + */ + +namespace Zend\Soap\Exception; + +class UnexpectedValueException + extends \UnexpectedValueException + implements ExceptionInterface +{} diff --git a/lib/Zend/Soap/Server.php b/lib/Zend/Soap/Server.php index 8f40d05e7dfcd0d4ef386e26e0c4403c3989ef1f..cf06c03fe6ced7142fb5de3df5355591ecbbc9ee 100644 --- a/lib/Zend/Soap/Server.php +++ b/lib/Zend/Soap/Server.php @@ -1,28 +1,21 @@ <?php /** - * Zend Framework + * Zend Framework (http://framework.zend.com/) * - * LICENSE - * - * This source file is subject to the new BSD license that is bundled - * with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://framework.zend.com/license/new-bsd - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@zend.com so we can send you a copy immediately. - * - * @category Zend - * @package Zend_Soap - * @subpackage Server - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Soap */ -/** - * @see Zend_Server_Interface - */ -#require_once 'Zend/Server/Interface.php'; +namespace Zend\Soap; + +use DOMDocument; +use DOMNode; +use SimpleXMLElement; +use stdClass; +use Traversable; +use Zend\Stdlib\ArrayUtils; /** * Zend_Soap_Server @@ -30,118 +23,114 @@ * @category Zend * @package Zend_Soap * @subpackage Server - * @uses Zend_Server_Interface - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - * @version $Id: Server.php 22223 2010-05-21 08:06:47Z jan $ */ -class Zend_Soap_Server implements Zend_Server_Interface +class Server implements \Zend\Server\Server { /** * Actor URI * @var string URI */ - protected $_actor; + protected $actor; /** * Class registered with this server * @var string */ - protected $_class; + protected $class; /** - * Arguments to pass to {@link $_class} constructor + * Arguments to pass to {@link $class} constructor * @var array */ - protected $_classArgs = array(); + protected $classArgs = array(); /** * Object registered with this server */ - protected $_object; + protected $object; /** * Array of SOAP type => PHP class pairings for handling return/incoming values * @var array */ - protected $_classmap; + protected $classmap; /** * Encoding * @var string */ - protected $_encoding; + protected $encoding; /** * SOAP Server Features * * @var int */ - protected $_features; + protected $features; /** * WSDL Caching Options of SOAP Server * * @var mixed */ - protected $_wsdlCache; + protected $wsdlCache; /** * Registered fault exceptions * @var array */ - protected $_faultExceptions = array(); + protected $faultExceptions = array(); /** * Functions registered with this server; may be either an array or the SOAP_FUNCTIONS_ALL * constant * @var array|int */ - protected $_functions = array(); + protected $functions = array(); /** * Persistence mode; should be one of the SOAP persistence constants * @var int */ - protected $_persistence; + protected $persistence; /** * Request XML * @var string */ - protected $_request; + protected $request; /** * Response XML * @var string */ - protected $_response; + protected $response; /** * Flag: whether or not {@link handle()} should return a response instead * of automatically emitting it. * @var boolean */ - protected $_returnResponse = false; + protected $returnResponse = false; /** * SOAP version to use; SOAP_1_2 by default, to allow processing of headers * @var int */ - protected $_soapVersion = SOAP_1_2; + protected $soapVersion = SOAP_1_2; /** * URI or path to WSDL * @var string */ - protected $_wsdl; + protected $wsdl; /** * URI namespace for SOAP server * @var string URI */ - protected $_uri; + protected $uri; /** * Constructor @@ -150,22 +139,21 @@ class Zend_Soap_Server implements Zend_Server_Interface * XML in response). Registers {@link handlePhpErrors()} as error handler * for E_USER_ERROR. * - * If $wsdl is provided, it is passed on to {@link setWsdl()}; if any + * If $wsdl is provided, it is passed on to {@link setWSDL()}; if any * options are specified, they are passed on to {@link setOptions()}. * * @param string $wsdl * @param array $options - * @return void + * @throws Exception\ExtensionNotLoadedException */ public function __construct($wsdl = null, array $options = null) { if (!extension_loaded('soap')) { - #require_once 'Zend/Soap/Server/Exception.php'; - throw new Zend_Soap_Server_Exception('SOAP extension is not loaded.'); + throw new Exception\ExtensionNotLoadedException('SOAP extension is not loaded.'); } if (null !== $wsdl) { - $this->setWsdl($wsdl); + $this->setWSDL($wsdl); } if (null !== $options) { @@ -178,13 +166,13 @@ class Zend_Soap_Server implements Zend_Server_Interface * * Allows setting options as an associative array of option => value pairs. * - * @param array|Zend_Config $options - * @return Zend_Soap_Server + * @param array|Traversable $options + * @return \Zend\Soap\Server */ public function setOptions($options) { - if($options instanceof Zend_Config) { - $options = $options->toArray(); + if ($options instanceof Traversable) { + $options = ArrayUtils::iteratorToArray($options); } foreach ($options as $key => $value) { @@ -207,7 +195,7 @@ class Zend_Soap_Server implements Zend_Server_Interface $this->setUri($value); break; case 'wsdl': - $this->setWsdl($value); + $this->setWSDL($value); break; case 'featues': trigger_error(__METHOD__ . ': the option "featues" is deprecated as of 1.10.x and will be removed with 2.0.0; use "features" instead', E_USER_NOTICE); @@ -215,7 +203,7 @@ class Zend_Soap_Server implements Zend_Server_Interface $this->setSoapFeatures($value); break; case 'cache_wsdl': - $this->setWsdlCache($value); + $this->setWSDLCache($value); break; default: break; @@ -233,32 +221,32 @@ class Zend_Soap_Server implements Zend_Server_Interface public function getOptions() { $options = array(); - if (null !== $this->_actor) { - $options['actor'] = $this->_actor; + if (null !== $this->actor) { + $options['actor'] = $this->actor; } - if (null !== $this->_classmap) { - $options['classmap'] = $this->_classmap; + if (null !== $this->classmap) { + $options['classmap'] = $this->classmap; } - if (null !== $this->_encoding) { - $options['encoding'] = $this->_encoding; + if (null !== $this->encoding) { + $options['encoding'] = $this->encoding; } - if (null !== $this->_soapVersion) { - $options['soap_version'] = $this->_soapVersion; + if (null !== $this->soapVersion) { + $options['soap_version'] = $this->soapVersion; } - if (null !== $this->_uri) { - $options['uri'] = $this->_uri; + if (null !== $this->uri) { + $options['uri'] = $this->uri; } - if(null !== $this->_features) { - $options['features'] = $this->_features; + if (null !== $this->features) { + $options['features'] = $this->features; } - if(null !== $this->_wsdlCache) { - $options['cache_wsdl'] = $this->_wsdlCache; + if (null !== $this->wsdlCache) { + $options['cache_wsdl'] = $this->wsdlCache; } return $options; @@ -268,17 +256,16 @@ class Zend_Soap_Server implements Zend_Server_Interface * Set encoding * * @param string $encoding - * @return Zend_Soap_Server - * @throws Zend_Soap_Server_Exception with invalid encoding argument + * @return Server + * @throws Exception\InvalidArgumentException with invalid encoding argument */ public function setEncoding($encoding) { if (!is_string($encoding)) { - #require_once 'Zend/Soap/Server/Exception.php'; - throw new Zend_Soap_Server_Exception('Invalid encoding specified'); + throw new Exception\InvalidArgumentException('Invalid encoding specified'); } - $this->_encoding = $encoding; + $this->encoding = $encoding; return $this; } @@ -289,24 +276,23 @@ class Zend_Soap_Server implements Zend_Server_Interface */ public function getEncoding() { - return $this->_encoding; + return $this->encoding; } /** * Set SOAP version * * @param int $version One of the SOAP_1_1 or SOAP_1_2 constants - * @return Zend_Soap_Server - * @throws Zend_Soap_Server_Exception with invalid soap version argument + * @return Server + * @throws Exception\InvalidArgumentException with invalid soap version argument */ public function setSoapVersion($version) { if (!in_array($version, array(SOAP_1_1, SOAP_1_2))) { - #require_once 'Zend/Soap/Server/Exception.php'; - throw new Zend_Soap_Server_Exception('Invalid soap version specified'); + throw new Exception\InvalidArgumentException('Invalid soap version specified'); } - $this->_soapVersion = $version; + $this->soapVersion = $version; return $this; } @@ -317,7 +303,7 @@ class Zend_Soap_Server implements Zend_Server_Interface */ public function getSoapVersion() { - return $this->_soapVersion; + return $this->soapVersion; } /** @@ -325,14 +311,13 @@ class Zend_Soap_Server implements Zend_Server_Interface * * @param string $urn * @return true - * @throws Zend_Soap_Server_Exception on invalid URN + * @throws Exception\InvalidArgumentException on invalid URN */ public function validateUrn($urn) { $scheme = parse_url($urn, PHP_URL_SCHEME); if ($scheme === false || $scheme === null) { - #require_once 'Zend/Soap/Server/Exception.php'; - throw new Zend_Soap_Server_Exception('Invalid URN'); + throw new Exception\InvalidArgumentException('Invalid URN'); } return true; @@ -344,12 +329,12 @@ class Zend_Soap_Server implements Zend_Server_Interface * Actor is the actor URI for the server. * * @param string $actor - * @return Zend_Soap_Server + * @return Server */ public function setActor($actor) { $this->validateUrn($actor); - $this->_actor = $actor; + $this->actor = $actor; return $this; } @@ -360,7 +345,7 @@ class Zend_Soap_Server implements Zend_Server_Interface */ public function getActor() { - return $this->_actor; + return $this->actor; } /** @@ -369,13 +354,12 @@ class Zend_Soap_Server implements Zend_Server_Interface * URI in SoapServer is actually the target namespace, not a URI; $uri must begin with 'urn:'. * * @param string $uri - * @return Zend_Soap_Server - * @throws Zend_Soap_Server_Exception with invalid uri argument + * @return Server */ public function setUri($uri) { $this->validateUrn($uri); - $this->_uri = $uri; + $this->uri = $uri; return $this; } @@ -386,36 +370,28 @@ class Zend_Soap_Server implements Zend_Server_Interface */ public function getUri() { - return $this->_uri; + return $this->uri; } /** * Set classmap * * @param array $classmap - * @return Zend_Soap_Server - * @throws Zend_Soap_Server_Exception for any invalid class in the class map + * @return Server + * @throws Exception\InvalidArgumentException for any invalid class in the class map */ public function setClassmap($classmap) { if (!is_array($classmap)) { - /** - * @see Zend_Soap_Server_Exception - */ - #require_once 'Zend/Soap/Server/Exception.php'; - throw new Zend_Soap_Server_Exception('Classmap must be an array'); + throw new Exception\InvalidArgumentException('Classmap must be an array'); } - foreach ($classmap as $type => $class) { + foreach ($classmap as $class) { if (!class_exists($class)) { - /** - * @see Zend_Soap_Server_Exception - */ - #require_once 'Zend/Soap/Server/Exception.php'; - throw new Zend_Soap_Server_Exception('Invalid class in class map'); + throw new Exception\InvalidArgumentException('Invalid class in class map'); } } - $this->_classmap = $classmap; + $this->classmap = $classmap; return $this; } @@ -426,18 +402,18 @@ class Zend_Soap_Server implements Zend_Server_Interface */ public function getClassmap() { - return $this->_classmap; + return $this->classmap; } /** * Set wsdl * * @param string $wsdl URI or path to a WSDL - * @return Zend_Soap_Server + * @return Server */ - public function setWsdl($wsdl) + public function setWSDL($wsdl) { - $this->_wsdl = $wsdl; + $this->wsdl = $wsdl; return $this; } @@ -446,20 +422,20 @@ class Zend_Soap_Server implements Zend_Server_Interface * * @return string */ - public function getWsdl() + public function getWSDL() { - return $this->_wsdl; + return $this->wsdl; } /** * Set the SOAP Feature options. * * @param string|int $feature - * @return Zend_Soap_Server + * @return Server */ public function setSoapFeatures($feature) { - $this->_features = $feature; + $this->features = $feature; return $this; } @@ -470,27 +446,27 @@ class Zend_Soap_Server implements Zend_Server_Interface */ public function getSoapFeatures() { - return $this->_features; + return $this->features; } /** - * Set the SOAP Wsdl Caching Options + * Set the SOAP WSDL Caching Options * - * @param string|int|boolean $caching - * @return Zend_Soap_Server + * @param string|int|boolean $options + * @return Server */ - public function setWsdlCache($options) + public function setWSDLCache($options) { - $this->_wsdlCache = $options; + $this->wsdlCache = $options; return $this; } /** - * Get current SOAP Wsdl Caching option + * Get current SOAP WSDL Caching option */ - public function getWsdlCache() + public function getWSDLCache() { - return $this->_wsdlCache; + return $this->wsdlCache; } /** @@ -499,37 +475,35 @@ class Zend_Soap_Server implements Zend_Server_Interface * @param array|string $function Function name, array of function names to attach, * or SOAP_FUNCTIONS_ALL to attach all functions * @param string $namespace Ignored - * @return Zend_Soap_Server - * @throws Zend_Soap_Server_Exception on invalid functions + * @return Server + * @throws Exception\InvalidArgumentException on invalid functions */ public function addFunction($function, $namespace = '') { // Bail early if set to SOAP_FUNCTIONS_ALL - if ($this->_functions == SOAP_FUNCTIONS_ALL) { + if ($this->functions == SOAP_FUNCTIONS_ALL) { return $this; } if (is_array($function)) { foreach ($function as $func) { if (is_string($func) && function_exists($func)) { - $this->_functions[] = $func; + $this->functions[] = $func; } else { - #require_once 'Zend/Soap/Server/Exception.php'; - throw new Zend_Soap_Server_Exception('One or more invalid functions specified in array'); + throw new Exception\InvalidArgumentException('One or more invalid functions specified in array'); } } - $this->_functions = array_merge($this->_functions, $function); + $this->functions = array_merge($this->functions, $function); } elseif (is_string($function) && function_exists($function)) { - $this->_functions[] = $function; + $this->functions[] = $function; } elseif ($function == SOAP_FUNCTIONS_ALL) { - $this->_functions = SOAP_FUNCTIONS_ALL; + $this->functions = SOAP_FUNCTIONS_ALL; } else { - #require_once 'Zend/Soap/Server/Exception.php'; - throw new Zend_Soap_Server_Exception('Invalid function specified'); + throw new Exception\InvalidArgumentException('Invalid function specified'); } - if (is_array($this->_functions)) { - $this->_functions = array_unique($this->_functions); + if (is_array($this->functions)) { + $this->functions = array_unique($this->functions); } return $this; @@ -543,33 +517,35 @@ class Zend_Soap_Server implements Zend_Server_Interface * * See {@link setObject()} to set preconfigured object instances as request handlers. * - * @param string $class Class Name which executes SOAP Requests at endpoint. - * @return Zend_Soap_Server - * @throws Zend_Soap_Server_Exception if called more than once, or if class + * @param string|object $class Class name or object instance which executes SOAP Requests at endpoint. + * @param string $namespace + * @param $argv + * @return Server + * @throws Exception\InvalidArgumentException if called more than once, or if class * does not exist */ public function setClass($class, $namespace = '', $argv = null) { - if (isset($this->_class)) { - #require_once 'Zend/Soap/Server/Exception.php'; - throw new Zend_Soap_Server_Exception('A class has already been registered with this soap server instance'); + if (isset($this->class)) { + throw new Exception\InvalidArgumentException('A class has already been registered with this soap server instance'); + } + + if (is_object($class)) { + return $this->setObject($class); } if (!is_string($class)) { - #require_once 'Zend/Soap/Server/Exception.php'; - throw new Zend_Soap_Server_Exception('Invalid class argument (' . gettype($class) . ')'); + throw new Exception\InvalidArgumentException('Invalid class argument (' . gettype($class) . ')'); } if (!class_exists($class)) { - #require_once 'Zend/Soap/Server/Exception.php'; - throw new Zend_Soap_Server_Exception('Class "' . $class . '" does not exist'); + throw new Exception\InvalidArgumentException('Class "' . $class . '" does not exist'); } - $this->_class = $class; - if (1 < func_num_args()) { + $this->class = $class; + if (2 < func_num_args()) { $argv = func_get_args(); - array_shift($argv); - $this->_classArgs = $argv; + $this->classArgs = array_slice($argv, 2); } return $this; @@ -581,21 +557,20 @@ class Zend_Soap_Server implements Zend_Server_Interface * Accepts an instanciated object to use when handling requests. * * @param object $object - * @return Zend_Soap_Server + * @throws Exception\InvalidArgumentException + * @return Server */ public function setObject($object) { - if(!is_object($object)) { - #require_once 'Zend/Soap/Server/Exception.php'; - throw new Zend_Soap_Server_Exception('Invalid object argument ('.gettype($object).')'); + if (!is_object($object)) { + throw new Exception\InvalidArgumentException('Invalid object argument ('.gettype($object).')'); } - if(isset($this->_object)) { - #require_once 'Zend/Soap/Server/Exception.php'; - throw new Zend_Soap_Server_Exception('An object has already been registered with this soap server instance'); + if (isset($this->object)) { + throw new Exception\InvalidArgumentException('An object has already been registered with this soap server instance'); } - $this->_object = $object; + $this->object = $object; return $this; } @@ -613,53 +588,52 @@ class Zend_Soap_Server implements Zend_Server_Interface public function getFunctions() { $functions = array(); - if (null !== $this->_class) { - $functions = get_class_methods($this->_class); - } elseif (null !== $this->_object) { - $functions = get_class_methods($this->_object); + if (null !== $this->class) { + $functions = get_class_methods($this->class); + } elseif (null !== $this->object) { + $functions = get_class_methods($this->object); } - return array_merge((array) $this->_functions, $functions); + return array_merge((array) $this->functions, $functions); } /** * Unimplemented: Load server definition * - * @param array $array + * @param array $definition * @return void - * @throws Zend_Soap_Server_Exception Unimplemented + * @throws Exception\RuntimeException Unimplemented */ public function loadFunctions($definition) { - #require_once 'Zend/Soap/Server/Exception.php'; - throw new Zend_Soap_Server_Exception('Unimplemented'); + throw new Exception\RuntimeException('Unimplemented method.'); } /** * Set server persistence * * @param int $mode - * @return Zend_Soap_Server + * @throws Exception\InvalidArgumentException + * @return Server */ public function setPersistence($mode) { if (!in_array($mode, array(SOAP_PERSISTENCE_SESSION, SOAP_PERSISTENCE_REQUEST))) { - #require_once 'Zend/Soap/Server/Exception.php'; - throw new Zend_Soap_Server_Exception('Invalid persistence mode specified'); + throw new Exception\InvalidArgumentException('Invalid persistence mode specified'); } - $this->_persistence = $mode; + $this->persistence = $mode; return $this; } /** * Get server persistence * - * @return Zend_Soap_Server + * @return Server */ public function getPersistence() { - return $this->_persistence; + return $this->persistence; } /** @@ -673,7 +647,8 @@ class Zend_Soap_Server implements Zend_Server_Interface * - string; if so, verifies XML * * @param DOMDocument|DOMNode|SimpleXMLElement|stdClass|string $request - * @return Zend_Soap_Server + * @throws Exception\InvalidArgumentException + * @return Server */ protected function _setRequest($request) { @@ -689,14 +664,21 @@ class Zend_Soap_Server implements Zend_Server_Interface } else { $xml = $request; } - + libxml_disable_entity_loader(true); $dom = new DOMDocument(); - if(strlen($xml) == 0 || !$dom->loadXML($xml)) { - #require_once 'Zend/Soap/Server/Exception.php'; - throw new Zend_Soap_Server_Exception('Invalid XML'); + if (strlen($xml) == 0 || !$dom->loadXML($xml)) { + throw new Exception\InvalidArgumentException('Invalid XML'); } + foreach ($dom->childNodes as $child) { + if ($child->nodeType === XML_DOCUMENT_TYPE_NODE) { + throw new Exception\InvalidArgumentException( + 'Invalid XML: Detected use of illegal DOCTYPE' + ); + } + } + libxml_disable_entity_loader(false); } - $this->_request = $xml; + $this->request = $xml; return $this; } @@ -707,7 +689,7 @@ class Zend_Soap_Server implements Zend_Server_Interface */ public function getLastRequest() { - return $this->_request; + return $this->request; } /** @@ -719,11 +701,11 @@ class Zend_Soap_Server implements Zend_Server_Interface * The response is always available via {@link getResponse()}. * * @param boolean $flag - * @return Zend_Soap_Server + * @return Server */ - public function setReturnResponse($flag) + public function setReturnResponse($flag = true) { - $this->_returnResponse = ($flag) ? true : false; + $this->returnResponse = ($flag) ? true : false; return $this; } @@ -734,7 +716,7 @@ class Zend_Soap_Server implements Zend_Server_Interface */ public function getReturnResponse() { - return $this->_returnResponse; + return $this->returnResponse; } /** @@ -742,41 +724,41 @@ class Zend_Soap_Server implements Zend_Server_Interface * * @return string */ - public function getLastResponse() + public function getResponse() { - return $this->_response; + return $this->response; } /** * Get SoapServer object * - * Uses {@link $_wsdl} and return value of {@link getOptions()} to instantiate + * Uses {@link $wsdl} and return value of {@link getOptions()} to instantiate * SoapServer object, and then registers any functions or class with it, as - * well as peristence. + * well as persistence. * - * @return SoapServer + * @return \SoapServer */ protected function _getSoap() { $options = $this->getOptions(); - $server = new SoapServer($this->_wsdl, $options); + $server = new \SoapServer($this->wsdl, $options); - if (!empty($this->_functions)) { - $server->addFunction($this->_functions); + if (!empty($this->functions)) { + $server->addFunction($this->functions); } - if (!empty($this->_class)) { - $args = $this->_classArgs; - array_unshift($args, $this->_class); + if (!empty($this->class)) { + $args = $this->classArgs; + array_unshift($args, $this->class); call_user_func_array(array($server, 'setClass'), $args); } - if (!empty($this->_object)) { - $server->setObject($this->_object); + if (!empty($this->object)) { + $server->setObject($this->object); } - if (null !== $this->_persistence) { - $server->setPersistence($this->_persistence); + if (null !== $this->persistence) { + $server->setPersistence($this->persistence); } return $server; @@ -796,7 +778,7 @@ class Zend_Soap_Server implements Zend_Server_Interface * - string; if so, verifies XML * * If no request is passed, pulls request using php:://input (for - * cross-platform compatability purposes). + * cross-platform compatibility purposes). * * @param DOMDocument|DOMNode|SimpleXMLElement|stdClass|string $request Optional request * @return void|string @@ -807,50 +789,51 @@ class Zend_Soap_Server implements Zend_Server_Interface $request = file_get_contents('php://input'); } - // Set Zend_Soap_Server error handler + // Set Server error handler $displayErrorsOriginalState = $this->_initializeSoapErrorContext(); $setRequestException = null; - /** - * @see Zend_Soap_Server_Exception - */ - #require_once 'Zend/Soap/Server/Exception.php'; try { $this->_setRequest($request); - } catch (Zend_Soap_Server_Exception $e) { + } catch (\Exception $e) { $setRequestException = $e; } $soap = $this->_getSoap(); + $fault = false; ob_start(); - if($setRequestException instanceof Exception) { - // Send SOAP fault message if we've catched exception - $soap->fault("Sender", $setRequestException->getMessage()); + if ($setRequestException instanceof \Exception) { + // Create SOAP fault message if we've caught a request exception + $fault = $this->fault($setRequestException->getMessage(), 'Sender'); } else { try { - $soap->handle($request); - } catch (Exception $e) { + $soap->handle($this->request); + } catch (\Exception $e) { $fault = $this->fault($e); - $soap->fault($fault->faultcode, $fault->faultstring); } } - $this->_response = ob_get_clean(); + $this->response = ob_get_clean(); // Restore original error handler restore_error_handler(); ini_set('display_errors', $displayErrorsOriginalState); - if (!$this->_returnResponse) { - echo $this->_response; + // Send a fault, if we have one + if ($fault) { + $this->response = $fault; + } + + if (!$this->returnResponse) { + echo $this->response; return; } - return $this->_response; + return $this->response; } /** - * Method initalizes the error context that the SOAPServer enviroment will run in. + * Method initializes the error context that the SOAPServer environment will run in. * * @return boolean display_errors original value */ @@ -866,11 +849,11 @@ class Zend_Soap_Server implements Zend_Server_Interface * Register a valid fault exception * * @param string|array $class Exception class or array of exception classes - * @return Zend_Soap_Server + * @return Server */ public function registerFaultException($class) { - $this->_faultExceptions = array_merge($this->_faultExceptions, (array) $class); + $this->faultExceptions = array_merge($this->faultExceptions, (array) $class); return $this; } @@ -882,9 +865,9 @@ class Zend_Soap_Server implements Zend_Server_Interface */ public function deregisterFaultException($class) { - if (in_array($class, $this->_faultExceptions, true)) { - $index = array_search($class, $this->_faultExceptions); - unset($this->_faultExceptions[$index]); + if (in_array($class, $this->faultExceptions, true)) { + $index = array_search($class, $this->faultExceptions); + unset($this->faultExceptions[$index]); return true; } @@ -898,7 +881,7 @@ class Zend_Soap_Server implements Zend_Server_Interface */ public function getFaultExceptions() { - return $this->_faultExceptions; + return $this->faultExceptions; } /** @@ -911,22 +894,22 @@ class Zend_Soap_Server implements Zend_Server_Interface * {@Link registerFaultException()}. * * @link http://www.w3.org/TR/soap12-part1/#faultcodes - * @param string|Exception $fault + * @param string|\Exception $fault * @param string $code SOAP Fault Codes - * @return SoapFault + * @return \SoapFault */ public function fault($fault = null, $code = "Receiver") { - if ($fault instanceof Exception) { + if ($fault instanceof \Exception) { $class = get_class($fault); - if (in_array($class, $this->_faultExceptions)) { + if (in_array($class, $this->faultExceptions)) { $message = $fault->getMessage(); $eCode = $fault->getCode(); $code = empty($eCode) ? $code : $eCode; } else { $message = 'Unknown error'; } - } elseif(is_string($fault)) { + } elseif (is_string($fault)) { $message = $fault; } else { $message = 'Unknown error'; @@ -936,11 +919,11 @@ class Zend_Soap_Server implements Zend_Server_Interface 'VersionMismatch', 'MustUnderstand', 'DataEncodingUnknown', 'Sender', 'Receiver', 'Server' ); - if(!in_array($code, $allowedFaultModes)) { + if (!in_array($code, $allowedFaultModes)) { $code = "Receiver"; } - return new SoapFault($code, $message); + return new \SoapFault($code, $message); } /** @@ -952,10 +935,10 @@ class Zend_Soap_Server implements Zend_Server_Interface * @param int $errline * @param array $errcontext * @return void - * @throws SoapFault + * @throws \SoapFault */ public function handlePhpErrors($errno, $errstr, $errfile = null, $errline = null, array $errcontext = null) { - throw $this->fault($errstr, "Receiver"); + throw $this->fault($errstr, 'Receiver'); } } diff --git a/lib/Zend/Soap/Server/DocumentLiteralWrapper.php b/lib/Zend/Soap/Server/DocumentLiteralWrapper.php new file mode 100644 index 0000000000000000000000000000000000000000..750942840c32e74a01198c587e02f8e9dd05939c --- /dev/null +++ b/lib/Zend/Soap/Server/DocumentLiteralWrapper.php @@ -0,0 +1,168 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Soap + */ + +namespace Zend\Soap\Server; + +use ReflectionClass; +use ReflectionObject; +use Zend\Soap\Exception\BadMethodCallException; +use Zend\Soap\Exception\UnexpectedValueException; + +/** + * Wraps WSDL Document/Literal Style service objects to hide SOAP request + * message abstraction from the actual service object. + * + * When using the document/literal SOAP message pattern you end up with one + * object passed to your service methods that contains all the parameters of + * the method. This obviously leads to a problem since Zend\Soap\Wsdl tightly + * couples method parameters to request message parameters. + * + * Example: + * + * class MyCalculatorService + * { + * /** + * * @param int $x + * * @param int $y + * * @return int + * * + * public function add($x, $y) {} + * } + * + * The document/literal wrapper pattern would lead php ext/soap to generate a + * single "request" object that contains $x and $y properties. To solve this a + * wrapper service is needed that extracts the properties and delegates a + * proper call to the underlying service. + * + * The input variable from a document/literal SOAP-call to the client + * MyCalculatorServiceClient#add(10, 20) would lead PHP ext/soap to create + * the following request object: + * + * $addRequest = new \stdClass; + * $addRequest->x = 10; + * $addRequest->y = 20; + * + * This object does not match the signature of the server-side + * MyCalculatorService and lead to failure. + * + * Also the response object in this case is supposed to be an array + * or object with a property "addResult": + * + * $addResponse = new \stdClass; + * $addResponse->addResult = 30; + * + * To keep your service object code free from this implementation detail + * of SOAP this wrapper service handles the parsing between the formats. + * + * @example + * + * $service = new MyCalculatorService(); + * $soap = new \Zend\Soap\Server($wsdlFile); + * $soap->setObject(new \Zend\Soap\Server\DocumentLiteralWrapper($service)); + * $soap->handle(); + * + * @category Zend + * @package Zend_Soap + * @subpackage Server + */ +class DocumentLiteralWrapper +{ + /** + * @var object + */ + protected $object; + + /** + * @var ReflectionObject + */ + protected $reflection; + + /** + * Pass Service object to the constructor + * + * @param object $object + */ + public function __construct($object) + { + $this->object = $object; + $this->reflection = new ReflectionObject($this->object); + } + + /** + * Proxy method that does the heavy document/literal decomposing. + * + * @param string $method + * @param array $args + * @return mixed + */ + public function __call($method, $args) + { + $this->_assertOnlyOneArgument($args); + $this->_assertServiceDelegateHasMethod($method); + + $delegateArgs = $this->_parseArguments($method, $args[0]); + $ret = call_user_func_array(array($this->object, $method), $delegateArgs); + return $this->_getResultMessage($method, $ret); + } + + /** + * Parse the document/literal wrapper into arguments to call the real + * service. + * + * @param string $method + * @param object $document + * @throws UnexpectedValueException + * @return array + */ + protected function _parseArguments($method, $document) + { + $reflMethod = $this->reflection->getMethod($method); + $params = array(); + foreach ($reflMethod->getParameters() as $param) { + $params[$param->getName()] = $param; + } + + $delegateArgs = array(); + foreach (get_object_vars($document) as $argName => $argValue) { + if (!isset($params[$argName])) { + throw new UnexpectedValueException(sprintf( + "Received unknown argument %s which is not an argument to %s::%s", + get_class($this->object), $method + )); + } + $delegateArgs[$params[$argName]->getPosition()] = $argValue; + } + return $delegateArgs; + } + + protected function _getResultMessage($method, $ret) + { + return array($method . 'Result' => $ret); + } + + protected function _assertServiceDelegateHasMethod($method) + { + if (!$this->reflection->hasMethod($method)) { + throw new BadMethodCallException(sprintf( + "Method %s does not exist on delegate object %s", + $method, get_class($this->object) + )); + } + } + + protected function _assertOnlyOneArgument($args) + { + if (count($args) != 1) { + throw new UnexpectedValueException(sprintf( + "Expecting exactly one argument that is the document/literal wrapper, got %d", + count($args))); + } + } +} diff --git a/lib/Zend/Soap/Server/Exception.php b/lib/Zend/Soap/Server/Exception.php deleted file mode 100644 index 5d576520dd1ecf07717d421bbfee48466385443d..0000000000000000000000000000000000000000 --- a/lib/Zend/Soap/Server/Exception.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php -/** - * Zend Framework - * - * LICENSE - * - * This source file is subject to the new BSD license that is bundled - * with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://framework.zend.com/license/new-bsd - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@zend.com so we can send you a copy immediately. - * - * @category Zend - * @package Zend_Soap - * @subpackage Server - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - */ - - -/** Zend_Exception */ -#require_once 'Zend/Exception.php'; - - -/** - * @category Zend - * @package Zend_Soap - * @subpackage Server - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - * @version $Id: Exception.php 20096 2010-01-06 02:05:09Z bkarwin $ - */ -class Zend_Soap_Server_Exception extends Zend_Exception -{} - diff --git a/lib/Zend/Soap/Wsdl.php b/lib/Zend/Soap/Wsdl.php index a18d626da51c260e415a2355c55d65ff676b07f8..5f11825a2d724c05cc71d2915ec06ececc961e9f 100644 --- a/lib/Zend/Soap/Wsdl.php +++ b/lib/Zend/Soap/Wsdl.php @@ -1,91 +1,86 @@ <?php /** - * Zend Framework + * Zend Framework (http://framework.zend.com/) * - * LICENSE - * - * This source file is subject to the new BSD license that is bundled - * with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://framework.zend.com/license/new-bsd - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@zend.com so we can send you a copy immediately. - * - * @category Zend - * @package Zend_Soap - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - * @version $Id: Wsdl.php 23342 2010-11-15 15:29:20Z alexander $ + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Soap */ -/** - * @see Zend_Soap_Wsdl_Strategy_Interface - */ -#require_once "Zend/Soap/Wsdl/Strategy/Interface.php"; +namespace Zend\Soap; -/** - * @see Zend_Soap_Wsdl_Strategy_Abstract - */ -#require_once "Zend/Soap/Wsdl/Strategy/Abstract.php"; +use DOMDocument; +use DOMElement; +use Zend\Soap\Wsdl\ComplexTypeStrategy\ComplexTypeStrategyInterface as ComplexTypeStrategy; +use Zend\Uri\Uri; /** - * Zend_Soap_Wsdl + * \Zend\Soap\Wsdl * * @category Zend * @package Zend_Soap */ -class Zend_Soap_Wsdl +class Wsdl { /** * @var object DomDocument Instance */ - private $_dom; + private $dom; /** * @var object WSDL Root XML_Tree_Node */ - private $_wsdl; + private $wsdl; /** * @var string URI where the WSDL will be available */ - private $_uri; + private $uri; /** * @var DOMElement */ - private $_schema = null; + private $schema = null; /** * Types defined on schema * * @var array */ - private $_includedTypes = array(); + private $includedTypes = array(); /** * Strategy for detection of complex types */ - protected $_strategy = null; + protected $strategy = null; + /** + * Map of PHP Class names to WSDL QNames. + * + * @var array + */ + protected $classMap = array(); /** * Constructor * * @param string $name Name of the Web Service being Described - * @param string $uri URI where the WSDL will be available - * @param boolean|string|Zend_Soap_Wsdl_Strategy_Interface $strategy + * @param string|Uri $uri URI where the WSDL will be available + * @param null|ComplexTypeStrategy $strategy Strategy for detection of complex types + * @param null|array $classMap Map of PHP Class names to WSDL QNames + * @throws Exception\RuntimeException */ - public function __construct($name, $uri, $strategy = true) + public function __construct($name, $uri, ComplexTypeStrategy $strategy = null, array $classMap = array()) { - if ($uri instanceof Zend_Uri_Http) { - $uri = $uri->getUri(); + if ($uri instanceof Uri) { + $uri = $uri->toString(); } - $this->_uri = $uri; + $this->uri = $uri; + $this->classMap = $classMap; /** - * @todo change DomDocument object creation from cparsing to construxting using API + * @todo change DomDocument object creation from cparsing to constructing using API * It also should authomatically escape $name and $uri values if necessary */ $wsdl = "<?xml version='1.0' ?> @@ -96,37 +91,64 @@ class Zend_Soap_Wsdl xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:soap-enc='http://schemas.xmlsoap.org/soap/encoding/' xmlns:wsdl='http://schemas.xmlsoap.org/wsdl/'></definitions>"; - $this->_dom = new DOMDocument(); - if (!$this->_dom->loadXML($wsdl)) { - #require_once 'Zend/Server/Exception.php'; - throw new Zend_Server_Exception('Unable to create DomDocument'); + libxml_disable_entity_loader(true); + $this->dom = new DOMDocument(); + if (!$this->dom->loadXML($wsdl)) { + throw new Exception\RuntimeException('Unable to create DomDocument'); } else { - $this->_wsdl = $this->_dom->documentElement; + foreach ($this->dom->childNodes as $child) { + if ($child->nodeType === XML_DOCUMENT_TYPE_NODE) { + throw new Exception\RuntimeException( + 'Invalid XML: Detected use of illegal DOCTYPE' + ); + } + } + $this->wsdl = $this->dom->documentElement; } + libxml_disable_entity_loader(false); + $this->setComplexTypeStrategy($strategy ?: new Wsdl\ComplexTypeStrategy\DefaultComplexType); + } - $this->setComplexTypeStrategy($strategy); + /** + * Get the class map of php to wsdl qname types. + * + * @return array + */ + public function getClassMap() + { + return $this->classMap; + } + + /** + * Set the class map of php to wsdl qname types. + */ + public function setClassMap($classMap) + { + $this->classMap = $classMap; } /** * Set a new uri for this WSDL * - * @param string|Zend_Uri_Http $uri - * @return Zend_Server_Wsdl + * @param string|Uri $uri + * @return \Zend\Soap\Wsdl */ public function setUri($uri) { - if ($uri instanceof Zend_Uri_Http) { - $uri = $uri->getUri(); + if ($uri instanceof Uri) { + $uri = $uri->toString(); } - $oldUri = $this->_uri; - $this->_uri = $uri; + $oldUri = $this->uri; + $this->uri = $uri; - if($this->_dom !== null) { + if ($this->dom !== null) { // @todo: This is the worst hack ever, but its needed due to design and non BC issues of WSDL generation - $xml = $this->_dom->saveXML(); + $xml = $this->dom->saveXML(); $xml = str_replace($oldUri, $uri, $xml); - $this->_dom = new DOMDocument(); - $this->_dom->loadXML($xml); + libxml_disable_entity_loader(true); + $this->dom = new DOMDocument(); + $this->dom->loadXML($xml); + libxml_disable_entity_loader(false); } return $this; @@ -135,45 +157,23 @@ class Zend_Soap_Wsdl /** * Set a strategy for complex type detection and handling * - * @todo Boolean is for backwards compability with extractComplexType object var. Remove it in later versions. - * @param boolean|string|Zend_Soap_Wsdl_Strategy_Interface $strategy - * @return Zend_Soap_Wsdl + * @param ComplexTypeStrategy $strategy + * @return \Zend\Soap\Wsdl */ - public function setComplexTypeStrategy($strategy) + public function setComplexTypeStrategy(ComplexTypeStrategy $strategy) { - if($strategy === true) { - #require_once "Zend/Soap/Wsdl/Strategy/DefaultComplexType.php"; - $strategy = new Zend_Soap_Wsdl_Strategy_DefaultComplexType(); - } else if($strategy === false) { - #require_once "Zend/Soap/Wsdl/Strategy/AnyType.php"; - $strategy = new Zend_Soap_Wsdl_Strategy_AnyType(); - } else if(is_string($strategy)) { - if(class_exists($strategy)) { - $strategy = new $strategy(); - } else { - #require_once "Zend/Soap/Wsdl/Exception.php"; - throw new Zend_Soap_Wsdl_Exception( - sprintf("Strategy with name '%s does not exist.", $strategy - )); - } - } - - if(!($strategy instanceof Zend_Soap_Wsdl_Strategy_Interface)) { - #require_once "Zend/Soap/Wsdl/Exception.php"; - throw new Zend_Soap_Wsdl_Exception("Set a strategy that is not of type 'Zend_Soap_Wsdl_Strategy_Interface'"); - } - $this->_strategy = $strategy; + $this->strategy = $strategy; return $this; } /** * Get the current complex type strategy * - * @return Zend_Soap_Wsdl_Strategy_Interface + * @return ComplexTypeStrategy */ public function getComplexTypeStrategy() { - return $this->_strategy; + return $this->strategy; } /** @@ -188,13 +188,13 @@ class Zend_Soap_Wsdl */ public function addMessage($name, $parts) { - $message = $this->_dom->createElement('message'); + $message = $this->dom->createElement('message'); $message->setAttribute('name', $name); - if (sizeof($parts) > 0) { + if (count($parts) > 0) { foreach ($parts as $name => $type) { - $part = $this->_dom->createElement('part'); + $part = $this->dom->createElement('part'); $part->setAttribute('name', $name); if (is_array($type)) { foreach ($type as $key => $value) { @@ -207,7 +207,7 @@ class Zend_Soap_Wsdl } } - $this->_wsdl->appendChild($message); + $this->wsdl->appendChild($message); return $message; } @@ -220,15 +220,15 @@ class Zend_Soap_Wsdl */ public function addPortType($name) { - $portType = $this->_dom->createElement('portType'); + $portType = $this->dom->createElement('portType'); $portType->setAttribute('name', $name); - $this->_wsdl->appendChild($portType); + $this->wsdl->appendChild($portType); return $portType; } /** - * Add an {@link http://www.w3.org/TR/wsdl#_request-response operation} element to a portType element + * Add an {@link http://www.w3.org/TR/wsdl#request-response operation} element to a portType element * * @param object $portType a portType XML_Tree_Node, from {@link function addPortType} * @param string $name Operation name @@ -239,21 +239,21 @@ class Zend_Soap_Wsdl */ public function addPortOperation($portType, $name, $input = false, $output = false, $fault = false) { - $operation = $this->_dom->createElement('operation'); + $operation = $this->dom->createElement('operation'); $operation->setAttribute('name', $name); if (is_string($input) && (strlen(trim($input)) >= 1)) { - $node = $this->_dom->createElement('input'); + $node = $this->dom->createElement('input'); $node->setAttribute('message', $input); $operation->appendChild($node); } if (is_string($output) && (strlen(trim($output)) >= 1)) { - $node= $this->_dom->createElement('output'); + $node= $this->dom->createElement('output'); $node->setAttribute('message', $output); $operation->appendChild($node); } if (is_string($fault) && (strlen(trim($fault)) >= 1)) { - $node = $this->_dom->createElement('fault'); + $node = $this->dom->createElement('fault'); $node->setAttribute('message', $fault); $operation->appendChild($node); } @@ -267,16 +267,16 @@ class Zend_Soap_Wsdl * Add a {@link http://www.w3.org/TR/wsdl#_bindings binding} element to WSDL * * @param string $name Name of the Binding - * @param string $type name of the portType to bind + * @param string $portType name of the portType to bind * @return object The new binding's XML_Tree_Node for use with {@link function addBindingOperation} and {@link function addDocumentation} */ public function addBinding($name, $portType) { - $binding = $this->_dom->createElement('binding'); + $binding = $this->dom->createElement('binding'); $binding->setAttribute('name', $name); $binding->setAttribute('type', $portType); - $this->_wsdl->appendChild($binding); + $this->wsdl->appendChild($binding); return $binding; } @@ -292,12 +292,12 @@ class Zend_Soap_Wsdl */ public function addBindingOperation($binding, $name, $input = false, $output = false, $fault = false) { - $operation = $this->_dom->createElement('operation'); + $operation = $this->dom->createElement('operation'); $operation->setAttribute('name', $name); if (is_array($input)) { - $node = $this->_dom->createElement('input'); - $soap_node = $this->_dom->createElement('soap:body'); + $node = $this->dom->createElement('input'); + $soap_node = $this->dom->createElement('soap:body'); foreach ($input as $name => $value) { $soap_node->setAttribute($name, $value); } @@ -306,8 +306,8 @@ class Zend_Soap_Wsdl } if (is_array($output)) { - $node = $this->_dom->createElement('output'); - $soap_node = $this->_dom->createElement('soap:body'); + $node = $this->dom->createElement('output'); + $soap_node = $this->dom->createElement('soap:body'); foreach ($output as $name => $value) { $soap_node->setAttribute($name, $value); } @@ -316,17 +316,11 @@ class Zend_Soap_Wsdl } if (is_array($fault)) { - $node = $this->_dom->createElement('fault'); - /** - * Note. Do we really need name attribute to be also set at wsdl:fault node??? - * W3C standard doesn't mention it (http://www.w3.org/TR/wsdl#_soap:fault) - * But some real world WSDLs use it, so it may be required for compatibility reasons. - */ + $node = $this->dom->createElement('fault'); if (isset($fault['name'])) { $node->setAttribute('name', $fault['name']); } - - $soap_node = $this->_dom->createElement('soap:fault'); + $soap_node = $this->dom->createElement('soap:fault'); foreach ($fault as $name => $value) { $soap_node->setAttribute($name, $value); } @@ -349,7 +343,7 @@ class Zend_Soap_Wsdl */ public function addSoapBinding($binding, $style = 'document', $transport = 'http://schemas.xmlsoap.org/soap/http') { - $soap_binding = $this->_dom->createElement('soap:binding'); + $soap_binding = $this->dom->createElement('soap:binding'); $soap_binding->setAttribute('style', $style); $soap_binding->setAttribute('transport', $transport); @@ -367,10 +361,10 @@ class Zend_Soap_Wsdl */ public function addSoapOperation($binding, $soap_action) { - if ($soap_action instanceof Zend_Uri_Http) { - $soap_action = $soap_action->getUri(); + if ($soap_action instanceof Uri) { + $soap_action = $soap_action->toString(); } - $soap_operation = $this->_dom->createElement('soap:operation'); + $soap_operation = $this->dom->createElement('soap:operation'); $soap_operation->setAttribute('soapAction', $soap_action); $binding->insertBefore($soap_operation, $binding->firstChild); @@ -389,23 +383,23 @@ class Zend_Soap_Wsdl */ public function addService($name, $port_name, $binding, $location) { - if ($location instanceof Zend_Uri_Http) { - $location = $location->getUri(); + if ($location instanceof Uri) { + $location = $location->toString(); } - $service = $this->_dom->createElement('service'); + $service = $this->dom->createElement('service'); $service->setAttribute('name', $name); - $port = $this->_dom->createElement('port'); + $port = $this->dom->createElement('port'); $port->setAttribute('name', $port_name); $port->setAttribute('binding', $binding); - $soap_address = $this->_dom->createElement('soap:address'); + $soap_address = $this->dom->createElement('soap:address'); $soap_address->setAttribute('location', $location); $port->appendChild($soap_address); $service->appendChild($port); - $this->_wsdl->appendChild($service); + $this->wsdl->appendChild($service); return $service; } @@ -424,16 +418,16 @@ class Zend_Soap_Wsdl public function addDocumentation($input_node, $documentation) { if ($input_node === $this) { - $node = $this->_dom->documentElement; + $node = $this->dom->documentElement; } else { $node = $input_node; } - $doc = $this->_dom->createElement('documentation'); - $doc_cdata = $this->_dom->createTextNode(str_replace(array("\r\n", "\r"), "\n", $documentation)); + $doc = $this->dom->createElement('documentation'); + $doc_cdata = $this->dom->createTextNode(str_replace(array("\r\n", "\r"), "\n", $documentation)); $doc->appendChild($doc_cdata); - if($node->hasChildNodes()) { + if ($node->hasChildNodes()) { $node->insertBefore($doc, $node->firstChild); } else { $node->appendChild($doc); @@ -449,12 +443,12 @@ class Zend_Soap_Wsdl */ public function addTypes($types) { - if ($types instanceof DomDocument) { - $dom = $this->_dom->importNode($types->documentElement); - $this->_wsdl->appendChild($types->documentElement); - } elseif ($types instanceof DomNode || $types instanceof DomElement || $types instanceof DomDocumentFragment ) { - $dom = $this->_dom->importNode($types); - $this->_wsdl->appendChild($dom); + if ($types instanceof \DomDocument) { + $dom = $this->dom->importNode($types->documentElement); + $this->wsdl->appendChild($types->documentElement); + } elseif ($types instanceof \DomNode || $types instanceof \DomElement || $types instanceof \DomDocumentFragment ) { + $dom = $this->dom->importNode($types); + $this->wsdl->appendChild($dom); } } @@ -462,12 +456,13 @@ class Zend_Soap_Wsdl * Add a complex type name that is part of this WSDL and can be used in signatures. * * @param string $type - * @return Zend_Soap_Wsdl + * @param string $wsdlType + * @return \Zend\Soap\Wsdl */ - public function addType($type) + public function addType($type, $wsdlType) { - if(!in_array($type, $this->_includedTypes)) { - $this->_includedTypes[] = $type; + if (!isset($this->includedTypes[$type])) { + $this->includedTypes[$type] = $wsdlType; } return $this; } @@ -479,7 +474,7 @@ class Zend_Soap_Wsdl */ public function getTypes() { - return $this->_includedTypes; + return $this->includedTypes; } /** @@ -489,11 +484,11 @@ class Zend_Soap_Wsdl */ public function getSchema() { - if($this->_schema == null) { + if ($this->schema == null) { $this->addSchemaTypeSection(); } - return $this->_schema; + return $this->schema; } /** @@ -503,7 +498,7 @@ class Zend_Soap_Wsdl */ public function toXML() { - return $this->_dom->saveXML(); + return $this->dom->saveXML(); } /** @@ -513,7 +508,7 @@ class Zend_Soap_Wsdl */ public function toDomDocument() { - return $this->_dom; + return $this->dom; } /** @@ -526,9 +521,8 @@ class Zend_Soap_Wsdl if (!$filename) { echo $this->toXML(); return true; - } else { - return file_put_contents($filename, $this->toXML()); } + return file_put_contents($filename, $this->toXML()); } /** @@ -543,28 +537,24 @@ class Zend_Soap_Wsdl case 'string': case 'str': return 'xsd:string'; - break; + case 'long': + return 'xsd:long'; case 'int': case 'integer': return 'xsd:int'; - break; case 'float': - case 'double': return 'xsd:float'; - break; + case 'double': + return 'xsd:double'; case 'boolean': case 'bool': return 'xsd:boolean'; - break; case 'array': return 'soap-enc:Array'; - break; case 'object': return 'xsd:struct'; - break; case 'mixed': return 'xsd:anyType'; - break; case 'void': return ''; default: @@ -576,20 +566,44 @@ class Zend_Soap_Wsdl /** * This function makes sure a complex types section and schema additions are set. * - * @return Zend_Soap_Wsdl + * @return \Zend\Soap\Wsdl */ public function addSchemaTypeSection() { - if ($this->_schema === null) { - $this->_schema = $this->_dom->createElement('xsd:schema'); - $this->_schema->setAttribute('targetNamespace', $this->_uri); - $types = $this->_dom->createElement('types'); - $types->appendChild($this->_schema); - $this->_wsdl->appendChild($types); + if ($this->schema === null) { + $this->schema = $this->dom->createElement('xsd:schema'); + $this->schema->setAttribute('targetNamespace', $this->uri); + $types = $this->dom->createElement('types'); + $types->appendChild($this->schema); + $this->wsdl->appendChild($types); } return $this; } + /** + * Translate PHP type into WSDL QName + * + * @param string $type + * @return string QName + */ + public function translateType($type) + { + if (isset($this->classMap[$type])) { + return $this->classMap[$type]; + } + + if ($type[0] == '\\') { + $type = substr($type, 1); + } + + $pos = strrpos($type, '\\'); + if ($pos) { + $type = substr($type, $pos+1); + } + + return str_replace('\\', '.', $type); + } + /** * Add a {@link http://www.w3.org/TR/wsdl#_types types} data type definition * @@ -598,8 +612,8 @@ class Zend_Soap_Wsdl */ public function addComplexType($type) { - if (in_array($type, $this->getTypes())) { - return "tns:$type"; + if (isset($this->includedTypes[$type])) { + return $this->includedTypes[$type]; } $this->addSchemaTypeSection(); @@ -613,22 +627,22 @@ class Zend_Soap_Wsdl * Parse an xsd:element represented as an array into a DOMElement. * * @param array $element an xsd:element represented as an array + * @throws Exception\RuntimeException if $element is not an array * @return DOMElement parsed element */ private function _parseElement($element) { if (!is_array($element)) { - #require_once "Zend/Soap/Wsdl/Exception.php"; - throw new Zend_Soap_Wsdl_Exception("The 'element' parameter needs to be an associative array."); + throw new Exception\RuntimeException("The 'element' parameter needs to be an associative array."); } - $elementXml = $this->_dom->createElement('xsd:element'); + $elementXml = $this->dom->createElement('xsd:element'); foreach ($element as $key => $value) { if (in_array($key, array('sequence', 'all', 'choice'))) { if (is_array($value)) { - $complexType = $this->_dom->createElement('xsd:complexType'); + $complexType = $this->dom->createElement('xsd:complexType'); if (count($value) > 0) { - $container = $this->_dom->createElement('xsd:' . $key); + $container = $this->dom->createElement('xsd:' . $key); foreach ($value as $subelement) { $subelementXml = $this->_parseElement($subelement); $container->appendChild($subelementXml); diff --git a/lib/Zend/Soap/Wsdl/ComplexTypeStrategy/AbstractComplexTypeStrategy.php b/lib/Zend/Soap/Wsdl/ComplexTypeStrategy/AbstractComplexTypeStrategy.php new file mode 100644 index 0000000000000000000000000000000000000000..fc53d90f35334a6067c12b069e8e9499fc049206 --- /dev/null +++ b/lib/Zend/Soap/Wsdl/ComplexTypeStrategy/AbstractComplexTypeStrategy.php @@ -0,0 +1,65 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Soap + */ + +namespace Zend\Soap\Wsdl\ComplexTypeStrategy; + +/** + * Abstract class for Zend_Soap_Wsdl_Strategy. + * + * @category Zend + * @package Zend_Soap + * @subpackage WSDL + */ +abstract class AbstractComplexTypeStrategy implements ComplexTypeStrategyInterface +{ + /** + * Context object + * + * @var \Zend\Soap\Wsdl + */ + protected $context; + + /** + * Set the Zend_Soap_Wsdl Context object this strategy resides in. + * + * @param \Zend\Soap\Wsdl $context + * @return void + */ + public function setContext(\Zend\Soap\Wsdl $context) + { + $this->context = $context; + } + + /** + * Return the current Zend_Soap_Wsdl context object + * + * @return \Zend\Soap\Wsdl + */ + public function getContext() + { + return $this->context; + } + + /** + * Look through registered types + * + * @param string $phpType + * @return string + */ + public function scanRegisteredTypes($phpType) + { + if (array_key_exists($phpType, $this->getContext()->getTypes())) { + $soapTypes = $this->getContext()->getTypes(); + return $soapTypes[$phpType]; + } + + return null; + } +} diff --git a/lib/Zend/Soap/Wsdl/ComplexTypeStrategy/AnyType.php b/lib/Zend/Soap/Wsdl/ComplexTypeStrategy/AnyType.php new file mode 100644 index 0000000000000000000000000000000000000000..a64556a0d828342bc73e49b40c9ac998fdbb5c5d --- /dev/null +++ b/lib/Zend/Soap/Wsdl/ComplexTypeStrategy/AnyType.php @@ -0,0 +1,42 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Soap + */ + +namespace Zend\Soap\Wsdl\ComplexTypeStrategy; + +/** + * Zend_Soap_Wsdl_Strategy_AnyType + * + * @category Zend + * @package Zend_Soap + * @subpackage WSDL + */ +class AnyType implements ComplexTypeStrategyInterface +{ + /** + * Not needed in this strategy. + * + * @param \Zend\Soap\Wsdl $context + */ + public function setContext(\Zend\Soap\Wsdl $context) + { + + } + + /** + * Returns xsd:anyType regardless of the input. + * + * @param string $type + * @return string + */ + public function addComplexType($type) + { + return 'xsd:anyType'; + } +} diff --git a/lib/Zend/Soap/Wsdl/ComplexTypeStrategy/ArrayOfTypeComplex.php b/lib/Zend/Soap/Wsdl/ComplexTypeStrategy/ArrayOfTypeComplex.php new file mode 100644 index 0000000000000000000000000000000000000000..116ae818ca4a4a9d681a456222d245f8cb5ea629 --- /dev/null +++ b/lib/Zend/Soap/Wsdl/ComplexTypeStrategy/ArrayOfTypeComplex.php @@ -0,0 +1,121 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Soap + */ + +namespace Zend\Soap\Wsdl\ComplexTypeStrategy; + +use Zend\Soap\Exception; + +/** + * ArrayOfTypeComplex strategy + * + * @category Zend + * @package Zend_Soap + * @subpackage WSDL + */ +class ArrayOfTypeComplex extends DefaultComplexType +{ + /** + * Add an ArrayOfType based on the xsd:complexType syntax if type[] is detected in return value doc comment. + * + * @param string $type + * @throws Exception\InvalidArgumentException + * @return string tns:xsd-type + */ + public function addComplexType($type) + { + if (($soapType = $this->scanRegisteredTypes($type)) !== null) { + return $soapType; + } + + $singularType = $this->_getSingularPhpType($type); + $nestingLevel = $this->_getNestedCount($type); + + if ($nestingLevel == 0) { + return parent::addComplexType($singularType); + } elseif ($nestingLevel == 1) { + // The following blocks define the Array of Object structure + return $this->_addArrayOfComplexType($singularType, $type); + } else { + throw new Exception\InvalidArgumentException( + 'ArrayOfTypeComplex cannot return nested ArrayOfObject deeper than ' + . 'one level. Use array object properties to return deep nested data.' + ); + } + } + + /** + * Add an ArrayOfType based on the xsd:complexType syntax if type[] is detected in return value doc comment. + * + * @param string $singularType e.g. '\MyNamespace\MyClassname' + * @param string $type e.g. '\MyNamespace\MyClassname[]' + * @return string tns:xsd-type e.g. 'tns:ArrayOfMyNamespace.MyClassname' + */ + protected function _addArrayOfComplexType($singularType, $type) + { + if (($soapType = $this->scanRegisteredTypes($type)) !== null) { + return $soapType; + } + + $xsdComplexTypeName = 'ArrayOf' . $this->getContext()->translateType($singularType); + $xsdComplexType = 'tns:' . $xsdComplexTypeName; + + // Register type here to avoid recursion + $this->getContext()->addType($type, $xsdComplexType); + + // Process singular type using DefaultComplexType strategy + parent::addComplexType($singularType); + + + // Add array type structure to WSDL document + $dom = $this->getContext()->toDomDocument(); + + $complexType = $dom->createElement('xsd:complexType'); + $complexType->setAttribute('name', $xsdComplexTypeName); + + $complexContent = $dom->createElement('xsd:complexContent'); + $complexType->appendChild($complexContent); + + $xsdRestriction = $dom->createElement('xsd:restriction'); + $xsdRestriction->setAttribute('base', 'soap-enc:Array'); + $complexContent->appendChild($xsdRestriction); + + $xsdAttribute = $dom->createElement('xsd:attribute'); + $xsdAttribute->setAttribute('ref', 'soap-enc:arrayType'); + $xsdAttribute->setAttribute('wsdl:arrayType', + 'tns:' . $this->getContext()->translateType($singularType) . '[]'); + $xsdRestriction->appendChild($xsdAttribute); + + $this->getContext()->getSchema()->appendChild($complexType); + + return $xsdComplexType; + } + + /** + * From a nested definition with type[], get the singular PHP Type + * + * @param string $type + * @return string + */ + protected function _getSingularPhpType($type) + { + return str_replace('[]', '', $type); + } + + /** + * Return the array nesting level based on the type name + * + * @param string $type + * @return integer + */ + protected function _getNestedCount($type) + { + return substr_count($type, '[]'); + } +} diff --git a/lib/Zend/Soap/Wsdl/ComplexTypeStrategy/ArrayOfTypeSequence.php b/lib/Zend/Soap/Wsdl/ComplexTypeStrategy/ArrayOfTypeSequence.php new file mode 100644 index 0000000000000000000000000000000000000000..e95d76b6a5b2ff8f83be5a8385d4db01b9e850e5 --- /dev/null +++ b/lib/Zend/Soap/Wsdl/ComplexTypeStrategy/ArrayOfTypeSequence.php @@ -0,0 +1,132 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Soap + */ + +namespace Zend\Soap\Wsdl\ComplexTypeStrategy; + +use Zend\Soap\Wsdl; + +/** + * Zend_Soap_Wsdl_Strategy_ArrayOfTypeSequence + * + * @category Zend + * @package Zend_Soap + * @subpackage WSDL + */ +class ArrayOfTypeSequence extends DefaultComplexType +{ + /** + * Add an unbounded ArrayOfType based on the xsd:sequence syntax if type[] is detected in return value doc comment. + * + * @param string $type + * @return string tns:xsd-type + */ + public function addComplexType($type) + { + $nestedCounter = $this->_getNestedCount($type); + + if ($nestedCounter > 0) { + $singularType = $this->_getSingularType($type); + + for ($i = 1; $i <= $nestedCounter; $i++) { + $complexType = $this->_getTypeBasedOnNestingLevel($singularType, $i); + $complexTypePhp = $singularType . str_repeat('[]', $i); + $childType = $this->_getTypeBasedOnNestingLevel($singularType, $i-1); + + $this->_addSequenceType($complexType, $childType, $complexTypePhp); + } + + return $complexType; + } elseif (($soapType = $this->scanRegisteredTypes($type)) !== null) { + // Existing complex type + return $soapType; + } else { + // New singular complex type + return parent::addComplexType($type); + } + } + + /** + * Return the ArrayOf or simple type name based on the singular xsdtype and the nesting level + * + * @param string $singularType + * @param int $level + * @return string + */ + protected function _getTypeBasedOnNestingLevel($singularType, $level) + { + if ($level == 0) { + // This is not an Array anymore, return the xsd simple type + return $this->getContext()->getType($singularType); + } else { + return 'tns:' . str_repeat('ArrayOf', $level) . ucfirst($this->getContext()->translateType($singularType)); + } + } + + /** + * From a nested definition with type[], get the singular xsd:type + * + * @param string $type + * @return string + */ + protected function _getSingularType($type) + { + return str_replace('[]', '', $type); + } + + /** + * Return the array nesting level based on the type name + * + * @param string $type + * @return integer + */ + protected function _getNestedCount($type) + { + return substr_count($type, '[]'); + } + + /** + * Append the complex type definition to the WSDL via the context access + * + * @param string $arrayType Array type name (e.g. 'tns:ArrayOfArrayOfInt') + * @param string $childType Qualified array items type (e.g. 'xsd:int', 'tns:ArrayOfInt') + * @param string $phpArrayType PHP type (e.g. 'int[][]', '\MyNamespace\MyClassName[][][]') + * @return void + */ + protected function _addSequenceType($arrayType, $childType, $phpArrayType) + { + if ($this->scanRegisteredTypes($phpArrayType) !== null) { + return; + } + + // Register type here to avoid recursion + $this->getContext()->addType($phpArrayType, $arrayType); + + + $dom = $this->getContext()->toDomDocument(); + + $arrayTypeName = substr($arrayType, strpos($arrayType, ':') + 1); + + $complexType = $dom->createElement('xsd:complexType'); + $complexType->setAttribute('name', $arrayTypeName); + + $sequence = $dom->createElement('xsd:sequence'); + + $element = $dom->createElement('xsd:element'); + $element->setAttribute('name', 'item'); + $element->setAttribute('type', $childType); + $element->setAttribute('minOccurs', 0); + $element->setAttribute('maxOccurs', 'unbounded'); + $sequence->appendChild($element); + + $complexType->appendChild($sequence); + + $this->getContext()->getSchema()->appendChild($complexType); + } +} diff --git a/lib/Zend/Soap/Wsdl/ComplexTypeStrategy/ComplexTypeStrategyInterface.php b/lib/Zend/Soap/Wsdl/ComplexTypeStrategy/ComplexTypeStrategyInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..1b6c1880817fda68e255774f83353e121e4e5778 --- /dev/null +++ b/lib/Zend/Soap/Wsdl/ComplexTypeStrategy/ComplexTypeStrategyInterface.php @@ -0,0 +1,38 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Soap + */ + +namespace Zend\Soap\Wsdl\ComplexTypeStrategy; + +use Zend\Soap\Wsdl; + +/** + * Interface strategies that generate an XSD-Schema for complex data types in WSDL files. + * + * @category Zend + * @package Zend_Soap + * @subpackage WSDL + */ +interface ComplexTypeStrategyInterface +{ + /** + * Method accepts the current WSDL context file. + * + * @param Wsdl $context + */ + public function setContext(Wsdl $context); + + /** + * Create a complex type based on a strategy + * + * @param string $type + * @return string XSD type + */ + public function addComplexType($type); +} diff --git a/lib/Zend/Soap/Wsdl/ComplexTypeStrategy/Composite.php b/lib/Zend/Soap/Wsdl/ComplexTypeStrategy/Composite.php new file mode 100644 index 0000000000000000000000000000000000000000..5f4db6dbf22bb61023b48b902f27a0208ce12d8f --- /dev/null +++ b/lib/Zend/Soap/Wsdl/ComplexTypeStrategy/Composite.php @@ -0,0 +1,158 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Soap + */ + +namespace Zend\Soap\Wsdl\ComplexTypeStrategy; + +use Zend\Soap\Exception; +use Zend\Soap\Wsdl; +use Zend\Soap\Wsdl\ComplexTypeStrategy\ComplexTypeStrategyInterface as ComplexTypeStrategy; + +/** + * Zend_Soap_Wsdl_Strategy_Composite + * + * @category Zend + * @package Zend_Soap + * @subpackage WSDL + */ +class Composite implements ComplexTypeStrategy +{ + /** + * Typemap of Complex Type => Strategy pairs. + * + * @var array + */ + protected $typeMap = array(); + + /** + * Default Strategy of this composite + * + * @var string|ComplexTypeStrategy + */ + protected $defaultStrategy; + + /** + * Context WSDL file that this composite serves + * + * @var \Zend\Soap\Wsdl|null + */ + protected $context; + + /** + * Construct Composite WSDL Strategy. + * + * @param array $typeMap + * @param string|ComplexTypeStrategy $defaultStrategy + */ + public function __construct(array $typeMap=array(), $defaultStrategy='\Zend\Soap\Wsdl\ComplexTypeStrategy\DefaultComplexType') + { + foreach ($typeMap AS $type => $strategy) { + $this->connectTypeToStrategy($type, $strategy); + } + $this->defaultStrategy = $defaultStrategy; + } + + /** + * Connect a complex type to a given strategy. + * + * @throws Exception\InvalidArgumentException + * @param string $type + * @param string|ComplexTypeStrategy $strategy + * @return Composite + */ + public function connectTypeToStrategy($type, $strategy) + { + if (!is_string($type)) { + throw new Exception\InvalidArgumentException('Invalid type given to Composite Type Map.'); + } + $this->typeMap[$type] = $strategy; + return $this; + } + + /** + * Return default strategy of this composite + * + * @throws Exception\InvalidArgumentException + * @return ComplexTypeStrategy + */ + public function getDefaultStrategy() + { + $strategy = $this->defaultStrategy; + if (is_string($strategy) && class_exists($strategy)) { + $strategy = new $strategy; + } + if ( !($strategy instanceof ComplexTypeStrategy) ) { + throw new Exception\InvalidArgumentException( + 'Default Strategy for Complex Types is not a valid strategy object.' + ); + } + $this->defaultStrategy = $strategy; + return $strategy; + } + + /** + * Return specific strategy or the default strategy of this type. + * + * @throws Exception\InvalidArgumentException + * @param string $type + * @return ComplexTypeStrategy + */ + public function getStrategyOfType($type) + { + if (isset($this->typeMap[$type])) { + $strategy = $this->typeMap[$type]; + + if (is_string($strategy) && class_exists($strategy)) { + $strategy = new $strategy(); + } + + if ( !($strategy instanceof ComplexTypeStrategy) ) { + throw new Exception\InvalidArgumentException( + "Strategy for Complex Type '$type' is not a valid strategy object." + ); + } + $this->typeMap[$type] = $strategy; + } else { + $strategy = $this->getDefaultStrategy(); + } + return $strategy; + } + + /** + * Method accepts the current WSDL context file. + * + * @param \Zend\Soap\Wsdl $context + * @return Composite + */ + public function setContext(Wsdl $context) + { + $this->context = $context; + return $this; + } + + /** + * Create a complex type based on a strategy + * + * @throws Exception\InvalidArgumentException + * @param string $type + * @return string XSD type + */ + public function addComplexType($type) + { + if (!($this->context instanceof Wsdl) ) { + throw new Exception\InvalidArgumentException( + "Cannot add complex type '$type', no context is set for this composite strategy." + ); + } + + $strategy = $this->getStrategyOfType($type); + $strategy->setContext($this->context); + return $strategy->addComplexType($type); + } +} diff --git a/lib/Zend/Soap/Wsdl/Strategy/DefaultComplexType.php b/lib/Zend/Soap/Wsdl/ComplexTypeStrategy/DefaultComplexType.php similarity index 52% rename from lib/Zend/Soap/Wsdl/Strategy/DefaultComplexType.php rename to lib/Zend/Soap/Wsdl/ComplexTypeStrategy/DefaultComplexType.php index 43cf5b0fb6be22a89b3a3cb9f732ff806b2132f3..f8bcc61f203b6db32577c324c570c60d10576928 100644 --- a/lib/Zend/Soap/Wsdl/Strategy/DefaultComplexType.php +++ b/lib/Zend/Soap/Wsdl/ComplexTypeStrategy/DefaultComplexType.php @@ -1,64 +1,60 @@ <?php /** - * Zend Framework + * Zend Framework (http://framework.zend.com/) * - * LICENSE - * - * This source file is subject to the new BSD license that is bundled - * with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://framework.zend.com/license/new-bsd - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@zend.com so we can send you a copy immediately. - * - * @category Zend - * @package Zend_Soap - * @subpackage Wsdl - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - * @version $Id: DefaultComplexType.php 22674 2010-07-25 19:35:20Z ramon $ + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Soap */ -/** - * @see Zend_Soap_Wsdl_Strategy_Abstract - */ -#require_once "Zend/Soap/Wsdl/Strategy/Abstract.php"; +namespace Zend\Soap\Wsdl\ComplexTypeStrategy; + +use Zend\Soap\Exception; /** * Zend_Soap_Wsdl_Strategy_DefaultComplexType * * @category Zend * @package Zend_Soap - * @subpackage Wsdl - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License + * @subpackage WSDL */ -class Zend_Soap_Wsdl_Strategy_DefaultComplexType extends Zend_Soap_Wsdl_Strategy_Abstract +class DefaultComplexType extends AbstractComplexTypeStrategy { /** * Add a complex type by recursivly using all the class properties fetched via Reflection. * * @param string $type Name of the class to be specified + * @throws Exception\InvalidArgumentException if class does not exist * @return string XSD Type for the given PHP type */ public function addComplexType($type) { - if(!class_exists($type)) { - #require_once "Zend/Soap/Wsdl/Exception.php"; - throw new Zend_Soap_Wsdl_Exception(sprintf( - "Cannot add a complex type %s that is not an object or where ". - "class could not be found in 'DefaultComplexType' strategy.", $type + if (!class_exists($type)) { + throw new Exception\InvalidArgumentException(sprintf( + 'Cannot add a complex type %s that is not an object or where ' + . 'class could not be found in \'DefaultComplexType\' strategy.', $type )); } + if (($soapType = $this->scanRegisteredTypes($type)) !== null) { + return $soapType; + } + $dom = $this->getContext()->toDomDocument(); - $class = new ReflectionClass($type); + $class = new \ReflectionClass($type); + + $soapTypeName = $this->getContext()->translateType($type); + $soapType = 'tns:' . $soapTypeName; + + // Register type here to avoid recursion + $this->getContext()->addType($type, $soapType); + $defaultProperties = $class->getDefaultProperties(); $complexType = $dom->createElement('xsd:complexType'); - $complexType->setAttribute('name', $type); + $complexType->setAttribute('name', $soapTypeName); $all = $dom->createElement('xsd:all'); @@ -84,8 +80,7 @@ class Zend_Soap_Wsdl_Strategy_DefaultComplexType extends Zend_Soap_Wsdl_Strategy $complexType->appendChild($all); $this->getContext()->getSchema()->appendChild($complexType); - $this->getContext()->addType($type); - return "tns:$type"; + return $soapType; } } diff --git a/lib/Zend/Soap/Wsdl/Exception.php b/lib/Zend/Soap/Wsdl/Exception.php deleted file mode 100644 index 97cd19b0b46812cf2627fd6987b70ad658e2b395..0000000000000000000000000000000000000000 --- a/lib/Zend/Soap/Wsdl/Exception.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php -/** - * Zend Framework - * - * LICENSE - * - * This source file is subject to the new BSD license that is bundled - * with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://framework.zend.com/license/new-bsd - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@zend.com so we can send you a copy immediately. - * - * @category Zend - * @package Zend_Soap - * @subpackage Wsdl - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - * @version $Id: Exception.php 20096 2010-01-06 02:05:09Z bkarwin $ - */ - -/** - * @see Zend_Exception - */ -#require_once "Zend/Exception.php"; - -/** - * Zend_Soap_Wsdl_Exception - * - * @category Zend - * @package Zend_Soap - * @subpackage Wsdl - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - */ -class Zend_Soap_Wsdl_Exception extends Zend_Exception { } \ No newline at end of file diff --git a/lib/Zend/Soap/Wsdl/Strategy/Abstract.php b/lib/Zend/Soap/Wsdl/Strategy/Abstract.php deleted file mode 100644 index f2c36a4c4c402c3bcd93260d7805c98654f1c141..0000000000000000000000000000000000000000 --- a/lib/Zend/Soap/Wsdl/Strategy/Abstract.php +++ /dev/null @@ -1,66 +0,0 @@ -<?php -/** - * Zend Framework - * - * LICENSE - * - * This source file is subject to the new BSD license that is bundled - * with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://framework.zend.com/license/new-bsd - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@zend.com so we can send you a copy immediately. - * - * @category Zend - * @package Zend_Soap - * @subpackage Wsdl - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - * @version $Id: Abstract.php 20096 2010-01-06 02:05:09Z bkarwin $ - */ - -/** - * @see Zend_Soap_Wsdl_Strategy_Interface - */ -#require_once "Zend/Soap/Wsdl/Strategy/Interface.php"; - -/** - * Abstract class for Zend_Soap_Wsdl_Strategy. - * - * @category Zend - * @package Zend_Soap - * @subpackage Wsdl - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - */ -abstract class Zend_Soap_Wsdl_Strategy_Abstract implements Zend_Soap_Wsdl_Strategy_Interface -{ - /** - * Context object - * - * @var Zend_Soap_Wsdl - */ - protected $_context; - - /** - * Set the Zend_Soap_Wsdl Context object this strategy resides in. - * - * @param Zend_Soap_Wsdl $context - * @return void - */ - public function setContext(Zend_Soap_Wsdl $context) - { - $this->_context = $context; - } - - /** - * Return the current Zend_Soap_Wsdl context object - * - * @return Zend_Soap_Wsdl - */ - public function getContext() - { - return $this->_context; - } -} diff --git a/lib/Zend/Soap/Wsdl/Strategy/AnyType.php b/lib/Zend/Soap/Wsdl/Strategy/AnyType.php deleted file mode 100644 index fa6158d75d876ee0cacc14955aac9b9b0f431500..0000000000000000000000000000000000000000 --- a/lib/Zend/Soap/Wsdl/Strategy/AnyType.php +++ /dev/null @@ -1,59 +0,0 @@ -<?php -/** - * Zend Framework - * - * LICENSE - * - * This source file is subject to the new BSD license that is bundled - * with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://framework.zend.com/license/new-bsd - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@zend.com so we can send you a copy immediately. - * - * @category Zend - * @package Zend_Soap - * @subpackage Wsdl - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - * @version $Id: AnyType.php 20096 2010-01-06 02:05:09Z bkarwin $ - */ - -/** - * @see Zend_Soap_Wsdl_Strategy_Interface - */ -#require_once "Zend/Soap/Wsdl/Strategy/Interface.php"; - -/** - * Zend_Soap_Wsdl_Strategy_AnyType - * - * @category Zend - * @package Zend_Soap - * @subpackage Wsdl - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - */ -class Zend_Soap_Wsdl_Strategy_AnyType implements Zend_Soap_Wsdl_Strategy_Interface -{ - /** - * Not needed in this strategy. - * - * @param Zend_Soap_Wsdl $context - */ - public function setContext(Zend_Soap_Wsdl $context) - { - - } - - /** - * Returns xsd:anyType regardless of the input. - * - * @param string $type - * @return string - */ - public function addComplexType($type) - { - return 'xsd:anyType'; - } -} \ No newline at end of file diff --git a/lib/Zend/Soap/Wsdl/Strategy/ArrayOfTypeComplex.php b/lib/Zend/Soap/Wsdl/Strategy/ArrayOfTypeComplex.php deleted file mode 100644 index d6ac5ff26a3814911370c0f1b928db95a1b759ce..0000000000000000000000000000000000000000 --- a/lib/Zend/Soap/Wsdl/Strategy/ArrayOfTypeComplex.php +++ /dev/null @@ -1,145 +0,0 @@ -<?php -/** - * Zend Framework - * - * LICENSE - * - * This source file is subject to the new BSD license that is bundled - * with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://framework.zend.com/license/new-bsd - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@zend.com so we can send you a copy immediately. - * - * @category Zend - * @package Zend_Soap - * @subpackage Wsdl - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - * @version $Id: ArrayOfTypeComplex.php 21858 2010-04-15 19:58:12Z beberlei $ - */ - -/** - * @see Zend_Soap_Wsdl_Strategy_DefaultComplexType - */ -#require_once "Zend/Soap/Wsdl/Strategy/DefaultComplexType.php"; - -/** - * Zend_Soap_Wsdl_Strategy_ArrayOfTypeComplex - * - * @category Zend - * @package Zend_Soap - * @subpackage Wsdl - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - */ -class Zend_Soap_Wsdl_Strategy_ArrayOfTypeComplex extends Zend_Soap_Wsdl_Strategy_DefaultComplexType -{ - protected $_inProcess = array(); - - /** - * Add an ArrayOfType based on the xsd:complexType syntax if type[] is detected in return value doc comment. - * - * @param string $type - * @return string tns:xsd-type - */ - public function addComplexType($type) - { - if (in_array($type, $this->_inProcess)) { - return "tns:" . $type; - } - $this->_inProcess[$type] = $type; - - $nestingLevel = $this->_getNestedCount($type); - - if($nestingLevel > 1) { - #require_once "Zend/Soap/Wsdl/Exception.php"; - throw new Zend_Soap_Wsdl_Exception( - "ArrayOfTypeComplex cannot return nested ArrayOfObject deeper than ". - "one level. Use array object properties to return deep nested data. - "); - } - - $singularType = $this->_getSingularPhpType($type); - - if(!class_exists($singularType)) { - #require_once "Zend/Soap/Wsdl/Exception.php"; - throw new Zend_Soap_Wsdl_Exception(sprintf( - "Cannot add a complex type %s that is not an object or where ". - "class could not be found in 'DefaultComplexType' strategy.", $type - )); - } - - if($nestingLevel == 1) { - // The following blocks define the Array of Object structure - $xsdComplexTypeName = $this->_addArrayOfComplexType($singularType, $type); - } else { - $xsdComplexTypeName = $singularType; - } - - // The array for the objects has been created, now build the object definition: - if(!in_array($singularType, $this->getContext()->getTypes())) { - parent::addComplexType($singularType); - } - - unset($this->_inProcess[$type]); - return "tns:".$xsdComplexTypeName; - } - - protected function _addArrayOfComplexType($singularType, $type) - { - $dom = $this->getContext()->toDomDocument(); - - $xsdComplexTypeName = $this->_getXsdComplexTypeName($singularType); - - if(!in_array($xsdComplexTypeName, $this->getContext()->getTypes())) { - $complexType = $dom->createElement('xsd:complexType'); - $complexType->setAttribute('name', $xsdComplexTypeName); - - $complexContent = $dom->createElement("xsd:complexContent"); - $complexType->appendChild($complexContent); - - $xsdRestriction = $dom->createElement("xsd:restriction"); - $xsdRestriction->setAttribute('base', 'soap-enc:Array'); - $complexContent->appendChild($xsdRestriction); - - $xsdAttribute = $dom->createElement("xsd:attribute"); - $xsdAttribute->setAttribute("ref", "soap-enc:arrayType"); - $xsdAttribute->setAttribute("wsdl:arrayType", sprintf("tns:%s[]", $singularType)); - $xsdRestriction->appendChild($xsdAttribute); - - $this->getContext()->getSchema()->appendChild($complexType); - $this->getContext()->addType($xsdComplexTypeName); - } - - return $xsdComplexTypeName; - } - - protected function _getXsdComplexTypeName($type) - { - return sprintf('ArrayOf%s', $type); - } - - /** - * From a nested definition with type[], get the singular PHP Type - * - * @param string $type - * @return string - */ - protected function _getSingularPhpType($type) - { - return str_replace("[]", "", $type); - } - - /** - * Return the array nesting level based on the type name - * - * @param string $type - * @return integer - */ - protected function _getNestedCount($type) - { - return substr_count($type, "[]"); - } -} \ No newline at end of file diff --git a/lib/Zend/Soap/Wsdl/Strategy/ArrayOfTypeSequence.php b/lib/Zend/Soap/Wsdl/Strategy/ArrayOfTypeSequence.php deleted file mode 100644 index 6cb48975c1a40af884a13166f7b7aecf0fe7cde3..0000000000000000000000000000000000000000 --- a/lib/Zend/Soap/Wsdl/Strategy/ArrayOfTypeSequence.php +++ /dev/null @@ -1,155 +0,0 @@ -<?php -/** - * Zend Framework - * - * LICENSE - * - * This source file is subject to the new BSD license that is bundled - * with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://framework.zend.com/license/new-bsd - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@zend.com so we can send you a copy immediately. - * - * @category Zend - * @package Zend_Soap - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - * @version $Id: ArrayOfTypeSequence.php 20096 2010-01-06 02:05:09Z bkarwin $ - */ - -/** - * @see Zend_Soap_Wsdl_Strategy_DefaultComplexType - */ -#require_once "Zend/Soap/Wsdl/Strategy/DefaultComplexType.php"; - -/** - * Zend_Soap_Wsdl_Strategy_ArrayOfTypeSequence - * - * @category Zend - * @package Zend_Soap - * @subpackage Wsdl - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - */ -class Zend_Soap_Wsdl_Strategy_ArrayOfTypeSequence extends Zend_Soap_Wsdl_Strategy_DefaultComplexType -{ - /** - * Add an unbounded ArrayOfType based on the xsd:sequence syntax if type[] is detected in return value doc comment. - * - * @param string $type - * @return string tns:xsd-type - */ - public function addComplexType($type) - { - $nestedCounter = $this->_getNestedCount($type); - - if($nestedCounter > 0) { - $singularType = $this->_getSingularType($type); - - for($i = 1; $i <= $nestedCounter; $i++) { - $complexTypeName = substr($this->_getTypeNameBasedOnNestingLevel($singularType, $i), 4); - $childTypeName = $this->_getTypeNameBasedOnNestingLevel($singularType, $i-1); - - $this->_addElementFromWsdlAndChildTypes($complexTypeName, $childTypeName); - } - // adding the PHP type which is resolved to a nested XSD type. therefore add only once. - $this->getContext()->addType($complexTypeName); - - return "tns:$complexTypeName"; - } else if (!in_array($type, $this->getContext()->getTypes())) { - // New singular complex type - return parent::addComplexType($type); - } else { - // Existing complex type - return $this->getContext()->getType($type); - } - } - - /** - * Return the ArrayOf or simple type name based on the singular xsdtype and the nesting level - * - * @param string $singularType - * @param int $level - * @return string - */ - protected function _getTypeNameBasedOnNestingLevel($singularType, $level) - { - if($level == 0) { - // This is not an Array anymore, return the xsd simple type - return $singularType; - } else { - $prefix = str_repeat("ArrayOf", $level); - $xsdType = $this->_getStrippedXsdType($singularType); - $arrayType = $prefix.$xsdType; - return "tns:$arrayType"; - } - } - - /** - * Strip the xsd: from a singularType and Format it nice for ArrayOf<Type> naming - * - * @param string $singularType - * @return string - */ - protected function _getStrippedXsdType($singularType) - { - return ucfirst(substr(strtolower($singularType), 4)); - } - - /** - * From a nested defintion with type[], get the singular xsd:type - * - * @throws Zend_Soap_Wsdl_Exception When no xsd:simpletype can be detected. - * @param string $type - * @return string - */ - protected function _getSingularType($type) - { - $singulartype = $this->getContext()->getType(str_replace("[]", "", $type)); - return $singulartype; - } - - /** - * Return the array nesting level based on the type name - * - * @param string $type - * @return integer - */ - protected function _getNestedCount($type) - { - return substr_count($type, "[]"); - } - - /** - * Append the complex type definition to the WSDL via the context access - * - * @param string $arrayType - * @param string $childTypeName - * @return void - */ - protected function _addElementFromWsdlAndChildTypes($arrayType, $childTypeName) - { - if (!in_array($arrayType, $this->getContext()->getTypes())) { - $dom = $this->getContext()->toDomDocument(); - - $complexType = $dom->createElement('xsd:complexType'); - $complexType->setAttribute('name', $arrayType); - - $sequence = $dom->createElement('xsd:sequence'); - - $element = $dom->createElement('xsd:element'); - $element->setAttribute('name', 'item'); - $element->setAttribute('type', $childTypeName); - $element->setAttribute('minOccurs', 0); - $element->setAttribute('maxOccurs', 'unbounded'); - $sequence->appendChild($element); - - $complexType->appendChild($sequence); - - $this->getContext()->getSchema()->appendChild($complexType); - $this->getContext()->addType($arrayType); - } - } -} diff --git a/lib/Zend/Soap/Wsdl/Strategy/Composite.php b/lib/Zend/Soap/Wsdl/Strategy/Composite.php deleted file mode 100644 index 0ee943fac8910b81bdfa59c1e3d7fa71baeb0e28..0000000000000000000000000000000000000000 --- a/lib/Zend/Soap/Wsdl/Strategy/Composite.php +++ /dev/null @@ -1,188 +0,0 @@ -<?php -/** - * Zend Framework - * - * LICENSE - * - * This source file is subject to the new BSD license that is bundled - * with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://framework.zend.com/license/new-bsd - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@zend.com so we can send you a copy immediately. - * - * @category Zend - * @package Zend_Soap - * @subpackage Wsdl - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - * @version $Id: Composite.php 20096 2010-01-06 02:05:09Z bkarwin $ - */ - -/** - * @see Zend_Soap_Wsdl_Strategy_Interface - */ -#require_once "Zend/Soap/Wsdl/Strategy/Interface.php"; - -/** - * Zend_Soap_Wsdl_Strategy_Composite - * - * @category Zend - * @package Zend_Soap - * @subpackage Wsdl - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - */ -class Zend_Soap_Wsdl_Strategy_Composite implements Zend_Soap_Wsdl_Strategy_Interface -{ - /** - * Typemap of Complex Type => Strategy pairs. - * - * @var array - */ - protected $_typeMap = array(); - - /** - * Default Strategy of this composite - * - * @var string|Zend_Soap_Wsdl_Strategy_Interface - */ - protected $_defaultStrategy; - - /** - * Context WSDL file that this composite serves - * - * @var Zend_Soap_Wsdl|null - */ - protected $_context; - - /** - * Construct Composite WSDL Strategy. - * - * @throws Zend_Soap_Wsdl_Exception - * @param array $typeMap - * @param string|Zend_Soap_Wsdl_Strategy_Interface $defaultStrategy - */ - public function __construct(array $typeMap=array(), $defaultStrategy="Zend_Soap_Wsdl_Strategy_DefaultComplexType") - { - foreach($typeMap AS $type => $strategy) { - $this->connectTypeToStrategy($type, $strategy); - } - $this->_defaultStrategy = $defaultStrategy; - } - - /** - * Connect a complex type to a given strategy. - * - * @throws Zend_Soap_Wsdl_Exception - * @param string $type - * @param string|Zend_Soap_Wsdl_Strategy_Interface $strategy - * @return Zend_Soap_Wsdl_Strategy_Composite - */ - public function connectTypeToStrategy($type, $strategy) - { - if(!is_string($type)) { - /** - * @see Zend_Soap_Wsdl_Exception - */ - #require_once "Zend/Soap/Wsdl/Exception.php"; - throw new Zend_Soap_Wsdl_Exception("Invalid type given to Composite Type Map."); - } - $this->_typeMap[$type] = $strategy; - return $this; - } - - /** - * Return default strategy of this composite - * - * @throws Zend_Soap_Wsdl_Exception - * @param string $type - * @return Zend_Soap_Wsdl_Strategy_Interface - */ - public function getDefaultStrategy() - { - $strategy = $this->_defaultStrategy; - if(is_string($strategy) && class_exists($strategy)) { - $strategy = new $strategy; - } - if( !($strategy instanceof Zend_Soap_Wsdl_Strategy_Interface) ) { - /** - * @see Zend_Soap_Wsdl_Exception - */ - #require_once "Zend/Soap/Wsdl/Exception.php"; - throw new Zend_Soap_Wsdl_Exception( - "Default Strategy for Complex Types is not a valid strategy object." - ); - } - $this->_defaultStrategy = $strategy; - return $strategy; - } - - /** - * Return specific strategy or the default strategy of this type. - * - * @throws Zend_Soap_Wsdl_Exception - * @param string $type - * @return Zend_Soap_Wsdl_Strategy_Interface - */ - public function getStrategyOfType($type) - { - if(isset($this->_typeMap[$type])) { - $strategy = $this->_typeMap[$type]; - - if(is_string($strategy) && class_exists($strategy)) { - $strategy = new $strategy(); - } - - if( !($strategy instanceof Zend_Soap_Wsdl_Strategy_Interface) ) { - /** - * @see Zend_Soap_Wsdl_Exception - */ - #require_once "Zend/Soap/Wsdl/Exception.php"; - throw new Zend_Soap_Wsdl_Exception( - "Strategy for Complex Type '".$type."' is not a valid strategy object." - ); - } - $this->_typeMap[$type] = $strategy; - } else { - $strategy = $this->getDefaultStrategy(); - } - return $strategy; - } - - /** - * Method accepts the current WSDL context file. - * - * @param Zend_Soap_Wsdl $context - */ - public function setContext(Zend_Soap_Wsdl $context) - { - $this->_context = $context; - return $this; - } - - /** - * Create a complex type based on a strategy - * - * @throws Zend_Soap_Wsdl_Exception - * @param string $type - * @return string XSD type - */ - public function addComplexType($type) - { - if(!($this->_context instanceof Zend_Soap_Wsdl) ) { - /** - * @see Zend_Soap_Wsdl_Exception - */ - #require_once "Zend/Soap/Wsdl/Exception.php"; - throw new Zend_Soap_Wsdl_Exception( - "Cannot add complex type '".$type."', no context is set for this composite strategy." - ); - } - - $strategy = $this->getStrategyOfType($type); - $strategy->setContext($this->_context); - return $strategy->addComplexType($type); - } -} \ No newline at end of file diff --git a/lib/Zend/Soap/Wsdl/Strategy/Interface.php b/lib/Zend/Soap/Wsdl/Strategy/Interface.php deleted file mode 100644 index d53d4f62ec987ad4b36c77334f03298cccdfa7ed..0000000000000000000000000000000000000000 --- a/lib/Zend/Soap/Wsdl/Strategy/Interface.php +++ /dev/null @@ -1,48 +0,0 @@ -<?php -/** - * Zend Framework - * - * LICENSE - * - * This source file is subject to the new BSD license that is bundled - * with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://framework.zend.com/license/new-bsd - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@zend.com so we can send you a copy immediately. - * - * @category Zend - * @package Zend_Soap - * @subpackage Wsdl - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - * @version $Id: Interface.php 20096 2010-01-06 02:05:09Z bkarwin $ - */ - -/** - * Interface for Zend_Soap_Wsdl_Strategy. - * - * @category Zend - * @package Zend_Soap - * @subpackage Wsdl - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - */ -interface Zend_Soap_Wsdl_Strategy_Interface -{ - /** - * Method accepts the current WSDL context file. - * - * @param <type> $context - */ - public function setContext(Zend_Soap_Wsdl $context); - - /** - * Create a complex type based on a strategy - * - * @param string $type - * @return string XSD type - */ - public function addComplexType($type); -} \ No newline at end of file diff --git a/lib/Zend/Soap/composer.json b/lib/Zend/Soap/composer.json new file mode 100644 index 0000000000000000000000000000000000000000..fbf77e9ce41f25ec1c618592f3ddd9aeffdb8046 --- /dev/null +++ b/lib/Zend/Soap/composer.json @@ -0,0 +1,21 @@ +{ + "name": "zendframework/zend-soap", + "description": " ", + "license": "BSD-3-Clause", + "keywords": [ + "zf2", + "soap" + ], + "autoload": { + "psr-0": { + "Zend\\Soap": "" + } + }, + "target-dir": "Zend/Soap", + "require": { + "php": ">=5.3.3", + "zendframework/zend-server": "self.version", + "zendframework/zend-stdlib": "self.version", + "zendframework/zend-uri": "self.version" + } +} \ No newline at end of file diff --git a/lib/Zend/Uri/Exception/ExceptionInterface.php b/lib/Zend/Uri/Exception/ExceptionInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..056cc70ae82b1659a66cd06d1e02db8b011ebade --- /dev/null +++ b/lib/Zend/Uri/Exception/ExceptionInterface.php @@ -0,0 +1,20 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Uri + */ + +namespace Zend\Uri\Exception; + +/** + * Exception for Zend_Uri + * + * @category Zend + * @package Zend_Uri + */ +interface ExceptionInterface +{} diff --git a/lib/Zend/Uri/Exception/InvalidArgumentException.php b/lib/Zend/Uri/Exception/InvalidArgumentException.php new file mode 100644 index 0000000000000000000000000000000000000000..dfb2a186d1a9be9bc749c7d3f2489c691b455572 --- /dev/null +++ b/lib/Zend/Uri/Exception/InvalidArgumentException.php @@ -0,0 +1,16 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Uri + */ + +namespace Zend\Uri\Exception; + +class InvalidArgumentException + extends \InvalidArgumentException + implements ExceptionInterface +{} diff --git a/lib/Zend/Uri/Exception/InvalidUriException.php b/lib/Zend/Uri/Exception/InvalidUriException.php new file mode 100644 index 0000000000000000000000000000000000000000..0f362246907c485f78419734fd1fe9a4d89110b4 --- /dev/null +++ b/lib/Zend/Uri/Exception/InvalidUriException.php @@ -0,0 +1,20 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Uri + */ + +namespace Zend\Uri\Exception; + +/** + * Exceptions for Zend_Uri + * + * @category Zend + * @package Zend_Uri + */ +class InvalidUriException extends InvalidArgumentException implements ExceptionInterface +{} diff --git a/lib/Zend/Uri/Exception/InvalidUriPartException.php b/lib/Zend/Uri/Exception/InvalidUriPartException.php new file mode 100644 index 0000000000000000000000000000000000000000..0ab1223647d6473d5d8975133a14b541ec2739b5 --- /dev/null +++ b/lib/Zend/Uri/Exception/InvalidUriPartException.php @@ -0,0 +1,35 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Uri + */ + +namespace Zend\Uri\Exception; + +/** + * @category Zend + * @package Zend_Uri + * @subpackage Exception + */ +class InvalidUriPartException extends InvalidArgumentException +{ + /** + * Part-specific error codes + * + * @var integer + */ + const INVALID_SCHEME = 1; + const INVALID_USER = 2; + const INVALID_PASSWORD = 4; + const INVALID_USERINFO = 6; + const INVALID_HOSTNAME = 8; + const INVALID_PORT = 16; + const INVALID_AUTHORITY = 30; + const INVALID_PATH = 32; + const INVALID_QUERY = 64; + const INVALID_FRAGMENT = 128; +} diff --git a/lib/Zend/Uri/File.php b/lib/Zend/Uri/File.php new file mode 100644 index 0000000000000000000000000000000000000000..2427c65f6180ab8adaa03434235313dc2b768538 --- /dev/null +++ b/lib/Zend/Uri/File.php @@ -0,0 +1,105 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Uri + */ + +namespace Zend\Uri; + +/** + * File URI handler + * + * The 'file:...' scheme is loosely defined in RFC-1738 + * + * @category Zend + * @package Zend_Uri + */ +class File extends Uri +{ + protected static $validSchemes = array('file'); + + /** + * Check if the URI is a valid File URI + * + * This applies additional specific validation rules beyond the ones + * required by the generic URI syntax. + * + * @return boolean + * @see Uri::isValid() + */ + public function isValid() + { + if ($this->query) { + return false; + } + + return parent::isValid(); + } + + /** + * User Info part is not used in file URIs + * + * @see Uri::setUserInfo() + * @param string $userInfo + * @return File + */ + public function setUserInfo($userInfo) + { + return $this; + } + + /** + * Fragment part is not used in file URIs + * + * @see Uri::setFragment() + * @param string $fragment + * @return File + */ + public function setFragment($fragment) + { + return $this; + } + + /** + * Convert a UNIX file path to a valid file:// URL + * + * @param string $path + * @return File + */ + public static function fromUnixPath($path) + { + $url = new self('file:'); + if (substr($path, 0, 1) == '/') { + $url->setHost(''); + } + + $url->setPath($path); + return $url; + } + + /** + * Convert a Windows file path to a valid file:// URL + * + * @param string $path + * @return File + */ + public static function fromWindowsPath($path) + { + $url = new self('file:'); + + // Convert directory separators + $path = str_replace(array('/', '\\'), array('%2F', '/'), $path); + + // Is this an absolute path? + if (preg_match('|^([a-zA-Z]:)?/|', $path)) { + $url->setHost(''); + } + + $url->setPath($path); + return $url; + } +} diff --git a/lib/Zend/Uri/Mailto.php b/lib/Zend/Uri/Mailto.php new file mode 100644 index 0000000000000000000000000000000000000000..f6f0d3126cc5819e4a76a65e6f79c9912553260e --- /dev/null +++ b/lib/Zend/Uri/Mailto.php @@ -0,0 +1,113 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Uri + */ + +namespace Zend\Uri; + +use Zend\Validator\EmailAddress as EmailValidator; +use Zend\Validator\ValidatorInterface; + +/** + * "Mailto" URI handler + * + * The 'mailto:...' scheme is loosely defined in RFC-1738 + * + * @category Zend + * @package Zend_Uri + */ +class Mailto extends Uri +{ + protected static $validSchemes = array('mailto'); + + /** + * Validator for use when validating email address + * @var ValidatorInterface + */ + protected $emailValidator; + + /** + * Check if the URI is a valid Mailto URI + * + * This applies additional specific validation rules beyond the ones + * required by the generic URI syntax + * + * @return boolean + * @see Uri::isValid() + */ + public function isValid() + { + if ($this->host || $this->userInfo || $this->port) { + return false; + } + + if (empty($this->path)) { + return false; + } + + if (0 === strpos($this->path, '/')) { + return false; + } + + $validator = $this->getValidator(); + return $validator->isValid($this->path); + } + + /** + * Set the email address + * + * This is in fact equivalent to setPath() - but provides a more clear interface + * + * @param string $email + * @return Mailto + */ + public function setEmail($email) + { + return $this->setPath($email); + } + + /** + * Get the email address + * + * This is infact equivalent to getPath() - but provides a more clear interface + * + * @return string + */ + public function getEmail() + { + return $this->getPath(); + } + + /** + * Set validator to use when validating email address + * + * @param ValidatorInterface $validator + * @return Mailto + */ + public function setValidator(ValidatorInterface $validator) + { + $this->emailValidator = $validator; + return $this; + } + + /** + * Retrieve validator for use with validating email address + * + * If none is currently set, an EmailValidator instance with default options + * will be used. + * + * @return ValidatorInterface + */ + public function getValidator() + { + if (null === $this->emailValidator) { + $this->setValidator(new EmailValidator()); + } + return $this->emailValidator; + } +} diff --git a/lib/Zend/Uri/Uri.php b/lib/Zend/Uri/Uri.php new file mode 100644 index 0000000000000000000000000000000000000000..08e24063aa6b80938a7bef1906c37282ce4dad35 --- /dev/null +++ b/lib/Zend/Uri/Uri.php @@ -0,0 +1,1335 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Uri + */ + +namespace Zend\Uri; + +use Zend\Escaper\Escaper; +use Zend\Validator; + +/** + * Generic URI handler + * + * @category Zend + * @package Zend_Uri + */ +class Uri implements UriInterface +{ + /** + * Character classes defined in RFC-3986 + */ + const CHAR_UNRESERVED = 'a-zA-Z0-9_\-\.~'; + const CHAR_GEN_DELIMS = ':\/\?#\[\]@'; + const CHAR_SUB_DELIMS = '!\$&\'\(\)\*\+,;='; + const CHAR_RESERVED = ':\/\?#\[\]@!\$&\'\(\)\*\+,;='; + + /** + * Host part types represented as binary masks + * The binary mask consists of 5 bits in the following order: + * <RegName> | <DNS> | <IPvFuture> | <IPv6> | <IPv4> + * Place 1 or 0 in the different positions for enable or disable the part. + * Finally use a hexadecimal representation. + */ + const HOST_IPV4 = 0x01; //00001 + const HOST_IPV6 = 0x02; //00010 + const HOST_IPVFUTURE = 0x04; //00100 + const HOST_IPVANY = 0x07; //00111 + const HOST_DNS = 0x08; //01000 + const HOST_DNS_OR_IPV4 = 0x09; //01001 + const HOST_DNS_OR_IPV6 = 0x0A; //01010 + const HOST_DNS_OR_IPV4_OR_IPV6 = 0x0B; //01011 + const HOST_DNS_OR_IPVANY = 0x0F; //01111 + const HOST_REGNAME = 0x10; //10000 + const HOST_ALL = 0x1F; //11111 + + /** + * URI scheme + * + * @var string + */ + protected $scheme; + + /** + * URI userInfo part (usually user:password in HTTP URLs) + * + * @var string + */ + protected $userInfo; + + /** + * URI hostname + * + * @var string + */ + protected $host; + + /** + * URI port + * + * @var integer + */ + protected $port; + + /** + * URI path + * + * @var string + */ + protected $path; + + /** + * URI query string + * + * @var string + */ + protected $query; + + /** + * URI fragment + * + * @var string + */ + protected $fragment; + + /** + * Which host part types are valid for this URI? + * + * @var integer + */ + protected $validHostTypes = self::HOST_ALL; + + /** + * Array of valid schemes. + * + * Subclasses of this class that only accept specific schemes may set the + * list of accepted schemes here. If not empty, when setScheme() is called + * it will only accept the schemes listed here. + * + * @var array + */ + protected static $validSchemes = array(); + + /** + * List of default ports per scheme + * + * Inheriting URI classes may set this, and the normalization methods will + * automatically remove the port if it is equal to the default port for the + * current scheme + * + * @var array + */ + protected static $defaultPorts = array(); + + /** + * @var Escaper + */ + protected static $escaper; + + /** + * Create a new URI object + * + * @param Uri|string|null $uri + * @throws Exception\InvalidArgumentException + */ + public function __construct($uri = null) + { + if (is_string($uri)) { + $this->parse($uri); + } elseif ($uri instanceof UriInterface) { + // Copy constructor + $this->setScheme($uri->getScheme()); + $this->setUserInfo($uri->getUserInfo()); + $this->setHost($uri->getHost()); + $this->setPort($uri->getPort()); + $this->setPath($uri->getPath()); + $this->setQuery($uri->getQuery()); + $this->setFragment($uri->getFragment()); + } elseif ($uri !== null) { + throw new Exception\InvalidArgumentException(sprintf( + 'Expecting a string or a URI object, received "%s"', + (is_object($uri) ? get_class($uri) : gettype($uri)) + )); + } + } + + /** + * Set Escaper instance + * + * @param Escaper $escaper + */ + public static function setEscaper(Escaper $escaper) + { + static::$escaper = $escaper; + } + + /** + * Retrieve Escaper instance + * + * Lazy-loads one if none provided + * + * @return Escaper + */ + public static function getEscaper() + { + if (null === static::$escaper) { + static::setEscaper(new Escaper()); + } + return static::$escaper; + } + + /** + * Check if the URI is valid + * + * Note that a relative URI may still be valid + * + * @return boolean + */ + public function isValid() + { + if ($this->host) { + if (strlen($this->path) > 0 && substr($this->path, 0, 1) != '/') { + return false; + } + return true; + } + + if ($this->userInfo || $this->port) { + return false; + } + + if ($this->path) { + // Check path-only (no host) URI + if (substr($this->path, 0, 2) == '//') { + return false; + } + return true; + } + + if (! ($this->query || $this->fragment)) { + // No host, path, query or fragment - this is not a valid URI + return false; + } + + return true; + } + + /** + * Check if the URI is a valid relative URI + * + * @return boolean + */ + public function isValidRelative() + { + if ($this->scheme || $this->host || $this->userInfo || $this->port) { + return false; + } + + if ($this->path) { + // Check path-only (no host) URI + if (substr($this->path, 0, 2) == '//') { + return false; + } + return true; + } + + if (! ($this->query || $this->fragment)) { + // No host, path, query or fragment - this is not a valid URI + return false; + } + + return true; + } + + /** + * Check if the URI is an absolute or relative URI + * + * @return boolean + */ + public function isAbsolute() + { + return ($this->scheme !== null); + } + + /** + * Parse a URI string + * + * @param string $uri + * @return Uri + */ + public function parse($uri) + { + // Capture scheme + if (($scheme = self::parseScheme($uri)) !== null) { + $this->setScheme($scheme); + $uri = substr($uri, strlen($scheme) + 1); + } + + // Capture authority part + if (preg_match('|^//([^/\?#]*)|', $uri, $match)) { + $authority = $match[1]; + $uri = substr($uri, strlen($match[0])); + + // Split authority into userInfo and host + if (strpos($authority, '@') !== false) { + // The userInfo can also contain '@' symbols; split $authority + // into segments, and set it to the last segment. + $segments = explode('@', $authority); + $authority = array_pop($segments); + $userInfo = implode('@', $segments); + unset($segments); + $this->setUserInfo($userInfo); + } + + $nMatches = preg_match('/:[\d]{1,5}$/', $authority, $matches); + if ($nMatches === 1) { + $portLength = strlen($matches[0]); + $port = substr($matches[0], 1); + + $this->setPort((int) $port); + $authority = substr($authority, 0, -$portLength); + } + + $this->setHost($authority); + } + + if (!$uri) { + return $this; + } + + // Capture the path + if (preg_match('|^[^\?#]*|', $uri, $match)) { + $this->setPath($match[0]); + $uri = substr($uri, strlen($match[0])); + } + + if (!$uri) { + return $this; + } + + // Capture the query + if (preg_match('|^\?([^#]*)|', $uri, $match)) { + $this->setQuery($match[1]); + $uri = substr($uri, strlen($match[0])); + } + if (!$uri) { + return $this; + } + + // All that's left is the fragment + if ($uri && substr($uri, 0, 1) == '#') { + $this->setFragment(substr($uri, 1)); + } + + return $this; + } + + /** + * Compose the URI into a string + * + * @return string + * @throws Exception\InvalidUriException + */ + public function toString() + { + if (!$this->isValid()) { + if ($this->isAbsolute() || !$this->isValidRelative()) { + throw new Exception\InvalidUriException( + 'URI is not valid and cannot be converted into a string' + ); + } + } + + $uri = ''; + + if ($this->scheme) { + $uri .= $this->scheme . ':'; + } + + if ($this->host !== null) { + $uri .= '//'; + if ($this->userInfo) { + $uri .= $this->userInfo . '@'; + } + $uri .= $this->host; + if ($this->port) { + $uri .= ':' . $this->port; + } + } + + if ($this->path) { + $uri .= self::encodePath($this->path); + } elseif ($this->host && ($this->query || $this->fragment)) { + $uri .= '/'; + } + + if ($this->query) { + $uri .= "?" . self::encodeQueryFragment($this->query); + } + + if ($this->fragment) { + $uri .= "#" . self::encodeQueryFragment($this->fragment); + } + + return $uri; + } + + /** + * Normalize the URI + * + * Normalizing a URI includes removing any redundant parent directory or + * current directory references from the path (e.g. foo/bar/../baz becomes + * foo/baz), normalizing the scheme case, decoding any over-encoded + * characters etc. + * + * Eventually, two normalized URLs pointing to the same resource should be + * equal even if they were originally represented by two different strings + * + * @return Uri + */ + public function normalize() + { + if ($this->scheme) { + $this->scheme = static::normalizeScheme($this->scheme); + } + + if ($this->host) { + $this->host = static::normalizeHost($this->host); + } + + if ($this->port) { + $this->port = static::normalizePort($this->port, $this->scheme); + } + + if ($this->path) { + $this->path = static::normalizePath($this->path); + } + + if ($this->query) { + $this->query = static::normalizeQuery($this->query); + } + + if ($this->fragment) { + $this->fragment = static::normalizeFragment($this->fragment); + } + + // If path is empty (and we have a host), path should be '/' + // Isn't this valid ONLY for HTTP-URI? + if ($this->host && empty($this->path)) { + $this->path = '/'; + } + + return $this; + } + + /** + * Convert a relative URI into an absolute URI using a base absolute URI as + * a reference. + * + * This is similar to merge() - only it uses the supplied URI as the + * base reference instead of using the current URI as the base reference. + * + * Merging algorithm is adapted from RFC-3986 section 5.2 + * (@link http://tools.ietf.org/html/rfc3986#section-5.2) + * + * @param Uri|string $baseUri + * @throws Exception\InvalidArgumentException + * @return Uri + */ + public function resolve($baseUri) + { + // Ignore if URI is absolute + if ($this->isAbsolute()) { + return $this; + } + + if (is_string($baseUri)) { + $baseUri = new static($baseUri); + } elseif (!$baseUri instanceof Uri) { + throw new Exception\InvalidArgumentException( + 'Provided base URI must be a string or a Uri object' + ); + } + + // Merging starts here... + if ($this->getHost()) { + $this->setPath(static::removePathDotSegments($this->getPath())); + } else { + $basePath = $baseUri->getPath(); + $relPath = $this->getPath(); + if (!$relPath) { + $this->setPath($basePath); + if (!$this->getQuery()) { + $this->setQuery($baseUri->getQuery()); + } + } else { + if (substr($relPath, 0, 1) == '/') { + $this->setPath(static::removePathDotSegments($relPath)); + } else { + if ($baseUri->getHost() && !$basePath) { + $mergedPath = '/'; + } else { + $mergedPath = substr($basePath, 0, strrpos($basePath, '/') + 1); + } + $this->setPath(static::removePathDotSegments($mergedPath . $relPath)); + } + } + + // Set the authority part + $this->setUserInfo($baseUri->getUserInfo()); + $this->setHost($baseUri->getHost()); + $this->setPort($baseUri->getPort()); + } + + $this->setScheme($baseUri->getScheme()); + return $this; + } + + + /** + * Convert the link to a relative link by substracting a base URI + * + * This is the opposite of resolving a relative link - i.e. creating a + * relative reference link from an original URI and a base URI. + * + * If the two URIs do not intersect (e.g. the original URI is not in any + * way related to the base URI) the URI will not be modified. + * + * @param Uri|string $baseUri + * @return Uri + */ + public function makeRelative($baseUri) + { + // Copy base URI, we should not modify it + $baseUri = new static($baseUri); + + $this->normalize(); + $baseUri->normalize(); + + $host = $this->getHost(); + $baseHost = $baseUri->getHost(); + if ($host && $baseHost && ($host != $baseHost)) { + // Not the same hostname + return $this; + } + + $port = $this->getPort(); + $basePort = $baseUri->getPort(); + if ($port && $basePort && ($port != $basePort)) { + // Not the same port + return $this; + } + + $scheme = $this->getScheme(); + $baseScheme = $baseUri->getScheme(); + if ($scheme && $baseScheme && ($scheme != $baseScheme)) { + // Not the same scheme (e.g. HTTP vs. HTTPS) + return $this; + } + + // Remove host, port and scheme + $this->setHost(null) + ->setPort(null) + ->setScheme(null); + + // Is path the same? + if ($this->getPath() == $baseUri->getPath()) { + $this->setPath(''); + return $this; + } + + $pathParts = preg_split('|(/)|', $this->getPath(), null, + PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); + $baseParts = preg_split('|(/)|', $baseUri->getPath(), null, + PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); + + // Get the intersection of existing path parts and those from the + // provided URI + $matchingParts = array_intersect_assoc($pathParts, $baseParts); + + // Loop through the matches + foreach ($matchingParts as $index => $segment) { + // If we skip an index at any point, we have parent traversal, and + // need to prepend the path accordingly + if ($index && !isset($matchingParts[$index - 1])) { + array_unshift($pathParts, '../'); + continue; + } + + // Otherwise, we simply unset the given path segment + unset($pathParts[$index]); + } + + // Reset the path by imploding path segments + $this->setPath(implode($pathParts)); + + return $this; + } + + /** + * Get the scheme part of the URI + * + * @return string|null + */ + public function getScheme() + { + return $this->scheme; + } + + /** + * Get the User-info (usually user:password) part + * + * @return string|null + */ + public function getUserInfo() + { + return $this->userInfo; + } + + /** + * Get the URI host + * + * @return string|null + */ + public function getHost() + { + return $this->host; + } + + /** + * Get the URI port + * + * @return integer|null + */ + public function getPort() + { + return $this->port; + } + + /** + * Get the URI path + * + * @return string|null + */ + public function getPath() + { + return $this->path; + } + + /** + * Get the URI query + * + * @return string|null + */ + public function getQuery() + { + return $this->query; + } + + /** + * Return the query string as an associative array of key => value pairs + * + * This is an extension to RFC-3986 but is quite useful when working with + * most common URI types + * + * @return array + */ + public function getQueryAsArray() + { + $query = array(); + if ($this->query) { + parse_str($this->query, $query); + } + + return $query; + } + + /** + * Get the URI fragment + * + * @return string|null + */ + public function getFragment() + { + return $this->fragment; + } + + /** + * Set the URI scheme + * + * If the scheme is not valid according to the generic scheme syntax or + * is not acceptable by the specific URI class (e.g. 'http' or 'https' are + * the only acceptable schemes for the Zend\Uri\Http class) an exception + * will be thrown. + * + * You can check if a scheme is valid before setting it using the + * validateScheme() method. + * + * @param string $scheme + * @throws Exception\InvalidUriPartException + * @return Uri + */ + public function setScheme($scheme) + { + if (($scheme !== null) && (!self::validateScheme($scheme))) { + throw new Exception\InvalidUriPartException(sprintf( + 'Scheme "%s" is not valid or is not accepted by %s', + $scheme, + get_called_class() + ), Exception\InvalidUriPartException::INVALID_SCHEME); + } + + $this->scheme = $scheme; + return $this; + } + + /** + * Set the URI User-info part (usually user:password) + * + * @param string $userInfo + * @return Uri + * @throws Exception\InvalidUriPartException If the schema definition + * does not have this part + */ + public function setUserInfo($userInfo) + { + $this->userInfo = $userInfo; + return $this; + } + + /** + * Set the URI host + * + * Note that the generic syntax for URIs allows using host names which + * are not necessarily IPv4 addresses or valid DNS host names. For example, + * IPv6 addresses are allowed as well, and also an abstract "registered name" + * which may be any name composed of a valid set of characters, including, + * for example, tilda (~) and underscore (_) which are not allowed in DNS + * names. + * + * Subclasses of Uri may impose more strict validation of host names - for + * example the HTTP RFC clearly states that only IPv4 and valid DNS names + * are allowed in HTTP URIs. + * + * @param string $host + * @throws Exception\InvalidUriPartException + * @return Uri + */ + public function setHost($host) + { + if (($host !== '') + && ($host !== null) + && !self::validateHost($host, $this->validHostTypes) + ) { + throw new Exception\InvalidUriPartException(sprintf( + 'Host "%s" is not valid or is not accepted by %s', + $host, + get_called_class() + ), Exception\InvalidUriPartException::INVALID_HOSTNAME); + } + + $this->host = $host; + return $this; + } + + /** + * Set the port part of the URI + * + * @param integer $port + * @return Uri + */ + public function setPort($port) + { + $this->port = $port; + return $this; + } + + /** + * Set the path + * + * @param string $path + * @return Uri + */ + public function setPath($path) + { + $this->path = $path; + return $this; + } + + /** + * Set the query string + * + * If an array is provided, will encode this array of parameters into a + * query string. Array values will be represented in the query string using + * PHP's common square bracket notation. + * + * @param string|array $query + * @return Uri + */ + public function setQuery($query) + { + if (is_array($query)) { + // We replace the + used for spaces by http_build_query with the + // more standard %20. + $query = str_replace('+', '%20', http_build_query($query)); + } + + $this->query = $query; + return $this; + } + + /** + * Set the URI fragment part + * + * @param string $fragment + * @return Uri + * @throws Exception\InvalidUriPartException If the schema definition + * does not have this part + */ + public function setFragment($fragment) + { + $this->fragment = $fragment; + return $this; + } + + /** + * Magic method to convert the URI to a string + * + * @return string + */ + public function __toString() + { + try { + return $this->toString(); + } catch (\Exception $e) { + return ''; + } + } + + /** + * Encoding and Validation Methods + */ + + /** + * Check if a scheme is valid or not + * + * Will check $scheme to be valid against the generic scheme syntax defined + * in RFC-3986. If the class also defines specific acceptable schemes, will + * also check that $scheme is one of them. + * + * @param string $scheme + * @return boolean + */ + public static function validateScheme($scheme) + { + if (!empty(static::$validSchemes) + && !in_array(strtolower($scheme), static::$validSchemes) + ) { + return false; + } + + return (bool) preg_match('/^[A-Za-z][A-Za-z0-9\-\.+]*$/', $scheme); + } + + /** + * Check that the userInfo part of a URI is valid + * + * @param string $userInfo + * @return boolean + */ + public static function validateUserInfo($userInfo) + { + $regex = '/^(?:[' . self::CHAR_UNRESERVED . self::CHAR_SUB_DELIMS . ':]+|%[A-Fa-f0-9]{2})*$/'; + return (boolean) preg_match($regex, $userInfo); + } + + /** + * Validate the host part + * + * Users may control which host types to allow by passing a second parameter + * with a bitmask of HOST_* constants which are allowed. If not specified, + * all address types will be allowed. + * + * Note that the generic URI syntax allows different host representations, + * including IPv4 addresses, IPv6 addresses and future IP address formats + * enclosed in square brackets, and registered names which may be DNS names + * or even more complex names. This is different (and is much more loose) + * from what is commonly accepted as valid HTTP URLs for example. + * + * @param string $host + * @param integer $allowed bitmask of allowed host types + * @return boolean + */ + public static function validateHost($host, $allowed = self::HOST_ALL) + { + /* + * "first-match-wins" algorithm (RFC 3986): + * If host matches the rule for IPv4address, then it should be + * considered an IPv4 address literal and not a reg-name + */ + if ($allowed & self::HOST_IPVANY) { + if (static::isValidIpAddress($host, $allowed)) { + return true; + } + } + + if ($allowed & self::HOST_REGNAME) { + if (static::isValidRegName($host)) { + return true; + } + } + + if ($allowed & self::HOST_DNS) { + if (static::isValidDnsHostname($host)) { + return true; + } + } + + return false; + } + + /** + * Validate the port + * + * Valid values include numbers between 1 and 65535, and empty values + * + * @param integer $port + * @return boolean + */ + public static function validatePort($port) + { + if ($port === 0) { + return false; + } + + if ($port) { + $port = (int) $port; + if ($port < 1 || $port > 0xffff) { + return false; + } + } + + return true; + } + + /** + * Validate the path + * + * @param string $path + * @return boolean + */ + public static function validatePath($path) + { + $pchar = '(?:[' . self::CHAR_UNRESERVED . ':@&=\+\$,]+|%[A-Fa-f0-9]{2})*'; + $segment = $pchar . "(?:;{$pchar})*"; + $regex = "/^{$segment}(?:\/{$segment})*$/"; + return (boolean) preg_match($regex, $path); + } + + /** + * Check if a URI query or fragment part is valid or not + * + * Query and Fragment parts are both restricted by the same syntax rules, + * so the same validation method can be used for both. + * + * You can encode a query or fragment part to ensure it is valid by passing + * it through the encodeQueryFragment() method. + * + * @param string $input + * @return boolean + */ + public static function validateQueryFragment($input) + { + $regex = '/^(?:[' . self::CHAR_UNRESERVED . self::CHAR_SUB_DELIMS . ':@\/\?]+|%[A-Fa-f0-9]{2})*$/'; + return (boolean) preg_match($regex, $input); + } + + /** + * URL-encode the user info part of a URI + * + * @param string $userInfo + * @return string + * @throws Exception\InvalidArgumentException + */ + public static function encodeUserInfo($userInfo) + { + if (!is_string($userInfo)) { + throw new Exception\InvalidArgumentException(sprintf( + 'Expecting a string, got %s', + (is_object($userInfo) ? get_class($userInfo) : gettype($userInfo)) + )); + } + + $regex = '/(?:[^' . self::CHAR_UNRESERVED . self::CHAR_SUB_DELIMS . '%:]|%(?![A-Fa-f0-9]{2}))/'; + $escaper = static::getEscaper(); + $replace = function ($match) use ($escaper) { + return $escaper->escapeUrl($match[0]); + }; + + return preg_replace_callback($regex, $replace, $userInfo); + } + + /** + * Encode the path + * + * Will replace all characters which are not strictly allowed in the path + * part with percent-encoded representation + * + * @param string $path + * @throws Exception\InvalidArgumentException + * @return string + */ + public static function encodePath($path) + { + if (!is_string($path)) { + throw new Exception\InvalidArgumentException(sprintf( + 'Expecting a string, got %s', + (is_object($path) ? get_class($path) : gettype($path)) + )); + } + + $regex = '/(?:[^' . self::CHAR_UNRESERVED . ':@&=\+\$,\/;%]+|%(?![A-Fa-f0-9]{2}))/'; + $escaper = static::getEscaper(); + $replace = function ($match) use ($escaper) { + return $escaper->escapeUrl($match[0]); + }; + + return preg_replace_callback($regex, $replace, $path); + } + + /** + * URL-encode a query string or fragment based on RFC-3986 guidelines. + * + * Note that query and fragment encoding allows more unencoded characters + * than the usual rawurlencode() function would usually return - for example + * '/' and ':' are allowed as literals. + * + * @param string $input + * @return string + * @throws Exception\InvalidArgumentException + */ + public static function encodeQueryFragment($input) + { + if (!is_string($input)) { + throw new Exception\InvalidArgumentException(sprintf( + 'Expecting a string, got %s', + (is_object($input) ? get_class($input) : gettype($input)) + )); + } + + $regex = '/(?:[^' . self::CHAR_UNRESERVED . self::CHAR_SUB_DELIMS . '%:@\/\?]+|%(?![A-Fa-f0-9]{2}))/'; + $escaper = static::getEscaper(); + $replace = function ($match) use ($escaper) { + return $escaper->escapeUrl($match[0]); + }; + + return preg_replace_callback($regex, $replace, $input); + } + + /** + * Extract only the scheme part out of a URI string. + * + * This is used by the parse() method, but is useful as a standalone public + * method if one wants to test a URI string for it's scheme before doing + * anything with it. + * + * Will return the scheme if found, or NULL if no scheme found (URI may + * still be valid, but not full) + * + * @param string $uriString + * @throws Exception\InvalidArgumentException + * @return string|null + */ + public static function parseScheme($uriString) + { + if (! is_string($uriString)) { + throw new Exception\InvalidArgumentException(sprintf( + 'Expecting a string, got %s', + (is_object($uriString) ? get_class($uriString) : gettype($uriString)) + )); + } + + if (preg_match('/^([A-Za-z][A-Za-z0-9\.\+\-]*):/', $uriString, $match)) { + return $match[1]; + } + + return null; + } + + /** + * Remove any extra dot segments (/../, /./) from a path + * + * Algorithm is adapted from RFC-3986 section 5.2.4 + * (@link http://tools.ietf.org/html/rfc3986#section-5.2.4) + * + * @todo consider optimizing + * + * @param string $path + * @return string + */ + public static function removePathDotSegments($path) + { + $output = ''; + + while ($path) { + if ($path == '..' || $path == '.') { + break; + } + + switch (true) { + case ($path == '/.'): + $path = '/'; + break; + case ($path == '/..'): + $path = '/'; + $output = substr($output, 0, strrpos($output, '/', -1)); + break; + case (substr($path, 0, 4) == '/../'): + $path = '/' . substr($path, 4); + $output = substr($output, 0, strrpos($output, '/', -1)); + break; + case (substr($path, 0, 3) == '/./'): + $path = substr($path, 2); + break; + case (substr($path, 0, 2) == './'): + $path = substr($path, 2); + break; + case (substr($path, 0, 3) == '../'): + $path = substr($path, 3); + break; + default: + $slash = strpos($path, '/', 1); + if ($slash === false) { + $seg = $path; + } else { + $seg = substr($path, 0, $slash); + } + + $output .= $seg; + $path = substr($path, strlen($seg)); + break; + } + } + + return $output; + } + + /** + * Merge a base URI and a relative URI into a new URI object + * + * This convenience method wraps ::resolve() to allow users to quickly + * create new absolute URLs without the need to instantiate and clone + * URI objects. + * + * If objects are passed in, none of the passed objects will be modified. + * + * @param Uri|string $baseUri + * @param Uri|string $relativeUri + * @return Uri + */ + public static function merge($baseUri, $relativeUri) + { + $uri = new static($relativeUri); + return $uri->resolve($baseUri); + } + + /** + * Check if a host name is a valid IP address, depending on allowed IP address types + * + * @param string $host + * @param integer $allowed allowed address types + * @return boolean + */ + protected static function isValidIpAddress($host, $allowed) + { + $validatorParams = array( + 'allowipv4' => (bool) ($allowed & self::HOST_IPV4), + 'allowipv6' => false, + 'allowipvfuture' => false, + 'allowliteral' => false, + ); + + // Test only IPv4 + $validator = new Validator\Ip($validatorParams); + $return = $validator->isValid($host); + if ($return) { + return true; + } + + // IPv6 & IPvLiteral must be in literal format + $validatorParams = array( + 'allowipv4' => false, + 'allowipv6' => (bool) ($allowed & self::HOST_IPV6), + 'allowipvfuture' => (bool) ($allowed & self::HOST_IPVFUTURE), + 'allowliteral' => true, + ); + static $regex = '/^\[.*\]$/'; + $validator->setOptions($validatorParams); + return (preg_match($regex, $host) && $validator->isValid($host)); + } + + /** + * Check if an address is a valid DNS hostname + * + * @param string $host + * @return boolean + */ + protected static function isValidDnsHostname($host) + { + $validator = new Validator\Hostname(array( + 'allow' => Validator\Hostname::ALLOW_DNS | Validator\Hostname::ALLOW_LOCAL, + )); + + return $validator->isValid($host); + } + + /** + * Check if an address is a valid registered name (as defined by RFC-3986) address + * + * @param string $host + * @return boolean + */ + protected static function isValidRegName($host) + { + $regex = '/^(?:[' . self::CHAR_UNRESERVED . self::CHAR_SUB_DELIMS . ':@\/\?]+|%[A-Fa-f0-9]{2})+$/'; + return (bool) preg_match($regex, $host); + } + + /** + * Part normalization methods + * + * These are called by normalize() using static::_normalize*() so they may + * be extended or overridden by extending classes to implement additional + * scheme specific normalization rules + */ + + /** + * Normalize the scheme + * + * Usually this means simply converting the scheme to lower case + * + * @param string $scheme + * @return string + */ + protected static function normalizeScheme($scheme) + { + return strtolower($scheme); + } + + /** + * Normalize the host part + * + * By default this converts host names to lower case + * + * @param string $host + * @return string + */ + protected static function normalizeHost($host) + { + return strtolower($host); + } + + /** + * Normalize the port + * + * If the class defines a default port for the current scheme, and the + * current port is default, it will be unset. + * + * @param integer $port + * @param string $scheme + * @return integer|null + */ + protected static function normalizePort($port, $scheme = null) + { + if ($scheme + && isset(static::$defaultPorts[$scheme]) + && ($port == static::$defaultPorts[$scheme]) + ) { + return null; + } + + return $port; + } + + /** + * Normalize the path + * + * This involves removing redundant dot segments, decoding any over-encoded + * characters and encoding everything that needs to be encoded and is not + * + * @param string $path + * @return string + */ + protected static function normalizePath($path) + { + $path = self::encodePath( + self::decodeUrlEncodedChars( + self::removePathDotSegments($path), + '/[' . self::CHAR_UNRESERVED . ':@&=\+\$,\/;%]/' + ) + ); + + return $path; + } + + /** + * Normalize the query part + * + * This involves decoding everything that doesn't need to be encoded, and + * encoding everything else + * + * @param string $query + * @return string + */ + protected static function normalizeQuery($query) + { + $query = self::encodeQueryFragment( + self::decodeUrlEncodedChars( + $query, + '/[' . self::CHAR_UNRESERVED . self::CHAR_SUB_DELIMS . '%:@\/\?]/' + ) + ); + + return $query; + } + + /** + * Normalize the fragment part + * + * Currently this is exactly the same as normalizeQuery(). + * + * @param string $fragment + * @return string + */ + protected static function normalizeFragment($fragment) + { + return static::normalizeQuery($fragment); + } + + /** + * Decode all percent encoded characters which are allowed to be represented literally + * + * Will not decode any characters which are not listed in the 'allowed' list + * + * @param string $input + * @param string $allowed Pattern of allowed characters + * @return mixed + */ + protected static function decodeUrlEncodedChars($input, $allowed = '') + { + $decodeCb = function($match) use ($allowed) { + $char = rawurldecode($match[0]); + if (preg_match($allowed, $char)) { + return $char; + } + return strtoupper($match[0]); + }; + + return preg_replace_callback('/%[A-Fa-f0-9]{2}/', $decodeCb, $input); + } +} diff --git a/lib/Zend/Uri/UriFactory.php b/lib/Zend/Uri/UriFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..6871e3e15277fbb20b40bf0d3af5d69b3aaee7f9 --- /dev/null +++ b/lib/Zend/Uri/UriFactory.php @@ -0,0 +1,112 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Uri + */ + +namespace Zend\Uri; + +use Zend\Uri\Uri; + +/** + * URI Factory Class + * + * The URI factory can be used to generate URI objects from strings, using a + * different URI subclass depending on the input URI scheme. New scheme-specific + * classes can be registered using the registerScheme() method. + * + * Note that this class contains only static methods and should not be + * instantiated + * + * @category Zend + * @package Zend_Uri + */ +abstract class UriFactory +{ + /** + * Registered scheme-specific classes + * + * @var array + */ + protected static $schemeClasses = array( + 'http' => 'Zend\Uri\Http', + 'https' => 'Zend\Uri\Http', + 'mailto' => 'Zend\Uri\Mailto', + 'file' => 'Zend\Uri\File', + 'urn' => 'Zend\Uri\Uri', + 'tag' => 'Zend\Uri\Uri', + ); + + /** + * Register a scheme-specific class to be used + * + * @param string $scheme + * @param string $class + */ + public static function registerScheme($scheme, $class) + { + $scheme = strtolower($scheme); + static::$schemeClasses[$scheme] = $class; + } + + /** + * Unregister a scheme + * + * @param string $scheme + */ + public static function unregisterScheme($scheme) + { + $scheme = strtolower($scheme); + if (isset(static::$schemeClasses[$scheme])) { + unset(static::$schemeClasses[$scheme]); + } + } + + /** + * Create a URI from a string + * + * @param string $uriString + * @param string $defaultScheme + * @throws Exception\InvalidArgumentException + * @return \Zend\Uri\Uri + */ + public static function factory($uriString, $defaultScheme = null) + { + if (!is_string($uriString)) { + throw new Exception\InvalidArgumentException(sprintf( + 'Expecting a string, received "%s"', + (is_object($uriString) ? get_class($uriString) : gettype($uriString)) + )); + } + + $uri = new Uri($uriString); + $scheme = strtolower($uri->getScheme()); + if (!$scheme && $defaultScheme) { + $scheme = $defaultScheme; + } + + if ($scheme && ! isset(static::$schemeClasses[$scheme])) { + throw new Exception\InvalidArgumentException(sprintf( + 'no class registered for scheme "%s"', + $scheme + )); + } + if ($scheme && isset(static::$schemeClasses[$scheme])) { + $class = static::$schemeClasses[$scheme]; + $uri = new $class($uri); + if (! $uri instanceof UriInterface) { + throw new Exception\InvalidArgumentException(sprintf( + 'class "%s" registered for scheme "%s" does not implement Zend\Uri\UriInterface', + $class, + $scheme + )); + } + } + + return $uri; + } +} diff --git a/lib/Zend/Uri/UriInterface.php b/lib/Zend/Uri/UriInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..74130fb8de6cdc45f439ee7930601542dc519ed3 --- /dev/null +++ b/lib/Zend/Uri/UriInterface.php @@ -0,0 +1,250 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Uri + */ + +namespace Zend\Uri; + +/** + * Interface defining an URI + * + * @category Zend + * @package Zend_Uri + */ +interface UriInterface +{ + + /** + * Create a new URI object + * + * @param Uri|string|null $uri + * @throws Exception\InvalidArgumentException + */ + public function __construct($uri = null); + + /** + * Check if the URI is valid + * + * Note that a relative URI may still be valid + * + * @return boolean + */ + public function isValid(); + + /** + * Check if the URI is a valid relative URI + * + * @return boolean + */ + public function isValidRelative(); + + /** + * Check if the URI is an absolute or relative URI + * + * @return boolean + */ + public function isAbsolute(); + + /** + * Parse a URI string + * + * @param string $uri + * @return Uri + */ + public function parse($uri); + + /** + * Compose the URI into a string + * + * @return string + * @throws Exception\InvalidUriException + */ + public function toString(); + + /** + * Normalize the URI + * + * Normalizing a URI includes removing any redundant parent directory or + * current directory references from the path (e.g. foo/bar/../baz becomes + * foo/baz), normalizing the scheme case, decoding any over-encoded + * characters etc. + * + * Eventually, two normalized URLs pointing to the same resource should be + * equal even if they were originally represented by two different strings + * + * @return Uri + */ + public function normalize(); + + + + /** + * Convert the link to a relative link by substracting a base URI + * + * This is the opposite of resolving a relative link - i.e. creating a + * relative reference link from an original URI and a base URI. + * + * If the two URIs do not intersect (e.g. the original URI is not in any + * way related to the base URI) the URI will not be modified. + * + * @param Uri|string $baseUri + * @return Uri + */ + public function makeRelative($baseUri); + + /** + * Get the scheme part of the URI + * + * @return string|null + */ + public function getScheme(); + + /** + * Get the User-info (usually user:password) part + * + * @return string|null + */ + public function getUserInfo(); + + /** + * Get the URI host + * + * @return string|null + */ + public function getHost(); + + /** + * Get the URI port + * + * @return integer|null + */ + public function getPort(); + + /** + * Get the URI path + * + * @return string|null + */ + public function getPath(); + + /** + * Get the URI query + * + * @return string|null + */ + public function getQuery(); + + /** + * Return the query string as an associative array of key => value pairs + * + * This is an extension to RFC-3986 but is quite useful when working with + * most common URI types + * + * @return array + */ + public function getQueryAsArray(); + + /** + * Get the URI fragment + * + * @return string|null + */ + public function getFragment(); + + /** + * Set the URI scheme + * + * If the scheme is not valid according to the generic scheme syntax or + * is not acceptable by the specific URI class (e.g. 'http' or 'https' are + * the only acceptable schemes for the Zend\Uri\Http class) an exception + * will be thrown. + * + * You can check if a scheme is valid before setting it using the + * validateScheme() method. + * + * @param string $scheme + * @throws Exception\InvalidUriPartException + * @return Uri + */ + public function setScheme($scheme); + + /** + * Set the URI User-info part (usually user:password) + * + * @param string $userInfo + * @return Uri + * @throws Exception\InvalidUriPartException If the schema definition + * does not have this part + */ + public function setUserInfo($userInfo); + + /** + * Set the URI host + * + * Note that the generic syntax for URIs allows using host names which + * are not necessarily IPv4 addresses or valid DNS host names. For example, + * IPv6 addresses are allowed as well, and also an abstract "registered name" + * which may be any name composed of a valid set of characters, including, + * for example, tilda (~) and underscore (_) which are not allowed in DNS + * names. + * + * Subclasses of Uri may impose more strict validation of host names - for + * example the HTTP RFC clearly states that only IPv4 and valid DNS names + * are allowed in HTTP URIs. + * + * @param string $host + * @throws Exception\InvalidUriPartException + * @return Uri + */ + public function setHost($host); + + /** + * Set the port part of the URI + * + * @param integer $port + * @return Uri + */ + public function setPort($port); + + /** + * Set the path + * + * @param string $path + * @return Uri + */ + public function setPath($path); + + /** + * Set the query string + * + * If an array is provided, will encode this array of parameters into a + * query string. Array values will be represented in the query string using + * PHP's common square bracket notation. + * + * @param string|array $query + * @return Uri + */ + public function setQuery($query); + + /** + * Set the URI fragment part + * + * @param string $fragment + * @return Uri + * @throws Exception\InvalidUriPartException If the schema definition + * does not have this part + */ + public function setFragment($fragment); + + /** + * Magic method to convert the URI to a string + * + * @return string + */ + public function __toString(); +} diff --git a/lib/Zend/Uri/composer.json b/lib/Zend/Uri/composer.json new file mode 100644 index 0000000000000000000000000000000000000000..ae5e2cbcf3c6a15a1e28a64297bca2bd76ac2087 --- /dev/null +++ b/lib/Zend/Uri/composer.json @@ -0,0 +1,20 @@ +{ + "name": "zendframework/zend-uri", + "description": "a component that aids in manipulating and validating » Uniform Resource Identifiers (URIs)", + "license": "BSD-3-Clause", + "keywords": [ + "zf2", + "uri" + ], + "autoload": { + "psr-0": { + "Zend\\Uri": "" + } + }, + "target-dir": "Zend/Uri", + "require": { + "php": ">=5.3.3", + "zendframework/zend-escaper": "self.version", + "zendframework/zend-validator": "self.version" + } +} diff --git a/lib/Zend/Validator/AbstractValidator.php b/lib/Zend/Validator/AbstractValidator.php new file mode 100644 index 0000000000000000000000000000000000000000..ce4dee7fb329886c5d60df6a8cc7f1ef56e6819c --- /dev/null +++ b/lib/Zend/Validator/AbstractValidator.php @@ -0,0 +1,597 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator; + +use Traversable; +use Zend\I18n\Translator\Translator; +use Zend\I18n\Translator\TranslatorAwareInterface; +use Zend\Stdlib\ArrayUtils; +use Zend\Validator\Exception\InvalidArgumentException; + +/** + * @category Zend + * @package Zend_Validate + */ +abstract class AbstractValidator implements + TranslatorAwareInterface, + ValidatorInterface +{ + /** + * The value to be validated + * + * @var mixed + */ + protected $value; + + /** + * Default translation object for all validate objects + * @var Translator + */ + protected static $defaultTranslator; + + /** + * Default text domain to be used with translator + * @var string + */ + protected static $defaultTranslatorTextDomain = 'default'; + + /** + * Limits the maximum returned length of a error message + * + * @var Integer + */ + protected static $messageLength = -1; + + protected $abstractOptions = array( + 'messages' => array(), // Array of validation failure messages + 'messageTemplates' => array(), // Array of validation failure message templates + 'messageVariables' => array(), // Array of additional variables available for validation failure messages + 'translator' => null, // Translation object to used -> Zend\I18n\Translator\Translator + 'translatorTextDomain' => null, // Translation text domain + 'translatorEnabled' => true, // Is translation enabled? + 'valueObscured' => false, // Flag indicating whether or not value should be obfuscated + // in error messages + ); + + /** + * Abstract constructor for all validators + * A validator should accept following parameters: + * - nothing f.e. Validator() + * - one or multiple scalar values f.e. Validator($first, $second, $third) + * - an array f.e. Validator(array($first => 'first', $second => 'second', $third => 'third')) + * - an instance of Traversable f.e. Validator($config_instance) + * + * @param array|Traversable $options + */ + public function __construct($options = null) + { + // The abstract constructor allows no scalar values + if ($options instanceof Traversable) { + $options = ArrayUtils::iteratorToArray($options); + } + + if (isset($this->messageTemplates)) { + $this->abstractOptions['messageTemplates'] = $this->messageTemplates; + } + + if (isset($this->messageVariables)) { + $this->abstractOptions['messageVariables'] = $this->messageVariables; + } + + if (is_array($options)) { + $this->setOptions($options); + } + } + + /** + * Returns an option + * + * @param string $option Option to be returned + * @return mixed Returned option + * @throws Exception\InvalidArgumentException + */ + public function getOption($option) + { + if (array_key_exists($option, $this->abstractOptions)) { + return $this->abstractOptions[$option]; + } + + if (isset($this->options) && array_key_exists($option, $this->options)) { + return $this->options[$option]; + } + + throw new InvalidArgumentException("Invalid option '$option'"); + } + + /** + * Returns all available options + * + * @return array Array with all available options + */ + public function getOptions() + { + $result = $this->abstractOptions; + if (isset($this->options)) { + $result += $this->options; + } + return $result; + } + + /** + * Sets one or multiple options + * + * @param array|Traversable $options Options to set + * @throws Exception\InvalidArgumentException If $options is not an array or Traversable + * @return AbstractValidator Provides fluid interface + */ + public function setOptions($options = array()) + { + if (!is_array($options) && !$options instanceof Traversable) { + throw new Exception\InvalidArgumentException(__METHOD__ . ' expects an array or Traversable'); + } + + foreach ($options as $name => $option) { + $fname = 'set' . ucfirst($name); + $fname2 = 'is' . ucfirst($name); + if (($name != 'setOptions') && method_exists($this, $name)) { + $this->{$name}($option); + } elseif (($fname != 'setOptions') && method_exists($this, $fname)) { + $this->{$fname}($option); + } elseif (($fname2 != 'setOptions') && method_exists($this, $fname2)) { + $this->{$fname2}($option); + } elseif (isset($this->options)) { + $this->options[$name] = $option; + } else { + $this->abstractOptions[$name] = $options; + } + } + + return $this; + } + + /** + * Returns array of validation failure messages + * + * @return array + */ + public function getMessages() + { + return $this->abstractOptions['messages']; + } + + /** + * Invoke as command + * + * @param mixed $value + * @return boolean + */ + public function __invoke($value) + { + return $this->isValid($value); + } + + /** + * Returns an array of the names of variables that are used in constructing validation failure messages + * + * @return array + */ + public function getMessageVariables() + { + return array_keys($this->abstractOptions['messageVariables']); + } + + /** + * Returns the message templates from the validator + * + * @return array + */ + public function getMessageTemplates() + { + return $this->abstractOptions['messageTemplates']; + } + + /** + * Sets the validation failure message template for a particular key + * + * @param string $messageString + * @param string $messageKey OPTIONAL + * @return AbstractValidator Provides a fluent interface + * @throws Exception\InvalidArgumentException + */ + public function setMessage($messageString, $messageKey = null) + { + if ($messageKey === null) { + $keys = array_keys($this->abstractOptions['messageTemplates']); + foreach ($keys as $key) { + $this->setMessage($messageString, $key); + } + return $this; + } + + if (!isset($this->abstractOptions['messageTemplates'][$messageKey])) { + throw new InvalidArgumentException("No message template exists for key '$messageKey'"); + } + + $this->abstractOptions['messageTemplates'][$messageKey] = $messageString; + return $this; + } + + /** + * Sets validation failure message templates given as an array, where the array keys are the message keys, + * and the array values are the message template strings. + * + * @param array $messages + * @return AbstractValidator + */ + public function setMessages(array $messages) + { + foreach ($messages as $key => $message) { + $this->setMessage($message, $key); + } + return $this; + } + + /** + * Magic function returns the value of the requested property, if and only if it is the value or a + * message variable. + * + * @param string $property + * @return mixed + * @throws Exception\InvalidArgumentException + */ + public function __get($property) + { + if ($property == 'value') { + return $this->value; + } + + if (array_key_exists($property, $this->abstractOptions['messageVariables'])) { + $result = $this->abstractOptions['messageVariables'][$property]; + if (is_array($result)) { + $result = $this->{key($result)}[current($result)]; + } else { + $result = $this->{$result}; + } + return $result; + } + + if (isset($this->messageVariables) && array_key_exists($property, $this->messageVariables)) { + $result = $this->{$this->messageVariables[$property]}; + if (is_array($result)) { + $result = $this->{key($result)}[current($result)]; + } else { + $result = $this->{$result}; + } + return $result; + } + + throw new InvalidArgumentException("No property exists by the name '$property'"); + } + + /** + * Constructs and returns a validation failure message with the given message key and value. + * + * Returns null if and only if $messageKey does not correspond to an existing template. + * + * If a translator is available and a translation exists for $messageKey, + * the translation will be used. + * + * @param string $messageKey + * @param string|array|object $value + * @return string + */ + protected function createMessage($messageKey, $value) + { + if (!isset($this->abstractOptions['messageTemplates'][$messageKey])) { + return null; + } + + $message = $this->abstractOptions['messageTemplates'][$messageKey]; + + $message = $this->translateMessage($messageKey, $message); + + if (is_object($value) && + !in_array('__toString', get_class_methods($value)) + ) { + $value = get_class($value) . ' object'; + } elseif (is_array($value)) { + $value = '[' . implode(', ', $value) . ']'; + } else { + $value = (string) $value; + } + + if ($this->isValueObscured()) { + $value = str_repeat('*', strlen($value)); + } + + $message = str_replace('%value%', (string) $value, $message); + foreach ($this->abstractOptions['messageVariables'] as $ident => $property) { + if (is_array($property)) { + $value = $this->{key($property)}[current($property)]; + if (is_array($value)) { + $value = '[' . implode(', ', $value) . ']'; + } + } else { + $value = $this->$property; + } + $message = str_replace("%$ident%", (string) $value, $message); + } + + $length = self::getMessageLength(); + if (($length > -1) && (strlen($message) > $length)) { + $message = substr($message, 0, ($length - 3)) . '...'; + } + + return $message; + } + + /** + * @param string $messageKey + * @param string $value OPTIONAL + * @return void + */ + protected function error($messageKey, $value = null) + { + if ($messageKey === null) { + $keys = array_keys($this->abstractOptions['messageTemplates']); + $messageKey = current($keys); + } + + if ($value === null) { + $value = $this->value; + } + + $this->abstractOptions['messages'][$messageKey] = $this->createMessage($messageKey, $value); + } + + /** + * Returns the validation value + * + * @return mixed Value to be validated + */ + protected function getValue() + { + return $this->value; + } + + /** + * Sets the value to be validated and clears the messages and errors arrays + * + * @param mixed $value + * @return void + */ + protected function setValue($value) + { + $this->value = $value; + $this->abstractOptions['messages'] = array(); + } + + /** + * Set flag indicating whether or not value should be obfuscated in messages + * + * @param bool $flag + * @return AbstractValidator + */ + public function setValueObscured($flag) + { + $this->abstractOptions['valueObscured'] = (bool) $flag; + return $this; + } + + /** + * Retrieve flag indicating whether or not value should be obfuscated in + * messages + * + * @return bool + */ + public function isValueObscured() + { + return $this->abstractOptions['valueObscured']; + } + + /** + * Set translation object + * + * @param Translator|null $translator + * @param string $textDomain (optional) + * @return AbstractValidator + * @throws Exception\InvalidArgumentException + */ + public function setTranslator(Translator $translator = null, $textDomain = null) + { + $this->abstractOptions['translator'] = $translator; + if (null !== $textDomain) { + $this->setTranslatorTextDomain($textDomain); + } + return $this; + } + + /** + * Return translation object + * + * @return Translator|null + */ + public function getTranslator() + { + if (! $this->isTranslatorEnabled()) { + return null; + } + + if (null === $this->abstractOptions['translator']) { + $this->abstractOptions['translator'] = self::getDefaultTranslator(); + } + + return $this->abstractOptions['translator']; + } + + /** + * Does this validator have its own specific translator? + * + * @return bool + */ + public function hasTranslator() + { + return (bool) $this->abstractOptions['translator']; + } + + /** + * Set translation text domain + * + * @param string $textDomain + * @return AbstractValidator + */ + public function setTranslatorTextDomain($textDomain = 'default') + { + $this->abstractOptions['translatorTextDomain'] = $textDomain; + return $this; + } + + /** + * Return the translation text domain + * + * @return string + */ + public function getTranslatorTextDomain() + { + if (null === $this->abstractOptions['translatorTextDomain']) { + $this->abstractOptions['translatorTextDomain'] = + self::getDefaultTranslatorTextDomain(); + } + return $this->abstractOptions['translatorTextDomain']; + } + + /** + * Set default translation object for all validate objects + * + * @param Translator|null $translator + * @param string $textDomain (optional) + * @return void + * @throws Exception\InvalidArgumentException + */ + public static function setDefaultTranslator( + Translator $translator = null, $textDomain = null + ) + { + self::$defaultTranslator = $translator; + if (null !== $textDomain) { + self::setDefaultTranslatorTextDomain($textDomain); + } + } + + /** + * Get default translation object for all validate objects + * + * @return Translator|null + */ + public static function getDefaultTranslator() + { + return self::$defaultTranslator; + } + + /** + * Is there a default translation object set? + * + * @return boolean + */ + public static function hasDefaultTranslator() + { + return (bool) self::$defaultTranslator; + } + + /** + * Set default translation text domain for all validate objects + * + * @param string $textDomain + * @return void + */ + public static function setDefaultTranslatorTextDomain($textDomain = 'default') + { + self::$defaultTranslatorTextDomain = $textDomain; + } + + /** + * Get default translation text domain for all validate objects + * + * @return string + */ + public static function getDefaultTranslatorTextDomain() + { + return self::$defaultTranslatorTextDomain; + } + + /** + * Indicate whether or not translation should be enabled + * + * @param bool $flag + * @return AbstractValidator + */ + public function setTranslatorEnabled($flag = true) + { + $this->abstractOptions['translatorEnabled'] = (bool) $flag; + return $this; + } + + /** + * Is translation enabled? + * + * @return bool + */ + public function isTranslatorEnabled() + { + return $this->abstractOptions['translatorEnabled']; + } + + /** + * Returns the maximum allowed message length + * + * @return integer + */ + public static function getMessageLength() + { + return self::$messageLength; + } + + /** + * Sets the maximum allowed message length + * + * @param integer $length + */ + public static function setMessageLength($length = -1) + { + self::$messageLength = $length; + } + + /** + * Translate a validation message + * + * @param string $messageKey + * @param string $message + * @return string + */ + protected function translateMessage($messageKey, $message) + { + $translator = $this->getTranslator(); + if (!$translator) { + return $message; + } + + $translated = $translator->translate( + $messageKey, $this->getTranslatorTextDomain() + ); + if ($translated !== $messageKey) { + return $translated; + } + + return $translator->translate( + $message, $this->getTranslatorTextDomain() + ); + } +} diff --git a/lib/Zend/Validator/Barcode.php b/lib/Zend/Validator/Barcode.php new file mode 100644 index 0000000000000000000000000000000000000000..615d3405f4b7793b55c83b1f3813085ac0b1ed90 --- /dev/null +++ b/lib/Zend/Validator/Barcode.php @@ -0,0 +1,183 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator; + +use Traversable; + +/** + * @category Zend + * @package Zend_Validate + */ +class Barcode extends AbstractValidator +{ + const INVALID = 'barcodeInvalid'; + const FAILED = 'barcodeFailed'; + const INVALID_CHARS = 'barcodeInvalidChars'; + const INVALID_LENGTH = 'barcodeInvalidLength'; + + protected $messageTemplates = array( + self::FAILED => "The input failed checksum validation", + self::INVALID_CHARS => "The input contains invalid characters", + self::INVALID_LENGTH => "The input should have a length of %length% characters", + self::INVALID => "Invalid type given. String expected", + ); + + /** + * Additional variables available for validation failure messages + * + * @var array + */ + protected $messageVariables = array( + 'length' => array('options' => 'length'), + ); + + protected $options = array( + 'adapter' => null, // Barcode adapter Zend\Validator\Barcode\AbstractAdapter + 'options' => null, // Options for this adapter + 'length' => null, + 'useChecksum' => null, + ); + + /** + * Constructor for barcodes + * + * @param array|string $options Options to use + */ + public function __construct($options = null) + { + if (!is_array($options) && !($options instanceof Traversable)) { + $options = array('adapter' => $options); + } + + if (array_key_exists('options', $options)) { + $options['options'] = array('options' => $options['options']); + } + + parent::__construct($options); + } + + /** + * Returns the set adapter + * + * @return Barcode\AbstractAdapter + */ + public function getAdapter() + { + if (!($this->options['adapter'] instanceof Barcode\AdapterInterface)) { + $this->setAdapter('Ean13'); + } + + return $this->options['adapter']; + } + + /** + * Sets a new barcode adapter + * + * @param string|Barcode\AbstractAdapter $adapter Barcode adapter to use + * @param array $options Options for this adapter + * @return Barcode + * @throws Exception\InvalidArgumentException + */ + public function setAdapter($adapter, $options = null) + { + if (is_string($adapter)) { + $adapter = ucfirst(strtolower($adapter)); + $adapter = 'Zend\\Validator\\Barcode\\' . $adapter; + + if (!class_exists($adapter)) { + throw new Exception\InvalidArgumentException('Barcode adapter matching "' . $adapter . '" not found'); + } + + $this->options['adapter'] = new $adapter($options); + } + + if (!$this->options['adapter'] instanceof Barcode\AdapterInterface) { + throw new Exception\InvalidArgumentException( + "Adapter $adapter does not implement Zend\\Validate\\Barcode\\AdapterInterface" + ); + } + + return $this; + } + + /** + * Returns the checksum option + * + * @return string + */ + public function getChecksum() + { + return $this->getAdapter()->getChecksum(); + } + + /** + * Sets if checksum should be validated, if no value is given the actual setting is returned + * + * @param boolean $checksum + * @return boolean + */ + public function useChecksum($checksum = null) + { + return $this->getAdapter()->useChecksum($checksum); + } + + /** + * Defined by Zend\Validator\ValidatorInterface + * + * Returns true if and only if $value contains a valid barcode + * + * @param string $value + * @return boolean + */ + public function isValid($value) + { + if (!is_string($value)) { + $this->error(self::INVALID); + return false; + } + + $this->setValue($value); + $adapter = $this->getAdapter(); + $this->options['length'] = $adapter->getLength(); + $result = $adapter->hasValidLength($value); + if (!$result) { + if (is_array($this->options['length'])) { + $temp = $this->options['length']; + $this->options['length'] = ""; + foreach ($temp as $length) { + $this->options['length'] .= "/"; + $this->options['length'] .= $length; + } + + $this->options['length'] = substr($this->options['length'], 1); + } + + $this->error(self::INVALID_LENGTH); + return false; + } + + $result = $adapter->hasValidCharacters($value); + if (!$result) { + $this->error(self::INVALID_CHARS); + return false; + } + + if ($this->useChecksum(null)) { + $result = $adapter->hasValidChecksum($value); + if (!$result) { + $this->error(self::FAILED); + return false; + } + } + + return true; + } +} diff --git a/lib/Zend/Validator/Barcode/AbstractAdapter.php b/lib/Zend/Validator/Barcode/AbstractAdapter.php new file mode 100644 index 0000000000000000000000000000000000000000..860e5420241214af1b9f2efa5e723f7d34a22e78 --- /dev/null +++ b/lib/Zend/Validator/Barcode/AbstractAdapter.php @@ -0,0 +1,315 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Barcode; + +/** + * @category Zend + * @package Zend_Validate + */ +abstract class AbstractAdapter implements AdapterInterface +{ + /** + * Allowed options for this adapter + * @var array + */ + protected $options = array( + 'length' => null, // Allowed barcode lengths, integer, array, string + 'characters' => null, // Allowed barcode characters + 'checksum' => null, // Callback to checksum function + 'useChecksum' => true, // Is a checksum value included?, boolean + ); + + /** + * Checks the length of a barcode + * + * @param string $value The barcode to check for proper length + * @return boolean + */ + public function hasValidLength($value) + { + if (!is_string($value)) { + return false; + } + + $fixum = strlen($value); + $found = false; + $length = $this->getLength(); + if (is_array($length)) { + foreach ($length as $value) { + if ($fixum == $value) { + $found = true; + } + + if ($value == -1) { + $found = true; + } + } + } elseif ($fixum == $length) { + $found = true; + } elseif ($length == -1) { + $found = true; + } elseif ($length == 'even') { + $count = $fixum % 2; + $found = ($count == 0) ? true : false; + } elseif ($length == 'odd') { + $count = $fixum % 2; + $found = ($count == 1) ? true : false; + } + + return $found; + } + + /** + * Checks for allowed characters within the barcode + * + * @param string $value The barcode to check for allowed characters + * @return boolean + */ + public function hasValidCharacters($value) + { + if (!is_string($value)) { + return false; + } + + $characters = $this->getCharacters(); + if ($characters == 128) { + for ($x = 0; $x < 128; ++$x) { + $value = str_replace(chr($x), '', $value); + } + } else { + $chars = str_split($characters); + foreach ($chars as $char) { + $value = str_replace($char, '', $value); + } + } + + if (strlen($value) > 0) { + return false; + } + + return true; + } + + /** + * Validates the checksum + * + * @param string $value The barcode to check the checksum for + * @return boolean + */ + public function hasValidChecksum($value) + { + $checksum = $this->getChecksum(); + if (!empty($checksum)) { + if (method_exists($this, $checksum)) { + return $this->$checksum($value); + } + } + + return false; + } + + /** + * Returns the allowed barcode length + * + * @return int|array + */ + public function getLength() + { + return $this->options['length']; + } + + /** + * Returns the allowed characters + * + * @return integer|string|array + */ + public function getCharacters() + { + return $this->options['characters']; + } + + /** + * Returns the checksum function name + * + */ + public function getChecksum() + { + return $this->options['checksum']; + } + + /** + * Sets the checksum validation method + * + * @param callable $checksum Checksum method to call + * @return AbstractAdapter + */ + protected function setChecksum($checksum) + { + $this->options['checksum'] = $checksum; + return $this; + } + + /** + * Sets the checksum validation, if no value is given, the actual setting is returned + * + * @param boolean $check + * @return AbstractAdapter|boolean + */ + public function useChecksum($check = null) + { + if ($check === null) { + return $this->options['useChecksum']; + } + + $this->options['useChecksum'] = (boolean) $check; + return $this; + } + + /** + * Sets the length of this barcode + * + * @param int|array $length + * @return AbstractAdapter + */ + protected function setLength($length) + { + $this->options['length'] = $length; + return $this; + } + + /** + * Sets the allowed characters of this barcode + * + * @param integer $characters + * @return AbstractAdapter + */ + protected function setCharacters($characters) + { + $this->options['characters'] = $characters; + return $this; + } + + /** + * Validates the checksum (Modulo 10) + * GTIN implementation factor 3 + * + * @param string $value The barcode to validate + * @return boolean + */ + protected function gtin($value) + { + $barcode = substr($value, 0, -1); + $sum = 0; + $length = strlen($barcode) - 1; + + for ($i = 0; $i <= $length; $i++) { + if (($i % 2) === 0) { + $sum += $barcode[$length - $i] * 3; + } else { + $sum += $barcode[$length - $i]; + } + } + + $calc = $sum % 10; + $checksum = ($calc === 0) ? 0 : (10 - $calc); + if ($value[$length + 1] != $checksum) { + return false; + } + + return true; + } + + /** + * Validates the checksum (Modulo 10) + * IDENTCODE implementation factors 9 and 4 + * + * @param string $value The barcode to validate + * @return boolean + */ + protected function identcode($value) + { + $barcode = substr($value, 0, -1); + $sum = 0; + $length = strlen($value) - 2; + + for ($i = 0; $i <= $length; $i++) { + if (($i % 2) === 0) { + $sum += $barcode[$length - $i] * 4; + } else { + $sum += $barcode[$length - $i] * 9; + } + } + + $calc = $sum % 10; + $checksum = ($calc === 0) ? 0 : (10 - $calc); + if ($value[$length + 1] != $checksum) { + return false; + } + + return true; + } + + /** + * Validates the checksum (Modulo 10) + * CODE25 implementation factor 3 + * + * @param string $value The barcode to validate + * @return boolean + */ + protected function code25($value) + { + $barcode = substr($value, 0, -1); + $sum = 0; + $length = strlen($barcode) - 1; + + for ($i = 0; $i <= $length; $i++) { + if (($i % 2) === 0) { + $sum += $barcode[$i] * 3; + } else { + $sum += $barcode[$i]; + } + } + + $calc = $sum % 10; + $checksum = ($calc === 0) ? 0 : (10 - $calc); + if ($value[$length + 1] != $checksum) { + return false; + } + + return true; + } + + /** + * Validates the checksum () + * POSTNET implementation + * + * @param string $value The barcode to validate + * @return boolean + */ + protected function postnet($value) + { + $checksum = substr($value, -1, 1); + $values = str_split(substr($value, 0, -1)); + + $check = 0; + foreach ($values as $row) { + $check += $row; + } + + $check %= 10; + $check = 10 - $check; + if ($check == $checksum) { + return true; + } + + return false; + } +} diff --git a/lib/Zend/Validator/Barcode/AdapterInterface.php b/lib/Zend/Validator/Barcode/AdapterInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..a2667cd0642b33cc06edb0d7207ca39ba3c98fcc --- /dev/null +++ b/lib/Zend/Validator/Barcode/AdapterInterface.php @@ -0,0 +1,71 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Barcode; + +/** + * @category Zend + * @package Zend_Validate + */ +interface AdapterInterface +{ + /** + * Checks the length of a barcode + * + * @param string $value The barcode to check for proper length + * @return boolean + */ + public function hasValidLength($value); + + /** + * Checks for allowed characters within the barcode + * + * @param string $value The barcode to check for allowed characters + * @return boolean + */ + public function hasValidCharacters($value); + + /** + * Validates the checksum + * + * @param string $value The barcode to check the checksum for + * @return boolean + */ + public function hasValidChecksum($value); + + /** + * Returns the allowed barcode length + * + * @return int|array + */ + public function getLength(); + + /** + * Returns the allowed characters + * + * @return integer|string|array + */ + public function getCharacters(); + + /** + * Returns if barcode uses a checksum + * + * @return boolean + */ + public function getChecksum(); + + /** + * Sets the checksum validation, if no value is given, the actual setting is returned + * + * @param boolean $check + * @return AbstractAdapter|boolean + */ + public function useChecksum($check = null); +} diff --git a/lib/Zend/Validator/Barcode/Codabar.php b/lib/Zend/Validator/Barcode/Codabar.php new file mode 100644 index 0000000000000000000000000000000000000000..2c52064fdac6cafd2f2d38a06cf42ec9f22ca56f --- /dev/null +++ b/lib/Zend/Validator/Barcode/Codabar.php @@ -0,0 +1,71 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Barcode; + +/** + * @category Zend + * @package Zend_Validate + */ +class Codabar extends AbstractAdapter +{ + /** + * Constructor for this barcode adapter + */ + public function __construct() + { + $this->setLength(-1); + $this->setCharacters('0123456789-$:/.+ABCDTN*E'); + $this->useChecksum(false); + } + + /** + * Checks for allowed characters + * @see Zend\Validator\Barcode.AbstractAdapter::checkChars() + */ + public function hasValidCharacters($value) + { + if (strpbrk($value, 'ABCD')) { + $first = $value[0]; + if (!strpbrk($first, 'ABCD')) { + // Missing start char + return false; + } + + $last = substr($value, -1, 1); + if (!strpbrk($last, 'ABCD')) { + // Missing stop char + return false; + } + + $value = substr($value, 1, -1); + } elseif (strpbrk($value, 'TN*E')) { + $first = $value[0]; + if (!strpbrk($first, 'TN*E')) { + // Missing start char + return false; + } + + $last = substr($value, -1, 1); + if (!strpbrk($last, 'TN*E')) { + // Missing stop char + return false; + } + + $value = substr($value, 1, -1); + } + + $chars = $this->getCharacters(); + $this->setCharacters('0123456789-$:/.+'); + $result = parent::hasValidCharacters($value); + $this->setCharacters($chars); + return $result; + } +} diff --git a/lib/Zend/Validator/Barcode/Code128.php b/lib/Zend/Validator/Barcode/Code128.php new file mode 100644 index 0000000000000000000000000000000000000000..f97d0f33ec22949519a0ece72a83b7adab808bfb --- /dev/null +++ b/lib/Zend/Validator/Barcode/Code128.php @@ -0,0 +1,416 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Barcode; + +/** + * @category Zend + * @package Zend_Validate + */ +class Code128 extends AbstractAdapter +{ + /** + * Constructor for this barcode adapter + */ + public function __construct() + { + $this->setLength(-1); + $this->setCharacters(array( + 'A' => array( + 0 => ' ', 1 => '!', 2 => '"', 3 => '#', 4 => '$', 5 => '%', 6 => '&', 7 => "'", + 8 => '(', 9 => ')', 10 => '*', 11 => '+', 12 => ',', 13 => '-', 14 => '.', 15 => '/', + 16 => '0', 17 => '1', 18 => '2', 19 => '3', 20 => '4', 21 => '5', 22 => '6', 23 => '7', + 24 => '8', 25 => '9', 26 => ':', 27 => ';', 28 => '<', 29 => '=', 30 => '>', 31 => '?', + 32 => '@', 33 => 'A', 34 => 'B', 35 => 'C', 36 => 'D', 37 => 'E', 38 => 'F', 39 => 'G', + 40 => 'H', 41 => 'I', 42 => 'J', 43 => 'K', 44 => 'L', 45 => 'M', 46 => 'N', 47 => 'O', + 48 => 'P', 49 => 'Q', 50 => 'R', 51 => 'S', 52 => 'T', 53 => 'U', 54 => 'V', 55 => 'W', + 56 => 'X', 57 => 'Y', 58 => 'Z', 59 => '[', 60 => '\\',61 => ']', 62 => '^', 63 => '_', + 64 =>0x00, 65 =>0x01, 66 =>0x02, 67 =>0x03, 68 =>0x04, 69 =>0x05, 70 =>0x06, 71 =>0x07, + 72 =>0x08, 73 =>0x09, 74 =>0x0A, 75 =>0x0B, 76 =>0x0C, 77 =>0x0D, 78 =>0x0E, 79 =>0x0F, + 80 =>0x10, 81 =>0x11, 82 =>0x12, 83 =>0x13, 84 =>0x14, 85 =>0x15, 86 =>0x16, 87 =>0x17, + 88 =>0x18, 89 =>0x19, 90 =>0x1A, 91 =>0x1B, 92 =>0x1C, 93 =>0x1D, 94 =>0x1E, 95 =>0x1F, + 96 => 'Ç', 97 => 'ü', 98 => 'é', 99 => 'â',100 => 'ä',101 => 'à ',102 => 'Ã¥',103 => '‡', + 104 => 'ˆ',105 => '‰',106 => 'Å '), + 'B' => array( + 0 => ' ', 1 => '!', 2 => '"', 3 => '#', 4 => '$', 5 => '%', 6 => '&', 7 => "'", + 8 => '(', 9 => ')', 10 => '*', 11 => '+', 12 => ',', 13 => '-', 14 => '.', 15 => '/', + 16 => '0', 17 => '1', 18 => '2', 19 => '3', 20 => '4', 21 => '5', 22 => '6', 23 => '7', + 24 => '8', 25 => '9', 26 => ':', 27 => ';', 28 => '<', 29 => '=', 30 => '>', 31 => '?', + 32 => '@', 33 => 'A', 34 => 'B', 35 => 'C', 36 => 'D', 37 => 'E', 38 => 'F', 39 => 'G', + 40 => 'H', 41 => 'I', 42 => 'J', 43 => 'K', 44 => 'L', 45 => 'M', 46 => 'N', 47 => 'O', + 48 => 'P', 49 => 'Q', 50 => 'R', 51 => 'S', 52 => 'T', 53 => 'U', 54 => 'V', 55 => 'W', + 56 => 'X', 57 => 'Y', 58 => 'Z', 59 => '[', 60 => '\\',61 => ']', 62 => '^', 63 => '_', + 64 => '`', 65 => 'a', 66 => 'b', 67 => 'c', 68 => 'd', 69 => 'e', 70 => 'f', 71 => 'g', + 72 => 'h', 73 => 'i', 74 => 'j', 75 => 'k', 76 => 'l', 77 => 'm', 78 => 'n', 79 => 'o', + 80 => 'p', 81 => 'q', 82 => 'r', 83 => 's', 84 => 't', 85 => 'u', 86 => 'v', 87 => 'w', + 88 => 'x', 89 => 'y', 90 => 'z', 91 => '{', 92 => '|', 93 => '}', 94 => '~', 95 =>0x7F, + 96 => 'Ç', 97 => 'ü', 98 => 'é', 99 => 'â',100 => 'ä',101 => 'à ',102 => 'Ã¥',103 => '‡', + 104 => 'ˆ',105 => '‰',106 => 'Å '), + 'C' => array( + 0 => '00', 1 => '01', 2 => '02', 3 => '03', 4 => '04', 5 => '05', 6 => '06', 7 => '07', + 8 => '08', 9 => '09', 10 => '10', 11 => '11', 12 => '12', 13 => '13', 14 => '14', 15 => '15', + 16 => '16', 17 => '17', 18 => '18', 19 => '19', 20 => '20', 21 => '21', 22 => '22', 23 => '23', + 24 => '24', 25 => '25', 26 => '26', 27 => '27', 28 => '28', 29 => '29', 30 => '30', 31 => '31', + 32 => '32', 33 => '33', 34 => '34', 35 => '35', 36 => '36', 37 => '37', 38 => '38', 39 => '39', + 40 => '40', 41 => '41', 42 => '42', 43 => '43', 44 => '44', 45 => '45', 46 => '46', 47 => '47', + 48 => '48', 49 => '49', 50 => '50', 51 => '51', 52 => '52', 53 => '53', 54 => '54', 55 => '55', + 56 => '56', 57 => '57', 58 => '58', 59 => '59', 60 => '60', 61 => '61', 62 => '62', 63 => '63', + 64 => '64', 65 => '65', 66 => '66', 67 => '67', 68 => '68', 69 => '69', 70 => '70', 71 => '71', + 72 => '72', 73 => '73', 74 => '74', 75 => '75', 76 => '76', 77 => '77', 78 => '78', 79 => '79', + 80 => '80', 81 => '81', 82 => '82', 83 => '83', 84 => '84', 85 => '85', 86 => '86', 87 => '87', + 88 => '88', 89 => '89', 90 => '90', 91 => '91', 92 => '92', 93 => '93', 94 => '94', 95 => '95', + 96 => '96', 97 => '97', 98 => '98', 99 => '99',100 => 'ä', 101 => 'à ', 102 => 'Ã¥', 103 => '‡', + 104 => 'ˆ', 105 => '‰', 106 => 'Å '))); + $this->setChecksum('code128'); + + } + + /** + * Checks for allowed characters within the barcode + * + * @param string $value The barcode to check for allowed characters + * @return boolean + */ + public function hasValidCharacters($value) + { + if (!is_string($value)) { + return false; + } + + // detect starting charset + $set = $this->getCodingSet($value); + $read = $set; + if ($set != '') { + $value = iconv_substr($value, 1, iconv_strlen($value, 'UTF-8'), 'UTF-8'); + } + + // process barcode + while ($value != '') { + $char = iconv_substr($value, 0, 1, 'UTF-8'); + + switch ($char) { + // Function definition + case 'Ç' : + case 'ü' : + case 'Ã¥' : + break; + + // Switch 1 char between A and B + case 'é' : + if ($set == 'A') { + $read = 'B'; + } elseif ($set == 'B') { + $read = 'A'; + } + break; + + // Switch to C + case 'â' : + $set = 'C'; + $read = 'C'; + break; + + // Switch to B + case 'ä' : + $set = 'B'; + $read = 'B'; + break; + + // Switch to A + case 'à ' : + $set = 'A'; + $read = 'A'; + break; + + // Doubled start character + case '‡' : + case 'ˆ' : + case '‰' : + return false; + break; + + // Chars after the stop character + case 'Å ' : + break 2; + + default: + // Does the char exist within the charset to read? + if ($this->ord128($char, $read) == -1) { + return false; + } + + break; + } + + $value = iconv_substr($value, 1); + $read = $set; + } + + if (($value != '') && (iconv_strlen($value, 'UTF-8') != 1)) { + return false; + } + + return true; + } + + /** + * Validates the checksum () + * + * @param string $value The barcode to validate + * @return boolean + */ + protected function code128($value) + { + $sum = 0; + $pos = 1; + $set = $this->getCodingSet($value); + $read = $set; + $usecheck = $this->useChecksum(null); + $char = iconv_substr($value, 0, 1, 'UTF-8'); + if ($char == '‡') { + $sum = 103; + } elseif ($char == 'ˆ') { + $sum = 104; + } elseif ($char == '‰') { + $sum = 105; + } elseif ($usecheck == true) { + // no start value, unable to detect an proper checksum + return false; + } + + $value = iconv_substr($value, 1, iconv_strlen($value, 'UTF-8'), 'UTF-8'); + while (iconv_strpos($value, 'Å ') || ($value != '')) { + $char = iconv_substr($value, 0, 1, 'UTF-8'); + if ($read == 'C') { + $char = iconv_substr($value, 0, 2, 'UTF-8'); + } + + switch ($char) { + // Function definition + case 'Ç' : + case 'ü' : + case 'Ã¥' : + $sum += ($pos * $this->ord128($char, $set)); + break; + + case 'é' : + $sum += ($pos * $this->ord128($char, $set)); + if ($set == 'A') { + $read = 'B'; + } elseif ($set == 'B') { + $read = 'A'; + } + break; + + // Switch to C + case 'â' : + $sum += ($pos * $this->ord128($char, $set)); + $set = 'C'; + $read = 'C'; + break; + + // Switch to B + case 'ä' : + $sum += ($pos * $this->ord128($char, $set)); + $set = 'B'; + $read = 'B'; + break; + + // Switch to A + case 'à ' : + $sum += ($pos * $this->ord128($char, $set)); + $set = 'A'; + $read = 'A'; + break; + + case '‡' : + case 'ˆ' : + case '‰' : + return false; + break; + + default: + // Does the char exist within the charset to read? + if ($this->ord128($char, $read) == -1) { + return false; + } + + $sum += ($pos * $this->ord128($char, $set)); + break; + } + + $value = iconv_substr($value, 1, iconv_strlen($value, 'UTF-8'), 'UTF-8'); + ++$pos; + if ((iconv_strpos($value, 'Å ', 0, 'UTF-8') == 1) && (iconv_strlen($value, 'UTF-8') == 2)) { + // break by stop and checksum char + break; + } + $read = $set; + } + + if ((iconv_strpos($value, 'Å ', 0, 'UTF-8') != 1) || (iconv_strlen($value, 'UTF-8') != 2)) { + // return false if checksum is not readable and true if no startvalue is detected + return (!$usecheck); + } + + $mod = $sum % 103; + if (iconv_substr($value, 0, 1, 'UTF-8') == $this->chr128($mod, $set)) { + return true; + } + + return false; + } + + /** + * Returns the coding set for a barcode + * + * @param string $value Barcode + * @return string + */ + protected function getCodingSet($value) + { + $value = iconv_substr($value, 0, 1, 'UTF-8'); + switch ($value) { + case '‡' : + return 'A'; + break; + case 'ˆ' : + return 'B'; + break; + case '‰' : + return 'C'; + break; + } + + return ''; + } + + /** + * Internal method to return the code128 integer from an ascii value + * + * Table A + * ASCII CODE128 + * 32 to 95 == 0 to 63 + * 0 to 31 == 64 to 95 + * 128 to 138 == 96 to 106 + * + * Table B + * ASCII CODE128 + * 32 to 138 == 0 to 106 + * + * Table C + * ASCII CODE128 + * "00" to "99" == 0 to 99 + * 132 to 138 == 100 to 106 + * + * @param string $value + * @param string $set + * @return integer + */ + protected function ord128($value, $set) + { + $ord = ord($value); + if ($set == 'A') { + if ($ord < 32) { + return ($ord + 64); + } elseif ($ord < 96) { + return ($ord - 32); + } elseif ($ord > 138) { + return -1; + } else { + return ($ord - 32); + } + } elseif ($set == 'B') { + if ($ord < 32) { + return -1; + } elseif ($ord <= 138) { + return ($ord - 32); + } else { + return -1; + } + } elseif ($set == 'C') { + $val = (int) $value; + if (($val >= 0) && ($val <= 99)) { + return $val; + } elseif (($ord >= 132) && ($ord <= 138)) { + return ($ord - 32); + } else { + return -1; + } + } else { + if ($ord < 32) { + return ($ord +64); + } elseif ($ord <= 138) { + return ($ord - 32); + } else { + return -1; + } + } + } + + /** + * Internal Method to return the ascii value from an code128 integer + * + * Table A + * ASCII CODE128 + * 32 to 95 == 0 to 63 + * 0 to 31 == 64 to 95 + * 128 to 138 == 96 to 106 + * + * Table B + * ASCII CODE128 + * 32 to 138 == 0 to 106 + * + * Table C + * ASCII CODE128 + * "00" to "99" == 0 to 99 + * 132 to 138 == 100 to 106 + * + * @param integer $value + * @param string $set + * @return string + */ + protected function chr128($value, $set) + { + if ($set == 'A') { + if ($value < 64) { + return chr($value + 32); + } elseif ($value < 96) { + return chr($value - 64); + } elseif ($value > 106) { + return -1; + } else { + return chr($value + 32); + } + } elseif ($set == 'B') { + if ($value > 106) { + return -1; + } else { + return chr($value + 32); + } + } elseif ($set == 'C') { + if (($value >= 0) && ($value <= 9)) { + return "0" . (string) $value; + } elseif ($value <= 99) { + return (string) $value; + } elseif ($value <= 106) { + return chr($value + 32); + } else { + return -1; + } + } else { + if ($ord <= 106) { + return ($ord + 32); + } else { + return -1; + } + } + } +} diff --git a/lib/Zend/Validator/Barcode/Code25.php b/lib/Zend/Validator/Barcode/Code25.php new file mode 100644 index 0000000000000000000000000000000000000000..22abdef7ee6186000ec20ffb680e8450438f0c04 --- /dev/null +++ b/lib/Zend/Validator/Barcode/Code25.php @@ -0,0 +1,29 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Barcode; + +/** + * @category Zend + * @package Zend_Validate + */ +class Code25 extends AbstractAdapter +{ + /** + * Constructor for this barcode adapter + */ + public function __construct() + { + $this->setLength(-1); + $this->setCharacters('0123456789'); + $this->setChecksum('code25'); + $this->useChecksum(false); + } +} diff --git a/lib/Zend/Validator/Barcode/Code25interleaved.php b/lib/Zend/Validator/Barcode/Code25interleaved.php new file mode 100644 index 0000000000000000000000000000000000000000..585bff79dbb4dcc4c4e4ce0272a850eacfa2116b --- /dev/null +++ b/lib/Zend/Validator/Barcode/Code25interleaved.php @@ -0,0 +1,31 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Barcode; + +/** + * @category Zend + * @package Zend_Validate + */ +class Code25interleaved extends AbstractAdapter +{ + /** + * Constructor + * + * Sets check flag to false. + */ + public function __construct() + { + $this->setLength('even'); + $this->setCharacters('0123456789'); + $this->setChecksum('code25'); + $this->useChecksum(false); + } +} diff --git a/lib/Zend/Validator/Barcode/Code39.php b/lib/Zend/Validator/Barcode/Code39.php new file mode 100644 index 0000000000000000000000000000000000000000..fb88000b57ec6b63968d315064db38abf24606ca --- /dev/null +++ b/lib/Zend/Validator/Barcode/Code39.php @@ -0,0 +1,65 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Barcode; + +/** + * @category Zend + * @package Zend_Validate + */ +class Code39 extends AbstractAdapter +{ + /** + * @var array + */ + protected $check = array( + '0' => 0, '1' => 1, '2' => 2, '3' => 3, '4' => 4, '5' => 5, '6' => 6, + '7' => 7, '8' => 8, '9' => 9, 'A' => 10, 'B' => 11, 'C' => 12, 'D' => 13, + 'E' => 14, 'F' => 15, 'G' => 16, 'H' => 17, 'I' => 18, 'J' => 19, 'K' => 20, + 'L' => 21, 'M' => 22, 'N' => 23, 'O' => 24, 'P' => 25, 'Q' => 26, 'R' => 27, + 'S' => 28, 'T' => 29, 'U' => 30, 'V' => 31, 'W' => 32, 'X' => 33, 'Y' => 34, + 'Z' => 35, '-' => 36, '.' => 37, ' ' => 38, '$' => 39, '/' => 40, '+' => 41, + '%' => 42, + ); + + /** + * Constructor for this barcode adapter + */ + public function __construct() + { + $this->setLength(-1); + $this->setCharacters('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ -.$/+%'); + $this->setChecksum('code39'); + $this->useChecksum(false); + } + + /** + * Validates the checksum (Modulo 43) + * + * @param string $value The barcode to validate + * @return boolean + */ + protected function code39($value) + { + $checksum = substr($value, -1, 1); + $value = str_split(substr($value, 0, -1)); + $count = 0; + foreach ($value as $char) { + $count += $this->check[$char]; + } + + $mod = $count % 43; + if ($mod == $this->check[$checksum]) { + return true; + } + + return false; + } +} diff --git a/lib/Zend/Validator/Barcode/Code39ext.php b/lib/Zend/Validator/Barcode/Code39ext.php new file mode 100644 index 0000000000000000000000000000000000000000..b8b5fb3fc1205aa3f744dc33ad8a0047d61cf2f9 --- /dev/null +++ b/lib/Zend/Validator/Barcode/Code39ext.php @@ -0,0 +1,28 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Barcode; + +/** + * @category Zend + * @package Zend_Validate + */ +class Code39ext extends AbstractAdapter +{ + /** + * Constructor for this barcode adapter + */ + public function __construct() + { + $this->setLength(-1); + $this->setCharacters(128); + $this->useChecksum(false); + } +} diff --git a/lib/Zend/Validator/Barcode/Code93.php b/lib/Zend/Validator/Barcode/Code93.php new file mode 100644 index 0000000000000000000000000000000000000000..524ec049bd482e3b0bcd5cc4e6d0effe0d0a1f8d --- /dev/null +++ b/lib/Zend/Validator/Barcode/Code93.php @@ -0,0 +1,85 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Barcode; + +/** + * @category Zend + * @package Zend_Validate + */ +class Code93 extends AbstractAdapter +{ + /** + * Note that the characters !"§& are only synonyms + * @var array + */ + protected $check = array( + '0' => 0, '1' => 1, '2' => 2, '3' => 3, '4' => 4, '5' => 5, '6' => 6, + '7' => 7, '8' => 8, '9' => 9, 'A' => 10, 'B' => 11, 'C' => 12, 'D' => 13, + 'E' => 14, 'F' => 15, 'G' => 16, 'H' => 17, 'I' => 18, 'J' => 19, 'K' => 20, + 'L' => 21, 'M' => 22, 'N' => 23, 'O' => 24, 'P' => 25, 'Q' => 26, 'R' => 27, + 'S' => 28, 'T' => 29, 'U' => 30, 'V' => 31, 'W' => 32, 'X' => 33, 'Y' => 34, + 'Z' => 35, '-' => 36, '.' => 37, ' ' => 38, '$' => 39, '/' => 40, '+' => 41, + '%' => 42, '!' => 43, '"' => 44, '§' => 45, '&' => 46, + ); + + /** + * Constructor for this barcode adapter + */ + public function __construct() + { + $this->setLength(-1); + $this->setCharacters('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ -.$/+%'); + $this->setChecksum('code93'); + $this->useChecksum(false); + } + + /** + * Validates the checksum (Modulo CK) + * + * @param string $value The barcode to validate + * @return boolean + */ + protected function code93($value) + { + $checksum = substr($value, -2, 2); + $value = str_split(substr($value, 0, -2)); + $count = 0; + $length = count($value) % 20; + foreach ($value as $char) { + if ($length == 0) { + $length = 20; + } + + $count += $this->check[$char] * $length; + --$length; + } + + $check = array_search(($count % 47), $this->check); + $value[] = $check; + $count = 0; + $length = count($value) % 15; + foreach ($value as $char) { + if ($length == 0) { + $length = 15; + } + + $count += $this->check[$char] * $length; + --$length; + } + $check .= array_search(($count % 47), $this->check); + + if ($check == $checksum) { + return true; + } + + return false; + } +} diff --git a/lib/Zend/Validator/Barcode/Code93ext.php b/lib/Zend/Validator/Barcode/Code93ext.php new file mode 100644 index 0000000000000000000000000000000000000000..3b910d3887bcf1fad100bb08aac933e703720666 --- /dev/null +++ b/lib/Zend/Validator/Barcode/Code93ext.php @@ -0,0 +1,28 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Barcode; + +/** + * @category Zend + * @package Zend_Validate + */ +class Code93ext extends AbstractAdapter +{ + /** + * Constructor for this barcode adapter + */ + public function __construct() + { + $this->setLength(-1); + $this->setCharacters(128); + $this->useChecksum(false); + } +} diff --git a/lib/Zend/Validator/Barcode/Ean12.php b/lib/Zend/Validator/Barcode/Ean12.php new file mode 100644 index 0000000000000000000000000000000000000000..b90d291c81aaa6000732b2a2394ad8605d1776f8 --- /dev/null +++ b/lib/Zend/Validator/Barcode/Ean12.php @@ -0,0 +1,28 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Barcode; + +/** + * @category Zend + * @package Zend_Validate + */ +class Ean12 extends AbstractAdapter +{ + /** + * Constructor for this barcode adapter + */ + public function __construct() + { + $this->setLength(12); + $this->setCharacters('0123456789'); + $this->setChecksum('gtin'); + } +} diff --git a/lib/Zend/Validator/Barcode/Ean13.php b/lib/Zend/Validator/Barcode/Ean13.php new file mode 100644 index 0000000000000000000000000000000000000000..5a58ae419ff0e7958ad4395c4deacbbb4f5de2d7 --- /dev/null +++ b/lib/Zend/Validator/Barcode/Ean13.php @@ -0,0 +1,28 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Barcode; + +/** + * @category Zend + * @package Zend_Validate + */ +class Ean13 extends AbstractAdapter +{ + /** + * Constructor for this barcode adapter + */ + public function __construct() + { + $this->setLength(13); + $this->setCharacters('0123456789'); + $this->setChecksum('gtin'); + } +} diff --git a/lib/Zend/Validator/Barcode/Ean14.php b/lib/Zend/Validator/Barcode/Ean14.php new file mode 100644 index 0000000000000000000000000000000000000000..426c604c7908b60edd003ff7b622cc20dd53aef1 --- /dev/null +++ b/lib/Zend/Validator/Barcode/Ean14.php @@ -0,0 +1,28 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Barcode; + +/** + * @category Zend + * @package Zend_Validate + */ +class Ean14 extends AbstractAdapter +{ + /** + * Constructor for this barcode adapter + */ + public function __construct() + { + $this->setLength(14); + $this->setCharacters('0123456789'); + $this->setChecksum('gtin'); + } +} diff --git a/lib/Zend/Validator/Barcode/Ean18.php b/lib/Zend/Validator/Barcode/Ean18.php new file mode 100644 index 0000000000000000000000000000000000000000..0a1a8acd0883391284c4d0ca2d84df4686e509c0 --- /dev/null +++ b/lib/Zend/Validator/Barcode/Ean18.php @@ -0,0 +1,28 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Barcode; + +/** + * @category Zend + * @package Zend_Validate + */ +class Ean18 extends AbstractAdapter +{ + /** + * Constructor for this barcode adapter + */ + public function __construct() + { + $this->setLength(18); + $this->setCharacters('0123456789'); + $this->setChecksum('gtin'); + } +} diff --git a/lib/Zend/Validator/Barcode/Ean2.php b/lib/Zend/Validator/Barcode/Ean2.php new file mode 100644 index 0000000000000000000000000000000000000000..2dd48d0bc43840bec82bfa2f79972c495ac0bf48 --- /dev/null +++ b/lib/Zend/Validator/Barcode/Ean2.php @@ -0,0 +1,28 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Barcode; + +/** + * @category Zend + * @package Zend_Validate + */ +class Ean2 extends AbstractAdapter +{ + /** + * Constructor for this barcode adapter + */ + public function __construct() + { + $this->setLength(2); + $this->setCharacters('0123456789'); + $this->useChecksum(false); + } +} diff --git a/lib/Zend/Validator/Barcode/Ean5.php b/lib/Zend/Validator/Barcode/Ean5.php new file mode 100644 index 0000000000000000000000000000000000000000..ec327c41c9ab8207b41f2557f62b1beba5c17dfe --- /dev/null +++ b/lib/Zend/Validator/Barcode/Ean5.php @@ -0,0 +1,30 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Barcode; + +/** + * @category Zend + * @package Zend_Validate + */ +class Ean5 extends AbstractAdapter +{ + /** + * Constructor + * + * Sets check flag to false. + */ + public function __construct() + { + $this->setLength(5); + $this->setCharacters('0123456789'); + $this->useChecksum(false); + } +} diff --git a/lib/Zend/Validator/Barcode/Ean8.php b/lib/Zend/Validator/Barcode/Ean8.php new file mode 100644 index 0000000000000000000000000000000000000000..ea0a1453f8517577dd48beb9634be7a6f9d25ac0 --- /dev/null +++ b/lib/Zend/Validator/Barcode/Ean8.php @@ -0,0 +1,45 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Barcode; + +/** + * @category Zend + * @package Zend_Validate + */ +class Ean8 extends AbstractAdapter +{ + /** + * Constructor for this barcode adapter + */ + public function __construct() + { + $this->setLength(array(7, 8)); + $this->setCharacters('0123456789'); + $this->setChecksum('gtin'); + } + + /** + * Overrides parent checkLength + * + * @param string $value Value + * @return boolean + */ + public function hasValidLength($value) + { + if (strlen($value) == 7) { + $this->useChecksum(false); + } else { + $this->useChecksum(true); + } + + return parent::hasValidLength($value); + } +} diff --git a/lib/Zend/Validator/Barcode/Gtin12.php b/lib/Zend/Validator/Barcode/Gtin12.php new file mode 100644 index 0000000000000000000000000000000000000000..2490969bad88fcc7ab85e1bfa03b224359dbd23e --- /dev/null +++ b/lib/Zend/Validator/Barcode/Gtin12.php @@ -0,0 +1,28 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Barcode; + +/** + * @category Zend + * @package Zend_Validate + */ +class Gtin12 extends AbstractAdapter +{ + /** + * Constructor for this barcode adapter + */ + public function __construct() + { + $this->setLength(12); + $this->setCharacters('0123456789'); + $this->setChecksum('gtin'); + } +} diff --git a/lib/Zend/Validator/Barcode/Gtin13.php b/lib/Zend/Validator/Barcode/Gtin13.php new file mode 100644 index 0000000000000000000000000000000000000000..cdc233d205af48a2853588d121e10034bf1af451 --- /dev/null +++ b/lib/Zend/Validator/Barcode/Gtin13.php @@ -0,0 +1,28 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Barcode; + +/** + * @category Zend + * @package Zend_Validate + */ +class Gtin13 extends AbstractAdapter +{ + /** + * Constructor for this barcode adapter + */ + public function __construct() + { + $this->setLength(13); + $this->setCharacters('0123456789'); + $this->setChecksum('gtin'); + } +} diff --git a/lib/Zend/Validator/Barcode/Gtin14.php b/lib/Zend/Validator/Barcode/Gtin14.php new file mode 100644 index 0000000000000000000000000000000000000000..9dc9639d6725f575fffa29b099acf4c6afd36170 --- /dev/null +++ b/lib/Zend/Validator/Barcode/Gtin14.php @@ -0,0 +1,28 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Barcode; + +/** + * @category Zend + * @package Zend_Validate + */ +class Gtin14 extends AbstractAdapter +{ + /** + * Constructor for this barcode adapter + */ + public function __construct() + { + $this->setLength(14); + $this->setCharacters('0123456789'); + $this->setChecksum('gtin'); + } +} diff --git a/lib/Zend/Validator/Barcode/Identcode.php b/lib/Zend/Validator/Barcode/Identcode.php new file mode 100644 index 0000000000000000000000000000000000000000..60ff77fc4c8e5909c4046f430fd222802ccab0d5 --- /dev/null +++ b/lib/Zend/Validator/Barcode/Identcode.php @@ -0,0 +1,46 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Barcode; + +/** + * @category Zend + * @package Zend_Validate + */ +class Identcode extends AbstractAdapter +{ + /** + * Allowed barcode lengths + * @var integer + */ + protected $length = 12; + + /** + * Allowed barcode characters + * @var string + */ + protected $characters = '0123456789'; + + /** + * Checksum function + * @var string + */ + protected $checksum = 'identcode'; + + /** + * Constructor for this barcode adapter + */ + public function __construct() + { + $this->setLength(12); + $this->setCharacters('0123456789'); + $this->setChecksum('identcode'); + } +} diff --git a/lib/Zend/Validator/Barcode/Intelligentmail.php b/lib/Zend/Validator/Barcode/Intelligentmail.php new file mode 100644 index 0000000000000000000000000000000000000000..6dd31f001a75cff27ed714e556277ea06784b8e1 --- /dev/null +++ b/lib/Zend/Validator/Barcode/Intelligentmail.php @@ -0,0 +1,30 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Barcode; + +/** + * @category Zend + * @package Zend_Validate + */ +class Intelligentmail extends AbstractAdapter +{ + /** + * Constructor + * + * Sets check flag to false. + */ + public function __construct() + { + $this->setLength(array(20, 25, 29, 31)); + $this->setCharacters('0123456789'); + $this->useChecksum(false); + } +} diff --git a/lib/Zend/Validator/Barcode/Issn.php b/lib/Zend/Validator/Barcode/Issn.php new file mode 100644 index 0000000000000000000000000000000000000000..d2b0a531e15e1743363863a8d9297f70a7904c40 --- /dev/null +++ b/lib/Zend/Validator/Barcode/Issn.php @@ -0,0 +1,95 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Barcode; + +/** + * @category Zend + * @package Zend_Validate + */ +class Issn extends AbstractAdapter +{ + /** + * Constructor for this barcode adapter + */ + public function __construct() + { + $this->setLength(array(8, 13)); + $this->setCharacters('0123456789X'); + $this->setChecksum('gtin'); + } + + /** + * Allows X on length of 8 chars + * + * @param string $value The barcode to check for allowed characters + * @return boolean + */ + public function hasValidCharacters($value) + { + if (strlen($value) != 8) { + if (strpos($value, 'X') !== false) { + return false; + } + } + + return parent::hasValidCharacters($value); + } + + /** + * Validates the checksum + * + * @param string $value The barcode to check the checksum for + * @return boolean + */ + public function hasValidChecksum($value) + { + if (strlen($value) == 8) { + $this->setChecksum('issn'); + } else { + $this->setChecksum('gtin'); + } + + return parent::hasValidChecksum($value); + } + + /** + * Validates the checksum () + * ISSN implementation (reversed mod11) + * + * @param string $value The barcode to validate + * @return boolean + */ + protected function issn($value) + { + $checksum = substr($value, -1, 1); + $values = str_split(substr($value, 0, -1)); + $check = 0; + $multi = 8; + foreach ($values as $token) { + if ($token == 'X') { + $token = 10; + } + + $check += ($token * $multi); + --$multi; + } + + $check %= 11; + $check = ($check === 0 ? 0 : (11 - $check)); + if ($check == $checksum) { + return true; + } elseif (($check == 10) && ($checksum == 'X')) { + return true; + } + + return false; + } +} diff --git a/lib/Zend/Validator/Barcode/Itf14.php b/lib/Zend/Validator/Barcode/Itf14.php new file mode 100644 index 0000000000000000000000000000000000000000..51e6166e2a59889d35dc6c02f16606308c3cf454 --- /dev/null +++ b/lib/Zend/Validator/Barcode/Itf14.php @@ -0,0 +1,28 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Barcode; + +/** + * @category Zend + * @package Zend_Validate + */ +class Itf14 extends AbstractAdapter +{ + /** + * Constructor for this barcode adapter + */ + public function __construct() + { + $this->setLength(14); + $this->setCharacters('0123456789'); + $this->setChecksum('gtin'); + } +} diff --git a/lib/Zend/Validator/Barcode/Leitcode.php b/lib/Zend/Validator/Barcode/Leitcode.php new file mode 100644 index 0000000000000000000000000000000000000000..6a069b0c37a643a8b92178dbfb05dbcca98227ab --- /dev/null +++ b/lib/Zend/Validator/Barcode/Leitcode.php @@ -0,0 +1,28 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Barcode; + +/** + * @category Zend + * @package Zend_Validate + */ +class Leitcode extends AbstractAdapter +{ + /** + * Constructor for this barcode adapter + */ + public function __construct() + { + $this->setLength(14); + $this->setCharacters('0123456789'); + $this->setChecksum('identcode'); + } +} diff --git a/lib/Zend/Validator/Barcode/Planet.php b/lib/Zend/Validator/Barcode/Planet.php new file mode 100644 index 0000000000000000000000000000000000000000..71eb79c492f73b88b27c8cbd87ecee974c754098 --- /dev/null +++ b/lib/Zend/Validator/Barcode/Planet.php @@ -0,0 +1,28 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Barcode; + +/** + * @category Zend + * @package Zend_Validate + */ +class Planet extends AbstractAdapter +{ + /** + * Constructor for this barcode adapter + */ + public function __construct() + { + $this->setLength(array(12, 14)); + $this->setCharacters('0123456789'); + $this->setChecksum('postnet'); + } +} diff --git a/lib/Zend/Validator/Barcode/Postnet.php b/lib/Zend/Validator/Barcode/Postnet.php new file mode 100644 index 0000000000000000000000000000000000000000..a9a97d5cfd9ba0b43f6007f5f53c63c992d79111 --- /dev/null +++ b/lib/Zend/Validator/Barcode/Postnet.php @@ -0,0 +1,28 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Barcode; + +/** + * @category Zend + * @package Zend_Validate + */ +class Postnet extends AbstractAdapter +{ + /** + * Constructor for this barcode adapter + */ + public function __construct() + { + $this->setLength(array(6, 7, 10, 12)); + $this->setCharacters('0123456789'); + $this->setChecksum('postnet'); + } +} diff --git a/lib/Zend/Validator/Barcode/Royalmail.php b/lib/Zend/Validator/Barcode/Royalmail.php new file mode 100644 index 0000000000000000000000000000000000000000..78beea2d6c8a4c5821298eda38a63509af119789 --- /dev/null +++ b/lib/Zend/Validator/Barcode/Royalmail.php @@ -0,0 +1,98 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Barcode; + +/** + * @category Zend + * @package Zend_Validate + */ +class Royalmail extends AbstractAdapter +{ + protected $rows = array( + '0' => 1, '1' => 1, '2' => 1, '3' => 1, '4' => 1, '5' => 1, + '6' => 2, '7' => 2, '8' => 2, '9' => 2, 'A' => 2, 'B' => 2, + 'C' => 3, 'D' => 3, 'E' => 3, 'F' => 3, 'G' => 3, 'H' => 3, + 'I' => 4, 'J' => 4, 'K' => 4, 'L' => 4, 'M' => 4, 'N' => 4, + 'O' => 5, 'P' => 5, 'Q' => 5, 'R' => 5, 'S' => 5, 'T' => 5, + 'U' => 0, 'V' => 0, 'W' => 0, 'X' => 0, 'Y' => 0, 'Z' => 0, + ); + + protected $columns = array( + '0' => 1, '1' => 2, '2' => 3, '3' => 4, '4' => 5, '5' => 0, + '6' => 1, '7' => 2, '8' => 3, '9' => 4, 'A' => 5, 'B' => 0, + 'C' => 1, 'D' => 2, 'E' => 3, 'F' => 4, 'G' => 5, 'H' => 0, + 'I' => 1, 'J' => 2, 'K' => 3, 'L' => 4, 'M' => 5, 'N' => 0, + 'O' => 1, 'P' => 2, 'Q' => 3, 'R' => 4, 'S' => 5, 'T' => 0, + 'U' => 1, 'V' => 2, 'W' => 3, 'X' => 4, 'Y' => 5, 'Z' => 0, + ); + + /** + * Constructor for this barcode adapter + */ + public function __construct() + { + $this->setLength(-1); + $this->setCharacters('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'); + $this->setChecksum('royalmail'); + } + + /** + * Validates the checksum () + * + * @param string $value The barcode to validate + * @return boolean + */ + protected function royalmail($value) + { + $checksum = substr($value, -1, 1); + $values = str_split(substr($value, 0, -1)); + $rowvalue = 0; + $colvalue = 0; + foreach ($values as $row) { + $rowvalue += $this->rows[$row]; + $colvalue += $this->columns[$row]; + } + + $rowvalue %= 6; + $colvalue %= 6; + + $rowchkvalue = array_keys($this->rows, $rowvalue); + $colchkvalue = array_keys($this->columns, $colvalue); + $intersect = array_intersect($rowchkvalue, $colchkvalue); + $chkvalue = current($intersect); + if ($chkvalue == $checksum) { + return true; + } + + return false; + } + + /** + * Allows start and stop tag within checked chars + * + * @param string $value The barcode to check for allowed characters + * @return boolean + */ + public function hasValidCharacters($value) + { + if ($value[0] == '(') { + $value = substr($value, 1); + + if ($value[strlen($value) - 1] == ')') { + $value = substr($value, 0, -1); + } else { + return false; + } + } + + return parent::hasValidCharacters($value); + } +} diff --git a/lib/Zend/Validator/Barcode/Sscc.php b/lib/Zend/Validator/Barcode/Sscc.php new file mode 100644 index 0000000000000000000000000000000000000000..1234034394673ada075856aab37c07b38b2ed14c --- /dev/null +++ b/lib/Zend/Validator/Barcode/Sscc.php @@ -0,0 +1,28 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Barcode; + +/** + * @category Zend + * @package Zend_Validate + */ +class Sscc extends AbstractAdapter +{ + /** + * Constructor for this barcode adapter + */ + public function __construct() + { + $this->setLength(18); + $this->setCharacters('0123456789'); + $this->setChecksum('gtin'); + } +} diff --git a/lib/Zend/Validator/Barcode/Upca.php b/lib/Zend/Validator/Barcode/Upca.php new file mode 100644 index 0000000000000000000000000000000000000000..72edb4416212ac38643df8a029d793f5074ec2ff --- /dev/null +++ b/lib/Zend/Validator/Barcode/Upca.php @@ -0,0 +1,28 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Barcode; + +/** + * @category Zend + * @package Zend_Validate + */ +class Upca extends AbstractAdapter +{ + /** + * Constructor for this barcode adapter + */ + public function __construct() + { + $this->setLength(12); + $this->setCharacters('0123456789'); + $this->setChecksum('gtin'); + } +} diff --git a/lib/Zend/Validator/Barcode/Upce.php b/lib/Zend/Validator/Barcode/Upce.php new file mode 100644 index 0000000000000000000000000000000000000000..f69dfc2ec3bb4220bfec48adcd0421102951f999 --- /dev/null +++ b/lib/Zend/Validator/Barcode/Upce.php @@ -0,0 +1,45 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Barcode; + +/** + * @category Zend + * @package Zend_Validate + */ +class Upce extends AbstractAdapter +{ + /** + * Constructor for this barcode adapter + */ + public function __construct() + { + $this->setLength(array(6, 7, 8)); + $this->setCharacters('0123456789'); + $this->setChecksum('gtin'); + } + + /** + * Overrides parent checkLength + * + * @param string $value Value + * @return boolean + */ + public function hasValidLength($value) + { + if (strlen($value) != 8) { + $this->useChecksum(false); + } else { + $this->useChecksum(true); + } + + return parent::hasValidLength($value); + } +} diff --git a/lib/Zend/Validator/Between.php b/lib/Zend/Validator/Between.php new file mode 100644 index 0000000000000000000000000000000000000000..9e2c3e78f4595b0181177eda43198c8e19098174 --- /dev/null +++ b/lib/Zend/Validator/Between.php @@ -0,0 +1,182 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator; + +use Traversable; +use Zend\Stdlib\ArrayUtils; + +/** + * @category Zend + * @package Zend_Validate + */ +class Between extends AbstractValidator +{ + const NOT_BETWEEN = 'notBetween'; + const NOT_BETWEEN_STRICT = 'notBetweenStrict'; + + /** + * Validation failure message template definitions + * + * @var array + */ + protected $messageTemplates = array( + self::NOT_BETWEEN => "The input is not between '%min%' and '%max%', inclusively", + self::NOT_BETWEEN_STRICT => "The input is not strictly between '%min%' and '%max%'" + ); + + /** + * Additional variables available for validation failure messages + * + * @var array + */ + protected $messageVariables = array( + 'min' => array('options' => 'min'), + 'max' => array('options' => 'max'), + ); + + /** + * Options for the between validator + * + * @var array + */ + protected $options = array( + 'inclusive' => true, // Whether to do inclusive comparisons, allowing equivalence to min and/or max + 'min' => 0, + 'max' => PHP_INT_MAX, + ); + + /** + * Sets validator options + * Accepts the following option keys: + * 'min' => scalar, minimum border + * 'max' => scalar, maximum border + * 'inclusive' => boolean, inclusive border values + * + * @param array|Traversable $options + */ + public function __construct($options = null) + { + if ($options instanceof Traversable) { + $options = ArrayUtils::iteratorToArray($options); + } + if (!is_array($options)) { + $options = func_get_args(); + $temp['min'] = array_shift($options); + if (!empty($options)) { + $temp['max'] = array_shift($options); + } + + if (!empty($options)) { + $temp['inclusive'] = array_shift($options); + } + + $options = $temp; + } + + if (!array_key_exists('min', $options) || !array_key_exists('max', $options)) { +// throw new Exception\InvalidArgumentException("Missing option. 'min' and 'max' has to be given"); + } + + parent::__construct($options); + } + + /** + * Returns the min option + * + * @return mixed + */ + public function getMin() + { + return $this->options['min']; + } + + /** + * Sets the min option + * + * @param mixed $min + * @return Between Provides a fluent interface + */ + public function setMin($min) + { + $this->options['min'] = $min; + return $this; + } + + /** + * Returns the max option + * + * @return mixed + */ + public function getMax() + { + return $this->options['max']; + } + + /** + * Sets the max option + * + * @param mixed $max + * @return Between Provides a fluent interface + */ + public function setMax($max) + { + $this->options['max'] = $max; + return $this; + } + + /** + * Returns the inclusive option + * + * @return boolean + */ + public function getInclusive() + { + return $this->options['inclusive']; + } + + /** + * Sets the inclusive option + * + * @param boolean $inclusive + * @return Between Provides a fluent interface + */ + public function setInclusive($inclusive) + { + $this->options['inclusive'] = $inclusive; + return $this; + } + + /** + * Returns true if and only if $value is between min and max options, inclusively + * if inclusive option is true. + * + * @param mixed $value + * @return boolean + */ + public function isValid($value) + { + $this->setValue($value); + + if ($this->getInclusive()) { + if ($this->getMin() > $value || $value > $this->getMax()) { + $this->error(self::NOT_BETWEEN); + return false; + } + } else { + if ($this->getMin() >= $value || $value >= $this->getMax()) { + $this->error(self::NOT_BETWEEN_STRICT); + return false; + } + } + + return true; + } +} diff --git a/lib/Zend/Validator/Callback.php b/lib/Zend/Validator/Callback.php new file mode 100644 index 0000000000000000000000000000000000000000..d1dd91cb252567a711f74703b79c2c40fe194020 --- /dev/null +++ b/lib/Zend/Validator/Callback.php @@ -0,0 +1,155 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator; + +/** + * @category Zend + * @package Zend_Validate + */ +class Callback extends AbstractValidator +{ + /** + * Invalid callback + */ + const INVALID_CALLBACK = 'callbackInvalid'; + + /** + * Invalid value + */ + const INVALID_VALUE = 'callbackValue'; + + /** + * Validation failure message template definitions + * + * @var array + */ + protected $messageTemplates = array( + self::INVALID_VALUE => "The input is not valid", + self::INVALID_CALLBACK => "An exception has been raised within the callback", + ); + + /** + * Default options to set for the validator + * + * @var mixed + */ + protected $options = array( + 'callback' => null, // Callback in a call_user_func format, string || array + 'callbackOptions' => array(), // Options for the callback + ); + + /** + * Constructor + * + * @param array|callable $options + */ + public function __construct($options = null) + { + if (is_callable($options)) { + $options = array('callback' => $options); + } + + parent::__construct($options); + } + + /** + * Returns the set callback + * + * @return mixed + */ + public function getCallback() + { + return $this->options['callback']; + } + + /** + * Sets the callback + * + * @param string|array|callable $callback + * @return Callback Provides a fluent interface + * @throws Exception\InvalidArgumentException + */ + public function setCallback($callback) + { + if (!is_callable($callback)) { + throw new Exception\InvalidArgumentException('Invalid callback given'); + } + + $this->options['callback'] = $callback; + return $this; + } + + /** + * Returns the set options for the callback + * + * @return mixed + */ + public function getCallbackOptions() + { + return $this->options['callbackOptions']; + } + + /** + * Sets options for the callback + * + * @param mixed $options + * @return Callback Provides a fluent interface + */ + public function setCallbackOptions($options) + { + $this->options['callbackOptions'] = (array) $options; + return $this; + } + + /** + * Returns true if and only if the set callback returns + * for the provided $value + * + * @param mixed $value + * @param mixed $context Additional context to provide to the callback + * @return boolean + * @throws Exception\InvalidArgumentException + */ + public function isValid($value, $context = null) + { + $this->setValue($value); + + $options = $this->getCallbackOptions(); + $callback = $this->getCallback(); + if (empty($callback)) { + throw new Exception\InvalidArgumentException('No callback given'); + } + + $args = array($value); + if (empty($options) && !empty($context)) { + $args[] = $context; + } + if (!empty($options) && empty($context)) { + $args = array_merge($args, $options); + } + if (!empty($options) && !empty($context)) { + $args[] = $context; + $args = array_merge($args, $options); + } + + try { + if (!call_user_func_array($callback, $args)) { + $this->error(self::INVALID_VALUE); + return false; + } + } catch (\Exception $e) { + $this->error(self::INVALID_CALLBACK); + return false; + } + + return true; + } +} diff --git a/lib/Zend/Validator/CreditCard.php b/lib/Zend/Validator/CreditCard.php new file mode 100644 index 0000000000000000000000000000000000000000..406a3b445e4712e4692d73772afed95e2e164cbd --- /dev/null +++ b/lib/Zend/Validator/CreditCard.php @@ -0,0 +1,323 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator; + +use Traversable; +use Zend\Stdlib\ArrayUtils; + +/** + * @category Zend + * @package Zend_Validate + */ +class CreditCard extends AbstractValidator +{ + /** + * Detected CCI list + * + * @var string + */ + const ALL = 'All'; + const AMERICAN_EXPRESS = 'American_Express'; + const UNIONPAY = 'Unionpay'; + const DINERS_CLUB = 'Diners_Club'; + const DINERS_CLUB_US = 'Diners_Club_US'; + const DISCOVER = 'Discover'; + const JCB = 'JCB'; + const LASER = 'Laser'; + const MAESTRO = 'Maestro'; + const MASTERCARD = 'Mastercard'; + const SOLO = 'Solo'; + const VISA = 'Visa'; + + const CHECKSUM = 'creditcardChecksum'; + const CONTENT = 'creditcardContent'; + const INVALID = 'creditcardInvalid'; + const LENGTH = 'creditcardLength'; + const PREFIX = 'creditcardPrefix'; + const SERVICE = 'creditcardService'; + const SERVICEFAILURE = 'creditcardServiceFailure'; + + /** + * Validation failure message template definitions + * + * @var array + */ + protected $messageTemplates = array( + self::CHECKSUM => "The input seems to contain an invalid checksum", + self::CONTENT => "The input must contain only digits", + self::INVALID => "Invalid type given. String expected", + self::LENGTH => "The input contains an invalid amount of digits", + self::PREFIX => "The input is not from an allowed institute", + self::SERVICE => "The input seems to be an invalid creditcard number", + self::SERVICEFAILURE => "An exception has been raised while validating the input", + ); + + /** + * List of CCV names + * + * @var array + */ + protected $cardName = array( + 0 => self::AMERICAN_EXPRESS, + 1 => self::DINERS_CLUB, + 2 => self::DINERS_CLUB_US, + 3 => self::DISCOVER, + 4 => self::JCB, + 5 => self::LASER, + 6 => self::MAESTRO, + 7 => self::MASTERCARD, + 8 => self::SOLO, + 9 => self::UNIONPAY, + 10 => self::VISA, + ); + + /** + * List of allowed CCV lengths + * + * @var array + */ + protected $cardLength = array( + self::AMERICAN_EXPRESS => array(15), + self::DINERS_CLUB => array(14), + self::DINERS_CLUB_US => array(16), + self::DISCOVER => array(16), + self::JCB => array(16), + self::LASER => array(16, 17, 18, 19), + self::MAESTRO => array(12, 13, 14, 15, 16, 17, 18, 19), + self::MASTERCARD => array(16), + self::SOLO => array(16, 18, 19), + self::UNIONPAY => array(16, 17, 18, 19), + self::VISA => array(16), + ); + + /** + * List of accepted CCV provider tags + * + * @var array + */ + protected $cardType = array( + self::AMERICAN_EXPRESS => array('34', '37'), + self::DINERS_CLUB => array('300', '301', '302', '303', '304', '305', '36'), + self::DINERS_CLUB_US => array('54', '55'), + self::DISCOVER => array('6011', '622126', '622127', '622128', '622129', '62213', + '62214', '62215', '62216', '62217', '62218', '62219', + '6222', '6223', '6224', '6225', '6226', '6227', '6228', + '62290', '62291', '622920', '622921', '622922', '622923', + '622924', '622925', '644', '645', '646', '647', '648', + '649', '65'), + self::JCB => array('3528', '3529', '353', '354', '355', '356', '357', '358'), + self::LASER => array('6304', '6706', '6771', '6709'), + self::MAESTRO => array('5018', '5020', '5038', '6304', '6759', '6761', '6763'), + self::MASTERCARD => array('51', '52', '53', '54', '55'), + self::SOLO => array('6334', '6767'), + self::UNIONPAY => array('622126', '622127', '622128', '622129', '62213', '62214', + '62215', '62216', '62217', '62218', '62219', '6222', '6223', + '6224', '6225', '6226', '6227', '6228', '62290', '62291', + '622920', '622921', '622922', '622923', '622924', '622925'), + self::VISA => array('4'), + ); + + /** + * Options for this validator + * + * @var array + */ + protected $options = array( + 'service' => null, // Service callback for additional validation + 'type' => array(), // CCIs which are accepted by validation + ); + + /** + * Constructor + * + * @param string|array|Traversable $options OPTIONAL Type of CCI to allow + */ + public function __construct($options = array()) + { + if ($options instanceof Traversable) { + $options = ArrayUtils::iteratorToArray($options); + } elseif (!is_array($options)) { + $options = func_get_args(); + $temp['type'] = array_shift($options); + if (!empty($options)) { + $temp['service'] = array_shift($options); + } + + $options = $temp; + } + + if (!array_key_exists('type', $options)) { + $options['type'] = self::ALL; + } + + $this->setType($options['type']); + unset($options['type']); + + if (array_key_exists('service', $options)) { + $this->setService($options['service']); + unset($options['service']); + } + + parent::__construct($options); + } + + /** + * Returns a list of accepted CCIs + * + * @return array + */ + public function getType() + { + return $this->options['type']; + } + + /** + * Sets CCIs which are accepted by validation + * + * @param string|array $type Type to allow for validation + * @return CreditCard Provides a fluid interface + */ + public function setType($type) + { + $this->options['type'] = array(); + return $this->addType($type); + } + + /** + * Adds a CCI to be accepted by validation + * + * @param string|array $type Type to allow for validation + * @return CreditCard Provides a fluid interface + */ + public function addType($type) + { + if (is_string($type)) { + $type = array($type); + } + + foreach ($type as $typ) { + if (defined('self::' . strtoupper($typ)) && !in_array($typ, $this->options['type'])) { + $this->options['type'][] = $typ; + } + + if (($typ == self::ALL)) { + $this->options['type'] = array_keys($this->cardLength); + } + } + + return $this; + } + + /** + * Returns the actual set service + * + * @return callable + */ + public function getService() + { + return $this->options['service']; + } + + /** + * Sets a new callback for service validation + * + * @param callable $service + * @return CreditCard + * @throws Exception\InvalidArgumentException on invalid service callback + */ + public function setService($service) + { + if (!is_callable($service)) { + throw new Exception\InvalidArgumentException('Invalid callback given'); + } + + $this->options['service'] = $service; + return $this; + } + + /** + * Returns true if and only if $value follows the Luhn algorithm (mod-10 checksum) + * + * @param string $value + * @return boolean + */ + public function isValid($value) + { + $this->setValue($value); + + if (!is_string($value)) { + $this->error(self::INVALID, $value); + return false; + } + + if (!ctype_digit($value)) { + $this->error(self::CONTENT, $value); + return false; + } + + $length = strlen($value); + $types = $this->getType(); + $foundp = false; + $foundl = false; + foreach ($types as $type) { + foreach ($this->cardType[$type] as $prefix) { + if (substr($value, 0, strlen($prefix)) == $prefix) { + $foundp = true; + if (in_array($length, $this->cardLength[$type])) { + $foundl = true; + break 2; + } + } + } + } + + if ($foundp == false) { + $this->error(self::PREFIX, $value); + return false; + } + + if ($foundl == false) { + $this->error(self::LENGTH, $value); + return false; + } + + $sum = 0; + $weight = 2; + + for ($i = $length - 2; $i >= 0; $i--) { + $digit = $weight * $value[$i]; + $sum += floor($digit / 10) + $digit % 10; + $weight = $weight % 2 + 1; + } + + if ((10 - $sum % 10) % 10 != $value[$length - 1]) { + $this->error(self::CHECKSUM, $value); + return false; + } + + $service = $this->getService(); + if (!empty($service)) { + try { + $callback = new Callback($service); + $callback->setOptions($this->getType()); + if (!$callback->isValid($value)) { + $this->error(self::SERVICE, $value); + return false; + } + } catch (\Exception $e) { + $this->error(self::SERVICEFAILURE, $value); + return false; + } + } + + return true; + } +} diff --git a/lib/Zend/Validator/Csrf.php b/lib/Zend/Validator/Csrf.php new file mode 100644 index 0000000000000000000000000000000000000000..61e1300c9aaa92e88dc9bf06747e422c19d52f99 --- /dev/null +++ b/lib/Zend/Validator/Csrf.php @@ -0,0 +1,316 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator; + +use Traversable; +use Zend\Math\Rand; +use Zend\Session\Container as SessionContainer; +use Zend\Stdlib\ArrayUtils; + +class Csrf extends AbstractValidator +{ + /** + * Error codes + * @const string + */ + const NOT_SAME = 'notSame'; + + /** + * Error messages + * @var array + */ + protected $messageTemplates = array( + self::NOT_SAME => "The form submitted did not originate from the expected site", + ); + + /** + * Actual hash used. + * + * @var mixed + */ + protected $hash; + + /** + * Static cache of the session names to generated hashes + * + * @var array + */ + protected static $hashCache; + + /** + * Name of CSRF element (used to create non-colliding hashes) + * + * @var string + */ + protected $name = 'csrf'; + + /** + * Salt for CSRF token + * @var string + */ + protected $salt = 'salt'; + + /** + * @var SessionContainer + */ + protected $session; + + /** + * TTL for CSRF token + * @var int|null + */ + protected $timeout = 300; + + /** + * Constructor + * + * @param array|Traversable $options + */ + public function __construct($options = array()) + { + parent::__construct($options); + + if ($options instanceof Traversable) { + $options = ArrayUtils::iteratorToArray($options); + } + + if (!is_array($options)) { + $options = (array) $options; + } + + foreach ($options as $key => $value) { + switch (strtolower($key)) { + case 'name': + $this->setName($value); + break; + case 'salt': + $this->setSalt($value); + break; + case 'session': + $this->setSession($value); + break; + case 'timeout': + $this->setTimeout($value); + break; + default: + // ignore unknown options + break; + } + } + } + + /** + * Does the provided token match the one generated? + * + * @param string $value + * @param mixed $context + * @return bool + */ + public function isValid($value, $context = null) + { + $this->setValue((string) $value); + + $hash = $this->getValidationToken(); + + if ($value !== $hash) { + $this->error(self::NOT_SAME); + return false; + } + + return true; + } + + /** + * Set CSRF name + * + * @param string $name + * @return Csrf + */ + public function setName($name) + { + $this->name = (string) $name; + return $this; + } + + /** + * Get CSRF name + * + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * Set session container + * + * @param SessionContainer $session + * @return Csrf + */ + public function setSession(SessionContainer $session) + { + $this->session = $session; + if ($this->hash) { + $this->initCsrfToken(); + } + return $this; + } + + /** + * Get session container + * + * Instantiate session container if none currently exists + * + * @return SessionContainer + */ + public function getSession() + { + if (null === $this->session) { + $this->session = new SessionContainer($this->getSessionName()); + } + return $this->session; + } + + /** + * Salt for CSRF token + * + * @param string $salt + * @return Csrf + */ + public function setSalt($salt) + { + $this->salt = (string) $salt; + return $this; + } + + /** + * Retrieve salt for CSRF token + * + * @return string + */ + public function getSalt() + { + return $this->salt; + } + + /** + * Retrieve CSRF token + * + * If no CSRF token currently exists, or should be regenerated, + * generates one. + * + * @param bool $regenerate default false + * @return string + */ + public function getHash($regenerate = false) + { + if ((null === $this->hash) || $regenerate) { + if ($regenerate) { + $this->hash = null; + } else { + $this->hash = $this->getValidationToken(); + } + if (null === $this->hash) { + $this->generateHash(); + } + } + return $this->hash; + } + + /** + * Get session namespace for CSRF token + * + * Generates a session namespace based on salt, element name, and class. + * + * @return string + */ + public function getSessionName() + { + return str_replace('\\', '_', __CLASS__) . '_' + . $this->getSalt() . '_' + . strtr($this->getName(), array('[' => '_', ']' => '')); + } + + /** + * Set timeout for CSRF session token + * + * @param int|null $ttl + * @return Csrf + */ + public function setTimeout($ttl) + { + $this->timeout = ($ttl !== null) ? (int)$ttl : null; + return $this; + } + + /** + * Get CSRF session token timeout + * + * @return int + */ + public function getTimeout() + { + return $this->timeout; + } + + /** + * Initialize CSRF token in session + * + * @return void + */ + protected function initCsrfToken() + { + $session = $this->getSession(); + //$session->setExpirationHops(1, null, true); + $timeout = $this->getTimeout(); + if (null !== $timeout) { + $session->setExpirationSeconds($timeout); + } + $session->hash = $this->getHash(); + } + + /** + * Generate CSRF token + * + * Generates CSRF token and stores both in {@link $hash} and element + * value. + * + * @return void + */ + protected function generateHash() + { + if (isset(static::$hashCache[$this->getSessionName()])) { + $this->hash = static::$hashCache[$this->getSessionName()]; + } else { + $this->hash = md5($this->getSalt() . Rand::getBytes(32) . $this->getName()); + static::$hashCache[$this->getSessionName()] = $this->hash; + } + $this->setValue($this->hash); + $this->initCsrfToken(); + } + + /** + * Get validation token + * + * Retrieve token from session, if it exists. + * + * @return null|string + */ + protected function getValidationToken() + { + $session = $this->getSession(); + if (isset($session->hash)) { + return $session->hash; + } + return null; + } +} diff --git a/lib/Zend/Validator/Date.php b/lib/Zend/Validator/Date.php new file mode 100644 index 0000000000000000000000000000000000000000..c2b12ca54ed8743e7741f95656cef72acea0881d --- /dev/null +++ b/lib/Zend/Validator/Date.php @@ -0,0 +1,157 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator; + +use DateTime; +use Traversable; + +/** + * @category Zend + * @package Zend_Validate + */ +class Date extends AbstractValidator +{ + const INVALID = 'dateInvalid'; + const INVALID_DATE = 'dateInvalidDate'; + const FALSEFORMAT = 'dateFalseFormat'; + + /** + * Validation failure message template definitions + * + * @var array + */ + protected $messageTemplates = array( + self::INVALID => "Invalid type given. String, integer, array or DateTime expected", + self::INVALID_DATE => "The input does not appear to be a valid date", + self::FALSEFORMAT => "The input does not fit the date format '%format%'", + ); + + /** + * @var array + */ + protected $messageVariables = array( + 'format' => 'format' + ); + + /** + * Optional format + * + * @var string|null + */ + protected $format; + + /** + * Sets validator options + * + * @param string|array|Traversable $options OPTIONAL + */ + public function __construct($options = array()) + { + if ($options instanceof Traversable) { + $options = iterator_to_array($options); + } elseif (!is_array($options)) { + $options = func_get_args(); + $temp['format'] = array_shift($options); + $options = $temp; + } + + if (array_key_exists('format', $options)) { + $this->setFormat($options['format']); + } + + parent::__construct($options); + } + + /** + * Returns the format option + * + * @return string|null + */ + public function getFormat() + { + return $this->format; + } + + /** + * Sets the format option + * + * @param string $format + * @return Date provides a fluent interface + */ + public function setFormat($format = null) + { + $this->format = $format; + return $this; + } + + /** + * Returns true if $value is a valid date of the format YYYY-MM-DD + * If optional $format is set the date format is checked + * according to DateTime + * + * @param string|array|int|DateTime $value + * @return boolean + */ + public function isValid($value) + { + if (!is_string($value) + && !is_array($value) + && !is_int($value) + && !($value instanceof DateTime) + ) { + $this->error(self::INVALID); + return false; + } + + $this->setValue($value); + + $format = $this->getFormat(); + + if ($value instanceof DateTime) { + return true; + } elseif (is_int($value) + || (is_string($value) && null !== $format) + ) { + $date = (is_int($value)) + ? date_create("@$value") // from timestamp + : DateTime::createFromFormat($format, $value); + + // Invalid dates can show up as warnings (ie. "2007-02-99") + // and still return a DateTime object + $errors = DateTime::getLastErrors(); + + if (false === $date || $errors['warning_count'] > 0) { + $this->error(self::INVALID_DATE); + return false; + } + } else { + if (is_array($value)) { + $value = implode('-', $value); + } + + if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $value)) { + $this->format = 'Y-m-d'; + $this->error(self::FALSEFORMAT); + $this->format = null; + return false; + } + + list($year, $month, $day) = sscanf($value, '%d-%d-%d'); + + if (!checkdate($month, $day, $year)) { + $this->error(self::INVALID_DATE); + return false; + } + } + + return true; + } +} diff --git a/lib/Zend/Validator/DateStep.php b/lib/Zend/Validator/DateStep.php new file mode 100644 index 0000000000000000000000000000000000000000..84b1b2a4d3aa38fbdfd5b57746b99095338074d4 --- /dev/null +++ b/lib/Zend/Validator/DateStep.php @@ -0,0 +1,405 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator; + +use DateInterval; +use DateTime; +use DateTimeZone; +use Traversable; +use Zend\Stdlib\ArrayUtils; +use Zend\Validator\Exception; + +/** + * @category Zend + * @package Zend_Validate + */ +class DateStep extends AbstractValidator +{ + const INVALID = 'dateStepInvalid'; + const INVALID_DATE = 'dateStepInvalidDate'; + const NOT_STEP = 'dateStepNotStep'; + + /** + * @var array + */ + protected $messageTemplates = array( + self::INVALID => "Invalid type given. String, integer, array or DateTime expected", + self::INVALID_DATE => "The input does not appear to be a valid date", + self::NOT_STEP => "The input is not a valid step" + ); + + /** + * Optional base date value + * + * @var string|integer|\DateTime + */ + protected $baseValue = '1970-01-01T00:00:00Z'; + + /** + * Date step interval (defaults to 1 day). + * Uses the DateInterval specification. + * + * @var DateInterval + */ + protected $step; + + /** + * Format to use for parsing date strings + * + * @var string + */ + protected $format = DateTime::ISO8601; + + /** + * Optional timezone to be used when the baseValue + * and validation values do not contain timezone info + * + * @var DateTimeZone + */ + protected $timezone; + + /** + * Set default options for this instance + * + * @param array $options + */ + public function __construct($options = array()) + { + if ($options instanceof Traversable) { + $options = ArrayUtils::iteratorToArray($options); + } elseif (!is_array($options)) { + $options = func_get_args(); + $temp['baseValue'] = array_shift($options); + if (!empty($options)) { + $temp['step'] = array_shift($options); + } + if (!empty($options)) { + $temp['format'] = array_shift($options); + } + if (!empty($options)) { + $temp['timezone'] = array_shift($options); + } + + $options = $temp; + } + + if (isset($options['baseValue'])) { + $this->setBaseValue($options['baseValue']); + } + if (isset($options['step'])) { + $this->setStep($options['step']); + } else { + $this->setStep(new DateInterval('P1D')); + } + if (array_key_exists('format', $options)) { + $this->setFormat($options['format']); + } + if (isset($options['timezone'])) { + $this->setTimezone($options['timezone']); + } else { + $this->setTimezone(new DateTimeZone(date_default_timezone_get())); + } + + parent::__construct($options); + } + + /** + * Sets the base value from which the step should be computed + * + * @param string|integer|\DateTime $baseValue + * @return DateStep + */ + public function setBaseValue($baseValue) + { + $this->baseValue = $baseValue; + return $this; + } + + /** + * Returns the base value from which the step should be computed + * + * @return string|integer|\DateTime + */ + public function getBaseValue() + { + return $this->baseValue; + } + + /** + * Sets the step date interval + * + * @param DateInterval $step + * @return DateStep + */ + public function setStep(DateInterval $step) + { + $this->step = $step; + return $this; + } + + /** + * Returns the step date interval + * + * @return DateInterval + */ + public function getStep() + { + return $this->step; + } + + /** + * Returns the format option + * + * @return string + */ + public function getFormat() + { + return $this->format; + } + + /** + * Sets the format option + * + * @param string $format + * @return DateStep + */ + public function setFormat($format) + { + $this->format = $format; + return $this; + } + + /** + * Returns the timezone option + * + * @return DateTimeZone + */ + public function getTimezone() + { + return $this->timezone; + } + + /** + * Sets the timezone option + * + * @param DateTimeZone $timezone + * @return DateStep + */ + public function setTimezone(DateTimeZone $timezone) + { + $this->timezone = $timezone; + return $this; + } + + /** + * Converts an int or string to a DateTime object + * + * @param string|integer|\DateTime $param + * @return \DateTime + * @throws Exception\InvalidArgumentException + */ + protected function convertToDateTime($param) + { + $dateObj = $param; + if (is_int($param)) { + // Convert from timestamp + $dateObj = date_create("@$param"); + } elseif (is_string($param)) { + // Custom week format support + if (strpos($this->getFormat(), 'Y-\WW') === 0 + && preg_match('/^([0-9]{4})\-W([0-9]{2})/', $param, $matches) + ) { + $dateObj = new DateTime(); + $dateObj->setISODate($matches[1], $matches[2]); + } else { + $dateObj = DateTime::createFromFormat( + $this->getFormat(), $param, $this->getTimezone() + ); + } + } + if (!($dateObj instanceof DateTime)) { + throw new Exception\InvalidArgumentException('Invalid date param given'); + } + + return $dateObj; + } + + /** + * Returns true if a date is within a valid step + * + * @param string|integer|\DateTime $value + * @return bool + * @throws Exception\InvalidArgumentException + */ + public function isValid($value) + { + if (!is_string($value) + && !is_int($value) + && !($value instanceof DateTime) + ) { + $this->error(self::INVALID); + return false; + } + + $this->setValue($value); + + $baseDate = $this->convertToDateTime($this->getBaseValue()); + $step = $this->getStep(); + + // Parse the date + try { + $valueDate = $this->convertToDateTime($value); + } catch (Exception\InvalidArgumentException $ex) { + $this->error(self::INVALID_DATE); + return false; + } + + // Same date? + if ($valueDate == $baseDate) { + return true; + } + + // Optimization for simple intervals. + // Handle intervals of just one date or time unit. + $intervalParts = explode('|', $step->format('%y|%m|%d|%h|%i|%s')); + $partCounts = array_count_values($intervalParts); + if (5 === $partCounts["0"]) { + // Find the unit with the non-zero interval + $unitKeys = array('years', 'months', 'days', 'hours', 'minutes', 'seconds'); + $intervalParts = array_combine($unitKeys, $intervalParts); + + $intervalUnit = null; + $stepValue = null; + foreach ($intervalParts as $key => $value) { + if (0 != $value) { + $intervalUnit = $key; + $stepValue = (int)$value; + break; + } + } + + // Get absolute time difference + $timeDiff = $valueDate->diff($baseDate, true); + $diffParts = explode('|', $timeDiff->format('%y|%m|%d|%h|%i|%s')); + $diffParts = array_combine($unitKeys, $diffParts); + + // Check date units + if (in_array($intervalUnit, array('years', 'months', 'days'))) { + switch ($intervalUnit) { + case 'years': + if ( 0 == $diffParts['months'] && 0 == $diffParts['days'] + && 0 == $diffParts['hours'] && 0 == $diffParts['minutes'] + && 0 == $diffParts['seconds'] + ) { + if (($diffParts['years'] % $stepValue) === 0) { + return true; + } + } + break; + case 'months': + if ( 0 == $diffParts['days'] && 0 == $diffParts['hours'] + && 0 == $diffParts['minutes'] && 0 == $diffParts['seconds'] + ) { + $months = ($diffParts['years'] * 12) + $diffParts['months']; + if (($months % $stepValue) === 0) { + return true; + } + } + break; + case 'days': + if ( 0 == $diffParts['hours'] && 0 == $diffParts['minutes'] + && 0 == $diffParts['seconds'] + ) { + $days = $timeDiff->format('%a'); // Total days + if (($days % $stepValue) === 0) { + return true; + } + } + break; + } + $this->error(self::NOT_STEP); + return false; + } + + // Check time units + if (in_array($intervalUnit, array('hours', 'minutes', 'seconds'))) { + + // Simple test if $stepValue is 1. + if (1 == $stepValue) { + if ('hours' === $intervalUnit + && 0 == $diffParts['minutes'] && 0 == $diffParts['seconds'] + ) { + return true; + } elseif ('minutes' === $intervalUnit && 0 == $diffParts['seconds']) { + return true; + } elseif ('seconds' === $intervalUnit) { + return true; + } + } + + // Simple test for same day, when using default baseDate + if ($baseDate->format('Y-m-d') == $valueDate->format('Y-m-d') + && $baseDate->format('Y-m-d') == '1970-01-01' + ) { + switch ($intervalUnit) { + case 'hours': + if (0 == $diffParts['minutes'] && 0 == $diffParts['seconds']) { + if (($diffParts['hours'] % $stepValue) === 0) { + return true; + } + } + break; + case 'minutes': + if (0 == $diffParts['seconds']) { + $minutes = ($diffParts['hours'] * 60) + $diffParts['minutes']; + if (($minutes % $stepValue) === 0) { + return true; + } + } + break; + case 'seconds': + $seconds = ($diffParts['hours'] * 60) + + ($diffParts['minutes'] * 60) + + $diffParts['seconds']; + if (($seconds % $stepValue) === 0) { + return true; + } + break; + } + $this->error(self::NOT_STEP); + return false; + } + } + } + + // Fall back to slower (but accurate) method for complex intervals. + // Keep adding steps to the base date until a match is found + // or until the value is exceeded. + if ($baseDate < $valueDate) { + while ($baseDate < $valueDate) { + $baseDate->add($step); + if ($baseDate == $valueDate) { + return true; + } + } + } else { + while ($baseDate > $valueDate) { + $baseDate->sub($step); + if ($baseDate == $valueDate) { + return true; + } + } + } + + $this->error(self::NOT_STEP); + return false; + } +} diff --git a/lib/Zend/Validator/Db/AbstractDb.php b/lib/Zend/Validator/Db/AbstractDb.php new file mode 100644 index 0000000000000000000000000000000000000000..476aac362ac1830f5b7299dd6e4dbab4848e2949 --- /dev/null +++ b/lib/Zend/Validator/Db/AbstractDb.php @@ -0,0 +1,345 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Db; + +use Traversable; +use Zend\Db\Adapter\Adapter as DbAdapter; +use Zend\Db\Adapter\Driver\DriverInterface as DbDriverInterface; +use Zend\Db\Sql\Select as DbSelect; +use Zend\Db\Sql\TableIdentifier; +use Zend\Stdlib\ArrayUtils; +use Zend\Validator\AbstractValidator; +use Zend\Validator\Exception; + +/** + * Class for Database record validation + * + * @category Zend + * @package Zend_Validate + */ +abstract class AbstractDb extends AbstractValidator +{ + /** + * Error constants + */ + const ERROR_NO_RECORD_FOUND = 'noRecordFound'; + const ERROR_RECORD_FOUND = 'recordFound'; + + /** + * @var array Message templates + */ + protected $messageTemplates = array( + self::ERROR_NO_RECORD_FOUND => "No record matching the input was found", + self::ERROR_RECORD_FOUND => "A record matching the input was found", + ); + + /** + * Select object to use. can be set, or will be auto-generated + * + * @var DbSelect + */ + protected $select; + + /** + * @var string + */ + protected $schema = null; + + /** + * @var string + */ + protected $table = ''; + + /** + * @var string + */ + protected $field = ''; + + /** + * @var mixed + */ + protected $exclude = null; + + /** + * Database adapter to use. If null isValid() will throw an exception + * + * @var \Zend\Db\Adapter\Adapter + */ + protected $adapter = null; + + /** + * Provides basic configuration for use with Zend\Validator\Db Validators + * Setting $exclude allows a single record to be excluded from matching. + * Exclude can either be a String containing a where clause, or an array with `field` and `value` keys + * to define the where clause added to the sql. + * A database adapter may optionally be supplied to avoid using the registered default adapter. + * + * The following option keys are supported: + * 'table' => The database table to validate against + * 'schema' => The schema keys + * 'field' => The field to check for a match + * 'exclude' => An optional where clause or field/value pair to exclude from the query + * 'adapter' => An optional database adapter to use + * + * @param array|Traversable|DbSelect $options Options to use for this validator + * @throws \Zend\Validator\Exception\InvalidArgumentException + */ + public function __construct($options = null) + { + parent::__construct($options); + + if ($options instanceof DbSelect) { + $this->setSelect($options); + return; + } + + if ($options instanceof Traversable) { + $options = ArrayUtils::iteratorToArray($options); + } elseif (func_num_args() > 1) { + $options = func_get_args(); + $firstArgument = array_shift($options); + if (is_array($firstArgument)) { + $temp = ArrayUtils::iteratorToArray($firstArgument); + } else { + $temp['table'] = $firstArgument; + } + + $temp['field'] = array_shift($options); + + if (!empty($options)) { + $temp['exclude'] = array_shift($options); + } + + if (!empty($options)) { + $temp['adapter'] = array_shift($options); + } + + $options = $temp; + } + + if (!array_key_exists('table', $options) && !array_key_exists('schema', $options)) { + throw new Exception\InvalidArgumentException('Table or Schema option missing!'); + } + + if (!array_key_exists('field', $options)) { + throw new Exception\InvalidArgumentException('Field option missing!'); + } + + if (array_key_exists('adapter', $options)) { + $this->setAdapter($options['adapter']); + } + + if (array_key_exists('exclude', $options)) { + $this->setExclude($options['exclude']); + } + + $this->setField($options['field']); + if (array_key_exists('table', $options)) { + $this->setTable($options['table']); + } + + if (array_key_exists('schema', $options)) { + $this->setSchema($options['schema']); + } + } + + /** + * Returns the set adapter + * + * @throws \Zend\Validator\Exception\RuntimeException When no database adapter is defined + * @return DbAdapter + */ + public function getAdapter() + { + return $this->adapter; + } + + /** + * Sets a new database adapter + * + * @param DbAdapter $adapter + * @return self Provides a fluent interface + */ + public function setAdapter(DbAdapter $adapter) + { + $this->adapter = $adapter; + return $this; + } + + /** + * Returns the set exclude clause + * + * @return string|array + */ + public function getExclude() + { + return $this->exclude; + } + + /** + * Sets a new exclude clause + * + * @param string|array $exclude + * @return self Provides a fluent interface + */ + public function setExclude($exclude) + { + $this->exclude = $exclude; + return $this; + } + + /** + * Returns the set field + * + * @return string|array + */ + public function getField() + { + return $this->field; + } + + /** + * Sets a new field + * + * @param string $field + * @return AbstractDb + */ + public function setField($field) + { + $this->field = (string)$field; + return $this; + } + + /** + * Returns the set table + * + * @return string + */ + public function getTable() + { + return $this->table; + } + + /** + * Sets a new table + * + * @param string $table + * @return self Provides a fluent interface + */ + public function setTable($table) + { + $this->table = (string)$table; + return $this; + } + + /** + * Returns the set schema + * + * @return string + */ + public function getSchema() + { + return $this->schema; + } + + /** + * Sets a new schema + * + * @param string $schema + * @return self Provides a fluent interface + */ + public function setSchema($schema) + { + $this->schema = $schema; + return $this; + } + + /** + * Sets the select object to be used by the validator + * + * @param DbSelect $select + * @return self Provides a fluent interface + */ + public function setSelect(DbSelect $select) + { + $this->select = $select; + return $this; + } + + /** + * Gets the select object to be used by the validator. + * If no select object was supplied to the constructor, + * then it will auto-generate one from the given table, + * schema, field, and adapter options. + * + * @return DbSelect The Select object which will be used + */ + public function getSelect() + { + if ($this->select instanceof DbSelect) { + return $this->select; + } + + $adapter = $this->getAdapter(); + $driver = $adapter->getDriver(); + $platform = $adapter->getPlatform(); + + /* + * Build select object + */ + $select = new DbSelect(); + $tableIdentifier = new TableIdentifier($this->table, $this->schema); + $select->from($tableIdentifier)->columns( + array($this->field) + ); + + // Support both named and positional parameters + if (DbDriverInterface::PARAMETERIZATION_NAMED == $driver->getPrepareType()) { + $select->where( + $platform->quoteIdentifier($this->field, true) . ' = :value' + ); + } else { + $select->where( + $platform->quoteIdentifier($this->field, true) . ' = ?' + ); + } + + if ($this->exclude !== null) { + if (is_array($this->exclude)) { + $select->where->notEqualTo( + $this->exclude['field'], + $this->exclude['value'] + ); + } else { + $select->where($this->exclude); + } + } + + $this->select = $select; + + return $this->select; + } + + /** + * Run query and returns matches, or null if no matches are found. + * + * @param string $value + * @return array when matches are found. + */ + protected function query($value) + { + $adapter = $this->getAdapter(); + $statement = $adapter->createStatement(); + $this->getSelect()->prepareStatement($adapter, $statement); + + return $statement->execute(array('value' => $value))->current(); + } +} diff --git a/lib/Zend/Validator/Db/NoRecordExists.php b/lib/Zend/Validator/Db/NoRecordExists.php new file mode 100644 index 0000000000000000000000000000000000000000..ed42d1f34baf860944de8223a31acebdafec8d5a --- /dev/null +++ b/lib/Zend/Validator/Db/NoRecordExists.php @@ -0,0 +1,43 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Db; + +use Zend\Validator\Exception; + +/** + * Confirms a record does not exist in a table. + * + * @category Zend + * @package Zend_Validate + */ +class NoRecordExists extends AbstractDb +{ + public function isValid($value) + { + /* + * Check for an adapter being defined. If not, throw an exception. + */ + if (null === $this->adapter) { + throw new Exception\RuntimeException('No database adapter present'); + } + + $valid = true; + $this->setValue($value); + + $result = $this->query($value); + if ($result) { + $valid = false; + $this->error(self::ERROR_RECORD_FOUND); + } + + return $valid; + } +} diff --git a/lib/Zend/Validator/Db/RecordExists.php b/lib/Zend/Validator/Db/RecordExists.php new file mode 100644 index 0000000000000000000000000000000000000000..1a0d41ab61d173bb91e341b821c1f06f13a0908d --- /dev/null +++ b/lib/Zend/Validator/Db/RecordExists.php @@ -0,0 +1,43 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Db; + +use Zend\Validator\Exception; + +/** + * Confirms a record exists in a table. + * + * @category Zend + * @package Zend_Validate + */ +class RecordExists extends AbstractDb +{ + public function isValid($value) + { + /* + * Check for an adapter being defined. If not, throw an exception. + */ + if (null === $this->adapter) { + throw new Exception\RuntimeException('No database adapter present'); + } + + $valid = true; + $this->setValue($value); + + $result = $this->query($value); + if (!$result) { + $valid = false; + $this->error(self::ERROR_NO_RECORD_FOUND); + } + + return $valid; + } +} diff --git a/lib/Zend/Validator/Digits.php b/lib/Zend/Validator/Digits.php new file mode 100644 index 0000000000000000000000000000000000000000..f95cf57ba9a764f7b336ac69a577839c265dff80 --- /dev/null +++ b/lib/Zend/Validator/Digits.php @@ -0,0 +1,74 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator; + +use Zend\Filter\Digits as DigitsFilter; + +/** + * @category Zend + * @package Zend_Validate + */ +class Digits extends AbstractValidator +{ + const NOT_DIGITS = 'notDigits'; + const STRING_EMPTY = 'digitsStringEmpty'; + const INVALID = 'digitsInvalid'; + + /** + * Digits filter used for validation + * + * @var \Zend\Filter\Digits + */ + protected static $filter = null; + + /** + * Validation failure message template definitions + * + * @var array + */ + protected $messageTemplates = array( + self::NOT_DIGITS => "The input must contain only digits", + self::STRING_EMPTY => "The input is an empty string", + self::INVALID => "Invalid type given. String, integer or float expected", + ); + + /** + * Returns true if and only if $value only contains digit characters + * + * @param string $value + * @return boolean + */ + public function isValid($value) + { + if (!is_string($value) && !is_int($value) && !is_float($value)) { + $this->error(self::INVALID); + return false; + } + + $this->setValue((string) $value); + + if ('' === $this->getValue()) { + $this->error(self::STRING_EMPTY); + return false; + } + + if (null === self::$filter) { + self::$filter = new DigitsFilter(); + } + + if ($this->getValue() !== self::$filter->filter($this->getValue())) { + $this->error(self::NOT_DIGITS); + return false; + } + + return true; + } +} diff --git a/lib/Zend/Validator/EmailAddress.php b/lib/Zend/Validator/EmailAddress.php new file mode 100644 index 0000000000000000000000000000000000000000..67a31d9e7f475cb9d930da9c5d8d76a547332278 --- /dev/null +++ b/lib/Zend/Validator/EmailAddress.php @@ -0,0 +1,536 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator; + +/** + * @category Zend + * @package Zend_Validate + */ +class EmailAddress extends AbstractValidator +{ + const INVALID = 'emailAddressInvalid'; + const INVALID_FORMAT = 'emailAddressInvalidFormat'; + const INVALID_HOSTNAME = 'emailAddressInvalidHostname'; + const INVALID_MX_RECORD = 'emailAddressInvalidMxRecord'; + const INVALID_SEGMENT = 'emailAddressInvalidSegment'; + const DOT_ATOM = 'emailAddressDotAtom'; + const QUOTED_STRING = 'emailAddressQuotedString'; + const INVALID_LOCAL_PART = 'emailAddressInvalidLocalPart'; + const LENGTH_EXCEEDED = 'emailAddressLengthExceeded'; + + /** + * @var array + */ + protected $messageTemplates = array( + self::INVALID => "Invalid type given. String expected", + self::INVALID_FORMAT => "The input is not a valid email address. Use the basic format local-part@hostname", + self::INVALID_HOSTNAME => "'%hostname%' is not a valid hostname for the email address", + self::INVALID_MX_RECORD => "'%hostname%' does not appear to have any valid MX or A records for the email address", + self::INVALID_SEGMENT => "'%hostname%' is not in a routable network segment. The email address should not be resolved from public network", + self::DOT_ATOM => "'%localPart%' can not be matched against dot-atom format", + self::QUOTED_STRING => "'%localPart%' can not be matched against quoted-string format", + self::INVALID_LOCAL_PART => "'%localPart%' is not a valid local part for the email address", + self::LENGTH_EXCEEDED => "The input exceeds the allowed length", + ); + + /** + * @var array + */ + protected $messageVariables = array( + 'hostname' => 'hostname', + 'localPart' => 'localPart' + ); + + /** + * @var string + */ + protected $hostname; + + /** + * @var string + */ + protected $localPart; + + /** + * Returns the found mx record informations + * + * @var array + */ + protected $mxRecord; + + /** + * Internal options array + */ + protected $options = array( + 'useMxCheck' => false, + 'useDeepMxCheck' => false, + 'useDomainCheck' => true, + 'allow' => Hostname::ALLOW_DNS, + 'hostnameValidator' => null, + ); + + /** + * Instantiates hostname validator for local use + * + * The following additional option keys are supported: + * 'hostnameValidator' => A hostname validator, see Zend\Validator\Hostname + * 'allow' => Options for the hostname validator, see Zend\Validator\Hostname::ALLOW_* + * 'useMxCheck' => If MX check should be enabled, boolean + * 'useDeepMxCheck' => If a deep MX check should be done, boolean + * + * @param array|\Traversable $options OPTIONAL + */ + public function __construct($options = array()) + { + if (!is_array($options)) { + $options = func_get_args(); + $temp['allow'] = array_shift($options); + if (!empty($options)) { + $temp['useMxCheck'] = array_shift($options); + } + + if (!empty($options)) { + $temp['hostnameValidator'] = array_shift($options); + } + + $options = $temp; + } + + if (!array_key_exists('hostnameValidator', $options)) { + $options['hostnameValidator'] = null; + } + + parent::__construct($options); + } + + /** + * Sets the validation failure message template for a particular key + * Adds the ability to set messages to the attached hostname validator + * + * @param string $messageString + * @param string $messageKey OPTIONAL + * @return AbstractValidator Provides a fluent interface + */ + public function setMessage($messageString, $messageKey = null) + { + if ($messageKey === null) { + $this->getHostnameValidator()->setMessage($messageString); + parent::setMessage($messageString); + return $this; + } + + if (!isset($this->messageTemplates[$messageKey])) { + $this->getHostnameValidator()->setMessage($messageString, $messageKey); + } else { + parent::setMessage($messageString, $messageKey); + } + + return $this; + } + + /** + * Returns the set hostname validator + * + * @return Hostname + */ + public function getHostnameValidator() + { + if (!isset($this->options['hostnameValidator']) + || !$this->options['hostnameValidator'] instanceof Hostname + ) { + $this->setHostnameValidator(); + } + + return $this->options['hostnameValidator']; + } + + /** + * @param Hostname $hostnameValidator OPTIONAL + * @return EmailAddress Provides a fluent interface + */ + public function setHostnameValidator(Hostname $hostnameValidator = null) + { + if (!$hostnameValidator) { + $hostnameValidator = new Hostname($this->getAllow()); + } + + $this->options['hostnameValidator'] = $hostnameValidator; + + return $this; + } + + /** + * Returns the allow option of the attached hostname validator + * + * @return integer + */ + public function getAllow() + { + return $this->options['allow']; + } + + /** + * Sets the allow option of the hostname validator to use + * + * @param integer $allow + * @return EmailAddress Provides a fluent interface + */ + public function setAllow($allow) + { + $this->options['allow'] = $allow; + if ($this->options['hostnameValidator'] !== null) { + $this->options['hostnameValidator']->setAllow($allow); + } + + return $this; + } + + /** + * Whether MX checking via getmxrr is supported or not + * + * @return boolean + */ + public function isMxSupported() + { + return function_exists('getmxrr'); + } + + /** + * Returns the set validateMx option + * + * @return boolean + */ + public function getMxCheck() + { + return $this->options['useMxCheck']; + } + + /** + * Set whether we check for a valid MX record via DNS + * + * This only applies when DNS hostnames are validated + * + * @param boolean $mx Set allowed to true to validate for MX records, and false to not validate them + * @return EmailAddress Fluid Interface + */ + public function useMxCheck($mx) + { + $this->options['useMxCheck'] = (bool) $mx; + return $this; + } + + /** + * Returns the set deepMxCheck option + * + * @return boolean + */ + public function getDeepMxCheck() + { + return $this->options['useDeepMxCheck']; + } + + /** + * Use deep validation for MX records + * + * @param boolean $deep Set deep to true to perform a deep validation process for MX records + * @return EmailAddress Fluid Interface + */ + public function useDeepMxCheck($deep) + { + $this->options['useDeepMxCheck'] = (bool) $deep; + return $this; + } + + /** + * Returns the set domainCheck option + * + * @return boolean + */ + public function getDomainCheck() + { + return $this->options['useDomainCheck']; + } + + /** + * Sets if the domain should also be checked + * or only the local part of the email address + * + * @param boolean $domain + * @return EmailAddress Fluid Interface + */ + public function useDomainCheck($domain = true) + { + $this->options['useDomainCheck'] = (boolean) $domain; + return $this; + } + + /** + * Returns if the given host is reserved + * + * The following addresses are seen as reserved + * '0.0.0.0/8', '10.0.0.0/8', '127.0.0.0/8' + * '100.64.0.0/10' + * '172.16.0.0/12' + * '198.18.0.0/15' + * '169.254.0.0/16', '192.168.0.0/16' + * '192.0.2.0/24', '192.88.99.0/24', '198.51.100.0/24', '203.0.113.0/24' + * '224.0.0.0/4', '240.0.0.0/4' + * @see http://en.wikipedia.org/wiki/Reserved_IP_addresses + * + * As of RFC5753 (JAN 2010), the following blocks are no longer reserved: + * - 128.0.0.0/16 + * - 191.255.0.0/16 + * - 223.255.255.0/24 + * @see http://tools.ietf.org/html/rfc5735#page-6 + * + * As of RFC6598 (APR 2012), the following blocks are now reserved: + * - 100.64.0.0/10 + * @see http://tools.ietf.org/html/rfc6598#section-7 + * + * @param string $host + * @return boolean Returns false when minimal one of the given addresses is not reserved + */ + protected function isReserved($host) + { + if (!preg_match('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/', $host)) { + $host = gethostbynamel($host); + } else { + $host = array($host); + } + + if (empty($host)) { + return false; + } + + foreach ($host as $server) { + // Search for 0.0.0.0/8, 10.0.0.0/8, 127.0.0.0/8 + if (!preg_match('/^(0|10|127)(\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))){3}$/', $server) && + // Search for 100.64.0.0/10 + !preg_match('/^100\.(6[0-4]|[7-9][0-9]|1[0-1][0-9]|12[0-7])(\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))){2}$/', $server) && + // Search for 172.16.0.0/12 + !preg_match('/^172\.(1[6-9]|2[0-9]|3[0-1])(\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))){2}$/', $server) && + // Search for 198.18.0.0/15 + !preg_match('/^198\.(1[8-9])(\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))){2}$/', $server) && + // Search for 169.254.0.0/16, 192.168.0.0/16 + !preg_match('/^(169\.254|192\.168)(\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))){2}$/', $server) && + // Search for 192.0.2.0/24, 192.88.99.0/24, 198.51.100.0/24, 203.0.113.0/24 + !preg_match('/^(192\.0\.2|192\.88\.99|198\.51\.100|203\.0\.113)\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))$/', $server) && + // Search for 224.0.0.0/4, 240.0.0.0/4 + !preg_match('/^(2(2[4-9]|[3-4][0-9]|5[0-5]))(\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))){3}$/', $server) + ) { + return false; + } + } + + return true; + } + + /** + * Internal method to validate the local part of the email address + * + * @return boolean + */ + protected function validateLocalPart() + { + // First try to match the local part on the common dot-atom format + $result = false; + + // Dot-atom characters are: 1*atext *("." 1*atext) + // atext: ALPHA / DIGIT / and "!", "#", "$", "%", "&", "'", "*", + // "+", "-", "/", "=", "?", "^", "_", "`", "{", "|", "}", "~" + $atext = 'a-zA-Z0-9\x21\x23\x24\x25\x26\x27\x2a\x2b\x2d\x2f\x3d\x3f\x5e\x5f\x60\x7b\x7c\x7d\x7e'; + if (preg_match('/^[' . $atext . ']+(\x2e+[' . $atext . ']+)*$/', $this->localPart)) { + $result = true; + } else { + // Try quoted string format + + // Quoted-string characters are: DQUOTE *([FWS] qtext/quoted-pair) [FWS] DQUOTE + // qtext: Non white space controls, and the rest of the US-ASCII characters not + // including "\" or the quote character + $noWsCtl = '\x01-\x08\x0b\x0c\x0e-\x1f\x7f'; + $qtext = $noWsCtl . '\x21\x23-\x5b\x5d-\x7e'; + $ws = '\x20\x09'; + if (preg_match('/^\x22([' . $ws . $qtext . '])*[$ws]?\x22$/', $this->localPart)) { + $result = true; + } else { + $this->error(self::DOT_ATOM); + $this->error(self::QUOTED_STRING); + $this->error(self::INVALID_LOCAL_PART); + } + } + + return $result; + } + + /** + * Returns the found MX Record information after validation including weight for further processing + * + * @return array + */ + public function getMXRecord() + { + return $this->mxRecord; + } + + /** + * Internal method to validate the servers MX records + * + * @return boolean + */ + protected function validateMXRecords() + { + $mxHosts = array(); + $weight = array(); + $result = getmxrr($this->hostname, $mxHosts, $weight); + if (!empty($mxHosts) && !empty($weight)) { + $this->mxRecord = array_combine($mxHosts, $weight); + } else { + $this->mxRecord = $mxHosts; + } + + arsort($this->mxRecord); + + // Fallback to IPv4 hosts if no MX record found (RFC 2821 SS 5). + if (!$result) { + $result = gethostbynamel($this->hostname); + if (is_array($result)) { + $this->mxRecord = array_flip($result); + } + } + + if (!$result) { + $this->error(self::INVALID_MX_RECORD); + return $result; + } + + if (!$this->options['useDeepMxCheck']) { + return $result; + } + + $validAddress = false; + $reserved = true; + foreach ($this->mxRecord as $hostname => $weight) { + $res = $this->isReserved($hostname); + if (!$res) { + $reserved = false; + } + + if (!$res + && (checkdnsrr($hostname, "A") + || checkdnsrr($hostname, "AAAA") + || checkdnsrr($hostname, "A6")) + ) { + $validAddress = true; + break; + } + } + + if (!$validAddress) { + $result = false; + $error = ($reserved) ? self::INVALID_SEGMENT : self::INVALID_MX_RECORD; + $this->error($error); + } + + return $result; + } + + /** + * Internal method to validate the hostname part of the email address + * + * @return boolean + */ + protected function validateHostnamePart() + { + $hostname = $this->getHostnameValidator()->setTranslator($this->getTranslator()) + ->isValid($this->hostname); + if (!$hostname) { + $this->error(self::INVALID_HOSTNAME); + // Get messages and errors from hostnameValidator + foreach ($this->getHostnameValidator()->getMessages() as $code => $message) { + $this->abstractOptions['messages'][$code] = $message; + } + } elseif ($this->options['useMxCheck']) { + // MX check on hostname + $hostname = $this->validateMXRecords(); + } + + return $hostname; + } + + /** + * Splits the given value in hostname and local part of the email address + * + * @param string $value Email address to be split + * @return bool Returns false when the email can not be split + */ + protected function splitEmailParts($value) + { + // Split email address up and disallow '..' + if ((strpos($value, '..') !== false) or + (!preg_match('/^(.+)@([^@]+)$/', $value, $matches))) { + return false; + } + + $this->localPart = $matches[1]; + $this->hostname = $matches[2]; + + return true; + } + + /** + * Defined by Zend_Validate_Interface + * + * Returns true if and only if $value is a valid email address + * according to RFC2822 + * + * @link http://www.ietf.org/rfc/rfc2822.txt RFC2822 + * @link http://www.columbia.edu/kermit/ascii.html US-ASCII characters + * @param string $value + * @return boolean + */ + public function isValid($value) + { + if (!is_string($value)) { + $this->error(self::INVALID); + return false; + } + + $length = true; + $this->setValue($value); + + // Split email address up and disallow '..' + if (!$this->splitEmailParts($value)) { + $this->error(self::INVALID_FORMAT); + return false; + } + + if ((strlen($this->localPart) > 64) || (strlen($this->hostname) > 255)) { + $length = false; + $this->error(self::LENGTH_EXCEEDED); + } + + // Match hostname part + if ($this->options['useDomainCheck']) { + $hostname = $this->validateHostnamePart(); + } + + $local = $this->validateLocalPart(); + + // If both parts valid, return true + if ($local && $length) { + if (($this->options['useDomainCheck'] && $hostname) || !$this->options['useDomainCheck']) { + return true; + } + } + + return false; + } +} diff --git a/lib/Zend/Validator/Exception/BadMethodCallException.php b/lib/Zend/Validator/Exception/BadMethodCallException.php new file mode 100644 index 0000000000000000000000000000000000000000..0292c7f3326dc40ffacb4a4f41e33c7841bf445c --- /dev/null +++ b/lib/Zend/Validator/Exception/BadMethodCallException.php @@ -0,0 +1,15 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Exception; + +class BadMethodCallException extends \BadMethodCallException + implements ExceptionInterface +{} diff --git a/lib/Zend/Validator/Exception/ExceptionInterface.php b/lib/Zend/Validator/Exception/ExceptionInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..3bad3ac22c60fa1f3f295b11b22f6f34ce1ee944 --- /dev/null +++ b/lib/Zend/Validator/Exception/ExceptionInterface.php @@ -0,0 +1,18 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Exception; + +/** + * @category Zend + * @package Zend_Validate + */ +interface ExceptionInterface +{} diff --git a/lib/Zend/Validator/Exception/ExtensionNotLoadedException.php b/lib/Zend/Validator/Exception/ExtensionNotLoadedException.php new file mode 100644 index 0000000000000000000000000000000000000000..f0d3e21408d760cccbae645c0ca10dd471ba26fc --- /dev/null +++ b/lib/Zend/Validator/Exception/ExtensionNotLoadedException.php @@ -0,0 +1,14 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Exception; + +class ExtensionNotLoadedException extends RuntimeException +{} diff --git a/lib/Zend/Validator/Exception/InvalidArgumentException.php b/lib/Zend/Validator/Exception/InvalidArgumentException.php new file mode 100644 index 0000000000000000000000000000000000000000..76d68afcbe30aad12244cb29bce9a4a105f7a236 --- /dev/null +++ b/lib/Zend/Validator/Exception/InvalidArgumentException.php @@ -0,0 +1,15 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Exception; + +class InvalidArgumentException extends \InvalidArgumentException + implements ExceptionInterface +{} diff --git a/lib/Zend/Validator/Exception/InvalidMagicMimeFileException.php b/lib/Zend/Validator/Exception/InvalidMagicMimeFileException.php new file mode 100644 index 0000000000000000000000000000000000000000..3e65e1aa94306a8de16a163db93c91195d1eb413 --- /dev/null +++ b/lib/Zend/Validator/Exception/InvalidMagicMimeFileException.php @@ -0,0 +1,14 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Exception; + +class InvalidMagicMimeFileException extends InvalidArgumentException +{} diff --git a/lib/Zend/Validator/Exception/RuntimeException.php b/lib/Zend/Validator/Exception/RuntimeException.php new file mode 100644 index 0000000000000000000000000000000000000000..ab6f5515f8dc413bdf64f87865dbe88500ae4ac9 --- /dev/null +++ b/lib/Zend/Validator/Exception/RuntimeException.php @@ -0,0 +1,15 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Exception; + +class RuntimeException extends \RuntimeException + implements ExceptionInterface +{} diff --git a/lib/Zend/Validator/Explode.php b/lib/Zend/Validator/Explode.php new file mode 100644 index 0000000000000000000000000000000000000000..56c8876c6cc72f925433ea072801f21bcd0963b1 --- /dev/null +++ b/lib/Zend/Validator/Explode.php @@ -0,0 +1,171 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator; + +/** + * @category Zend + * @package Zend_Validate + */ +class Explode extends AbstractValidator +{ + const INVALID = 'explodeInvalid'; + + /** + * @var array + */ + protected $messageTemplates = array( + self::INVALID => "Invalid type given. String expected", + ); + + /** + * @var array + */ + protected $messageVariables = array(); + + /** + * @var string + */ + protected $valueDelimiter = ','; + + /** + * @var ValidatorInterface + */ + protected $validator; + + /** + * @var boolean + */ + protected $breakOnFirstFailure = false; + + /** + * Sets the delimiter string that the values will be split upon + * + * @param string $delimiter + * @return Explode + */ + public function setValueDelimiter($delimiter) + { + $this->valueDelimiter = $delimiter; + return $this; + } + + /** + * Returns the delimiter string that the values will be split upon + * + * @return string + */ + public function getValueDelimiter() + { + return $this->valueDelimiter; + } + + /** + * Sets the Validator for validating each value + * + * @param ValidatorInterface $validator + * @return Explode + */ + public function setValidator(ValidatorInterface $validator) + { + $this->validator = $validator; + return $this; + } + + /** + * Gets the Validator for validating each value + * + * @return ValidatorInterface + */ + public function getValidator() + { + return $this->validator; + } + + /** + * Set break on first failure setting + * + * @param boolean $break + * @return Explode + */ + public function setBreakOnFirstFailure($break) + { + $this->breakOnFirstFailure = (bool) $break; + return $this; + } + + /** + * Get break on first failure setting + * + * @return boolean + */ + public function isBreakOnFirstFailure() + { + return $this->breakOnFirstFailure; + } + + /** + * Defined by Zend_Validate_Interface + * + * Returns true if all values validate true + * + * @param string|array $value + * @return boolean + * @throws Exception\RuntimeException + */ + public function isValid($value) + { + if (!is_string($value) && !is_array($value)) { + $this->error(self::INVALID); + return false; + } + + $this->setValue($value); + + if (!is_array($value)) { + $delimiter = $this->getValueDelimiter(); + // Skip explode if delimiter is null, + // used when value is expected to be either an + // array when multiple values and a string for + // single values (ie. MultiCheckbox form behavior) + $values = (null !== $delimiter) + ? explode($this->valueDelimiter, $value) + : array($value); + } else { + $values = $value; + } + + $retval = true; + $messages = array(); + $validator = $this->getValidator(); + + if (!$validator) { + throw new Exception\RuntimeException(sprintf( + '%s expects a validator to be set; none given', + __METHOD__ + )); + } + + foreach ($values as $value) { + if (!$validator->isValid($value)) { + $messages[] = $validator->getMessages(); + $retval = false; + + if ($this->isBreakOnFirstFailure()) { + break; + } + } + } + + $this->abstractOptions['messages'] = $messages; + + return $retval; + } +} diff --git a/lib/Zend/Validator/File/Count.php b/lib/Zend/Validator/File/Count.php new file mode 100644 index 0000000000000000000000000000000000000000..dbc82dcf2c1b1fd43801eac488c353f3040e24f9 --- /dev/null +++ b/lib/Zend/Validator/File/Count.php @@ -0,0 +1,252 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\File; + +use Zend\Validator\AbstractValidator; +use Zend\Validator\Exception; + +/** + * Validator for counting all given files + * + * @category Zend + * @package Zend_Validate + */ +class Count extends AbstractValidator +{ + /**#@+ + * @const string Error constants + */ + const TOO_MANY = 'fileCountTooMany'; + const TOO_FEW = 'fileCountTooFew'; + /**#@-*/ + + /** + * @var array Error message templates + */ + protected $messageTemplates = array( + self::TOO_MANY => "Too many files, maximum '%max%' are allowed but '%count%' are given", + self::TOO_FEW => "Too few files, minimum '%min%' are expected but '%count%' are given", + ); + + /** + * @var array Error message template variables + */ + protected $messageVariables = array( + 'min' => array('options' => 'min'), + 'max' => array('options' => 'max'), + 'count' => 'count' + ); + + /** + * Actual filecount + * + * @var integer + */ + protected $count; + + /** + * Internal file array + * @var array + */ + protected $files; + + /** + * Options for this validator + * + * @var array + */ + protected $options = array( + 'min' => null, // Minimum file count, if null there is no minimum file count + 'max' => null, // Maximum file count, if null there is no maximum file count + ); + + /** + * Sets validator options + * + * Min limits the file count, when used with max=null it is the maximum file count + * It also accepts an array with the keys 'min' and 'max' + * + * If $options is a integer, it will be used as maximum file count + * As Array is accepts the following keys: + * 'min': Minimum filecount + * 'max': Maximum filecount + * + * @param integer|array|\Traversable $options Options for the adapter + */ + public function __construct($options = null) + { + if (is_string($options) || is_numeric($options)) { + $options = array('max' => $options); + } + + if (1 < func_num_args()) { + $options['min'] = func_get_arg(0); + $options['max'] = func_get_arg(1); + } + + parent::__construct($options); + } + + /** + * Returns the minimum file count + * + * @return integer + */ + public function getMin() + { + return $this->options['min']; + } + + /** + * Sets the minimum file count + * + * @param integer|array $min The minimum file count + * @return Count Provides a fluent interface + * @throws Exception\InvalidArgumentException When min is greater than max + */ + public function setMin($min) + { + if (is_array($min) and isset($min['min'])) { + $min = $min['min']; + } + + if (!is_string($min) and !is_numeric($min)) { + throw new Exception\InvalidArgumentException('Invalid options to validator provided'); + } + + $min = (integer) $min; + if (($this->getMax() !== null) && ($min > $this->getMax())) { + throw new Exception\InvalidArgumentException("The minimum must be less than or equal to the maximum file count, but $min >" + . " {$this->getMax()}"); + } + + $this->options['min'] = $min; + return $this; + } + + /** + * Returns the maximum file count + * + * @return integer + */ + public function getMax() + { + return $this->options['max']; + } + + /** + * Sets the maximum file count + * + * @param integer|array $max The maximum file count + * @return Count Provides a fluent interface + * @throws Exception\InvalidArgumentException When max is smaller than min + */ + public function setMax($max) + { + if (is_array($max) and isset($max['max'])) { + $max = $max['max']; + } + + if (!is_string($max) and !is_numeric($max)) { + throw new Exception\InvalidArgumentException('Invalid options to validator provided'); + } + + $max = (integer) $max; + if (($this->getMin() !== null) && ($max < $this->getMin())) { + throw new Exception\InvalidArgumentException("The maximum must be greater than or equal to the minimum file count, but " + . "$max < {$this->getMin()}"); + } + + $this->options['max'] = $max; + return $this; + } + + /** + * Adds a file for validation + * + * @param string|array $file + * @return Count + */ + public function addFile($file) + { + if (is_string($file)) { + $file = array($file); + } + + if (is_array($file)) { + foreach ($file as $name) { + if (!isset($this->files[$name]) && !empty($name)) { + $this->files[$name] = $name; + } + } + } + + return $this; + } + + /** + * Returns true if and only if the file count of all checked files is at least min and + * not bigger than max (when max is not null). Attention: When checking with set min you + * must give all files with the first call, otherwise you will get an false. + * + * @param string|array $value Filenames to check for count + * @param array $file File data from \Zend\File\Transfer\Transfer + * @return boolean + */ + public function isValid($value, $file = null) + { + if (($file !== null) && !array_key_exists('destination', $file)) { + $file['destination'] = dirname($value); + } + + if (($file !== null) && array_key_exists('tmp_name', $file)) { + $value = $file['destination'] . DIRECTORY_SEPARATOR . $file['name']; + } + + if (($file === null) || !empty($file['tmp_name'])) { + $this->addFile($value); + } + + $this->count = count($this->files); + if (($this->getMax() !== null) && ($this->count > $this->getMax())) { + return $this->throwError($file, self::TOO_MANY); + } + + if (($this->getMin() !== null) && ($this->count < $this->getMin())) { + return $this->throwError($file, self::TOO_FEW); + } + + return true; + } + + /** + * Throws an error of the given type + * + * @param string $file + * @param string $errorType + * @return false + */ + protected function throwError($file, $errorType) + { + if ($file !== null) { + if (is_array($file)) { + if (array_key_exists('name', $file)) { + $this->value = $file['name']; + } + } elseif (is_string($file)) { + $this->value = $file; + } + } + + $this->error($errorType); + return false; + } +} diff --git a/lib/Zend/Validator/File/Crc32.php b/lib/Zend/Validator/File/Crc32.php new file mode 100644 index 0000000000000000000000000000000000000000..cf55b00554751871e3019e17be407f841b01013e --- /dev/null +++ b/lib/Zend/Validator/File/Crc32.php @@ -0,0 +1,113 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\File; + +/** + * Validator for the crc32 hash of given files + * + * @category Zend + * @package Zend_Validate + */ +class Crc32 extends Hash +{ + /** + * @const string Error constants + */ + const DOES_NOT_MATCH = 'fileCrc32DoesNotMatch'; + const NOT_DETECTED = 'fileCrc32NotDetected'; + const NOT_FOUND = 'fileCrc32NotFound'; + + /** + * @var array Error message templates + */ + protected $messageTemplates = array( + self::DOES_NOT_MATCH => "File '%value%' does not match the given crc32 hashes", + self::NOT_DETECTED => "A crc32 hash could not be evaluated for the given file", + self::NOT_FOUND => "File '%value%' is not readable or does not exist", + ); + + /** + * Options for this validator + * + * @var string + */ + protected $options = array( + 'algorithm' => 'crc32', + 'hash' => null, + ); + + /** + * Returns all set crc32 hashes + * + * @return array + */ + public function getCrc32() + { + return $this->getHash(); + } + + /** + * Sets the crc32 hash for one or multiple files + * + * @param string|array $options + * @return Crc32 Provides a fluent interface + */ + public function setCrc32($options) + { + $this->setHash($options); + return $this; + } + + /** + * Adds the crc32 hash for one or multiple files + * + * @param string|array $options + * @return Crc32 Provides a fluent interface + */ + public function addCrc32($options) + { + $this->addHash($options); + return $this; + } + + /** + * Returns true if and only if the given file confirms the set hash + * + * @param string $value Filename to check for hash + * @param array $file File data from \Zend\File\Transfer\Transfer + * @return boolean + */ + public function isValid($value, $file = null) + { + if ($file === null) { + $file = array('name' => basename($value)); + } + + // Is file readable ? + if (false === stream_resolve_include_path($value)) { + return $this->throwError($file, self::NOT_FOUND); + } + + $hashes = array_unique(array_keys($this->getHash())); + $filehash = hash_file('crc32', $value); + if ($filehash === false) { + return $this->throwError($file, self::NOT_DETECTED); + } + + foreach ($hashes as $hash) { + if ($filehash === $hash) { + return true; + } + } + + return $this->throwError($file, self::DOES_NOT_MATCH); + } +} diff --git a/lib/Zend/Validator/File/ExcludeExtension.php b/lib/Zend/Validator/File/ExcludeExtension.php new file mode 100644 index 0000000000000000000000000000000000000000..57938d9416468116649d4c068ecce77942cb32c6 --- /dev/null +++ b/lib/Zend/Validator/File/ExcludeExtension.php @@ -0,0 +1,79 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\File; + +/** + * Validator for the excluding file extensions + * + * @category Zend + * @package Zend_Validate + */ +class ExcludeExtension extends Extension +{ + /** + * @const string Error constants + */ + const FALSE_EXTENSION = 'fileExcludeExtensionFalse'; + const NOT_FOUND = 'fileExcludeExtensionNotFound'; + + /** + * @var array Error message templates + */ + protected $messageTemplates = array( + self::FALSE_EXTENSION => "File '%value%' has a false extension", + self::NOT_FOUND => "File '%value%' is not readable or does not exist", + ); + + /** + * Returns true if and only if the file extension of $value is not included in the + * set extension list + * + * @param string $value Real file to check for extension + * @param array $file File data from \Zend\File\Transfer\Transfer + * @return boolean + */ + public function isValid($value, $file = null) + { + if ($file === null) { + $file = array('name' => basename($value)); + } + + // Is file readable ? + if (false === stream_resolve_include_path($value)) { + return $this->throwError($file, self::NOT_FOUND); + } + + if ($file !== null) { + $info['extension'] = substr($file['name'], strrpos($file['name'], '.') + 1); + } else { + $info = pathinfo($value); + } + + $extensions = $this->getExtension(); + + if ($this->getCase() and (!in_array($info['extension'], $extensions))) { + return true; + } elseif (!$this->getCase()) { + $found = false; + foreach ($extensions as $extension) { + if (strtolower($extension) == strtolower($info['extension'])) { + $found = true; + } + } + + if (!$found) { + return true; + } + } + + return $this->throwError($file, self::FALSE_EXTENSION); + } +} diff --git a/lib/Zend/Validator/File/ExcludeMimeType.php b/lib/Zend/Validator/File/ExcludeMimeType.php new file mode 100644 index 0000000000000000000000000000000000000000..62c086ae1640a24c6edaec4fdee125b909abf1c1 --- /dev/null +++ b/lib/Zend/Validator/File/ExcludeMimeType.php @@ -0,0 +1,97 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\File; + +use finfo; + +/** + * Validator for the mime type of a file + * + * @category Zend + * @package Zend_Validate + */ +class ExcludeMimeType extends MimeType +{ + const FALSE_TYPE = 'fileExcludeMimeTypeFalse'; + const NOT_DETECTED = 'fileExcludeMimeTypeNotDetected'; + const NOT_READABLE = 'fileExcludeMimeTypeNotReadable'; + + /** + * Returns true if the mimetype of the file does not matche the given ones. Also parts + * of mimetypes can be checked. If you give for example "image" all image + * mime types will not be accepted like "image/gif", "image/jpeg" and so on. + * + * @param string $value Real file to check for mimetype + * @param array $file File data from \Zend\File\Transfer\Transfer + * @return boolean + */ + public function isValid($value, $file = null) + { + if ($file === null) { + $file = array( + 'type' => null, + 'name' => $value, + ); + } + + // Is file readable ? + if (false === stream_resolve_include_path($value)) { + return $this->createError($file, self::NOT_READABLE); + } + + $mimefile = $this->getMagicFile(); + if (class_exists('finfo', false)) { + $const = defined('FILEINFO_MIME_TYPE') ? FILEINFO_MIME_TYPE : FILEINFO_MIME; + if (!$this->isMagicFileDisabled() && (!empty($mimefile) && empty($this->finfo))) { + $this->finfo = finfo_open($const, $mimefile); + } + + if (empty($this->finfo)) { + $this->finfo = finfo_open($const); + } + + $this->type = null; + if (!empty($this->finfo)) { + $this->type = finfo_file($this->finfo, $value); + } + } + + if (empty($this->type) && + (function_exists('mime_content_type') && ini_get('mime_magic.magicfile')) + ) { + $this->type = mime_content_type($value); + } + + if (empty($this->type) && $this->getHeaderCheck()) { + $this->type = $file['type']; + } + + if (empty($this->type)) { + return $this->createError($file, self::NOT_DETECTED); + } + + $mimetype = $this->getMimeType(true); + if (in_array($this->type, $mimetype)) { + return $this->createError($file, self::FALSE_TYPE); + } + + $types = explode('/', $this->type); + $types = array_merge($types, explode('-', $this->type)); + $types = array_merge($types, explode(';', $this->type)); + foreach ($mimetype as $mime) { + if (in_array($mime, $types)) { + return $this->createError($file, self::FALSE_TYPE); + } + } + + return true; + } +} diff --git a/lib/Zend/Validator/File/Exists.php b/lib/Zend/Validator/File/Exists.php new file mode 100644 index 0000000000000000000000000000000000000000..7631df7e4da0f8b145f5411835cc71b49a6fe38b --- /dev/null +++ b/lib/Zend/Validator/File/Exists.php @@ -0,0 +1,195 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\File; + +use Zend\Validator\AbstractValidator; +use Zend\Validator\Exception; + +/** + * Validator which checks if the file already exists in the directory + * + * @category Zend + * @package Zend_Validate + */ +class Exists extends AbstractValidator +{ + /** + * @const string Error constants + */ + const DOES_NOT_EXIST = 'fileExistsDoesNotExist'; + + /** + * @var array Error message templates + */ + protected $messageTemplates = array( + self::DOES_NOT_EXIST => "File '%value%' does not exist", + ); + + /** + * Options for this validator + * + * @var array + */ + protected $options = array( + 'directory' => null, // internal list of directories + ); + + /** + * @var array Error message template variables + */ + protected $messageVariables = array( + 'directory' => array('options' => 'directory'), + ); + + /** + * Sets validator options + * + * @param string|array|\Traversable $options + */ + public function __construct($options = null) + { + if (is_string($options)) { + $options = explode(',', $options); + } + + if (is_array($options) && !array_key_exists('directory', $options)) { + $options = array('directory' => $options); + } + + parent::__construct($options); + } + + /** + * Returns the set file directories which are checked + * + * @param boolean $asArray Returns the values as array, when false an concatenated string is returned + * @return string + */ + public function getDirectory($asArray = false) + { + $asArray = (bool) $asArray; + $directory = (string) $this->options['directory']; + if ($asArray) { + $directory = explode(',', $directory); + } + + return $directory; + } + + /** + * Sets the file directory which will be checked + * + * @param string|array $directory The directories to validate + * @return Extension Provides a fluent interface + */ + public function setDirectory($directory) + { + $this->options['directory'] = null; + $this->addDirectory($directory); + return $this; + } + + /** + * Adds the file directory which will be checked + * + * @param string|array $directory The directory to add for validation + * @return Extension Provides a fluent interface + * @throws Exception\InvalidArgumentException + */ + public function addDirectory($directory) + { + $directories = $this->getDirectory(true); + + if (is_string($directory)) { + $directory = explode(',', $directory); + } elseif (!is_array($directory)) { + throw new Exception\InvalidArgumentException('Invalid options to validator provided'); + } + + foreach ($directory as $content) { + if (empty($content) || !is_string($content)) { + continue; + } + + $directories[] = trim($content); + } + $directories = array_unique($directories); + + // Sanity check to ensure no empty values + foreach ($directories as $key => $dir) { + if (empty($dir)) { + unset($directories[$key]); + } + } + + $this->options['directory'] = implode(',', $directories); + + return $this; + } + + /** + * Returns true if and only if the file already exists in the set directories + * + * @param string $value Real file to check for existence + * @param array $file File data from \Zend\File\Transfer\Transfer + * @return boolean + */ + public function isValid($value, $file = null) + { + $directories = $this->getDirectory(true); + if (($file !== null) and (!empty($file['destination']))) { + $directories[] = $file['destination']; + } elseif (!isset($file['name'])) { + $file['name'] = $value; + } + + $check = false; + foreach ($directories as $directory) { + if (empty($directory)) { + continue; + } + + $check = true; + if (!file_exists($directory . DIRECTORY_SEPARATOR . $file['name'])) { + return $this->throwError($file, self::DOES_NOT_EXIST); + } + } + + if (!$check) { + return $this->throwError($file, self::DOES_NOT_EXIST); + } + + return true; + } + + /** + * Throws an error of the given type + * + * @param string $file + * @param string $errorType + * @return false + */ + protected function throwError($file, $errorType) + { + if ($file !== null) { + if (is_array($file)) { + if (array_key_exists('name', $file)) { + $this->value = basename($file['name']); + } + } elseif (is_string($file)) { + $this->value = basename($file); + } + } + + $this->error($errorType); + return false; + } +} diff --git a/lib/Zend/Validator/File/Extension.php b/lib/Zend/Validator/File/Extension.php new file mode 100644 index 0000000000000000000000000000000000000000..8b59d503f123914e928e6e7ad4ab33e9106c1fe9 --- /dev/null +++ b/lib/Zend/Validator/File/Extension.php @@ -0,0 +1,235 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\File; + +use Traversable; +use Zend\Stdlib\ArrayUtils; +use Zend\Validator\AbstractValidator; + +/** + * Validator for the file extension of a file + * + * @category Zend + * @package Zend_Validate + */ +class Extension extends AbstractValidator +{ + /** + * @const string Error constants + */ + const FALSE_EXTENSION = 'fileExtensionFalse'; + const NOT_FOUND = 'fileExtensionNotFound'; + + /** + * @var array Error message templates + */ + protected $messageTemplates = array( + self::FALSE_EXTENSION => "File '%value%' has a false extension", + self::NOT_FOUND => "File '%value%' is not readable or does not exist", + ); + + /** + * Options for this validator + * + * @var array + */ + protected $options = array( + 'case' => false, // Validate case sensitive + 'extension' => '', // List of extensions + ); + + /** + * @var array Error message template variables + */ + protected $messageVariables = array( + 'extension' => array('options' => 'extension'), + ); + + /** + * Sets validator options + * + * @param string|array|\Traversable $options + */ + public function __construct($options = null) + { + if ($options instanceof Traversable) { + $options = ArrayUtils::iteratorToArray($options); + } + + $case = null; + if (1 < func_num_args()) { + $case = func_get_arg(1); + } + + if (is_array($options)) { + if (isset($options['case'])) { + $case = $options['case']; + unset($options['case']); + } + + if (!array_key_exists('extension', $options)) { + $options = array('extension' => $options); + } + } else { + $options = array('extension' => $options); + } + + if ($case !== null) { + $options['case'] = $case; + } + + parent::__construct($options); + } + + /** + * Returns the case option + * + * @return boolean + */ + public function getCase() + { + return $this->options['case']; + } + + /** + * Sets the case to use + * + * @param boolean $case + * @return Extension Provides a fluent interface + */ + public function setCase($case) + { + $this->options['case'] = (boolean) $case; + return $this; + } + + /** + * Returns the set file extension + * + * @return array + */ + public function getExtension() + { + $extension = explode(',', $this->options['extension']); + + return $extension; + } + + /** + * Sets the file extensions + * + * @param string|array $extension The extensions to validate + * @return Extension Provides a fluent interface + */ + public function setExtension($extension) + { + $this->options['extension'] = null; + $this->addExtension($extension); + return $this; + } + + /** + * Adds the file extensions + * + * @param string|array $extension The extensions to add for validation + * @return Extension Provides a fluent interface + */ + public function addExtension($extension) + { + $extensions = $this->getExtension(); + if (is_string($extension)) { + $extension = explode(',', $extension); + } + + foreach ($extension as $content) { + if (empty($content) || !is_string($content)) { + continue; + } + + $extensions[] = trim($content); + } + + $extensions = array_unique($extensions); + + // Sanity check to ensure no empty values + foreach ($extensions as $key => $ext) { + if (empty($ext)) { + unset($extensions[$key]); + } + } + + $this->options['extension'] = implode(',', $extensions); + return $this; + } + + /** + * Returns true if and only if the file extension of $value is included in the + * set extension list + * + * @param string $value Real file to check for extension + * @param array $file File data from \Zend\File\Transfer\Transfer + * @return boolean + */ + public function isValid($value, $file = null) + { + if ($file === null) { + $file = array('name' => basename($value)); + } + + // Is file readable ? + if (false === stream_resolve_include_path($value)) { + return $this->throwError($file, self::NOT_FOUND); + } + + if ($file !== null) { + $info['extension'] = substr($file['name'], strrpos($file['name'], '.') + 1); + } else { + $info = pathinfo($value); + } + + $extensions = $this->getExtension(); + + if ($this->getCase() && (in_array($info['extension'], $extensions))) { + return true; + } elseif (!$this->getCase()) { + foreach ($extensions as $extension) { + if (strtolower($extension) == strtolower($info['extension'])) { + return true; + } + } + } + + return $this->throwError($file, self::FALSE_EXTENSION); + } + + /** + * Throws an error of the given type + * + * @param string $file + * @param string $errorType + * @return false + */ + protected function throwError($file, $errorType) + { + if ($file !== null) { + if (is_array($file)) { + if (array_key_exists('name', $file)) { + $this->value = $file['name']; + } + } elseif (is_string($file)) { + $this->value = $file; + } + } + + $this->error($errorType); + return false; + } +} diff --git a/lib/Zend/Validator/File/FilesSize.php b/lib/Zend/Validator/File/FilesSize.php new file mode 100644 index 0000000000000000000000000000000000000000..511e466eadcf104b04b0c81ae922cd8da9838c4c --- /dev/null +++ b/lib/Zend/Validator/File/FilesSize.php @@ -0,0 +1,151 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\File; + +use Traversable; +use Zend\Stdlib\ArrayUtils; +use Zend\Stdlib\ErrorHandler; +use Zend\Validator\Exception; + +/** + * Validator for the size of all files which will be validated in sum + * + * @category Zend + * @package Zend_Validate + */ +class FilesSize extends Size +{ + /** + * @const string Error constants + */ + const TOO_BIG = 'fileFilesSizeTooBig'; + const TOO_SMALL = 'fileFilesSizeTooSmall'; + const NOT_READABLE = 'fileFilesSizeNotReadable'; + + /** + * @var array Error message templates + */ + protected $messageTemplates = array( + self::TOO_BIG => "All files in sum should have a maximum size of '%max%' but '%size%' were detected", + self::TOO_SMALL => "All files in sum should have a minimum size of '%min%' but '%size%' were detected", + self::NOT_READABLE => "One or more files can not be read", + ); + + /** + * Internal file array + * + * @var array + */ + protected $files; + + /** + * Sets validator options + * + * Min limits the used disk space for all files, when used with max=null it is the maximum file size + * It also accepts an array with the keys 'min' and 'max' + * + * @param integer|array|Traversable $options Options for this validator + * @throws \Zend\Validator\Exception\InvalidArgumentException + */ + public function __construct($options = null) + { + $this->files = array(); + $this->setSize(0); + + if ($options instanceof Traversable) { + $options = ArrayUtils::iteratorToArray($options); + } elseif (is_scalar($options)) { + $options = array('max' => $options); + } elseif (!is_array($options)) { + throw new Exception\InvalidArgumentException('Invalid options to validator provided'); + } + + if (1 < func_num_args()) { + $argv = func_get_args(); + array_shift($argv); + $options['max'] = array_shift($argv); + if (!empty($argv)) { + $options['useByteString'] = array_shift($argv); + } + } + + parent::__construct($options); + } + + /** + * Returns true if and only if the disk usage of all files is at least min and + * not bigger than max (when max is not null). + * + * @param string|array $value Real file to check for size + * @param array $file File data from \Zend\File\Transfer\Transfer + * @return boolean + */ + public function isValid($value, $file = null) + { + if (is_string($value)) { + $value = array($value); + } + + $min = $this->getMin(true); + $max = $this->getMax(true); + $size = $this->getSize(); + foreach ($value as $files) { + // Is file readable ? + if (false === stream_resolve_include_path($files)) { + $this->throwError($file, self::NOT_READABLE); + continue; + } + + if (!isset($this->files[$files])) { + $this->files[$files] = $files; + } else { + // file already counted... do not count twice + continue; + } + + // limited to 2GB files + ErrorHandler::start(); + $size += filesize($files); + ErrorHandler::stop(); + $this->size = $size; + if (($max !== null) && ($max < $size)) { + if ($this->getByteString()) { + $this->options['max'] = $this->toByteString($max); + $this->size = $this->toByteString($size); + $this->throwError($file, self::TOO_BIG); + $this->options['max'] = $max; + $this->size = $size; + } else { + $this->throwError($file, self::TOO_BIG); + } + } + } + + // Check that aggregate files are >= minimum size + if (($min !== null) && ($size < $min)) { + if ($this->getByteString()) { + $this->options['min'] = $this->toByteString($min); + $this->size = $this->toByteString($size); + $this->throwError($file, self::TOO_SMALL); + $this->options['min'] = $min; + $this->size = $size; + } else { + $this->throwError($file, self::TOO_SMALL); + } + } + + if (count($this->getMessages()) > 0) { + return false; + } + + return true; + } +} diff --git a/lib/Zend/Validator/File/Hash.php b/lib/Zend/Validator/File/Hash.php new file mode 100644 index 0000000000000000000000000000000000000000..d51efe04d90c07aa54dcb46830d417e62b8e80ec --- /dev/null +++ b/lib/Zend/Validator/File/Hash.php @@ -0,0 +1,185 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\File; + +use Zend\Validator\AbstractValidator; +use Zend\Validator\Exception; + +/** + * Validator for the hash of given files + * + * @category Zend + * @package Zend_Validate + */ +class Hash extends AbstractValidator +{ + /** + * @const string Error constants + */ + const DOES_NOT_MATCH = 'fileHashDoesNotMatch'; + const NOT_DETECTED = 'fileHashHashNotDetected'; + const NOT_FOUND = 'fileHashNotFound'; + + /** + * @var array Error message templates + */ + protected $messageTemplates = array( + self::DOES_NOT_MATCH => "File '%value%' does not match the given hashes", + self::NOT_DETECTED => "A hash could not be evaluated for the given file", + self::NOT_FOUND => "File '%value%' is not readable or does not exist" + ); + + /** + * Options for this validator + * + * @var string + */ + protected $options = array( + 'algorithm' => 'crc32', + 'hash' => null, + ); + + /** + * Sets validator options + * + * @param string|array $options + */ + public function __construct($options = null) + { + if (is_scalar($options) || + (is_array($options) && !array_key_exists('hash', $options))) { + $options = array('hash' => $options); + } + + if (1 < func_num_args()) { + $options['algorithm'] = func_get_arg(1); + } + + parent::__construct($options); + } + + /** + * Returns the set hash values as array, the hash as key and the algorithm the value + * + * @return array + */ + public function getHash() + { + return $this->options['hash']; + } + + /** + * Sets the hash for one or multiple files + * + * @param string|array $options + * @return Hash Provides a fluent interface + */ + public function setHash($options) + { + $this->options['hash'] = null; + $this->addHash($options); + + return $this; + } + + /** + * Adds the hash for one or multiple files + * + * @param string|array $options + * @return Hash Provides a fluent interface + * @throws Exception\InvalidArgumentException + */ + public function addHash($options) + { + if (is_string($options)) { + $options = array($options); + } elseif (!is_array($options)) { + throw new Exception\InvalidArgumentException("False parameter given"); + } + + $known = hash_algos(); + if (!isset($options['algorithm'])) { + $algorithm = $this->options['algorithm']; + } else { + $algorithm = $options['algorithm']; + unset($options['algorithm']); + } + + if (!in_array($algorithm, $known)) { + throw new Exception\InvalidArgumentException("Unknown algorithm '{$algorithm}'"); + } + + foreach ($options as $value) { + $this->options['hash'][$value] = $algorithm; + } + + return $this; + } + + /** + * Returns true if and only if the given file confirms the set hash + * + * @param string $value Filename to check for hash + * @param array $file File data from \Zend\File\Transfer\Transfer + * @return boolean + */ + public function isValid($value, $file = null) + { + if ($file === null) { + $file = array('name' => basename($value)); + } + + // Is file readable ? + if (false === stream_resolve_include_path($value)) { + return $this->throwError($file, self::NOT_FOUND); + } + + $algos = array_unique(array_values($this->getHash())); + $hashes = array_unique(array_keys($this->getHash())); + foreach ($algos as $algorithm) { + $filehash = hash_file($algorithm, $value); + if ($filehash === false) { + return $this->throwError($file, self::NOT_DETECTED); + } + + foreach ($hashes as $hash) { + if ($filehash === $hash) { + return true; + } + } + } + + return $this->throwError($file, self::DOES_NOT_MATCH); + } + + /** + * Throws an error of the given type + * + * @param string $file + * @param string $errorType + * @return false + */ + protected function throwError($file, $errorType) + { + if ($file !== null) { + if (is_array($file)) { + if (array_key_exists('name', $file)) { + $this->value = $file['name']; + } + } elseif (is_string($file)) { + $this->value = $file; + } + } + + $this->error($errorType); + return false; + } +} diff --git a/lib/Zend/Validator/File/ImageSize.php b/lib/Zend/Validator/File/ImageSize.php new file mode 100644 index 0000000000000000000000000000000000000000..70dfdc6b4d10564da4444f1e2f7d8d69420d6ee4 --- /dev/null +++ b/lib/Zend/Validator/File/ImageSize.php @@ -0,0 +1,396 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\File; + +use Zend\Stdlib\ErrorHandler; +use Zend\Validator\AbstractValidator; +use Zend\Validator\Exception; + +/** + * Validator for the image size of a image file + * + * @category Zend + * @package Zend_Validate + */ +class ImageSize extends AbstractValidator +{ + /** + * @const string Error constants + */ + const WIDTH_TOO_BIG = 'fileImageSizeWidthTooBig'; + const WIDTH_TOO_SMALL = 'fileImageSizeWidthTooSmall'; + const HEIGHT_TOO_BIG = 'fileImageSizeHeightTooBig'; + const HEIGHT_TOO_SMALL = 'fileImageSizeHeightTooSmall'; + const NOT_DETECTED = 'fileImageSizeNotDetected'; + const NOT_READABLE = 'fileImageSizeNotReadable'; + + /** + * @var array Error message template + */ + protected $messageTemplates = array( + self::WIDTH_TOO_BIG => "Maximum allowed width for image '%value%' should be '%maxwidth%' but '%width%' detected", + self::WIDTH_TOO_SMALL => "Minimum expected width for image '%value%' should be '%minwidth%' but '%width%' detected", + self::HEIGHT_TOO_BIG => "Maximum allowed height for image '%value%' should be '%maxheight%' but '%height%' detected", + self::HEIGHT_TOO_SMALL => "Minimum expected height for image '%value%' should be '%minheight%' but '%height%' detected", + self::NOT_DETECTED => "The size of image '%value%' could not be detected", + self::NOT_READABLE => "File '%value%' is not readable or does not exist", + ); + + /** + * @var array Error message template variables + */ + protected $messageVariables = array( + 'minwidth' => array('options' => 'minWidth'), + 'maxwidth' => array('options' => 'maxWidth'), + 'minheight' => array('options' => 'minHeight'), + 'maxheight' => array('options' => 'maxHeight'), + 'width' => 'width', + 'height' => 'height' + ); + + /** + * Detected width + * + * @var integer + */ + protected $width; + + /** + * Detected height + * + * @var integer + */ + protected $height; + + /** + * Options for this validator + * + * @var array + */ + protected $options = array( + 'minWidth' => null, // Minimum image width + 'maxWidth' => null, // Maximum image width + 'minHeight' => null, // Minimum image height + 'maxHeight' => null, // Maximum image height + ); + + /** + * Sets validator options + * + * Accepts the following option keys: + * - minheight + * - minwidth + * - maxheight + * - maxwidth + * + * @param array|\Traversable $options + */ + public function __construct($options = null) + { + if (1 < func_num_args()) { + if (!is_array($options)) { + $options = array('minWidth' => $options); + } + + $argv = func_get_args(); + array_shift($argv); + $options['minHeight'] = array_shift($argv); + if (!empty($argv)) { + $options['maxWidth'] = array_shift($argv); + if (!empty($argv)) { + $options['maxHeight'] = array_shift($argv); + } + } + } + + parent::__construct($options); + } + + /** + * Returns the minimum allowed width + * + * @return integer + */ + public function getMinWidth() + { + return $this->options['minWidth']; + } + + /** + * Sets the minimum allowed width + * + * @param integer $minWidth + * @return ImageSize Provides a fluid interface + * @throws Exception\InvalidArgumentException When minwidth is greater than maxwidth + */ + public function setMinWidth($minWidth) + { + if (($this->getMaxWidth() !== null) && ($minWidth > $this->getMaxWidth())) { + throw new Exception\InvalidArgumentException("The minimum image width must be less than or equal to the " + . " maximum image width, but {$minWidth} > {$this->getMaxWidth()}"); + } + + $this->options['minWidth'] = (int) $minWidth; + return $this; + } + + /** + * Returns the maximum allowed width + * + * @return integer + */ + public function getMaxWidth() + { + return $this->options['maxWidth']; + } + + /** + * Sets the maximum allowed width + * + * @param integer $maxWidth + * @return ImageSize Provides a fluid interface + * @throws Exception\InvalidArgumentException When maxwidth is less than minwidth + */ + public function setMaxWidth($maxWidth) + { + if (($this->getMinWidth() !== null) && ($maxWidth < $this->getMinWidth())) { + throw new Exception\InvalidArgumentException("The maximum image width must be greater than or equal to the " + . "minimum image width, but {$maxWidth} < {$this->getMinWidth()}"); + } + + $this->options['maxWidth'] = (int) $maxWidth; + return $this; + } + + /** + * Returns the minimum allowed height + * + * @return integer + */ + public function getMinHeight() + { + return $this->options['minHeight']; + } + + /** + * Sets the minimum allowed height + * + * @param integer $minHeight + * @return ImageSize Provides a fluid interface + * @throws Exception\InvalidArgumentException When minheight is greater than maxheight + */ + public function setMinHeight($minHeight) + { + if (($this->getMaxHeight() !== null) && ($minHeight > $this->getMaxHeight())) { + throw new Exception\InvalidArgumentException("The minimum image height must be less than or equal to the " + . " maximum image height, but {$minHeight} > {$this->getMaxHeight()}"); + } + + $this->options['minHeight'] = (int) $minHeight; + return $this; + } + + /** + * Returns the maximum allowed height + * + * @return integer + */ + public function getMaxHeight() + { + return $this->options['maxHeight']; + } + + /** + * Sets the maximum allowed height + * + * @param integer $maxHeight + * @return ImageSize Provides a fluid interface + * @throws Exception\InvalidArgumentException When maxheight is less than minheight + */ + public function setMaxHeight($maxHeight) + { + if (($this->getMinHeight() !== null) && ($maxHeight < $this->getMinHeight())) { + throw new Exception\InvalidArgumentException("The maximum image height must be greater than or equal to the " + . "minimum image height, but {$maxHeight} < {$this->getMinHeight()}"); + } + + $this->options['maxHeight'] = (int) $maxHeight; + return $this; + } + + /** + * Returns the set minimum image sizes + * + * @return array + */ + public function getImageMin() + { + return array('minWidth' => $this->getMinWidth(), 'minHeight' => $this->getMinHeight()); + } + + /** + * Returns the set maximum image sizes + * + * @return array + */ + public function getImageMax() + { + return array('maxWidth' => $this->getMaxWidth(), 'maxHeight' => $this->getMaxHeight()); + } + + /** + * Returns the set image width sizes + * + * @return array + */ + public function getImageWidth() + { + return array('minWidth' => $this->getMinWidth(), 'maxWidth' => $this->getMaxWidth()); + } + + /** + * Returns the set image height sizes + * + * @return array + */ + public function getImageHeight() + { + return array('minHeight' => $this->getMinHeight(), 'maxHeight' => $this->getMaxHeight()); + } + + /** + * Sets the minimum image size + * + * @param array $options The minimum image dimensions + * @return ImageSize Provides a fluent interface + */ + public function setImageMin($options) + { + $this->setOptions($options); + return $this; + } + + /** + * Sets the maximum image size + * + * @param array|\Traversable $options The maximum image dimensions + * @return ImageSize Provides a fluent interface + */ + public function setImageMax($options) + { + $this->setOptions($options); + return $this; + } + + /** + * Sets the minimum and maximum image width + * + * @param array $options The image width dimensions + * @return ImageSize Provides a fluent interface + */ + public function setImageWidth($options) + { + $this->setImageMin($options); + $this->setImageMax($options); + + return $this; + } + + /** + * Sets the minimum and maximum image height + * + * @param array $options The image height dimensions + * @return ImageSize Provides a fluent interface + */ + public function setImageHeight($options) + { + $this->setImageMin($options); + $this->setImageMax($options); + + return $this; + } + + /** + * Returns true if and only if the image size of $value is at least min and + * not bigger than max + * + * @param string $value Real file to check for image size + * @param array $file File data from \Zend\File\Transfer\Transfer + * @return boolean + */ + public function isValid($value, $file = null) + { + if ($file === null) { + $file = array('name' => basename($value)); + } + + // Is file readable ? + if (false === stream_resolve_include_path($value)) { + return $this->throwError($file, self::NOT_READABLE); + } + + ErrorHandler::start(); + $size = getimagesize($value); + ErrorHandler::stop(); + $this->setValue($file); + + if (empty($size) or ($size[0] === 0) or ($size[1] === 0)) { + return $this->throwError($file, self::NOT_DETECTED); + } + + $this->width = $size[0]; + $this->height = $size[1]; + if ($this->width < $this->getMinWidth()) { + $this->throwError($file, self::WIDTH_TOO_SMALL); + } + + if (($this->getMaxWidth() !== null) and ($this->getMaxWidth() < $this->width)) { + $this->throwError($file, self::WIDTH_TOO_BIG); + } + + if ($this->height < $this->getMinHeight()) { + $this->throwError($file, self::HEIGHT_TOO_SMALL); + } + + if (($this->getMaxHeight() !== null) and ($this->getMaxHeight() < $this->height)) { + $this->throwError($file, self::HEIGHT_TOO_BIG); + } + + if (count($this->getMessages()) > 0) { + return false; + } + + return true; + } + + /** + * Throws an error of the given type + * + * @param string $file + * @param string $errorType + * @return false + */ + protected function throwError($file, $errorType) + { + if ($file !== null) { + if (is_array($file)) { + if (array_key_exists('name', $file)) { + $this->value = $file['name']; + } + } elseif (is_string($file)) { + $this->value = $file; + } + } + + $this->error($errorType); + return false; + } +} diff --git a/lib/Zend/Validator/File/IsCompressed.php b/lib/Zend/Validator/File/IsCompressed.php new file mode 100644 index 0000000000000000000000000000000000000000..19656492166db54ce40320d32df316ef1b7c60c8 --- /dev/null +++ b/lib/Zend/Validator/File/IsCompressed.php @@ -0,0 +1,130 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\File; + +use Traversable; +use Zend\Stdlib\ArrayUtils; + +/** + * Validator which checks if the file already exists in the directory + * + * @category Zend + * @package Zend_Validate + */ +class IsCompressed extends MimeType +{ + /** + * @const string Error constants + */ + const FALSE_TYPE = 'fileIsCompressedFalseType'; + const NOT_DETECTED = 'fileIsCompressedNotDetected'; + const NOT_READABLE = 'fileIsCompressedNotReadable'; + + /** + * @var array Error message templates + */ + protected $messageTemplates = array( + self::FALSE_TYPE => "File '%value%' is not compressed, '%type%' detected", + self::NOT_DETECTED => "The mimetype of file '%value%' could not be detected", + self::NOT_READABLE => "File '%value%' is not readable or does not exist", + ); + + /** + * Sets validator options + * + * @param string|array|Traversable $options + */ + public function __construct($options = array()) + { + // http://de.wikipedia.org/wiki/Liste_von_Dateiendungen + $default = array( + 'application/arj', + 'application/gnutar', + 'application/lha', + 'application/lzx', + 'application/vnd.ms-cab-compressed', + 'application/x-ace-compressed', + 'application/x-arc', + 'application/x-archive', + 'application/x-arj', + 'application/x-bzip', + 'application/x-bzip2', + 'application/x-cab-compressed', + 'application/x-compress', + 'application/x-compressed', + 'application/x-cpio', + 'application/x-debian-package', + 'application/x-eet', + 'application/x-gzip', + 'application/x-java-pack200', + 'application/x-lha', + 'application/x-lharc', + 'application/x-lzh', + 'application/x-lzma', + 'application/x-lzx', + 'application/x-rar', + 'application/x-sit', + 'application/x-stuffit', + 'application/x-tar', + 'application/zip', + 'application/zoo', + 'multipart/x-gzip', + ); + + if ($options instanceof Traversable) { + $options = ArrayUtils::iteratorToArray($options); + } + + if (empty($options)) { + $options = array('mimeType' => $default); + } + + parent::__construct($options); + } + + /** + * Throws an error of the given type + * Duplicates parent method due to OOP Problem with late static binding in PHP 5.2 + * + * @param string $file + * @param string $errorType + * @return false + */ + protected function createError($file, $errorType) + { + if ($file !== null) { + if (is_array($file)) { + if (array_key_exists('name', $file)) { + $file = $file['name']; + } + } + + if (is_string($file)) { + $this->value = basename($file); + } + } + + switch ($errorType) { + case MimeType::FALSE_TYPE : + $errorType = self::FALSE_TYPE; + break; + case MimeType::NOT_DETECTED : + $errorType = self::NOT_DETECTED; + break; + case MimeType::NOT_READABLE : + $errorType = self::NOT_READABLE; + break; + } + + $this->error($errorType); + return false; + } +} diff --git a/lib/Zend/Validator/File/IsImage.php b/lib/Zend/Validator/File/IsImage.php new file mode 100644 index 0000000000000000000000000000000000000000..9acb63e3d7b3af78b87ab7b7f6c592610b011a25 --- /dev/null +++ b/lib/Zend/Validator/File/IsImage.php @@ -0,0 +1,155 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\File; + +use Traversable; +use Zend\Stdlib\ArrayUtils; + +/** + * Validator which checks if the file already exists in the directory + * + * @category Zend + * @package Zend_Validate + */ +class IsImage extends MimeType +{ + /** + * @const string Error constants + */ + const FALSE_TYPE = 'fileIsImageFalseType'; + const NOT_DETECTED = 'fileIsImageNotDetected'; + const NOT_READABLE = 'fileIsImageNotReadable'; + + /** + * @var array Error message templates + */ + protected $messageTemplates = array( + self::FALSE_TYPE => "File '%value%' is no image, '%type%' detected", + self::NOT_DETECTED => "The mimetype of file '%value%' could not be detected", + self::NOT_READABLE => "File '%value%' is not readable or does not exist", + ); + + /** + * Sets validator options + * + * @param array|Traversable|string $options + */ + public function __construct($options = array()) + { + // http://de.wikipedia.org/wiki/Liste_von_Dateiendungen + // http://www.iana.org/assignments/media-types/image/ + $default = array( + 'application/cdf', + 'application/dicom', + 'application/fractals', + 'application/postscript', + 'application/vnd.hp-hpgl', + 'application/vnd.oasis.opendocument.graphics', + 'application/x-cdf', + 'application/x-cmu-raster', + 'application/x-ima', + 'application/x-inventor', + 'application/x-koan', + 'application/x-portable-anymap', + 'application/x-world-x-3dmf', + 'image/bmp', + 'image/c', + 'image/cgm', + 'image/fif', + 'image/gif', + 'image/jpeg', + 'image/jpm', + 'image/jpx', + 'image/jp2', + 'image/naplps', + 'image/pjpeg', + 'image/png', + 'image/svg', + 'image/svg+xml', + 'image/tiff', + 'image/vnd.adobe.photoshop', + 'image/vnd.djvu', + 'image/vnd.fpx', + 'image/vnd.net-fpx', + 'image/x-cmu-raster', + 'image/x-cmx', + 'image/x-coreldraw', + 'image/x-cpi', + 'image/x-emf', + 'image/x-ico', + 'image/x-icon', + 'image/x-jg', + 'image/x-ms-bmp', + 'image/x-niff', + 'image/x-pict', + 'image/x-pcx', + 'image/x-png', + 'image/x-portable-anymap', + 'image/x-portable-bitmap', + 'image/x-portable-greymap', + 'image/x-portable-pixmap', + 'image/x-quicktime', + 'image/x-rgb', + 'image/x-tiff', + 'image/x-unknown', + 'image/x-windows-bmp', + 'image/x-xpmi', + ); + + if ($options instanceof Traversable) { + $options = ArrayUtils::iteratorToArray($options); + } + + if (empty($options)) { + $options = array('mimeType' => $default); + } + + parent::__construct($options); + } + + /** + * Throws an error of the given type + * Duplicates parent method due to OOP Problem with late static binding in PHP 5.2 + * + * @param string $file + * @param string $errorType + * @return false + */ + protected function createError($file, $errorType) + { + if ($file !== null) { + if (is_array($file)) { + if (array_key_exists('name', $file)) { + $file = $file['name']; + } + } + + if (is_string($file)) { + $this->value = basename($file); + } + } + + switch ($errorType) { + case MimeType::FALSE_TYPE : + $errorType = self::FALSE_TYPE; + break; + case MimeType::NOT_DETECTED : + $errorType = self::NOT_DETECTED; + break; + case MimeType::NOT_READABLE : + $errorType = self::NOT_READABLE; + break; + } + + $this->error($errorType); + return false; + } +} diff --git a/lib/Zend/Validator/File/Md5.php b/lib/Zend/Validator/File/Md5.php new file mode 100644 index 0000000000000000000000000000000000000000..38bbf4323b8eed8dbd160d8963c78d9d7277924f --- /dev/null +++ b/lib/Zend/Validator/File/Md5.php @@ -0,0 +1,113 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\File; + +/** + * Validator for the md5 hash of given files + * + * @category Zend + * @package Zend_Validate + */ +class Md5 extends Hash +{ + /** + * @const string Error constants + */ + const DOES_NOT_MATCH = 'fileMd5DoesNotMatch'; + const NOT_DETECTED = 'fileMd5NotDetected'; + const NOT_FOUND = 'fileMd5NotFound'; + + /** + * @var array Error message templates + */ + protected $messageTemplates = array( + self::DOES_NOT_MATCH => "File '%value%' does not match the given md5 hashes", + self::NOT_DETECTED => "A md5 hash could not be evaluated for the given file", + self::NOT_FOUND => "File '%value%' is not readable or does not exist", + ); + + /** + * Options for this validator + * + * @var string + */ + protected $options = array( + 'algorithm' => 'md5', + 'hash' => null, + ); + + /** + * Returns all set md5 hashes + * + * @return array + */ + public function getMd5() + { + return $this->getHash(); + } + + /** + * Sets the md5 hash for one or multiple files + * + * @param string|array $options + * @return Hash Provides a fluent interface + */ + public function setMd5($options) + { + $this->setHash($options); + return $this; + } + + /** + * Adds the md5 hash for one or multiple files + * + * @param string|array $options + * @return Hash Provides a fluent interface + */ + public function addMd5($options) + { + $this->addHash($options); + return $this; + } + + /** + * Returns true if and only if the given file confirms the set hash + * + * @param string $value Filename to check for hash + * @param array $file File data from \Zend\File\Transfer\Transfer + * @return boolean + */ + public function isValid($value, $file = null) + { + if ($file === null) { + $file = array('name' => basename($value)); + } + + // Is file readable ? + if (false === stream_resolve_include_path($value)) { + return $this->throwError($file, self::NOT_FOUND); + } + + $hashes = array_unique(array_keys($this->getHash())); + $filehash = hash_file('md5', $value); + if ($filehash === false) { + return $this->throwError($file, self::NOT_DETECTED); + } + + foreach ($hashes as $hash) { + if ($filehash === $hash) { + return true; + } + } + + return $this->throwError($file, self::DOES_NOT_MATCH); + } +} diff --git a/lib/Zend/Validator/File/MimeType.php b/lib/Zend/Validator/File/MimeType.php new file mode 100644 index 0000000000000000000000000000000000000000..cc4ffff6428b473126aabc6ce9dfe4fe9e4df4ac --- /dev/null +++ b/lib/Zend/Validator/File/MimeType.php @@ -0,0 +1,441 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\File; + +use Traversable; +use Zend\Stdlib\ArrayUtils; +use Zend\Stdlib\ErrorHandler; +use Zend\Validator\AbstractValidator; +use Zend\Validator\Exception; + +/** + * Validator for the mime type of a file + * + * @category Zend + * @package Zend_Validate + */ +class MimeType extends AbstractValidator +{ + /**#@+ + * @const Error type constants + */ + const FALSE_TYPE = 'fileMimeTypeFalse'; + const NOT_DETECTED = 'fileMimeTypeNotDetected'; + const NOT_READABLE = 'fileMimeTypeNotReadable'; + /**#@-*/ + + /** + * @var array Error message templates + */ + protected $messageTemplates = array( + self::FALSE_TYPE => "File '%value%' has a false mimetype of '%type%'", + self::NOT_DETECTED => "The mimetype of file '%value%' could not be detected", + self::NOT_READABLE => "File '%value%' is not readable or does not exist", + ); + + /** + * @var array + */ + protected $messageVariables = array( + 'type' => 'type' + ); + + /** + * @var string + */ + protected $type; + + /** + * Finfo object to use + * + * @var resource + */ + protected $finfo; + + /** + * If no environment variable 'MAGIC' is set, try and autodiscover it based on common locations + * @var array + */ + protected $magicFiles = array( + '/usr/share/misc/magic', + '/usr/share/misc/magic.mime', + '/usr/share/misc/magic.mgc', + '/usr/share/mime/magic', + '/usr/share/mime/magic.mime', + '/usr/share/mime/magic.mgc', + '/usr/share/file/magic', + '/usr/share/file/magic.mime', + '/usr/share/file/magic.mgc', + ); + + /** + * Options for this validator + * + * @var array + */ + protected $options = array( + 'enableHeaderCheck' => false, // Allow header check + 'disableMagicFile' => false, // Disable usage of magicfile + 'magicFile' => null, // Magicfile to use + 'mimeType' => null, // Mimetype to allow + ); + + /** + * Sets validator options + * + * Mimetype to accept + * - NULL means default PHP usage by using the environment variable 'magic' + * - FALSE means disabling searching for mimetype, should be used for PHP 5.3 + * - A string is the mimetype file to use + * + * @param string|array|Traversable $options + */ + public function __construct($options = null) + { + if ($options instanceof Traversable) { + $options = ArrayUtils::iteratorToArray($options); + } elseif (is_string($options)) { + $this->setMimeType($options); + $options = array(); + } + + if (isset($options['magicFile'])) { + $this->setMagicFile($options['magicFile']); + unset($options['magicFile']); + } + + if (isset($options['enableHeaderCheck'])) { + $this->enableHeaderCheck($options['enableHeaderCheck']); + unset($options['enableHeaderCheck']); + } + + if (array_key_exists('mimeType', $options)) { + $this->setMimeType($options['mimeType']); + unset($options['mimeType']); + } + + // Handle cases where mimetypes are interspersed with options, or + // options are simply an array of mime types + foreach (array_keys($options) as $key) { + if (!is_int($key)) { + continue; + } + $this->addMimeType($options[$key]); + unset($options[$key]); + } + + parent::__construct($options); + } + + /** + * Returns the actual set magicfile + * + * @return string + */ + public function getMagicFile() + { + if (null === $this->options['magicFile']) { + $magic = getenv('magic'); + if (!empty($magic)) { + $this->setMagicFile($magic); + if ($this->options['magicFile'] === null) { + $this->options['magicFile'] = false; + } + return $this->options['magicFile']; + } + + ErrorHandler::start(); + $safeMode = ini_get('safe_mode'); + ErrorHandler::stop(); + + if (!($safeMode == 'On' || $safeMode === 1)) { + foreach ($this->magicFiles as $file) { + // suppressing errors which are thrown due to openbase_dir restrictions + try { + $this->setMagicFile($file); + if ($this->options['magicFile'] !== null) { + break; + } + } catch (Exception\ExceptionInterface $e) { + // Intentionally, catch and fall through + } + } + } + + if ($this->options['magicFile'] === null) { + $this->options['magicFile'] = false; + } + } + + return $this->options['magicFile']; + } + + /** + * Sets the magicfile to use + * if null, the MAGIC constant from php is used + * if the MAGIC file is erroneous, no file will be set + * if false, the default MAGIC file from PHP will be used + * + * @param string $file + * @return MimeType Provides fluid interface + * @throws Exception\RuntimeException When finfo can not read the magicfile + * @throws Exception\InvalidArgumentException + * @throws Exception\InvalidMagicMimeFileException + */ + public function setMagicFile($file) + { + if ($file === false) { + $this->options['magicFile'] = false; + } elseif (empty($file)) { + $this->options['magicFile'] = null; + } elseif (!(class_exists('finfo', false))) { + $this->options['magicFile'] = null; + throw new Exception\RuntimeException('Magicfile can not be set; there is no finfo extension installed'); + } elseif (!is_file($file) || !is_readable($file)) { + throw new Exception\InvalidArgumentException(sprintf( + 'The given magicfile ("%s") could not be read', + $file + )); + } else { + $const = defined('FILEINFO_MIME_TYPE') ? FILEINFO_MIME_TYPE : FILEINFO_MIME; + ErrorHandler::start(E_NOTICE|E_WARNING); + $this->finfo = finfo_open($const, $file); + $error = ErrorHandler::stop(); + if (empty($this->finfo)) { + $this->finfo = null; + throw new Exception\InvalidMagicMimeFileException(sprintf( + 'The given magicfile ("%s") could not be used by ext/finfo', + $file + ), 0, $error); + } + $this->options['magicFile'] = $file; + } + + return $this; + } + + /** + * Disables usage of MagicFile + * + * @param $disable boolean False disables usage of magic file + * @return MimeType Provides fluid interface + */ + public function disableMagicFile($disable) + { + $this->options['disableMagicFile'] = (bool) $disable; + return $this; + } + + /** + * Is usage of MagicFile disabled? + * + * @return boolean + */ + public function isMagicFileDisabled() + { + return $this->options['disableMagicFile']; + } + + /** + * Returns the Header Check option + * + * @return boolean + */ + public function getHeaderCheck() + { + return $this->options['enableHeaderCheck']; + } + + /** + * Defines if the http header should be used + * Note that this is unsafe and therefor the default value is false + * + * @param boolean $headerCheck + * @return MimeType Provides fluid interface + */ + public function enableHeaderCheck($headerCheck = true) + { + $this->options['enableHeaderCheck'] = (boolean) $headerCheck; + return $this; + } + + /** + * Returns the set mimetypes + * + * @param boolean $asArray Returns the values as array, when false a concatenated string is returned + * @return string|array + */ + public function getMimeType($asArray = false) + { + $asArray = (bool) $asArray; + $mimetype = (string) $this->options['mimeType']; + if ($asArray) { + $mimetype = explode(',', $mimetype); + } + + return $mimetype; + } + + /** + * Sets the mimetypes + * + * @param string|array $mimetype The mimetypes to validate + * @return MimeType Provides a fluent interface + */ + public function setMimeType($mimetype) + { + $this->options['mimeType'] = null; + $this->addMimeType($mimetype); + return $this; + } + + /** + * Adds the mimetypes + * + * @param string|array $mimetype The mimetypes to add for validation + * @return MimeType Provides a fluent interface + * @throws Exception\InvalidArgumentException + */ + public function addMimeType($mimetype) + { + $mimetypes = $this->getMimeType(true); + + if (is_string($mimetype)) { + $mimetype = explode(',', $mimetype); + } elseif (!is_array($mimetype)) { + throw new Exception\InvalidArgumentException("Invalid options to validator provided"); + } + + if (isset($mimetype['magicFile'])) { + unset($mimetype['magicFile']); + } + + foreach ($mimetype as $content) { + if (empty($content) || !is_string($content)) { + continue; + } + $mimetypes[] = trim($content); + } + $mimetypes = array_unique($mimetypes); + + // Sanity check to ensure no empty values + foreach ($mimetypes as $key => $mt) { + if (empty($mt)) { + unset($mimetypes[$key]); + } + } + + $this->options['mimeType'] = implode(',', $mimetypes); + + return $this; + } + + /** + * Defined by Zend_Validate_Interface + * + * Returns true if the mimetype of the file matches the given ones. Also parts + * of mimetypes can be checked. If you give for example "image" all image + * mime types will be accepted like "image/gif", "image/jpeg" and so on. + * + * @param string $value Real file to check for mimetype + * @param array $file File data from \Zend\File\Transfer\Transfer + * @return boolean + */ + public function isValid($value, $file = null) + { + if ($file === null) { + $file = array( + 'type' => null, + 'name' => $value, + ); + } + + // Is file readable ? + if (false === stream_resolve_include_path($value)) { + return $this->createError($file, self::NOT_READABLE); + } + + $mimefile = $this->getMagicFile(); + if (class_exists('finfo', false)) { + $const = defined('FILEINFO_MIME_TYPE') ? FILEINFO_MIME_TYPE : FILEINFO_MIME; + if (!$this->isMagicFileDisabled() && (!empty($mimefile) && empty($this->finfo))) { + ErrorHandler::start(E_NOTICE|E_WARNING); + $this->finfo = finfo_open($const, $mimefile); + ErrorHandler::stop(); + } + + if (empty($this->finfo)) { + ErrorHandler::start(E_NOTICE|E_WARNING); + $this->finfo = finfo_open($const); + ErrorHandler::stop(); + } + + $this->type = null; + if (!empty($this->finfo)) { + $this->type = finfo_file($this->finfo, $value); + } + } + + if (empty($this->type) && + (function_exists('mime_content_type') && ini_get('mime_magic.magicfile'))) { + $this->type = mime_content_type($value); + } + + if (empty($this->type) && $this->getHeaderCheck()) { + $this->type = $file['type']; + } + + if (empty($this->type)) { + return $this->createError($file, self::NOT_DETECTED); + } + + $mimetype = $this->getMimeType(true); + if (in_array($this->type, $mimetype)) { + return true; + } + + $types = explode('/', $this->type); + $types = array_merge($types, explode('-', $this->type)); + $types = array_merge($types, explode(';', $this->type)); + foreach ($mimetype as $mime) { + if (in_array($mime, $types)) { + return true; + } + } + + return $this->createError($file, self::FALSE_TYPE); + } + + /** + * Throws an error of the given type + * + * @param string $file + * @param string $errorType + * @return false + */ + protected function createError($file, $errorType) + { + if ($file !== null) { + if (is_array($file)) { + if (array_key_exists('name', $file)) { + $file = $file['name']; + } + } + + if (is_string($file)) { + $this->value = basename($file); + } + } + + $this->error($errorType); + return false; + } +} diff --git a/lib/Zend/Validator/File/NotExists.php b/lib/Zend/Validator/File/NotExists.php new file mode 100644 index 0000000000000000000000000000000000000000..6ffc314807e7f251201320d3ed49fb77a4110cd7 --- /dev/null +++ b/lib/Zend/Validator/File/NotExists.php @@ -0,0 +1,66 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\File; + +/** + * Validator which checks if the destination file does not exist + * + * @category Zend + * @package Zend_Validate + */ +class NotExists extends Exists +{ + /** + * @const string Error constants + */ + const DOES_EXIST = 'fileNotExistsDoesExist'; + + /** + * @var array Error message templates + */ + protected $messageTemplates = array( + self::DOES_EXIST => "File '%value%' exists", + ); + + /** + * Returns true if and only if the file does not exist in the set destinations + * + * @param string $value Real file to check for + * @param array $file File data from \Zend\File\Transfer\Transfer + * @return boolean + */ + public function isValid($value, $file = null) + { + $directories = $this->getDirectory(true); + if (($file !== null) and (!empty($file['destination']))) { + $directories[] = $file['destination']; + } elseif (!isset($file['name'])) { + $file['name'] = $value; + } + + foreach ($directories as $directory) { + if (empty($directory)) { + continue; + } + + $check = true; + if (file_exists($directory . DIRECTORY_SEPARATOR . $file['name'])) { + return $this->throwError($file, self::DOES_EXIST); + } + } + + if (!isset($check)) { + return $this->throwError($file, self::DOES_EXIST); + } + + return true; + } +} diff --git a/lib/Zend/Validator/File/Sha1.php b/lib/Zend/Validator/File/Sha1.php new file mode 100644 index 0000000000000000000000000000000000000000..c76a7a7e41d698dc059bad38a59f10ab3a65dee4 --- /dev/null +++ b/lib/Zend/Validator/File/Sha1.php @@ -0,0 +1,115 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\File; + +use Zend\Validator\Exception; + +/** + * Validator for the sha1 hash of given files + * + * @category Zend + * @package Zend_Validate + */ +class Sha1 extends Hash +{ + /** + * @const string Error constants + */ + const DOES_NOT_MATCH = 'fileSha1DoesNotMatch'; + const NOT_DETECTED = 'fileSha1NotDetected'; + const NOT_FOUND = 'fileSha1NotFound'; + + /** + * @var array Error message templates + */ + protected $messageTemplates = array( + self::DOES_NOT_MATCH => "File '%value%' does not match the given sha1 hashes", + self::NOT_DETECTED => "A sha1 hash could not be evaluated for the given file", + self::NOT_FOUND => "File '%value%' is not readable or does not exist", + ); + + /** + * Options for this validator + * + * @var string + */ + protected $options = array( + 'algorithm' => 'sha1', + 'hash' => null, + ); + + /** + * Returns all set sha1 hashes + * + * @return array + */ + public function getSha1() + { + return $this->getHash(); + } + + /** + * Sets the sha1 hash for one or multiple files + * + * @param string|array $options + * @return Hash Provides a fluent interface + */ + public function setSha1($options) + { + $this->setHash($options); + return $this; + } + + /** + * Adds the sha1 hash for one or multiple files + * + * @param string|array $options + * @return Hash Provides a fluent interface + */ + public function addSha1($options) + { + $this->addHash($options); + return $this; + } + + /** + * Returns true if and only if the given file confirms the set hash + * + * @param string $value Filename to check for hash + * @param array $file File data from \Zend\File\Transfer\Transfer + * @return boolean + */ + public function isValid($value, $file = null) + { + if ($file === null) { + $file = array('name' => basename($value)); + } + + // Is file readable ? + if (false === stream_resolve_include_path($value)) { + return $this->throwError($file, self::NOT_FOUND); + } + + $hashes = array_unique(array_keys($this->getHash())); + $filehash = hash_file('sha1', $value); + if ($filehash === false) { + return $this->throwError($file, self::NOT_DETECTED); + } + + foreach ($hashes as $hash) { + if ($filehash === $hash) { + return true; + } + } + + return $this->throwError($file, self::DOES_NOT_MATCH); + } +} diff --git a/lib/Zend/Validator/File/Size.php b/lib/Zend/Validator/File/Size.php new file mode 100644 index 0000000000000000000000000000000000000000..858876a39a7989fdadd98d766b9032ada10b920e --- /dev/null +++ b/lib/Zend/Validator/File/Size.php @@ -0,0 +1,380 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\File; + +use Zend\Stdlib\ErrorHandler; +use Zend\Validator\AbstractValidator; +use Zend\Validator\Exception; + +/** + * Validator for the maximum size of a file up to a max of 2GB + * + * @category Zend + * @package Zend_Validate + */ +class Size extends AbstractValidator +{ + /** + * @const string Error constants + */ + const TOO_BIG = 'fileSizeTooBig'; + const TOO_SMALL = 'fileSizeTooSmall'; + const NOT_FOUND = 'fileSizeNotFound'; + + /** + * @var array Error message templates + */ + protected $messageTemplates = array( + self::TOO_BIG => "Maximum allowed size for file '%value%' is '%max%' but '%size%' detected", + self::TOO_SMALL => "Minimum expected size for file '%value%' is '%min%' but '%size%' detected", + self::NOT_FOUND => "File '%value%' is not readable or does not exist", + ); + + /** + * @var array Error message template variables + */ + protected $messageVariables = array( + 'min' => array('options' => 'min'), + 'max' => array('options' => 'max'), + 'size' => 'size', + ); + + /** + * Detected size + * + * @var integer + */ + protected $size; + + /** + * Options for this validator + * + * @var array + */ + protected $options = array( + 'min' => null, // Minimum file size, if null there is no minimum + 'max' => null, // Maximum file size, if null there is no maximum + 'useByteString' => true, // Use byte string? + ); + + /** + * Sets validator options + * + * If $options is a integer, it will be used as maximum file size + * As Array is accepts the following keys: + * 'min': Minimum file size + * 'max': Maximum file size + * 'useByteString': Use bytestring or real size for messages + * + * @param integer|array|\Traversable $options Options for the adapter + */ + public function __construct($options = null) + { + if (is_string($options) || is_numeric($options)) { + $options = array('max' => $options); + } + + if (1 < func_num_args()) { + $argv = func_get_args(); + array_shift($argv); + $options['max'] = array_shift($argv); + if (!empty($argv)) { + $options['useByteString'] = array_shift($argv); + } + } + + parent::__construct($options); + } + + /** + * Should messages return bytes as integer or as string in SI notation + * + * @param boolean $byteString Use bytestring ? + * @return integer + */ + public function useByteString($byteString = true) + { + $this->options['useByteString'] = (bool) $byteString; + return $this; + } + + /** + * Will bytestring be used? + * + * @return boolean + */ + public function getByteString() + { + return $this->options['useByteString']; + } + + /** + * Returns the minimum file size + * + * @param bool $raw Whether or not to force return of the raw value (defaults off) + * @return integer|string + */ + public function getMin($raw = false) + { + $min = $this->options['min']; + if (!$raw && $this->getByteString()) { + $min = $this->toByteString($min); + } + + return $min; + } + + /** + * Sets the minimum file size + * + * File size can be an integer or an byte string + * This includes 'B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB' + * For example: 2000, 2MB, 0.2GB + * + * @param integer|string $min The minimum file size + * @return Size Provides a fluent interface + * @throws Exception\InvalidArgumentException When min is greater than max + */ + public function setMin($min) + { + if (!is_string($min) and !is_numeric($min)) { + throw new Exception\InvalidArgumentException('Invalid options to validator provided'); + } + + $min = (integer) $this->fromByteString($min); + $max = $this->getMax(true); + if (($max !== null) && ($min > $max)) { + throw new Exception\InvalidArgumentException( + 'The minimum must be less than or equal to the maximum file' + ." size, but $min > $max"); + } + + $this->options['min'] = $min; + return $this; + } + + /** + * Returns the maximum file size + * + * @param bool $raw Whether or not to force return of the raw value (defaults off) + * @return integer|string + */ + public function getMax($raw = false) + { + $max = $this->options['max']; + if (!$raw && $this->getByteString()) { + $max = $this->toByteString($max); + } + + return $max; + } + + /** + * Sets the maximum file size + * + * File size can be an integer or an byte string + * This includes 'B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB' + * For example: 2000, 2MB, 0.2GB + * + * @param integer|string $max The maximum file size + * @return Size Provides a fluent interface + * @throws Exception\InvalidArgumentException When max is smaller than min + */ + public function setMax($max) + { + if (!is_string($max) && !is_numeric($max)) { + throw new Exception\InvalidArgumentException('Invalid options to validator provided'); + } + + $max = (integer) $this->fromByteString($max); + $min = $this->getMin(true); + if (($min !== null) && ($max < $min)) { + throw new Exception\InvalidArgumentException( + 'The maximum must be greater than or equal to the minimum file' + ." size, but $max < $min"); + } + + $this->options['max'] = $max; + return $this; + } + + /** + * Retrieve current detected file size + * + * @return int + */ + protected function getSize() + { + return $this->size; + } + + /** + * Set current size + * + * @param int $size + * @return Size + */ + protected function setSize($size) + { + $this->size = $size; + return $this; + } + + /** + * Returns true if and only if the file size of $value is at least min and + * not bigger than max (when max is not null). + * + * @param string $value Real file to check for size + * @param array $file File data from \Zend\File\Transfer\Transfer + * @return boolean + */ + public function isValid($value, $file = null) + { + if ($file === null) { + $file = array('name' => basename($value)); + } + + // Is file readable ? + if (false === stream_resolve_include_path($value)) { + return $this->throwError($file, self::NOT_FOUND); + } + + // limited to 4GB files + ErrorHandler::start(); + $size = sprintf("%u", filesize($value)); + ErrorHandler::stop(); + $this->size = $size; + + // Check to see if it's smaller than min size + $min = $this->getMin(true); + $max = $this->getMax(true); + if (($min !== null) && ($size < $min)) { + if ($this->getByteString()) { + $this->options['min'] = $this->toByteString($min); + $this->size = $this->toByteString($size); + $this->throwError($file, self::TOO_SMALL); + $this->options['min'] = $min; + $this->size = $size; + } else { + $this->throwError($file, self::TOO_SMALL); + } + } + + // Check to see if it's larger than max size + if (($max !== null) && ($max < $size)) { + if ($this->getByteString()) { + $this->options['max'] = $this->toByteString($max); + $this->size = $this->toByteString($size); + $this->throwError($file, self::TOO_BIG); + $this->options['max'] = $max; + $this->size = $size; + } else { + $this->throwError($file, self::TOO_BIG); + } + } + + if (count($this->getMessages()) > 0) { + return false; + } + + return true; + } + + /** + * Returns the formatted size + * + * @param integer $size + * @return string + */ + protected function toByteString($size) + { + $sizes = array('B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'); + for ($i=0; $size >= 1024 && $i < 9; $i++) { + $size /= 1024; + } + + return round($size, 2) . $sizes[$i]; + } + + /** + * Returns the unformatted size + * + * @param string $size + * @return integer + */ + protected function fromByteString($size) + { + if (is_numeric($size)) { + return (integer) $size; + } + + $type = trim(substr($size, -2, 1)); + + $value = substr($size, 0, -1); + if (!is_numeric($value)) { + $value = substr($value, 0, -1); + } + + switch (strtoupper($type)) { + case 'Y': + $value *= (1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024); + break; + case 'Z': + $value *= (1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024); + break; + case 'E': + $value *= (1024 * 1024 * 1024 * 1024 * 1024 * 1024); + break; + case 'P': + $value *= (1024 * 1024 * 1024 * 1024 * 1024); + break; + case 'T': + $value *= (1024 * 1024 * 1024 * 1024); + break; + case 'G': + $value *= (1024 * 1024 * 1024); + break; + case 'M': + $value *= (1024 * 1024); + break; + case 'K': + $value *= 1024; + break; + default: + break; + } + + return $value; + } + + /** + * Throws an error of the given type + * + * @param string $file + * @param string $errorType + * @return false + */ + protected function throwError($file, $errorType) + { + if ($file !== null) { + if (is_array($file)) { + if (array_key_exists('name', $file)) { + $this->value = $file['name']; + } + } elseif (is_string($file)) { + $this->value = $file; + } + } + + $this->error($errorType); + return false; + } +} diff --git a/lib/Zend/Validator/File/Upload.php b/lib/Zend/Validator/File/Upload.php new file mode 100644 index 0000000000000000000000000000000000000000..59c3846fe39b98f11995e4cec1f8c4ad91c2c97e --- /dev/null +++ b/lib/Zend/Validator/File/Upload.php @@ -0,0 +1,236 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\File; + +use Zend\Validator\AbstractValidator; +use Zend\Validator\Exception; + +/** + * Validator for the maximum size of a file up to a max of 2GB + * + * @category Zend + * @package Zend_Validate + */ +class Upload extends AbstractValidator +{ + /** + * @const string Error constants + */ + const INI_SIZE = 'fileUploadErrorIniSize'; + const FORM_SIZE = 'fileUploadErrorFormSize'; + const PARTIAL = 'fileUploadErrorPartial'; + const NO_FILE = 'fileUploadErrorNoFile'; + const NO_TMP_DIR = 'fileUploadErrorNoTmpDir'; + const CANT_WRITE = 'fileUploadErrorCantWrite'; + const EXTENSION = 'fileUploadErrorExtension'; + const ATTACK = 'fileUploadErrorAttack'; + const FILE_NOT_FOUND = 'fileUploadErrorFileNotFound'; + const UNKNOWN = 'fileUploadErrorUnknown'; + + /** + * @var array Error message templates + */ + protected $messageTemplates = array( + self::INI_SIZE => "File '%value%' exceeds the defined ini size", + self::FORM_SIZE => "File '%value%' exceeds the defined form size", + self::PARTIAL => "File '%value%' was only partially uploaded", + self::NO_FILE => "File '%value%' was not uploaded", + self::NO_TMP_DIR => "No temporary directory was found for file '%value%'", + self::CANT_WRITE => "File '%value%' can't be written", + self::EXTENSION => "A PHP extension returned an error while uploading the file '%value%'", + self::ATTACK => "File '%value%' was illegally uploaded. This could be a possible attack", + self::FILE_NOT_FOUND => "File '%value%' was not found", + self::UNKNOWN => "Unknown error while uploading file '%value%'" + ); + + protected $options = array( + 'files' => array(), + ); + + /** + * Sets validator options + * + * The array $files must be given in syntax of Zend_File_Transfer to be checked + * If no files are given the $_FILES array will be used automatically. + * NOTE: This validator will only work with HTTP POST uploads! + * + * @param array|\Traversable $options Array of files in syntax of \Zend\File\Transfer\Transfer + */ + public function __construct($options = array()) + { + if (is_array($options) && !array_key_exists('files', $options)) { + $options = array('files' => $options); + } + + parent::__construct($options); + } + + /** + * Returns the array of set files + * + * @param string $file (Optional) The file to return in detail + * @return array + * @throws Exception\InvalidArgumentException If file is not found + */ + public function getFiles($file = null) + { + if ($file !== null) { + $return = array(); + foreach ($this->options['files'] as $name => $content) { + if ($name === $file) { + $return[$file] = $this->options['files'][$name]; + } + + if ($content['name'] === $file) { + $return[$name] = $this->options['files'][$name]; + } + } + + if (count($return) === 0) { + throw new Exception\InvalidArgumentException("The file '$file' was not found"); + } + + return $return; + } + + return $this->options['files']; + } + + /** + * Sets the files to be checked + * + * @param array $files The files to check in syntax of \Zend\File\Transfer\Transfer + * @return Upload Provides a fluent interface + */ + public function setFiles($files = array()) + { + if (count($files) === 0) { + $this->options['files'] = $_FILES; + } else { + $this->options['files'] = $files; + } + + if ($this->options['files'] === NULL) { + $this->options['files'] = array(); + } + + foreach ($this->options['files'] as $file => $content) { + if (!isset($content['error'])) { + unset($this->options['files'][$file]); + } + } + + return $this; + } + + /** + * Returns true if and only if the file was uploaded without errors + * + * @param string $value Single file to check for upload errors, when giving null the $_FILES array + * from initialization will be used + * @param mixed $file + * @return boolean + */ + public function isValid($value, $file = null) + { + $files = array(); + $this->setValue($value); + if (array_key_exists($value, $this->getFiles())) { + $files = array_merge($files, $this->getFiles($value)); + } else { + foreach ($this->getFiles() as $file => $content) { + if (isset($content['name']) && ($content['name'] === $value)) { + $files = array_merge($files, $this->getFiles($file)); + } + + if (isset($content['tmp_name']) && ($content['tmp_name'] === $value)) { + $files = array_merge($files, $this->getFiles($file)); + } + } + } + + if (empty($files)) { + return $this->throwError($file, self::FILE_NOT_FOUND); + } + + foreach ($files as $file => $content) { + $this->value = $file; + switch ($content['error']) { + case 0: + if (!is_uploaded_file($content['tmp_name'])) { + $this->throwError($file, self::ATTACK); + } + break; + + case 1: + $this->throwError($file, self::INI_SIZE); + break; + + case 2: + $this->throwError($file, self::FORM_SIZE); + break; + + case 3: + $this->throwError($file, self::PARTIAL); + break; + + case 4: + $this->throwError($file, self::NO_FILE); + break; + + case 6: + $this->throwError($file, self::NO_TMP_DIR); + break; + + case 7: + $this->throwError($file, self::CANT_WRITE); + break; + + case 8: + $this->throwError($file, self::EXTENSION); + break; + + default: + $this->throwError($file, self::UNKNOWN); + break; + } + } + + if (count($this->getMessages()) > 0) { + return false; + } else { + return true; + } + } + + /** + * Throws an error of the given type + * + * @param string $file + * @param string $errorType + * @return false + */ + protected function throwError($file, $errorType) + { + if ($file !== null) { + if (is_array($file)) { + if (array_key_exists('name', $file)) { + $this->value = $file['name']; + } + } elseif (is_string($file)) { + $this->value = $file; + } + } + + $this->error($errorType); + return false; + } +} diff --git a/lib/Zend/Validator/File/WordCount.php b/lib/Zend/Validator/File/WordCount.php new file mode 100644 index 0000000000000000000000000000000000000000..48a0fc2cb5d27a0dcbb223681c5292c450b6909a --- /dev/null +++ b/lib/Zend/Validator/File/WordCount.php @@ -0,0 +1,68 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\File; + +/** + * Validator for counting all words in a file + * + * @category Zend + * @package Zend_Validate + */ +class WordCount extends Count +{ + /** + * @const string Error constants + */ + const TOO_MUCH = 'fileWordCountTooMuch'; + const TOO_LESS = 'fileWordCountTooLess'; + const NOT_FOUND = 'fileWordCountNotFound'; + + /** + * @var array Error message templates + */ + protected $messageTemplates = array( + self::TOO_MUCH => "Too much words, maximum '%max%' are allowed but '%count%' were counted", + self::TOO_LESS => "Too less words, minimum '%min%' are expected but '%count%' were counted", + self::NOT_FOUND => "File '%value%' is not readable or does not exist", + ); + + /** + * Returns true if and only if the counted words are at least min and + * not bigger than max (when max is not null). + * + * @param string $value Filename to check for word count + * @param array $file File data from \Zend\File\Transfer\Transfer + * @return boolean + */ + public function isValid($value, $file = null) + { + if ($file === null) { + $file = array('name' => basename($value)); + } + + // Is file readable ? + if (false === stream_resolve_include_path($value)) { + return $this->throwError($file, self::NOT_FOUND); + } + + $content = file_get_contents($value); + $this->count = str_word_count($content); + if (($this->getMax() !== null) && ($this->count > $this->getMax())) { + return $this->throwError($file, self::TOO_MUCH); + } + + if (($this->getMin() !== null) && ($this->count < $this->getMin())) { + return $this->throwError($file, self::TOO_LESS); + } + + return true; + } +} diff --git a/lib/Zend/Validator/GreaterThan.php b/lib/Zend/Validator/GreaterThan.php new file mode 100644 index 0000000000000000000000000000000000000000..38be082f796110adc2ea3e424dbf29041adc86bb --- /dev/null +++ b/lib/Zend/Validator/GreaterThan.php @@ -0,0 +1,164 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator; + +use Traversable; +use Zend\Stdlib\ArrayUtils; + +/** + * @category Zend + * @package Zend_Validate + */ +class GreaterThan extends AbstractValidator +{ + const NOT_GREATER = 'notGreaterThan'; + const NOT_GREATER_INCLUSIVE = 'notGreaterThanInclusive'; + + /** + * Validation failure message template definitions + * + * @var array + */ + protected $messageTemplates = array( + self::NOT_GREATER => "The input is not greater than '%min%'", + self::NOT_GREATER_INCLUSIVE => "The input is not greater or equal than '%min%'" + ); + + /** + * @var array + */ + protected $messageVariables = array( + 'min' => 'min' + ); + + /** + * Minimum value + * + * @var mixed + */ + protected $min; + + /** + * Whether to do inclusive comparisons, allowing equivalence to max + * + * If false, then strict comparisons are done, and the value may equal + * the min option + * + * @var boolean + */ + protected $inclusive; + + /** + * Sets validator options + * + * @param array|Traversable $options + * @throws Exception\InvalidArgumentException + */ + public function __construct($options = null) + { + if ($options instanceof Traversable) { + $options = ArrayUtils::iteratorToArray($options); + } + if (!is_array($options)) { + $options = func_get_args(); + $temp['min'] = array_shift($options); + + if (!empty($options)) { + $temp['inclusive'] = array_shift($options); + } + + $options = $temp; + } + + if (!array_key_exists('min', $options)) { + throw new Exception\InvalidArgumentException("Missing option 'min'"); + } + + if (!array_key_exists('inclusive', $options)) { + $options['inclusive'] = false; + } + + $this->setMin($options['min']) + ->setInclusive($options['inclusive']); + + parent::__construct($options); + } + + /** + * Returns the min option + * + * @return mixed + */ + public function getMin() + { + return $this->min; + } + + /** + * Sets the min option + * + * @param mixed $min + * @return GreaterThan Provides a fluent interface + */ + public function setMin($min) + { + $this->min = $min; + return $this; + } + + /** + * Returns the inclusive option + * + * @return boolean + */ + public function getInclusive() + { + return $this->inclusive; + } + + /** + * Sets the inclusive option + * + * @param boolean $inclusive + * @return GreaterThan Provides a fluent interface + */ + public function setInclusive($inclusive) + { + $this->inclusive = $inclusive; + return $this; + } + + /** + * Returns true if and only if $value is greater than min option + * + * @param mixed $value + * @return boolean + */ + public function isValid($value) + { + $this->setValue($value); + + if ($this->inclusive) { + if ($this->min > $value) { + $this->error(self::NOT_GREATER_INCLUSIVE); + return false; + } + } else { + if ($this->min >= $value) { + $this->error(self::NOT_GREATER); + return false; + } + } + + return true; + } + +} diff --git a/lib/Zend/Validator/Hex.php b/lib/Zend/Validator/Hex.php new file mode 100644 index 0000000000000000000000000000000000000000..8aaf75deb8134eab351b856024868def8128053e --- /dev/null +++ b/lib/Zend/Validator/Hex.php @@ -0,0 +1,54 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator; + +/** + * @category Zend + * @package Zend_Validate + */ +class Hex extends AbstractValidator +{ + const INVALID = 'hexInvalid'; + const NOT_HEX = 'notHex'; + + /** + * Validation failure message template definitions + * + * @var array + */ + protected $messageTemplates = array( + self::INVALID => "Invalid type given. String expected", + self::NOT_HEX => "The input contains non-hexadecimal characters", + ); + + /** + * Returns true if and only if $value contains only hexadecimal digit characters + * + * @param string $value + * @return boolean + */ + public function isValid($value) + { + if (!is_string($value) && !is_int($value)) { + $this->error(self::INVALID); + return false; + } + + $this->setValue($value); + if (!ctype_xdigit((string) $value)) { + $this->error(self::NOT_HEX); + return false; + } + + return true; + } + +} diff --git a/lib/Zend/Validator/Hostname.php b/lib/Zend/Validator/Hostname.php new file mode 100644 index 0000000000000000000000000000000000000000..d780cd51b4bc7dad612a9ba0c604651112b01715 --- /dev/null +++ b/lib/Zend/Validator/Hostname.php @@ -0,0 +1,727 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator; + +use Zend\Stdlib\ErrorHandler; + +/** + * Please note there are two standalone test scripts for testing IDN characters due to problems + * with file encoding. + * + * The first is tests/Zend/Validator/HostnameTestStandalone.php which is designed to be run on + * the command line. + * + * The second is tests/Zend/Validator/HostnameTestForm.php which is designed to be run via HTML + * to allow users to test entering UTF-8 characters in a form. + * + * @category Zend + * @package Zend_Validator + */ +class Hostname extends AbstractValidator +{ + const CANNOT_DECODE_PUNYCODE = 'hostnameCannotDecodePunycode'; + const INVALID = 'hostnameInvalid'; + const INVALID_DASH = 'hostnameDashCharacter'; + const INVALID_HOSTNAME = 'hostnameInvalidHostname'; + const INVALID_HOSTNAME_SCHEMA = 'hostnameInvalidHostnameSchema'; + const INVALID_LOCAL_NAME = 'hostnameInvalidLocalName'; + const INVALID_URI = 'hostnameInvalidUri'; + const IP_ADDRESS_NOT_ALLOWED = 'hostnameIpAddressNotAllowed'; + const LOCAL_NAME_NOT_ALLOWED = 'hostnameLocalNameNotAllowed'; + const UNDECIPHERABLE_TLD = 'hostnameUndecipherableTld'; + const UNKNOWN_TLD = 'hostnameUnknownTld'; + + /** + * @var array + */ + protected $messageTemplates = array( + self::CANNOT_DECODE_PUNYCODE => "The input appears to be a DNS hostname but the given punycode notation cannot be decoded", + self::INVALID => "Invalid type given. String expected", + self::INVALID_DASH => "The input appears to be a DNS hostname but contains a dash in an invalid position", + self::INVALID_HOSTNAME => "The input does not match the expected structure for a DNS hostname", + self::INVALID_HOSTNAME_SCHEMA => "The input appears to be a DNS hostname but cannot match against hostname schema for TLD '%tld%'", + self::INVALID_LOCAL_NAME => "The input does not appear to be a valid local network name", + self::INVALID_URI => "The input does not appear to be a valid URI hostname", + self::IP_ADDRESS_NOT_ALLOWED => "The input appears to be an IP address, but IP addresses are not allowed", + self::LOCAL_NAME_NOT_ALLOWED => "The input appears to be a local network name but local network names are not allowed", + self::UNDECIPHERABLE_TLD => "The input appears to be a DNS hostname but cannot extract TLD part", + self::UNKNOWN_TLD => "The input appears to be a DNS hostname but cannot match TLD against known list", + ); + + /** + * @var array + */ + protected $messageVariables = array( + 'tld' => 'tld', + ); + + const ALLOW_DNS = 1; // Allows Internet domain names (e.g., example.com) + const ALLOW_IP = 2; // Allows IP addresses + const ALLOW_LOCAL = 4; // Allows local network names (e.g., localhost, www.localdomain) + const ALLOW_URI = 8; // Allows URI hostnames + const ALLOW_ALL = 15; // Allows all types of hostnames + + /** + * Array of valid top-level-domains + * + * @see ftp://data.iana.org/TLD/tlds-alpha-by-domain.txt List of all TLDs by domain + * @see http://www.iana.org/domains/root/db/ Official list of supported TLDs + * @var array + */ + protected $validTlds = array( + 'ac', 'ad', 'ae', 'aero', 'af', 'ag', 'ai', 'al', 'am', 'an', 'ao', 'aq', 'ar', 'arpa', + 'as', 'asia', 'at', 'au', 'aw', 'ax', 'az', 'ba', 'bb', 'bd', 'be', 'bf', 'bg', 'bh', 'bi', + 'biz', 'bj', 'bm', 'bn', 'bo', 'br', 'bs', 'bt', 'bv', 'bw', 'by', 'bz', 'ca', 'cat', 'cc', + 'cd', 'cf', 'cg', 'ch', 'ci', 'ck', 'cl', 'cm', 'cn', 'co', 'com', 'coop', 'cr', 'cu', + 'cv', 'cx', 'cy', 'cz', 'de', 'dj', 'dk', 'dm', 'do', 'dz', 'ec', 'edu', 'ee', 'eg', 'er', + 'es', 'et', 'eu', 'fi', 'fj', 'fk', 'fm', 'fo', 'fr', 'ga', 'gb', 'gd', 'ge', 'gf', 'gg', + 'gh', 'gi', 'gl', 'gm', 'gn', 'gov', 'gp', 'gq', 'gr', 'gs', 'gt', 'gu', 'gw', 'gy', 'hk', + 'hm', 'hn', 'hr', 'ht', 'hu', 'id', 'ie', 'il', 'im', 'in', 'info', 'int', 'io', 'iq', + 'ir', 'is', 'it', 'je', 'jm', 'jo', 'jobs', 'jp', 'ke', 'kg', 'kh', 'ki', 'km', 'kn', 'kp', + 'kr', 'kw', 'ky', 'kz', 'la', 'lb', 'lc', 'li', 'lk', 'lr', 'ls', 'lt', 'lu', 'lv', 'ly', + 'ma', 'mc', 'md', 'me', 'mg', 'mh', 'mil', 'mk', 'ml', 'mm', 'mn', 'mo', 'mobi', 'mp', + 'mq', 'mr', 'ms', 'mt', 'mu', 'museum', 'mv', 'mw', 'mx', 'my', 'mz', 'na', 'name', 'nc', + 'ne', 'net', 'nf', 'ng', 'ni', 'nl', 'no', 'np', 'nr', 'nu', 'nz', 'om', 'org', 'pa', 'pe', + 'pf', 'pg', 'ph', 'pk', 'pl', 'pm', 'pn', 'pr', 'pro', 'ps', 'pt', 'pw', 'py', 'qa', 're', + 'ro', 'rs', 'ru', 'rw', 'sa', 'sb', 'sc', 'sd', 'se', 'sg', 'sh', 'si', 'sj', 'sk', 'sl', + 'sm', 'sn', 'so', 'sr', 'st', 'su', 'sv', 'sy', 'sz', 'tc', 'td', 'tel', 'tf', 'tg', 'th', + 'tj', 'tk', 'tl', 'tm', 'tn', 'to', 'tp', 'tr', 'travel', 'tt', 'tv', 'tw', 'tz', 'ua', + 'ug', 'uk', 'um', 'us', 'uy', 'uz', 'va', 'vc', 've', 'vg', 'vi', 'vn', 'vu', 'wf', 'ws', + 'xxx', 'ye', 'yt', 'yu', 'za', 'zm', 'zw' + ); + + /** + * Array for valid Idns + * @see http://www.iana.org/domains/idn-tables/ Official list of supported IDN Chars + * (.AC) Ascension Island http://www.nic.ac/pdf/AC-IDN-Policy.pdf + * (.AR) Argentina http://www.nic.ar/faqidn.html + * (.AS) American Samoa http://www.nic.as/idn/chars.cfm + * (.AT) Austria http://www.nic.at/en/service/technical_information/idn/charset_converter/ + * (.BIZ) International http://www.iana.org/domains/idn-tables/ + * (.BR) Brazil http://registro.br/faq/faq6.html + * (.BV) Bouvett Island http://www.norid.no/domeneregistrering/idn/idn_nyetegn.en.html + * (.CAT) Catalan http://www.iana.org/domains/idn-tables/tables/cat_ca_1.0.html + * (.CH) Switzerland https://nic.switch.ch/reg/ocView.action?res=EF6GW2JBPVTG67DLNIQXU234MN6SC33JNQQGI7L6#anhang1 + * (.CL) Chile http://www.iana.org/domains/idn-tables/tables/cl_latn_1.0.html + * (.COM) International http://www.verisign.com/information-services/naming-services/internationalized-domain-names/index.html + * (.DE) Germany http://www.denic.de/en/domains/idns/liste.html + * (.DK) Danmark http://www.dk-hostmaster.dk/index.php?id=151 + * (.ES) Spain https://www.nic.es/media/2008-05/1210147705287.pdf + * (.FI) Finland http://www.ficora.fi/en/index/palvelut/fiverkkotunnukset/aakkostenkaytto.html + * (.GR) Greece https://grweb.ics.forth.gr/CharacterTable1_en.jsp + * (.HU) Hungary http://www.domain.hu/domain/English/szabalyzat/szabalyzat.html + * (.INFO) International http://www.nic.info/info/idn + * (.IO) British Indian Ocean Territory http://www.nic.io/IO-IDN-Policy.pdf + * (.IR) Iran http://www.nic.ir/Allowable_Characters_dot-iran + * (.IS) Iceland http://www.isnic.is/domain/rules.php + * (.KR) Korea http://www.iana.org/domains/idn-tables/tables/kr_ko-kr_1.0.html + * (.LI) Liechtenstein https://nic.switch.ch/reg/ocView.action?res=EF6GW2JBPVTG67DLNIQXU234MN6SC33JNQQGI7L6#anhang1 + * (.LT) Lithuania http://www.domreg.lt/static/doc/public/idn_symbols-en.pdf + * (.MD) Moldova http://www.register.md/ + * (.MUSEUM) International http://www.iana.org/domains/idn-tables/tables/museum_latn_1.0.html + * (.NET) International http://www.verisign.com/information-services/naming-services/internationalized-domain-names/index.html + * (.NO) Norway http://www.norid.no/domeneregistrering/idn/idn_nyetegn.en.html + * (.NU) Niue http://www.worldnames.net/ + * (.ORG) International http://www.pir.org/index.php?db=content/FAQs&tbl=FAQs_Registrant&id=2 + * (.PE) Peru https://www.nic.pe/nuevas_politicas_faq_2.php + * (.PL) Poland http://www.dns.pl/IDN/allowed_character_sets.pdf + * (.PR) Puerto Rico http://www.nic.pr/idn_rules.asp + * (.PT) Portugal https://online.dns.pt/dns_2008/do?com=DS;8216320233;111;+PAGE(4000058)+K-CAT-CODIGO(C.125)+RCNT(100); + * (.RU) Russia http://www.iana.org/domains/idn-tables/tables/ru_ru-ru_1.0.html + * (.SA) Saudi Arabia http://www.iana.org/domains/idn-tables/tables/sa_ar_1.0.html + * (.SE) Sweden http://www.iis.se/english/IDN_campaignsite.shtml?lang=en + * (.SH) Saint Helena http://www.nic.sh/SH-IDN-Policy.pdf + * (.SJ) Svalbard and Jan Mayen http://www.norid.no/domeneregistrering/idn/idn_nyetegn.en.html + * (.TH) Thailand http://www.iana.org/domains/idn-tables/tables/th_th-th_1.0.html + * (.TM) Turkmenistan http://www.nic.tm/TM-IDN-Policy.pdf + * (.TR) Turkey https://www.nic.tr/index.php + * (.VE) Venice http://www.iana.org/domains/idn-tables/tables/ve_es_1.0.html + * (.VN) Vietnam http://www.vnnic.vn/english/5-6-300-2-2-04-20071115.htm#1.%20Introduction + * + * @var array + */ + protected $validIdns = array( + 'AC' => array(1 => '/^[\x{002d}0-9a-zà -öø-ÿÄăąćĉċÄÄđēėęěÄġģĥħīįĵķĺļľŀłńņňŋőœŕŗřśÅşšţťŧūÅůűųŵŷźżž]{1,63}$/iu'), + 'AR' => array(1 => '/^[\x{002d}0-9a-zà -ãç-êìÃñ-õü]{1,63}$/iu'), + 'AS' => array(1 => '/^[\x{002d}0-9a-zà -öø-ÿÄăąćĉċÄÄđēĕėęěÄğġģĥħĩīÄįıĵķĸĺļľłńņňŋÅÅőœŕŗřśÅşšţťŧũūÅůűųŵŷźż]{1,63}$/iu'), + 'AT' => array(1 => '/^[\x{002d}0-9a-zà -öø-ÿœšž]{1,63}$/iu'), + 'BIZ' => 'Hostname/Biz.php', + 'BR' => array(1 => '/^[\x{002d}0-9a-zà -ãçéÃó-õúü]{1,63}$/iu'), + 'BV' => array(1 => '/^[\x{002d}0-9a-zà áä-éêñ-ôöøüÄđńŋšŧž]{1,63}$/iu'), + 'CAT' => array(1 => '/^[\x{002d}0-9a-z·à ç-éÃïòóúü]{1,63}$/iu'), + 'CH' => array(1 => '/^[\x{002d}0-9a-zà -öø-ÿœ]{1,63}$/iu'), + 'CL' => array(1 => '/^[\x{002d}0-9a-záéÃñóúü]{1,63}$/iu'), + 'CN' => 'Hostname/Cn.php', + 'COM' => 'Hostname/Com.php', + 'DE' => array(1 => '/^[\x{002d}0-9a-zà -öø-ÿăąÄćĉÄÄ‹ÄđĕěėęēğÄġģĥħÄĩįīıĵķĺľļłńňņŋÅőŜĸŕřŗśÅšşťţŧÅůűũųūŵŷźžż]{1,63}$/iu'), + 'DK' => array(1 => '/^[\x{002d}0-9a-zäéöü]{1,63}$/iu'), + 'ES' => array(1 => '/^[\x{002d}0-9a-zà áçèéÃïñòóúü·]{1,63}$/iu'), + 'EU' => array(1 => '/^[\x{002d}0-9a-zà -öø-ÿ]{1,63}$/iu', + 2 => '/^[\x{002d}0-9a-zÄăąćĉċÄÄđēĕėęěÄğġģĥħĩīÄįıĵķĺļľŀłńņňʼnŋÅÅőœŕŗřśÅšťŧũūÅůűųŵŷźżž]{1,63}$/iu', + 3 => '/^[\x{002d}0-9a-zșț]{1,63}$/iu', + 4 => '/^[\x{002d}0-9a-zÎάÎήίΰαβγδεζηθικλμνξοπÏςστυφχψωϊϋόÏÏŽ]{1,63}$/iu', + 5 => '/^[\x{002d}0-9a-zабвгдежзийклмнопрÑтуфхцчшщъыьÑÑŽÑ]{1,63}$/iu', + 6 => '/^[\x{002d}0-9a-zá¼€-ἇá¼-ἕἠ-á¼§á¼°-á¼·á½€-á½…á½-á½—á½ -á½§á½°-ὼώᾀ-ᾇá¾-á¾—á¾ -á¾§á¾°-ᾴᾶᾷῂῃῄῆῇá¿-á¿’Îá¿–á¿—á¿ -ῧῲῳῴῶῷ]{1,63}$/iu'), + 'FI' => array(1 => '/^[\x{002d}0-9a-zäåö]{1,63}$/iu'), + 'GR' => array(1 => '/^[\x{002d}0-9a-zΆΈΉΊΌΎ-ΡΣ-ÏŽá¼€-ἕἘ-á¼á¼ -ὅὈ-á½á½-ὗὙὛá½á½Ÿ-ώᾀ-á¾´á¾¶-ᾼῂῃῄῆ-ῌá¿-á¿“á¿–-Ίῠ-Ῥῲῳῴῶ-ῼ]{1,63}$/iu'), + 'HK' => 'Hostname/Cn.php', + 'HU' => array(1 => '/^[\x{002d}0-9a-záéÃóöúüőű]{1,63}$/iu'), + 'INFO'=> array(1 => '/^[\x{002d}0-9a-zäåæéöøü]{1,63}$/iu', + 2 => '/^[\x{002d}0-9a-záéÃóöúüőű]{1,63}$/iu', + 3 => '/^[\x{002d}0-9a-záæéÃðóöúýþ]{1,63}$/iu', + 4 => '/^[\x{AC00}-\x{D7A3}]{1,17}$/iu', + 5 => '/^[\x{002d}0-9a-zÄÄēģīķļņÅŗšūž]{1,63}$/iu', + 6 => '/^[\x{002d}0-9a-zÄ…Äėęįšūųž]{1,63}$/iu', + 7 => '/^[\x{002d}0-9a-zóąćęłńśźż]{1,63}$/iu', + 8 => '/^[\x{002d}0-9a-záéÃñóúü]{1,63}$/iu'), + 'IO' => array(1 => '/^[\x{002d}0-9a-zà -öø-ÿăąÄćĉÄÄ‹ÄđĕěėęēğÄġģĥħÄĩįīıĵķĺľļłńňņŋÅőŜĸŕřŗśÅšşťţŧÅůűũųūŵŷźžż]{1,63}$/iu'), + 'IS' => array(1 => '/^[\x{002d}0-9a-záéýúÃóþæöð]{1,63}$/iu'), + 'JP' => 'Hostname/Jp.php', + 'KR' => array(1 => '/^[\x{AC00}-\x{D7A3}]{1,17}$/iu'), + 'LI' => array(1 => '/^[\x{002d}0-9a-zà -öø-ÿœ]{1,63}$/iu'), + 'LT' => array(1 => '/^[\x{002d}0-9Ä…Äęėįšųūž]{1,63}$/iu'), + 'MD' => array(1 => '/^[\x{002d}0-9ăâîşţ]{1,63}$/iu'), + 'MUSEUM' => array(1 => '/^[\x{002d}0-9a-zà -öø-ÿÄăąćċÄÄđēėęěğġģħīįıķĺļľłńņňŋÅőœŕŗřśşšţťŧūůűųŵŷźżžǎÇÇ’Ç”\x{01E5}\x{01E7}\x{01E9}\x{01EF}É™\x{0292}áºáºƒáº…ỳ]{1,63}$/iu'), + 'NET' => 'Hostname/Com.php', + 'NO' => array(1 => '/^[\x{002d}0-9a-zà áä-éêñ-ôöøüÄđńŋšŧž]{1,63}$/iu'), + 'NU' => 'Hostname/Com.php', + 'ORG' => array(1 => '/^[\x{002d}0-9a-záéÃñóúü]{1,63}$/iu', + 2 => '/^[\x{002d}0-9a-zóąćęłńśźż]{1,63}$/iu', + 3 => '/^[\x{002d}0-9a-záäåæéëÃðóöøúüýþ]{1,63}$/iu', + 4 => '/^[\x{002d}0-9a-záéÃóöúüőű]{1,63}$/iu', + 5 => '/^[\x{002d}0-9a-zÄ…Äėęįšūųž]{1,63}$/iu', + 6 => '/^[\x{AC00}-\x{D7A3}]{1,17}$/iu', + 7 => '/^[\x{002d}0-9a-zÄÄēģīķļņÅŗšūž]{1,63}$/iu'), + 'PE' => array(1 => '/^[\x{002d}0-9a-zñáéÃóúü]{1,63}$/iu'), + 'PL' => array(1 => '/^[\x{002d}0-9a-zÄÄēģīķļņÅŗšūž]{1,63}$/iu', + 2 => '/^[\x{002d}а-ик-ш\x{0450}ѓѕјљњќџ]{1,63}$/iu', + 3 => '/^[\x{002d}0-9a-zâîăşţ]{1,63}$/iu', + 4 => '/^[\x{002d}0-9а-ÑÑ‘\x{04C2}]{1,63}$/iu', + 5 => '/^[\x{002d}0-9a-zà áâèéêìÃîòóôùúûċġħż]{1,63}$/iu', + 6 => '/^[\x{002d}0-9a-zà äåæéêòóôöøü]{1,63}$/iu', + 7 => '/^[\x{002d}0-9a-zóąćęłńśźż]{1,63}$/iu', + 8 => '/^[\x{002d}0-9a-zà áâãçéêÃòóôõúü]{1,63}$/iu', + 9 => '/^[\x{002d}0-9a-zâîăşţ]{1,63}$/iu', + 10=> '/^[\x{002d}0-9a-záäéÃóôúýÄÄĺľňŕšťž]{1,63}$/iu', + 11=> '/^[\x{002d}0-9a-zçë]{1,63}$/iu', + 12=> '/^[\x{002d}0-9а-ик-шђјљњћџ]{1,63}$/iu', + 13=> '/^[\x{002d}0-9a-zćÄđšž]{1,63}$/iu', + 14=> '/^[\x{002d}0-9a-zâçöûüğış]{1,63}$/iu', + 15=> '/^[\x{002d}0-9a-záéÃñóúü]{1,63}$/iu', + 16=> '/^[\x{002d}0-9a-zäõöüšž]{1,63}$/iu', + 17=> '/^[\x{002d}0-9a-zĉÄĥĵÅÅ]{1,63}$/iu', + 18=> '/^[\x{002d}0-9a-zâäéëîô]{1,63}$/iu', + 19=> '/^[\x{002d}0-9a-zà áâäåæçèéêëìÃîïðñòôöøùúûüýćÄłńřśš]{1,63}$/iu', + 20=> '/^[\x{002d}0-9a-zäåæõöøüšž]{1,63}$/iu', + 21=> '/^[\x{002d}0-9a-zà áçèéìÃòóùú]{1,63}$/iu', + 22=> '/^[\x{002d}0-9a-zà áéÃóöúüőű]{1,63}$/iu', + 23=> '/^[\x{002d}0-9Îά-ÏŽ]{1,63}$/iu', + 24=> '/^[\x{002d}0-9a-zà áâåæçèéêëðóôöøüþœ]{1,63}$/iu', + 25=> '/^[\x{002d}0-9a-záäéÃóöúüýÄÄěňřšťůž]{1,63}$/iu', + 26=> '/^[\x{002d}0-9a-z·à çèéÃïòóúü]{1,63}$/iu', + 27=> '/^[\x{002d}0-9а-ъьюÑ\x{0450}\x{045D}]{1,63}$/iu', + 28=> '/^[\x{002d}0-9а-Ñёіў]{1,63}$/iu', + 29=> '/^[\x{002d}0-9a-zÄ…Äėęįšūųž]{1,63}$/iu', + 30=> '/^[\x{002d}0-9a-záäåæéëÃðóöøúüýþ]{1,63}$/iu', + 31=> '/^[\x{002d}0-9a-zà âæçèéêëîïñôùûüÿœ]{1,63}$/iu', + 32=> '/^[\x{002d}0-9а-щъыьÑÑŽÑёєіїґ]{1,63}$/iu', + 33=> '/^[\x{002d}0-9×-ת]{1,63}$/iu'), + 'PR' => array(1 => '/^[\x{002d}0-9a-záéÃóúñäëïüöâêîôûà èùæçœãõ]{1,63}$/iu'), + 'PT' => array(1 => '/^[\x{002d}0-9a-záà âãçéêÃóôõú]{1,63}$/iu'), + 'RU' => array(1 => '/^[\x{002d}0-9а-ÑÑ‘]{1,63}$/iu'), + 'SA' => array(1 => '/^[\x{002d}.0-9\x{0621}-\x{063A}\x{0641}-\x{064A}\x{0660}-\x{0669}]{1,63}$/iu'), + 'SE' => array(1 => '/^[\x{002d}0-9a-zäåéöü]{1,63}$/iu'), + 'SH' => array(1 => '/^[\x{002d}0-9a-zà -öø-ÿăąÄćĉÄÄ‹ÄđĕěėęēğÄġģĥħÄĩįīıĵķĺľļłńňņŋÅőŜĸŕřŗśÅšşťţŧÅůűũųūŵŷźžż]{1,63}$/iu'), + 'SI' => array( + 1 => '/^[\x{002d}0-9a-zà -öø-ÿ]{1,63}$/iu', + 2 => '/^[\x{002d}0-9a-zÄăąćĉċÄÄđēĕėęěÄğġģĥħĩīÄįıĵķĺļľŀłńņňʼnŋÅÅőœŕŗřśÅšťŧũūÅůűųŵŷźżž]{1,63}$/iu', + 3 => '/^[\x{002d}0-9a-zșț]{1,63}$/iu'), + 'SJ' => array(1 => '/^[\x{002d}0-9a-zà áä-éêñ-ôöøüÄđńŋšŧž]{1,63}$/iu'), + 'TH' => array(1 => '/^[\x{002d}0-9a-z\x{0E01}-\x{0E3A}\x{0E40}-\x{0E4D}\x{0E50}-\x{0E59}]{1,63}$/iu'), + 'TM' => array(1 => '/^[\x{002d}0-9a-zà -öø-ÿÄăąćĉċÄÄđēėęěÄġģĥħīįĵķĺļľŀłńņňŋőœŕŗřśÅşšţťŧūÅůűųŵŷźżž]{1,63}$/iu'), + 'TW' => 'Hostname/Cn.php', + 'TR' => array(1 => '/^[\x{002d}0-9a-zğıüşöç]{1,63}$/iu'), + 'VE' => array(1 => '/^[\x{002d}0-9a-záéÃóúüñ]{1,63}$/iu'), + 'VN' => array(1 => '/^[ÀÃÂÃÈÉÊÌÃÒÓÔÕÙÚÃà áâãèéêìÃòóôõùúýĂăÄÄ‘Ä¨Ä©Å¨Å©Æ Æ¡Æ¯Æ°\x{1EA0}-\x{1EF9}]{1,63}$/iu'), + 'ä¸å›½' => 'Hostname/Cn.php', + 'ä¸åœ‹' => 'Hostname/Cn.php', + 'ලංකà·' => array(1 => '/^[\x{0d80}-\x{0dff}]{1,63}$/iu'), + '香港' => 'Hostname/Cn.php', + 'å°æ¹¾' => 'Hostname/Cn.php', + 'å°ç£' => 'Hostname/Cn.php', + 'امارات' => array(1 => '/^[\x{0621}-\x{0624}\x{0626}-\x{063A}\x{0641}\x{0642}\x{0644}-\x{0648}\x{067E}\x{0686}\x{0698}\x{06A9}\x{06AF}\x{06CC}\x{06F0}-\x{06F9}]{1,30}$/iu'), + 'الاردن' => array(1 => '/^[\x{0621}-\x{0624}\x{0626}-\x{063A}\x{0641}\x{0642}\x{0644}-\x{0648}\x{067E}\x{0686}\x{0698}\x{06A9}\x{06AF}\x{06CC}\x{06F0}-\x{06F9}]{1,30}$/iu'), + 'السعودية' => array(1 => '/^[\x{0621}-\x{0624}\x{0626}-\x{063A}\x{0641}\x{0642}\x{0644}-\x{0648}\x{067E}\x{0686}\x{0698}\x{06A9}\x{06AF}\x{06CC}\x{06F0}-\x{06F9}]{1,30}$/iu'), + 'ไทย' => array(1 => '/^[\x{002d}0-9a-z\x{0E01}-\x{0E3A}\x{0E40}-\x{0E4D}\x{0E50}-\x{0E59}]{1,63}$/iu'), + 'рф' => array(1 => '/^[\x{002d}0-9а-ÑÑ‘]{1,63}$/iu'), + 'تونس' => array(1 => '/^[\x{0621}-\x{0624}\x{0626}-\x{063A}\x{0641}\x{0642}\x{0644}-\x{0648}\x{067E}\x{0686}\x{0698}\x{06A9}\x{06AF}\x{06CC}\x{06F0}-\x{06F9}]{1,30}$/iu'), + 'مصر' => array(1 => '/^[\x{0621}-\x{0624}\x{0626}-\x{063A}\x{0641}\x{0642}\x{0644}-\x{0648}\x{067E}\x{0686}\x{0698}\x{06A9}\x{06AF}\x{06CC}\x{06F0}-\x{06F9}]{1,30}$/iu'), + 'இலஙà¯à®•ை' => array(1 => '/^[\x{0b80}-\x{0bff}]{1,63}$/iu'), + 'Ùلسطين' => array(1 => '/^[\x{0621}-\x{0624}\x{0626}-\x{063A}\x{0641}\x{0642}\x{0644}-\x{0648}\x{067E}\x{0686}\x{0698}\x{06A9}\x{06AF}\x{06CC}\x{06F0}-\x{06F9}]{1,30}$/iu'), + ); + + protected $idnLength = array( + 'BIZ' => array(5 => 17, 11 => 15, 12 => 20), + 'CN' => array(1 => 20), + 'COM' => array(3 => 17, 5 => 20), + 'HK' => array(1 => 15), + 'INFO'=> array(4 => 17), + 'KR' => array(1 => 17), + 'NET' => array(3 => 17, 5 => 20), + 'ORG' => array(6 => 17), + 'TW' => array(1 => 20), + 'امارات' => array(1 => 30), + 'الاردن' => array(1 => 30), + 'السعودية' => array(1 => 30), + 'تونس' => array(1 => 30), + 'مصر' => array(1 => 30), + 'Ùلسطين' => array(1 => 30), + 'ä¸å›½' => array(1 => 20), + 'ä¸åœ‹' => array(1 => 20), + '香港' => array(1 => 20), + 'å°æ¹¾' => array(1 => 20), + 'å°ç£' => array(1 => 20), + ); + + protected $tld; + + /** + * Options for the hostname validator + * + * @var array + */ + protected $options = array( + 'allow' => self::ALLOW_DNS, // Allow these hostnames + 'useIdnCheck' => true, // Check IDN domains + 'useTldCheck' => true, // Check TLD elements + 'ipValidator' => null, // IP validator to use + ); + + /** + * Sets validator options + * + * @param integer $allow OPTIONAL Set what types of hostname to allow (default ALLOW_DNS) + * @param boolean $validateIdn OPTIONAL Set whether IDN domains are validated (default true) + * @param boolean $validateTld OPTIONAL Set whether the TLD element of a hostname is validated (default true) + * @param Ip $ipValidator OPTIONAL + * @see http://www.iana.org/cctld/specifications-policies-cctlds-01apr02.htm Technical Specifications for ccTLDs + */ + public function __construct($options = array()) + { + if (!is_array($options)) { + $options = func_get_args(); + $temp['allow'] = array_shift($options); + if (!empty($options)) { + $temp['useIdnCheck'] = array_shift($options); + } + + if (!empty($options)) { + $temp['useTldCheck'] = array_shift($options); + } + + if (!empty($options)) { + $temp['ipValidator'] = array_shift($options); + } + + $options = $temp; + } + + if (!array_key_exists('ipValidator', $options)) { + $options['ipValidator'] = null; + } + + parent::__construct($options); + } + + /** + * Returns the set ip validator + * + * @return Ip + */ + public function getIpValidator() + { + return $this->options['ipValidator']; + } + + /** + * @param Ip $ipValidator OPTIONAL + * @return Hostname; + */ + public function setIpValidator(Ip $ipValidator = null) + { + if ($ipValidator === null) { + $ipValidator = new Ip(); + } + + $this->options['ipValidator'] = $ipValidator; + return $this; + } + + /** + * Returns the allow option + * + * @return integer + */ + public function getAllow() + { + return $this->options['allow']; + } + + /** + * Sets the allow option + * + * @param integer $allow + * @return Hostname Provides a fluent interface + */ + public function setAllow($allow) + { + $this->options['allow'] = $allow; + return $this; + } + + /** + * Returns the set idn option + * + * @return boolean + */ + public function getIdnCheck() + { + return $this->options['useIdnCheck']; + } + + /** + * Set whether IDN domains are validated + * + * This only applies when DNS hostnames are validated + * + * @param boolean $useIdnCheck Set to true to validate IDN domains + * @return Hostname + */ + public function useIdnCheck ($useIdnCheck) + { + $this->options['useIdnCheck'] = (bool) $useIdnCheck; + return $this; + } + + /** + * Returns the set tld option + * + * @return boolean + */ + public function getTldCheck() + { + return $this->options['useTldCheck']; + } + + /** + * Set whether the TLD element of a hostname is validated + * + * This only applies when DNS hostnames are validated + * + * @param boolean $useTldCheck Set to true to validate TLD elements + * @return Hostname + */ + public function useTldCheck ($useTldCheck) + { + $this->options['useTldCheck'] = (bool) $useTldCheck; + return $this; + } + + /** + * Defined by Interface + * + * Returns true if and only if the $value is a valid hostname with respect to the current allow option + * + * @param string $value + * @return boolean + */ + public function isValid($value) + { + if (!is_string($value)) { + $this->error(self::INVALID); + return false; + } + + $this->setValue($value); + // Check input against IP address schema + if (preg_match('/^[0-9a-f:.]*$/i', $value) && + $this->getIpValidator()->setTranslator($this->getTranslator())->isValid($value)) { + if (!($this->getAllow() & self::ALLOW_IP)) { + $this->error(self::IP_ADDRESS_NOT_ALLOWED); + return false; + } else { + return true; + } + } + + // Local hostnames are allowed to be partial (ending '.') + if ($this->getAllow() & self::ALLOW_LOCAL) { + if (substr($value, -1) === '.') { + $value = substr($value, 0, -1); + if (substr($value, -1) === '.') { + // Empty hostnames (ending '..') are not allowed + $this->error(self::INVALID_LOCAL_NAME); + return false; + } + } + } + + $domainParts = explode('.', $value); + + // Prevent partial IP V4 addresses (ending '.') + if ((count($domainParts) == 4) && preg_match('/^[0-9.a-e:.]*$/i', $value) && + $this->getIpValidator()->setTranslator($this->getTranslator())->isValid($value)) { + $this->error(self::INVALID_LOCAL_NAME); + } + + // Check input against DNS hostname schema + if ((count($domainParts) > 1) && (strlen($value) >= 4) && (strlen($value) <= 254)) { + $status = false; + + $origenc = iconv_get_encoding('internal_encoding'); + iconv_set_encoding('internal_encoding', 'UTF-8'); + do { + // First check TLD + $matches = array(); + if (preg_match('/([^.]{2,10})$/i', end($domainParts), $matches) || + (array_key_exists(end($domainParts), $this->validIdns))) { + reset($domainParts); + + // Hostname characters are: *(label dot)(label dot label); max 254 chars + // label: id-prefix [*ldh{61} id-prefix]; max 63 chars + // id-prefix: alpha / digit + // ldh: alpha / digit / dash + + // Match TLD against known list + $this->tld = strtolower($matches[1]); + if ($this->getTldCheck()) { + if (!in_array($this->tld, $this->validTlds)) { + $this->error(self::UNKNOWN_TLD); + $status = false; + break; + } + } + + /** + * Match against IDN hostnames + * Note: Keep label regex short to avoid issues with long patterns when matching IDN hostnames + * @see Hostname\Interface + */ + $regexChars = array(0 => '/^[a-z0-9\x2d]{1,63}$/i'); + if ($this->getIdnCheck() && isset($this->validIdns[strtoupper($this->tld)])) { + if (is_string($this->validIdns[strtoupper($this->tld)])) { + $regexChars += include ($this->validIdns[strtoupper($this->tld)]); + } else { + $regexChars += $this->validIdns[strtoupper($this->tld)]; + } + } + + // Check each hostname part + $check = 0; + foreach ($domainParts as $domainPart) { + // Decode Punycode domain names to IDN + if (strpos($domainPart, 'xn--') === 0) { + $domainPart = $this->decodePunycode(substr($domainPart, 4)); + if ($domainPart === false) { + return false; + } + } + + // Check dash (-) does not start, end or appear in 3rd and 4th positions + if ((strpos($domainPart, '-') === 0) + || ((strlen($domainPart) > 2) && (strpos($domainPart, '-', 2) == 2) && (strpos($domainPart, '-', 3) == 3)) + || (strpos($domainPart, '-') === (strlen($domainPart) - 1))) { + $this->error(self::INVALID_DASH); + $status = false; + break 2; + } + + // Check each domain part + $checked = false; + foreach ($regexChars as $regexKey => $regexChar) { + ErrorHandler::start(); + $status = preg_match($regexChar, $domainPart); + ErrorHandler::stop(); + if ($status > 0) { + $length = 63; + if (array_key_exists(strtoupper($this->tld), $this->idnLength) + && (array_key_exists($regexKey, $this->idnLength[strtoupper($this->tld)]))) { + $length = $this->idnLength[strtoupper($this->tld)]; + } + + if (iconv_strlen($domainPart, 'UTF-8') > $length) { + $this->error(self::INVALID_HOSTNAME); + } else { + $checked = true; + break; + } + } + } + + if ($checked) { + ++$check; + } + } + + // If one of the labels doesn't match, the hostname is invalid + if ($check !== count($domainParts)) { + $this->error(self::INVALID_HOSTNAME_SCHEMA); + $status = false; + } + } else { + // Hostname not long enough + $this->error(self::UNDECIPHERABLE_TLD); + $status = false; + } + } while (false); + + iconv_set_encoding('internal_encoding', $origenc); + // If the input passes as an Internet domain name, and domain names are allowed, then the hostname + // passes validation + if ($status && ($this->getAllow() & self::ALLOW_DNS)) { + return true; + } + } elseif ($this->getAllow() & self::ALLOW_DNS) { + $this->error(self::INVALID_HOSTNAME); + } + + // Check for URI Syntax (RFC3986) + if ($this->getAllow() & self::ALLOW_URI) { + if (preg_match("/^([a-zA-Z0-9-._~!$&\'()*+,;=]|%[[:xdigit:]]{2}){1,254}$/i", $value)) { + return true; + } else { + $this->error(self::INVALID_URI); + } + } + + // Check input against local network name schema; last chance to pass validation + ErrorHandler::start(); + $regexLocal = '/^(([a-zA-Z0-9\x2d]{1,63}\x2e)*[a-zA-Z0-9\x2d]{1,63}[\x2e]{0,1}){1,254}$/'; + $status = preg_match($regexLocal, $value); + ErrorHandler::stop(); + + // If the input passes as a local network name, and local network names are allowed, then the + // hostname passes validation + $allowLocal = $this->getAllow() & self::ALLOW_LOCAL; + if ($status && $allowLocal) { + return true; + } + + // If the input does not pass as a local network name, add a message + if (!$status) { + $this->error(self::INVALID_LOCAL_NAME); + } + + // If local network names are not allowed, add a message + if ($status && !$allowLocal) { + $this->error(self::LOCAL_NAME_NOT_ALLOWED); + } + + return false; + } + + /** + * Decodes a punycode encoded string to it's original utf8 string + * In case of a decoding failure the original string is returned + * + * @param string $encoded Punycode encoded string to decode + * @return string + */ + protected function decodePunycode($encoded) + { + $found = preg_match('/([^a-z0-9\x2d]{1,10})$/i', $encoded); + if (empty($encoded) || ($found > 0)) { + // no punycode encoded string, return as is + $this->error(self::CANNOT_DECODE_PUNYCODE); + return false; + } + + $separator = strrpos($encoded, '-'); + if ($separator > 0) { + for ($x = 0; $x < $separator; ++$x) { + // prepare decoding matrix + $decoded[] = ord($encoded[$x]); + } + } else { + $this->error(self::CANNOT_DECODE_PUNYCODE); + return false; + } + + $lengthd = count($decoded); + $lengthe = strlen($encoded); + + // decoding + $init = true; + $base = 72; + $index = 0; + $char = 0x80; + + for ($indexe = ($separator) ? ($separator + 1) : 0; $indexe < $lengthe; ++$lengthd) { + for ($old_index = $index, $pos = 1, $key = 36; 1 ; $key += 36) { + $hex = ord($encoded[$indexe++]); + $digit = ($hex - 48 < 10) ? $hex - 22 + : (($hex - 65 < 26) ? $hex - 65 + : (($hex - 97 < 26) ? $hex - 97 + : 36)); + + $index += $digit * $pos; + $tag = ($key <= $base) ? 1 : (($key >= $base + 26) ? 26 : ($key - $base)); + if ($digit < $tag) { + break; + } + + $pos = (int) ($pos * (36 - $tag)); + } + + $delta = intval($init ? (($index - $old_index) / 700) : (($index - $old_index) / 2)); + $delta += intval($delta / ($lengthd + 1)); + for ($key = 0; $delta > 910 / 2; $key += 36) { + $delta = intval($delta / 35); + } + + $base = intval($key + 36 * $delta / ($delta + 38)); + $init = false; + $char += (int) ($index / ($lengthd + 1)); + $index %= ($lengthd + 1); + if ($lengthd > 0) { + for ($i = $lengthd; $i > $index; $i--) { + $decoded[$i] = $decoded[($i - 1)]; + } + } + + $decoded[$index++] = $char; + } + + // convert decoded ucs4 to utf8 string + foreach ($decoded as $key => $value) { + if ($value < 128) { + $decoded[$key] = chr($value); + } elseif ($value < (1 << 11)) { + $decoded[$key] = chr(192 + ($value >> 6)); + $decoded[$key] .= chr(128 + ($value & 63)); + } elseif ($value < (1 << 16)) { + $decoded[$key] = chr(224 + ($value >> 12)); + $decoded[$key] .= chr(128 + (($value >> 6) & 63)); + $decoded[$key] .= chr(128 + ($value & 63)); + } elseif ($value < (1 << 21)) { + $decoded[$key] = chr(240 + ($value >> 18)); + $decoded[$key] .= chr(128 + (($value >> 12) & 63)); + $decoded[$key] .= chr(128 + (($value >> 6) & 63)); + $decoded[$key] .= chr(128 + ($value & 63)); + } else { + $this->error(self::CANNOT_DECODE_PUNYCODE); + return false; + } + } + + return implode($decoded); + } +} diff --git a/lib/Zend/Validator/Hostname/Biz.php b/lib/Zend/Validator/Hostname/Biz.php new file mode 100644 index 0000000000000000000000000000000000000000..54b9ea50cc0c21a03311a7b7388acbe8392b1a82 --- /dev/null +++ b/lib/Zend/Validator/Hostname/Biz.php @@ -0,0 +1,2907 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Hostname; + +/** + * Resource file for biz idn validation + * + * @category Zend + * @package Zend_Validate + */ +return array( + 1 => '/^[\x{002d}0-9a-zäåæéöøü]{1,63}$/iu', + 2 => '/^[\x{002d}0-9a-záéÃñóúü]{1,63}$/iu', + 3 => '/^[\x{002d}0-9a-záéÃóöúüőű]{1,63}$/iu', + 4 => '/^[\x{002d}0-9a-záæéÃðóöúýþ]{1,63}$/iu', + 5 => '/^[\x{AC00}-\x{D7A3}]{1,17}$/iu', + 6 => '/^[\x{002d}0-9a-zÄ…Äėęįšūųž]{1,63}$/iu', + 7 => '/^[\x{002d}0-9a-zÄÄēģīķļņÅŗšūž]{1,63}$/iu', + 8 => '/^[\x{002d}0-9a-zà áä-éêñ-ôöøüÄđńŋšŧž]{1,63}$/iu', + 9 => '/^[\x{002d}0-9a-zóąćęłńśźż]{1,63}$/iu', + 10 => '/^[\x{002d}0-9a-záà âãçéêÃóôõú]{1,63}$/iu', + 11 => '/^[\x{002d}0-9a-z\x{3005}-\x{3007}\x{3041}-\x{3093}\x{309D}\x{309E}\x{30A1}-\x{30F6}\x{30FC}' . + '\x{30FD}\x{30FE}\x{4E00}\x{4E01}\x{4E03}\x{4E07}\x{4E08}\x{4E09}\x{4E0A}' . + '\x{4E0B}\x{4E0D}\x{4E0E}\x{4E10}\x{4E11}\x{4E14}\x{4E15}\x{4E16}\x{4E17}' . + '\x{4E18}\x{4E19}\x{4E1E}\x{4E21}\x{4E26}\x{4E2A}\x{4E2D}\x{4E31}\x{4E32}' . + '\x{4E36}\x{4E38}\x{4E39}\x{4E3B}\x{4E3C}\x{4E3F}\x{4E42}\x{4E43}\x{4E45}' . + '\x{4E4B}\x{4E4D}\x{4E4E}\x{4E4F}\x{4E55}\x{4E56}\x{4E57}\x{4E58}\x{4E59}' . + '\x{4E5D}\x{4E5E}\x{4E5F}\x{4E62}\x{4E71}\x{4E73}\x{4E7E}\x{4E80}\x{4E82}' . + '\x{4E85}\x{4E86}\x{4E88}\x{4E89}\x{4E8A}\x{4E8B}\x{4E8C}\x{4E8E}\x{4E91}' . + '\x{4E92}\x{4E94}\x{4E95}\x{4E98}\x{4E99}\x{4E9B}\x{4E9C}\x{4E9E}\x{4E9F}' . + '\x{4EA0}\x{4EA1}\x{4EA2}\x{4EA4}\x{4EA5}\x{4EA6}\x{4EA8}\x{4EAB}\x{4EAC}' . + '\x{4EAD}\x{4EAE}\x{4EB0}\x{4EB3}\x{4EB6}\x{4EBA}\x{4EC0}\x{4EC1}\x{4EC2}' . + '\x{4EC4}\x{4EC6}\x{4EC7}\x{4ECA}\x{4ECB}\x{4ECD}\x{4ECE}\x{4ECF}\x{4ED4}' . + '\x{4ED5}\x{4ED6}\x{4ED7}\x{4ED8}\x{4ED9}\x{4EDD}\x{4EDE}\x{4EDF}\x{4EE3}' . + '\x{4EE4}\x{4EE5}\x{4EED}\x{4EEE}\x{4EF0}\x{4EF2}\x{4EF6}\x{4EF7}\x{4EFB}' . + '\x{4F01}\x{4F09}\x{4F0A}\x{4F0D}\x{4F0E}\x{4F0F}\x{4F10}\x{4F11}\x{4F1A}' . + '\x{4F1C}\x{4F1D}\x{4F2F}\x{4F30}\x{4F34}\x{4F36}\x{4F38}\x{4F3A}\x{4F3C}' . + '\x{4F3D}\x{4F43}\x{4F46}\x{4F47}\x{4F4D}\x{4F4E}\x{4F4F}\x{4F50}\x{4F51}' . + '\x{4F53}\x{4F55}\x{4F57}\x{4F59}\x{4F5A}\x{4F5B}\x{4F5C}\x{4F5D}\x{4F5E}' . + '\x{4F69}\x{4F6F}\x{4F70}\x{4F73}\x{4F75}\x{4F76}\x{4F7B}\x{4F7C}\x{4F7F}' . + '\x{4F83}\x{4F86}\x{4F88}\x{4F8B}\x{4F8D}\x{4F8F}\x{4F91}\x{4F96}\x{4F98}' . + '\x{4F9B}\x{4F9D}\x{4FA0}\x{4FA1}\x{4FAB}\x{4FAD}\x{4FAE}\x{4FAF}\x{4FB5}' . + '\x{4FB6}\x{4FBF}\x{4FC2}\x{4FC3}\x{4FC4}\x{4FCA}\x{4FCE}\x{4FD0}\x{4FD1}' . + '\x{4FD4}\x{4FD7}\x{4FD8}\x{4FDA}\x{4FDB}\x{4FDD}\x{4FDF}\x{4FE1}\x{4FE3}' . + '\x{4FE4}\x{4FE5}\x{4FEE}\x{4FEF}\x{4FF3}\x{4FF5}\x{4FF6}\x{4FF8}\x{4FFA}' . + '\x{4FFE}\x{5005}\x{5006}\x{5009}\x{500B}\x{500D}\x{500F}\x{5011}\x{5012}' . + '\x{5014}\x{5016}\x{5019}\x{501A}\x{501F}\x{5021}\x{5023}\x{5024}\x{5025}' . + '\x{5026}\x{5028}\x{5029}\x{502A}\x{502B}\x{502C}\x{502D}\x{5036}\x{5039}' . + '\x{5043}\x{5047}\x{5048}\x{5049}\x{504F}\x{5050}\x{5055}\x{5056}\x{505A}' . + '\x{505C}\x{5065}\x{506C}\x{5072}\x{5074}\x{5075}\x{5076}\x{5078}\x{507D}' . + '\x{5080}\x{5085}\x{508D}\x{5091}\x{5098}\x{5099}\x{509A}\x{50AC}\x{50AD}' . + '\x{50B2}\x{50B3}\x{50B4}\x{50B5}\x{50B7}\x{50BE}\x{50C2}\x{50C5}\x{50C9}' . + '\x{50CA}\x{50CD}\x{50CF}\x{50D1}\x{50D5}\x{50D6}\x{50DA}\x{50DE}\x{50E3}' . + '\x{50E5}\x{50E7}\x{50ED}\x{50EE}\x{50F5}\x{50F9}\x{50FB}\x{5100}\x{5101}' . + '\x{5102}\x{5104}\x{5109}\x{5112}\x{5114}\x{5115}\x{5116}\x{5118}\x{511A}' . + '\x{511F}\x{5121}\x{512A}\x{5132}\x{5137}\x{513A}\x{513B}\x{513C}\x{513F}' . + '\x{5140}\x{5141}\x{5143}\x{5144}\x{5145}\x{5146}\x{5147}\x{5148}\x{5149}' . + '\x{514B}\x{514C}\x{514D}\x{514E}\x{5150}\x{5152}\x{5154}\x{515A}\x{515C}' . + '\x{5162}\x{5165}\x{5168}\x{5169}\x{516A}\x{516B}\x{516C}\x{516D}\x{516E}' . + '\x{5171}\x{5175}\x{5176}\x{5177}\x{5178}\x{517C}\x{5180}\x{5182}\x{5185}' . + '\x{5186}\x{5189}\x{518A}\x{518C}\x{518D}\x{518F}\x{5190}\x{5191}\x{5192}' . + '\x{5193}\x{5195}\x{5196}\x{5197}\x{5199}\x{51A0}\x{51A2}\x{51A4}\x{51A5}' . + '\x{51A6}\x{51A8}\x{51A9}\x{51AA}\x{51AB}\x{51AC}\x{51B0}\x{51B1}\x{51B2}' . + '\x{51B3}\x{51B4}\x{51B5}\x{51B6}\x{51B7}\x{51BD}\x{51C4}\x{51C5}\x{51C6}' . + '\x{51C9}\x{51CB}\x{51CC}\x{51CD}\x{51D6}\x{51DB}\x{51DC}\x{51DD}\x{51E0}' . + '\x{51E1}\x{51E6}\x{51E7}\x{51E9}\x{51EA}\x{51ED}\x{51F0}\x{51F1}\x{51F5}' . + '\x{51F6}\x{51F8}\x{51F9}\x{51FA}\x{51FD}\x{51FE}\x{5200}\x{5203}\x{5204}' . + '\x{5206}\x{5207}\x{5208}\x{520A}\x{520B}\x{520E}\x{5211}\x{5214}\x{5217}' . + '\x{521D}\x{5224}\x{5225}\x{5227}\x{5229}\x{522A}\x{522E}\x{5230}\x{5233}' . + '\x{5236}\x{5237}\x{5238}\x{5239}\x{523A}\x{523B}\x{5243}\x{5244}\x{5247}' . + '\x{524A}\x{524B}\x{524C}\x{524D}\x{524F}\x{5254}\x{5256}\x{525B}\x{525E}' . + '\x{5263}\x{5264}\x{5265}\x{5269}\x{526A}\x{526F}\x{5270}\x{5271}\x{5272}' . + '\x{5273}\x{5274}\x{5275}\x{527D}\x{527F}\x{5283}\x{5287}\x{5288}\x{5289}' . + '\x{528D}\x{5291}\x{5292}\x{5294}\x{529B}\x{529F}\x{52A0}\x{52A3}\x{52A9}' . + '\x{52AA}\x{52AB}\x{52AC}\x{52AD}\x{52B1}\x{52B4}\x{52B5}\x{52B9}\x{52BC}' . + '\x{52BE}\x{52C1}\x{52C3}\x{52C5}\x{52C7}\x{52C9}\x{52CD}\x{52D2}\x{52D5}' . + '\x{52D7}\x{52D8}\x{52D9}\x{52DD}\x{52DE}\x{52DF}\x{52E0}\x{52E2}\x{52E3}' . + '\x{52E4}\x{52E6}\x{52E7}\x{52F2}\x{52F3}\x{52F5}\x{52F8}\x{52F9}\x{52FA}' . + '\x{52FE}\x{52FF}\x{5301}\x{5302}\x{5305}\x{5306}\x{5308}\x{530D}\x{530F}' . + '\x{5310}\x{5315}\x{5316}\x{5317}\x{5319}\x{531A}\x{531D}\x{5320}\x{5321}' . + '\x{5323}\x{532A}\x{532F}\x{5331}\x{5333}\x{5338}\x{5339}\x{533A}\x{533B}' . + '\x{533F}\x{5340}\x{5341}\x{5343}\x{5345}\x{5346}\x{5347}\x{5348}\x{5349}' . + '\x{534A}\x{534D}\x{5351}\x{5352}\x{5353}\x{5354}\x{5357}\x{5358}\x{535A}' . + '\x{535C}\x{535E}\x{5360}\x{5366}\x{5369}\x{536E}\x{536F}\x{5370}\x{5371}' . + '\x{5373}\x{5374}\x{5375}\x{5377}\x{5378}\x{537B}\x{537F}\x{5382}\x{5384}' . + '\x{5396}\x{5398}\x{539A}\x{539F}\x{53A0}\x{53A5}\x{53A6}\x{53A8}\x{53A9}' . + '\x{53AD}\x{53AE}\x{53B0}\x{53B3}\x{53B6}\x{53BB}\x{53C2}\x{53C3}\x{53C8}' . + '\x{53C9}\x{53CA}\x{53CB}\x{53CC}\x{53CD}\x{53CE}\x{53D4}\x{53D6}\x{53D7}' . + '\x{53D9}\x{53DB}\x{53DF}\x{53E1}\x{53E2}\x{53E3}\x{53E4}\x{53E5}\x{53E8}' . + '\x{53E9}\x{53EA}\x{53EB}\x{53EC}\x{53ED}\x{53EE}\x{53EF}\x{53F0}\x{53F1}' . + '\x{53F2}\x{53F3}\x{53F6}\x{53F7}\x{53F8}\x{53FA}\x{5401}\x{5403}\x{5404}' . + '\x{5408}\x{5409}\x{540A}\x{540B}\x{540C}\x{540D}\x{540E}\x{540F}\x{5410}' . + '\x{5411}\x{541B}\x{541D}\x{541F}\x{5420}\x{5426}\x{5429}\x{542B}\x{542C}' . + '\x{542D}\x{542E}\x{5436}\x{5438}\x{5439}\x{543B}\x{543C}\x{543D}\x{543E}' . + '\x{5440}\x{5442}\x{5446}\x{5448}\x{5449}\x{544A}\x{544E}\x{5451}\x{545F}' . + '\x{5468}\x{546A}\x{5470}\x{5471}\x{5473}\x{5475}\x{5476}\x{5477}\x{547B}' . + '\x{547C}\x{547D}\x{5480}\x{5484}\x{5486}\x{548B}\x{548C}\x{548E}\x{548F}' . + '\x{5490}\x{5492}\x{54A2}\x{54A4}\x{54A5}\x{54A8}\x{54AB}\x{54AC}\x{54AF}' . + '\x{54B2}\x{54B3}\x{54B8}\x{54BC}\x{54BD}\x{54BE}\x{54C0}\x{54C1}\x{54C2}' . + '\x{54C4}\x{54C7}\x{54C8}\x{54C9}\x{54D8}\x{54E1}\x{54E2}\x{54E5}\x{54E6}' . + '\x{54E8}\x{54E9}\x{54ED}\x{54EE}\x{54F2}\x{54FA}\x{54FD}\x{5504}\x{5506}' . + '\x{5507}\x{550F}\x{5510}\x{5514}\x{5516}\x{552E}\x{552F}\x{5531}\x{5533}' . + '\x{5538}\x{5539}\x{553E}\x{5540}\x{5544}\x{5545}\x{5546}\x{554C}\x{554F}' . + '\x{5553}\x{5556}\x{5557}\x{555C}\x{555D}\x{5563}\x{557B}\x{557C}\x{557E}' . + '\x{5580}\x{5583}\x{5584}\x{5587}\x{5589}\x{558A}\x{558B}\x{5598}\x{5599}' . + '\x{559A}\x{559C}\x{559D}\x{559E}\x{559F}\x{55A7}\x{55A8}\x{55A9}\x{55AA}' . + '\x{55AB}\x{55AC}\x{55AE}\x{55B0}\x{55B6}\x{55C4}\x{55C5}\x{55C7}\x{55D4}' . + '\x{55DA}\x{55DC}\x{55DF}\x{55E3}\x{55E4}\x{55F7}\x{55F9}\x{55FD}\x{55FE}' . + '\x{5606}\x{5609}\x{5614}\x{5616}\x{5617}\x{5618}\x{561B}\x{5629}\x{562F}' . + '\x{5631}\x{5632}\x{5634}\x{5636}\x{5638}\x{5642}\x{564C}\x{564E}\x{5650}' . + '\x{565B}\x{5664}\x{5668}\x{566A}\x{566B}\x{566C}\x{5674}\x{5678}\x{567A}' . + '\x{5680}\x{5686}\x{5687}\x{568A}\x{568F}\x{5694}\x{56A0}\x{56A2}\x{56A5}' . + '\x{56AE}\x{56B4}\x{56B6}\x{56BC}\x{56C0}\x{56C1}\x{56C2}\x{56C3}\x{56C8}' . + '\x{56CE}\x{56D1}\x{56D3}\x{56D7}\x{56D8}\x{56DA}\x{56DB}\x{56DE}\x{56E0}' . + '\x{56E3}\x{56EE}\x{56F0}\x{56F2}\x{56F3}\x{56F9}\x{56FA}\x{56FD}\x{56FF}' . + '\x{5700}\x{5703}\x{5704}\x{5708}\x{5709}\x{570B}\x{570D}\x{570F}\x{5712}' . + '\x{5713}\x{5716}\x{5718}\x{571C}\x{571F}\x{5726}\x{5727}\x{5728}\x{572D}' . + '\x{5730}\x{5737}\x{5738}\x{573B}\x{5740}\x{5742}\x{5747}\x{574A}\x{574E}' . + '\x{574F}\x{5750}\x{5751}\x{5761}\x{5764}\x{5766}\x{5769}\x{576A}\x{577F}' . + '\x{5782}\x{5788}\x{5789}\x{578B}\x{5793}\x{57A0}\x{57A2}\x{57A3}\x{57A4}' . + '\x{57AA}\x{57B0}\x{57B3}\x{57C0}\x{57C3}\x{57C6}\x{57CB}\x{57CE}\x{57D2}' . + '\x{57D3}\x{57D4}\x{57D6}\x{57DC}\x{57DF}\x{57E0}\x{57E3}\x{57F4}\x{57F7}' . + '\x{57F9}\x{57FA}\x{57FC}\x{5800}\x{5802}\x{5805}\x{5806}\x{580A}\x{580B}' . + '\x{5815}\x{5819}\x{581D}\x{5821}\x{5824}\x{582A}\x{582F}\x{5830}\x{5831}' . + '\x{5834}\x{5835}\x{583A}\x{583D}\x{5840}\x{5841}\x{584A}\x{584B}\x{5851}' . + '\x{5852}\x{5854}\x{5857}\x{5858}\x{5859}\x{585A}\x{585E}\x{5862}\x{5869}' . + '\x{586B}\x{5870}\x{5872}\x{5875}\x{5879}\x{587E}\x{5883}\x{5885}\x{5893}' . + '\x{5897}\x{589C}\x{589F}\x{58A8}\x{58AB}\x{58AE}\x{58B3}\x{58B8}\x{58B9}' . + '\x{58BA}\x{58BB}\x{58BE}\x{58C1}\x{58C5}\x{58C7}\x{58CA}\x{58CC}\x{58D1}' . + '\x{58D3}\x{58D5}\x{58D7}\x{58D8}\x{58D9}\x{58DC}\x{58DE}\x{58DF}\x{58E4}' . + '\x{58E5}\x{58EB}\x{58EC}\x{58EE}\x{58EF}\x{58F0}\x{58F1}\x{58F2}\x{58F7}' . + '\x{58F9}\x{58FA}\x{58FB}\x{58FC}\x{58FD}\x{5902}\x{5909}\x{590A}\x{590F}' . + '\x{5910}\x{5915}\x{5916}\x{5918}\x{5919}\x{591A}\x{591B}\x{591C}\x{5922}' . + '\x{5925}\x{5927}\x{5929}\x{592A}\x{592B}\x{592C}\x{592D}\x{592E}\x{5931}' . + '\x{5932}\x{5937}\x{5938}\x{593E}\x{5944}\x{5947}\x{5948}\x{5949}\x{594E}' . + '\x{594F}\x{5950}\x{5951}\x{5954}\x{5955}\x{5957}\x{5958}\x{595A}\x{5960}' . + '\x{5962}\x{5965}\x{5967}\x{5968}\x{5969}\x{596A}\x{596C}\x{596E}\x{5973}' . + '\x{5974}\x{5978}\x{597D}\x{5981}\x{5982}\x{5983}\x{5984}\x{598A}\x{598D}' . + '\x{5993}\x{5996}\x{5999}\x{599B}\x{599D}\x{59A3}\x{59A5}\x{59A8}\x{59AC}' . + '\x{59B2}\x{59B9}\x{59BB}\x{59BE}\x{59C6}\x{59C9}\x{59CB}\x{59D0}\x{59D1}' . + '\x{59D3}\x{59D4}\x{59D9}\x{59DA}\x{59DC}\x{59E5}\x{59E6}\x{59E8}\x{59EA}' . + '\x{59EB}\x{59F6}\x{59FB}\x{59FF}\x{5A01}\x{5A03}\x{5A09}\x{5A11}\x{5A18}' . + '\x{5A1A}\x{5A1C}\x{5A1F}\x{5A20}\x{5A25}\x{5A29}\x{5A2F}\x{5A35}\x{5A36}' . + '\x{5A3C}\x{5A40}\x{5A41}\x{5A46}\x{5A49}\x{5A5A}\x{5A62}\x{5A66}\x{5A6A}' . + '\x{5A6C}\x{5A7F}\x{5A92}\x{5A9A}\x{5A9B}\x{5ABC}\x{5ABD}\x{5ABE}\x{5AC1}' . + '\x{5AC2}\x{5AC9}\x{5ACB}\x{5ACC}\x{5AD0}\x{5AD6}\x{5AD7}\x{5AE1}\x{5AE3}' . + '\x{5AE6}\x{5AE9}\x{5AFA}\x{5AFB}\x{5B09}\x{5B0B}\x{5B0C}\x{5B16}\x{5B22}' . + '\x{5B2A}\x{5B2C}\x{5B30}\x{5B32}\x{5B36}\x{5B3E}\x{5B40}\x{5B43}\x{5B45}' . + '\x{5B50}\x{5B51}\x{5B54}\x{5B55}\x{5B57}\x{5B58}\x{5B5A}\x{5B5B}\x{5B5C}' . + '\x{5B5D}\x{5B5F}\x{5B63}\x{5B64}\x{5B65}\x{5B66}\x{5B69}\x{5B6B}\x{5B70}' . + '\x{5B71}\x{5B73}\x{5B75}\x{5B78}\x{5B7A}\x{5B80}\x{5B83}\x{5B85}\x{5B87}' . + '\x{5B88}\x{5B89}\x{5B8B}\x{5B8C}\x{5B8D}\x{5B8F}\x{5B95}\x{5B97}\x{5B98}' . + '\x{5B99}\x{5B9A}\x{5B9B}\x{5B9C}\x{5B9D}\x{5B9F}\x{5BA2}\x{5BA3}\x{5BA4}' . + '\x{5BA5}\x{5BA6}\x{5BAE}\x{5BB0}\x{5BB3}\x{5BB4}\x{5BB5}\x{5BB6}\x{5BB8}' . + '\x{5BB9}\x{5BBF}\x{5BC2}\x{5BC3}\x{5BC4}\x{5BC5}\x{5BC6}\x{5BC7}\x{5BC9}' . + '\x{5BCC}\x{5BD0}\x{5BD2}\x{5BD3}\x{5BD4}\x{5BDB}\x{5BDD}\x{5BDE}\x{5BDF}' . + '\x{5BE1}\x{5BE2}\x{5BE4}\x{5BE5}\x{5BE6}\x{5BE7}\x{5BE8}\x{5BE9}\x{5BEB}' . + '\x{5BEE}\x{5BF0}\x{5BF3}\x{5BF5}\x{5BF6}\x{5BF8}\x{5BFA}\x{5BFE}\x{5BFF}' . + '\x{5C01}\x{5C02}\x{5C04}\x{5C05}\x{5C06}\x{5C07}\x{5C08}\x{5C09}\x{5C0A}' . + '\x{5C0B}\x{5C0D}\x{5C0E}\x{5C0F}\x{5C11}\x{5C13}\x{5C16}\x{5C1A}\x{5C20}' . + '\x{5C22}\x{5C24}\x{5C28}\x{5C2D}\x{5C31}\x{5C38}\x{5C39}\x{5C3A}\x{5C3B}' . + '\x{5C3C}\x{5C3D}\x{5C3E}\x{5C3F}\x{5C40}\x{5C41}\x{5C45}\x{5C46}\x{5C48}' . + '\x{5C4A}\x{5C4B}\x{5C4D}\x{5C4E}\x{5C4F}\x{5C50}\x{5C51}\x{5C53}\x{5C55}' . + '\x{5C5E}\x{5C60}\x{5C61}\x{5C64}\x{5C65}\x{5C6C}\x{5C6E}\x{5C6F}\x{5C71}' . + '\x{5C76}\x{5C79}\x{5C8C}\x{5C90}\x{5C91}\x{5C94}\x{5CA1}\x{5CA8}\x{5CA9}' . + '\x{5CAB}\x{5CAC}\x{5CB1}\x{5CB3}\x{5CB6}\x{5CB7}\x{5CB8}\x{5CBB}\x{5CBC}' . + '\x{5CBE}\x{5CC5}\x{5CC7}\x{5CD9}\x{5CE0}\x{5CE1}\x{5CE8}\x{5CE9}\x{5CEA}' . + '\x{5CED}\x{5CEF}\x{5CF0}\x{5CF6}\x{5CFA}\x{5CFB}\x{5CFD}\x{5D07}\x{5D0B}' . + '\x{5D0E}\x{5D11}\x{5D14}\x{5D15}\x{5D16}\x{5D17}\x{5D18}\x{5D19}\x{5D1A}' . + '\x{5D1B}\x{5D1F}\x{5D22}\x{5D29}\x{5D4B}\x{5D4C}\x{5D4E}\x{5D50}\x{5D52}' . + '\x{5D5C}\x{5D69}\x{5D6C}\x{5D6F}\x{5D73}\x{5D76}\x{5D82}\x{5D84}\x{5D87}' . + '\x{5D8B}\x{5D8C}\x{5D90}\x{5D9D}\x{5DA2}\x{5DAC}\x{5DAE}\x{5DB7}\x{5DBA}' . + '\x{5DBC}\x{5DBD}\x{5DC9}\x{5DCC}\x{5DCD}\x{5DD2}\x{5DD3}\x{5DD6}\x{5DDB}' . + '\x{5DDD}\x{5DDE}\x{5DE1}\x{5DE3}\x{5DE5}\x{5DE6}\x{5DE7}\x{5DE8}\x{5DEB}' . + '\x{5DEE}\x{5DF1}\x{5DF2}\x{5DF3}\x{5DF4}\x{5DF5}\x{5DF7}\x{5DFB}\x{5DFD}' . + '\x{5DFE}\x{5E02}\x{5E03}\x{5E06}\x{5E0B}\x{5E0C}\x{5E11}\x{5E16}\x{5E19}' . + '\x{5E1A}\x{5E1B}\x{5E1D}\x{5E25}\x{5E2B}\x{5E2D}\x{5E2F}\x{5E30}\x{5E33}' . + '\x{5E36}\x{5E37}\x{5E38}\x{5E3D}\x{5E40}\x{5E43}\x{5E44}\x{5E45}\x{5E47}' . + '\x{5E4C}\x{5E4E}\x{5E54}\x{5E55}\x{5E57}\x{5E5F}\x{5E61}\x{5E62}\x{5E63}' . + '\x{5E64}\x{5E72}\x{5E73}\x{5E74}\x{5E75}\x{5E76}\x{5E78}\x{5E79}\x{5E7A}' . + '\x{5E7B}\x{5E7C}\x{5E7D}\x{5E7E}\x{5E7F}\x{5E81}\x{5E83}\x{5E84}\x{5E87}' . + '\x{5E8A}\x{5E8F}\x{5E95}\x{5E96}\x{5E97}\x{5E9A}\x{5E9C}\x{5EA0}\x{5EA6}' . + '\x{5EA7}\x{5EAB}\x{5EAD}\x{5EB5}\x{5EB6}\x{5EB7}\x{5EB8}\x{5EC1}\x{5EC2}' . + '\x{5EC3}\x{5EC8}\x{5EC9}\x{5ECA}\x{5ECF}\x{5ED0}\x{5ED3}\x{5ED6}\x{5EDA}' . + '\x{5EDB}\x{5EDD}\x{5EDF}\x{5EE0}\x{5EE1}\x{5EE2}\x{5EE3}\x{5EE8}\x{5EE9}' . + '\x{5EEC}\x{5EF0}\x{5EF1}\x{5EF3}\x{5EF4}\x{5EF6}\x{5EF7}\x{5EF8}\x{5EFA}' . + '\x{5EFB}\x{5EFC}\x{5EFE}\x{5EFF}\x{5F01}\x{5F03}\x{5F04}\x{5F09}\x{5F0A}' . + '\x{5F0B}\x{5F0C}\x{5F0D}\x{5F0F}\x{5F10}\x{5F11}\x{5F13}\x{5F14}\x{5F15}' . + '\x{5F16}\x{5F17}\x{5F18}\x{5F1B}\x{5F1F}\x{5F25}\x{5F26}\x{5F27}\x{5F29}' . + '\x{5F2D}\x{5F2F}\x{5F31}\x{5F35}\x{5F37}\x{5F38}\x{5F3C}\x{5F3E}\x{5F41}' . + '\x{5F48}\x{5F4A}\x{5F4C}\x{5F4E}\x{5F51}\x{5F53}\x{5F56}\x{5F57}\x{5F59}' . + '\x{5F5C}\x{5F5D}\x{5F61}\x{5F62}\x{5F66}\x{5F69}\x{5F6A}\x{5F6B}\x{5F6C}' . + '\x{5F6D}\x{5F70}\x{5F71}\x{5F73}\x{5F77}\x{5F79}\x{5F7C}\x{5F7F}\x{5F80}' . + '\x{5F81}\x{5F82}\x{5F83}\x{5F84}\x{5F85}\x{5F87}\x{5F88}\x{5F8A}\x{5F8B}' . + '\x{5F8C}\x{5F90}\x{5F91}\x{5F92}\x{5F93}\x{5F97}\x{5F98}\x{5F99}\x{5F9E}' . + '\x{5FA0}\x{5FA1}\x{5FA8}\x{5FA9}\x{5FAA}\x{5FAD}\x{5FAE}\x{5FB3}\x{5FB4}' . + '\x{5FB9}\x{5FBC}\x{5FBD}\x{5FC3}\x{5FC5}\x{5FCC}\x{5FCD}\x{5FD6}\x{5FD7}' . + '\x{5FD8}\x{5FD9}\x{5FDC}\x{5FDD}\x{5FE0}\x{5FE4}\x{5FEB}\x{5FF0}\x{5FF1}' . + '\x{5FF5}\x{5FF8}\x{5FFB}\x{5FFD}\x{5FFF}\x{600E}\x{600F}\x{6010}\x{6012}' . + '\x{6015}\x{6016}\x{6019}\x{601B}\x{601C}\x{601D}\x{6020}\x{6021}\x{6025}' . + '\x{6026}\x{6027}\x{6028}\x{6029}\x{602A}\x{602B}\x{602F}\x{6031}\x{603A}' . + '\x{6041}\x{6042}\x{6043}\x{6046}\x{604A}\x{604B}\x{604D}\x{6050}\x{6052}' . + '\x{6055}\x{6059}\x{605A}\x{605F}\x{6060}\x{6062}\x{6063}\x{6064}\x{6065}' . + '\x{6068}\x{6069}\x{606A}\x{606B}\x{606C}\x{606D}\x{606F}\x{6070}\x{6075}' . + '\x{6077}\x{6081}\x{6083}\x{6084}\x{6089}\x{608B}\x{608C}\x{608D}\x{6092}' . + '\x{6094}\x{6096}\x{6097}\x{609A}\x{609B}\x{609F}\x{60A0}\x{60A3}\x{60A6}' . + '\x{60A7}\x{60A9}\x{60AA}\x{60B2}\x{60B3}\x{60B4}\x{60B5}\x{60B6}\x{60B8}' . + '\x{60BC}\x{60BD}\x{60C5}\x{60C6}\x{60C7}\x{60D1}\x{60D3}\x{60D8}\x{60DA}' . + '\x{60DC}\x{60DF}\x{60E0}\x{60E1}\x{60E3}\x{60E7}\x{60E8}\x{60F0}\x{60F1}' . + '\x{60F3}\x{60F4}\x{60F6}\x{60F7}\x{60F9}\x{60FA}\x{60FB}\x{6100}\x{6101}' . + '\x{6103}\x{6106}\x{6108}\x{6109}\x{610D}\x{610E}\x{610F}\x{6115}\x{611A}' . + '\x{611B}\x{611F}\x{6121}\x{6127}\x{6128}\x{612C}\x{6134}\x{613C}\x{613D}' . + '\x{613E}\x{613F}\x{6142}\x{6144}\x{6147}\x{6148}\x{614A}\x{614B}\x{614C}' . + '\x{614D}\x{614E}\x{6153}\x{6155}\x{6158}\x{6159}\x{615A}\x{615D}\x{615F}' . + '\x{6162}\x{6163}\x{6165}\x{6167}\x{6168}\x{616B}\x{616E}\x{616F}\x{6170}' . + '\x{6171}\x{6173}\x{6174}\x{6175}\x{6176}\x{6177}\x{617E}\x{6182}\x{6187}' . + '\x{618A}\x{618E}\x{6190}\x{6191}\x{6194}\x{6196}\x{6199}\x{619A}\x{61A4}' . + '\x{61A7}\x{61A9}\x{61AB}\x{61AC}\x{61AE}\x{61B2}\x{61B6}\x{61BA}\x{61BE}' . + '\x{61C3}\x{61C6}\x{61C7}\x{61C8}\x{61C9}\x{61CA}\x{61CB}\x{61CC}\x{61CD}' . + '\x{61D0}\x{61E3}\x{61E6}\x{61F2}\x{61F4}\x{61F6}\x{61F7}\x{61F8}\x{61FA}' . + '\x{61FC}\x{61FD}\x{61FE}\x{61FF}\x{6200}\x{6208}\x{6209}\x{620A}\x{620C}' . + '\x{620D}\x{620E}\x{6210}\x{6211}\x{6212}\x{6214}\x{6216}\x{621A}\x{621B}' . + '\x{621D}\x{621E}\x{621F}\x{6221}\x{6226}\x{622A}\x{622E}\x{622F}\x{6230}' . + '\x{6232}\x{6233}\x{6234}\x{6238}\x{623B}\x{623F}\x{6240}\x{6241}\x{6247}' . + '\x{6248}\x{6249}\x{624B}\x{624D}\x{624E}\x{6253}\x{6255}\x{6258}\x{625B}' . + '\x{625E}\x{6260}\x{6263}\x{6268}\x{626E}\x{6271}\x{6276}\x{6279}\x{627C}' . + '\x{627E}\x{627F}\x{6280}\x{6282}\x{6283}\x{6284}\x{6289}\x{628A}\x{6291}' . + '\x{6292}\x{6293}\x{6294}\x{6295}\x{6296}\x{6297}\x{6298}\x{629B}\x{629C}' . + '\x{629E}\x{62AB}\x{62AC}\x{62B1}\x{62B5}\x{62B9}\x{62BB}\x{62BC}\x{62BD}' . + '\x{62C2}\x{62C5}\x{62C6}\x{62C7}\x{62C8}\x{62C9}\x{62CA}\x{62CC}\x{62CD}' . + '\x{62CF}\x{62D0}\x{62D1}\x{62D2}\x{62D3}\x{62D4}\x{62D7}\x{62D8}\x{62D9}' . + '\x{62DB}\x{62DC}\x{62DD}\x{62E0}\x{62E1}\x{62EC}\x{62ED}\x{62EE}\x{62EF}' . + '\x{62F1}\x{62F3}\x{62F5}\x{62F6}\x{62F7}\x{62FE}\x{62FF}\x{6301}\x{6302}' . + '\x{6307}\x{6308}\x{6309}\x{630C}\x{6311}\x{6319}\x{631F}\x{6327}\x{6328}' . + '\x{632B}\x{632F}\x{633A}\x{633D}\x{633E}\x{633F}\x{6349}\x{634C}\x{634D}' . + '\x{634F}\x{6350}\x{6355}\x{6357}\x{635C}\x{6367}\x{6368}\x{6369}\x{636B}' . + '\x{636E}\x{6372}\x{6376}\x{6377}\x{637A}\x{637B}\x{6380}\x{6383}\x{6388}' . + '\x{6389}\x{638C}\x{638E}\x{638F}\x{6392}\x{6396}\x{6398}\x{639B}\x{639F}' . + '\x{63A0}\x{63A1}\x{63A2}\x{63A3}\x{63A5}\x{63A7}\x{63A8}\x{63A9}\x{63AA}' . + '\x{63AB}\x{63AC}\x{63B2}\x{63B4}\x{63B5}\x{63BB}\x{63BE}\x{63C0}\x{63C3}' . + '\x{63C4}\x{63C6}\x{63C9}\x{63CF}\x{63D0}\x{63D2}\x{63D6}\x{63DA}\x{63DB}' . + '\x{63E1}\x{63E3}\x{63E9}\x{63EE}\x{63F4}\x{63F6}\x{63FA}\x{6406}\x{640D}' . + '\x{640F}\x{6413}\x{6416}\x{6417}\x{641C}\x{6426}\x{6428}\x{642C}\x{642D}' . + '\x{6434}\x{6436}\x{643A}\x{643E}\x{6442}\x{644E}\x{6458}\x{6467}\x{6469}' . + '\x{646F}\x{6476}\x{6478}\x{647A}\x{6483}\x{6488}\x{6492}\x{6493}\x{6495}' . + '\x{649A}\x{649E}\x{64A4}\x{64A5}\x{64A9}\x{64AB}\x{64AD}\x{64AE}\x{64B0}' . + '\x{64B2}\x{64B9}\x{64BB}\x{64BC}\x{64C1}\x{64C2}\x{64C5}\x{64C7}\x{64CD}' . + '\x{64D2}\x{64D4}\x{64D8}\x{64DA}\x{64E0}\x{64E1}\x{64E2}\x{64E3}\x{64E6}' . + '\x{64E7}\x{64EC}\x{64EF}\x{64F1}\x{64F2}\x{64F4}\x{64F6}\x{64FA}\x{64FD}' . + '\x{64FE}\x{6500}\x{6505}\x{6518}\x{651C}\x{651D}\x{6523}\x{6524}\x{652A}' . + '\x{652B}\x{652C}\x{652F}\x{6534}\x{6535}\x{6536}\x{6537}\x{6538}\x{6539}' . + '\x{653B}\x{653E}\x{653F}\x{6545}\x{6548}\x{654D}\x{654F}\x{6551}\x{6555}' . + '\x{6556}\x{6557}\x{6558}\x{6559}\x{655D}\x{655E}\x{6562}\x{6563}\x{6566}' . + '\x{656C}\x{6570}\x{6572}\x{6574}\x{6575}\x{6577}\x{6578}\x{6582}\x{6583}' . + '\x{6587}\x{6588}\x{6589}\x{658C}\x{658E}\x{6590}\x{6591}\x{6597}\x{6599}' . + '\x{659B}\x{659C}\x{659F}\x{65A1}\x{65A4}\x{65A5}\x{65A7}\x{65AB}\x{65AC}' . + '\x{65AD}\x{65AF}\x{65B0}\x{65B7}\x{65B9}\x{65BC}\x{65BD}\x{65C1}\x{65C3}' . + '\x{65C4}\x{65C5}\x{65C6}\x{65CB}\x{65CC}\x{65CF}\x{65D2}\x{65D7}\x{65D9}' . + '\x{65DB}\x{65E0}\x{65E1}\x{65E2}\x{65E5}\x{65E6}\x{65E7}\x{65E8}\x{65E9}' . + '\x{65EC}\x{65ED}\x{65F1}\x{65FA}\x{65FB}\x{6602}\x{6603}\x{6606}\x{6607}' . + '\x{660A}\x{660C}\x{660E}\x{660F}\x{6613}\x{6614}\x{661C}\x{661F}\x{6620}' . + '\x{6625}\x{6627}\x{6628}\x{662D}\x{662F}\x{6634}\x{6635}\x{6636}\x{663C}' . + '\x{663F}\x{6641}\x{6642}\x{6643}\x{6644}\x{6649}\x{664B}\x{664F}\x{6652}' . + '\x{665D}\x{665E}\x{665F}\x{6662}\x{6664}\x{6666}\x{6667}\x{6668}\x{6669}' . + '\x{666E}\x{666F}\x{6670}\x{6674}\x{6676}\x{667A}\x{6681}\x{6683}\x{6684}' . + '\x{6687}\x{6688}\x{6689}\x{668E}\x{6691}\x{6696}\x{6697}\x{6698}\x{669D}' . + '\x{66A2}\x{66A6}\x{66AB}\x{66AE}\x{66B4}\x{66B8}\x{66B9}\x{66BC}\x{66BE}' . + '\x{66C1}\x{66C4}\x{66C7}\x{66C9}\x{66D6}\x{66D9}\x{66DA}\x{66DC}\x{66DD}' . + '\x{66E0}\x{66E6}\x{66E9}\x{66F0}\x{66F2}\x{66F3}\x{66F4}\x{66F5}\x{66F7}' . + '\x{66F8}\x{66F9}\x{66FC}\x{66FD}\x{66FE}\x{66FF}\x{6700}\x{6703}\x{6708}' . + '\x{6709}\x{670B}\x{670D}\x{670F}\x{6714}\x{6715}\x{6716}\x{6717}\x{671B}' . + '\x{671D}\x{671E}\x{671F}\x{6726}\x{6727}\x{6728}\x{672A}\x{672B}\x{672C}' . + '\x{672D}\x{672E}\x{6731}\x{6734}\x{6736}\x{6737}\x{6738}\x{673A}\x{673D}' . + '\x{673F}\x{6741}\x{6746}\x{6749}\x{674E}\x{674F}\x{6750}\x{6751}\x{6753}' . + '\x{6756}\x{6759}\x{675C}\x{675E}\x{675F}\x{6760}\x{6761}\x{6762}\x{6763}' . + '\x{6764}\x{6765}\x{676A}\x{676D}\x{676F}\x{6770}\x{6771}\x{6772}\x{6773}' . + '\x{6775}\x{6777}\x{677C}\x{677E}\x{677F}\x{6785}\x{6787}\x{6789}\x{678B}' . + '\x{678C}\x{6790}\x{6795}\x{6797}\x{679A}\x{679C}\x{679D}\x{67A0}\x{67A1}' . + '\x{67A2}\x{67A6}\x{67A9}\x{67AF}\x{67B3}\x{67B4}\x{67B6}\x{67B7}\x{67B8}' . + '\x{67B9}\x{67C1}\x{67C4}\x{67C6}\x{67CA}\x{67CE}\x{67CF}\x{67D0}\x{67D1}' . + '\x{67D3}\x{67D4}\x{67D8}\x{67DA}\x{67DD}\x{67DE}\x{67E2}\x{67E4}\x{67E7}' . + '\x{67E9}\x{67EC}\x{67EE}\x{67EF}\x{67F1}\x{67F3}\x{67F4}\x{67F5}\x{67FB}' . + '\x{67FE}\x{67FF}\x{6802}\x{6803}\x{6804}\x{6813}\x{6816}\x{6817}\x{681E}' . + '\x{6821}\x{6822}\x{6829}\x{682A}\x{682B}\x{6832}\x{6834}\x{6838}\x{6839}' . + '\x{683C}\x{683D}\x{6840}\x{6841}\x{6842}\x{6843}\x{6846}\x{6848}\x{684D}' . + '\x{684E}\x{6850}\x{6851}\x{6853}\x{6854}\x{6859}\x{685C}\x{685D}\x{685F}' . + '\x{6863}\x{6867}\x{6874}\x{6876}\x{6877}\x{687E}\x{687F}\x{6881}\x{6883}' . + '\x{6885}\x{688D}\x{688F}\x{6893}\x{6894}\x{6897}\x{689B}\x{689D}\x{689F}' . + '\x{68A0}\x{68A2}\x{68A6}\x{68A7}\x{68A8}\x{68AD}\x{68AF}\x{68B0}\x{68B1}' . + '\x{68B3}\x{68B5}\x{68B6}\x{68B9}\x{68BA}\x{68BC}\x{68C4}\x{68C6}\x{68C9}' . + '\x{68CA}\x{68CB}\x{68CD}\x{68D2}\x{68D4}\x{68D5}\x{68D7}\x{68D8}\x{68DA}' . + '\x{68DF}\x{68E0}\x{68E1}\x{68E3}\x{68E7}\x{68EE}\x{68EF}\x{68F2}\x{68F9}' . + '\x{68FA}\x{6900}\x{6901}\x{6904}\x{6905}\x{6908}\x{690B}\x{690C}\x{690D}' . + '\x{690E}\x{690F}\x{6912}\x{6919}\x{691A}\x{691B}\x{691C}\x{6921}\x{6922}' . + '\x{6923}\x{6925}\x{6926}\x{6928}\x{692A}\x{6930}\x{6934}\x{6936}\x{6939}' . + '\x{693D}\x{693F}\x{694A}\x{6953}\x{6954}\x{6955}\x{6959}\x{695A}\x{695C}' . + '\x{695D}\x{695E}\x{6960}\x{6961}\x{6962}\x{696A}\x{696B}\x{696D}\x{696E}' . + '\x{696F}\x{6973}\x{6974}\x{6975}\x{6977}\x{6978}\x{6979}\x{697C}\x{697D}' . + '\x{697E}\x{6981}\x{6982}\x{698A}\x{698E}\x{6991}\x{6994}\x{6995}\x{699B}' . + '\x{699C}\x{69A0}\x{69A7}\x{69AE}\x{69B1}\x{69B2}\x{69B4}\x{69BB}\x{69BE}' . + '\x{69BF}\x{69C1}\x{69C3}\x{69C7}\x{69CA}\x{69CB}\x{69CC}\x{69CD}\x{69CE}' . + '\x{69D0}\x{69D3}\x{69D8}\x{69D9}\x{69DD}\x{69DE}\x{69E7}\x{69E8}\x{69EB}' . + '\x{69ED}\x{69F2}\x{69F9}\x{69FB}\x{69FD}\x{69FF}\x{6A02}\x{6A05}\x{6A0A}' . + '\x{6A0B}\x{6A0C}\x{6A12}\x{6A13}\x{6A14}\x{6A17}\x{6A19}\x{6A1B}\x{6A1E}' . + '\x{6A1F}\x{6A21}\x{6A22}\x{6A23}\x{6A29}\x{6A2A}\x{6A2B}\x{6A2E}\x{6A35}' . + '\x{6A36}\x{6A38}\x{6A39}\x{6A3A}\x{6A3D}\x{6A44}\x{6A47}\x{6A48}\x{6A4B}' . + '\x{6A58}\x{6A59}\x{6A5F}\x{6A61}\x{6A62}\x{6A66}\x{6A72}\x{6A78}\x{6A7F}' . + '\x{6A80}\x{6A84}\x{6A8D}\x{6A8E}\x{6A90}\x{6A97}\x{6A9C}\x{6AA0}\x{6AA2}' . + '\x{6AA3}\x{6AAA}\x{6AAC}\x{6AAE}\x{6AB3}\x{6AB8}\x{6ABB}\x{6AC1}\x{6AC2}' . + '\x{6AC3}\x{6AD1}\x{6AD3}\x{6ADA}\x{6ADB}\x{6ADE}\x{6ADF}\x{6AE8}\x{6AEA}' . + '\x{6AFA}\x{6AFB}\x{6B04}\x{6B05}\x{6B0A}\x{6B12}\x{6B16}\x{6B1D}\x{6B1F}' . + '\x{6B20}\x{6B21}\x{6B23}\x{6B27}\x{6B32}\x{6B37}\x{6B38}\x{6B39}\x{6B3A}' . + '\x{6B3D}\x{6B3E}\x{6B43}\x{6B47}\x{6B49}\x{6B4C}\x{6B4E}\x{6B50}\x{6B53}' . + '\x{6B54}\x{6B59}\x{6B5B}\x{6B5F}\x{6B61}\x{6B62}\x{6B63}\x{6B64}\x{6B66}' . + '\x{6B69}\x{6B6A}\x{6B6F}\x{6B73}\x{6B74}\x{6B78}\x{6B79}\x{6B7B}\x{6B7F}' . + '\x{6B80}\x{6B83}\x{6B84}\x{6B86}\x{6B89}\x{6B8A}\x{6B8B}\x{6B8D}\x{6B95}' . + '\x{6B96}\x{6B98}\x{6B9E}\x{6BA4}\x{6BAA}\x{6BAB}\x{6BAF}\x{6BB1}\x{6BB2}' . + '\x{6BB3}\x{6BB4}\x{6BB5}\x{6BB7}\x{6BBA}\x{6BBB}\x{6BBC}\x{6BBF}\x{6BC0}' . + '\x{6BC5}\x{6BC6}\x{6BCB}\x{6BCD}\x{6BCE}\x{6BD2}\x{6BD3}\x{6BD4}\x{6BD8}' . + '\x{6BDB}\x{6BDF}\x{6BEB}\x{6BEC}\x{6BEF}\x{6BF3}\x{6C08}\x{6C0F}\x{6C11}' . + '\x{6C13}\x{6C14}\x{6C17}\x{6C1B}\x{6C23}\x{6C24}\x{6C34}\x{6C37}\x{6C38}' . + '\x{6C3E}\x{6C40}\x{6C41}\x{6C42}\x{6C4E}\x{6C50}\x{6C55}\x{6C57}\x{6C5A}' . + '\x{6C5D}\x{6C5E}\x{6C5F}\x{6C60}\x{6C62}\x{6C68}\x{6C6A}\x{6C70}\x{6C72}' . + '\x{6C73}\x{6C7A}\x{6C7D}\x{6C7E}\x{6C81}\x{6C82}\x{6C83}\x{6C88}\x{6C8C}' . + '\x{6C8D}\x{6C90}\x{6C92}\x{6C93}\x{6C96}\x{6C99}\x{6C9A}\x{6C9B}\x{6CA1}' . + '\x{6CA2}\x{6CAB}\x{6CAE}\x{6CB1}\x{6CB3}\x{6CB8}\x{6CB9}\x{6CBA}\x{6CBB}' . + '\x{6CBC}\x{6CBD}\x{6CBE}\x{6CBF}\x{6CC1}\x{6CC4}\x{6CC5}\x{6CC9}\x{6CCA}' . + '\x{6CCC}\x{6CD3}\x{6CD5}\x{6CD7}\x{6CD9}\x{6CDB}\x{6CDD}\x{6CE1}\x{6CE2}' . + '\x{6CE3}\x{6CE5}\x{6CE8}\x{6CEA}\x{6CEF}\x{6CF0}\x{6CF1}\x{6CF3}\x{6D0B}' . + '\x{6D0C}\x{6D12}\x{6D17}\x{6D19}\x{6D1B}\x{6D1E}\x{6D1F}\x{6D25}\x{6D29}' . + '\x{6D2A}\x{6D2B}\x{6D32}\x{6D33}\x{6D35}\x{6D36}\x{6D38}\x{6D3B}\x{6D3D}' . + '\x{6D3E}\x{6D41}\x{6D44}\x{6D45}\x{6D59}\x{6D5A}\x{6D5C}\x{6D63}\x{6D64}' . + '\x{6D66}\x{6D69}\x{6D6A}\x{6D6C}\x{6D6E}\x{6D74}\x{6D77}\x{6D78}\x{6D79}' . + '\x{6D85}\x{6D88}\x{6D8C}\x{6D8E}\x{6D93}\x{6D95}\x{6D99}\x{6D9B}\x{6D9C}' . + '\x{6DAF}\x{6DB2}\x{6DB5}\x{6DB8}\x{6DBC}\x{6DC0}\x{6DC5}\x{6DC6}\x{6DC7}' . + '\x{6DCB}\x{6DCC}\x{6DD1}\x{6DD2}\x{6DD5}\x{6DD8}\x{6DD9}\x{6DDE}\x{6DE1}' . + '\x{6DE4}\x{6DE6}\x{6DE8}\x{6DEA}\x{6DEB}\x{6DEC}\x{6DEE}\x{6DF1}\x{6DF3}' . + '\x{6DF5}\x{6DF7}\x{6DF9}\x{6DFA}\x{6DFB}\x{6E05}\x{6E07}\x{6E08}\x{6E09}' . + '\x{6E0A}\x{6E0B}\x{6E13}\x{6E15}\x{6E19}\x{6E1A}\x{6E1B}\x{6E1D}\x{6E1F}' . + '\x{6E20}\x{6E21}\x{6E23}\x{6E24}\x{6E25}\x{6E26}\x{6E29}\x{6E2B}\x{6E2C}' . + '\x{6E2D}\x{6E2E}\x{6E2F}\x{6E38}\x{6E3A}\x{6E3E}\x{6E43}\x{6E4A}\x{6E4D}' . + '\x{6E4E}\x{6E56}\x{6E58}\x{6E5B}\x{6E5F}\x{6E67}\x{6E6B}\x{6E6E}\x{6E6F}' . + '\x{6E72}\x{6E76}\x{6E7E}\x{6E7F}\x{6E80}\x{6E82}\x{6E8C}\x{6E8F}\x{6E90}' . + '\x{6E96}\x{6E98}\x{6E9C}\x{6E9D}\x{6E9F}\x{6EA2}\x{6EA5}\x{6EAA}\x{6EAF}' . + '\x{6EB2}\x{6EB6}\x{6EB7}\x{6EBA}\x{6EBD}\x{6EC2}\x{6EC4}\x{6EC5}\x{6EC9}' . + '\x{6ECB}\x{6ECC}\x{6ED1}\x{6ED3}\x{6ED4}\x{6ED5}\x{6EDD}\x{6EDE}\x{6EEC}' . + '\x{6EEF}\x{6EF2}\x{6EF4}\x{6EF7}\x{6EF8}\x{6EFE}\x{6EFF}\x{6F01}\x{6F02}' . + '\x{6F06}\x{6F09}\x{6F0F}\x{6F11}\x{6F13}\x{6F14}\x{6F15}\x{6F20}\x{6F22}' . + '\x{6F23}\x{6F2B}\x{6F2C}\x{6F31}\x{6F32}\x{6F38}\x{6F3E}\x{6F3F}\x{6F41}' . + '\x{6F45}\x{6F54}\x{6F58}\x{6F5B}\x{6F5C}\x{6F5F}\x{6F64}\x{6F66}\x{6F6D}' . + '\x{6F6E}\x{6F6F}\x{6F70}\x{6F74}\x{6F78}\x{6F7A}\x{6F7C}\x{6F80}\x{6F81}' . + '\x{6F82}\x{6F84}\x{6F86}\x{6F8E}\x{6F91}\x{6F97}\x{6FA1}\x{6FA3}\x{6FA4}' . + '\x{6FAA}\x{6FB1}\x{6FB3}\x{6FB9}\x{6FC0}\x{6FC1}\x{6FC2}\x{6FC3}\x{6FC6}' . + '\x{6FD4}\x{6FD5}\x{6FD8}\x{6FDB}\x{6FDF}\x{6FE0}\x{6FE1}\x{6FE4}\x{6FEB}' . + '\x{6FEC}\x{6FEE}\x{6FEF}\x{6FF1}\x{6FF3}\x{6FF6}\x{6FFA}\x{6FFE}\x{7001}' . + '\x{7009}\x{700B}\x{700F}\x{7011}\x{7015}\x{7018}\x{701A}\x{701B}\x{701D}' . + '\x{701E}\x{701F}\x{7026}\x{7027}\x{702C}\x{7030}\x{7032}\x{703E}\x{704C}' . + '\x{7051}\x{7058}\x{7063}\x{706B}\x{706F}\x{7070}\x{7078}\x{707C}\x{707D}' . + '\x{7089}\x{708A}\x{708E}\x{7092}\x{7099}\x{70AC}\x{70AD}\x{70AE}\x{70AF}' . + '\x{70B3}\x{70B8}\x{70B9}\x{70BA}\x{70C8}\x{70CB}\x{70CF}\x{70D9}\x{70DD}' . + '\x{70DF}\x{70F1}\x{70F9}\x{70FD}\x{7109}\x{7114}\x{7119}\x{711A}\x{711C}' . + '\x{7121}\x{7126}\x{7136}\x{713C}\x{7149}\x{714C}\x{714E}\x{7155}\x{7156}' . + '\x{7159}\x{7162}\x{7164}\x{7165}\x{7166}\x{7167}\x{7169}\x{716C}\x{716E}' . + '\x{717D}\x{7184}\x{7188}\x{718A}\x{718F}\x{7194}\x{7195}\x{7199}\x{719F}' . + '\x{71A8}\x{71AC}\x{71B1}\x{71B9}\x{71BE}\x{71C3}\x{71C8}\x{71C9}\x{71CE}' . + '\x{71D0}\x{71D2}\x{71D4}\x{71D5}\x{71D7}\x{71DF}\x{71E0}\x{71E5}\x{71E6}' . + '\x{71E7}\x{71EC}\x{71ED}\x{71EE}\x{71F5}\x{71F9}\x{71FB}\x{71FC}\x{71FF}' . + '\x{7206}\x{720D}\x{7210}\x{721B}\x{7228}\x{722A}\x{722C}\x{722D}\x{7230}' . + '\x{7232}\x{7235}\x{7236}\x{723A}\x{723B}\x{723C}\x{723D}\x{723E}\x{723F}' . + '\x{7240}\x{7246}\x{7247}\x{7248}\x{724B}\x{724C}\x{7252}\x{7258}\x{7259}' . + '\x{725B}\x{725D}\x{725F}\x{7261}\x{7262}\x{7267}\x{7269}\x{7272}\x{7274}' . + '\x{7279}\x{727D}\x{727E}\x{7280}\x{7281}\x{7282}\x{7287}\x{7292}\x{7296}' . + '\x{72A0}\x{72A2}\x{72A7}\x{72AC}\x{72AF}\x{72B2}\x{72B6}\x{72B9}\x{72C2}' . + '\x{72C3}\x{72C4}\x{72C6}\x{72CE}\x{72D0}\x{72D2}\x{72D7}\x{72D9}\x{72DB}' . + '\x{72E0}\x{72E1}\x{72E2}\x{72E9}\x{72EC}\x{72ED}\x{72F7}\x{72F8}\x{72F9}' . + '\x{72FC}\x{72FD}\x{730A}\x{7316}\x{7317}\x{731B}\x{731C}\x{731D}\x{731F}' . + '\x{7325}\x{7329}\x{732A}\x{732B}\x{732E}\x{732F}\x{7334}\x{7336}\x{7337}' . + '\x{733E}\x{733F}\x{7344}\x{7345}\x{734E}\x{734F}\x{7357}\x{7363}\x{7368}' . + '\x{736A}\x{7370}\x{7372}\x{7375}\x{7378}\x{737A}\x{737B}\x{7384}\x{7387}' . + '\x{7389}\x{738B}\x{7396}\x{73A9}\x{73B2}\x{73B3}\x{73BB}\x{73C0}\x{73C2}' . + '\x{73C8}\x{73CA}\x{73CD}\x{73CE}\x{73DE}\x{73E0}\x{73E5}\x{73EA}\x{73ED}' . + '\x{73EE}\x{73F1}\x{73F8}\x{73FE}\x{7403}\x{7405}\x{7406}\x{7409}\x{7422}' . + '\x{7425}\x{7432}\x{7433}\x{7434}\x{7435}\x{7436}\x{743A}\x{743F}\x{7441}' . + '\x{7455}\x{7459}\x{745A}\x{745B}\x{745C}\x{745E}\x{745F}\x{7460}\x{7463}' . + '\x{7464}\x{7469}\x{746A}\x{746F}\x{7470}\x{7473}\x{7476}\x{747E}\x{7483}' . + '\x{748B}\x{749E}\x{74A2}\x{74A7}\x{74B0}\x{74BD}\x{74CA}\x{74CF}\x{74D4}' . + '\x{74DC}\x{74E0}\x{74E2}\x{74E3}\x{74E6}\x{74E7}\x{74E9}\x{74EE}\x{74F0}' . + '\x{74F1}\x{74F2}\x{74F6}\x{74F7}\x{74F8}\x{7503}\x{7504}\x{7505}\x{750C}' . + '\x{750D}\x{750E}\x{7511}\x{7513}\x{7515}\x{7518}\x{751A}\x{751C}\x{751E}' . + '\x{751F}\x{7523}\x{7525}\x{7526}\x{7528}\x{752B}\x{752C}\x{7530}\x{7531}' . + '\x{7532}\x{7533}\x{7537}\x{7538}\x{753A}\x{753B}\x{753C}\x{7544}\x{7546}' . + '\x{7549}\x{754A}\x{754B}\x{754C}\x{754D}\x{754F}\x{7551}\x{7554}\x{7559}' . + '\x{755A}\x{755B}\x{755C}\x{755D}\x{7560}\x{7562}\x{7564}\x{7565}\x{7566}' . + '\x{7567}\x{7569}\x{756A}\x{756B}\x{756D}\x{7570}\x{7573}\x{7574}\x{7576}' . + '\x{7577}\x{7578}\x{757F}\x{7582}\x{7586}\x{7587}\x{7589}\x{758A}\x{758B}' . + '\x{758E}\x{758F}\x{7591}\x{7594}\x{759A}\x{759D}\x{75A3}\x{75A5}\x{75AB}' . + '\x{75B1}\x{75B2}\x{75B3}\x{75B5}\x{75B8}\x{75B9}\x{75BC}\x{75BD}\x{75BE}' . + '\x{75C2}\x{75C3}\x{75C5}\x{75C7}\x{75CA}\x{75CD}\x{75D2}\x{75D4}\x{75D5}' . + '\x{75D8}\x{75D9}\x{75DB}\x{75DE}\x{75E2}\x{75E3}\x{75E9}\x{75F0}\x{75F2}' . + '\x{75F3}\x{75F4}\x{75FA}\x{75FC}\x{75FE}\x{75FF}\x{7601}\x{7609}\x{760B}' . + '\x{760D}\x{761F}\x{7620}\x{7621}\x{7622}\x{7624}\x{7627}\x{7630}\x{7634}' . + '\x{763B}\x{7642}\x{7646}\x{7647}\x{7648}\x{764C}\x{7652}\x{7656}\x{7658}' . + '\x{765C}\x{7661}\x{7662}\x{7667}\x{7668}\x{7669}\x{766A}\x{766C}\x{7670}' . + '\x{7672}\x{7676}\x{7678}\x{767A}\x{767B}\x{767C}\x{767D}\x{767E}\x{7680}' . + '\x{7683}\x{7684}\x{7686}\x{7687}\x{7688}\x{768B}\x{768E}\x{7690}\x{7693}' . + '\x{7696}\x{7699}\x{769A}\x{76AE}\x{76B0}\x{76B4}\x{76B7}\x{76B8}\x{76B9}' . + '\x{76BA}\x{76BF}\x{76C2}\x{76C3}\x{76C6}\x{76C8}\x{76CA}\x{76CD}\x{76D2}' . + '\x{76D6}\x{76D7}\x{76DB}\x{76DC}\x{76DE}\x{76DF}\x{76E1}\x{76E3}\x{76E4}' . + '\x{76E5}\x{76E7}\x{76EA}\x{76EE}\x{76F2}\x{76F4}\x{76F8}\x{76FB}\x{76FE}' . + '\x{7701}\x{7704}\x{7707}\x{7708}\x{7709}\x{770B}\x{770C}\x{771B}\x{771E}' . + '\x{771F}\x{7720}\x{7724}\x{7725}\x{7726}\x{7729}\x{7737}\x{7738}\x{773A}' . + '\x{773C}\x{7740}\x{7747}\x{775A}\x{775B}\x{7761}\x{7763}\x{7765}\x{7766}' . + '\x{7768}\x{776B}\x{7779}\x{777E}\x{777F}\x{778B}\x{778E}\x{7791}\x{779E}' . + '\x{77A0}\x{77A5}\x{77AC}\x{77AD}\x{77B0}\x{77B3}\x{77B6}\x{77B9}\x{77BB}' . + '\x{77BC}\x{77BD}\x{77BF}\x{77C7}\x{77CD}\x{77D7}\x{77DA}\x{77DB}\x{77DC}' . + '\x{77E2}\x{77E3}\x{77E5}\x{77E7}\x{77E9}\x{77ED}\x{77EE}\x{77EF}\x{77F3}' . + '\x{77FC}\x{7802}\x{780C}\x{7812}\x{7814}\x{7815}\x{7820}\x{7825}\x{7826}' . + '\x{7827}\x{7832}\x{7834}\x{783A}\x{783F}\x{7845}\x{785D}\x{786B}\x{786C}' . + '\x{786F}\x{7872}\x{7874}\x{787C}\x{7881}\x{7886}\x{7887}\x{788C}\x{788D}' . + '\x{788E}\x{7891}\x{7893}\x{7895}\x{7897}\x{789A}\x{78A3}\x{78A7}\x{78A9}' . + '\x{78AA}\x{78AF}\x{78B5}\x{78BA}\x{78BC}\x{78BE}\x{78C1}\x{78C5}\x{78C6}' . + '\x{78CA}\x{78CB}\x{78D0}\x{78D1}\x{78D4}\x{78DA}\x{78E7}\x{78E8}\x{78EC}' . + '\x{78EF}\x{78F4}\x{78FD}\x{7901}\x{7907}\x{790E}\x{7911}\x{7912}\x{7919}' . + '\x{7926}\x{792A}\x{792B}\x{792C}\x{793A}\x{793C}\x{793E}\x{7940}\x{7941}' . + '\x{7947}\x{7948}\x{7949}\x{7950}\x{7953}\x{7955}\x{7956}\x{7957}\x{795A}' . + '\x{795D}\x{795E}\x{795F}\x{7960}\x{7962}\x{7965}\x{7968}\x{796D}\x{7977}' . + '\x{797A}\x{797F}\x{7980}\x{7981}\x{7984}\x{7985}\x{798A}\x{798D}\x{798E}' . + '\x{798F}\x{799D}\x{79A6}\x{79A7}\x{79AA}\x{79AE}\x{79B0}\x{79B3}\x{79B9}' . + '\x{79BA}\x{79BD}\x{79BE}\x{79BF}\x{79C0}\x{79C1}\x{79C9}\x{79CB}\x{79D1}' . + '\x{79D2}\x{79D5}\x{79D8}\x{79DF}\x{79E1}\x{79E3}\x{79E4}\x{79E6}\x{79E7}' . + '\x{79E9}\x{79EC}\x{79F0}\x{79FB}\x{7A00}\x{7A08}\x{7A0B}\x{7A0D}\x{7A0E}' . + '\x{7A14}\x{7A17}\x{7A18}\x{7A19}\x{7A1A}\x{7A1C}\x{7A1F}\x{7A20}\x{7A2E}' . + '\x{7A31}\x{7A32}\x{7A37}\x{7A3B}\x{7A3C}\x{7A3D}\x{7A3E}\x{7A3F}\x{7A40}' . + '\x{7A42}\x{7A43}\x{7A46}\x{7A49}\x{7A4D}\x{7A4E}\x{7A4F}\x{7A50}\x{7A57}' . + '\x{7A61}\x{7A62}\x{7A63}\x{7A69}\x{7A6B}\x{7A70}\x{7A74}\x{7A76}\x{7A79}' . + '\x{7A7A}\x{7A7D}\x{7A7F}\x{7A81}\x{7A83}\x{7A84}\x{7A88}\x{7A92}\x{7A93}' . + '\x{7A95}\x{7A96}\x{7A97}\x{7A98}\x{7A9F}\x{7AA9}\x{7AAA}\x{7AAE}\x{7AAF}' . + '\x{7AB0}\x{7AB6}\x{7ABA}\x{7ABF}\x{7AC3}\x{7AC4}\x{7AC5}\x{7AC7}\x{7AC8}' . + '\x{7ACA}\x{7ACB}\x{7ACD}\x{7ACF}\x{7AD2}\x{7AD3}\x{7AD5}\x{7AD9}\x{7ADA}' . + '\x{7ADC}\x{7ADD}\x{7ADF}\x{7AE0}\x{7AE1}\x{7AE2}\x{7AE3}\x{7AE5}\x{7AE6}' . + '\x{7AEA}\x{7AED}\x{7AEF}\x{7AF0}\x{7AF6}\x{7AF8}\x{7AF9}\x{7AFA}\x{7AFF}' . + '\x{7B02}\x{7B04}\x{7B06}\x{7B08}\x{7B0A}\x{7B0B}\x{7B0F}\x{7B11}\x{7B18}' . + '\x{7B19}\x{7B1B}\x{7B1E}\x{7B20}\x{7B25}\x{7B26}\x{7B28}\x{7B2C}\x{7B33}' . + '\x{7B35}\x{7B36}\x{7B39}\x{7B45}\x{7B46}\x{7B48}\x{7B49}\x{7B4B}\x{7B4C}' . + '\x{7B4D}\x{7B4F}\x{7B50}\x{7B51}\x{7B52}\x{7B54}\x{7B56}\x{7B5D}\x{7B65}' . + '\x{7B67}\x{7B6C}\x{7B6E}\x{7B70}\x{7B71}\x{7B74}\x{7B75}\x{7B7A}\x{7B86}' . + '\x{7B87}\x{7B8B}\x{7B8D}\x{7B8F}\x{7B92}\x{7B94}\x{7B95}\x{7B97}\x{7B98}' . + '\x{7B99}\x{7B9A}\x{7B9C}\x{7B9D}\x{7B9F}\x{7BA1}\x{7BAA}\x{7BAD}\x{7BB1}' . + '\x{7BB4}\x{7BB8}\x{7BC0}\x{7BC1}\x{7BC4}\x{7BC6}\x{7BC7}\x{7BC9}\x{7BCB}' . + '\x{7BCC}\x{7BCF}\x{7BDD}\x{7BE0}\x{7BE4}\x{7BE5}\x{7BE6}\x{7BE9}\x{7BED}' . + '\x{7BF3}\x{7BF6}\x{7BF7}\x{7C00}\x{7C07}\x{7C0D}\x{7C11}\x{7C12}\x{7C13}' . + '\x{7C14}\x{7C17}\x{7C1F}\x{7C21}\x{7C23}\x{7C27}\x{7C2A}\x{7C2B}\x{7C37}' . + '\x{7C38}\x{7C3D}\x{7C3E}\x{7C3F}\x{7C40}\x{7C43}\x{7C4C}\x{7C4D}\x{7C4F}' . + '\x{7C50}\x{7C54}\x{7C56}\x{7C58}\x{7C5F}\x{7C60}\x{7C64}\x{7C65}\x{7C6C}' . + '\x{7C73}\x{7C75}\x{7C7E}\x{7C81}\x{7C82}\x{7C83}\x{7C89}\x{7C8B}\x{7C8D}' . + '\x{7C90}\x{7C92}\x{7C95}\x{7C97}\x{7C98}\x{7C9B}\x{7C9F}\x{7CA1}\x{7CA2}' . + '\x{7CA4}\x{7CA5}\x{7CA7}\x{7CA8}\x{7CAB}\x{7CAD}\x{7CAE}\x{7CB1}\x{7CB2}' . + '\x{7CB3}\x{7CB9}\x{7CBD}\x{7CBE}\x{7CC0}\x{7CC2}\x{7CC5}\x{7CCA}\x{7CCE}' . + '\x{7CD2}\x{7CD6}\x{7CD8}\x{7CDC}\x{7CDE}\x{7CDF}\x{7CE0}\x{7CE2}\x{7CE7}' . + '\x{7CEF}\x{7CF2}\x{7CF4}\x{7CF6}\x{7CF8}\x{7CFA}\x{7CFB}\x{7CFE}\x{7D00}' . + '\x{7D02}\x{7D04}\x{7D05}\x{7D06}\x{7D0A}\x{7D0B}\x{7D0D}\x{7D10}\x{7D14}' . + '\x{7D15}\x{7D17}\x{7D18}\x{7D19}\x{7D1A}\x{7D1B}\x{7D1C}\x{7D20}\x{7D21}' . + '\x{7D22}\x{7D2B}\x{7D2C}\x{7D2E}\x{7D2F}\x{7D30}\x{7D32}\x{7D33}\x{7D35}' . + '\x{7D39}\x{7D3A}\x{7D3F}\x{7D42}\x{7D43}\x{7D44}\x{7D45}\x{7D46}\x{7D4B}' . + '\x{7D4C}\x{7D4E}\x{7D4F}\x{7D50}\x{7D56}\x{7D5B}\x{7D5E}\x{7D61}\x{7D62}' . + '\x{7D63}\x{7D66}\x{7D68}\x{7D6E}\x{7D71}\x{7D72}\x{7D73}\x{7D75}\x{7D76}' . + '\x{7D79}\x{7D7D}\x{7D89}\x{7D8F}\x{7D93}\x{7D99}\x{7D9A}\x{7D9B}\x{7D9C}' . + '\x{7D9F}\x{7DA2}\x{7DA3}\x{7DAB}\x{7DAC}\x{7DAD}\x{7DAE}\x{7DAF}\x{7DB0}' . + '\x{7DB1}\x{7DB2}\x{7DB4}\x{7DB5}\x{7DB8}\x{7DBA}\x{7DBB}\x{7DBD}\x{7DBE}' . + '\x{7DBF}\x{7DC7}\x{7DCA}\x{7DCB}\x{7DCF}\x{7DD1}\x{7DD2}\x{7DD5}\x{7DD8}' . + '\x{7DDA}\x{7DDC}\x{7DDD}\x{7DDE}\x{7DE0}\x{7DE1}\x{7DE4}\x{7DE8}\x{7DE9}' . + '\x{7DEC}\x{7DEF}\x{7DF2}\x{7DF4}\x{7DFB}\x{7E01}\x{7E04}\x{7E05}\x{7E09}' . + '\x{7E0A}\x{7E0B}\x{7E12}\x{7E1B}\x{7E1E}\x{7E1F}\x{7E21}\x{7E22}\x{7E23}' . + '\x{7E26}\x{7E2B}\x{7E2E}\x{7E31}\x{7E32}\x{7E35}\x{7E37}\x{7E39}\x{7E3A}' . + '\x{7E3B}\x{7E3D}\x{7E3E}\x{7E41}\x{7E43}\x{7E46}\x{7E4A}\x{7E4B}\x{7E4D}' . + '\x{7E54}\x{7E55}\x{7E56}\x{7E59}\x{7E5A}\x{7E5D}\x{7E5E}\x{7E66}\x{7E67}' . + '\x{7E69}\x{7E6A}\x{7E6D}\x{7E70}\x{7E79}\x{7E7B}\x{7E7C}\x{7E7D}\x{7E7F}' . + '\x{7E82}\x{7E83}\x{7E88}\x{7E89}\x{7E8C}\x{7E8E}\x{7E8F}\x{7E90}\x{7E92}' . + '\x{7E93}\x{7E94}\x{7E96}\x{7E9B}\x{7E9C}\x{7F36}\x{7F38}\x{7F3A}\x{7F45}' . + '\x{7F4C}\x{7F4D}\x{7F4E}\x{7F50}\x{7F51}\x{7F54}\x{7F55}\x{7F58}\x{7F5F}' . + '\x{7F60}\x{7F67}\x{7F68}\x{7F69}\x{7F6A}\x{7F6B}\x{7F6E}\x{7F70}\x{7F72}' . + '\x{7F75}\x{7F77}\x{7F78}\x{7F79}\x{7F82}\x{7F83}\x{7F85}\x{7F86}\x{7F87}' . + '\x{7F88}\x{7F8A}\x{7F8C}\x{7F8E}\x{7F94}\x{7F9A}\x{7F9D}\x{7F9E}\x{7FA3}' . + '\x{7FA4}\x{7FA8}\x{7FA9}\x{7FAE}\x{7FAF}\x{7FB2}\x{7FB6}\x{7FB8}\x{7FB9}' . + '\x{7FBD}\x{7FC1}\x{7FC5}\x{7FC6}\x{7FCA}\x{7FCC}\x{7FD2}\x{7FD4}\x{7FD5}' . + '\x{7FE0}\x{7FE1}\x{7FE6}\x{7FE9}\x{7FEB}\x{7FF0}\x{7FF3}\x{7FF9}\x{7FFB}' . + '\x{7FFC}\x{8000}\x{8001}\x{8003}\x{8004}\x{8005}\x{8006}\x{800B}\x{800C}' . + '\x{8010}\x{8012}\x{8015}\x{8017}\x{8018}\x{8019}\x{801C}\x{8021}\x{8028}' . + '\x{8033}\x{8036}\x{803B}\x{803D}\x{803F}\x{8046}\x{804A}\x{8052}\x{8056}' . + '\x{8058}\x{805A}\x{805E}\x{805F}\x{8061}\x{8062}\x{8068}\x{806F}\x{8070}' . + '\x{8072}\x{8073}\x{8074}\x{8076}\x{8077}\x{8079}\x{807D}\x{807E}\x{807F}' . + '\x{8084}\x{8085}\x{8086}\x{8087}\x{8089}\x{808B}\x{808C}\x{8093}\x{8096}' . + '\x{8098}\x{809A}\x{809B}\x{809D}\x{80A1}\x{80A2}\x{80A5}\x{80A9}\x{80AA}' . + '\x{80AC}\x{80AD}\x{80AF}\x{80B1}\x{80B2}\x{80B4}\x{80BA}\x{80C3}\x{80C4}' . + '\x{80C6}\x{80CC}\x{80CE}\x{80D6}\x{80D9}\x{80DA}\x{80DB}\x{80DD}\x{80DE}' . + '\x{80E1}\x{80E4}\x{80E5}\x{80EF}\x{80F1}\x{80F4}\x{80F8}\x{80FC}\x{80FD}' . + '\x{8102}\x{8105}\x{8106}\x{8107}\x{8108}\x{8109}\x{810A}\x{811A}\x{811B}' . + '\x{8123}\x{8129}\x{812F}\x{8131}\x{8133}\x{8139}\x{813E}\x{8146}\x{814B}' . + '\x{814E}\x{8150}\x{8151}\x{8153}\x{8154}\x{8155}\x{815F}\x{8165}\x{8166}' . + '\x{816B}\x{816E}\x{8170}\x{8171}\x{8174}\x{8178}\x{8179}\x{817A}\x{817F}' . + '\x{8180}\x{8182}\x{8183}\x{8188}\x{818A}\x{818F}\x{8193}\x{8195}\x{819A}' . + '\x{819C}\x{819D}\x{81A0}\x{81A3}\x{81A4}\x{81A8}\x{81A9}\x{81B0}\x{81B3}' . + '\x{81B5}\x{81B8}\x{81BA}\x{81BD}\x{81BE}\x{81BF}\x{81C0}\x{81C2}\x{81C6}' . + '\x{81C8}\x{81C9}\x{81CD}\x{81D1}\x{81D3}\x{81D8}\x{81D9}\x{81DA}\x{81DF}' . + '\x{81E0}\x{81E3}\x{81E5}\x{81E7}\x{81E8}\x{81EA}\x{81ED}\x{81F3}\x{81F4}' . + '\x{81FA}\x{81FB}\x{81FC}\x{81FE}\x{8201}\x{8202}\x{8205}\x{8207}\x{8208}' . + '\x{8209}\x{820A}\x{820C}\x{820D}\x{820E}\x{8210}\x{8212}\x{8216}\x{8217}' . + '\x{8218}\x{821B}\x{821C}\x{821E}\x{821F}\x{8229}\x{822A}\x{822B}\x{822C}' . + '\x{822E}\x{8233}\x{8235}\x{8236}\x{8237}\x{8238}\x{8239}\x{8240}\x{8247}' . + '\x{8258}\x{8259}\x{825A}\x{825D}\x{825F}\x{8262}\x{8264}\x{8266}\x{8268}' . + '\x{826A}\x{826B}\x{826E}\x{826F}\x{8271}\x{8272}\x{8276}\x{8277}\x{8278}' . + '\x{827E}\x{828B}\x{828D}\x{8292}\x{8299}\x{829D}\x{829F}\x{82A5}\x{82A6}' . + '\x{82AB}\x{82AC}\x{82AD}\x{82AF}\x{82B1}\x{82B3}\x{82B8}\x{82B9}\x{82BB}' . + '\x{82BD}\x{82C5}\x{82D1}\x{82D2}\x{82D3}\x{82D4}\x{82D7}\x{82D9}\x{82DB}' . + '\x{82DC}\x{82DE}\x{82DF}\x{82E1}\x{82E3}\x{82E5}\x{82E6}\x{82E7}\x{82EB}' . + '\x{82F1}\x{82F3}\x{82F4}\x{82F9}\x{82FA}\x{82FB}\x{8302}\x{8303}\x{8304}' . + '\x{8305}\x{8306}\x{8309}\x{830E}\x{8316}\x{8317}\x{8318}\x{831C}\x{8323}' . + '\x{8328}\x{832B}\x{832F}\x{8331}\x{8332}\x{8334}\x{8335}\x{8336}\x{8338}' . + '\x{8339}\x{8340}\x{8345}\x{8349}\x{834A}\x{834F}\x{8350}\x{8352}\x{8358}' . + '\x{8373}\x{8375}\x{8377}\x{837B}\x{837C}\x{8385}\x{8387}\x{8389}\x{838A}' . + '\x{838E}\x{8393}\x{8396}\x{839A}\x{839E}\x{839F}\x{83A0}\x{83A2}\x{83A8}' . + '\x{83AA}\x{83AB}\x{83B1}\x{83B5}\x{83BD}\x{83C1}\x{83C5}\x{83CA}\x{83CC}' . + '\x{83CE}\x{83D3}\x{83D6}\x{83D8}\x{83DC}\x{83DF}\x{83E0}\x{83E9}\x{83EB}' . + '\x{83EF}\x{83F0}\x{83F1}\x{83F2}\x{83F4}\x{83F7}\x{83FB}\x{83FD}\x{8403}' . + '\x{8404}\x{8407}\x{840B}\x{840C}\x{840D}\x{840E}\x{8413}\x{8420}\x{8422}' . + '\x{8429}\x{842A}\x{842C}\x{8431}\x{8435}\x{8438}\x{843C}\x{843D}\x{8446}' . + '\x{8449}\x{844E}\x{8457}\x{845B}\x{8461}\x{8462}\x{8463}\x{8466}\x{8469}' . + '\x{846B}\x{846C}\x{846D}\x{846E}\x{846F}\x{8471}\x{8475}\x{8477}\x{8479}' . + '\x{847A}\x{8482}\x{8484}\x{848B}\x{8490}\x{8494}\x{8499}\x{849C}\x{849F}' . + '\x{84A1}\x{84AD}\x{84B2}\x{84B8}\x{84B9}\x{84BB}\x{84BC}\x{84BF}\x{84C1}' . + '\x{84C4}\x{84C6}\x{84C9}\x{84CA}\x{84CB}\x{84CD}\x{84D0}\x{84D1}\x{84D6}' . + '\x{84D9}\x{84DA}\x{84EC}\x{84EE}\x{84F4}\x{84FC}\x{84FF}\x{8500}\x{8506}' . + '\x{8511}\x{8513}\x{8514}\x{8515}\x{8517}\x{8518}\x{851A}\x{851F}\x{8521}' . + '\x{8526}\x{852C}\x{852D}\x{8535}\x{853D}\x{8540}\x{8541}\x{8543}\x{8548}' . + '\x{8549}\x{854A}\x{854B}\x{854E}\x{8555}\x{8557}\x{8558}\x{855A}\x{8563}' . + '\x{8568}\x{8569}\x{856A}\x{856D}\x{8577}\x{857E}\x{8580}\x{8584}\x{8587}' . + '\x{8588}\x{858A}\x{8590}\x{8591}\x{8594}\x{8597}\x{8599}\x{859B}\x{859C}' . + '\x{85A4}\x{85A6}\x{85A8}\x{85A9}\x{85AA}\x{85AB}\x{85AC}\x{85AE}\x{85AF}' . + '\x{85B9}\x{85BA}\x{85C1}\x{85C9}\x{85CD}\x{85CF}\x{85D0}\x{85D5}\x{85DC}' . + '\x{85DD}\x{85E4}\x{85E5}\x{85E9}\x{85EA}\x{85F7}\x{85F9}\x{85FA}\x{85FB}' . + '\x{85FE}\x{8602}\x{8606}\x{8607}\x{860A}\x{860B}\x{8613}\x{8616}\x{8617}' . + '\x{861A}\x{8622}\x{862D}\x{862F}\x{8630}\x{863F}\x{864D}\x{864E}\x{8650}' . + '\x{8654}\x{8655}\x{865A}\x{865C}\x{865E}\x{865F}\x{8667}\x{866B}\x{8671}' . + '\x{8679}\x{867B}\x{868A}\x{868B}\x{868C}\x{8693}\x{8695}\x{86A3}\x{86A4}' . + '\x{86A9}\x{86AA}\x{86AB}\x{86AF}\x{86B0}\x{86B6}\x{86C4}\x{86C6}\x{86C7}' . + '\x{86C9}\x{86CB}\x{86CD}\x{86CE}\x{86D4}\x{86D9}\x{86DB}\x{86DE}\x{86DF}' . + '\x{86E4}\x{86E9}\x{86EC}\x{86ED}\x{86EE}\x{86EF}\x{86F8}\x{86F9}\x{86FB}' . + '\x{86FE}\x{8700}\x{8702}\x{8703}\x{8706}\x{8708}\x{8709}\x{870A}\x{870D}' . + '\x{8711}\x{8712}\x{8718}\x{871A}\x{871C}\x{8725}\x{8729}\x{8734}\x{8737}' . + '\x{873B}\x{873F}\x{8749}\x{874B}\x{874C}\x{874E}\x{8753}\x{8755}\x{8757}' . + '\x{8759}\x{875F}\x{8760}\x{8763}\x{8766}\x{8768}\x{876A}\x{876E}\x{8774}' . + '\x{8776}\x{8778}\x{877F}\x{8782}\x{878D}\x{879F}\x{87A2}\x{87AB}\x{87AF}' . + '\x{87B3}\x{87BA}\x{87BB}\x{87BD}\x{87C0}\x{87C4}\x{87C6}\x{87C7}\x{87CB}' . + '\x{87D0}\x{87D2}\x{87E0}\x{87EF}\x{87F2}\x{87F6}\x{87F7}\x{87F9}\x{87FB}' . + '\x{87FE}\x{8805}\x{880D}\x{880E}\x{880F}\x{8811}\x{8815}\x{8816}\x{8821}' . + '\x{8822}\x{8823}\x{8827}\x{8831}\x{8836}\x{8839}\x{883B}\x{8840}\x{8842}' . + '\x{8844}\x{8846}\x{884C}\x{884D}\x{8852}\x{8853}\x{8857}\x{8859}\x{885B}' . + '\x{885D}\x{885E}\x{8861}\x{8862}\x{8863}\x{8868}\x{886B}\x{8870}\x{8872}' . + '\x{8875}\x{8877}\x{887D}\x{887E}\x{887F}\x{8881}\x{8882}\x{8888}\x{888B}' . + '\x{888D}\x{8892}\x{8896}\x{8897}\x{8899}\x{889E}\x{88A2}\x{88A4}\x{88AB}' . + '\x{88AE}\x{88B0}\x{88B1}\x{88B4}\x{88B5}\x{88B7}\x{88BF}\x{88C1}\x{88C2}' . + '\x{88C3}\x{88C4}\x{88C5}\x{88CF}\x{88D4}\x{88D5}\x{88D8}\x{88D9}\x{88DC}' . + '\x{88DD}\x{88DF}\x{88E1}\x{88E8}\x{88F2}\x{88F3}\x{88F4}\x{88F8}\x{88F9}' . + '\x{88FC}\x{88FD}\x{88FE}\x{8902}\x{8904}\x{8907}\x{890A}\x{890C}\x{8910}' . + '\x{8912}\x{8913}\x{891D}\x{891E}\x{8925}\x{892A}\x{892B}\x{8936}\x{8938}' . + '\x{893B}\x{8941}\x{8943}\x{8944}\x{894C}\x{894D}\x{8956}\x{895E}\x{895F}' . + '\x{8960}\x{8964}\x{8966}\x{896A}\x{896D}\x{896F}\x{8972}\x{8974}\x{8977}' . + '\x{897E}\x{897F}\x{8981}\x{8983}\x{8986}\x{8987}\x{8988}\x{898A}\x{898B}' . + '\x{898F}\x{8993}\x{8996}\x{8997}\x{8998}\x{899A}\x{89A1}\x{89A6}\x{89A7}' . + '\x{89A9}\x{89AA}\x{89AC}\x{89AF}\x{89B2}\x{89B3}\x{89BA}\x{89BD}\x{89BF}' . + '\x{89C0}\x{89D2}\x{89DA}\x{89DC}\x{89DD}\x{89E3}\x{89E6}\x{89E7}\x{89F4}' . + '\x{89F8}\x{8A00}\x{8A02}\x{8A03}\x{8A08}\x{8A0A}\x{8A0C}\x{8A0E}\x{8A10}' . + '\x{8A13}\x{8A16}\x{8A17}\x{8A18}\x{8A1B}\x{8A1D}\x{8A1F}\x{8A23}\x{8A25}' . + '\x{8A2A}\x{8A2D}\x{8A31}\x{8A33}\x{8A34}\x{8A36}\x{8A3A}\x{8A3B}\x{8A3C}' . + '\x{8A41}\x{8A46}\x{8A48}\x{8A50}\x{8A51}\x{8A52}\x{8A54}\x{8A55}\x{8A5B}' . + '\x{8A5E}\x{8A60}\x{8A62}\x{8A63}\x{8A66}\x{8A69}\x{8A6B}\x{8A6C}\x{8A6D}' . + '\x{8A6E}\x{8A70}\x{8A71}\x{8A72}\x{8A73}\x{8A7C}\x{8A82}\x{8A84}\x{8A85}' . + '\x{8A87}\x{8A89}\x{8A8C}\x{8A8D}\x{8A91}\x{8A93}\x{8A95}\x{8A98}\x{8A9A}' . + '\x{8A9E}\x{8AA0}\x{8AA1}\x{8AA3}\x{8AA4}\x{8AA5}\x{8AA6}\x{8AA8}\x{8AAC}' . + '\x{8AAD}\x{8AB0}\x{8AB2}\x{8AB9}\x{8ABC}\x{8ABF}\x{8AC2}\x{8AC4}\x{8AC7}' . + '\x{8ACB}\x{8ACC}\x{8ACD}\x{8ACF}\x{8AD2}\x{8AD6}\x{8ADA}\x{8ADB}\x{8ADC}' . + '\x{8ADE}\x{8AE0}\x{8AE1}\x{8AE2}\x{8AE4}\x{8AE6}\x{8AE7}\x{8AEB}\x{8AED}' . + '\x{8AEE}\x{8AF1}\x{8AF3}\x{8AF7}\x{8AF8}\x{8AFA}\x{8AFE}\x{8B00}\x{8B01}' . + '\x{8B02}\x{8B04}\x{8B07}\x{8B0C}\x{8B0E}\x{8B10}\x{8B14}\x{8B16}\x{8B17}' . + '\x{8B19}\x{8B1A}\x{8B1B}\x{8B1D}\x{8B20}\x{8B21}\x{8B26}\x{8B28}\x{8B2B}' . + '\x{8B2C}\x{8B33}\x{8B39}\x{8B3E}\x{8B41}\x{8B49}\x{8B4C}\x{8B4E}\x{8B4F}' . + '\x{8B56}\x{8B58}\x{8B5A}\x{8B5B}\x{8B5C}\x{8B5F}\x{8B66}\x{8B6B}\x{8B6C}' . + '\x{8B6F}\x{8B70}\x{8B71}\x{8B72}\x{8B74}\x{8B77}\x{8B7D}\x{8B80}\x{8B83}' . + '\x{8B8A}\x{8B8C}\x{8B8E}\x{8B90}\x{8B92}\x{8B93}\x{8B96}\x{8B99}\x{8B9A}' . + '\x{8C37}\x{8C3A}\x{8C3F}\x{8C41}\x{8C46}\x{8C48}\x{8C4A}\x{8C4C}\x{8C4E}' . + '\x{8C50}\x{8C55}\x{8C5A}\x{8C61}\x{8C62}\x{8C6A}\x{8C6B}\x{8C6C}\x{8C78}' . + '\x{8C79}\x{8C7A}\x{8C7C}\x{8C82}\x{8C85}\x{8C89}\x{8C8A}\x{8C8C}\x{8C8D}' . + '\x{8C8E}\x{8C94}\x{8C98}\x{8C9D}\x{8C9E}\x{8CA0}\x{8CA1}\x{8CA2}\x{8CA7}' . + '\x{8CA8}\x{8CA9}\x{8CAA}\x{8CAB}\x{8CAC}\x{8CAD}\x{8CAE}\x{8CAF}\x{8CB0}' . + '\x{8CB2}\x{8CB3}\x{8CB4}\x{8CB6}\x{8CB7}\x{8CB8}\x{8CBB}\x{8CBC}\x{8CBD}' . + '\x{8CBF}\x{8CC0}\x{8CC1}\x{8CC2}\x{8CC3}\x{8CC4}\x{8CC7}\x{8CC8}\x{8CCA}' . + '\x{8CCD}\x{8CCE}\x{8CD1}\x{8CD3}\x{8CDA}\x{8CDB}\x{8CDC}\x{8CDE}\x{8CE0}' . + '\x{8CE2}\x{8CE3}\x{8CE4}\x{8CE6}\x{8CEA}\x{8CED}\x{8CFA}\x{8CFB}\x{8CFC}' . + '\x{8CFD}\x{8D04}\x{8D05}\x{8D07}\x{8D08}\x{8D0A}\x{8D0B}\x{8D0D}\x{8D0F}' . + '\x{8D10}\x{8D13}\x{8D14}\x{8D16}\x{8D64}\x{8D66}\x{8D67}\x{8D6B}\x{8D6D}' . + '\x{8D70}\x{8D71}\x{8D73}\x{8D74}\x{8D77}\x{8D81}\x{8D85}\x{8D8A}\x{8D99}' . + '\x{8DA3}\x{8DA8}\x{8DB3}\x{8DBA}\x{8DBE}\x{8DC2}\x{8DCB}\x{8DCC}\x{8DCF}' . + '\x{8DD6}\x{8DDA}\x{8DDB}\x{8DDD}\x{8DDF}\x{8DE1}\x{8DE3}\x{8DE8}\x{8DEA}' . + '\x{8DEB}\x{8DEF}\x{8DF3}\x{8DF5}\x{8DFC}\x{8DFF}\x{8E08}\x{8E09}\x{8E0A}' . + '\x{8E0F}\x{8E10}\x{8E1D}\x{8E1E}\x{8E1F}\x{8E2A}\x{8E30}\x{8E34}\x{8E35}' . + '\x{8E42}\x{8E44}\x{8E47}\x{8E48}\x{8E49}\x{8E4A}\x{8E4C}\x{8E50}\x{8E55}' . + '\x{8E59}\x{8E5F}\x{8E60}\x{8E63}\x{8E64}\x{8E72}\x{8E74}\x{8E76}\x{8E7C}' . + '\x{8E81}\x{8E84}\x{8E85}\x{8E87}\x{8E8A}\x{8E8B}\x{8E8D}\x{8E91}\x{8E93}' . + '\x{8E94}\x{8E99}\x{8EA1}\x{8EAA}\x{8EAB}\x{8EAC}\x{8EAF}\x{8EB0}\x{8EB1}' . + '\x{8EBE}\x{8EC5}\x{8EC6}\x{8EC8}\x{8ECA}\x{8ECB}\x{8ECC}\x{8ECD}\x{8ED2}' . + '\x{8EDB}\x{8EDF}\x{8EE2}\x{8EE3}\x{8EEB}\x{8EF8}\x{8EFB}\x{8EFC}\x{8EFD}' . + '\x{8EFE}\x{8F03}\x{8F05}\x{8F09}\x{8F0A}\x{8F0C}\x{8F12}\x{8F13}\x{8F14}' . + '\x{8F15}\x{8F19}\x{8F1B}\x{8F1C}\x{8F1D}\x{8F1F}\x{8F26}\x{8F29}\x{8F2A}' . + '\x{8F2F}\x{8F33}\x{8F38}\x{8F39}\x{8F3B}\x{8F3E}\x{8F3F}\x{8F42}\x{8F44}' . + '\x{8F45}\x{8F46}\x{8F49}\x{8F4C}\x{8F4D}\x{8F4E}\x{8F57}\x{8F5C}\x{8F5F}' . + '\x{8F61}\x{8F62}\x{8F63}\x{8F64}\x{8F9B}\x{8F9C}\x{8F9E}\x{8F9F}\x{8FA3}' . + '\x{8FA7}\x{8FA8}\x{8FAD}\x{8FAE}\x{8FAF}\x{8FB0}\x{8FB1}\x{8FB2}\x{8FB7}' . + '\x{8FBA}\x{8FBB}\x{8FBC}\x{8FBF}\x{8FC2}\x{8FC4}\x{8FC5}\x{8FCE}\x{8FD1}' . + '\x{8FD4}\x{8FDA}\x{8FE2}\x{8FE5}\x{8FE6}\x{8FE9}\x{8FEA}\x{8FEB}\x{8FED}' . + '\x{8FEF}\x{8FF0}\x{8FF4}\x{8FF7}\x{8FF8}\x{8FF9}\x{8FFA}\x{8FFD}\x{9000}' . + '\x{9001}\x{9003}\x{9005}\x{9006}\x{900B}\x{900D}\x{900E}\x{900F}\x{9010}' . + '\x{9011}\x{9013}\x{9014}\x{9015}\x{9016}\x{9017}\x{9019}\x{901A}\x{901D}' . + '\x{901E}\x{901F}\x{9020}\x{9021}\x{9022}\x{9023}\x{9027}\x{902E}\x{9031}' . + '\x{9032}\x{9035}\x{9036}\x{9038}\x{9039}\x{903C}\x{903E}\x{9041}\x{9042}' . + '\x{9045}\x{9047}\x{9049}\x{904A}\x{904B}\x{904D}\x{904E}\x{904F}\x{9050}' . + '\x{9051}\x{9052}\x{9053}\x{9054}\x{9055}\x{9056}\x{9058}\x{9059}\x{905C}' . + '\x{905E}\x{9060}\x{9061}\x{9063}\x{9065}\x{9068}\x{9069}\x{906D}\x{906E}' . + '\x{906F}\x{9072}\x{9075}\x{9076}\x{9077}\x{9078}\x{907A}\x{907C}\x{907D}' . + '\x{907F}\x{9080}\x{9081}\x{9082}\x{9083}\x{9084}\x{9087}\x{9089}\x{908A}' . + '\x{908F}\x{9091}\x{90A3}\x{90A6}\x{90A8}\x{90AA}\x{90AF}\x{90B1}\x{90B5}' . + '\x{90B8}\x{90C1}\x{90CA}\x{90CE}\x{90DB}\x{90E1}\x{90E2}\x{90E4}\x{90E8}' . + '\x{90ED}\x{90F5}\x{90F7}\x{90FD}\x{9102}\x{9112}\x{9119}\x{912D}\x{9130}' . + '\x{9132}\x{9149}\x{914A}\x{914B}\x{914C}\x{914D}\x{914E}\x{9152}\x{9154}' . + '\x{9156}\x{9158}\x{9162}\x{9163}\x{9165}\x{9169}\x{916A}\x{916C}\x{9172}' . + '\x{9173}\x{9175}\x{9177}\x{9178}\x{9182}\x{9187}\x{9189}\x{918B}\x{918D}' . + '\x{9190}\x{9192}\x{9197}\x{919C}\x{91A2}\x{91A4}\x{91AA}\x{91AB}\x{91AF}' . + '\x{91B4}\x{91B5}\x{91B8}\x{91BA}\x{91C0}\x{91C1}\x{91C6}\x{91C7}\x{91C8}' . + '\x{91C9}\x{91CB}\x{91CC}\x{91CD}\x{91CE}\x{91CF}\x{91D0}\x{91D1}\x{91D6}' . + '\x{91D8}\x{91DB}\x{91DC}\x{91DD}\x{91DF}\x{91E1}\x{91E3}\x{91E6}\x{91E7}' . + '\x{91F5}\x{91F6}\x{91FC}\x{91FF}\x{920D}\x{920E}\x{9211}\x{9214}\x{9215}' . + '\x{921E}\x{9229}\x{922C}\x{9234}\x{9237}\x{923F}\x{9244}\x{9245}\x{9248}' . + '\x{9249}\x{924B}\x{9250}\x{9257}\x{925A}\x{925B}\x{925E}\x{9262}\x{9264}' . + '\x{9266}\x{9271}\x{927E}\x{9280}\x{9283}\x{9285}\x{9291}\x{9293}\x{9295}' . + '\x{9296}\x{9298}\x{929A}\x{929B}\x{929C}\x{92AD}\x{92B7}\x{92B9}\x{92CF}' . + '\x{92D2}\x{92E4}\x{92E9}\x{92EA}\x{92ED}\x{92F2}\x{92F3}\x{92F8}\x{92FA}' . + '\x{92FC}\x{9306}\x{930F}\x{9310}\x{9318}\x{9319}\x{931A}\x{9320}\x{9322}' . + '\x{9323}\x{9326}\x{9328}\x{932B}\x{932C}\x{932E}\x{932F}\x{9332}\x{9335}' . + '\x{933A}\x{933B}\x{9344}\x{934B}\x{934D}\x{9354}\x{9356}\x{935B}\x{935C}' . + '\x{9360}\x{936C}\x{936E}\x{9375}\x{937C}\x{937E}\x{938C}\x{9394}\x{9396}' . + '\x{9397}\x{939A}\x{93A7}\x{93AC}\x{93AD}\x{93AE}\x{93B0}\x{93B9}\x{93C3}' . + '\x{93C8}\x{93D0}\x{93D1}\x{93D6}\x{93D7}\x{93D8}\x{93DD}\x{93E1}\x{93E4}' . + '\x{93E5}\x{93E8}\x{9403}\x{9407}\x{9410}\x{9413}\x{9414}\x{9418}\x{9419}' . + '\x{941A}\x{9421}\x{942B}\x{9435}\x{9436}\x{9438}\x{943A}\x{9441}\x{9444}' . + '\x{9451}\x{9452}\x{9453}\x{945A}\x{945B}\x{945E}\x{9460}\x{9462}\x{946A}' . + '\x{9470}\x{9475}\x{9477}\x{947C}\x{947D}\x{947E}\x{947F}\x{9481}\x{9577}' . + '\x{9580}\x{9582}\x{9583}\x{9587}\x{9589}\x{958A}\x{958B}\x{958F}\x{9591}' . + '\x{9593}\x{9594}\x{9596}\x{9598}\x{9599}\x{95A0}\x{95A2}\x{95A3}\x{95A4}' . + '\x{95A5}\x{95A7}\x{95A8}\x{95AD}\x{95B2}\x{95B9}\x{95BB}\x{95BC}\x{95BE}' . + '\x{95C3}\x{95C7}\x{95CA}\x{95CC}\x{95CD}\x{95D4}\x{95D5}\x{95D6}\x{95D8}' . + '\x{95DC}\x{95E1}\x{95E2}\x{95E5}\x{961C}\x{9621}\x{9628}\x{962A}\x{962E}' . + '\x{962F}\x{9632}\x{963B}\x{963F}\x{9640}\x{9642}\x{9644}\x{964B}\x{964C}' . + '\x{964D}\x{964F}\x{9650}\x{965B}\x{965C}\x{965D}\x{965E}\x{965F}\x{9662}' . + '\x{9663}\x{9664}\x{9665}\x{9666}\x{966A}\x{966C}\x{9670}\x{9672}\x{9673}' . + '\x{9675}\x{9676}\x{9677}\x{9678}\x{967A}\x{967D}\x{9685}\x{9686}\x{9688}' . + '\x{968A}\x{968B}\x{968D}\x{968E}\x{968F}\x{9694}\x{9695}\x{9697}\x{9698}' . + '\x{9699}\x{969B}\x{969C}\x{96A0}\x{96A3}\x{96A7}\x{96A8}\x{96AA}\x{96B0}' . + '\x{96B1}\x{96B2}\x{96B4}\x{96B6}\x{96B7}\x{96B8}\x{96B9}\x{96BB}\x{96BC}' . + '\x{96C0}\x{96C1}\x{96C4}\x{96C5}\x{96C6}\x{96C7}\x{96C9}\x{96CB}\x{96CC}' . + '\x{96CD}\x{96CE}\x{96D1}\x{96D5}\x{96D6}\x{96D9}\x{96DB}\x{96DC}\x{96E2}' . + '\x{96E3}\x{96E8}\x{96EA}\x{96EB}\x{96F0}\x{96F2}\x{96F6}\x{96F7}\x{96F9}' . + '\x{96FB}\x{9700}\x{9704}\x{9706}\x{9707}\x{9708}\x{970A}\x{970D}\x{970E}' . + '\x{970F}\x{9711}\x{9713}\x{9716}\x{9719}\x{971C}\x{971E}\x{9724}\x{9727}' . + '\x{972A}\x{9730}\x{9732}\x{9738}\x{9739}\x{973D}\x{973E}\x{9742}\x{9744}' . + '\x{9746}\x{9748}\x{9749}\x{9752}\x{9756}\x{9759}\x{975C}\x{975E}\x{9760}' . + '\x{9761}\x{9762}\x{9764}\x{9766}\x{9768}\x{9769}\x{976B}\x{976D}\x{9771}' . + '\x{9774}\x{9779}\x{977A}\x{977C}\x{9781}\x{9784}\x{9785}\x{9786}\x{978B}' . + '\x{978D}\x{978F}\x{9790}\x{9798}\x{979C}\x{97A0}\x{97A3}\x{97A6}\x{97A8}' . + '\x{97AB}\x{97AD}\x{97B3}\x{97B4}\x{97C3}\x{97C6}\x{97C8}\x{97CB}\x{97D3}' . + '\x{97DC}\x{97ED}\x{97EE}\x{97F2}\x{97F3}\x{97F5}\x{97F6}\x{97FB}\x{97FF}' . + '\x{9801}\x{9802}\x{9803}\x{9805}\x{9806}\x{9808}\x{980C}\x{980F}\x{9810}' . + '\x{9811}\x{9812}\x{9813}\x{9817}\x{9818}\x{981A}\x{9821}\x{9824}\x{982C}' . + '\x{982D}\x{9834}\x{9837}\x{9838}\x{983B}\x{983C}\x{983D}\x{9846}\x{984B}' . + '\x{984C}\x{984D}\x{984E}\x{984F}\x{9854}\x{9855}\x{9858}\x{985B}\x{985E}' . + '\x{9867}\x{986B}\x{986F}\x{9870}\x{9871}\x{9873}\x{9874}\x{98A8}\x{98AA}' . + '\x{98AF}\x{98B1}\x{98B6}\x{98C3}\x{98C4}\x{98C6}\x{98DB}\x{98DC}\x{98DF}' . + '\x{98E2}\x{98E9}\x{98EB}\x{98ED}\x{98EE}\x{98EF}\x{98F2}\x{98F4}\x{98FC}' . + '\x{98FD}\x{98FE}\x{9903}\x{9905}\x{9909}\x{990A}\x{990C}\x{9910}\x{9912}' . + '\x{9913}\x{9914}\x{9918}\x{991D}\x{991E}\x{9920}\x{9921}\x{9924}\x{9928}' . + '\x{992C}\x{992E}\x{993D}\x{993E}\x{9942}\x{9945}\x{9949}\x{994B}\x{994C}' . + '\x{9950}\x{9951}\x{9952}\x{9955}\x{9957}\x{9996}\x{9997}\x{9998}\x{9999}' . + '\x{99A5}\x{99A8}\x{99AC}\x{99AD}\x{99AE}\x{99B3}\x{99B4}\x{99BC}\x{99C1}' . + '\x{99C4}\x{99C5}\x{99C6}\x{99C8}\x{99D0}\x{99D1}\x{99D2}\x{99D5}\x{99D8}' . + '\x{99DB}\x{99DD}\x{99DF}\x{99E2}\x{99ED}\x{99EE}\x{99F1}\x{99F2}\x{99F8}' . + '\x{99FB}\x{99FF}\x{9A01}\x{9A05}\x{9A0E}\x{9A0F}\x{9A12}\x{9A13}\x{9A19}' . + '\x{9A28}\x{9A2B}\x{9A30}\x{9A37}\x{9A3E}\x{9A40}\x{9A42}\x{9A43}\x{9A45}' . + '\x{9A4D}\x{9A55}\x{9A57}\x{9A5A}\x{9A5B}\x{9A5F}\x{9A62}\x{9A64}\x{9A65}' . + '\x{9A69}\x{9A6A}\x{9A6B}\x{9AA8}\x{9AAD}\x{9AB0}\x{9AB8}\x{9ABC}\x{9AC0}' . + '\x{9AC4}\x{9ACF}\x{9AD1}\x{9AD3}\x{9AD4}\x{9AD8}\x{9ADE}\x{9ADF}\x{9AE2}' . + '\x{9AE3}\x{9AE6}\x{9AEA}\x{9AEB}\x{9AED}\x{9AEE}\x{9AEF}\x{9AF1}\x{9AF4}' . + '\x{9AF7}\x{9AFB}\x{9B06}\x{9B18}\x{9B1A}\x{9B1F}\x{9B22}\x{9B23}\x{9B25}' . + '\x{9B27}\x{9B28}\x{9B29}\x{9B2A}\x{9B2E}\x{9B2F}\x{9B31}\x{9B32}\x{9B3B}' . + '\x{9B3C}\x{9B41}\x{9B42}\x{9B43}\x{9B44}\x{9B45}\x{9B4D}\x{9B4E}\x{9B4F}' . + '\x{9B51}\x{9B54}\x{9B58}\x{9B5A}\x{9B6F}\x{9B74}\x{9B83}\x{9B8E}\x{9B91}' . + '\x{9B92}\x{9B93}\x{9B96}\x{9B97}\x{9B9F}\x{9BA0}\x{9BA8}\x{9BAA}\x{9BAB}' . + '\x{9BAD}\x{9BAE}\x{9BB4}\x{9BB9}\x{9BC0}\x{9BC6}\x{9BC9}\x{9BCA}\x{9BCF}' . + '\x{9BD1}\x{9BD2}\x{9BD4}\x{9BD6}\x{9BDB}\x{9BE1}\x{9BE2}\x{9BE3}\x{9BE4}' . + '\x{9BE8}\x{9BF0}\x{9BF1}\x{9BF2}\x{9BF5}\x{9C04}\x{9C06}\x{9C08}\x{9C09}' . + '\x{9C0A}\x{9C0C}\x{9C0D}\x{9C10}\x{9C12}\x{9C13}\x{9C14}\x{9C15}\x{9C1B}' . + '\x{9C21}\x{9C24}\x{9C25}\x{9C2D}\x{9C2E}\x{9C2F}\x{9C30}\x{9C32}\x{9C39}' . + '\x{9C3A}\x{9C3B}\x{9C3E}\x{9C46}\x{9C47}\x{9C48}\x{9C52}\x{9C57}\x{9C5A}' . + '\x{9C60}\x{9C67}\x{9C76}\x{9C78}\x{9CE5}\x{9CE7}\x{9CE9}\x{9CEB}\x{9CEC}' . + '\x{9CF0}\x{9CF3}\x{9CF4}\x{9CF6}\x{9D03}\x{9D06}\x{9D07}\x{9D08}\x{9D09}' . + '\x{9D0E}\x{9D12}\x{9D15}\x{9D1B}\x{9D1F}\x{9D23}\x{9D26}\x{9D28}\x{9D2A}' . + '\x{9D2B}\x{9D2C}\x{9D3B}\x{9D3E}\x{9D3F}\x{9D41}\x{9D44}\x{9D46}\x{9D48}' . + '\x{9D50}\x{9D51}\x{9D59}\x{9D5C}\x{9D5D}\x{9D5E}\x{9D60}\x{9D61}\x{9D64}' . + '\x{9D6C}\x{9D6F}\x{9D72}\x{9D7A}\x{9D87}\x{9D89}\x{9D8F}\x{9D9A}\x{9DA4}' . + '\x{9DA9}\x{9DAB}\x{9DAF}\x{9DB2}\x{9DB4}\x{9DB8}\x{9DBA}\x{9DBB}\x{9DC1}' . + '\x{9DC2}\x{9DC4}\x{9DC6}\x{9DCF}\x{9DD3}\x{9DD9}\x{9DE6}\x{9DED}\x{9DEF}' . + '\x{9DF2}\x{9DF8}\x{9DF9}\x{9DFA}\x{9DFD}\x{9E1A}\x{9E1B}\x{9E1E}\x{9E75}' . + '\x{9E78}\x{9E79}\x{9E7D}\x{9E7F}\x{9E81}\x{9E88}\x{9E8B}\x{9E8C}\x{9E91}' . + '\x{9E92}\x{9E93}\x{9E95}\x{9E97}\x{9E9D}\x{9E9F}\x{9EA5}\x{9EA6}\x{9EA9}' . + '\x{9EAA}\x{9EAD}\x{9EB8}\x{9EB9}\x{9EBA}\x{9EBB}\x{9EBC}\x{9EBE}\x{9EBF}' . + '\x{9EC4}\x{9ECC}\x{9ECD}\x{9ECE}\x{9ECF}\x{9ED0}\x{9ED2}\x{9ED4}\x{9ED8}' . + '\x{9ED9}\x{9EDB}\x{9EDC}\x{9EDD}\x{9EDE}\x{9EE0}\x{9EE5}\x{9EE8}\x{9EEF}' . + '\x{9EF4}\x{9EF6}\x{9EF7}\x{9EF9}\x{9EFB}\x{9EFC}\x{9EFD}\x{9F07}\x{9F08}' . + '\x{9F0E}\x{9F13}\x{9F15}\x{9F20}\x{9F21}\x{9F2C}\x{9F3B}\x{9F3E}\x{9F4A}' . + '\x{9F4B}\x{9F4E}\x{9F4F}\x{9F52}\x{9F54}\x{9F5F}\x{9F60}\x{9F61}\x{9F62}' . + '\x{9F63}\x{9F66}\x{9F67}\x{9F6A}\x{9F6C}\x{9F72}\x{9F76}\x{9F77}\x{9F8D}' . + '\x{9F95}\x{9F9C}\x{9F9D}\x{9FA0}]{1,15}$/iu', + 12 => '/^[\x{002d}0-9a-z\x{3447}\x{3473}\x{359E}\x{360E}\x{361A}\x{3918}\x{396E}\x{39CF}\x{39D0}' . + '\x{39DF}\x{3A73}\x{3B4E}\x{3C6E}\x{3CE0}\x{4056}\x{415F}\x{4337}\x{43AC}' . + '\x{43B1}\x{43DD}\x{44D6}\x{464C}\x{4661}\x{4723}\x{4729}\x{477C}\x{478D}' . + '\x{4947}\x{497A}\x{497D}\x{4982}\x{4983}\x{4985}\x{4986}\x{499B}\x{499F}' . + '\x{49B6}\x{49B7}\x{4C77}\x{4C9F}\x{4CA0}\x{4CA1}\x{4CA2}\x{4CA3}\x{4D13}' . + '\x{4D14}\x{4D15}\x{4D16}\x{4D17}\x{4D18}\x{4D19}\x{4DAE}\x{4E00}\x{4E01}' . + '\x{4E02}\x{4E03}\x{4E04}\x{4E05}\x{4E06}\x{4E07}\x{4E08}\x{4E09}\x{4E0A}' . + '\x{4E0B}\x{4E0C}\x{4E0D}\x{4E0E}\x{4E0F}\x{4E10}\x{4E11}\x{4E13}\x{4E14}' . + '\x{4E15}\x{4E16}\x{4E17}\x{4E18}\x{4E19}\x{4E1A}\x{4E1B}\x{4E1C}\x{4E1D}' . + '\x{4E1E}\x{4E1F}\x{4E20}\x{4E21}\x{4E22}\x{4E23}\x{4E24}\x{4E25}\x{4E26}' . + '\x{4E27}\x{4E28}\x{4E2A}\x{4E2B}\x{4E2C}\x{4E2D}\x{4E2E}\x{4E2F}\x{4E30}' . + '\x{4E31}\x{4E32}\x{4E33}\x{4E34}\x{4E35}\x{4E36}\x{4E37}\x{4E38}\x{4E39}' . + '\x{4E3A}\x{4E3B}\x{4E3C}\x{4E3D}\x{4E3E}\x{4E3F}\x{4E40}\x{4E41}\x{4E42}' . + '\x{4E43}\x{4E44}\x{4E45}\x{4E46}\x{4E47}\x{4E48}\x{4E49}\x{4E4A}\x{4E4B}' . + '\x{4E4C}\x{4E4D}\x{4E4E}\x{4E4F}\x{4E50}\x{4E51}\x{4E52}\x{4E53}\x{4E54}' . + '\x{4E56}\x{4E57}\x{4E58}\x{4E59}\x{4E5A}\x{4E5B}\x{4E5C}\x{4E5D}\x{4E5E}' . + '\x{4E5F}\x{4E60}\x{4E61}\x{4E62}\x{4E63}\x{4E64}\x{4E65}\x{4E66}\x{4E67}' . + '\x{4E69}\x{4E6A}\x{4E6B}\x{4E6C}\x{4E6D}\x{4E6E}\x{4E6F}\x{4E70}\x{4E71}' . + '\x{4E72}\x{4E73}\x{4E74}\x{4E75}\x{4E76}\x{4E77}\x{4E78}\x{4E7A}\x{4E7B}' . + '\x{4E7C}\x{4E7D}\x{4E7E}\x{4E7F}\x{4E80}\x{4E81}\x{4E82}\x{4E83}\x{4E84}' . + '\x{4E85}\x{4E86}\x{4E87}\x{4E88}\x{4E89}\x{4E8B}\x{4E8C}\x{4E8D}\x{4E8E}' . + '\x{4E8F}\x{4E90}\x{4E91}\x{4E92}\x{4E93}\x{4E94}\x{4E95}\x{4E97}\x{4E98}' . + '\x{4E99}\x{4E9A}\x{4E9B}\x{4E9C}\x{4E9D}\x{4E9E}\x{4E9F}\x{4EA0}\x{4EA1}' . + '\x{4EA2}\x{4EA4}\x{4EA5}\x{4EA6}\x{4EA7}\x{4EA8}\x{4EA9}\x{4EAA}\x{4EAB}' . + '\x{4EAC}\x{4EAD}\x{4EAE}\x{4EAF}\x{4EB0}\x{4EB1}\x{4EB2}\x{4EB3}\x{4EB4}' . + '\x{4EB5}\x{4EB6}\x{4EB7}\x{4EB8}\x{4EB9}\x{4EBA}\x{4EBB}\x{4EBD}\x{4EBE}' . + '\x{4EBF}\x{4EC0}\x{4EC1}\x{4EC2}\x{4EC3}\x{4EC4}\x{4EC5}\x{4EC6}\x{4EC7}' . + '\x{4EC8}\x{4EC9}\x{4ECA}\x{4ECB}\x{4ECD}\x{4ECE}\x{4ECF}\x{4ED0}\x{4ED1}' . + '\x{4ED2}\x{4ED3}\x{4ED4}\x{4ED5}\x{4ED6}\x{4ED7}\x{4ED8}\x{4ED9}\x{4EDA}' . + '\x{4EDB}\x{4EDC}\x{4EDD}\x{4EDE}\x{4EDF}\x{4EE0}\x{4EE1}\x{4EE2}\x{4EE3}' . + '\x{4EE4}\x{4EE5}\x{4EE6}\x{4EE8}\x{4EE9}\x{4EEA}\x{4EEB}\x{4EEC}\x{4EEF}' . + '\x{4EF0}\x{4EF1}\x{4EF2}\x{4EF3}\x{4EF4}\x{4EF5}\x{4EF6}\x{4EF7}\x{4EFB}' . + '\x{4EFD}\x{4EFF}\x{4F00}\x{4F01}\x{4F02}\x{4F03}\x{4F04}\x{4F05}\x{4F06}' . + '\x{4F08}\x{4F09}\x{4F0A}\x{4F0B}\x{4F0C}\x{4F0D}\x{4F0E}\x{4F0F}\x{4F10}' . + '\x{4F11}\x{4F12}\x{4F13}\x{4F14}\x{4F15}\x{4F17}\x{4F18}\x{4F19}\x{4F1A}' . + '\x{4F1B}\x{4F1C}\x{4F1D}\x{4F1E}\x{4F1F}\x{4F20}\x{4F21}\x{4F22}\x{4F23}' . + '\x{4F24}\x{4F25}\x{4F26}\x{4F27}\x{4F29}\x{4F2A}\x{4F2B}\x{4F2C}\x{4F2D}' . + '\x{4F2E}\x{4F2F}\x{4F30}\x{4F32}\x{4F33}\x{4F34}\x{4F36}\x{4F38}\x{4F39}' . + '\x{4F3A}\x{4F3B}\x{4F3C}\x{4F3D}\x{4F3E}\x{4F3F}\x{4F41}\x{4F42}\x{4F43}' . + '\x{4F45}\x{4F46}\x{4F47}\x{4F48}\x{4F49}\x{4F4A}\x{4F4B}\x{4F4C}\x{4F4D}' . + '\x{4F4E}\x{4F4F}\x{4F50}\x{4F51}\x{4F52}\x{4F53}\x{4F54}\x{4F55}\x{4F56}' . + '\x{4F57}\x{4F58}\x{4F59}\x{4F5A}\x{4F5B}\x{4F5C}\x{4F5D}\x{4F5E}\x{4F5F}' . + '\x{4F60}\x{4F61}\x{4F62}\x{4F63}\x{4F64}\x{4F65}\x{4F66}\x{4F67}\x{4F68}' . + '\x{4F69}\x{4F6A}\x{4F6B}\x{4F6C}\x{4F6D}\x{4F6E}\x{4F6F}\x{4F70}\x{4F72}' . + '\x{4F73}\x{4F74}\x{4F75}\x{4F76}\x{4F77}\x{4F78}\x{4F79}\x{4F7A}\x{4F7B}' . + '\x{4F7C}\x{4F7D}\x{4F7E}\x{4F7F}\x{4F80}\x{4F81}\x{4F82}\x{4F83}\x{4F84}' . + '\x{4F85}\x{4F86}\x{4F87}\x{4F88}\x{4F89}\x{4F8A}\x{4F8B}\x{4F8D}\x{4F8F}' . + '\x{4F90}\x{4F91}\x{4F92}\x{4F93}\x{4F94}\x{4F95}\x{4F96}\x{4F97}\x{4F98}' . + '\x{4F99}\x{4F9A}\x{4F9B}\x{4F9C}\x{4F9D}\x{4F9E}\x{4F9F}\x{4FA0}\x{4FA1}' . + '\x{4FA3}\x{4FA4}\x{4FA5}\x{4FA6}\x{4FA7}\x{4FA8}\x{4FA9}\x{4FAA}\x{4FAB}' . + '\x{4FAC}\x{4FAE}\x{4FAF}\x{4FB0}\x{4FB1}\x{4FB2}\x{4FB3}\x{4FB4}\x{4FB5}' . + '\x{4FB6}\x{4FB7}\x{4FB8}\x{4FB9}\x{4FBA}\x{4FBB}\x{4FBC}\x{4FBE}\x{4FBF}' . + '\x{4FC0}\x{4FC1}\x{4FC2}\x{4FC3}\x{4FC4}\x{4FC5}\x{4FC7}\x{4FC9}\x{4FCA}' . + '\x{4FCB}\x{4FCD}\x{4FCE}\x{4FCF}\x{4FD0}\x{4FD1}\x{4FD2}\x{4FD3}\x{4FD4}' . + '\x{4FD5}\x{4FD6}\x{4FD7}\x{4FD8}\x{4FD9}\x{4FDA}\x{4FDB}\x{4FDC}\x{4FDD}' . + '\x{4FDE}\x{4FDF}\x{4FE0}\x{4FE1}\x{4FE3}\x{4FE4}\x{4FE5}\x{4FE6}\x{4FE7}' . + '\x{4FE8}\x{4FE9}\x{4FEA}\x{4FEB}\x{4FEC}\x{4FED}\x{4FEE}\x{4FEF}\x{4FF0}' . + '\x{4FF1}\x{4FF2}\x{4FF3}\x{4FF4}\x{4FF5}\x{4FF6}\x{4FF7}\x{4FF8}\x{4FF9}' . + '\x{4FFA}\x{4FFB}\x{4FFE}\x{4FFF}\x{5000}\x{5001}\x{5002}\x{5003}\x{5004}' . + '\x{5005}\x{5006}\x{5007}\x{5008}\x{5009}\x{500A}\x{500B}\x{500C}\x{500D}' . + '\x{500E}\x{500F}\x{5011}\x{5012}\x{5013}\x{5014}\x{5015}\x{5016}\x{5017}' . + '\x{5018}\x{5019}\x{501A}\x{501B}\x{501C}\x{501D}\x{501E}\x{501F}\x{5020}' . + '\x{5021}\x{5022}\x{5023}\x{5024}\x{5025}\x{5026}\x{5027}\x{5028}\x{5029}' . + '\x{502A}\x{502B}\x{502C}\x{502D}\x{502E}\x{502F}\x{5030}\x{5031}\x{5032}' . + '\x{5033}\x{5035}\x{5036}\x{5037}\x{5039}\x{503A}\x{503B}\x{503C}\x{503E}' . + '\x{503F}\x{5040}\x{5041}\x{5043}\x{5044}\x{5045}\x{5046}\x{5047}\x{5048}' . + '\x{5049}\x{504A}\x{504B}\x{504C}\x{504D}\x{504E}\x{504F}\x{5051}\x{5053}' . + '\x{5054}\x{5055}\x{5056}\x{5057}\x{5059}\x{505A}\x{505B}\x{505C}\x{505D}' . + '\x{505E}\x{505F}\x{5060}\x{5061}\x{5062}\x{5063}\x{5064}\x{5065}\x{5066}' . + '\x{5067}\x{5068}\x{5069}\x{506A}\x{506B}\x{506C}\x{506D}\x{506E}\x{506F}' . + '\x{5070}\x{5071}\x{5072}\x{5073}\x{5074}\x{5075}\x{5076}\x{5077}\x{5078}' . + '\x{5079}\x{507A}\x{507B}\x{507D}\x{507E}\x{507F}\x{5080}\x{5082}\x{5083}' . + '\x{5084}\x{5085}\x{5086}\x{5087}\x{5088}\x{5089}\x{508A}\x{508B}\x{508C}' . + '\x{508D}\x{508E}\x{508F}\x{5090}\x{5091}\x{5092}\x{5094}\x{5095}\x{5096}' . + '\x{5098}\x{5099}\x{509A}\x{509B}\x{509C}\x{509D}\x{509E}\x{50A2}\x{50A3}' . + '\x{50A4}\x{50A5}\x{50A6}\x{50A7}\x{50A8}\x{50A9}\x{50AA}\x{50AB}\x{50AC}' . + '\x{50AD}\x{50AE}\x{50AF}\x{50B0}\x{50B1}\x{50B2}\x{50B3}\x{50B4}\x{50B5}' . + '\x{50B6}\x{50B7}\x{50B8}\x{50BA}\x{50BB}\x{50BC}\x{50BD}\x{50BE}\x{50BF}' . + '\x{50C0}\x{50C1}\x{50C2}\x{50C4}\x{50C5}\x{50C6}\x{50C7}\x{50C8}\x{50C9}' . + '\x{50CA}\x{50CB}\x{50CC}\x{50CD}\x{50CE}\x{50CF}\x{50D0}\x{50D1}\x{50D2}' . + '\x{50D3}\x{50D4}\x{50D5}\x{50D6}\x{50D7}\x{50D9}\x{50DA}\x{50DB}\x{50DC}' . + '\x{50DD}\x{50DE}\x{50E0}\x{50E3}\x{50E4}\x{50E5}\x{50E6}\x{50E7}\x{50E8}' . + '\x{50E9}\x{50EA}\x{50EC}\x{50ED}\x{50EE}\x{50EF}\x{50F0}\x{50F1}\x{50F2}' . + '\x{50F3}\x{50F5}\x{50F6}\x{50F8}\x{50F9}\x{50FA}\x{50FB}\x{50FC}\x{50FD}' . + '\x{50FE}\x{50FF}\x{5100}\x{5101}\x{5102}\x{5103}\x{5104}\x{5105}\x{5106}' . + '\x{5107}\x{5108}\x{5109}\x{510A}\x{510B}\x{510C}\x{510D}\x{510E}\x{510F}' . + '\x{5110}\x{5111}\x{5112}\x{5113}\x{5114}\x{5115}\x{5116}\x{5117}\x{5118}' . + '\x{5119}\x{511A}\x{511C}\x{511D}\x{511E}\x{511F}\x{5120}\x{5121}\x{5122}' . + '\x{5123}\x{5124}\x{5125}\x{5126}\x{5127}\x{5129}\x{512A}\x{512C}\x{512D}' . + '\x{512E}\x{512F}\x{5130}\x{5131}\x{5132}\x{5133}\x{5134}\x{5135}\x{5136}' . + '\x{5137}\x{5138}\x{5139}\x{513A}\x{513B}\x{513C}\x{513D}\x{513E}\x{513F}' . + '\x{5140}\x{5141}\x{5143}\x{5144}\x{5145}\x{5146}\x{5147}\x{5148}\x{5149}' . + '\x{514B}\x{514C}\x{514D}\x{514E}\x{5150}\x{5151}\x{5152}\x{5154}\x{5155}' . + '\x{5156}\x{5157}\x{5159}\x{515A}\x{515B}\x{515C}\x{515D}\x{515E}\x{515F}' . + '\x{5161}\x{5162}\x{5163}\x{5165}\x{5166}\x{5167}\x{5168}\x{5169}\x{516A}' . + '\x{516B}\x{516C}\x{516D}\x{516E}\x{516F}\x{5170}\x{5171}\x{5173}\x{5174}' . + '\x{5175}\x{5176}\x{5177}\x{5178}\x{5179}\x{517A}\x{517B}\x{517C}\x{517D}' . + '\x{517F}\x{5180}\x{5181}\x{5182}\x{5185}\x{5186}\x{5187}\x{5188}\x{5189}' . + '\x{518A}\x{518B}\x{518C}\x{518D}\x{518F}\x{5190}\x{5191}\x{5192}\x{5193}' . + '\x{5194}\x{5195}\x{5196}\x{5197}\x{5198}\x{5199}\x{519A}\x{519B}\x{519C}' . + '\x{519D}\x{519E}\x{519F}\x{51A0}\x{51A2}\x{51A4}\x{51A5}\x{51A6}\x{51A7}' . + '\x{51A8}\x{51AA}\x{51AB}\x{51AC}\x{51AE}\x{51AF}\x{51B0}\x{51B1}\x{51B2}' . + '\x{51B3}\x{51B5}\x{51B6}\x{51B7}\x{51B9}\x{51BB}\x{51BC}\x{51BD}\x{51BE}' . + '\x{51BF}\x{51C0}\x{51C1}\x{51C3}\x{51C4}\x{51C5}\x{51C6}\x{51C7}\x{51C8}' . + '\x{51C9}\x{51CA}\x{51CB}\x{51CC}\x{51CD}\x{51CE}\x{51CF}\x{51D0}\x{51D1}' . + '\x{51D4}\x{51D5}\x{51D6}\x{51D7}\x{51D8}\x{51D9}\x{51DA}\x{51DB}\x{51DC}' . + '\x{51DD}\x{51DE}\x{51E0}\x{51E1}\x{51E2}\x{51E3}\x{51E4}\x{51E5}\x{51E7}' . + '\x{51E8}\x{51E9}\x{51EA}\x{51EB}\x{51ED}\x{51EF}\x{51F0}\x{51F1}\x{51F3}' . + '\x{51F4}\x{51F5}\x{51F6}\x{51F7}\x{51F8}\x{51F9}\x{51FA}\x{51FB}\x{51FC}' . + '\x{51FD}\x{51FE}\x{51FF}\x{5200}\x{5201}\x{5202}\x{5203}\x{5204}\x{5205}' . + '\x{5206}\x{5207}\x{5208}\x{5209}\x{520A}\x{520B}\x{520C}\x{520D}\x{520E}' . + '\x{520F}\x{5210}\x{5211}\x{5212}\x{5213}\x{5214}\x{5215}\x{5216}\x{5217}' . + '\x{5218}\x{5219}\x{521A}\x{521B}\x{521C}\x{521D}\x{521E}\x{521F}\x{5220}' . + '\x{5221}\x{5222}\x{5223}\x{5224}\x{5225}\x{5226}\x{5228}\x{5229}\x{522A}' . + '\x{522B}\x{522C}\x{522D}\x{522E}\x{522F}\x{5230}\x{5231}\x{5232}\x{5233}' . + '\x{5234}\x{5235}\x{5236}\x{5237}\x{5238}\x{5239}\x{523A}\x{523B}\x{523C}' . + '\x{523D}\x{523E}\x{523F}\x{5240}\x{5241}\x{5242}\x{5243}\x{5244}\x{5245}' . + '\x{5246}\x{5247}\x{5248}\x{5249}\x{524A}\x{524B}\x{524C}\x{524D}\x{524E}' . + '\x{5250}\x{5251}\x{5252}\x{5254}\x{5255}\x{5256}\x{5257}\x{5258}\x{5259}' . + '\x{525A}\x{525B}\x{525C}\x{525D}\x{525E}\x{525F}\x{5260}\x{5261}\x{5262}' . + '\x{5263}\x{5264}\x{5265}\x{5267}\x{5268}\x{5269}\x{526A}\x{526B}\x{526C}' . + '\x{526D}\x{526E}\x{526F}\x{5270}\x{5272}\x{5273}\x{5274}\x{5275}\x{5276}' . + '\x{5277}\x{5278}\x{527A}\x{527B}\x{527C}\x{527D}\x{527E}\x{527F}\x{5280}' . + '\x{5281}\x{5282}\x{5283}\x{5284}\x{5286}\x{5287}\x{5288}\x{5289}\x{528A}' . + '\x{528B}\x{528C}\x{528D}\x{528F}\x{5290}\x{5291}\x{5292}\x{5293}\x{5294}' . + '\x{5295}\x{5296}\x{5297}\x{5298}\x{5299}\x{529A}\x{529B}\x{529C}\x{529D}' . + '\x{529E}\x{529F}\x{52A0}\x{52A1}\x{52A2}\x{52A3}\x{52A5}\x{52A6}\x{52A7}' . + '\x{52A8}\x{52A9}\x{52AA}\x{52AB}\x{52AC}\x{52AD}\x{52AE}\x{52AF}\x{52B0}' . + '\x{52B1}\x{52B2}\x{52B3}\x{52B4}\x{52B5}\x{52B6}\x{52B7}\x{52B8}\x{52B9}' . + '\x{52BA}\x{52BB}\x{52BC}\x{52BD}\x{52BE}\x{52BF}\x{52C0}\x{52C1}\x{52C2}' . + '\x{52C3}\x{52C6}\x{52C7}\x{52C9}\x{52CA}\x{52CB}\x{52CD}\x{52CF}\x{52D0}' . + '\x{52D2}\x{52D3}\x{52D5}\x{52D6}\x{52D7}\x{52D8}\x{52D9}\x{52DA}\x{52DB}' . + '\x{52DC}\x{52DD}\x{52DE}\x{52DF}\x{52E0}\x{52E2}\x{52E3}\x{52E4}\x{52E6}' . + '\x{52E7}\x{52E8}\x{52E9}\x{52EA}\x{52EB}\x{52EC}\x{52ED}\x{52EF}\x{52F0}' . + '\x{52F1}\x{52F2}\x{52F3}\x{52F4}\x{52F5}\x{52F6}\x{52F7}\x{52F8}\x{52F9}' . + '\x{52FA}\x{52FB}\x{52FC}\x{52FD}\x{52FE}\x{52FF}\x{5300}\x{5301}\x{5302}' . + '\x{5305}\x{5306}\x{5307}\x{5308}\x{5309}\x{530A}\x{530B}\x{530C}\x{530D}' . + '\x{530E}\x{530F}\x{5310}\x{5311}\x{5312}\x{5313}\x{5314}\x{5315}\x{5316}' . + '\x{5317}\x{5319}\x{531A}\x{531C}\x{531D}\x{531F}\x{5320}\x{5321}\x{5322}' . + '\x{5323}\x{5324}\x{5325}\x{5326}\x{5328}\x{532A}\x{532B}\x{532C}\x{532D}' . + '\x{532E}\x{532F}\x{5330}\x{5331}\x{5333}\x{5334}\x{5337}\x{5339}\x{533A}' . + '\x{533B}\x{533C}\x{533D}\x{533E}\x{533F}\x{5340}\x{5341}\x{5343}\x{5344}' . + '\x{5345}\x{5346}\x{5347}\x{5348}\x{5349}\x{534A}\x{534B}\x{534C}\x{534D}' . + '\x{534E}\x{534F}\x{5350}\x{5351}\x{5352}\x{5353}\x{5354}\x{5355}\x{5356}' . + '\x{5357}\x{5358}\x{5359}\x{535A}\x{535C}\x{535E}\x{535F}\x{5360}\x{5361}' . + '\x{5362}\x{5363}\x{5364}\x{5365}\x{5366}\x{5367}\x{5369}\x{536B}\x{536C}' . + '\x{536E}\x{536F}\x{5370}\x{5371}\x{5372}\x{5373}\x{5374}\x{5375}\x{5376}' . + '\x{5377}\x{5378}\x{5379}\x{537A}\x{537B}\x{537C}\x{537D}\x{537E}\x{537F}' . + '\x{5381}\x{5382}\x{5383}\x{5384}\x{5385}\x{5386}\x{5387}\x{5388}\x{5389}' . + '\x{538A}\x{538B}\x{538C}\x{538D}\x{538E}\x{538F}\x{5390}\x{5391}\x{5392}' . + '\x{5393}\x{5394}\x{5395}\x{5396}\x{5397}\x{5398}\x{5399}\x{539A}\x{539B}' . + '\x{539C}\x{539D}\x{539E}\x{539F}\x{53A0}\x{53A2}\x{53A3}\x{53A4}\x{53A5}' . + '\x{53A6}\x{53A7}\x{53A8}\x{53A9}\x{53AC}\x{53AD}\x{53AE}\x{53B0}\x{53B1}' . + '\x{53B2}\x{53B3}\x{53B4}\x{53B5}\x{53B6}\x{53B7}\x{53B8}\x{53B9}\x{53BB}' . + '\x{53BC}\x{53BD}\x{53BE}\x{53BF}\x{53C0}\x{53C1}\x{53C2}\x{53C3}\x{53C4}' . + '\x{53C6}\x{53C7}\x{53C8}\x{53C9}\x{53CA}\x{53CB}\x{53CC}\x{53CD}\x{53CE}' . + '\x{53D0}\x{53D1}\x{53D2}\x{53D3}\x{53D4}\x{53D5}\x{53D6}\x{53D7}\x{53D8}' . + '\x{53D9}\x{53DB}\x{53DC}\x{53DF}\x{53E0}\x{53E1}\x{53E2}\x{53E3}\x{53E4}' . + '\x{53E5}\x{53E6}\x{53E8}\x{53E9}\x{53EA}\x{53EB}\x{53EC}\x{53ED}\x{53EE}' . + '\x{53EF}\x{53F0}\x{53F1}\x{53F2}\x{53F3}\x{53F4}\x{53F5}\x{53F6}\x{53F7}' . + '\x{53F8}\x{53F9}\x{53FA}\x{53FB}\x{53FC}\x{53FD}\x{53FE}\x{5401}\x{5402}' . + '\x{5403}\x{5404}\x{5405}\x{5406}\x{5407}\x{5408}\x{5409}\x{540A}\x{540B}' . + '\x{540C}\x{540D}\x{540E}\x{540F}\x{5410}\x{5411}\x{5412}\x{5413}\x{5414}' . + '\x{5415}\x{5416}\x{5417}\x{5418}\x{5419}\x{541B}\x{541C}\x{541D}\x{541E}' . + '\x{541F}\x{5420}\x{5421}\x{5423}\x{5424}\x{5425}\x{5426}\x{5427}\x{5428}' . + '\x{5429}\x{542A}\x{542B}\x{542C}\x{542D}\x{542E}\x{542F}\x{5430}\x{5431}' . + '\x{5432}\x{5433}\x{5434}\x{5435}\x{5436}\x{5437}\x{5438}\x{5439}\x{543A}' . + '\x{543B}\x{543C}\x{543D}\x{543E}\x{543F}\x{5440}\x{5441}\x{5442}\x{5443}' . + '\x{5444}\x{5445}\x{5446}\x{5447}\x{5448}\x{5449}\x{544A}\x{544B}\x{544D}' . + '\x{544E}\x{544F}\x{5450}\x{5451}\x{5452}\x{5453}\x{5454}\x{5455}\x{5456}' . + '\x{5457}\x{5458}\x{5459}\x{545A}\x{545B}\x{545C}\x{545E}\x{545F}\x{5460}' . + '\x{5461}\x{5462}\x{5463}\x{5464}\x{5465}\x{5466}\x{5467}\x{5468}\x{546A}' . + '\x{546B}\x{546C}\x{546D}\x{546E}\x{546F}\x{5470}\x{5471}\x{5472}\x{5473}' . + '\x{5474}\x{5475}\x{5476}\x{5477}\x{5478}\x{5479}\x{547A}\x{547B}\x{547C}' . + '\x{547D}\x{547E}\x{547F}\x{5480}\x{5481}\x{5482}\x{5483}\x{5484}\x{5485}' . + '\x{5486}\x{5487}\x{5488}\x{5489}\x{548B}\x{548C}\x{548D}\x{548E}\x{548F}' . + '\x{5490}\x{5491}\x{5492}\x{5493}\x{5494}\x{5495}\x{5496}\x{5497}\x{5498}' . + '\x{5499}\x{549A}\x{549B}\x{549C}\x{549D}\x{549E}\x{549F}\x{54A0}\x{54A1}' . + '\x{54A2}\x{54A3}\x{54A4}\x{54A5}\x{54A6}\x{54A7}\x{54A8}\x{54A9}\x{54AA}' . + '\x{54AB}\x{54AC}\x{54AD}\x{54AE}\x{54AF}\x{54B0}\x{54B1}\x{54B2}\x{54B3}' . + '\x{54B4}\x{54B6}\x{54B7}\x{54B8}\x{54B9}\x{54BA}\x{54BB}\x{54BC}\x{54BD}' . + '\x{54BE}\x{54BF}\x{54C0}\x{54C1}\x{54C2}\x{54C3}\x{54C4}\x{54C5}\x{54C6}' . + '\x{54C7}\x{54C8}\x{54C9}\x{54CA}\x{54CB}\x{54CC}\x{54CD}\x{54CE}\x{54CF}' . + '\x{54D0}\x{54D1}\x{54D2}\x{54D3}\x{54D4}\x{54D5}\x{54D6}\x{54D7}\x{54D8}' . + '\x{54D9}\x{54DA}\x{54DB}\x{54DC}\x{54DD}\x{54DE}\x{54DF}\x{54E0}\x{54E1}' . + '\x{54E2}\x{54E3}\x{54E4}\x{54E5}\x{54E6}\x{54E7}\x{54E8}\x{54E9}\x{54EA}' . + '\x{54EB}\x{54EC}\x{54ED}\x{54EE}\x{54EF}\x{54F0}\x{54F1}\x{54F2}\x{54F3}' . + '\x{54F4}\x{54F5}\x{54F7}\x{54F8}\x{54F9}\x{54FA}\x{54FB}\x{54FC}\x{54FD}' . + '\x{54FE}\x{54FF}\x{5500}\x{5501}\x{5502}\x{5503}\x{5504}\x{5505}\x{5506}' . + '\x{5507}\x{5508}\x{5509}\x{550A}\x{550B}\x{550C}\x{550D}\x{550E}\x{550F}' . + '\x{5510}\x{5511}\x{5512}\x{5513}\x{5514}\x{5516}\x{5517}\x{551A}\x{551B}' . + '\x{551C}\x{551D}\x{551E}\x{551F}\x{5520}\x{5521}\x{5522}\x{5523}\x{5524}' . + '\x{5525}\x{5526}\x{5527}\x{5528}\x{5529}\x{552A}\x{552B}\x{552C}\x{552D}' . + '\x{552E}\x{552F}\x{5530}\x{5531}\x{5532}\x{5533}\x{5534}\x{5535}\x{5536}' . + '\x{5537}\x{5538}\x{5539}\x{553A}\x{553B}\x{553C}\x{553D}\x{553E}\x{553F}' . + '\x{5540}\x{5541}\x{5542}\x{5543}\x{5544}\x{5545}\x{5546}\x{5548}\x{5549}' . + '\x{554A}\x{554B}\x{554C}\x{554D}\x{554E}\x{554F}\x{5550}\x{5551}\x{5552}' . + '\x{5553}\x{5554}\x{5555}\x{5556}\x{5557}\x{5558}\x{5559}\x{555A}\x{555B}' . + '\x{555C}\x{555D}\x{555E}\x{555F}\x{5561}\x{5562}\x{5563}\x{5564}\x{5565}' . + '\x{5566}\x{5567}\x{5568}\x{5569}\x{556A}\x{556B}\x{556C}\x{556D}\x{556E}' . + '\x{556F}\x{5570}\x{5571}\x{5572}\x{5573}\x{5574}\x{5575}\x{5576}\x{5577}' . + '\x{5578}\x{5579}\x{557B}\x{557C}\x{557D}\x{557E}\x{557F}\x{5580}\x{5581}' . + '\x{5582}\x{5583}\x{5584}\x{5585}\x{5586}\x{5587}\x{5588}\x{5589}\x{558A}' . + '\x{558B}\x{558C}\x{558D}\x{558E}\x{558F}\x{5590}\x{5591}\x{5592}\x{5593}' . + '\x{5594}\x{5595}\x{5596}\x{5597}\x{5598}\x{5599}\x{559A}\x{559B}\x{559C}' . + '\x{559D}\x{559E}\x{559F}\x{55A0}\x{55A1}\x{55A2}\x{55A3}\x{55A4}\x{55A5}' . + '\x{55A6}\x{55A7}\x{55A8}\x{55A9}\x{55AA}\x{55AB}\x{55AC}\x{55AD}\x{55AE}' . + '\x{55AF}\x{55B0}\x{55B1}\x{55B2}\x{55B3}\x{55B4}\x{55B5}\x{55B6}\x{55B7}' . + '\x{55B8}\x{55B9}\x{55BA}\x{55BB}\x{55BC}\x{55BD}\x{55BE}\x{55BF}\x{55C0}' . + '\x{55C1}\x{55C2}\x{55C3}\x{55C4}\x{55C5}\x{55C6}\x{55C7}\x{55C8}\x{55C9}' . + '\x{55CA}\x{55CB}\x{55CC}\x{55CD}\x{55CE}\x{55CF}\x{55D0}\x{55D1}\x{55D2}' . + '\x{55D3}\x{55D4}\x{55D5}\x{55D6}\x{55D7}\x{55D8}\x{55D9}\x{55DA}\x{55DB}' . + '\x{55DC}\x{55DD}\x{55DE}\x{55DF}\x{55E1}\x{55E2}\x{55E3}\x{55E4}\x{55E5}' . + '\x{55E6}\x{55E7}\x{55E8}\x{55E9}\x{55EA}\x{55EB}\x{55EC}\x{55ED}\x{55EE}' . + '\x{55EF}\x{55F0}\x{55F1}\x{55F2}\x{55F3}\x{55F4}\x{55F5}\x{55F6}\x{55F7}' . + '\x{55F9}\x{55FA}\x{55FB}\x{55FC}\x{55FD}\x{55FE}\x{55FF}\x{5600}\x{5601}' . + '\x{5602}\x{5603}\x{5604}\x{5606}\x{5607}\x{5608}\x{5609}\x{560C}\x{560D}' . + '\x{560E}\x{560F}\x{5610}\x{5611}\x{5612}\x{5613}\x{5614}\x{5615}\x{5616}' . + '\x{5617}\x{5618}\x{5619}\x{561A}\x{561B}\x{561C}\x{561D}\x{561E}\x{561F}' . + '\x{5621}\x{5622}\x{5623}\x{5624}\x{5625}\x{5626}\x{5627}\x{5628}\x{5629}' . + '\x{562A}\x{562C}\x{562D}\x{562E}\x{562F}\x{5630}\x{5631}\x{5632}\x{5633}' . + '\x{5634}\x{5635}\x{5636}\x{5638}\x{5639}\x{563A}\x{563B}\x{563D}\x{563E}' . + '\x{563F}\x{5640}\x{5641}\x{5642}\x{5643}\x{5645}\x{5646}\x{5647}\x{5648}' . + '\x{5649}\x{564A}\x{564C}\x{564D}\x{564E}\x{564F}\x{5650}\x{5652}\x{5653}' . + '\x{5654}\x{5655}\x{5657}\x{5658}\x{5659}\x{565A}\x{565B}\x{565C}\x{565D}' . + '\x{565E}\x{5660}\x{5662}\x{5663}\x{5664}\x{5665}\x{5666}\x{5667}\x{5668}' . + '\x{5669}\x{566A}\x{566B}\x{566C}\x{566D}\x{566E}\x{566F}\x{5670}\x{5671}' . + '\x{5672}\x{5673}\x{5674}\x{5676}\x{5677}\x{5678}\x{5679}\x{567A}\x{567B}' . + '\x{567C}\x{567E}\x{567F}\x{5680}\x{5681}\x{5682}\x{5683}\x{5684}\x{5685}' . + '\x{5686}\x{5687}\x{568A}\x{568C}\x{568D}\x{568E}\x{568F}\x{5690}\x{5691}' . + '\x{5692}\x{5693}\x{5694}\x{5695}\x{5697}\x{5698}\x{5699}\x{569A}\x{569B}' . + '\x{569C}\x{569D}\x{569F}\x{56A0}\x{56A1}\x{56A3}\x{56A4}\x{56A5}\x{56A6}' . + '\x{56A7}\x{56A8}\x{56A9}\x{56AA}\x{56AB}\x{56AC}\x{56AD}\x{56AE}\x{56AF}' . + '\x{56B0}\x{56B1}\x{56B2}\x{56B3}\x{56B4}\x{56B5}\x{56B6}\x{56B7}\x{56B8}' . + '\x{56B9}\x{56BB}\x{56BC}\x{56BD}\x{56BE}\x{56BF}\x{56C0}\x{56C1}\x{56C2}' . + '\x{56C3}\x{56C4}\x{56C5}\x{56C6}\x{56C7}\x{56C8}\x{56C9}\x{56CA}\x{56CB}' . + '\x{56CC}\x{56CD}\x{56CE}\x{56D0}\x{56D1}\x{56D2}\x{56D3}\x{56D4}\x{56D5}' . + '\x{56D6}\x{56D7}\x{56D8}\x{56DA}\x{56DB}\x{56DC}\x{56DD}\x{56DE}\x{56DF}' . + '\x{56E0}\x{56E1}\x{56E2}\x{56E3}\x{56E4}\x{56E5}\x{56E7}\x{56E8}\x{56E9}' . + '\x{56EA}\x{56EB}\x{56EC}\x{56ED}\x{56EE}\x{56EF}\x{56F0}\x{56F1}\x{56F2}' . + '\x{56F3}\x{56F4}\x{56F5}\x{56F7}\x{56F9}\x{56FA}\x{56FD}\x{56FE}\x{56FF}' . + '\x{5700}\x{5701}\x{5702}\x{5703}\x{5704}\x{5706}\x{5707}\x{5708}\x{5709}' . + '\x{570A}\x{570B}\x{570C}\x{570D}\x{570E}\x{570F}\x{5710}\x{5712}\x{5713}' . + '\x{5714}\x{5715}\x{5716}\x{5718}\x{5719}\x{571A}\x{571B}\x{571C}\x{571D}' . + '\x{571E}\x{571F}\x{5720}\x{5722}\x{5723}\x{5725}\x{5726}\x{5727}\x{5728}' . + '\x{5729}\x{572A}\x{572B}\x{572C}\x{572D}\x{572E}\x{572F}\x{5730}\x{5731}' . + '\x{5732}\x{5733}\x{5734}\x{5735}\x{5736}\x{5737}\x{5738}\x{5739}\x{573A}' . + '\x{573B}\x{573C}\x{573E}\x{573F}\x{5740}\x{5741}\x{5742}\x{5744}\x{5745}' . + '\x{5746}\x{5747}\x{5749}\x{574A}\x{574B}\x{574C}\x{574D}\x{574E}\x{574F}' . + '\x{5750}\x{5751}\x{5752}\x{5753}\x{5754}\x{5757}\x{5759}\x{575A}\x{575B}' . + '\x{575C}\x{575D}\x{575E}\x{575F}\x{5760}\x{5761}\x{5762}\x{5764}\x{5765}' . + '\x{5766}\x{5767}\x{5768}\x{5769}\x{576A}\x{576B}\x{576C}\x{576D}\x{576F}' . + '\x{5770}\x{5771}\x{5772}\x{5773}\x{5774}\x{5775}\x{5776}\x{5777}\x{5779}' . + '\x{577A}\x{577B}\x{577C}\x{577D}\x{577E}\x{577F}\x{5780}\x{5782}\x{5783}' . + '\x{5784}\x{5785}\x{5786}\x{5788}\x{5789}\x{578A}\x{578B}\x{578C}\x{578D}' . + '\x{578E}\x{578F}\x{5790}\x{5791}\x{5792}\x{5793}\x{5794}\x{5795}\x{5797}' . + '\x{5798}\x{5799}\x{579A}\x{579B}\x{579C}\x{579D}\x{579E}\x{579F}\x{57A0}' . + '\x{57A1}\x{57A2}\x{57A3}\x{57A4}\x{57A5}\x{57A6}\x{57A7}\x{57A9}\x{57AA}' . + '\x{57AB}\x{57AC}\x{57AD}\x{57AE}\x{57AF}\x{57B0}\x{57B1}\x{57B2}\x{57B3}' . + '\x{57B4}\x{57B5}\x{57B6}\x{57B7}\x{57B8}\x{57B9}\x{57BA}\x{57BB}\x{57BC}' . + '\x{57BD}\x{57BE}\x{57BF}\x{57C0}\x{57C1}\x{57C2}\x{57C3}\x{57C4}\x{57C5}' . + '\x{57C6}\x{57C7}\x{57C8}\x{57C9}\x{57CB}\x{57CC}\x{57CD}\x{57CE}\x{57CF}' . + '\x{57D0}\x{57D2}\x{57D3}\x{57D4}\x{57D5}\x{57D6}\x{57D8}\x{57D9}\x{57DA}' . + '\x{57DC}\x{57DD}\x{57DF}\x{57E0}\x{57E1}\x{57E2}\x{57E3}\x{57E4}\x{57E5}' . + '\x{57E6}\x{57E7}\x{57E8}\x{57E9}\x{57EA}\x{57EB}\x{57EC}\x{57ED}\x{57EE}' . + '\x{57EF}\x{57F0}\x{57F1}\x{57F2}\x{57F3}\x{57F4}\x{57F5}\x{57F6}\x{57F7}' . + '\x{57F8}\x{57F9}\x{57FA}\x{57FB}\x{57FC}\x{57FD}\x{57FE}\x{57FF}\x{5800}' . + '\x{5801}\x{5802}\x{5803}\x{5804}\x{5805}\x{5806}\x{5807}\x{5808}\x{5809}' . + '\x{580A}\x{580B}\x{580C}\x{580D}\x{580E}\x{580F}\x{5810}\x{5811}\x{5812}' . + '\x{5813}\x{5814}\x{5815}\x{5816}\x{5819}\x{581A}\x{581B}\x{581C}\x{581D}' . + '\x{581E}\x{581F}\x{5820}\x{5821}\x{5822}\x{5823}\x{5824}\x{5825}\x{5826}' . + '\x{5827}\x{5828}\x{5829}\x{582A}\x{582B}\x{582C}\x{582D}\x{582E}\x{582F}' . + '\x{5830}\x{5831}\x{5832}\x{5833}\x{5834}\x{5835}\x{5836}\x{5837}\x{5838}' . + '\x{5839}\x{583A}\x{583B}\x{583C}\x{583D}\x{583E}\x{583F}\x{5840}\x{5842}' . + '\x{5843}\x{5844}\x{5845}\x{5846}\x{5847}\x{5848}\x{5849}\x{584A}\x{584B}' . + '\x{584C}\x{584D}\x{584E}\x{584F}\x{5851}\x{5852}\x{5853}\x{5854}\x{5855}' . + '\x{5857}\x{5858}\x{5859}\x{585A}\x{585B}\x{585C}\x{585D}\x{585E}\x{585F}' . + '\x{5861}\x{5862}\x{5863}\x{5864}\x{5865}\x{5868}\x{5869}\x{586A}\x{586B}' . + '\x{586C}\x{586D}\x{586E}\x{586F}\x{5870}\x{5871}\x{5872}\x{5873}\x{5874}' . + '\x{5875}\x{5876}\x{5878}\x{5879}\x{587A}\x{587B}\x{587C}\x{587D}\x{587E}' . + '\x{587F}\x{5880}\x{5881}\x{5882}\x{5883}\x{5884}\x{5885}\x{5886}\x{5887}' . + '\x{5888}\x{5889}\x{588A}\x{588B}\x{588C}\x{588D}\x{588E}\x{588F}\x{5890}' . + '\x{5891}\x{5892}\x{5893}\x{5894}\x{5896}\x{5897}\x{5898}\x{5899}\x{589A}' . + '\x{589B}\x{589C}\x{589D}\x{589E}\x{589F}\x{58A0}\x{58A1}\x{58A2}\x{58A3}' . + '\x{58A4}\x{58A5}\x{58A6}\x{58A7}\x{58A8}\x{58A9}\x{58AB}\x{58AC}\x{58AD}' . + '\x{58AE}\x{58AF}\x{58B0}\x{58B1}\x{58B2}\x{58B3}\x{58B4}\x{58B7}\x{58B8}' . + '\x{58B9}\x{58BA}\x{58BB}\x{58BC}\x{58BD}\x{58BE}\x{58BF}\x{58C1}\x{58C2}' . + '\x{58C5}\x{58C6}\x{58C7}\x{58C8}\x{58C9}\x{58CA}\x{58CB}\x{58CE}\x{58CF}' . + '\x{58D1}\x{58D2}\x{58D3}\x{58D4}\x{58D5}\x{58D6}\x{58D7}\x{58D8}\x{58D9}' . + '\x{58DA}\x{58DB}\x{58DD}\x{58DE}\x{58DF}\x{58E0}\x{58E2}\x{58E3}\x{58E4}' . + '\x{58E5}\x{58E7}\x{58E8}\x{58E9}\x{58EA}\x{58EB}\x{58EC}\x{58ED}\x{58EE}' . + '\x{58EF}\x{58F0}\x{58F1}\x{58F2}\x{58F3}\x{58F4}\x{58F6}\x{58F7}\x{58F8}' . + '\x{58F9}\x{58FA}\x{58FB}\x{58FC}\x{58FD}\x{58FE}\x{58FF}\x{5900}\x{5902}' . + '\x{5903}\x{5904}\x{5906}\x{5907}\x{5909}\x{590A}\x{590B}\x{590C}\x{590D}' . + '\x{590E}\x{590F}\x{5910}\x{5912}\x{5914}\x{5915}\x{5916}\x{5917}\x{5918}' . + '\x{5919}\x{591A}\x{591B}\x{591C}\x{591D}\x{591E}\x{591F}\x{5920}\x{5921}' . + '\x{5922}\x{5924}\x{5925}\x{5926}\x{5927}\x{5928}\x{5929}\x{592A}\x{592B}' . + '\x{592C}\x{592D}\x{592E}\x{592F}\x{5930}\x{5931}\x{5932}\x{5934}\x{5935}' . + '\x{5937}\x{5938}\x{5939}\x{593A}\x{593B}\x{593C}\x{593D}\x{593E}\x{593F}' . + '\x{5940}\x{5941}\x{5942}\x{5943}\x{5944}\x{5945}\x{5946}\x{5947}\x{5948}' . + '\x{5949}\x{594A}\x{594B}\x{594C}\x{594D}\x{594E}\x{594F}\x{5950}\x{5951}' . + '\x{5952}\x{5953}\x{5954}\x{5955}\x{5956}\x{5957}\x{5958}\x{595A}\x{595C}' . + '\x{595D}\x{595E}\x{595F}\x{5960}\x{5961}\x{5962}\x{5963}\x{5964}\x{5965}' . + '\x{5966}\x{5967}\x{5968}\x{5969}\x{596A}\x{596B}\x{596C}\x{596D}\x{596E}' . + '\x{596F}\x{5970}\x{5971}\x{5972}\x{5973}\x{5974}\x{5975}\x{5976}\x{5977}' . + '\x{5978}\x{5979}\x{597A}\x{597B}\x{597C}\x{597D}\x{597E}\x{597F}\x{5980}' . + '\x{5981}\x{5982}\x{5983}\x{5984}\x{5985}\x{5986}\x{5987}\x{5988}\x{5989}' . + '\x{598A}\x{598B}\x{598C}\x{598D}\x{598E}\x{598F}\x{5990}\x{5991}\x{5992}' . + '\x{5993}\x{5994}\x{5995}\x{5996}\x{5997}\x{5998}\x{5999}\x{599A}\x{599C}' . + '\x{599D}\x{599E}\x{599F}\x{59A0}\x{59A1}\x{59A2}\x{59A3}\x{59A4}\x{59A5}' . + '\x{59A6}\x{59A7}\x{59A8}\x{59A9}\x{59AA}\x{59AB}\x{59AC}\x{59AD}\x{59AE}' . + '\x{59AF}\x{59B0}\x{59B1}\x{59B2}\x{59B3}\x{59B4}\x{59B5}\x{59B6}\x{59B8}' . + '\x{59B9}\x{59BA}\x{59BB}\x{59BC}\x{59BD}\x{59BE}\x{59BF}\x{59C0}\x{59C1}' . + '\x{59C2}\x{59C3}\x{59C4}\x{59C5}\x{59C6}\x{59C7}\x{59C8}\x{59C9}\x{59CA}' . + '\x{59CB}\x{59CC}\x{59CD}\x{59CE}\x{59CF}\x{59D0}\x{59D1}\x{59D2}\x{59D3}' . + '\x{59D4}\x{59D5}\x{59D6}\x{59D7}\x{59D8}\x{59D9}\x{59DA}\x{59DB}\x{59DC}' . + '\x{59DD}\x{59DE}\x{59DF}\x{59E0}\x{59E1}\x{59E2}\x{59E3}\x{59E4}\x{59E5}' . + '\x{59E6}\x{59E8}\x{59E9}\x{59EA}\x{59EB}\x{59EC}\x{59ED}\x{59EE}\x{59EF}' . + '\x{59F0}\x{59F1}\x{59F2}\x{59F3}\x{59F4}\x{59F5}\x{59F6}\x{59F7}\x{59F8}' . + '\x{59F9}\x{59FA}\x{59FB}\x{59FC}\x{59FD}\x{59FE}\x{59FF}\x{5A00}\x{5A01}' . + '\x{5A02}\x{5A03}\x{5A04}\x{5A05}\x{5A06}\x{5A07}\x{5A08}\x{5A09}\x{5A0A}' . + '\x{5A0B}\x{5A0C}\x{5A0D}\x{5A0E}\x{5A0F}\x{5A10}\x{5A11}\x{5A12}\x{5A13}' . + '\x{5A14}\x{5A15}\x{5A16}\x{5A17}\x{5A18}\x{5A19}\x{5A1A}\x{5A1B}\x{5A1C}' . + '\x{5A1D}\x{5A1E}\x{5A1F}\x{5A20}\x{5A21}\x{5A22}\x{5A23}\x{5A25}\x{5A27}' . + '\x{5A28}\x{5A29}\x{5A2A}\x{5A2B}\x{5A2D}\x{5A2E}\x{5A2F}\x{5A31}\x{5A32}' . + '\x{5A33}\x{5A34}\x{5A35}\x{5A36}\x{5A37}\x{5A38}\x{5A39}\x{5A3A}\x{5A3B}' . + '\x{5A3C}\x{5A3D}\x{5A3E}\x{5A3F}\x{5A40}\x{5A41}\x{5A42}\x{5A43}\x{5A44}' . + '\x{5A45}\x{5A46}\x{5A47}\x{5A48}\x{5A49}\x{5A4A}\x{5A4B}\x{5A4C}\x{5A4D}' . + '\x{5A4E}\x{5A4F}\x{5A50}\x{5A51}\x{5A52}\x{5A53}\x{5A55}\x{5A56}\x{5A57}' . + '\x{5A58}\x{5A5A}\x{5A5B}\x{5A5C}\x{5A5D}\x{5A5E}\x{5A5F}\x{5A60}\x{5A61}' . + '\x{5A62}\x{5A63}\x{5A64}\x{5A65}\x{5A66}\x{5A67}\x{5A68}\x{5A69}\x{5A6A}' . + '\x{5A6B}\x{5A6C}\x{5A6D}\x{5A6E}\x{5A70}\x{5A72}\x{5A73}\x{5A74}\x{5A75}' . + '\x{5A76}\x{5A77}\x{5A78}\x{5A79}\x{5A7A}\x{5A7B}\x{5A7C}\x{5A7D}\x{5A7E}' . + '\x{5A7F}\x{5A80}\x{5A81}\x{5A82}\x{5A83}\x{5A84}\x{5A85}\x{5A86}\x{5A88}' . + '\x{5A89}\x{5A8A}\x{5A8B}\x{5A8C}\x{5A8E}\x{5A8F}\x{5A90}\x{5A91}\x{5A92}' . + '\x{5A93}\x{5A94}\x{5A95}\x{5A96}\x{5A97}\x{5A98}\x{5A99}\x{5A9A}\x{5A9B}' . + '\x{5A9C}\x{5A9D}\x{5A9E}\x{5A9F}\x{5AA0}\x{5AA1}\x{5AA2}\x{5AA3}\x{5AA4}' . + '\x{5AA5}\x{5AA6}\x{5AA7}\x{5AA8}\x{5AA9}\x{5AAA}\x{5AAC}\x{5AAD}\x{5AAE}' . + '\x{5AAF}\x{5AB0}\x{5AB1}\x{5AB2}\x{5AB3}\x{5AB4}\x{5AB5}\x{5AB6}\x{5AB7}' . + '\x{5AB8}\x{5AB9}\x{5ABA}\x{5ABB}\x{5ABC}\x{5ABD}\x{5ABE}\x{5ABF}\x{5AC0}' . + '\x{5AC1}\x{5AC2}\x{5AC3}\x{5AC4}\x{5AC5}\x{5AC6}\x{5AC7}\x{5AC8}\x{5AC9}' . + '\x{5ACA}\x{5ACB}\x{5ACC}\x{5ACD}\x{5ACE}\x{5ACF}\x{5AD1}\x{5AD2}\x{5AD4}' . + '\x{5AD5}\x{5AD6}\x{5AD7}\x{5AD8}\x{5AD9}\x{5ADA}\x{5ADB}\x{5ADC}\x{5ADD}' . + '\x{5ADE}\x{5ADF}\x{5AE0}\x{5AE1}\x{5AE2}\x{5AE3}\x{5AE4}\x{5AE5}\x{5AE6}' . + '\x{5AE7}\x{5AE8}\x{5AE9}\x{5AEA}\x{5AEB}\x{5AEC}\x{5AED}\x{5AEE}\x{5AF1}' . + '\x{5AF2}\x{5AF3}\x{5AF4}\x{5AF5}\x{5AF6}\x{5AF7}\x{5AF8}\x{5AF9}\x{5AFA}' . + '\x{5AFB}\x{5AFC}\x{5AFD}\x{5AFE}\x{5AFF}\x{5B00}\x{5B01}\x{5B02}\x{5B03}' . + '\x{5B04}\x{5B05}\x{5B06}\x{5B07}\x{5B08}\x{5B09}\x{5B0B}\x{5B0C}\x{5B0E}' . + '\x{5B0F}\x{5B10}\x{5B11}\x{5B12}\x{5B13}\x{5B14}\x{5B15}\x{5B16}\x{5B17}' . + '\x{5B18}\x{5B19}\x{5B1A}\x{5B1B}\x{5B1C}\x{5B1D}\x{5B1E}\x{5B1F}\x{5B20}' . + '\x{5B21}\x{5B22}\x{5B23}\x{5B24}\x{5B25}\x{5B26}\x{5B27}\x{5B28}\x{5B29}' . + '\x{5B2A}\x{5B2B}\x{5B2C}\x{5B2D}\x{5B2E}\x{5B2F}\x{5B30}\x{5B31}\x{5B32}' . + '\x{5B33}\x{5B34}\x{5B35}\x{5B36}\x{5B37}\x{5B38}\x{5B3A}\x{5B3B}\x{5B3C}' . + '\x{5B3D}\x{5B3E}\x{5B3F}\x{5B40}\x{5B41}\x{5B42}\x{5B43}\x{5B44}\x{5B45}' . + '\x{5B47}\x{5B48}\x{5B49}\x{5B4A}\x{5B4B}\x{5B4C}\x{5B4D}\x{5B4E}\x{5B50}' . + '\x{5B51}\x{5B53}\x{5B54}\x{5B55}\x{5B56}\x{5B57}\x{5B58}\x{5B59}\x{5B5A}' . + '\x{5B5B}\x{5B5C}\x{5B5D}\x{5B5E}\x{5B5F}\x{5B62}\x{5B63}\x{5B64}\x{5B65}' . + '\x{5B66}\x{5B67}\x{5B68}\x{5B69}\x{5B6A}\x{5B6B}\x{5B6C}\x{5B6D}\x{5B6E}' . + '\x{5B70}\x{5B71}\x{5B72}\x{5B73}\x{5B74}\x{5B75}\x{5B76}\x{5B77}\x{5B78}' . + '\x{5B7A}\x{5B7B}\x{5B7C}\x{5B7D}\x{5B7F}\x{5B80}\x{5B81}\x{5B82}\x{5B83}' . + '\x{5B84}\x{5B85}\x{5B87}\x{5B88}\x{5B89}\x{5B8A}\x{5B8B}\x{5B8C}\x{5B8D}' . + '\x{5B8E}\x{5B8F}\x{5B91}\x{5B92}\x{5B93}\x{5B94}\x{5B95}\x{5B96}\x{5B97}' . + '\x{5B98}\x{5B99}\x{5B9A}\x{5B9B}\x{5B9C}\x{5B9D}\x{5B9E}\x{5B9F}\x{5BA0}' . + '\x{5BA1}\x{5BA2}\x{5BA3}\x{5BA4}\x{5BA5}\x{5BA6}\x{5BA7}\x{5BA8}\x{5BAA}' . + '\x{5BAB}\x{5BAC}\x{5BAD}\x{5BAE}\x{5BAF}\x{5BB0}\x{5BB1}\x{5BB3}\x{5BB4}' . + '\x{5BB5}\x{5BB6}\x{5BB8}\x{5BB9}\x{5BBA}\x{5BBB}\x{5BBD}\x{5BBE}\x{5BBF}' . + '\x{5BC0}\x{5BC1}\x{5BC2}\x{5BC3}\x{5BC4}\x{5BC5}\x{5BC6}\x{5BC7}\x{5BCA}' . + '\x{5BCB}\x{5BCC}\x{5BCD}\x{5BCE}\x{5BCF}\x{5BD0}\x{5BD1}\x{5BD2}\x{5BD3}' . + '\x{5BD4}\x{5BD5}\x{5BD6}\x{5BD8}\x{5BD9}\x{5BDB}\x{5BDC}\x{5BDD}\x{5BDE}' . + '\x{5BDF}\x{5BE0}\x{5BE1}\x{5BE2}\x{5BE3}\x{5BE4}\x{5BE5}\x{5BE6}\x{5BE7}' . + '\x{5BE8}\x{5BE9}\x{5BEA}\x{5BEB}\x{5BEC}\x{5BED}\x{5BEE}\x{5BEF}\x{5BF0}' . + '\x{5BF1}\x{5BF2}\x{5BF3}\x{5BF4}\x{5BF5}\x{5BF6}\x{5BF7}\x{5BF8}\x{5BF9}' . + '\x{5BFA}\x{5BFB}\x{5BFC}\x{5BFD}\x{5BFF}\x{5C01}\x{5C03}\x{5C04}\x{5C05}' . + '\x{5C06}\x{5C07}\x{5C08}\x{5C09}\x{5C0A}\x{5C0B}\x{5C0C}\x{5C0D}\x{5C0E}' . + '\x{5C0F}\x{5C10}\x{5C11}\x{5C12}\x{5C13}\x{5C14}\x{5C15}\x{5C16}\x{5C17}' . + '\x{5C18}\x{5C19}\x{5C1A}\x{5C1C}\x{5C1D}\x{5C1E}\x{5C1F}\x{5C20}\x{5C21}' . + '\x{5C22}\x{5C24}\x{5C25}\x{5C27}\x{5C28}\x{5C2A}\x{5C2B}\x{5C2C}\x{5C2D}' . + '\x{5C2E}\x{5C2F}\x{5C30}\x{5C31}\x{5C32}\x{5C33}\x{5C34}\x{5C35}\x{5C37}' . + '\x{5C38}\x{5C39}\x{5C3A}\x{5C3B}\x{5C3C}\x{5C3D}\x{5C3E}\x{5C3F}\x{5C40}' . + '\x{5C41}\x{5C42}\x{5C43}\x{5C44}\x{5C45}\x{5C46}\x{5C47}\x{5C48}\x{5C49}' . + '\x{5C4A}\x{5C4B}\x{5C4C}\x{5C4D}\x{5C4E}\x{5C4F}\x{5C50}\x{5C51}\x{5C52}' . + '\x{5C53}\x{5C54}\x{5C55}\x{5C56}\x{5C57}\x{5C58}\x{5C59}\x{5C5B}\x{5C5C}' . + '\x{5C5D}\x{5C5E}\x{5C5F}\x{5C60}\x{5C61}\x{5C62}\x{5C63}\x{5C64}\x{5C65}' . + '\x{5C66}\x{5C67}\x{5C68}\x{5C69}\x{5C6A}\x{5C6B}\x{5C6C}\x{5C6D}\x{5C6E}' . + '\x{5C6F}\x{5C70}\x{5C71}\x{5C72}\x{5C73}\x{5C74}\x{5C75}\x{5C76}\x{5C77}' . + '\x{5C78}\x{5C79}\x{5C7A}\x{5C7B}\x{5C7C}\x{5C7D}\x{5C7E}\x{5C7F}\x{5C80}' . + '\x{5C81}\x{5C82}\x{5C83}\x{5C84}\x{5C86}\x{5C87}\x{5C88}\x{5C89}\x{5C8A}' . + '\x{5C8B}\x{5C8C}\x{5C8D}\x{5C8E}\x{5C8F}\x{5C90}\x{5C91}\x{5C92}\x{5C93}' . + '\x{5C94}\x{5C95}\x{5C96}\x{5C97}\x{5C98}\x{5C99}\x{5C9A}\x{5C9B}\x{5C9C}' . + '\x{5C9D}\x{5C9E}\x{5C9F}\x{5CA0}\x{5CA1}\x{5CA2}\x{5CA3}\x{5CA4}\x{5CA5}' . + '\x{5CA6}\x{5CA7}\x{5CA8}\x{5CA9}\x{5CAA}\x{5CAB}\x{5CAC}\x{5CAD}\x{5CAE}' . + '\x{5CAF}\x{5CB0}\x{5CB1}\x{5CB2}\x{5CB3}\x{5CB5}\x{5CB6}\x{5CB7}\x{5CB8}' . + '\x{5CBA}\x{5CBB}\x{5CBC}\x{5CBD}\x{5CBE}\x{5CBF}\x{5CC1}\x{5CC2}\x{5CC3}' . + '\x{5CC4}\x{5CC5}\x{5CC6}\x{5CC7}\x{5CC8}\x{5CC9}\x{5CCA}\x{5CCB}\x{5CCC}' . + '\x{5CCD}\x{5CCE}\x{5CCF}\x{5CD0}\x{5CD1}\x{5CD2}\x{5CD3}\x{5CD4}\x{5CD6}' . + '\x{5CD7}\x{5CD8}\x{5CD9}\x{5CDA}\x{5CDB}\x{5CDC}\x{5CDE}\x{5CDF}\x{5CE0}' . + '\x{5CE1}\x{5CE2}\x{5CE3}\x{5CE4}\x{5CE5}\x{5CE6}\x{5CE7}\x{5CE8}\x{5CE9}' . + '\x{5CEA}\x{5CEB}\x{5CEC}\x{5CED}\x{5CEE}\x{5CEF}\x{5CF0}\x{5CF1}\x{5CF2}' . + '\x{5CF3}\x{5CF4}\x{5CF6}\x{5CF7}\x{5CF8}\x{5CF9}\x{5CFA}\x{5CFB}\x{5CFC}' . + '\x{5CFD}\x{5CFE}\x{5CFF}\x{5D00}\x{5D01}\x{5D02}\x{5D03}\x{5D04}\x{5D05}' . + '\x{5D06}\x{5D07}\x{5D08}\x{5D09}\x{5D0A}\x{5D0B}\x{5D0C}\x{5D0D}\x{5D0E}' . + '\x{5D0F}\x{5D10}\x{5D11}\x{5D12}\x{5D13}\x{5D14}\x{5D15}\x{5D16}\x{5D17}' . + '\x{5D18}\x{5D19}\x{5D1A}\x{5D1B}\x{5D1C}\x{5D1D}\x{5D1E}\x{5D1F}\x{5D20}' . + '\x{5D21}\x{5D22}\x{5D23}\x{5D24}\x{5D25}\x{5D26}\x{5D27}\x{5D28}\x{5D29}' . + '\x{5D2A}\x{5D2C}\x{5D2D}\x{5D2E}\x{5D30}\x{5D31}\x{5D32}\x{5D33}\x{5D34}' . + '\x{5D35}\x{5D36}\x{5D37}\x{5D38}\x{5D39}\x{5D3A}\x{5D3C}\x{5D3D}\x{5D3E}' . + '\x{5D3F}\x{5D40}\x{5D41}\x{5D42}\x{5D43}\x{5D44}\x{5D45}\x{5D46}\x{5D47}' . + '\x{5D48}\x{5D49}\x{5D4A}\x{5D4B}\x{5D4C}\x{5D4D}\x{5D4E}\x{5D4F}\x{5D50}' . + '\x{5D51}\x{5D52}\x{5D54}\x{5D55}\x{5D56}\x{5D58}\x{5D59}\x{5D5A}\x{5D5B}' . + '\x{5D5D}\x{5D5E}\x{5D5F}\x{5D61}\x{5D62}\x{5D63}\x{5D64}\x{5D65}\x{5D66}' . + '\x{5D67}\x{5D68}\x{5D69}\x{5D6A}\x{5D6B}\x{5D6C}\x{5D6D}\x{5D6E}\x{5D6F}' . + '\x{5D70}\x{5D71}\x{5D72}\x{5D73}\x{5D74}\x{5D75}\x{5D76}\x{5D77}\x{5D78}' . + '\x{5D79}\x{5D7A}\x{5D7B}\x{5D7C}\x{5D7D}\x{5D7E}\x{5D7F}\x{5D80}\x{5D81}' . + '\x{5D82}\x{5D84}\x{5D85}\x{5D86}\x{5D87}\x{5D88}\x{5D89}\x{5D8A}\x{5D8B}' . + '\x{5D8C}\x{5D8D}\x{5D8E}\x{5D8F}\x{5D90}\x{5D91}\x{5D92}\x{5D93}\x{5D94}' . + '\x{5D95}\x{5D97}\x{5D98}\x{5D99}\x{5D9A}\x{5D9B}\x{5D9C}\x{5D9D}\x{5D9E}' . + '\x{5D9F}\x{5DA0}\x{5DA1}\x{5DA2}\x{5DA5}\x{5DA6}\x{5DA7}\x{5DA8}\x{5DA9}' . + '\x{5DAA}\x{5DAC}\x{5DAD}\x{5DAE}\x{5DAF}\x{5DB0}\x{5DB1}\x{5DB2}\x{5DB4}' . + '\x{5DB5}\x{5DB6}\x{5DB7}\x{5DB8}\x{5DBA}\x{5DBB}\x{5DBC}\x{5DBD}\x{5DBE}' . + '\x{5DBF}\x{5DC0}\x{5DC1}\x{5DC2}\x{5DC3}\x{5DC5}\x{5DC6}\x{5DC7}\x{5DC8}' . + '\x{5DC9}\x{5DCA}\x{5DCB}\x{5DCC}\x{5DCD}\x{5DCE}\x{5DCF}\x{5DD0}\x{5DD1}' . + '\x{5DD2}\x{5DD3}\x{5DD4}\x{5DD5}\x{5DD6}\x{5DD8}\x{5DD9}\x{5DDB}\x{5DDD}' . + '\x{5DDE}\x{5DDF}\x{5DE0}\x{5DE1}\x{5DE2}\x{5DE3}\x{5DE4}\x{5DE5}\x{5DE6}' . + '\x{5DE7}\x{5DE8}\x{5DE9}\x{5DEA}\x{5DEB}\x{5DEC}\x{5DED}\x{5DEE}\x{5DEF}' . + '\x{5DF0}\x{5DF1}\x{5DF2}\x{5DF3}\x{5DF4}\x{5DF5}\x{5DF7}\x{5DF8}\x{5DF9}' . + '\x{5DFA}\x{5DFB}\x{5DFC}\x{5DFD}\x{5DFE}\x{5DFF}\x{5E00}\x{5E01}\x{5E02}' . + '\x{5E03}\x{5E04}\x{5E05}\x{5E06}\x{5E07}\x{5E08}\x{5E09}\x{5E0A}\x{5E0B}' . + '\x{5E0C}\x{5E0D}\x{5E0E}\x{5E0F}\x{5E10}\x{5E11}\x{5E13}\x{5E14}\x{5E15}' . + '\x{5E16}\x{5E17}\x{5E18}\x{5E19}\x{5E1A}\x{5E1B}\x{5E1C}\x{5E1D}\x{5E1E}' . + '\x{5E1F}\x{5E20}\x{5E21}\x{5E22}\x{5E23}\x{5E24}\x{5E25}\x{5E26}\x{5E27}' . + '\x{5E28}\x{5E29}\x{5E2A}\x{5E2B}\x{5E2C}\x{5E2D}\x{5E2E}\x{5E2F}\x{5E30}' . + '\x{5E31}\x{5E32}\x{5E33}\x{5E34}\x{5E35}\x{5E36}\x{5E37}\x{5E38}\x{5E39}' . + '\x{5E3A}\x{5E3B}\x{5E3C}\x{5E3D}\x{5E3E}\x{5E40}\x{5E41}\x{5E42}\x{5E43}' . + '\x{5E44}\x{5E45}\x{5E46}\x{5E47}\x{5E49}\x{5E4A}\x{5E4B}\x{5E4C}\x{5E4D}' . + '\x{5E4E}\x{5E4F}\x{5E50}\x{5E52}\x{5E53}\x{5E54}\x{5E55}\x{5E56}\x{5E57}' . + '\x{5E58}\x{5E59}\x{5E5A}\x{5E5B}\x{5E5C}\x{5E5D}\x{5E5E}\x{5E5F}\x{5E60}' . + '\x{5E61}\x{5E62}\x{5E63}\x{5E64}\x{5E65}\x{5E66}\x{5E67}\x{5E68}\x{5E69}' . + '\x{5E6A}\x{5E6B}\x{5E6C}\x{5E6D}\x{5E6E}\x{5E6F}\x{5E70}\x{5E71}\x{5E72}' . + '\x{5E73}\x{5E74}\x{5E75}\x{5E76}\x{5E77}\x{5E78}\x{5E79}\x{5E7A}\x{5E7B}' . + '\x{5E7C}\x{5E7D}\x{5E7E}\x{5E7F}\x{5E80}\x{5E81}\x{5E82}\x{5E83}\x{5E84}' . + '\x{5E85}\x{5E86}\x{5E87}\x{5E88}\x{5E89}\x{5E8A}\x{5E8B}\x{5E8C}\x{5E8D}' . + '\x{5E8E}\x{5E8F}\x{5E90}\x{5E91}\x{5E93}\x{5E94}\x{5E95}\x{5E96}\x{5E97}' . + '\x{5E98}\x{5E99}\x{5E9A}\x{5E9B}\x{5E9C}\x{5E9D}\x{5E9E}\x{5E9F}\x{5EA0}' . + '\x{5EA1}\x{5EA2}\x{5EA3}\x{5EA4}\x{5EA5}\x{5EA6}\x{5EA7}\x{5EA8}\x{5EA9}' . + '\x{5EAA}\x{5EAB}\x{5EAC}\x{5EAD}\x{5EAE}\x{5EAF}\x{5EB0}\x{5EB1}\x{5EB2}' . + '\x{5EB3}\x{5EB4}\x{5EB5}\x{5EB6}\x{5EB7}\x{5EB8}\x{5EB9}\x{5EBB}\x{5EBC}' . + '\x{5EBD}\x{5EBE}\x{5EBF}\x{5EC1}\x{5EC2}\x{5EC3}\x{5EC4}\x{5EC5}\x{5EC6}' . + '\x{5EC7}\x{5EC8}\x{5EC9}\x{5ECA}\x{5ECB}\x{5ECC}\x{5ECD}\x{5ECE}\x{5ECF}' . + '\x{5ED0}\x{5ED1}\x{5ED2}\x{5ED3}\x{5ED4}\x{5ED5}\x{5ED6}\x{5ED7}\x{5ED8}' . + '\x{5ED9}\x{5EDA}\x{5EDB}\x{5EDC}\x{5EDD}\x{5EDE}\x{5EDF}\x{5EE0}\x{5EE1}' . + '\x{5EE2}\x{5EE3}\x{5EE4}\x{5EE5}\x{5EE6}\x{5EE7}\x{5EE8}\x{5EE9}\x{5EEA}' . + '\x{5EEC}\x{5EED}\x{5EEE}\x{5EEF}\x{5EF0}\x{5EF1}\x{5EF2}\x{5EF3}\x{5EF4}' . + '\x{5EF5}\x{5EF6}\x{5EF7}\x{5EF8}\x{5EFA}\x{5EFB}\x{5EFC}\x{5EFD}\x{5EFE}' . + '\x{5EFF}\x{5F00}\x{5F01}\x{5F02}\x{5F03}\x{5F04}\x{5F05}\x{5F06}\x{5F07}' . + '\x{5F08}\x{5F0A}\x{5F0B}\x{5F0C}\x{5F0D}\x{5F0F}\x{5F11}\x{5F12}\x{5F13}' . + '\x{5F14}\x{5F15}\x{5F16}\x{5F17}\x{5F18}\x{5F19}\x{5F1A}\x{5F1B}\x{5F1C}' . + '\x{5F1D}\x{5F1E}\x{5F1F}\x{5F20}\x{5F21}\x{5F22}\x{5F23}\x{5F24}\x{5F25}' . + '\x{5F26}\x{5F27}\x{5F28}\x{5F29}\x{5F2A}\x{5F2B}\x{5F2C}\x{5F2D}\x{5F2E}' . + '\x{5F2F}\x{5F30}\x{5F31}\x{5F32}\x{5F33}\x{5F34}\x{5F35}\x{5F36}\x{5F37}' . + '\x{5F38}\x{5F39}\x{5F3A}\x{5F3C}\x{5F3E}\x{5F3F}\x{5F40}\x{5F41}\x{5F42}' . + '\x{5F43}\x{5F44}\x{5F45}\x{5F46}\x{5F47}\x{5F48}\x{5F49}\x{5F4A}\x{5F4B}' . + '\x{5F4C}\x{5F4D}\x{5F4E}\x{5F4F}\x{5F50}\x{5F51}\x{5F52}\x{5F53}\x{5F54}' . + '\x{5F55}\x{5F56}\x{5F57}\x{5F58}\x{5F59}\x{5F5A}\x{5F5B}\x{5F5C}\x{5F5D}' . + '\x{5F5E}\x{5F5F}\x{5F60}\x{5F61}\x{5F62}\x{5F63}\x{5F64}\x{5F65}\x{5F66}' . + '\x{5F67}\x{5F68}\x{5F69}\x{5F6A}\x{5F6B}\x{5F6C}\x{5F6D}\x{5F6E}\x{5F6F}' . + '\x{5F70}\x{5F71}\x{5F72}\x{5F73}\x{5F74}\x{5F75}\x{5F76}\x{5F77}\x{5F78}' . + '\x{5F79}\x{5F7A}\x{5F7B}\x{5F7C}\x{5F7D}\x{5F7E}\x{5F7F}\x{5F80}\x{5F81}' . + '\x{5F82}\x{5F83}\x{5F84}\x{5F85}\x{5F86}\x{5F87}\x{5F88}\x{5F89}\x{5F8A}' . + '\x{5F8B}\x{5F8C}\x{5F8D}\x{5F8E}\x{5F90}\x{5F91}\x{5F92}\x{5F93}\x{5F94}' . + '\x{5F95}\x{5F96}\x{5F97}\x{5F98}\x{5F99}\x{5F9B}\x{5F9C}\x{5F9D}\x{5F9E}' . + '\x{5F9F}\x{5FA0}\x{5FA1}\x{5FA2}\x{5FA5}\x{5FA6}\x{5FA7}\x{5FA8}\x{5FA9}' . + '\x{5FAA}\x{5FAB}\x{5FAC}\x{5FAD}\x{5FAE}\x{5FAF}\x{5FB1}\x{5FB2}\x{5FB3}' . + '\x{5FB4}\x{5FB5}\x{5FB6}\x{5FB7}\x{5FB8}\x{5FB9}\x{5FBA}\x{5FBB}\x{5FBC}' . + '\x{5FBD}\x{5FBE}\x{5FBF}\x{5FC0}\x{5FC1}\x{5FC3}\x{5FC4}\x{5FC5}\x{5FC6}' . + '\x{5FC7}\x{5FC8}\x{5FC9}\x{5FCA}\x{5FCB}\x{5FCC}\x{5FCD}\x{5FCF}\x{5FD0}' . + '\x{5FD1}\x{5FD2}\x{5FD3}\x{5FD4}\x{5FD5}\x{5FD6}\x{5FD7}\x{5FD8}\x{5FD9}' . + '\x{5FDA}\x{5FDC}\x{5FDD}\x{5FDE}\x{5FE0}\x{5FE1}\x{5FE3}\x{5FE4}\x{5FE5}' . + '\x{5FE6}\x{5FE7}\x{5FE8}\x{5FE9}\x{5FEA}\x{5FEB}\x{5FED}\x{5FEE}\x{5FEF}' . + '\x{5FF0}\x{5FF1}\x{5FF2}\x{5FF3}\x{5FF4}\x{5FF5}\x{5FF6}\x{5FF7}\x{5FF8}' . + '\x{5FF9}\x{5FFA}\x{5FFB}\x{5FFD}\x{5FFE}\x{5FFF}\x{6000}\x{6001}\x{6002}' . + '\x{6003}\x{6004}\x{6005}\x{6006}\x{6007}\x{6008}\x{6009}\x{600A}\x{600B}' . + '\x{600C}\x{600D}\x{600E}\x{600F}\x{6010}\x{6011}\x{6012}\x{6013}\x{6014}' . + '\x{6015}\x{6016}\x{6017}\x{6018}\x{6019}\x{601A}\x{601B}\x{601C}\x{601D}' . + '\x{601E}\x{601F}\x{6020}\x{6021}\x{6022}\x{6024}\x{6025}\x{6026}\x{6027}' . + '\x{6028}\x{6029}\x{602A}\x{602B}\x{602C}\x{602D}\x{602E}\x{602F}\x{6030}' . + '\x{6031}\x{6032}\x{6033}\x{6034}\x{6035}\x{6036}\x{6037}\x{6038}\x{6039}' . + '\x{603A}\x{603B}\x{603C}\x{603D}\x{603E}\x{603F}\x{6040}\x{6041}\x{6042}' . + '\x{6043}\x{6044}\x{6045}\x{6046}\x{6047}\x{6048}\x{6049}\x{604A}\x{604B}' . + '\x{604C}\x{604D}\x{604E}\x{604F}\x{6050}\x{6051}\x{6052}\x{6053}\x{6054}' . + '\x{6055}\x{6057}\x{6058}\x{6059}\x{605A}\x{605B}\x{605C}\x{605D}\x{605E}' . + '\x{605F}\x{6062}\x{6063}\x{6064}\x{6065}\x{6066}\x{6067}\x{6068}\x{6069}' . + '\x{606A}\x{606B}\x{606C}\x{606D}\x{606E}\x{606F}\x{6070}\x{6072}\x{6073}' . + '\x{6075}\x{6076}\x{6077}\x{6078}\x{6079}\x{607A}\x{607B}\x{607C}\x{607D}' . + '\x{607E}\x{607F}\x{6080}\x{6081}\x{6082}\x{6083}\x{6084}\x{6085}\x{6086}' . + '\x{6087}\x{6088}\x{6089}\x{608A}\x{608B}\x{608C}\x{608D}\x{608E}\x{608F}' . + '\x{6090}\x{6092}\x{6094}\x{6095}\x{6096}\x{6097}\x{6098}\x{6099}\x{609A}' . + '\x{609B}\x{609C}\x{609D}\x{609E}\x{609F}\x{60A0}\x{60A1}\x{60A2}\x{60A3}' . + '\x{60A4}\x{60A6}\x{60A7}\x{60A8}\x{60AA}\x{60AB}\x{60AC}\x{60AD}\x{60AE}' . + '\x{60AF}\x{60B0}\x{60B1}\x{60B2}\x{60B3}\x{60B4}\x{60B5}\x{60B6}\x{60B7}' . + '\x{60B8}\x{60B9}\x{60BA}\x{60BB}\x{60BC}\x{60BD}\x{60BE}\x{60BF}\x{60C0}' . + '\x{60C1}\x{60C2}\x{60C3}\x{60C4}\x{60C5}\x{60C6}\x{60C7}\x{60C8}\x{60C9}' . + '\x{60CA}\x{60CB}\x{60CC}\x{60CD}\x{60CE}\x{60CF}\x{60D0}\x{60D1}\x{60D3}' . + '\x{60D4}\x{60D5}\x{60D7}\x{60D8}\x{60D9}\x{60DA}\x{60DB}\x{60DC}\x{60DD}' . + '\x{60DF}\x{60E0}\x{60E1}\x{60E2}\x{60E4}\x{60E6}\x{60E7}\x{60E8}\x{60E9}' . + '\x{60EA}\x{60EB}\x{60EC}\x{60ED}\x{60EE}\x{60EF}\x{60F0}\x{60F1}\x{60F2}' . + '\x{60F3}\x{60F4}\x{60F5}\x{60F6}\x{60F7}\x{60F8}\x{60F9}\x{60FA}\x{60FB}' . + '\x{60FC}\x{60FE}\x{60FF}\x{6100}\x{6101}\x{6103}\x{6104}\x{6105}\x{6106}' . + '\x{6108}\x{6109}\x{610A}\x{610B}\x{610C}\x{610D}\x{610E}\x{610F}\x{6110}' . + '\x{6112}\x{6113}\x{6114}\x{6115}\x{6116}\x{6117}\x{6118}\x{6119}\x{611A}' . + '\x{611B}\x{611C}\x{611D}\x{611F}\x{6120}\x{6122}\x{6123}\x{6124}\x{6125}' . + '\x{6126}\x{6127}\x{6128}\x{6129}\x{612A}\x{612B}\x{612C}\x{612D}\x{612E}' . + '\x{612F}\x{6130}\x{6132}\x{6134}\x{6136}\x{6137}\x{613A}\x{613B}\x{613C}' . + '\x{613D}\x{613E}\x{613F}\x{6140}\x{6141}\x{6142}\x{6143}\x{6144}\x{6145}' . + '\x{6146}\x{6147}\x{6148}\x{6149}\x{614A}\x{614B}\x{614C}\x{614D}\x{614E}' . + '\x{614F}\x{6150}\x{6151}\x{6152}\x{6153}\x{6154}\x{6155}\x{6156}\x{6157}' . + '\x{6158}\x{6159}\x{615A}\x{615B}\x{615C}\x{615D}\x{615E}\x{615F}\x{6161}' . + '\x{6162}\x{6163}\x{6164}\x{6165}\x{6166}\x{6167}\x{6168}\x{6169}\x{616A}' . + '\x{616B}\x{616C}\x{616D}\x{616E}\x{6170}\x{6171}\x{6172}\x{6173}\x{6174}' . + '\x{6175}\x{6176}\x{6177}\x{6178}\x{6179}\x{617A}\x{617C}\x{617E}\x{6180}' . + '\x{6181}\x{6182}\x{6183}\x{6184}\x{6185}\x{6187}\x{6188}\x{6189}\x{618A}' . + '\x{618B}\x{618C}\x{618D}\x{618E}\x{618F}\x{6190}\x{6191}\x{6192}\x{6193}' . + '\x{6194}\x{6195}\x{6196}\x{6198}\x{6199}\x{619A}\x{619B}\x{619D}\x{619E}' . + '\x{619F}\x{61A0}\x{61A1}\x{61A2}\x{61A3}\x{61A4}\x{61A5}\x{61A6}\x{61A7}' . + '\x{61A8}\x{61A9}\x{61AA}\x{61AB}\x{61AC}\x{61AD}\x{61AE}\x{61AF}\x{61B0}' . + '\x{61B1}\x{61B2}\x{61B3}\x{61B4}\x{61B5}\x{61B6}\x{61B7}\x{61B8}\x{61BA}' . + '\x{61BC}\x{61BD}\x{61BE}\x{61BF}\x{61C0}\x{61C1}\x{61C2}\x{61C3}\x{61C4}' . + '\x{61C5}\x{61C6}\x{61C7}\x{61C8}\x{61C9}\x{61CA}\x{61CB}\x{61CC}\x{61CD}' . + '\x{61CE}\x{61CF}\x{61D0}\x{61D1}\x{61D2}\x{61D4}\x{61D6}\x{61D7}\x{61D8}' . + '\x{61D9}\x{61DA}\x{61DB}\x{61DC}\x{61DD}\x{61DE}\x{61DF}\x{61E0}\x{61E1}' . + '\x{61E2}\x{61E3}\x{61E4}\x{61E5}\x{61E6}\x{61E7}\x{61E8}\x{61E9}\x{61EA}' . + '\x{61EB}\x{61ED}\x{61EE}\x{61F0}\x{61F1}\x{61F2}\x{61F3}\x{61F5}\x{61F6}' . + '\x{61F7}\x{61F8}\x{61F9}\x{61FA}\x{61FB}\x{61FC}\x{61FD}\x{61FE}\x{61FF}' . + '\x{6200}\x{6201}\x{6202}\x{6203}\x{6204}\x{6206}\x{6207}\x{6208}\x{6209}' . + '\x{620A}\x{620B}\x{620C}\x{620D}\x{620E}\x{620F}\x{6210}\x{6211}\x{6212}' . + '\x{6213}\x{6214}\x{6215}\x{6216}\x{6217}\x{6218}\x{6219}\x{621A}\x{621B}' . + '\x{621C}\x{621D}\x{621E}\x{621F}\x{6220}\x{6221}\x{6222}\x{6223}\x{6224}' . + '\x{6225}\x{6226}\x{6227}\x{6228}\x{6229}\x{622A}\x{622B}\x{622C}\x{622D}' . + '\x{622E}\x{622F}\x{6230}\x{6231}\x{6232}\x{6233}\x{6234}\x{6236}\x{6237}' . + '\x{6238}\x{623A}\x{623B}\x{623C}\x{623D}\x{623E}\x{623F}\x{6240}\x{6241}' . + '\x{6242}\x{6243}\x{6244}\x{6245}\x{6246}\x{6247}\x{6248}\x{6249}\x{624A}' . + '\x{624B}\x{624C}\x{624D}\x{624E}\x{624F}\x{6250}\x{6251}\x{6252}\x{6253}' . + '\x{6254}\x{6255}\x{6256}\x{6258}\x{6259}\x{625A}\x{625B}\x{625C}\x{625D}' . + '\x{625E}\x{625F}\x{6260}\x{6261}\x{6262}\x{6263}\x{6264}\x{6265}\x{6266}' . + '\x{6267}\x{6268}\x{6269}\x{626A}\x{626B}\x{626C}\x{626D}\x{626E}\x{626F}' . + '\x{6270}\x{6271}\x{6272}\x{6273}\x{6274}\x{6275}\x{6276}\x{6277}\x{6278}' . + '\x{6279}\x{627A}\x{627B}\x{627C}\x{627D}\x{627E}\x{627F}\x{6280}\x{6281}' . + '\x{6283}\x{6284}\x{6285}\x{6286}\x{6287}\x{6288}\x{6289}\x{628A}\x{628B}' . + '\x{628C}\x{628E}\x{628F}\x{6290}\x{6291}\x{6292}\x{6293}\x{6294}\x{6295}' . + '\x{6296}\x{6297}\x{6298}\x{6299}\x{629A}\x{629B}\x{629C}\x{629E}\x{629F}' . + '\x{62A0}\x{62A1}\x{62A2}\x{62A3}\x{62A4}\x{62A5}\x{62A7}\x{62A8}\x{62A9}' . + '\x{62AA}\x{62AB}\x{62AC}\x{62AD}\x{62AE}\x{62AF}\x{62B0}\x{62B1}\x{62B2}' . + '\x{62B3}\x{62B4}\x{62B5}\x{62B6}\x{62B7}\x{62B8}\x{62B9}\x{62BA}\x{62BB}' . + '\x{62BC}\x{62BD}\x{62BE}\x{62BF}\x{62C0}\x{62C1}\x{62C2}\x{62C3}\x{62C4}' . + '\x{62C5}\x{62C6}\x{62C7}\x{62C8}\x{62C9}\x{62CA}\x{62CB}\x{62CC}\x{62CD}' . + '\x{62CE}\x{62CF}\x{62D0}\x{62D1}\x{62D2}\x{62D3}\x{62D4}\x{62D5}\x{62D6}' . + '\x{62D7}\x{62D8}\x{62D9}\x{62DA}\x{62DB}\x{62DC}\x{62DD}\x{62DF}\x{62E0}' . + '\x{62E1}\x{62E2}\x{62E3}\x{62E4}\x{62E5}\x{62E6}\x{62E7}\x{62E8}\x{62E9}' . + '\x{62EB}\x{62EC}\x{62ED}\x{62EE}\x{62EF}\x{62F0}\x{62F1}\x{62F2}\x{62F3}' . + '\x{62F4}\x{62F5}\x{62F6}\x{62F7}\x{62F8}\x{62F9}\x{62FA}\x{62FB}\x{62FC}' . + '\x{62FD}\x{62FE}\x{62FF}\x{6300}\x{6301}\x{6302}\x{6303}\x{6304}\x{6305}' . + '\x{6306}\x{6307}\x{6308}\x{6309}\x{630B}\x{630C}\x{630D}\x{630E}\x{630F}' . + '\x{6310}\x{6311}\x{6312}\x{6313}\x{6314}\x{6315}\x{6316}\x{6318}\x{6319}' . + '\x{631A}\x{631B}\x{631C}\x{631D}\x{631E}\x{631F}\x{6320}\x{6321}\x{6322}' . + '\x{6323}\x{6324}\x{6325}\x{6326}\x{6327}\x{6328}\x{6329}\x{632A}\x{632B}' . + '\x{632C}\x{632D}\x{632E}\x{632F}\x{6330}\x{6332}\x{6333}\x{6334}\x{6336}' . + '\x{6338}\x{6339}\x{633A}\x{633B}\x{633C}\x{633D}\x{633E}\x{6340}\x{6341}' . + '\x{6342}\x{6343}\x{6344}\x{6345}\x{6346}\x{6347}\x{6348}\x{6349}\x{634A}' . + '\x{634B}\x{634C}\x{634D}\x{634E}\x{634F}\x{6350}\x{6351}\x{6352}\x{6353}' . + '\x{6354}\x{6355}\x{6356}\x{6357}\x{6358}\x{6359}\x{635A}\x{635C}\x{635D}' . + '\x{635E}\x{635F}\x{6360}\x{6361}\x{6362}\x{6363}\x{6364}\x{6365}\x{6366}' . + '\x{6367}\x{6368}\x{6369}\x{636A}\x{636B}\x{636C}\x{636D}\x{636E}\x{636F}' . + '\x{6370}\x{6371}\x{6372}\x{6373}\x{6374}\x{6375}\x{6376}\x{6377}\x{6378}' . + '\x{6379}\x{637A}\x{637B}\x{637C}\x{637D}\x{637E}\x{6380}\x{6381}\x{6382}' . + '\x{6383}\x{6384}\x{6385}\x{6386}\x{6387}\x{6388}\x{6389}\x{638A}\x{638C}' . + '\x{638D}\x{638E}\x{638F}\x{6390}\x{6391}\x{6392}\x{6394}\x{6395}\x{6396}' . + '\x{6397}\x{6398}\x{6399}\x{639A}\x{639B}\x{639C}\x{639D}\x{639E}\x{639F}' . + '\x{63A0}\x{63A1}\x{63A2}\x{63A3}\x{63A4}\x{63A5}\x{63A6}\x{63A7}\x{63A8}' . + '\x{63A9}\x{63AA}\x{63AB}\x{63AC}\x{63AD}\x{63AE}\x{63AF}\x{63B0}\x{63B1}' . + '\x{63B2}\x{63B3}\x{63B4}\x{63B5}\x{63B6}\x{63B7}\x{63B8}\x{63B9}\x{63BA}' . + '\x{63BC}\x{63BD}\x{63BE}\x{63BF}\x{63C0}\x{63C1}\x{63C2}\x{63C3}\x{63C4}' . + '\x{63C5}\x{63C6}\x{63C7}\x{63C8}\x{63C9}\x{63CA}\x{63CB}\x{63CC}\x{63CD}' . + '\x{63CE}\x{63CF}\x{63D0}\x{63D2}\x{63D3}\x{63D4}\x{63D5}\x{63D6}\x{63D7}' . + '\x{63D8}\x{63D9}\x{63DA}\x{63DB}\x{63DC}\x{63DD}\x{63DE}\x{63DF}\x{63E0}' . + '\x{63E1}\x{63E2}\x{63E3}\x{63E4}\x{63E5}\x{63E6}\x{63E7}\x{63E8}\x{63E9}' . + '\x{63EA}\x{63EB}\x{63EC}\x{63ED}\x{63EE}\x{63EF}\x{63F0}\x{63F1}\x{63F2}' . + '\x{63F3}\x{63F4}\x{63F5}\x{63F6}\x{63F7}\x{63F8}\x{63F9}\x{63FA}\x{63FB}' . + '\x{63FC}\x{63FD}\x{63FE}\x{63FF}\x{6400}\x{6401}\x{6402}\x{6403}\x{6404}' . + '\x{6405}\x{6406}\x{6408}\x{6409}\x{640A}\x{640B}\x{640C}\x{640D}\x{640E}' . + '\x{640F}\x{6410}\x{6411}\x{6412}\x{6413}\x{6414}\x{6415}\x{6416}\x{6417}' . + '\x{6418}\x{6419}\x{641A}\x{641B}\x{641C}\x{641D}\x{641E}\x{641F}\x{6420}' . + '\x{6421}\x{6422}\x{6423}\x{6424}\x{6425}\x{6426}\x{6427}\x{6428}\x{6429}' . + '\x{642A}\x{642B}\x{642C}\x{642D}\x{642E}\x{642F}\x{6430}\x{6431}\x{6432}' . + '\x{6433}\x{6434}\x{6435}\x{6436}\x{6437}\x{6438}\x{6439}\x{643A}\x{643D}' . + '\x{643E}\x{643F}\x{6440}\x{6441}\x{6443}\x{6444}\x{6445}\x{6446}\x{6447}' . + '\x{6448}\x{644A}\x{644B}\x{644C}\x{644D}\x{644E}\x{644F}\x{6450}\x{6451}' . + '\x{6452}\x{6453}\x{6454}\x{6455}\x{6456}\x{6457}\x{6458}\x{6459}\x{645B}' . + '\x{645C}\x{645D}\x{645E}\x{645F}\x{6460}\x{6461}\x{6462}\x{6463}\x{6464}' . + '\x{6465}\x{6466}\x{6467}\x{6468}\x{6469}\x{646A}\x{646B}\x{646C}\x{646D}' . + '\x{646E}\x{646F}\x{6470}\x{6471}\x{6472}\x{6473}\x{6474}\x{6475}\x{6476}' . + '\x{6477}\x{6478}\x{6479}\x{647A}\x{647B}\x{647C}\x{647D}\x{647F}\x{6480}' . + '\x{6481}\x{6482}\x{6483}\x{6484}\x{6485}\x{6487}\x{6488}\x{6489}\x{648A}' . + '\x{648B}\x{648C}\x{648D}\x{648E}\x{648F}\x{6490}\x{6491}\x{6492}\x{6493}' . + '\x{6494}\x{6495}\x{6496}\x{6497}\x{6498}\x{6499}\x{649A}\x{649B}\x{649C}' . + '\x{649D}\x{649E}\x{649F}\x{64A0}\x{64A2}\x{64A3}\x{64A4}\x{64A5}\x{64A6}' . + '\x{64A7}\x{64A8}\x{64A9}\x{64AA}\x{64AB}\x{64AC}\x{64AD}\x{64AE}\x{64B0}' . + '\x{64B1}\x{64B2}\x{64B3}\x{64B4}\x{64B5}\x{64B7}\x{64B8}\x{64B9}\x{64BA}' . + '\x{64BB}\x{64BC}\x{64BD}\x{64BE}\x{64BF}\x{64C0}\x{64C1}\x{64C2}\x{64C3}' . + '\x{64C4}\x{64C5}\x{64C6}\x{64C7}\x{64C9}\x{64CA}\x{64CB}\x{64CC}\x{64CD}' . + '\x{64CE}\x{64CF}\x{64D0}\x{64D1}\x{64D2}\x{64D3}\x{64D4}\x{64D6}\x{64D7}' . + '\x{64D8}\x{64D9}\x{64DA}\x{64DB}\x{64DC}\x{64DD}\x{64DE}\x{64DF}\x{64E0}' . + '\x{64E2}\x{64E3}\x{64E4}\x{64E6}\x{64E7}\x{64E8}\x{64E9}\x{64EA}\x{64EB}' . + '\x{64EC}\x{64ED}\x{64EF}\x{64F0}\x{64F1}\x{64F2}\x{64F3}\x{64F4}\x{64F6}' . + '\x{64F7}\x{64F8}\x{64FA}\x{64FB}\x{64FC}\x{64FD}\x{64FE}\x{64FF}\x{6500}' . + '\x{6501}\x{6503}\x{6504}\x{6505}\x{6506}\x{6507}\x{6508}\x{6509}\x{650B}' . + '\x{650C}\x{650D}\x{650E}\x{650F}\x{6510}\x{6511}\x{6512}\x{6513}\x{6514}' . + '\x{6515}\x{6516}\x{6517}\x{6518}\x{6519}\x{651A}\x{651B}\x{651C}\x{651D}' . + '\x{651E}\x{6520}\x{6521}\x{6522}\x{6523}\x{6524}\x{6525}\x{6526}\x{6527}' . + '\x{6529}\x{652A}\x{652B}\x{652C}\x{652D}\x{652E}\x{652F}\x{6530}\x{6531}' . + '\x{6532}\x{6533}\x{6534}\x{6535}\x{6536}\x{6537}\x{6538}\x{6539}\x{653A}' . + '\x{653B}\x{653C}\x{653D}\x{653E}\x{653F}\x{6541}\x{6543}\x{6544}\x{6545}' . + '\x{6546}\x{6547}\x{6548}\x{6549}\x{654A}\x{654B}\x{654C}\x{654D}\x{654E}' . + '\x{654F}\x{6550}\x{6551}\x{6552}\x{6553}\x{6554}\x{6555}\x{6556}\x{6557}' . + '\x{6558}\x{6559}\x{655B}\x{655C}\x{655D}\x{655E}\x{6560}\x{6561}\x{6562}' . + '\x{6563}\x{6564}\x{6565}\x{6566}\x{6567}\x{6568}\x{6569}\x{656A}\x{656B}' . + '\x{656C}\x{656E}\x{656F}\x{6570}\x{6571}\x{6572}\x{6573}\x{6574}\x{6575}' . + '\x{6576}\x{6577}\x{6578}\x{6579}\x{657A}\x{657B}\x{657C}\x{657E}\x{657F}' . + '\x{6580}\x{6581}\x{6582}\x{6583}\x{6584}\x{6585}\x{6586}\x{6587}\x{6588}' . + '\x{6589}\x{658B}\x{658C}\x{658D}\x{658E}\x{658F}\x{6590}\x{6591}\x{6592}' . + '\x{6593}\x{6594}\x{6595}\x{6596}\x{6597}\x{6598}\x{6599}\x{659B}\x{659C}' . + '\x{659D}\x{659E}\x{659F}\x{65A0}\x{65A1}\x{65A2}\x{65A3}\x{65A4}\x{65A5}' . + '\x{65A6}\x{65A7}\x{65A8}\x{65A9}\x{65AA}\x{65AB}\x{65AC}\x{65AD}\x{65AE}' . + '\x{65AF}\x{65B0}\x{65B1}\x{65B2}\x{65B3}\x{65B4}\x{65B6}\x{65B7}\x{65B8}' . + '\x{65B9}\x{65BA}\x{65BB}\x{65BC}\x{65BD}\x{65BF}\x{65C0}\x{65C1}\x{65C2}' . + '\x{65C3}\x{65C4}\x{65C5}\x{65C6}\x{65C7}\x{65CA}\x{65CB}\x{65CC}\x{65CD}' . + '\x{65CE}\x{65CF}\x{65D0}\x{65D2}\x{65D3}\x{65D4}\x{65D5}\x{65D6}\x{65D7}' . + '\x{65DA}\x{65DB}\x{65DD}\x{65DE}\x{65DF}\x{65E0}\x{65E1}\x{65E2}\x{65E3}' . + '\x{65E5}\x{65E6}\x{65E7}\x{65E8}\x{65E9}\x{65EB}\x{65EC}\x{65ED}\x{65EE}' . + '\x{65EF}\x{65F0}\x{65F1}\x{65F2}\x{65F3}\x{65F4}\x{65F5}\x{65F6}\x{65F7}' . + '\x{65F8}\x{65FA}\x{65FB}\x{65FC}\x{65FD}\x{6600}\x{6601}\x{6602}\x{6603}' . + '\x{6604}\x{6605}\x{6606}\x{6607}\x{6608}\x{6609}\x{660A}\x{660B}\x{660C}' . + '\x{660D}\x{660E}\x{660F}\x{6610}\x{6611}\x{6612}\x{6613}\x{6614}\x{6615}' . + '\x{6616}\x{6618}\x{6619}\x{661A}\x{661B}\x{661C}\x{661D}\x{661F}\x{6620}' . + '\x{6621}\x{6622}\x{6623}\x{6624}\x{6625}\x{6626}\x{6627}\x{6628}\x{6629}' . + '\x{662A}\x{662B}\x{662D}\x{662E}\x{662F}\x{6630}\x{6631}\x{6632}\x{6633}' . + '\x{6634}\x{6635}\x{6636}\x{6639}\x{663A}\x{663C}\x{663D}\x{663E}\x{6640}' . + '\x{6641}\x{6642}\x{6643}\x{6644}\x{6645}\x{6646}\x{6647}\x{6649}\x{664A}' . + '\x{664B}\x{664C}\x{664E}\x{664F}\x{6650}\x{6651}\x{6652}\x{6653}\x{6654}' . + '\x{6655}\x{6656}\x{6657}\x{6658}\x{6659}\x{665A}\x{665B}\x{665C}\x{665D}' . + '\x{665E}\x{665F}\x{6661}\x{6662}\x{6664}\x{6665}\x{6666}\x{6668}\x{6669}' . + '\x{666A}\x{666B}\x{666C}\x{666D}\x{666E}\x{666F}\x{6670}\x{6671}\x{6672}' . + '\x{6673}\x{6674}\x{6675}\x{6676}\x{6677}\x{6678}\x{6679}\x{667A}\x{667B}' . + '\x{667C}\x{667D}\x{667E}\x{667F}\x{6680}\x{6681}\x{6682}\x{6683}\x{6684}' . + '\x{6685}\x{6686}\x{6687}\x{6688}\x{6689}\x{668A}\x{668B}\x{668C}\x{668D}' . + '\x{668E}\x{668F}\x{6690}\x{6691}\x{6693}\x{6694}\x{6695}\x{6696}\x{6697}' . + '\x{6698}\x{6699}\x{669A}\x{669B}\x{669D}\x{669F}\x{66A0}\x{66A1}\x{66A2}' . + '\x{66A3}\x{66A4}\x{66A5}\x{66A6}\x{66A7}\x{66A8}\x{66A9}\x{66AA}\x{66AB}' . + '\x{66AE}\x{66AF}\x{66B0}\x{66B1}\x{66B2}\x{66B3}\x{66B4}\x{66B5}\x{66B6}' . + '\x{66B7}\x{66B8}\x{66B9}\x{66BA}\x{66BB}\x{66BC}\x{66BD}\x{66BE}\x{66BF}' . + '\x{66C0}\x{66C1}\x{66C2}\x{66C3}\x{66C4}\x{66C5}\x{66C6}\x{66C7}\x{66C8}' . + '\x{66C9}\x{66CA}\x{66CB}\x{66CC}\x{66CD}\x{66CE}\x{66CF}\x{66D1}\x{66D2}' . + '\x{66D4}\x{66D5}\x{66D6}\x{66D8}\x{66D9}\x{66DA}\x{66DB}\x{66DC}\x{66DD}' . + '\x{66DE}\x{66E0}\x{66E1}\x{66E2}\x{66E3}\x{66E4}\x{66E5}\x{66E6}\x{66E7}' . + '\x{66E8}\x{66E9}\x{66EA}\x{66EB}\x{66EC}\x{66ED}\x{66EE}\x{66F0}\x{66F1}' . + '\x{66F2}\x{66F3}\x{66F4}\x{66F5}\x{66F6}\x{66F7}\x{66F8}\x{66F9}\x{66FA}' . + '\x{66FB}\x{66FC}\x{66FE}\x{66FF}\x{6700}\x{6701}\x{6703}\x{6704}\x{6705}' . + '\x{6706}\x{6708}\x{6709}\x{670A}\x{670B}\x{670C}\x{670D}\x{670E}\x{670F}' . + '\x{6710}\x{6711}\x{6712}\x{6713}\x{6714}\x{6715}\x{6716}\x{6717}\x{6718}' . + '\x{671A}\x{671B}\x{671C}\x{671D}\x{671E}\x{671F}\x{6720}\x{6721}\x{6722}' . + '\x{6723}\x{6725}\x{6726}\x{6727}\x{6728}\x{672A}\x{672B}\x{672C}\x{672D}' . + '\x{672E}\x{672F}\x{6730}\x{6731}\x{6732}\x{6733}\x{6734}\x{6735}\x{6736}' . + '\x{6737}\x{6738}\x{6739}\x{673A}\x{673B}\x{673C}\x{673D}\x{673E}\x{673F}' . + '\x{6740}\x{6741}\x{6742}\x{6743}\x{6744}\x{6745}\x{6746}\x{6747}\x{6748}' . + '\x{6749}\x{674A}\x{674B}\x{674C}\x{674D}\x{674E}\x{674F}\x{6750}\x{6751}' . + '\x{6752}\x{6753}\x{6754}\x{6755}\x{6756}\x{6757}\x{6758}\x{6759}\x{675A}' . + '\x{675B}\x{675C}\x{675D}\x{675E}\x{675F}\x{6760}\x{6761}\x{6762}\x{6763}' . + '\x{6764}\x{6765}\x{6766}\x{6768}\x{6769}\x{676A}\x{676B}\x{676C}\x{676D}' . + '\x{676E}\x{676F}\x{6770}\x{6771}\x{6772}\x{6773}\x{6774}\x{6775}\x{6776}' . + '\x{6777}\x{6778}\x{6779}\x{677A}\x{677B}\x{677C}\x{677D}\x{677E}\x{677F}' . + '\x{6780}\x{6781}\x{6782}\x{6783}\x{6784}\x{6785}\x{6786}\x{6787}\x{6789}' . + '\x{678A}\x{678B}\x{678C}\x{678D}\x{678E}\x{678F}\x{6790}\x{6791}\x{6792}' . + '\x{6793}\x{6794}\x{6795}\x{6797}\x{6798}\x{6799}\x{679A}\x{679B}\x{679C}' . + '\x{679D}\x{679E}\x{679F}\x{67A0}\x{67A1}\x{67A2}\x{67A3}\x{67A4}\x{67A5}' . + '\x{67A6}\x{67A7}\x{67A8}\x{67AA}\x{67AB}\x{67AC}\x{67AD}\x{67AE}\x{67AF}' . + '\x{67B0}\x{67B1}\x{67B2}\x{67B3}\x{67B4}\x{67B5}\x{67B6}\x{67B7}\x{67B8}' . + '\x{67B9}\x{67BA}\x{67BB}\x{67BC}\x{67BE}\x{67C0}\x{67C1}\x{67C2}\x{67C3}' . + '\x{67C4}\x{67C5}\x{67C6}\x{67C7}\x{67C8}\x{67C9}\x{67CA}\x{67CB}\x{67CC}' . + '\x{67CD}\x{67CE}\x{67CF}\x{67D0}\x{67D1}\x{67D2}\x{67D3}\x{67D4}\x{67D6}' . + '\x{67D8}\x{67D9}\x{67DA}\x{67DB}\x{67DC}\x{67DD}\x{67DE}\x{67DF}\x{67E0}' . + '\x{67E1}\x{67E2}\x{67E3}\x{67E4}\x{67E5}\x{67E6}\x{67E7}\x{67E8}\x{67E9}' . + '\x{67EA}\x{67EB}\x{67EC}\x{67ED}\x{67EE}\x{67EF}\x{67F0}\x{67F1}\x{67F2}' . + '\x{67F3}\x{67F4}\x{67F5}\x{67F6}\x{67F7}\x{67F8}\x{67FA}\x{67FB}\x{67FC}' . + '\x{67FD}\x{67FE}\x{67FF}\x{6800}\x{6802}\x{6803}\x{6804}\x{6805}\x{6806}' . + '\x{6807}\x{6808}\x{6809}\x{680A}\x{680B}\x{680C}\x{680D}\x{680E}\x{680F}' . + '\x{6810}\x{6811}\x{6812}\x{6813}\x{6814}\x{6816}\x{6817}\x{6818}\x{6819}' . + '\x{681A}\x{681B}\x{681C}\x{681D}\x{681F}\x{6820}\x{6821}\x{6822}\x{6823}' . + '\x{6824}\x{6825}\x{6826}\x{6828}\x{6829}\x{682A}\x{682B}\x{682C}\x{682D}' . + '\x{682E}\x{682F}\x{6831}\x{6832}\x{6833}\x{6834}\x{6835}\x{6836}\x{6837}' . + '\x{6838}\x{6839}\x{683A}\x{683B}\x{683C}\x{683D}\x{683E}\x{683F}\x{6840}' . + '\x{6841}\x{6842}\x{6843}\x{6844}\x{6845}\x{6846}\x{6847}\x{6848}\x{6849}' . + '\x{684A}\x{684B}\x{684C}\x{684D}\x{684E}\x{684F}\x{6850}\x{6851}\x{6852}' . + '\x{6853}\x{6854}\x{6855}\x{6856}\x{6857}\x{685B}\x{685D}\x{6860}\x{6861}' . + '\x{6862}\x{6863}\x{6864}\x{6865}\x{6866}\x{6867}\x{6868}\x{6869}\x{686A}' . + '\x{686B}\x{686C}\x{686D}\x{686E}\x{686F}\x{6870}\x{6871}\x{6872}\x{6873}' . + '\x{6874}\x{6875}\x{6876}\x{6877}\x{6878}\x{6879}\x{687B}\x{687C}\x{687D}' . + '\x{687E}\x{687F}\x{6880}\x{6881}\x{6882}\x{6883}\x{6884}\x{6885}\x{6886}' . + '\x{6887}\x{6888}\x{6889}\x{688A}\x{688B}\x{688C}\x{688D}\x{688E}\x{688F}' . + '\x{6890}\x{6891}\x{6892}\x{6893}\x{6894}\x{6896}\x{6897}\x{6898}\x{689A}' . + '\x{689B}\x{689C}\x{689D}\x{689E}\x{689F}\x{68A0}\x{68A1}\x{68A2}\x{68A3}' . + '\x{68A4}\x{68A6}\x{68A7}\x{68A8}\x{68A9}\x{68AA}\x{68AB}\x{68AC}\x{68AD}' . + '\x{68AE}\x{68AF}\x{68B0}\x{68B1}\x{68B2}\x{68B3}\x{68B4}\x{68B5}\x{68B6}' . + '\x{68B7}\x{68B9}\x{68BB}\x{68BC}\x{68BD}\x{68BE}\x{68BF}\x{68C0}\x{68C1}' . + '\x{68C2}\x{68C4}\x{68C6}\x{68C7}\x{68C8}\x{68C9}\x{68CA}\x{68CB}\x{68CC}' . + '\x{68CD}\x{68CE}\x{68CF}\x{68D0}\x{68D1}\x{68D2}\x{68D3}\x{68D4}\x{68D5}' . + '\x{68D6}\x{68D7}\x{68D8}\x{68DA}\x{68DB}\x{68DC}\x{68DD}\x{68DE}\x{68DF}' . + '\x{68E0}\x{68E1}\x{68E3}\x{68E4}\x{68E6}\x{68E7}\x{68E8}\x{68E9}\x{68EA}' . + '\x{68EB}\x{68EC}\x{68ED}\x{68EE}\x{68EF}\x{68F0}\x{68F1}\x{68F2}\x{68F3}' . + '\x{68F4}\x{68F5}\x{68F6}\x{68F7}\x{68F8}\x{68F9}\x{68FA}\x{68FB}\x{68FC}' . + '\x{68FD}\x{68FE}\x{68FF}\x{6901}\x{6902}\x{6903}\x{6904}\x{6905}\x{6906}' . + '\x{6907}\x{6908}\x{690A}\x{690B}\x{690C}\x{690D}\x{690E}\x{690F}\x{6910}' . + '\x{6911}\x{6912}\x{6913}\x{6914}\x{6915}\x{6916}\x{6917}\x{6918}\x{6919}' . + '\x{691A}\x{691B}\x{691C}\x{691D}\x{691E}\x{691F}\x{6920}\x{6921}\x{6922}' . + '\x{6923}\x{6924}\x{6925}\x{6926}\x{6927}\x{6928}\x{6929}\x{692A}\x{692B}' . + '\x{692C}\x{692D}\x{692E}\x{692F}\x{6930}\x{6931}\x{6932}\x{6933}\x{6934}' . + '\x{6935}\x{6936}\x{6937}\x{6938}\x{6939}\x{693A}\x{693B}\x{693C}\x{693D}' . + '\x{693F}\x{6940}\x{6941}\x{6942}\x{6943}\x{6944}\x{6945}\x{6946}\x{6947}' . + '\x{6948}\x{6949}\x{694A}\x{694B}\x{694C}\x{694E}\x{694F}\x{6950}\x{6951}' . + '\x{6952}\x{6953}\x{6954}\x{6955}\x{6956}\x{6957}\x{6958}\x{6959}\x{695A}' . + '\x{695B}\x{695C}\x{695D}\x{695E}\x{695F}\x{6960}\x{6961}\x{6962}\x{6963}' . + '\x{6964}\x{6965}\x{6966}\x{6967}\x{6968}\x{6969}\x{696A}\x{696B}\x{696C}' . + '\x{696D}\x{696E}\x{696F}\x{6970}\x{6971}\x{6972}\x{6973}\x{6974}\x{6975}' . + '\x{6976}\x{6977}\x{6978}\x{6979}\x{697A}\x{697B}\x{697C}\x{697D}\x{697E}' . + '\x{697F}\x{6980}\x{6981}\x{6982}\x{6983}\x{6984}\x{6985}\x{6986}\x{6987}' . + '\x{6988}\x{6989}\x{698A}\x{698B}\x{698C}\x{698D}\x{698E}\x{698F}\x{6990}' . + '\x{6991}\x{6992}\x{6993}\x{6994}\x{6995}\x{6996}\x{6997}\x{6998}\x{6999}' . + '\x{699A}\x{699B}\x{699C}\x{699D}\x{699E}\x{69A0}\x{69A1}\x{69A3}\x{69A4}' . + '\x{69A5}\x{69A6}\x{69A7}\x{69A8}\x{69A9}\x{69AA}\x{69AB}\x{69AC}\x{69AD}' . + '\x{69AE}\x{69AF}\x{69B0}\x{69B1}\x{69B2}\x{69B3}\x{69B4}\x{69B5}\x{69B6}' . + '\x{69B7}\x{69B8}\x{69B9}\x{69BA}\x{69BB}\x{69BC}\x{69BD}\x{69BE}\x{69BF}' . + '\x{69C1}\x{69C2}\x{69C3}\x{69C4}\x{69C5}\x{69C6}\x{69C7}\x{69C8}\x{69C9}' . + '\x{69CA}\x{69CB}\x{69CC}\x{69CD}\x{69CE}\x{69CF}\x{69D0}\x{69D3}\x{69D4}' . + '\x{69D8}\x{69D9}\x{69DA}\x{69DB}\x{69DC}\x{69DD}\x{69DE}\x{69DF}\x{69E0}' . + '\x{69E1}\x{69E2}\x{69E3}\x{69E4}\x{69E5}\x{69E6}\x{69E7}\x{69E8}\x{69E9}' . + '\x{69EA}\x{69EB}\x{69EC}\x{69ED}\x{69EE}\x{69EF}\x{69F0}\x{69F1}\x{69F2}' . + '\x{69F3}\x{69F4}\x{69F5}\x{69F6}\x{69F7}\x{69F8}\x{69FA}\x{69FB}\x{69FC}' . + '\x{69FD}\x{69FE}\x{69FF}\x{6A00}\x{6A01}\x{6A02}\x{6A04}\x{6A05}\x{6A06}' . + '\x{6A07}\x{6A08}\x{6A09}\x{6A0A}\x{6A0B}\x{6A0D}\x{6A0E}\x{6A0F}\x{6A10}' . + '\x{6A11}\x{6A12}\x{6A13}\x{6A14}\x{6A15}\x{6A16}\x{6A17}\x{6A18}\x{6A19}' . + '\x{6A1A}\x{6A1B}\x{6A1D}\x{6A1E}\x{6A1F}\x{6A20}\x{6A21}\x{6A22}\x{6A23}' . + '\x{6A25}\x{6A26}\x{6A27}\x{6A28}\x{6A29}\x{6A2A}\x{6A2B}\x{6A2C}\x{6A2D}' . + '\x{6A2E}\x{6A2F}\x{6A30}\x{6A31}\x{6A32}\x{6A33}\x{6A34}\x{6A35}\x{6A36}' . + '\x{6A38}\x{6A39}\x{6A3A}\x{6A3B}\x{6A3C}\x{6A3D}\x{6A3E}\x{6A3F}\x{6A40}' . + '\x{6A41}\x{6A42}\x{6A43}\x{6A44}\x{6A45}\x{6A46}\x{6A47}\x{6A48}\x{6A49}' . + '\x{6A4B}\x{6A4C}\x{6A4D}\x{6A4E}\x{6A4F}\x{6A50}\x{6A51}\x{6A52}\x{6A54}' . + '\x{6A55}\x{6A56}\x{6A57}\x{6A58}\x{6A59}\x{6A5A}\x{6A5B}\x{6A5D}\x{6A5E}' . + '\x{6A5F}\x{6A60}\x{6A61}\x{6A62}\x{6A63}\x{6A64}\x{6A65}\x{6A66}\x{6A67}' . + '\x{6A68}\x{6A69}\x{6A6A}\x{6A6B}\x{6A6C}\x{6A6D}\x{6A6F}\x{6A71}\x{6A72}' . + '\x{6A73}\x{6A74}\x{6A75}\x{6A76}\x{6A77}\x{6A78}\x{6A79}\x{6A7A}\x{6A7B}' . + '\x{6A7C}\x{6A7D}\x{6A7E}\x{6A7F}\x{6A80}\x{6A81}\x{6A82}\x{6A83}\x{6A84}' . + '\x{6A85}\x{6A87}\x{6A88}\x{6A89}\x{6A8B}\x{6A8C}\x{6A8D}\x{6A8E}\x{6A90}' . + '\x{6A91}\x{6A92}\x{6A93}\x{6A94}\x{6A95}\x{6A96}\x{6A97}\x{6A98}\x{6A9A}' . + '\x{6A9B}\x{6A9C}\x{6A9E}\x{6A9F}\x{6AA0}\x{6AA1}\x{6AA2}\x{6AA3}\x{6AA4}' . + '\x{6AA5}\x{6AA6}\x{6AA7}\x{6AA8}\x{6AA9}\x{6AAB}\x{6AAC}\x{6AAD}\x{6AAE}' . + '\x{6AAF}\x{6AB0}\x{6AB2}\x{6AB3}\x{6AB4}\x{6AB5}\x{6AB6}\x{6AB7}\x{6AB8}' . + '\x{6AB9}\x{6ABA}\x{6ABB}\x{6ABC}\x{6ABD}\x{6ABF}\x{6AC1}\x{6AC2}\x{6AC3}' . + '\x{6AC5}\x{6AC6}\x{6AC7}\x{6ACA}\x{6ACB}\x{6ACC}\x{6ACD}\x{6ACE}\x{6ACF}' . + '\x{6AD0}\x{6AD1}\x{6AD2}\x{6AD3}\x{6AD4}\x{6AD5}\x{6AD6}\x{6AD7}\x{6AD9}' . + '\x{6ADA}\x{6ADB}\x{6ADC}\x{6ADD}\x{6ADE}\x{6ADF}\x{6AE0}\x{6AE1}\x{6AE2}' . + '\x{6AE3}\x{6AE4}\x{6AE5}\x{6AE6}\x{6AE7}\x{6AE8}\x{6AEA}\x{6AEB}\x{6AEC}' . + '\x{6AED}\x{6AEE}\x{6AEF}\x{6AF0}\x{6AF1}\x{6AF2}\x{6AF3}\x{6AF4}\x{6AF5}' . + '\x{6AF6}\x{6AF7}\x{6AF8}\x{6AF9}\x{6AFA}\x{6AFB}\x{6AFC}\x{6AFD}\x{6AFE}' . + '\x{6AFF}\x{6B00}\x{6B01}\x{6B02}\x{6B03}\x{6B04}\x{6B05}\x{6B06}\x{6B07}' . + '\x{6B08}\x{6B09}\x{6B0A}\x{6B0B}\x{6B0C}\x{6B0D}\x{6B0F}\x{6B10}\x{6B11}' . + '\x{6B12}\x{6B13}\x{6B14}\x{6B15}\x{6B16}\x{6B17}\x{6B18}\x{6B19}\x{6B1A}' . + '\x{6B1C}\x{6B1D}\x{6B1E}\x{6B1F}\x{6B20}\x{6B21}\x{6B22}\x{6B23}\x{6B24}' . + '\x{6B25}\x{6B26}\x{6B27}\x{6B28}\x{6B29}\x{6B2A}\x{6B2B}\x{6B2C}\x{6B2D}' . + '\x{6B2F}\x{6B30}\x{6B31}\x{6B32}\x{6B33}\x{6B34}\x{6B36}\x{6B37}\x{6B38}' . + '\x{6B39}\x{6B3A}\x{6B3B}\x{6B3C}\x{6B3D}\x{6B3E}\x{6B3F}\x{6B41}\x{6B42}' . + '\x{6B43}\x{6B44}\x{6B45}\x{6B46}\x{6B47}\x{6B48}\x{6B49}\x{6B4A}\x{6B4B}' . + '\x{6B4C}\x{6B4D}\x{6B4E}\x{6B4F}\x{6B50}\x{6B51}\x{6B52}\x{6B53}\x{6B54}' . + '\x{6B55}\x{6B56}\x{6B59}\x{6B5A}\x{6B5B}\x{6B5C}\x{6B5E}\x{6B5F}\x{6B60}' . + '\x{6B61}\x{6B62}\x{6B63}\x{6B64}\x{6B65}\x{6B66}\x{6B67}\x{6B69}\x{6B6A}' . + '\x{6B6B}\x{6B6D}\x{6B6F}\x{6B70}\x{6B72}\x{6B73}\x{6B74}\x{6B76}\x{6B77}' . + '\x{6B78}\x{6B79}\x{6B7A}\x{6B7B}\x{6B7C}\x{6B7E}\x{6B7F}\x{6B80}\x{6B81}' . + '\x{6B82}\x{6B83}\x{6B84}\x{6B85}\x{6B86}\x{6B87}\x{6B88}\x{6B89}\x{6B8A}' . + '\x{6B8B}\x{6B8C}\x{6B8D}\x{6B8E}\x{6B8F}\x{6B90}\x{6B91}\x{6B92}\x{6B93}' . + '\x{6B94}\x{6B95}\x{6B96}\x{6B97}\x{6B98}\x{6B99}\x{6B9A}\x{6B9B}\x{6B9C}' . + '\x{6B9D}\x{6B9E}\x{6B9F}\x{6BA0}\x{6BA1}\x{6BA2}\x{6BA3}\x{6BA4}\x{6BA5}' . + '\x{6BA6}\x{6BA7}\x{6BA8}\x{6BA9}\x{6BAA}\x{6BAB}\x{6BAC}\x{6BAD}\x{6BAE}' . + '\x{6BAF}\x{6BB0}\x{6BB2}\x{6BB3}\x{6BB4}\x{6BB5}\x{6BB6}\x{6BB7}\x{6BB9}' . + '\x{6BBA}\x{6BBB}\x{6BBC}\x{6BBD}\x{6BBE}\x{6BBF}\x{6BC0}\x{6BC1}\x{6BC2}' . + '\x{6BC3}\x{6BC4}\x{6BC5}\x{6BC6}\x{6BC7}\x{6BC8}\x{6BC9}\x{6BCA}\x{6BCB}' . + '\x{6BCC}\x{6BCD}\x{6BCE}\x{6BCF}\x{6BD0}\x{6BD1}\x{6BD2}\x{6BD3}\x{6BD4}' . + '\x{6BD5}\x{6BD6}\x{6BD7}\x{6BD8}\x{6BD9}\x{6BDA}\x{6BDB}\x{6BDC}\x{6BDD}' . + '\x{6BDE}\x{6BDF}\x{6BE0}\x{6BE1}\x{6BE2}\x{6BE3}\x{6BE4}\x{6BE5}\x{6BE6}' . + '\x{6BE7}\x{6BE8}\x{6BEA}\x{6BEB}\x{6BEC}\x{6BED}\x{6BEE}\x{6BEF}\x{6BF0}' . + '\x{6BF2}\x{6BF3}\x{6BF5}\x{6BF6}\x{6BF7}\x{6BF8}\x{6BF9}\x{6BFB}\x{6BFC}' . + '\x{6BFD}\x{6BFE}\x{6BFF}\x{6C00}\x{6C01}\x{6C02}\x{6C03}\x{6C04}\x{6C05}' . + '\x{6C06}\x{6C07}\x{6C08}\x{6C09}\x{6C0B}\x{6C0C}\x{6C0D}\x{6C0E}\x{6C0F}' . + '\x{6C10}\x{6C11}\x{6C12}\x{6C13}\x{6C14}\x{6C15}\x{6C16}\x{6C18}\x{6C19}' . + '\x{6C1A}\x{6C1B}\x{6C1D}\x{6C1E}\x{6C1F}\x{6C20}\x{6C21}\x{6C22}\x{6C23}' . + '\x{6C24}\x{6C25}\x{6C26}\x{6C27}\x{6C28}\x{6C29}\x{6C2A}\x{6C2B}\x{6C2C}' . + '\x{6C2E}\x{6C2F}\x{6C30}\x{6C31}\x{6C32}\x{6C33}\x{6C34}\x{6C35}\x{6C36}' . + '\x{6C37}\x{6C38}\x{6C3A}\x{6C3B}\x{6C3D}\x{6C3E}\x{6C3F}\x{6C40}\x{6C41}' . + '\x{6C42}\x{6C43}\x{6C44}\x{6C46}\x{6C47}\x{6C48}\x{6C49}\x{6C4A}\x{6C4B}' . + '\x{6C4C}\x{6C4D}\x{6C4E}\x{6C4F}\x{6C50}\x{6C51}\x{6C52}\x{6C53}\x{6C54}' . + '\x{6C55}\x{6C56}\x{6C57}\x{6C58}\x{6C59}\x{6C5A}\x{6C5B}\x{6C5C}\x{6C5D}' . + '\x{6C5E}\x{6C5F}\x{6C60}\x{6C61}\x{6C62}\x{6C63}\x{6C64}\x{6C65}\x{6C66}' . + '\x{6C67}\x{6C68}\x{6C69}\x{6C6A}\x{6C6B}\x{6C6D}\x{6C6F}\x{6C70}\x{6C71}' . + '\x{6C72}\x{6C73}\x{6C74}\x{6C75}\x{6C76}\x{6C77}\x{6C78}\x{6C79}\x{6C7A}' . + '\x{6C7B}\x{6C7C}\x{6C7D}\x{6C7E}\x{6C7F}\x{6C80}\x{6C81}\x{6C82}\x{6C83}' . + '\x{6C84}\x{6C85}\x{6C86}\x{6C87}\x{6C88}\x{6C89}\x{6C8A}\x{6C8B}\x{6C8C}' . + '\x{6C8D}\x{6C8E}\x{6C8F}\x{6C90}\x{6C91}\x{6C92}\x{6C93}\x{6C94}\x{6C95}' . + '\x{6C96}\x{6C97}\x{6C98}\x{6C99}\x{6C9A}\x{6C9B}\x{6C9C}\x{6C9D}\x{6C9E}' . + '\x{6C9F}\x{6CA1}\x{6CA2}\x{6CA3}\x{6CA4}\x{6CA5}\x{6CA6}\x{6CA7}\x{6CA8}' . + '\x{6CA9}\x{6CAA}\x{6CAB}\x{6CAC}\x{6CAD}\x{6CAE}\x{6CAF}\x{6CB0}\x{6CB1}' . + '\x{6CB2}\x{6CB3}\x{6CB4}\x{6CB5}\x{6CB6}\x{6CB7}\x{6CB8}\x{6CB9}\x{6CBA}' . + '\x{6CBB}\x{6CBC}\x{6CBD}\x{6CBE}\x{6CBF}\x{6CC0}\x{6CC1}\x{6CC2}\x{6CC3}' . + '\x{6CC4}\x{6CC5}\x{6CC6}\x{6CC7}\x{6CC8}\x{6CC9}\x{6CCA}\x{6CCB}\x{6CCC}' . + '\x{6CCD}\x{6CCE}\x{6CCF}\x{6CD0}\x{6CD1}\x{6CD2}\x{6CD3}\x{6CD4}\x{6CD5}' . + '\x{6CD6}\x{6CD7}\x{6CD9}\x{6CDA}\x{6CDB}\x{6CDC}\x{6CDD}\x{6CDE}\x{6CDF}' . + '\x{6CE0}\x{6CE1}\x{6CE2}\x{6CE3}\x{6CE4}\x{6CE5}\x{6CE6}\x{6CE7}\x{6CE8}' . + '\x{6CE9}\x{6CEA}\x{6CEB}\x{6CEC}\x{6CED}\x{6CEE}\x{6CEF}\x{6CF0}\x{6CF1}' . + '\x{6CF2}\x{6CF3}\x{6CF5}\x{6CF6}\x{6CF7}\x{6CF8}\x{6CF9}\x{6CFA}\x{6CFB}' . + '\x{6CFC}\x{6CFD}\x{6CFE}\x{6CFF}\x{6D00}\x{6D01}\x{6D03}\x{6D04}\x{6D05}' . + '\x{6D06}\x{6D07}\x{6D08}\x{6D09}\x{6D0A}\x{6D0B}\x{6D0C}\x{6D0D}\x{6D0E}' . + '\x{6D0F}\x{6D10}\x{6D11}\x{6D12}\x{6D13}\x{6D14}\x{6D15}\x{6D16}\x{6D17}' . + '\x{6D18}\x{6D19}\x{6D1A}\x{6D1B}\x{6D1D}\x{6D1E}\x{6D1F}\x{6D20}\x{6D21}' . + '\x{6D22}\x{6D23}\x{6D25}\x{6D26}\x{6D27}\x{6D28}\x{6D29}\x{6D2A}\x{6D2B}' . + '\x{6D2C}\x{6D2D}\x{6D2E}\x{6D2F}\x{6D30}\x{6D31}\x{6D32}\x{6D33}\x{6D34}' . + '\x{6D35}\x{6D36}\x{6D37}\x{6D38}\x{6D39}\x{6D3A}\x{6D3B}\x{6D3C}\x{6D3D}' . + '\x{6D3E}\x{6D3F}\x{6D40}\x{6D41}\x{6D42}\x{6D43}\x{6D44}\x{6D45}\x{6D46}' . + '\x{6D47}\x{6D48}\x{6D49}\x{6D4A}\x{6D4B}\x{6D4C}\x{6D4D}\x{6D4E}\x{6D4F}' . + '\x{6D50}\x{6D51}\x{6D52}\x{6D53}\x{6D54}\x{6D55}\x{6D56}\x{6D57}\x{6D58}' . + '\x{6D59}\x{6D5A}\x{6D5B}\x{6D5C}\x{6D5D}\x{6D5E}\x{6D5F}\x{6D60}\x{6D61}' . + '\x{6D62}\x{6D63}\x{6D64}\x{6D65}\x{6D66}\x{6D67}\x{6D68}\x{6D69}\x{6D6A}' . + '\x{6D6B}\x{6D6C}\x{6D6D}\x{6D6E}\x{6D6F}\x{6D70}\x{6D72}\x{6D73}\x{6D74}' . + '\x{6D75}\x{6D76}\x{6D77}\x{6D78}\x{6D79}\x{6D7A}\x{6D7B}\x{6D7C}\x{6D7D}' . + '\x{6D7E}\x{6D7F}\x{6D80}\x{6D82}\x{6D83}\x{6D84}\x{6D85}\x{6D86}\x{6D87}' . + '\x{6D88}\x{6D89}\x{6D8A}\x{6D8B}\x{6D8C}\x{6D8D}\x{6D8E}\x{6D8F}\x{6D90}' . + '\x{6D91}\x{6D92}\x{6D93}\x{6D94}\x{6D95}\x{6D97}\x{6D98}\x{6D99}\x{6D9A}' . + '\x{6D9B}\x{6D9D}\x{6D9E}\x{6D9F}\x{6DA0}\x{6DA1}\x{6DA2}\x{6DA3}\x{6DA4}' . + '\x{6DA5}\x{6DA6}\x{6DA7}\x{6DA8}\x{6DA9}\x{6DAA}\x{6DAB}\x{6DAC}\x{6DAD}' . + '\x{6DAE}\x{6DAF}\x{6DB2}\x{6DB3}\x{6DB4}\x{6DB5}\x{6DB7}\x{6DB8}\x{6DB9}' . + '\x{6DBA}\x{6DBB}\x{6DBC}\x{6DBD}\x{6DBE}\x{6DBF}\x{6DC0}\x{6DC1}\x{6DC2}' . + '\x{6DC3}\x{6DC4}\x{6DC5}\x{6DC6}\x{6DC7}\x{6DC8}\x{6DC9}\x{6DCA}\x{6DCB}' . + '\x{6DCC}\x{6DCD}\x{6DCE}\x{6DCF}\x{6DD0}\x{6DD1}\x{6DD2}\x{6DD3}\x{6DD4}' . + '\x{6DD5}\x{6DD6}\x{6DD7}\x{6DD8}\x{6DD9}\x{6DDA}\x{6DDB}\x{6DDC}\x{6DDD}' . + '\x{6DDE}\x{6DDF}\x{6DE0}\x{6DE1}\x{6DE2}\x{6DE3}\x{6DE4}\x{6DE5}\x{6DE6}' . + '\x{6DE7}\x{6DE8}\x{6DE9}\x{6DEA}\x{6DEB}\x{6DEC}\x{6DED}\x{6DEE}\x{6DEF}' . + '\x{6DF0}\x{6DF1}\x{6DF2}\x{6DF3}\x{6DF4}\x{6DF5}\x{6DF6}\x{6DF7}\x{6DF8}' . + '\x{6DF9}\x{6DFA}\x{6DFB}\x{6DFC}\x{6DFD}\x{6E00}\x{6E03}\x{6E04}\x{6E05}' . + '\x{6E07}\x{6E08}\x{6E09}\x{6E0A}\x{6E0B}\x{6E0C}\x{6E0D}\x{6E0E}\x{6E0F}' . + '\x{6E10}\x{6E11}\x{6E14}\x{6E15}\x{6E16}\x{6E17}\x{6E19}\x{6E1A}\x{6E1B}' . + '\x{6E1C}\x{6E1D}\x{6E1E}\x{6E1F}\x{6E20}\x{6E21}\x{6E22}\x{6E23}\x{6E24}' . + '\x{6E25}\x{6E26}\x{6E27}\x{6E28}\x{6E29}\x{6E2B}\x{6E2C}\x{6E2D}\x{6E2E}' . + '\x{6E2F}\x{6E30}\x{6E31}\x{6E32}\x{6E33}\x{6E34}\x{6E35}\x{6E36}\x{6E37}' . + '\x{6E38}\x{6E39}\x{6E3A}\x{6E3B}\x{6E3C}\x{6E3D}\x{6E3E}\x{6E3F}\x{6E40}' . + '\x{6E41}\x{6E42}\x{6E43}\x{6E44}\x{6E45}\x{6E46}\x{6E47}\x{6E48}\x{6E49}' . + '\x{6E4A}\x{6E4B}\x{6E4D}\x{6E4E}\x{6E4F}\x{6E50}\x{6E51}\x{6E52}\x{6E53}' . + '\x{6E54}\x{6E55}\x{6E56}\x{6E57}\x{6E58}\x{6E59}\x{6E5A}\x{6E5B}\x{6E5C}' . + '\x{6E5D}\x{6E5E}\x{6E5F}\x{6E60}\x{6E61}\x{6E62}\x{6E63}\x{6E64}\x{6E65}' . + '\x{6E66}\x{6E67}\x{6E68}\x{6E69}\x{6E6A}\x{6E6B}\x{6E6D}\x{6E6E}\x{6E6F}' . + '\x{6E70}\x{6E71}\x{6E72}\x{6E73}\x{6E74}\x{6E75}\x{6E77}\x{6E78}\x{6E79}' . + '\x{6E7E}\x{6E7F}\x{6E80}\x{6E81}\x{6E82}\x{6E83}\x{6E84}\x{6E85}\x{6E86}' . + '\x{6E87}\x{6E88}\x{6E89}\x{6E8A}\x{6E8D}\x{6E8E}\x{6E8F}\x{6E90}\x{6E91}' . + '\x{6E92}\x{6E93}\x{6E94}\x{6E96}\x{6E97}\x{6E98}\x{6E99}\x{6E9A}\x{6E9B}' . + '\x{6E9C}\x{6E9D}\x{6E9E}\x{6E9F}\x{6EA0}\x{6EA1}\x{6EA2}\x{6EA3}\x{6EA4}' . + '\x{6EA5}\x{6EA6}\x{6EA7}\x{6EA8}\x{6EA9}\x{6EAA}\x{6EAB}\x{6EAC}\x{6EAD}' . + '\x{6EAE}\x{6EAF}\x{6EB0}\x{6EB1}\x{6EB2}\x{6EB3}\x{6EB4}\x{6EB5}\x{6EB6}' . + '\x{6EB7}\x{6EB8}\x{6EB9}\x{6EBA}\x{6EBB}\x{6EBC}\x{6EBD}\x{6EBE}\x{6EBF}' . + '\x{6EC0}\x{6EC1}\x{6EC2}\x{6EC3}\x{6EC4}\x{6EC5}\x{6EC6}\x{6EC7}\x{6EC8}' . + '\x{6EC9}\x{6ECA}\x{6ECB}\x{6ECC}\x{6ECD}\x{6ECE}\x{6ECF}\x{6ED0}\x{6ED1}' . + '\x{6ED2}\x{6ED3}\x{6ED4}\x{6ED5}\x{6ED6}\x{6ED7}\x{6ED8}\x{6ED9}\x{6EDA}' . + '\x{6EDC}\x{6EDE}\x{6EDF}\x{6EE0}\x{6EE1}\x{6EE2}\x{6EE4}\x{6EE5}\x{6EE6}' . + '\x{6EE7}\x{6EE8}\x{6EE9}\x{6EEA}\x{6EEB}\x{6EEC}\x{6EED}\x{6EEE}\x{6EEF}' . + '\x{6EF0}\x{6EF1}\x{6EF2}\x{6EF3}\x{6EF4}\x{6EF5}\x{6EF6}\x{6EF7}\x{6EF8}' . + '\x{6EF9}\x{6EFA}\x{6EFB}\x{6EFC}\x{6EFD}\x{6EFE}\x{6EFF}\x{6F00}\x{6F01}' . + '\x{6F02}\x{6F03}\x{6F05}\x{6F06}\x{6F07}\x{6F08}\x{6F09}\x{6F0A}\x{6F0C}' . + '\x{6F0D}\x{6F0E}\x{6F0F}\x{6F10}\x{6F11}\x{6F12}\x{6F13}\x{6F14}\x{6F15}' . + '\x{6F16}\x{6F17}\x{6F18}\x{6F19}\x{6F1A}\x{6F1B}\x{6F1C}\x{6F1D}\x{6F1E}' . + '\x{6F1F}\x{6F20}\x{6F21}\x{6F22}\x{6F23}\x{6F24}\x{6F25}\x{6F26}\x{6F27}' . + '\x{6F28}\x{6F29}\x{6F2A}\x{6F2B}\x{6F2C}\x{6F2D}\x{6F2E}\x{6F2F}\x{6F30}' . + '\x{6F31}\x{6F32}\x{6F33}\x{6F34}\x{6F35}\x{6F36}\x{6F37}\x{6F38}\x{6F39}' . + '\x{6F3A}\x{6F3B}\x{6F3C}\x{6F3D}\x{6F3E}\x{6F3F}\x{6F40}\x{6F41}\x{6F43}' . + '\x{6F44}\x{6F45}\x{6F46}\x{6F47}\x{6F49}\x{6F4B}\x{6F4C}\x{6F4D}\x{6F4E}' . + '\x{6F4F}\x{6F50}\x{6F51}\x{6F52}\x{6F53}\x{6F54}\x{6F55}\x{6F56}\x{6F57}' . + '\x{6F58}\x{6F59}\x{6F5A}\x{6F5B}\x{6F5C}\x{6F5D}\x{6F5E}\x{6F5F}\x{6F60}' . + '\x{6F61}\x{6F62}\x{6F63}\x{6F64}\x{6F65}\x{6F66}\x{6F67}\x{6F68}\x{6F69}' . + '\x{6F6A}\x{6F6B}\x{6F6C}\x{6F6D}\x{6F6E}\x{6F6F}\x{6F70}\x{6F71}\x{6F72}' . + '\x{6F73}\x{6F74}\x{6F75}\x{6F76}\x{6F77}\x{6F78}\x{6F7A}\x{6F7B}\x{6F7C}' . + '\x{6F7D}\x{6F7E}\x{6F7F}\x{6F80}\x{6F81}\x{6F82}\x{6F83}\x{6F84}\x{6F85}' . + '\x{6F86}\x{6F87}\x{6F88}\x{6F89}\x{6F8A}\x{6F8B}\x{6F8C}\x{6F8D}\x{6F8E}' . + '\x{6F8F}\x{6F90}\x{6F91}\x{6F92}\x{6F93}\x{6F94}\x{6F95}\x{6F96}\x{6F97}' . + '\x{6F99}\x{6F9B}\x{6F9C}\x{6F9D}\x{6F9E}\x{6FA0}\x{6FA1}\x{6FA2}\x{6FA3}' . + '\x{6FA4}\x{6FA5}\x{6FA6}\x{6FA7}\x{6FA8}\x{6FA9}\x{6FAA}\x{6FAB}\x{6FAC}' . + '\x{6FAD}\x{6FAE}\x{6FAF}\x{6FB0}\x{6FB1}\x{6FB2}\x{6FB3}\x{6FB4}\x{6FB5}' . + '\x{6FB6}\x{6FB8}\x{6FB9}\x{6FBA}\x{6FBB}\x{6FBC}\x{6FBD}\x{6FBE}\x{6FBF}' . + '\x{6FC0}\x{6FC1}\x{6FC2}\x{6FC3}\x{6FC4}\x{6FC6}\x{6FC7}\x{6FC8}\x{6FC9}' . + '\x{6FCA}\x{6FCB}\x{6FCC}\x{6FCD}\x{6FCE}\x{6FCF}\x{6FD1}\x{6FD2}\x{6FD4}' . + '\x{6FD5}\x{6FD6}\x{6FD7}\x{6FD8}\x{6FD9}\x{6FDA}\x{6FDB}\x{6FDC}\x{6FDD}' . + '\x{6FDE}\x{6FDF}\x{6FE0}\x{6FE1}\x{6FE2}\x{6FE3}\x{6FE4}\x{6FE5}\x{6FE6}' . + '\x{6FE7}\x{6FE8}\x{6FE9}\x{6FEA}\x{6FEB}\x{6FEC}\x{6FED}\x{6FEE}\x{6FEF}' . + '\x{6FF0}\x{6FF1}\x{6FF2}\x{6FF3}\x{6FF4}\x{6FF6}\x{6FF7}\x{6FF8}\x{6FF9}' . + '\x{6FFA}\x{6FFB}\x{6FFC}\x{6FFE}\x{6FFF}\x{7000}\x{7001}\x{7002}\x{7003}' . + '\x{7004}\x{7005}\x{7006}\x{7007}\x{7008}\x{7009}\x{700A}\x{700B}\x{700C}' . + '\x{700D}\x{700E}\x{700F}\x{7011}\x{7012}\x{7014}\x{7015}\x{7016}\x{7017}' . + '\x{7018}\x{7019}\x{701A}\x{701B}\x{701C}\x{701D}\x{701F}\x{7020}\x{7021}' . + '\x{7022}\x{7023}\x{7024}\x{7025}\x{7026}\x{7027}\x{7028}\x{7029}\x{702A}' . + '\x{702B}\x{702C}\x{702D}\x{702E}\x{702F}\x{7030}\x{7031}\x{7032}\x{7033}' . + '\x{7034}\x{7035}\x{7036}\x{7037}\x{7038}\x{7039}\x{703A}\x{703B}\x{703C}' . + '\x{703D}\x{703E}\x{703F}\x{7040}\x{7041}\x{7042}\x{7043}\x{7044}\x{7045}' . + '\x{7046}\x{7048}\x{7049}\x{704A}\x{704C}\x{704D}\x{704F}\x{7050}\x{7051}' . + '\x{7052}\x{7053}\x{7054}\x{7055}\x{7056}\x{7057}\x{7058}\x{7059}\x{705A}' . + '\x{705B}\x{705C}\x{705D}\x{705E}\x{705F}\x{7060}\x{7061}\x{7062}\x{7063}' . + '\x{7064}\x{7065}\x{7066}\x{7067}\x{7068}\x{7069}\x{706A}\x{706B}\x{706C}' . + '\x{706D}\x{706E}\x{706F}\x{7070}\x{7071}\x{7074}\x{7075}\x{7076}\x{7077}' . + '\x{7078}\x{7079}\x{707A}\x{707C}\x{707D}\x{707E}\x{707F}\x{7080}\x{7082}' . + '\x{7083}\x{7084}\x{7085}\x{7086}\x{7087}\x{7088}\x{7089}\x{708A}\x{708B}' . + '\x{708C}\x{708E}\x{708F}\x{7090}\x{7091}\x{7092}\x{7093}\x{7094}\x{7095}' . + '\x{7096}\x{7098}\x{7099}\x{709A}\x{709C}\x{709D}\x{709E}\x{709F}\x{70A0}' . + '\x{70A1}\x{70A2}\x{70A3}\x{70A4}\x{70A5}\x{70A6}\x{70A7}\x{70A8}\x{70A9}' . + '\x{70AB}\x{70AC}\x{70AD}\x{70AE}\x{70AF}\x{70B0}\x{70B1}\x{70B3}\x{70B4}' . + '\x{70B5}\x{70B7}\x{70B8}\x{70B9}\x{70BA}\x{70BB}\x{70BC}\x{70BD}\x{70BE}' . + '\x{70BF}\x{70C0}\x{70C1}\x{70C2}\x{70C3}\x{70C4}\x{70C5}\x{70C6}\x{70C7}' . + '\x{70C8}\x{70C9}\x{70CA}\x{70CB}\x{70CC}\x{70CD}\x{70CE}\x{70CF}\x{70D0}' . + '\x{70D1}\x{70D2}\x{70D3}\x{70D4}\x{70D6}\x{70D7}\x{70D8}\x{70D9}\x{70DA}' . + '\x{70DB}\x{70DC}\x{70DD}\x{70DE}\x{70DF}\x{70E0}\x{70E1}\x{70E2}\x{70E3}' . + '\x{70E4}\x{70E5}\x{70E6}\x{70E7}\x{70E8}\x{70E9}\x{70EA}\x{70EB}\x{70EC}' . + '\x{70ED}\x{70EE}\x{70EF}\x{70F0}\x{70F1}\x{70F2}\x{70F3}\x{70F4}\x{70F5}' . + '\x{70F6}\x{70F7}\x{70F8}\x{70F9}\x{70FA}\x{70FB}\x{70FC}\x{70FD}\x{70FF}' . + '\x{7100}\x{7101}\x{7102}\x{7103}\x{7104}\x{7105}\x{7106}\x{7107}\x{7109}' . + '\x{710A}\x{710B}\x{710C}\x{710D}\x{710E}\x{710F}\x{7110}\x{7111}\x{7112}' . + '\x{7113}\x{7115}\x{7116}\x{7117}\x{7118}\x{7119}\x{711A}\x{711B}\x{711C}' . + '\x{711D}\x{711E}\x{711F}\x{7120}\x{7121}\x{7122}\x{7123}\x{7125}\x{7126}' . + '\x{7127}\x{7128}\x{7129}\x{712A}\x{712B}\x{712C}\x{712D}\x{712E}\x{712F}' . + '\x{7130}\x{7131}\x{7132}\x{7135}\x{7136}\x{7137}\x{7138}\x{7139}\x{713A}' . + '\x{713B}\x{713D}\x{713E}\x{713F}\x{7140}\x{7141}\x{7142}\x{7143}\x{7144}' . + '\x{7145}\x{7146}\x{7147}\x{7148}\x{7149}\x{714A}\x{714B}\x{714C}\x{714D}' . + '\x{714E}\x{714F}\x{7150}\x{7151}\x{7152}\x{7153}\x{7154}\x{7156}\x{7158}' . + '\x{7159}\x{715A}\x{715B}\x{715C}\x{715D}\x{715E}\x{715F}\x{7160}\x{7161}' . + '\x{7162}\x{7163}\x{7164}\x{7165}\x{7166}\x{7167}\x{7168}\x{7169}\x{716A}' . + '\x{716C}\x{716E}\x{716F}\x{7170}\x{7171}\x{7172}\x{7173}\x{7174}\x{7175}' . + '\x{7176}\x{7177}\x{7178}\x{7179}\x{717A}\x{717B}\x{717C}\x{717D}\x{717E}' . + '\x{717F}\x{7180}\x{7181}\x{7182}\x{7183}\x{7184}\x{7185}\x{7186}\x{7187}' . + '\x{7188}\x{7189}\x{718A}\x{718B}\x{718C}\x{718E}\x{718F}\x{7190}\x{7191}' . + '\x{7192}\x{7193}\x{7194}\x{7195}\x{7197}\x{7198}\x{7199}\x{719A}\x{719B}' . + '\x{719C}\x{719D}\x{719E}\x{719F}\x{71A0}\x{71A1}\x{71A2}\x{71A3}\x{71A4}' . + '\x{71A5}\x{71A7}\x{71A8}\x{71A9}\x{71AA}\x{71AC}\x{71AD}\x{71AE}\x{71AF}' . + '\x{71B0}\x{71B1}\x{71B2}\x{71B3}\x{71B4}\x{71B5}\x{71B7}\x{71B8}\x{71B9}' . + '\x{71BA}\x{71BB}\x{71BC}\x{71BD}\x{71BE}\x{71BF}\x{71C0}\x{71C1}\x{71C2}' . + '\x{71C3}\x{71C4}\x{71C5}\x{71C6}\x{71C7}\x{71C8}\x{71C9}\x{71CA}\x{71CB}' . + '\x{71CD}\x{71CE}\x{71CF}\x{71D0}\x{71D1}\x{71D2}\x{71D4}\x{71D5}\x{71D6}' . + '\x{71D7}\x{71D8}\x{71D9}\x{71DA}\x{71DB}\x{71DC}\x{71DD}\x{71DE}\x{71DF}' . + '\x{71E0}\x{71E1}\x{71E2}\x{71E3}\x{71E4}\x{71E5}\x{71E6}\x{71E7}\x{71E8}' . + '\x{71E9}\x{71EA}\x{71EB}\x{71EC}\x{71ED}\x{71EE}\x{71EF}\x{71F0}\x{71F1}' . + '\x{71F2}\x{71F4}\x{71F5}\x{71F6}\x{71F7}\x{71F8}\x{71F9}\x{71FB}\x{71FC}' . + '\x{71FD}\x{71FE}\x{71FF}\x{7201}\x{7202}\x{7203}\x{7204}\x{7205}\x{7206}' . + '\x{7207}\x{7208}\x{7209}\x{720A}\x{720C}\x{720D}\x{720E}\x{720F}\x{7210}' . + '\x{7212}\x{7213}\x{7214}\x{7216}\x{7218}\x{7219}\x{721A}\x{721B}\x{721C}' . + '\x{721D}\x{721E}\x{721F}\x{7221}\x{7222}\x{7223}\x{7226}\x{7227}\x{7228}' . + '\x{7229}\x{722A}\x{722B}\x{722C}\x{722D}\x{722E}\x{7230}\x{7231}\x{7232}' . + '\x{7233}\x{7235}\x{7236}\x{7237}\x{7238}\x{7239}\x{723A}\x{723B}\x{723C}' . + '\x{723D}\x{723E}\x{723F}\x{7240}\x{7241}\x{7242}\x{7243}\x{7244}\x{7246}' . + '\x{7247}\x{7248}\x{7249}\x{724A}\x{724B}\x{724C}\x{724D}\x{724F}\x{7251}' . + '\x{7252}\x{7253}\x{7254}\x{7256}\x{7257}\x{7258}\x{7259}\x{725A}\x{725B}' . + '\x{725C}\x{725D}\x{725E}\x{725F}\x{7260}\x{7261}\x{7262}\x{7263}\x{7264}' . + '\x{7265}\x{7266}\x{7267}\x{7268}\x{7269}\x{726A}\x{726B}\x{726C}\x{726D}' . + '\x{726E}\x{726F}\x{7270}\x{7271}\x{7272}\x{7273}\x{7274}\x{7275}\x{7276}' . + '\x{7277}\x{7278}\x{7279}\x{727A}\x{727B}\x{727C}\x{727D}\x{727E}\x{727F}' . + '\x{7280}\x{7281}\x{7282}\x{7283}\x{7284}\x{7285}\x{7286}\x{7287}\x{7288}' . + '\x{7289}\x{728A}\x{728B}\x{728C}\x{728D}\x{728E}\x{728F}\x{7290}\x{7291}' . + '\x{7292}\x{7293}\x{7294}\x{7295}\x{7296}\x{7297}\x{7298}\x{7299}\x{729A}' . + '\x{729B}\x{729C}\x{729D}\x{729E}\x{729F}\x{72A1}\x{72A2}\x{72A3}\x{72A4}' . + '\x{72A5}\x{72A6}\x{72A7}\x{72A8}\x{72A9}\x{72AA}\x{72AC}\x{72AD}\x{72AE}' . + '\x{72AF}\x{72B0}\x{72B1}\x{72B2}\x{72B3}\x{72B4}\x{72B5}\x{72B6}\x{72B7}' . + '\x{72B8}\x{72B9}\x{72BA}\x{72BB}\x{72BC}\x{72BD}\x{72BF}\x{72C0}\x{72C1}' . + '\x{72C2}\x{72C3}\x{72C4}\x{72C5}\x{72C6}\x{72C7}\x{72C8}\x{72C9}\x{72CA}' . + '\x{72CB}\x{72CC}\x{72CD}\x{72CE}\x{72CF}\x{72D0}\x{72D1}\x{72D2}\x{72D3}' . + '\x{72D4}\x{72D5}\x{72D6}\x{72D7}\x{72D8}\x{72D9}\x{72DA}\x{72DB}\x{72DC}' . + '\x{72DD}\x{72DE}\x{72DF}\x{72E0}\x{72E1}\x{72E2}\x{72E3}\x{72E4}\x{72E5}' . + '\x{72E6}\x{72E7}\x{72E8}\x{72E9}\x{72EA}\x{72EB}\x{72EC}\x{72ED}\x{72EE}' . + '\x{72EF}\x{72F0}\x{72F1}\x{72F2}\x{72F3}\x{72F4}\x{72F5}\x{72F6}\x{72F7}' . + '\x{72F8}\x{72F9}\x{72FA}\x{72FB}\x{72FC}\x{72FD}\x{72FE}\x{72FF}\x{7300}' . + '\x{7301}\x{7303}\x{7304}\x{7305}\x{7306}\x{7307}\x{7308}\x{7309}\x{730A}' . + '\x{730B}\x{730C}\x{730D}\x{730E}\x{730F}\x{7311}\x{7312}\x{7313}\x{7314}' . + '\x{7315}\x{7316}\x{7317}\x{7318}\x{7319}\x{731A}\x{731B}\x{731C}\x{731D}' . + '\x{731E}\x{7320}\x{7321}\x{7322}\x{7323}\x{7324}\x{7325}\x{7326}\x{7327}' . + '\x{7329}\x{732A}\x{732B}\x{732C}\x{732D}\x{732E}\x{7330}\x{7331}\x{7332}' . + '\x{7333}\x{7334}\x{7335}\x{7336}\x{7337}\x{7338}\x{7339}\x{733A}\x{733B}' . + '\x{733C}\x{733D}\x{733E}\x{733F}\x{7340}\x{7341}\x{7342}\x{7343}\x{7344}' . + '\x{7345}\x{7346}\x{7347}\x{7348}\x{7349}\x{734A}\x{734B}\x{734C}\x{734D}' . + '\x{734E}\x{7350}\x{7351}\x{7352}\x{7354}\x{7355}\x{7356}\x{7357}\x{7358}' . + '\x{7359}\x{735A}\x{735B}\x{735C}\x{735D}\x{735E}\x{735F}\x{7360}\x{7361}' . + '\x{7362}\x{7364}\x{7365}\x{7366}\x{7367}\x{7368}\x{7369}\x{736A}\x{736B}' . + '\x{736C}\x{736D}\x{736E}\x{736F}\x{7370}\x{7371}\x{7372}\x{7373}\x{7374}' . + '\x{7375}\x{7376}\x{7377}\x{7378}\x{7379}\x{737A}\x{737B}\x{737C}\x{737D}' . + '\x{737E}\x{737F}\x{7380}\x{7381}\x{7382}\x{7383}\x{7384}\x{7385}\x{7386}' . + '\x{7387}\x{7388}\x{7389}\x{738A}\x{738B}\x{738C}\x{738D}\x{738E}\x{738F}' . + '\x{7390}\x{7391}\x{7392}\x{7393}\x{7394}\x{7395}\x{7396}\x{7397}\x{7398}' . + '\x{7399}\x{739A}\x{739B}\x{739D}\x{739E}\x{739F}\x{73A0}\x{73A1}\x{73A2}' . + '\x{73A3}\x{73A4}\x{73A5}\x{73A6}\x{73A7}\x{73A8}\x{73A9}\x{73AA}\x{73AB}' . + '\x{73AC}\x{73AD}\x{73AE}\x{73AF}\x{73B0}\x{73B1}\x{73B2}\x{73B3}\x{73B4}' . + '\x{73B5}\x{73B6}\x{73B7}\x{73B8}\x{73B9}\x{73BA}\x{73BB}\x{73BC}\x{73BD}' . + '\x{73BE}\x{73BF}\x{73C0}\x{73C2}\x{73C3}\x{73C4}\x{73C5}\x{73C6}\x{73C7}' . + '\x{73C8}\x{73C9}\x{73CA}\x{73CB}\x{73CC}\x{73CD}\x{73CE}\x{73CF}\x{73D0}' . + '\x{73D1}\x{73D2}\x{73D3}\x{73D4}\x{73D5}\x{73D6}\x{73D7}\x{73D8}\x{73D9}' . + '\x{73DA}\x{73DB}\x{73DC}\x{73DD}\x{73DE}\x{73DF}\x{73E0}\x{73E2}\x{73E3}' . + '\x{73E5}\x{73E6}\x{73E7}\x{73E8}\x{73E9}\x{73EA}\x{73EB}\x{73EC}\x{73ED}' . + '\x{73EE}\x{73EF}\x{73F0}\x{73F1}\x{73F2}\x{73F4}\x{73F5}\x{73F6}\x{73F7}' . + '\x{73F8}\x{73F9}\x{73FA}\x{73FC}\x{73FD}\x{73FE}\x{73FF}\x{7400}\x{7401}' . + '\x{7402}\x{7403}\x{7404}\x{7405}\x{7406}\x{7407}\x{7408}\x{7409}\x{740A}' . + '\x{740B}\x{740C}\x{740D}\x{740E}\x{740F}\x{7410}\x{7411}\x{7412}\x{7413}' . + '\x{7414}\x{7415}\x{7416}\x{7417}\x{7419}\x{741A}\x{741B}\x{741C}\x{741D}' . + '\x{741E}\x{741F}\x{7420}\x{7421}\x{7422}\x{7423}\x{7424}\x{7425}\x{7426}' . + '\x{7427}\x{7428}\x{7429}\x{742A}\x{742B}\x{742C}\x{742D}\x{742E}\x{742F}' . + '\x{7430}\x{7431}\x{7432}\x{7433}\x{7434}\x{7435}\x{7436}\x{7437}\x{7438}' . + '\x{743A}\x{743B}\x{743C}\x{743D}\x{743F}\x{7440}\x{7441}\x{7442}\x{7443}' . + '\x{7444}\x{7445}\x{7446}\x{7448}\x{744A}\x{744B}\x{744C}\x{744D}\x{744E}' . + '\x{744F}\x{7450}\x{7451}\x{7452}\x{7453}\x{7454}\x{7455}\x{7456}\x{7457}' . + '\x{7459}\x{745A}\x{745B}\x{745C}\x{745D}\x{745E}\x{745F}\x{7461}\x{7462}' . + '\x{7463}\x{7464}\x{7465}\x{7466}\x{7467}\x{7468}\x{7469}\x{746A}\x{746B}' . + '\x{746C}\x{746D}\x{746E}\x{746F}\x{7470}\x{7471}\x{7472}\x{7473}\x{7474}' . + '\x{7475}\x{7476}\x{7477}\x{7478}\x{7479}\x{747A}\x{747C}\x{747D}\x{747E}' . + '\x{747F}\x{7480}\x{7481}\x{7482}\x{7483}\x{7485}\x{7486}\x{7487}\x{7488}' . + '\x{7489}\x{748A}\x{748B}\x{748C}\x{748D}\x{748E}\x{748F}\x{7490}\x{7491}' . + '\x{7492}\x{7493}\x{7494}\x{7495}\x{7497}\x{7498}\x{7499}\x{749A}\x{749B}' . + '\x{749C}\x{749E}\x{749F}\x{74A0}\x{74A1}\x{74A3}\x{74A4}\x{74A5}\x{74A6}' . + '\x{74A7}\x{74A8}\x{74A9}\x{74AA}\x{74AB}\x{74AC}\x{74AD}\x{74AE}\x{74AF}' . + '\x{74B0}\x{74B1}\x{74B2}\x{74B3}\x{74B4}\x{74B5}\x{74B6}\x{74B7}\x{74B8}' . + '\x{74B9}\x{74BA}\x{74BB}\x{74BC}\x{74BD}\x{74BE}\x{74BF}\x{74C0}\x{74C1}' . + '\x{74C2}\x{74C3}\x{74C4}\x{74C5}\x{74C6}\x{74CA}\x{74CB}\x{74CD}\x{74CE}' . + '\x{74CF}\x{74D0}\x{74D1}\x{74D2}\x{74D3}\x{74D4}\x{74D5}\x{74D6}\x{74D7}' . + '\x{74D8}\x{74D9}\x{74DA}\x{74DB}\x{74DC}\x{74DD}\x{74DE}\x{74DF}\x{74E0}' . + '\x{74E1}\x{74E2}\x{74E3}\x{74E4}\x{74E5}\x{74E6}\x{74E7}\x{74E8}\x{74E9}' . + '\x{74EA}\x{74EC}\x{74ED}\x{74EE}\x{74EF}\x{74F0}\x{74F1}\x{74F2}\x{74F3}' . + '\x{74F4}\x{74F5}\x{74F6}\x{74F7}\x{74F8}\x{74F9}\x{74FA}\x{74FB}\x{74FC}' . + '\x{74FD}\x{74FE}\x{74FF}\x{7500}\x{7501}\x{7502}\x{7503}\x{7504}\x{7505}' . + '\x{7506}\x{7507}\x{7508}\x{7509}\x{750A}\x{750B}\x{750C}\x{750D}\x{750F}' . + '\x{7510}\x{7511}\x{7512}\x{7513}\x{7514}\x{7515}\x{7516}\x{7517}\x{7518}' . + '\x{7519}\x{751A}\x{751B}\x{751C}\x{751D}\x{751E}\x{751F}\x{7521}\x{7522}' . + '\x{7523}\x{7524}\x{7525}\x{7526}\x{7527}\x{7528}\x{7529}\x{752A}\x{752B}' . + '\x{752C}\x{752D}\x{752E}\x{752F}\x{7530}\x{7531}\x{7532}\x{7533}\x{7535}' . + '\x{7536}\x{7537}\x{7538}\x{7539}\x{753A}\x{753B}\x{753C}\x{753D}\x{753E}' . + '\x{753F}\x{7540}\x{7542}\x{7543}\x{7544}\x{7545}\x{7546}\x{7547}\x{7548}' . + '\x{7549}\x{754B}\x{754C}\x{754D}\x{754E}\x{754F}\x{7550}\x{7551}\x{7553}' . + '\x{7554}\x{7556}\x{7557}\x{7558}\x{7559}\x{755A}\x{755B}\x{755C}\x{755D}' . + '\x{755F}\x{7560}\x{7562}\x{7563}\x{7564}\x{7565}\x{7566}\x{7567}\x{7568}' . + '\x{7569}\x{756A}\x{756B}\x{756C}\x{756D}\x{756E}\x{756F}\x{7570}\x{7572}' . + '\x{7574}\x{7575}\x{7576}\x{7577}\x{7578}\x{7579}\x{757C}\x{757D}\x{757E}' . + '\x{757F}\x{7580}\x{7581}\x{7582}\x{7583}\x{7584}\x{7586}\x{7587}\x{7588}' . + '\x{7589}\x{758A}\x{758B}\x{758C}\x{758D}\x{758F}\x{7590}\x{7591}\x{7592}' . + '\x{7593}\x{7594}\x{7595}\x{7596}\x{7597}\x{7598}\x{7599}\x{759A}\x{759B}' . + '\x{759C}\x{759D}\x{759E}\x{759F}\x{75A0}\x{75A1}\x{75A2}\x{75A3}\x{75A4}' . + '\x{75A5}\x{75A6}\x{75A7}\x{75A8}\x{75AA}\x{75AB}\x{75AC}\x{75AD}\x{75AE}' . + '\x{75AF}\x{75B0}\x{75B1}\x{75B2}\x{75B3}\x{75B4}\x{75B5}\x{75B6}\x{75B8}' . + '\x{75B9}\x{75BA}\x{75BB}\x{75BC}\x{75BD}\x{75BE}\x{75BF}\x{75C0}\x{75C1}' . + '\x{75C2}\x{75C3}\x{75C4}\x{75C5}\x{75C6}\x{75C7}\x{75C8}\x{75C9}\x{75CA}' . + '\x{75CB}\x{75CC}\x{75CD}\x{75CE}\x{75CF}\x{75D0}\x{75D1}\x{75D2}\x{75D3}' . + '\x{75D4}\x{75D5}\x{75D6}\x{75D7}\x{75D8}\x{75D9}\x{75DA}\x{75DB}\x{75DD}' . + '\x{75DE}\x{75DF}\x{75E0}\x{75E1}\x{75E2}\x{75E3}\x{75E4}\x{75E5}\x{75E6}' . + '\x{75E7}\x{75E8}\x{75EA}\x{75EB}\x{75EC}\x{75ED}\x{75EF}\x{75F0}\x{75F1}' . + '\x{75F2}\x{75F3}\x{75F4}\x{75F5}\x{75F6}\x{75F7}\x{75F8}\x{75F9}\x{75FA}' . + '\x{75FB}\x{75FC}\x{75FD}\x{75FE}\x{75FF}\x{7600}\x{7601}\x{7602}\x{7603}' . + '\x{7604}\x{7605}\x{7606}\x{7607}\x{7608}\x{7609}\x{760A}\x{760B}\x{760C}' . + '\x{760D}\x{760E}\x{760F}\x{7610}\x{7611}\x{7612}\x{7613}\x{7614}\x{7615}' . + '\x{7616}\x{7617}\x{7618}\x{7619}\x{761A}\x{761B}\x{761C}\x{761D}\x{761E}' . + '\x{761F}\x{7620}\x{7621}\x{7622}\x{7623}\x{7624}\x{7625}\x{7626}\x{7627}' . + '\x{7628}\x{7629}\x{762A}\x{762B}\x{762D}\x{762E}\x{762F}\x{7630}\x{7631}' . + '\x{7632}\x{7633}\x{7634}\x{7635}\x{7636}\x{7637}\x{7638}\x{7639}\x{763A}' . + '\x{763B}\x{763C}\x{763D}\x{763E}\x{763F}\x{7640}\x{7641}\x{7642}\x{7643}' . + '\x{7646}\x{7647}\x{7648}\x{7649}\x{764A}\x{764B}\x{764C}\x{764D}\x{764F}' . + '\x{7650}\x{7652}\x{7653}\x{7654}\x{7656}\x{7657}\x{7658}\x{7659}\x{765A}' . + '\x{765B}\x{765C}\x{765D}\x{765E}\x{765F}\x{7660}\x{7661}\x{7662}\x{7663}' . + '\x{7664}\x{7665}\x{7666}\x{7667}\x{7668}\x{7669}\x{766A}\x{766B}\x{766C}' . + '\x{766D}\x{766E}\x{766F}\x{7670}\x{7671}\x{7672}\x{7674}\x{7675}\x{7676}' . + '\x{7677}\x{7678}\x{7679}\x{767B}\x{767C}\x{767D}\x{767E}\x{767F}\x{7680}' . + '\x{7681}\x{7682}\x{7683}\x{7684}\x{7685}\x{7686}\x{7687}\x{7688}\x{7689}' . + '\x{768A}\x{768B}\x{768C}\x{768E}\x{768F}\x{7690}\x{7691}\x{7692}\x{7693}' . + '\x{7694}\x{7695}\x{7696}\x{7697}\x{7698}\x{7699}\x{769A}\x{769B}\x{769C}' . + '\x{769D}\x{769E}\x{769F}\x{76A0}\x{76A3}\x{76A4}\x{76A6}\x{76A7}\x{76A9}' . + '\x{76AA}\x{76AB}\x{76AC}\x{76AD}\x{76AE}\x{76AF}\x{76B0}\x{76B1}\x{76B2}' . + '\x{76B4}\x{76B5}\x{76B7}\x{76B8}\x{76BA}\x{76BB}\x{76BC}\x{76BD}\x{76BE}' . + '\x{76BF}\x{76C0}\x{76C2}\x{76C3}\x{76C4}\x{76C5}\x{76C6}\x{76C7}\x{76C8}' . + '\x{76C9}\x{76CA}\x{76CD}\x{76CE}\x{76CF}\x{76D0}\x{76D1}\x{76D2}\x{76D3}' . + '\x{76D4}\x{76D5}\x{76D6}\x{76D7}\x{76D8}\x{76DA}\x{76DB}\x{76DC}\x{76DD}' . + '\x{76DE}\x{76DF}\x{76E0}\x{76E1}\x{76E2}\x{76E3}\x{76E4}\x{76E5}\x{76E6}' . + '\x{76E7}\x{76E8}\x{76E9}\x{76EA}\x{76EC}\x{76ED}\x{76EE}\x{76EF}\x{76F0}' . + '\x{76F1}\x{76F2}\x{76F3}\x{76F4}\x{76F5}\x{76F6}\x{76F7}\x{76F8}\x{76F9}' . + '\x{76FA}\x{76FB}\x{76FC}\x{76FD}\x{76FE}\x{76FF}\x{7701}\x{7703}\x{7704}' . + '\x{7705}\x{7706}\x{7707}\x{7708}\x{7709}\x{770A}\x{770B}\x{770C}\x{770D}' . + '\x{770F}\x{7710}\x{7711}\x{7712}\x{7713}\x{7714}\x{7715}\x{7716}\x{7717}' . + '\x{7718}\x{7719}\x{771A}\x{771B}\x{771C}\x{771D}\x{771E}\x{771F}\x{7720}' . + '\x{7722}\x{7723}\x{7725}\x{7726}\x{7727}\x{7728}\x{7729}\x{772A}\x{772C}' . + '\x{772D}\x{772E}\x{772F}\x{7730}\x{7731}\x{7732}\x{7733}\x{7734}\x{7735}' . + '\x{7736}\x{7737}\x{7738}\x{7739}\x{773A}\x{773B}\x{773C}\x{773D}\x{773E}' . + '\x{7740}\x{7741}\x{7743}\x{7744}\x{7745}\x{7746}\x{7747}\x{7748}\x{7749}' . + '\x{774A}\x{774B}\x{774C}\x{774D}\x{774E}\x{774F}\x{7750}\x{7751}\x{7752}' . + '\x{7753}\x{7754}\x{7755}\x{7756}\x{7757}\x{7758}\x{7759}\x{775A}\x{775B}' . + '\x{775C}\x{775D}\x{775E}\x{775F}\x{7760}\x{7761}\x{7762}\x{7763}\x{7765}' . + '\x{7766}\x{7767}\x{7768}\x{7769}\x{776A}\x{776B}\x{776C}\x{776D}\x{776E}' . + '\x{776F}\x{7770}\x{7771}\x{7772}\x{7773}\x{7774}\x{7775}\x{7776}\x{7777}' . + '\x{7778}\x{7779}\x{777A}\x{777B}\x{777C}\x{777D}\x{777E}\x{777F}\x{7780}' . + '\x{7781}\x{7782}\x{7783}\x{7784}\x{7785}\x{7786}\x{7787}\x{7788}\x{7789}' . + '\x{778A}\x{778B}\x{778C}\x{778D}\x{778E}\x{778F}\x{7790}\x{7791}\x{7792}' . + '\x{7793}\x{7794}\x{7795}\x{7797}\x{7798}\x{7799}\x{779A}\x{779B}\x{779C}' . + '\x{779D}\x{779E}\x{779F}\x{77A0}\x{77A1}\x{77A2}\x{77A3}\x{77A5}\x{77A6}' . + '\x{77A7}\x{77A8}\x{77A9}\x{77AA}\x{77AB}\x{77AC}\x{77AD}\x{77AE}\x{77AF}' . + '\x{77B0}\x{77B1}\x{77B2}\x{77B3}\x{77B4}\x{77B5}\x{77B6}\x{77B7}\x{77B8}' . + '\x{77B9}\x{77BA}\x{77BB}\x{77BC}\x{77BD}\x{77BF}\x{77C0}\x{77C2}\x{77C3}' . + '\x{77C4}\x{77C5}\x{77C6}\x{77C7}\x{77C8}\x{77C9}\x{77CA}\x{77CB}\x{77CC}' . + '\x{77CD}\x{77CE}\x{77CF}\x{77D0}\x{77D1}\x{77D3}\x{77D4}\x{77D5}\x{77D6}' . + '\x{77D7}\x{77D8}\x{77D9}\x{77DA}\x{77DB}\x{77DC}\x{77DE}\x{77DF}\x{77E0}' . + '\x{77E1}\x{77E2}\x{77E3}\x{77E5}\x{77E7}\x{77E8}\x{77E9}\x{77EA}\x{77EB}' . + '\x{77EC}\x{77ED}\x{77EE}\x{77EF}\x{77F0}\x{77F1}\x{77F2}\x{77F3}\x{77F6}' . + '\x{77F7}\x{77F8}\x{77F9}\x{77FA}\x{77FB}\x{77FC}\x{77FD}\x{77FE}\x{77FF}' . + '\x{7800}\x{7801}\x{7802}\x{7803}\x{7804}\x{7805}\x{7806}\x{7808}\x{7809}' . + '\x{780A}\x{780B}\x{780C}\x{780D}\x{780E}\x{780F}\x{7810}\x{7811}\x{7812}' . + '\x{7813}\x{7814}\x{7815}\x{7816}\x{7817}\x{7818}\x{7819}\x{781A}\x{781B}' . + '\x{781C}\x{781D}\x{781E}\x{781F}\x{7820}\x{7821}\x{7822}\x{7823}\x{7825}' . + '\x{7826}\x{7827}\x{7828}\x{7829}\x{782A}\x{782B}\x{782C}\x{782D}\x{782E}' . + '\x{782F}\x{7830}\x{7831}\x{7832}\x{7833}\x{7834}\x{7835}\x{7837}\x{7838}' . + '\x{7839}\x{783A}\x{783B}\x{783C}\x{783D}\x{783E}\x{7840}\x{7841}\x{7843}' . + '\x{7844}\x{7845}\x{7847}\x{7848}\x{7849}\x{784A}\x{784C}\x{784D}\x{784E}' . + '\x{7850}\x{7851}\x{7852}\x{7853}\x{7854}\x{7855}\x{7856}\x{7857}\x{7858}' . + '\x{7859}\x{785A}\x{785B}\x{785C}\x{785D}\x{785E}\x{785F}\x{7860}\x{7861}' . + '\x{7862}\x{7863}\x{7864}\x{7865}\x{7866}\x{7867}\x{7868}\x{7869}\x{786A}' . + '\x{786B}\x{786C}\x{786D}\x{786E}\x{786F}\x{7870}\x{7871}\x{7872}\x{7873}' . + '\x{7874}\x{7875}\x{7877}\x{7878}\x{7879}\x{787A}\x{787B}\x{787C}\x{787D}' . + '\x{787E}\x{787F}\x{7880}\x{7881}\x{7882}\x{7883}\x{7884}\x{7885}\x{7886}' . + '\x{7887}\x{7889}\x{788A}\x{788B}\x{788C}\x{788D}\x{788E}\x{788F}\x{7890}' . + '\x{7891}\x{7892}\x{7893}\x{7894}\x{7895}\x{7896}\x{7897}\x{7898}\x{7899}' . + '\x{789A}\x{789B}\x{789C}\x{789D}\x{789E}\x{789F}\x{78A0}\x{78A1}\x{78A2}' . + '\x{78A3}\x{78A4}\x{78A5}\x{78A6}\x{78A7}\x{78A8}\x{78A9}\x{78AA}\x{78AB}' . + '\x{78AC}\x{78AD}\x{78AE}\x{78AF}\x{78B0}\x{78B1}\x{78B2}\x{78B3}\x{78B4}' . + '\x{78B5}\x{78B6}\x{78B7}\x{78B8}\x{78B9}\x{78BA}\x{78BB}\x{78BC}\x{78BD}' . + '\x{78BE}\x{78BF}\x{78C0}\x{78C1}\x{78C3}\x{78C4}\x{78C5}\x{78C6}\x{78C8}' . + '\x{78C9}\x{78CA}\x{78CB}\x{78CC}\x{78CD}\x{78CE}\x{78CF}\x{78D0}\x{78D1}' . + '\x{78D3}\x{78D4}\x{78D5}\x{78D6}\x{78D7}\x{78D8}\x{78D9}\x{78DA}\x{78DB}' . + '\x{78DC}\x{78DD}\x{78DE}\x{78DF}\x{78E0}\x{78E1}\x{78E2}\x{78E3}\x{78E4}' . + '\x{78E5}\x{78E6}\x{78E7}\x{78E8}\x{78E9}\x{78EA}\x{78EB}\x{78EC}\x{78ED}' . + '\x{78EE}\x{78EF}\x{78F1}\x{78F2}\x{78F3}\x{78F4}\x{78F5}\x{78F6}\x{78F7}' . + '\x{78F9}\x{78FA}\x{78FB}\x{78FC}\x{78FD}\x{78FE}\x{78FF}\x{7901}\x{7902}' . + '\x{7903}\x{7904}\x{7905}\x{7906}\x{7907}\x{7909}\x{790A}\x{790B}\x{790C}' . + '\x{790E}\x{790F}\x{7910}\x{7911}\x{7912}\x{7913}\x{7914}\x{7916}\x{7917}' . + '\x{7918}\x{7919}\x{791A}\x{791B}\x{791C}\x{791D}\x{791E}\x{7921}\x{7922}' . + '\x{7923}\x{7924}\x{7925}\x{7926}\x{7927}\x{7928}\x{7929}\x{792A}\x{792B}' . + '\x{792C}\x{792D}\x{792E}\x{792F}\x{7930}\x{7931}\x{7933}\x{7934}\x{7935}' . + '\x{7937}\x{7938}\x{7939}\x{793A}\x{793B}\x{793C}\x{793D}\x{793E}\x{793F}' . + '\x{7940}\x{7941}\x{7942}\x{7943}\x{7944}\x{7945}\x{7946}\x{7947}\x{7948}' . + '\x{7949}\x{794A}\x{794B}\x{794C}\x{794D}\x{794E}\x{794F}\x{7950}\x{7951}' . + '\x{7952}\x{7953}\x{7954}\x{7955}\x{7956}\x{7957}\x{7958}\x{795A}\x{795B}' . + '\x{795C}\x{795D}\x{795E}\x{795F}\x{7960}\x{7961}\x{7962}\x{7963}\x{7964}' . + '\x{7965}\x{7966}\x{7967}\x{7968}\x{7969}\x{796A}\x{796B}\x{796D}\x{796F}' . + '\x{7970}\x{7971}\x{7972}\x{7973}\x{7974}\x{7977}\x{7978}\x{7979}\x{797A}' . + '\x{797B}\x{797C}\x{797D}\x{797E}\x{797F}\x{7980}\x{7981}\x{7982}\x{7983}' . + '\x{7984}\x{7985}\x{7988}\x{7989}\x{798A}\x{798B}\x{798C}\x{798D}\x{798E}' . + '\x{798F}\x{7990}\x{7991}\x{7992}\x{7993}\x{7994}\x{7995}\x{7996}\x{7997}' . + '\x{7998}\x{7999}\x{799A}\x{799B}\x{799C}\x{799F}\x{79A0}\x{79A1}\x{79A2}' . + '\x{79A3}\x{79A4}\x{79A5}\x{79A6}\x{79A7}\x{79A8}\x{79AA}\x{79AB}\x{79AC}' . + '\x{79AD}\x{79AE}\x{79AF}\x{79B0}\x{79B1}\x{79B2}\x{79B3}\x{79B4}\x{79B5}' . + '\x{79B6}\x{79B7}\x{79B8}\x{79B9}\x{79BA}\x{79BB}\x{79BD}\x{79BE}\x{79BF}' . + '\x{79C0}\x{79C1}\x{79C2}\x{79C3}\x{79C5}\x{79C6}\x{79C8}\x{79C9}\x{79CA}' . + '\x{79CB}\x{79CD}\x{79CE}\x{79CF}\x{79D0}\x{79D1}\x{79D2}\x{79D3}\x{79D5}' . + '\x{79D6}\x{79D8}\x{79D9}\x{79DA}\x{79DB}\x{79DC}\x{79DD}\x{79DE}\x{79DF}' . + '\x{79E0}\x{79E1}\x{79E2}\x{79E3}\x{79E4}\x{79E5}\x{79E6}\x{79E7}\x{79E8}' . + '\x{79E9}\x{79EA}\x{79EB}\x{79EC}\x{79ED}\x{79EE}\x{79EF}\x{79F0}\x{79F1}' . + '\x{79F2}\x{79F3}\x{79F4}\x{79F5}\x{79F6}\x{79F7}\x{79F8}\x{79F9}\x{79FA}' . + '\x{79FB}\x{79FC}\x{79FD}\x{79FE}\x{79FF}\x{7A00}\x{7A02}\x{7A03}\x{7A04}' . + '\x{7A05}\x{7A06}\x{7A08}\x{7A0A}\x{7A0B}\x{7A0C}\x{7A0D}\x{7A0E}\x{7A0F}' . + '\x{7A10}\x{7A11}\x{7A12}\x{7A13}\x{7A14}\x{7A15}\x{7A16}\x{7A17}\x{7A18}' . + '\x{7A19}\x{7A1A}\x{7A1B}\x{7A1C}\x{7A1D}\x{7A1E}\x{7A1F}\x{7A20}\x{7A21}' . + '\x{7A22}\x{7A23}\x{7A24}\x{7A25}\x{7A26}\x{7A27}\x{7A28}\x{7A29}\x{7A2A}' . + '\x{7A2B}\x{7A2D}\x{7A2E}\x{7A2F}\x{7A30}\x{7A31}\x{7A32}\x{7A33}\x{7A34}' . + '\x{7A35}\x{7A37}\x{7A39}\x{7A3B}\x{7A3C}\x{7A3D}\x{7A3E}\x{7A3F}\x{7A40}' . + '\x{7A41}\x{7A42}\x{7A43}\x{7A44}\x{7A45}\x{7A46}\x{7A47}\x{7A48}\x{7A49}' . + '\x{7A4A}\x{7A4B}\x{7A4C}\x{7A4D}\x{7A4E}\x{7A50}\x{7A51}\x{7A52}\x{7A53}' . + '\x{7A54}\x{7A55}\x{7A56}\x{7A57}\x{7A58}\x{7A59}\x{7A5A}\x{7A5B}\x{7A5C}' . + '\x{7A5D}\x{7A5E}\x{7A5F}\x{7A60}\x{7A61}\x{7A62}\x{7A65}\x{7A66}\x{7A67}' . + '\x{7A68}\x{7A69}\x{7A6B}\x{7A6C}\x{7A6D}\x{7A6E}\x{7A70}\x{7A71}\x{7A72}' . + '\x{7A73}\x{7A74}\x{7A75}\x{7A76}\x{7A77}\x{7A78}\x{7A79}\x{7A7A}\x{7A7B}' . + '\x{7A7C}\x{7A7D}\x{7A7E}\x{7A7F}\x{7A80}\x{7A81}\x{7A83}\x{7A84}\x{7A85}' . + '\x{7A86}\x{7A87}\x{7A88}\x{7A89}\x{7A8A}\x{7A8B}\x{7A8C}\x{7A8D}\x{7A8E}' . + '\x{7A8F}\x{7A90}\x{7A91}\x{7A92}\x{7A93}\x{7A94}\x{7A95}\x{7A96}\x{7A97}' . + '\x{7A98}\x{7A99}\x{7A9C}\x{7A9D}\x{7A9E}\x{7A9F}\x{7AA0}\x{7AA1}\x{7AA2}' . + '\x{7AA3}\x{7AA4}\x{7AA5}\x{7AA6}\x{7AA7}\x{7AA8}\x{7AA9}\x{7AAA}\x{7AAB}' . + '\x{7AAC}\x{7AAD}\x{7AAE}\x{7AAF}\x{7AB0}\x{7AB1}\x{7AB2}\x{7AB3}\x{7AB4}' . + '\x{7AB5}\x{7AB6}\x{7AB7}\x{7AB8}\x{7ABA}\x{7ABE}\x{7ABF}\x{7AC0}\x{7AC1}' . + '\x{7AC4}\x{7AC5}\x{7AC7}\x{7AC8}\x{7AC9}\x{7ACA}\x{7ACB}\x{7ACC}\x{7ACD}' . + '\x{7ACE}\x{7ACF}\x{7AD0}\x{7AD1}\x{7AD2}\x{7AD3}\x{7AD4}\x{7AD5}\x{7AD6}' . + '\x{7AD8}\x{7AD9}\x{7ADB}\x{7ADC}\x{7ADD}\x{7ADE}\x{7ADF}\x{7AE0}\x{7AE1}' . + '\x{7AE2}\x{7AE3}\x{7AE4}\x{7AE5}\x{7AE6}\x{7AE7}\x{7AE8}\x{7AEA}\x{7AEB}' . + '\x{7AEC}\x{7AED}\x{7AEE}\x{7AEF}\x{7AF0}\x{7AF1}\x{7AF2}\x{7AF3}\x{7AF4}' . + '\x{7AF6}\x{7AF7}\x{7AF8}\x{7AF9}\x{7AFA}\x{7AFB}\x{7AFD}\x{7AFE}\x{7AFF}' . + '\x{7B00}\x{7B01}\x{7B02}\x{7B03}\x{7B04}\x{7B05}\x{7B06}\x{7B08}\x{7B09}' . + '\x{7B0A}\x{7B0B}\x{7B0C}\x{7B0D}\x{7B0E}\x{7B0F}\x{7B10}\x{7B11}\x{7B12}' . + '\x{7B13}\x{7B14}\x{7B15}\x{7B16}\x{7B17}\x{7B18}\x{7B19}\x{7B1A}\x{7B1B}' . + '\x{7B1C}\x{7B1D}\x{7B1E}\x{7B20}\x{7B21}\x{7B22}\x{7B23}\x{7B24}\x{7B25}' . + '\x{7B26}\x{7B28}\x{7B2A}\x{7B2B}\x{7B2C}\x{7B2D}\x{7B2E}\x{7B2F}\x{7B30}' . + '\x{7B31}\x{7B32}\x{7B33}\x{7B34}\x{7B35}\x{7B36}\x{7B37}\x{7B38}\x{7B39}' . + '\x{7B3A}\x{7B3B}\x{7B3C}\x{7B3D}\x{7B3E}\x{7B3F}\x{7B40}\x{7B41}\x{7B43}' . + '\x{7B44}\x{7B45}\x{7B46}\x{7B47}\x{7B48}\x{7B49}\x{7B4A}\x{7B4B}\x{7B4C}' . + '\x{7B4D}\x{7B4E}\x{7B4F}\x{7B50}\x{7B51}\x{7B52}\x{7B54}\x{7B55}\x{7B56}' . + '\x{7B57}\x{7B58}\x{7B59}\x{7B5A}\x{7B5B}\x{7B5C}\x{7B5D}\x{7B5E}\x{7B5F}' . + '\x{7B60}\x{7B61}\x{7B62}\x{7B63}\x{7B64}\x{7B65}\x{7B66}\x{7B67}\x{7B68}' . + '\x{7B69}\x{7B6A}\x{7B6B}\x{7B6C}\x{7B6D}\x{7B6E}\x{7B70}\x{7B71}\x{7B72}' . + '\x{7B73}\x{7B74}\x{7B75}\x{7B76}\x{7B77}\x{7B78}\x{7B79}\x{7B7B}\x{7B7C}' . + '\x{7B7D}\x{7B7E}\x{7B7F}\x{7B80}\x{7B81}\x{7B82}\x{7B83}\x{7B84}\x{7B85}' . + '\x{7B87}\x{7B88}\x{7B89}\x{7B8A}\x{7B8B}\x{7B8C}\x{7B8D}\x{7B8E}\x{7B8F}' . + '\x{7B90}\x{7B91}\x{7B93}\x{7B94}\x{7B95}\x{7B96}\x{7B97}\x{7B98}\x{7B99}' . + '\x{7B9A}\x{7B9B}\x{7B9C}\x{7B9D}\x{7B9E}\x{7B9F}\x{7BA0}\x{7BA1}\x{7BA2}' . + '\x{7BA4}\x{7BA6}\x{7BA7}\x{7BA8}\x{7BA9}\x{7BAA}\x{7BAB}\x{7BAC}\x{7BAD}' . + '\x{7BAE}\x{7BAF}\x{7BB1}\x{7BB3}\x{7BB4}\x{7BB5}\x{7BB6}\x{7BB7}\x{7BB8}' . + '\x{7BB9}\x{7BBA}\x{7BBB}\x{7BBC}\x{7BBD}\x{7BBE}\x{7BBF}\x{7BC0}\x{7BC1}' . + '\x{7BC2}\x{7BC3}\x{7BC4}\x{7BC5}\x{7BC6}\x{7BC7}\x{7BC8}\x{7BC9}\x{7BCA}' . + '\x{7BCB}\x{7BCC}\x{7BCD}\x{7BCE}\x{7BD0}\x{7BD1}\x{7BD2}\x{7BD3}\x{7BD4}' . + '\x{7BD5}\x{7BD6}\x{7BD7}\x{7BD8}\x{7BD9}\x{7BDA}\x{7BDB}\x{7BDC}\x{7BDD}' . + '\x{7BDE}\x{7BDF}\x{7BE0}\x{7BE1}\x{7BE2}\x{7BE3}\x{7BE4}\x{7BE5}\x{7BE6}' . + '\x{7BE7}\x{7BE8}\x{7BE9}\x{7BEA}\x{7BEB}\x{7BEC}\x{7BED}\x{7BEE}\x{7BEF}' . + '\x{7BF0}\x{7BF1}\x{7BF2}\x{7BF3}\x{7BF4}\x{7BF5}\x{7BF6}\x{7BF7}\x{7BF8}' . + '\x{7BF9}\x{7BFB}\x{7BFC}\x{7BFD}\x{7BFE}\x{7BFF}\x{7C00}\x{7C01}\x{7C02}' . + '\x{7C03}\x{7C04}\x{7C05}\x{7C06}\x{7C07}\x{7C08}\x{7C09}\x{7C0A}\x{7C0B}' . + '\x{7C0C}\x{7C0D}\x{7C0E}\x{7C0F}\x{7C10}\x{7C11}\x{7C12}\x{7C13}\x{7C15}' . + '\x{7C16}\x{7C17}\x{7C18}\x{7C19}\x{7C1A}\x{7C1C}\x{7C1D}\x{7C1E}\x{7C1F}' . + '\x{7C20}\x{7C21}\x{7C22}\x{7C23}\x{7C24}\x{7C25}\x{7C26}\x{7C27}\x{7C28}' . + '\x{7C29}\x{7C2A}\x{7C2B}\x{7C2C}\x{7C2D}\x{7C30}\x{7C31}\x{7C32}\x{7C33}' . + '\x{7C34}\x{7C35}\x{7C36}\x{7C37}\x{7C38}\x{7C39}\x{7C3A}\x{7C3B}\x{7C3C}' . + '\x{7C3D}\x{7C3E}\x{7C3F}\x{7C40}\x{7C41}\x{7C42}\x{7C43}\x{7C44}\x{7C45}' . + '\x{7C46}\x{7C47}\x{7C48}\x{7C49}\x{7C4A}\x{7C4B}\x{7C4C}\x{7C4D}\x{7C4E}' . + '\x{7C50}\x{7C51}\x{7C53}\x{7C54}\x{7C56}\x{7C57}\x{7C58}\x{7C59}\x{7C5A}' . + '\x{7C5B}\x{7C5C}\x{7C5E}\x{7C5F}\x{7C60}\x{7C61}\x{7C62}\x{7C63}\x{7C64}' . + '\x{7C65}\x{7C66}\x{7C67}\x{7C68}\x{7C69}\x{7C6A}\x{7C6B}\x{7C6C}\x{7C6D}' . + '\x{7C6E}\x{7C6F}\x{7C70}\x{7C71}\x{7C72}\x{7C73}\x{7C74}\x{7C75}\x{7C77}' . + '\x{7C78}\x{7C79}\x{7C7A}\x{7C7B}\x{7C7C}\x{7C7D}\x{7C7E}\x{7C7F}\x{7C80}' . + '\x{7C81}\x{7C82}\x{7C84}\x{7C85}\x{7C86}\x{7C88}\x{7C89}\x{7C8A}\x{7C8B}' . + '\x{7C8C}\x{7C8D}\x{7C8E}\x{7C8F}\x{7C90}\x{7C91}\x{7C92}\x{7C94}\x{7C95}' . + '\x{7C96}\x{7C97}\x{7C98}\x{7C99}\x{7C9B}\x{7C9C}\x{7C9D}\x{7C9E}\x{7C9F}' . + '\x{7CA0}\x{7CA1}\x{7CA2}\x{7CA3}\x{7CA4}\x{7CA5}\x{7CA6}\x{7CA7}\x{7CA8}' . + '\x{7CA9}\x{7CAA}\x{7CAD}\x{7CAE}\x{7CAF}\x{7CB0}\x{7CB1}\x{7CB2}\x{7CB3}' . + '\x{7CB4}\x{7CB5}\x{7CB6}\x{7CB7}\x{7CB8}\x{7CB9}\x{7CBA}\x{7CBB}\x{7CBC}' . + '\x{7CBD}\x{7CBE}\x{7CBF}\x{7CC0}\x{7CC1}\x{7CC2}\x{7CC3}\x{7CC4}\x{7CC5}' . + '\x{7CC6}\x{7CC7}\x{7CC8}\x{7CC9}\x{7CCA}\x{7CCB}\x{7CCC}\x{7CCD}\x{7CCE}' . + '\x{7CCF}\x{7CD0}\x{7CD1}\x{7CD2}\x{7CD4}\x{7CD5}\x{7CD6}\x{7CD7}\x{7CD8}' . + '\x{7CD9}\x{7CDC}\x{7CDD}\x{7CDE}\x{7CDF}\x{7CE0}\x{7CE2}\x{7CE4}\x{7CE7}' . + '\x{7CE8}\x{7CE9}\x{7CEA}\x{7CEB}\x{7CEC}\x{7CED}\x{7CEE}\x{7CEF}\x{7CF0}' . + '\x{7CF1}\x{7CF2}\x{7CF3}\x{7CF4}\x{7CF5}\x{7CF6}\x{7CF7}\x{7CF8}\x{7CF9}' . + '\x{7CFA}\x{7CFB}\x{7CFD}\x{7CFE}\x{7D00}\x{7D01}\x{7D02}\x{7D03}\x{7D04}' . + '\x{7D05}\x{7D06}\x{7D07}\x{7D08}\x{7D09}\x{7D0A}\x{7D0B}\x{7D0C}\x{7D0D}' . + '\x{7D0E}\x{7D0F}\x{7D10}\x{7D11}\x{7D12}\x{7D13}\x{7D14}\x{7D15}\x{7D16}' . + '\x{7D17}\x{7D18}\x{7D19}\x{7D1A}\x{7D1B}\x{7D1C}\x{7D1D}\x{7D1E}\x{7D1F}' . + '\x{7D20}\x{7D21}\x{7D22}\x{7D24}\x{7D25}\x{7D26}\x{7D27}\x{7D28}\x{7D29}' . + '\x{7D2B}\x{7D2C}\x{7D2E}\x{7D2F}\x{7D30}\x{7D31}\x{7D32}\x{7D33}\x{7D34}' . + '\x{7D35}\x{7D36}\x{7D37}\x{7D38}\x{7D39}\x{7D3A}\x{7D3B}\x{7D3C}\x{7D3D}' . + '\x{7D3E}\x{7D3F}\x{7D40}\x{7D41}\x{7D42}\x{7D43}\x{7D44}\x{7D45}\x{7D46}' . + '\x{7D47}\x{7D49}\x{7D4A}\x{7D4B}\x{7D4C}\x{7D4E}\x{7D4F}\x{7D50}\x{7D51}' . + '\x{7D52}\x{7D53}\x{7D54}\x{7D55}\x{7D56}\x{7D57}\x{7D58}\x{7D59}\x{7D5B}' . + '\x{7D5C}\x{7D5D}\x{7D5E}\x{7D5F}\x{7D60}\x{7D61}\x{7D62}\x{7D63}\x{7D65}' . + '\x{7D66}\x{7D67}\x{7D68}\x{7D69}\x{7D6A}\x{7D6B}\x{7D6C}\x{7D6D}\x{7D6E}' . + '\x{7D6F}\x{7D70}\x{7D71}\x{7D72}\x{7D73}\x{7D74}\x{7D75}\x{7D76}\x{7D77}' . + '\x{7D79}\x{7D7A}\x{7D7B}\x{7D7C}\x{7D7D}\x{7D7E}\x{7D7F}\x{7D80}\x{7D81}' . + '\x{7D83}\x{7D84}\x{7D85}\x{7D86}\x{7D87}\x{7D88}\x{7D89}\x{7D8A}\x{7D8B}' . + '\x{7D8C}\x{7D8D}\x{7D8E}\x{7D8F}\x{7D90}\x{7D91}\x{7D92}\x{7D93}\x{7D94}' . + '\x{7D96}\x{7D97}\x{7D99}\x{7D9B}\x{7D9C}\x{7D9D}\x{7D9E}\x{7D9F}\x{7DA0}' . + '\x{7DA1}\x{7DA2}\x{7DA3}\x{7DA5}\x{7DA6}\x{7DA7}\x{7DA9}\x{7DAA}\x{7DAB}' . + '\x{7DAC}\x{7DAD}\x{7DAE}\x{7DAF}\x{7DB0}\x{7DB1}\x{7DB2}\x{7DB3}\x{7DB4}' . + '\x{7DB5}\x{7DB6}\x{7DB7}\x{7DB8}\x{7DB9}\x{7DBA}\x{7DBB}\x{7DBC}\x{7DBD}' . + '\x{7DBE}\x{7DBF}\x{7DC0}\x{7DC1}\x{7DC2}\x{7DC3}\x{7DC4}\x{7DC5}\x{7DC6}' . + '\x{7DC7}\x{7DC8}\x{7DC9}\x{7DCA}\x{7DCB}\x{7DCC}\x{7DCE}\x{7DCF}\x{7DD0}' . + '\x{7DD1}\x{7DD2}\x{7DD4}\x{7DD5}\x{7DD6}\x{7DD7}\x{7DD8}\x{7DD9}\x{7DDA}' . + '\x{7DDB}\x{7DDD}\x{7DDE}\x{7DDF}\x{7DE0}\x{7DE1}\x{7DE2}\x{7DE3}\x{7DE6}' . + '\x{7DE7}\x{7DE8}\x{7DE9}\x{7DEA}\x{7DEC}\x{7DED}\x{7DEE}\x{7DEF}\x{7DF0}' . + '\x{7DF1}\x{7DF2}\x{7DF3}\x{7DF4}\x{7DF5}\x{7DF6}\x{7DF7}\x{7DF8}\x{7DF9}' . + '\x{7DFA}\x{7DFB}\x{7DFC}\x{7E00}\x{7E01}\x{7E02}\x{7E03}\x{7E04}\x{7E05}' . + '\x{7E06}\x{7E07}\x{7E08}\x{7E09}\x{7E0A}\x{7E0B}\x{7E0C}\x{7E0D}\x{7E0E}' . + '\x{7E0F}\x{7E10}\x{7E11}\x{7E12}\x{7E13}\x{7E14}\x{7E15}\x{7E16}\x{7E17}' . + '\x{7E19}\x{7E1A}\x{7E1B}\x{7E1C}\x{7E1D}\x{7E1E}\x{7E1F}\x{7E20}\x{7E21}' . + '\x{7E22}\x{7E23}\x{7E24}\x{7E25}\x{7E26}\x{7E27}\x{7E28}\x{7E29}\x{7E2A}' . + '\x{7E2B}\x{7E2C}\x{7E2D}\x{7E2E}\x{7E2F}\x{7E30}\x{7E31}\x{7E32}\x{7E33}' . + '\x{7E34}\x{7E35}\x{7E36}\x{7E37}\x{7E38}\x{7E39}\x{7E3A}\x{7E3B}\x{7E3C}' . + '\x{7E3D}\x{7E3E}\x{7E3F}\x{7E40}\x{7E41}\x{7E42}\x{7E43}\x{7E44}\x{7E45}' . + '\x{7E46}\x{7E47}\x{7E48}\x{7E49}\x{7E4C}\x{7E4D}\x{7E4E}\x{7E4F}\x{7E50}' . + '\x{7E51}\x{7E52}\x{7E53}\x{7E54}\x{7E55}\x{7E56}\x{7E57}\x{7E58}\x{7E59}' . + '\x{7E5A}\x{7E5C}\x{7E5D}\x{7E5E}\x{7E5F}\x{7E60}\x{7E61}\x{7E62}\x{7E63}' . + '\x{7E65}\x{7E66}\x{7E67}\x{7E68}\x{7E69}\x{7E6A}\x{7E6B}\x{7E6C}\x{7E6D}' . + '\x{7E6E}\x{7E6F}\x{7E70}\x{7E71}\x{7E72}\x{7E73}\x{7E74}\x{7E75}\x{7E76}' . + '\x{7E77}\x{7E78}\x{7E79}\x{7E7A}\x{7E7B}\x{7E7C}\x{7E7D}\x{7E7E}\x{7E7F}' . + '\x{7E80}\x{7E81}\x{7E82}\x{7E83}\x{7E84}\x{7E85}\x{7E86}\x{7E87}\x{7E88}' . + '\x{7E89}\x{7E8A}\x{7E8B}\x{7E8C}\x{7E8D}\x{7E8E}\x{7E8F}\x{7E90}\x{7E91}' . + '\x{7E92}\x{7E93}\x{7E94}\x{7E95}\x{7E96}\x{7E97}\x{7E98}\x{7E99}\x{7E9A}' . + '\x{7E9B}\x{7E9C}\x{7E9E}\x{7E9F}\x{7EA0}\x{7EA1}\x{7EA2}\x{7EA3}\x{7EA4}' . + '\x{7EA5}\x{7EA6}\x{7EA7}\x{7EA8}\x{7EA9}\x{7EAA}\x{7EAB}\x{7EAC}\x{7EAD}' . + '\x{7EAE}\x{7EAF}\x{7EB0}\x{7EB1}\x{7EB2}\x{7EB3}\x{7EB4}\x{7EB5}\x{7EB6}' . + '\x{7EB7}\x{7EB8}\x{7EB9}\x{7EBA}\x{7EBB}\x{7EBC}\x{7EBD}\x{7EBE}\x{7EBF}' . + '\x{7EC0}\x{7EC1}\x{7EC2}\x{7EC3}\x{7EC4}\x{7EC5}\x{7EC6}\x{7EC7}\x{7EC8}' . + '\x{7EC9}\x{7ECA}\x{7ECB}\x{7ECC}\x{7ECD}\x{7ECE}\x{7ECF}\x{7ED0}\x{7ED1}' . + '\x{7ED2}\x{7ED3}\x{7ED4}\x{7ED5}\x{7ED6}\x{7ED7}\x{7ED8}\x{7ED9}\x{7EDA}' . + '\x{7EDB}\x{7EDC}\x{7EDD}\x{7EDE}\x{7EDF}\x{7EE0}\x{7EE1}\x{7EE2}\x{7EE3}' . + '\x{7EE4}\x{7EE5}\x{7EE6}\x{7EE7}\x{7EE8}\x{7EE9}\x{7EEA}\x{7EEB}\x{7EEC}' . + '\x{7EED}\x{7EEE}\x{7EEF}\x{7EF0}\x{7EF1}\x{7EF2}\x{7EF3}\x{7EF4}\x{7EF5}' . + '\x{7EF6}\x{7EF7}\x{7EF8}\x{7EF9}\x{7EFA}\x{7EFB}\x{7EFC}\x{7EFD}\x{7EFE}' . + '\x{7EFF}\x{7F00}\x{7F01}\x{7F02}\x{7F03}\x{7F04}\x{7F05}\x{7F06}\x{7F07}' . + '\x{7F08}\x{7F09}\x{7F0A}\x{7F0B}\x{7F0C}\x{7F0D}\x{7F0E}\x{7F0F}\x{7F10}' . + '\x{7F11}\x{7F12}\x{7F13}\x{7F14}\x{7F15}\x{7F16}\x{7F17}\x{7F18}\x{7F19}' . + '\x{7F1A}\x{7F1B}\x{7F1C}\x{7F1D}\x{7F1E}\x{7F1F}\x{7F20}\x{7F21}\x{7F22}' . + '\x{7F23}\x{7F24}\x{7F25}\x{7F26}\x{7F27}\x{7F28}\x{7F29}\x{7F2A}\x{7F2B}' . + '\x{7F2C}\x{7F2D}\x{7F2E}\x{7F2F}\x{7F30}\x{7F31}\x{7F32}\x{7F33}\x{7F34}' . + '\x{7F35}\x{7F36}\x{7F37}\x{7F38}\x{7F39}\x{7F3A}\x{7F3D}\x{7F3E}\x{7F3F}' . + '\x{7F40}\x{7F42}\x{7F43}\x{7F44}\x{7F45}\x{7F47}\x{7F48}\x{7F49}\x{7F4A}' . + '\x{7F4B}\x{7F4C}\x{7F4D}\x{7F4E}\x{7F4F}\x{7F50}\x{7F51}\x{7F52}\x{7F53}' . + '\x{7F54}\x{7F55}\x{7F56}\x{7F57}\x{7F58}\x{7F5A}\x{7F5B}\x{7F5C}\x{7F5D}' . + '\x{7F5E}\x{7F5F}\x{7F60}\x{7F61}\x{7F62}\x{7F63}\x{7F64}\x{7F65}\x{7F66}' . + '\x{7F67}\x{7F68}\x{7F69}\x{7F6A}\x{7F6B}\x{7F6C}\x{7F6D}\x{7F6E}\x{7F6F}' . + '\x{7F70}\x{7F71}\x{7F72}\x{7F73}\x{7F74}\x{7F75}\x{7F76}\x{7F77}\x{7F78}' . + '\x{7F79}\x{7F7A}\x{7F7B}\x{7F7C}\x{7F7D}\x{7F7E}\x{7F7F}\x{7F80}\x{7F81}' . + '\x{7F82}\x{7F83}\x{7F85}\x{7F86}\x{7F87}\x{7F88}\x{7F89}\x{7F8A}\x{7F8B}' . + '\x{7F8C}\x{7F8D}\x{7F8E}\x{7F8F}\x{7F91}\x{7F92}\x{7F93}\x{7F94}\x{7F95}' . + '\x{7F96}\x{7F98}\x{7F9A}\x{7F9B}\x{7F9C}\x{7F9D}\x{7F9E}\x{7F9F}\x{7FA0}' . + '\x{7FA1}\x{7FA2}\x{7FA3}\x{7FA4}\x{7FA5}\x{7FA6}\x{7FA7}\x{7FA8}\x{7FA9}' . + '\x{7FAA}\x{7FAB}\x{7FAC}\x{7FAD}\x{7FAE}\x{7FAF}\x{7FB0}\x{7FB1}\x{7FB2}' . + '\x{7FB3}\x{7FB5}\x{7FB6}\x{7FB7}\x{7FB8}\x{7FB9}\x{7FBA}\x{7FBB}\x{7FBC}' . + '\x{7FBD}\x{7FBE}\x{7FBF}\x{7FC0}\x{7FC1}\x{7FC2}\x{7FC3}\x{7FC4}\x{7FC5}' . + '\x{7FC6}\x{7FC7}\x{7FC8}\x{7FC9}\x{7FCA}\x{7FCB}\x{7FCC}\x{7FCD}\x{7FCE}' . + '\x{7FCF}\x{7FD0}\x{7FD1}\x{7FD2}\x{7FD3}\x{7FD4}\x{7FD5}\x{7FD7}\x{7FD8}' . + '\x{7FD9}\x{7FDA}\x{7FDB}\x{7FDC}\x{7FDE}\x{7FDF}\x{7FE0}\x{7FE1}\x{7FE2}' . + '\x{7FE3}\x{7FE5}\x{7FE6}\x{7FE7}\x{7FE8}\x{7FE9}\x{7FEA}\x{7FEB}\x{7FEC}' . + '\x{7FED}\x{7FEE}\x{7FEF}\x{7FF0}\x{7FF1}\x{7FF2}\x{7FF3}\x{7FF4}\x{7FF5}' . + '\x{7FF6}\x{7FF7}\x{7FF8}\x{7FF9}\x{7FFA}\x{7FFB}\x{7FFC}\x{7FFD}\x{7FFE}' . + '\x{7FFF}\x{8000}\x{8001}\x{8002}\x{8003}\x{8004}\x{8005}\x{8006}\x{8007}' . + '\x{8008}\x{8009}\x{800B}\x{800C}\x{800D}\x{800E}\x{800F}\x{8010}\x{8011}' . + '\x{8012}\x{8013}\x{8014}\x{8015}\x{8016}\x{8017}\x{8018}\x{8019}\x{801A}' . + '\x{801B}\x{801C}\x{801D}\x{801E}\x{801F}\x{8020}\x{8021}\x{8022}\x{8023}' . + '\x{8024}\x{8025}\x{8026}\x{8027}\x{8028}\x{8029}\x{802A}\x{802B}\x{802C}' . + '\x{802D}\x{802E}\x{8030}\x{8031}\x{8032}\x{8033}\x{8034}\x{8035}\x{8036}' . + '\x{8037}\x{8038}\x{8039}\x{803A}\x{803B}\x{803D}\x{803E}\x{803F}\x{8041}' . + '\x{8042}\x{8043}\x{8044}\x{8045}\x{8046}\x{8047}\x{8048}\x{8049}\x{804A}' . + '\x{804B}\x{804C}\x{804D}\x{804E}\x{804F}\x{8050}\x{8051}\x{8052}\x{8053}' . + '\x{8054}\x{8055}\x{8056}\x{8057}\x{8058}\x{8059}\x{805A}\x{805B}\x{805C}' . + '\x{805D}\x{805E}\x{805F}\x{8060}\x{8061}\x{8062}\x{8063}\x{8064}\x{8065}' . + '\x{8067}\x{8068}\x{8069}\x{806A}\x{806B}\x{806C}\x{806D}\x{806E}\x{806F}' . + '\x{8070}\x{8071}\x{8072}\x{8073}\x{8074}\x{8075}\x{8076}\x{8077}\x{8078}' . + '\x{8079}\x{807A}\x{807B}\x{807C}\x{807D}\x{807E}\x{807F}\x{8080}\x{8081}' . + '\x{8082}\x{8083}\x{8084}\x{8085}\x{8086}\x{8087}\x{8089}\x{808A}\x{808B}' . + '\x{808C}\x{808D}\x{808F}\x{8090}\x{8091}\x{8092}\x{8093}\x{8095}\x{8096}' . + '\x{8097}\x{8098}\x{8099}\x{809A}\x{809B}\x{809C}\x{809D}\x{809E}\x{809F}' . + '\x{80A0}\x{80A1}\x{80A2}\x{80A3}\x{80A4}\x{80A5}\x{80A9}\x{80AA}\x{80AB}' . + '\x{80AD}\x{80AE}\x{80AF}\x{80B0}\x{80B1}\x{80B2}\x{80B4}\x{80B5}\x{80B6}' . + '\x{80B7}\x{80B8}\x{80BA}\x{80BB}\x{80BC}\x{80BD}\x{80BE}\x{80BF}\x{80C0}' . + '\x{80C1}\x{80C2}\x{80C3}\x{80C4}\x{80C5}\x{80C6}\x{80C7}\x{80C8}\x{80C9}' . + '\x{80CA}\x{80CB}\x{80CC}\x{80CD}\x{80CE}\x{80CF}\x{80D0}\x{80D1}\x{80D2}' . + '\x{80D3}\x{80D4}\x{80D5}\x{80D6}\x{80D7}\x{80D8}\x{80D9}\x{80DA}\x{80DB}' . + '\x{80DC}\x{80DD}\x{80DE}\x{80E0}\x{80E1}\x{80E2}\x{80E3}\x{80E4}\x{80E5}' . + '\x{80E6}\x{80E7}\x{80E8}\x{80E9}\x{80EA}\x{80EB}\x{80EC}\x{80ED}\x{80EE}' . + '\x{80EF}\x{80F0}\x{80F1}\x{80F2}\x{80F3}\x{80F4}\x{80F5}\x{80F6}\x{80F7}' . + '\x{80F8}\x{80F9}\x{80FA}\x{80FB}\x{80FC}\x{80FD}\x{80FE}\x{80FF}\x{8100}' . + '\x{8101}\x{8102}\x{8105}\x{8106}\x{8107}\x{8108}\x{8109}\x{810A}\x{810B}' . + '\x{810C}\x{810D}\x{810E}\x{810F}\x{8110}\x{8111}\x{8112}\x{8113}\x{8114}' . + '\x{8115}\x{8116}\x{8118}\x{8119}\x{811A}\x{811B}\x{811C}\x{811D}\x{811E}' . + '\x{811F}\x{8120}\x{8121}\x{8122}\x{8123}\x{8124}\x{8125}\x{8126}\x{8127}' . + '\x{8128}\x{8129}\x{812A}\x{812B}\x{812C}\x{812D}\x{812E}\x{812F}\x{8130}' . + '\x{8131}\x{8132}\x{8136}\x{8137}\x{8138}\x{8139}\x{813A}\x{813B}\x{813C}' . + '\x{813D}\x{813E}\x{813F}\x{8140}\x{8141}\x{8142}\x{8143}\x{8144}\x{8145}' . + '\x{8146}\x{8147}\x{8148}\x{8149}\x{814A}\x{814B}\x{814C}\x{814D}\x{814E}' . + '\x{814F}\x{8150}\x{8151}\x{8152}\x{8153}\x{8154}\x{8155}\x{8156}\x{8157}' . + '\x{8158}\x{8159}\x{815A}\x{815B}\x{815C}\x{815D}\x{815E}\x{8160}\x{8161}' . + '\x{8162}\x{8163}\x{8164}\x{8165}\x{8166}\x{8167}\x{8168}\x{8169}\x{816A}' . + '\x{816B}\x{816C}\x{816D}\x{816E}\x{816F}\x{8170}\x{8171}\x{8172}\x{8173}' . + '\x{8174}\x{8175}\x{8176}\x{8177}\x{8178}\x{8179}\x{817A}\x{817B}\x{817C}' . + '\x{817D}\x{817E}\x{817F}\x{8180}\x{8181}\x{8182}\x{8183}\x{8185}\x{8186}' . + '\x{8187}\x{8188}\x{8189}\x{818A}\x{818B}\x{818C}\x{818D}\x{818E}\x{818F}' . + '\x{8191}\x{8192}\x{8193}\x{8194}\x{8195}\x{8197}\x{8198}\x{8199}\x{819A}' . + '\x{819B}\x{819C}\x{819D}\x{819E}\x{819F}\x{81A0}\x{81A1}\x{81A2}\x{81A3}' . + '\x{81A4}\x{81A5}\x{81A6}\x{81A7}\x{81A8}\x{81A9}\x{81AA}\x{81AB}\x{81AC}' . + '\x{81AD}\x{81AE}\x{81AF}\x{81B0}\x{81B1}\x{81B2}\x{81B3}\x{81B4}\x{81B5}' . + '\x{81B6}\x{81B7}\x{81B8}\x{81B9}\x{81BA}\x{81BB}\x{81BC}\x{81BD}\x{81BE}' . + '\x{81BF}\x{81C0}\x{81C1}\x{81C2}\x{81C3}\x{81C4}\x{81C5}\x{81C6}\x{81C7}' . + '\x{81C8}\x{81C9}\x{81CA}\x{81CC}\x{81CD}\x{81CE}\x{81CF}\x{81D0}\x{81D1}' . + '\x{81D2}\x{81D4}\x{81D5}\x{81D6}\x{81D7}\x{81D8}\x{81D9}\x{81DA}\x{81DB}' . + '\x{81DC}\x{81DD}\x{81DE}\x{81DF}\x{81E0}\x{81E1}\x{81E2}\x{81E3}\x{81E5}' . + '\x{81E6}\x{81E7}\x{81E8}\x{81E9}\x{81EA}\x{81EB}\x{81EC}\x{81ED}\x{81EE}' . + '\x{81F1}\x{81F2}\x{81F3}\x{81F4}\x{81F5}\x{81F6}\x{81F7}\x{81F8}\x{81F9}' . + '\x{81FA}\x{81FB}\x{81FC}\x{81FD}\x{81FE}\x{81FF}\x{8200}\x{8201}\x{8202}' . + '\x{8203}\x{8204}\x{8205}\x{8206}\x{8207}\x{8208}\x{8209}\x{820A}\x{820B}' . + '\x{820C}\x{820D}\x{820E}\x{820F}\x{8210}\x{8211}\x{8212}\x{8214}\x{8215}' . + '\x{8216}\x{8218}\x{8219}\x{821A}\x{821B}\x{821C}\x{821D}\x{821E}\x{821F}' . + '\x{8220}\x{8221}\x{8222}\x{8223}\x{8225}\x{8226}\x{8227}\x{8228}\x{8229}' . + '\x{822A}\x{822B}\x{822C}\x{822D}\x{822F}\x{8230}\x{8231}\x{8232}\x{8233}' . + '\x{8234}\x{8235}\x{8236}\x{8237}\x{8238}\x{8239}\x{823A}\x{823B}\x{823C}' . + '\x{823D}\x{823E}\x{823F}\x{8240}\x{8242}\x{8243}\x{8244}\x{8245}\x{8246}' . + '\x{8247}\x{8248}\x{8249}\x{824A}\x{824B}\x{824C}\x{824D}\x{824E}\x{824F}' . + '\x{8250}\x{8251}\x{8252}\x{8253}\x{8254}\x{8255}\x{8256}\x{8257}\x{8258}' . + '\x{8259}\x{825A}\x{825B}\x{825C}\x{825D}\x{825E}\x{825F}\x{8260}\x{8261}' . + '\x{8263}\x{8264}\x{8266}\x{8267}\x{8268}\x{8269}\x{826A}\x{826B}\x{826C}' . + '\x{826D}\x{826E}\x{826F}\x{8270}\x{8271}\x{8272}\x{8273}\x{8274}\x{8275}' . + '\x{8276}\x{8277}\x{8278}\x{8279}\x{827A}\x{827B}\x{827C}\x{827D}\x{827E}' . + '\x{827F}\x{8280}\x{8281}\x{8282}\x{8283}\x{8284}\x{8285}\x{8286}\x{8287}' . + '\x{8288}\x{8289}\x{828A}\x{828B}\x{828D}\x{828E}\x{828F}\x{8290}\x{8291}' . + '\x{8292}\x{8293}\x{8294}\x{8295}\x{8296}\x{8297}\x{8298}\x{8299}\x{829A}' . + '\x{829B}\x{829C}\x{829D}\x{829E}\x{829F}\x{82A0}\x{82A1}\x{82A2}\x{82A3}' . + '\x{82A4}\x{82A5}\x{82A6}\x{82A7}\x{82A8}\x{82A9}\x{82AA}\x{82AB}\x{82AC}' . + '\x{82AD}\x{82AE}\x{82AF}\x{82B0}\x{82B1}\x{82B3}\x{82B4}\x{82B5}\x{82B6}' . + '\x{82B7}\x{82B8}\x{82B9}\x{82BA}\x{82BB}\x{82BC}\x{82BD}\x{82BE}\x{82BF}' . + '\x{82C0}\x{82C1}\x{82C2}\x{82C3}\x{82C4}\x{82C5}\x{82C6}\x{82C7}\x{82C8}' . + '\x{82C9}\x{82CA}\x{82CB}\x{82CC}\x{82CD}\x{82CE}\x{82CF}\x{82D0}\x{82D1}' . + '\x{82D2}\x{82D3}\x{82D4}\x{82D5}\x{82D6}\x{82D7}\x{82D8}\x{82D9}\x{82DA}' . + '\x{82DB}\x{82DC}\x{82DD}\x{82DE}\x{82DF}\x{82E0}\x{82E1}\x{82E3}\x{82E4}' . + '\x{82E5}\x{82E6}\x{82E7}\x{82E8}\x{82E9}\x{82EA}\x{82EB}\x{82EC}\x{82ED}' . + '\x{82EE}\x{82EF}\x{82F0}\x{82F1}\x{82F2}\x{82F3}\x{82F4}\x{82F5}\x{82F6}' . + '\x{82F7}\x{82F8}\x{82F9}\x{82FA}\x{82FB}\x{82FD}\x{82FE}\x{82FF}\x{8300}' . + '\x{8301}\x{8302}\x{8303}\x{8304}\x{8305}\x{8306}\x{8307}\x{8308}\x{8309}' . + '\x{830B}\x{830C}\x{830D}\x{830E}\x{830F}\x{8311}\x{8312}\x{8313}\x{8314}' . + '\x{8315}\x{8316}\x{8317}\x{8318}\x{8319}\x{831A}\x{831B}\x{831C}\x{831D}' . + '\x{831E}\x{831F}\x{8320}\x{8321}\x{8322}\x{8323}\x{8324}\x{8325}\x{8326}' . + '\x{8327}\x{8328}\x{8329}\x{832A}\x{832B}\x{832C}\x{832D}\x{832E}\x{832F}' . + '\x{8331}\x{8332}\x{8333}\x{8334}\x{8335}\x{8336}\x{8337}\x{8338}\x{8339}' . + '\x{833A}\x{833B}\x{833C}\x{833D}\x{833E}\x{833F}\x{8340}\x{8341}\x{8342}' . + '\x{8343}\x{8344}\x{8345}\x{8346}\x{8347}\x{8348}\x{8349}\x{834A}\x{834B}' . + '\x{834C}\x{834D}\x{834E}\x{834F}\x{8350}\x{8351}\x{8352}\x{8353}\x{8354}' . + '\x{8356}\x{8357}\x{8358}\x{8359}\x{835A}\x{835B}\x{835C}\x{835D}\x{835E}' . + '\x{835F}\x{8360}\x{8361}\x{8362}\x{8363}\x{8364}\x{8365}\x{8366}\x{8367}' . + '\x{8368}\x{8369}\x{836A}\x{836B}\x{836C}\x{836D}\x{836E}\x{836F}\x{8370}' . + '\x{8371}\x{8372}\x{8373}\x{8374}\x{8375}\x{8376}\x{8377}\x{8378}\x{8379}' . + '\x{837A}\x{837B}\x{837C}\x{837D}\x{837E}\x{837F}\x{8380}\x{8381}\x{8382}' . + '\x{8383}\x{8384}\x{8385}\x{8386}\x{8387}\x{8388}\x{8389}\x{838A}\x{838B}' . + '\x{838C}\x{838D}\x{838E}\x{838F}\x{8390}\x{8391}\x{8392}\x{8393}\x{8394}' . + '\x{8395}\x{8396}\x{8397}\x{8398}\x{8399}\x{839A}\x{839B}\x{839C}\x{839D}' . + '\x{839E}\x{83A0}\x{83A1}\x{83A2}\x{83A3}\x{83A4}\x{83A5}\x{83A6}\x{83A7}' . + '\x{83A8}\x{83A9}\x{83AA}\x{83AB}\x{83AC}\x{83AD}\x{83AE}\x{83AF}\x{83B0}' . + '\x{83B1}\x{83B2}\x{83B3}\x{83B4}\x{83B6}\x{83B7}\x{83B8}\x{83B9}\x{83BA}' . + '\x{83BB}\x{83BC}\x{83BD}\x{83BF}\x{83C0}\x{83C1}\x{83C2}\x{83C3}\x{83C4}' . + '\x{83C5}\x{83C6}\x{83C7}\x{83C8}\x{83C9}\x{83CA}\x{83CB}\x{83CC}\x{83CD}' . + '\x{83CE}\x{83CF}\x{83D0}\x{83D1}\x{83D2}\x{83D3}\x{83D4}\x{83D5}\x{83D6}' . + '\x{83D7}\x{83D8}\x{83D9}\x{83DA}\x{83DB}\x{83DC}\x{83DD}\x{83DE}\x{83DF}' . + '\x{83E0}\x{83E1}\x{83E2}\x{83E3}\x{83E4}\x{83E5}\x{83E7}\x{83E8}\x{83E9}' . + '\x{83EA}\x{83EB}\x{83EC}\x{83EE}\x{83EF}\x{83F0}\x{83F1}\x{83F2}\x{83F3}' . + '\x{83F4}\x{83F5}\x{83F6}\x{83F7}\x{83F8}\x{83F9}\x{83FA}\x{83FB}\x{83FC}' . + '\x{83FD}\x{83FE}\x{83FF}\x{8400}\x{8401}\x{8402}\x{8403}\x{8404}\x{8405}' . + '\x{8406}\x{8407}\x{8408}\x{8409}\x{840A}\x{840B}\x{840C}\x{840D}\x{840E}' . + '\x{840F}\x{8410}\x{8411}\x{8412}\x{8413}\x{8415}\x{8418}\x{8419}\x{841A}' . + '\x{841B}\x{841C}\x{841D}\x{841E}\x{8421}\x{8422}\x{8423}\x{8424}\x{8425}' . + '\x{8426}\x{8427}\x{8428}\x{8429}\x{842A}\x{842B}\x{842C}\x{842D}\x{842E}' . + '\x{842F}\x{8430}\x{8431}\x{8432}\x{8433}\x{8434}\x{8435}\x{8436}\x{8437}' . + '\x{8438}\x{8439}\x{843A}\x{843B}\x{843C}\x{843D}\x{843E}\x{843F}\x{8440}' . + '\x{8441}\x{8442}\x{8443}\x{8444}\x{8445}\x{8446}\x{8447}\x{8448}\x{8449}' . + '\x{844A}\x{844B}\x{844C}\x{844D}\x{844E}\x{844F}\x{8450}\x{8451}\x{8452}' . + '\x{8453}\x{8454}\x{8455}\x{8456}\x{8457}\x{8459}\x{845A}\x{845B}\x{845C}' . + '\x{845D}\x{845E}\x{845F}\x{8460}\x{8461}\x{8462}\x{8463}\x{8464}\x{8465}' . + '\x{8466}\x{8467}\x{8468}\x{8469}\x{846A}\x{846B}\x{846C}\x{846D}\x{846E}' . + '\x{846F}\x{8470}\x{8471}\x{8472}\x{8473}\x{8474}\x{8475}\x{8476}\x{8477}' . + '\x{8478}\x{8479}\x{847A}\x{847B}\x{847C}\x{847D}\x{847E}\x{847F}\x{8480}' . + '\x{8481}\x{8482}\x{8484}\x{8485}\x{8486}\x{8487}\x{8488}\x{8489}\x{848A}' . + '\x{848B}\x{848C}\x{848D}\x{848E}\x{848F}\x{8490}\x{8491}\x{8492}\x{8493}' . + '\x{8494}\x{8496}\x{8497}\x{8498}\x{8499}\x{849A}\x{849B}\x{849C}\x{849D}' . + '\x{849E}\x{849F}\x{84A0}\x{84A1}\x{84A2}\x{84A3}\x{84A4}\x{84A5}\x{84A6}' . + '\x{84A7}\x{84A8}\x{84A9}\x{84AA}\x{84AB}\x{84AC}\x{84AE}\x{84AF}\x{84B0}' . + '\x{84B1}\x{84B2}\x{84B3}\x{84B4}\x{84B5}\x{84B6}\x{84B8}\x{84B9}\x{84BA}' . + '\x{84BB}\x{84BC}\x{84BD}\x{84BE}\x{84BF}\x{84C0}\x{84C1}\x{84C2}\x{84C4}' . + '\x{84C5}\x{84C6}\x{84C7}\x{84C8}\x{84C9}\x{84CA}\x{84CB}\x{84CC}\x{84CD}' . + '\x{84CE}\x{84CF}\x{84D0}\x{84D1}\x{84D2}\x{84D3}\x{84D4}\x{84D5}\x{84D6}' . + '\x{84D7}\x{84D8}\x{84D9}\x{84DB}\x{84DC}\x{84DD}\x{84DE}\x{84DF}\x{84E0}' . + '\x{84E1}\x{84E2}\x{84E3}\x{84E4}\x{84E5}\x{84E6}\x{84E7}\x{84E8}\x{84E9}' . + '\x{84EA}\x{84EB}\x{84EC}\x{84EE}\x{84EF}\x{84F0}\x{84F1}\x{84F2}\x{84F3}' . + '\x{84F4}\x{84F5}\x{84F6}\x{84F7}\x{84F8}\x{84F9}\x{84FA}\x{84FB}\x{84FC}' . + '\x{84FD}\x{84FE}\x{84FF}\x{8500}\x{8501}\x{8502}\x{8503}\x{8504}\x{8506}' . + '\x{8507}\x{8508}\x{8509}\x{850A}\x{850B}\x{850C}\x{850D}\x{850E}\x{850F}' . + '\x{8511}\x{8512}\x{8513}\x{8514}\x{8515}\x{8516}\x{8517}\x{8518}\x{8519}' . + '\x{851A}\x{851B}\x{851C}\x{851D}\x{851E}\x{851F}\x{8520}\x{8521}\x{8522}' . + '\x{8523}\x{8524}\x{8525}\x{8526}\x{8527}\x{8528}\x{8529}\x{852A}\x{852B}' . + '\x{852C}\x{852D}\x{852E}\x{852F}\x{8530}\x{8531}\x{8534}\x{8535}\x{8536}' . + '\x{8537}\x{8538}\x{8539}\x{853A}\x{853B}\x{853C}\x{853D}\x{853E}\x{853F}' . + '\x{8540}\x{8541}\x{8542}\x{8543}\x{8544}\x{8545}\x{8546}\x{8547}\x{8548}' . + '\x{8549}\x{854A}\x{854B}\x{854D}\x{854E}\x{854F}\x{8551}\x{8552}\x{8553}' . + '\x{8554}\x{8555}\x{8556}\x{8557}\x{8558}\x{8559}\x{855A}\x{855B}\x{855C}' . + '\x{855D}\x{855E}\x{855F}\x{8560}\x{8561}\x{8562}\x{8563}\x{8564}\x{8565}' . + '\x{8566}\x{8567}\x{8568}\x{8569}\x{856A}\x{856B}\x{856C}\x{856D}\x{856E}' . + '\x{856F}\x{8570}\x{8571}\x{8572}\x{8573}\x{8574}\x{8575}\x{8576}\x{8577}' . + '\x{8578}\x{8579}\x{857A}\x{857B}\x{857C}\x{857D}\x{857E}\x{8580}\x{8581}' . + '\x{8582}\x{8583}\x{8584}\x{8585}\x{8586}\x{8587}\x{8588}\x{8589}\x{858A}' . + '\x{858B}\x{858C}\x{858D}\x{858E}\x{858F}\x{8590}\x{8591}\x{8592}\x{8594}' . + '\x{8595}\x{8596}\x{8598}\x{8599}\x{859A}\x{859B}\x{859C}\x{859D}\x{859E}' . + '\x{859F}\x{85A0}\x{85A1}\x{85A2}\x{85A3}\x{85A4}\x{85A5}\x{85A6}\x{85A7}' . + '\x{85A8}\x{85A9}\x{85AA}\x{85AB}\x{85AC}\x{85AD}\x{85AE}\x{85AF}\x{85B0}' . + '\x{85B1}\x{85B3}\x{85B4}\x{85B5}\x{85B6}\x{85B7}\x{85B8}\x{85B9}\x{85BA}' . + '\x{85BC}\x{85BD}\x{85BE}\x{85BF}\x{85C0}\x{85C1}\x{85C2}\x{85C3}\x{85C4}' . + '\x{85C5}\x{85C6}\x{85C7}\x{85C8}\x{85C9}\x{85CA}\x{85CB}\x{85CD}\x{85CE}' . + '\x{85CF}\x{85D0}\x{85D1}\x{85D2}\x{85D3}\x{85D4}\x{85D5}\x{85D6}\x{85D7}' . + '\x{85D8}\x{85D9}\x{85DA}\x{85DB}\x{85DC}\x{85DD}\x{85DE}\x{85DF}\x{85E0}' . + '\x{85E1}\x{85E2}\x{85E3}\x{85E4}\x{85E5}\x{85E6}\x{85E7}\x{85E8}\x{85E9}' . + '\x{85EA}\x{85EB}\x{85EC}\x{85ED}\x{85EF}\x{85F0}\x{85F1}\x{85F2}\x{85F4}' . + '\x{85F5}\x{85F6}\x{85F7}\x{85F8}\x{85F9}\x{85FA}\x{85FB}\x{85FD}\x{85FE}' . + '\x{85FF}\x{8600}\x{8601}\x{8602}\x{8604}\x{8605}\x{8606}\x{8607}\x{8608}' . + '\x{8609}\x{860A}\x{860B}\x{860C}\x{860F}\x{8611}\x{8612}\x{8613}\x{8614}' . + '\x{8616}\x{8617}\x{8618}\x{8619}\x{861A}\x{861B}\x{861C}\x{861E}\x{861F}' . + '\x{8620}\x{8621}\x{8622}\x{8623}\x{8624}\x{8625}\x{8626}\x{8627}\x{8628}' . + '\x{8629}\x{862A}\x{862B}\x{862C}\x{862D}\x{862E}\x{862F}\x{8630}\x{8631}' . + '\x{8632}\x{8633}\x{8634}\x{8635}\x{8636}\x{8638}\x{8639}\x{863A}\x{863B}' . + '\x{863C}\x{863D}\x{863E}\x{863F}\x{8640}\x{8641}\x{8642}\x{8643}\x{8644}' . + '\x{8645}\x{8646}\x{8647}\x{8648}\x{8649}\x{864A}\x{864B}\x{864C}\x{864D}' . + '\x{864E}\x{864F}\x{8650}\x{8651}\x{8652}\x{8653}\x{8654}\x{8655}\x{8656}' . + '\x{8658}\x{8659}\x{865A}\x{865B}\x{865C}\x{865D}\x{865E}\x{865F}\x{8660}' . + '\x{8661}\x{8662}\x{8663}\x{8664}\x{8665}\x{8666}\x{8667}\x{8668}\x{8669}' . + '\x{866A}\x{866B}\x{866C}\x{866D}\x{866E}\x{866F}\x{8670}\x{8671}\x{8672}' . + '\x{8673}\x{8674}\x{8676}\x{8677}\x{8678}\x{8679}\x{867A}\x{867B}\x{867C}' . + '\x{867D}\x{867E}\x{867F}\x{8680}\x{8681}\x{8682}\x{8683}\x{8684}\x{8685}' . + '\x{8686}\x{8687}\x{8688}\x{868A}\x{868B}\x{868C}\x{868D}\x{868E}\x{868F}' . + '\x{8690}\x{8691}\x{8693}\x{8694}\x{8695}\x{8696}\x{8697}\x{8698}\x{8699}' . + '\x{869A}\x{869B}\x{869C}\x{869D}\x{869E}\x{869F}\x{86A1}\x{86A2}\x{86A3}' . + '\x{86A4}\x{86A5}\x{86A7}\x{86A8}\x{86A9}\x{86AA}\x{86AB}\x{86AC}\x{86AD}' . + '\x{86AE}\x{86AF}\x{86B0}\x{86B1}\x{86B2}\x{86B3}\x{86B4}\x{86B5}\x{86B6}' . + '\x{86B7}\x{86B8}\x{86B9}\x{86BA}\x{86BB}\x{86BC}\x{86BD}\x{86BE}\x{86BF}' . + '\x{86C0}\x{86C1}\x{86C2}\x{86C3}\x{86C4}\x{86C5}\x{86C6}\x{86C7}\x{86C8}' . + '\x{86C9}\x{86CA}\x{86CB}\x{86CC}\x{86CE}\x{86CF}\x{86D0}\x{86D1}\x{86D2}' . + '\x{86D3}\x{86D4}\x{86D6}\x{86D7}\x{86D8}\x{86D9}\x{86DA}\x{86DB}\x{86DC}' . + '\x{86DD}\x{86DE}\x{86DF}\x{86E1}\x{86E2}\x{86E3}\x{86E4}\x{86E5}\x{86E6}' . + '\x{86E8}\x{86E9}\x{86EA}\x{86EB}\x{86EC}\x{86ED}\x{86EE}\x{86EF}\x{86F0}' . + '\x{86F1}\x{86F2}\x{86F3}\x{86F4}\x{86F5}\x{86F6}\x{86F7}\x{86F8}\x{86F9}' . + '\x{86FA}\x{86FB}\x{86FC}\x{86FE}\x{86FF}\x{8700}\x{8701}\x{8702}\x{8703}' . + '\x{8704}\x{8705}\x{8706}\x{8707}\x{8708}\x{8709}\x{870A}\x{870B}\x{870C}' . + '\x{870D}\x{870E}\x{870F}\x{8710}\x{8711}\x{8712}\x{8713}\x{8714}\x{8715}' . + '\x{8716}\x{8717}\x{8718}\x{8719}\x{871A}\x{871B}\x{871C}\x{871E}\x{871F}' . + '\x{8720}\x{8721}\x{8722}\x{8723}\x{8724}\x{8725}\x{8726}\x{8727}\x{8728}' . + '\x{8729}\x{872A}\x{872B}\x{872C}\x{872D}\x{872E}\x{8730}\x{8731}\x{8732}' . + '\x{8733}\x{8734}\x{8735}\x{8736}\x{8737}\x{8738}\x{8739}\x{873A}\x{873B}' . + '\x{873C}\x{873E}\x{873F}\x{8740}\x{8741}\x{8742}\x{8743}\x{8744}\x{8746}' . + '\x{8747}\x{8748}\x{8749}\x{874A}\x{874C}\x{874D}\x{874E}\x{874F}\x{8750}' . + '\x{8751}\x{8752}\x{8753}\x{8754}\x{8755}\x{8756}\x{8757}\x{8758}\x{8759}' . + '\x{875A}\x{875B}\x{875C}\x{875D}\x{875E}\x{875F}\x{8760}\x{8761}\x{8762}' . + '\x{8763}\x{8764}\x{8765}\x{8766}\x{8767}\x{8768}\x{8769}\x{876A}\x{876B}' . + '\x{876C}\x{876D}\x{876E}\x{876F}\x{8770}\x{8772}\x{8773}\x{8774}\x{8775}' . + '\x{8776}\x{8777}\x{8778}\x{8779}\x{877A}\x{877B}\x{877C}\x{877D}\x{877E}' . + '\x{8780}\x{8781}\x{8782}\x{8783}\x{8784}\x{8785}\x{8786}\x{8787}\x{8788}' . + '\x{8789}\x{878A}\x{878B}\x{878C}\x{878D}\x{878F}\x{8790}\x{8791}\x{8792}' . + '\x{8793}\x{8794}\x{8795}\x{8796}\x{8797}\x{8798}\x{879A}\x{879B}\x{879C}' . + '\x{879D}\x{879E}\x{879F}\x{87A0}\x{87A1}\x{87A2}\x{87A3}\x{87A4}\x{87A5}' . + '\x{87A6}\x{87A7}\x{87A8}\x{87A9}\x{87AA}\x{87AB}\x{87AC}\x{87AD}\x{87AE}' . + '\x{87AF}\x{87B0}\x{87B1}\x{87B2}\x{87B3}\x{87B4}\x{87B5}\x{87B6}\x{87B7}' . + '\x{87B8}\x{87B9}\x{87BA}\x{87BB}\x{87BC}\x{87BD}\x{87BE}\x{87BF}\x{87C0}' . + '\x{87C1}\x{87C2}\x{87C3}\x{87C4}\x{87C5}\x{87C6}\x{87C7}\x{87C8}\x{87C9}' . + '\x{87CA}\x{87CB}\x{87CC}\x{87CD}\x{87CE}\x{87CF}\x{87D0}\x{87D1}\x{87D2}' . + '\x{87D3}\x{87D4}\x{87D5}\x{87D6}\x{87D7}\x{87D8}\x{87D9}\x{87DB}\x{87DC}' . + '\x{87DD}\x{87DE}\x{87DF}\x{87E0}\x{87E1}\x{87E2}\x{87E3}\x{87E4}\x{87E5}' . + '\x{87E6}\x{87E7}\x{87E8}\x{87E9}\x{87EA}\x{87EB}\x{87EC}\x{87ED}\x{87EE}' . + '\x{87EF}\x{87F1}\x{87F2}\x{87F3}\x{87F4}\x{87F5}\x{87F6}\x{87F7}\x{87F8}' . + '\x{87F9}\x{87FA}\x{87FB}\x{87FC}\x{87FD}\x{87FE}\x{87FF}\x{8800}\x{8801}' . + '\x{8802}\x{8803}\x{8804}\x{8805}\x{8806}\x{8808}\x{8809}\x{880A}\x{880B}' . + '\x{880C}\x{880D}\x{880E}\x{880F}\x{8810}\x{8811}\x{8813}\x{8814}\x{8815}' . + '\x{8816}\x{8817}\x{8818}\x{8819}\x{881A}\x{881B}\x{881C}\x{881D}\x{881E}' . + '\x{881F}\x{8820}\x{8821}\x{8822}\x{8823}\x{8824}\x{8825}\x{8826}\x{8827}' . + '\x{8828}\x{8829}\x{882A}\x{882B}\x{882C}\x{882E}\x{882F}\x{8830}\x{8831}' . + '\x{8832}\x{8833}\x{8834}\x{8835}\x{8836}\x{8837}\x{8838}\x{8839}\x{883B}' . + '\x{883C}\x{883D}\x{883E}\x{883F}\x{8840}\x{8841}\x{8842}\x{8843}\x{8844}' . + '\x{8845}\x{8846}\x{8848}\x{8849}\x{884A}\x{884B}\x{884C}\x{884D}\x{884E}' . + '\x{884F}\x{8850}\x{8851}\x{8852}\x{8853}\x{8854}\x{8855}\x{8856}\x{8857}' . + '\x{8859}\x{885A}\x{885B}\x{885D}\x{885E}\x{8860}\x{8861}\x{8862}\x{8863}' . + '\x{8864}\x{8865}\x{8866}\x{8867}\x{8868}\x{8869}\x{886A}\x{886B}\x{886C}' . + '\x{886D}\x{886E}\x{886F}\x{8870}\x{8871}\x{8872}\x{8873}\x{8874}\x{8875}' . + '\x{8876}\x{8877}\x{8878}\x{8879}\x{887B}\x{887C}\x{887D}\x{887E}\x{887F}' . + '\x{8880}\x{8881}\x{8882}\x{8883}\x{8884}\x{8885}\x{8886}\x{8887}\x{8888}' . + '\x{8889}\x{888A}\x{888B}\x{888C}\x{888D}\x{888E}\x{888F}\x{8890}\x{8891}' . + '\x{8892}\x{8893}\x{8894}\x{8895}\x{8896}\x{8897}\x{8898}\x{8899}\x{889A}' . + '\x{889B}\x{889C}\x{889D}\x{889E}\x{889F}\x{88A0}\x{88A1}\x{88A2}\x{88A3}' . + '\x{88A4}\x{88A5}\x{88A6}\x{88A7}\x{88A8}\x{88A9}\x{88AA}\x{88AB}\x{88AC}' . + '\x{88AD}\x{88AE}\x{88AF}\x{88B0}\x{88B1}\x{88B2}\x{88B3}\x{88B4}\x{88B6}' . + '\x{88B7}\x{88B8}\x{88B9}\x{88BA}\x{88BB}\x{88BC}\x{88BD}\x{88BE}\x{88BF}' . + '\x{88C0}\x{88C1}\x{88C2}\x{88C3}\x{88C4}\x{88C5}\x{88C6}\x{88C7}\x{88C8}' . + '\x{88C9}\x{88CA}\x{88CB}\x{88CC}\x{88CD}\x{88CE}\x{88CF}\x{88D0}\x{88D1}' . + '\x{88D2}\x{88D3}\x{88D4}\x{88D5}\x{88D6}\x{88D7}\x{88D8}\x{88D9}\x{88DA}' . + '\x{88DB}\x{88DC}\x{88DD}\x{88DE}\x{88DF}\x{88E0}\x{88E1}\x{88E2}\x{88E3}' . + '\x{88E4}\x{88E5}\x{88E7}\x{88E8}\x{88EA}\x{88EB}\x{88EC}\x{88EE}\x{88EF}' . + '\x{88F0}\x{88F1}\x{88F2}\x{88F3}\x{88F4}\x{88F5}\x{88F6}\x{88F7}\x{88F8}' . + '\x{88F9}\x{88FA}\x{88FB}\x{88FC}\x{88FD}\x{88FE}\x{88FF}\x{8900}\x{8901}' . + '\x{8902}\x{8904}\x{8905}\x{8906}\x{8907}\x{8908}\x{8909}\x{890A}\x{890B}' . + '\x{890C}\x{890D}\x{890E}\x{8910}\x{8911}\x{8912}\x{8913}\x{8914}\x{8915}' . + '\x{8916}\x{8917}\x{8918}\x{8919}\x{891A}\x{891B}\x{891C}\x{891D}\x{891E}' . + '\x{891F}\x{8920}\x{8921}\x{8922}\x{8923}\x{8925}\x{8926}\x{8927}\x{8928}' . + '\x{8929}\x{892A}\x{892B}\x{892C}\x{892D}\x{892E}\x{892F}\x{8930}\x{8931}' . + '\x{8932}\x{8933}\x{8934}\x{8935}\x{8936}\x{8937}\x{8938}\x{8939}\x{893A}' . + '\x{893B}\x{893C}\x{893D}\x{893E}\x{893F}\x{8940}\x{8941}\x{8942}\x{8943}' . + '\x{8944}\x{8945}\x{8946}\x{8947}\x{8948}\x{8949}\x{894A}\x{894B}\x{894C}' . + '\x{894E}\x{894F}\x{8950}\x{8951}\x{8952}\x{8953}\x{8954}\x{8955}\x{8956}' . + '\x{8957}\x{8958}\x{8959}\x{895A}\x{895B}\x{895C}\x{895D}\x{895E}\x{895F}' . + '\x{8960}\x{8961}\x{8962}\x{8963}\x{8964}\x{8966}\x{8967}\x{8968}\x{8969}' . + '\x{896A}\x{896B}\x{896C}\x{896D}\x{896E}\x{896F}\x{8970}\x{8971}\x{8972}' . + '\x{8973}\x{8974}\x{8976}\x{8977}\x{8978}\x{8979}\x{897A}\x{897B}\x{897C}' . + '\x{897E}\x{897F}\x{8980}\x{8981}\x{8982}\x{8983}\x{8984}\x{8985}\x{8986}' . + '\x{8987}\x{8988}\x{8989}\x{898A}\x{898B}\x{898C}\x{898E}\x{898F}\x{8991}' . + '\x{8992}\x{8993}\x{8995}\x{8996}\x{8997}\x{8998}\x{899A}\x{899B}\x{899C}' . + '\x{899D}\x{899E}\x{899F}\x{89A0}\x{89A1}\x{89A2}\x{89A3}\x{89A4}\x{89A5}' . + '\x{89A6}\x{89A7}\x{89A8}\x{89AA}\x{89AB}\x{89AC}\x{89AD}\x{89AE}\x{89AF}' . + '\x{89B1}\x{89B2}\x{89B3}\x{89B5}\x{89B6}\x{89B7}\x{89B8}\x{89B9}\x{89BA}' . + '\x{89BD}\x{89BE}\x{89BF}\x{89C0}\x{89C1}\x{89C2}\x{89C3}\x{89C4}\x{89C5}' . + '\x{89C6}\x{89C7}\x{89C8}\x{89C9}\x{89CA}\x{89CB}\x{89CC}\x{89CD}\x{89CE}' . + '\x{89CF}\x{89D0}\x{89D1}\x{89D2}\x{89D3}\x{89D4}\x{89D5}\x{89D6}\x{89D7}' . + '\x{89D8}\x{89D9}\x{89DA}\x{89DB}\x{89DC}\x{89DD}\x{89DE}\x{89DF}\x{89E0}' . + '\x{89E1}\x{89E2}\x{89E3}\x{89E4}\x{89E5}\x{89E6}\x{89E7}\x{89E8}\x{89E9}' . + '\x{89EA}\x{89EB}\x{89EC}\x{89ED}\x{89EF}\x{89F0}\x{89F1}\x{89F2}\x{89F3}' . + '\x{89F4}\x{89F6}\x{89F7}\x{89F8}\x{89FA}\x{89FB}\x{89FC}\x{89FE}\x{89FF}' . + '\x{8A00}\x{8A01}\x{8A02}\x{8A03}\x{8A04}\x{8A07}\x{8A08}\x{8A09}\x{8A0A}' . + '\x{8A0B}\x{8A0C}\x{8A0D}\x{8A0E}\x{8A0F}\x{8A10}\x{8A11}\x{8A12}\x{8A13}' . + '\x{8A15}\x{8A16}\x{8A17}\x{8A18}\x{8A1A}\x{8A1B}\x{8A1C}\x{8A1D}\x{8A1E}' . + '\x{8A1F}\x{8A22}\x{8A23}\x{8A24}\x{8A25}\x{8A26}\x{8A27}\x{8A28}\x{8A29}' . + '\x{8A2A}\x{8A2C}\x{8A2D}\x{8A2E}\x{8A2F}\x{8A30}\x{8A31}\x{8A32}\x{8A34}' . + '\x{8A35}\x{8A36}\x{8A37}\x{8A38}\x{8A39}\x{8A3A}\x{8A3B}\x{8A3C}\x{8A3E}' . + '\x{8A3F}\x{8A40}\x{8A41}\x{8A42}\x{8A43}\x{8A44}\x{8A45}\x{8A46}\x{8A47}' . + '\x{8A48}\x{8A49}\x{8A4A}\x{8A4C}\x{8A4D}\x{8A4E}\x{8A4F}\x{8A50}\x{8A51}' . + '\x{8A52}\x{8A53}\x{8A54}\x{8A55}\x{8A56}\x{8A57}\x{8A58}\x{8A59}\x{8A5A}' . + '\x{8A5B}\x{8A5C}\x{8A5D}\x{8A5E}\x{8A5F}\x{8A60}\x{8A61}\x{8A62}\x{8A63}' . + '\x{8A65}\x{8A66}\x{8A67}\x{8A68}\x{8A69}\x{8A6A}\x{8A6B}\x{8A6C}\x{8A6D}' . + '\x{8A6E}\x{8A6F}\x{8A70}\x{8A71}\x{8A72}\x{8A73}\x{8A74}\x{8A75}\x{8A76}' . + '\x{8A77}\x{8A79}\x{8A7A}\x{8A7B}\x{8A7C}\x{8A7E}\x{8A7F}\x{8A80}\x{8A81}' . + '\x{8A82}\x{8A83}\x{8A84}\x{8A85}\x{8A86}\x{8A87}\x{8A89}\x{8A8A}\x{8A8B}' . + '\x{8A8C}\x{8A8D}\x{8A8E}\x{8A8F}\x{8A90}\x{8A91}\x{8A92}\x{8A93}\x{8A94}' . + '\x{8A95}\x{8A96}\x{8A97}\x{8A98}\x{8A99}\x{8A9A}\x{8A9B}\x{8A9C}\x{8A9D}' . + '\x{8A9E}\x{8AA0}\x{8AA1}\x{8AA2}\x{8AA3}\x{8AA4}\x{8AA5}\x{8AA6}\x{8AA7}' . + '\x{8AA8}\x{8AA9}\x{8AAA}\x{8AAB}\x{8AAC}\x{8AAE}\x{8AB0}\x{8AB1}\x{8AB2}' . + '\x{8AB3}\x{8AB4}\x{8AB5}\x{8AB6}\x{8AB8}\x{8AB9}\x{8ABA}\x{8ABB}\x{8ABC}' . + '\x{8ABD}\x{8ABE}\x{8ABF}\x{8AC0}\x{8AC1}\x{8AC2}\x{8AC3}\x{8AC4}\x{8AC5}' . + '\x{8AC6}\x{8AC7}\x{8AC8}\x{8AC9}\x{8ACA}\x{8ACB}\x{8ACC}\x{8ACD}\x{8ACE}' . + '\x{8ACF}\x{8AD1}\x{8AD2}\x{8AD3}\x{8AD4}\x{8AD5}\x{8AD6}\x{8AD7}\x{8AD8}' . + '\x{8AD9}\x{8ADA}\x{8ADB}\x{8ADC}\x{8ADD}\x{8ADE}\x{8ADF}\x{8AE0}\x{8AE1}' . + '\x{8AE2}\x{8AE3}\x{8AE4}\x{8AE5}\x{8AE6}\x{8AE7}\x{8AE8}\x{8AE9}\x{8AEA}' . + '\x{8AEB}\x{8AED}\x{8AEE}\x{8AEF}\x{8AF0}\x{8AF1}\x{8AF2}\x{8AF3}\x{8AF4}' . + '\x{8AF5}\x{8AF6}\x{8AF7}\x{8AF8}\x{8AF9}\x{8AFA}\x{8AFB}\x{8AFC}\x{8AFD}' . + '\x{8AFE}\x{8AFF}\x{8B00}\x{8B01}\x{8B02}\x{8B03}\x{8B04}\x{8B05}\x{8B06}' . + '\x{8B07}\x{8B08}\x{8B09}\x{8B0A}\x{8B0B}\x{8B0D}\x{8B0E}\x{8B0F}\x{8B10}' . + '\x{8B11}\x{8B12}\x{8B13}\x{8B14}\x{8B15}\x{8B16}\x{8B17}\x{8B18}\x{8B19}' . + '\x{8B1A}\x{8B1B}\x{8B1C}\x{8B1D}\x{8B1E}\x{8B1F}\x{8B20}\x{8B21}\x{8B22}' . + '\x{8B23}\x{8B24}\x{8B25}\x{8B26}\x{8B27}\x{8B28}\x{8B2A}\x{8B2B}\x{8B2C}' . + '\x{8B2D}\x{8B2E}\x{8B2F}\x{8B30}\x{8B31}\x{8B33}\x{8B34}\x{8B35}\x{8B36}' . + '\x{8B37}\x{8B39}\x{8B3A}\x{8B3B}\x{8B3C}\x{8B3D}\x{8B3E}\x{8B40}\x{8B41}' . + '\x{8B42}\x{8B43}\x{8B44}\x{8B45}\x{8B46}\x{8B47}\x{8B48}\x{8B49}\x{8B4A}' . + '\x{8B4B}\x{8B4C}\x{8B4D}\x{8B4E}\x{8B4F}\x{8B50}\x{8B51}\x{8B52}\x{8B53}' . + '\x{8B54}\x{8B55}\x{8B56}\x{8B57}\x{8B58}\x{8B59}\x{8B5A}\x{8B5B}\x{8B5C}' . + '\x{8B5D}\x{8B5E}\x{8B5F}\x{8B60}\x{8B63}\x{8B64}\x{8B65}\x{8B66}\x{8B67}' . + '\x{8B68}\x{8B6A}\x{8B6B}\x{8B6C}\x{8B6D}\x{8B6E}\x{8B6F}\x{8B70}\x{8B71}' . + '\x{8B73}\x{8B74}\x{8B76}\x{8B77}\x{8B78}\x{8B79}\x{8B7A}\x{8B7B}\x{8B7D}' . + '\x{8B7E}\x{8B7F}\x{8B80}\x{8B82}\x{8B83}\x{8B84}\x{8B85}\x{8B86}\x{8B88}' . + '\x{8B89}\x{8B8A}\x{8B8B}\x{8B8C}\x{8B8E}\x{8B90}\x{8B91}\x{8B92}\x{8B93}' . + '\x{8B94}\x{8B95}\x{8B96}\x{8B97}\x{8B98}\x{8B99}\x{8B9A}\x{8B9C}\x{8B9D}' . + '\x{8B9E}\x{8B9F}\x{8BA0}\x{8BA1}\x{8BA2}\x{8BA3}\x{8BA4}\x{8BA5}\x{8BA6}' . + '\x{8BA7}\x{8BA8}\x{8BA9}\x{8BAA}\x{8BAB}\x{8BAC}\x{8BAD}\x{8BAE}\x{8BAF}' . + '\x{8BB0}\x{8BB1}\x{8BB2}\x{8BB3}\x{8BB4}\x{8BB5}\x{8BB6}\x{8BB7}\x{8BB8}' . + '\x{8BB9}\x{8BBA}\x{8BBB}\x{8BBC}\x{8BBD}\x{8BBE}\x{8BBF}\x{8BC0}\x{8BC1}' . + '\x{8BC2}\x{8BC3}\x{8BC4}\x{8BC5}\x{8BC6}\x{8BC7}\x{8BC8}\x{8BC9}\x{8BCA}' . + '\x{8BCB}\x{8BCC}\x{8BCD}\x{8BCE}\x{8BCF}\x{8BD0}\x{8BD1}\x{8BD2}\x{8BD3}' . + '\x{8BD4}\x{8BD5}\x{8BD6}\x{8BD7}\x{8BD8}\x{8BD9}\x{8BDA}\x{8BDB}\x{8BDC}' . + '\x{8BDD}\x{8BDE}\x{8BDF}\x{8BE0}\x{8BE1}\x{8BE2}\x{8BE3}\x{8BE4}\x{8BE5}' . + '\x{8BE6}\x{8BE7}\x{8BE8}\x{8BE9}\x{8BEA}\x{8BEB}\x{8BEC}\x{8BED}\x{8BEE}' . + '\x{8BEF}\x{8BF0}\x{8BF1}\x{8BF2}\x{8BF3}\x{8BF4}\x{8BF5}\x{8BF6}\x{8BF7}' . + '\x{8BF8}\x{8BF9}\x{8BFA}\x{8BFB}\x{8BFC}\x{8BFD}\x{8BFE}\x{8BFF}\x{8C00}' . + '\x{8C01}\x{8C02}\x{8C03}\x{8C04}\x{8C05}\x{8C06}\x{8C07}\x{8C08}\x{8C09}' . + '\x{8C0A}\x{8C0B}\x{8C0C}\x{8C0D}\x{8C0E}\x{8C0F}\x{8C10}\x{8C11}\x{8C12}' . + '\x{8C13}\x{8C14}\x{8C15}\x{8C16}\x{8C17}\x{8C18}\x{8C19}\x{8C1A}\x{8C1B}' . + '\x{8C1C}\x{8C1D}\x{8C1E}\x{8C1F}\x{8C20}\x{8C21}\x{8C22}\x{8C23}\x{8C24}' . + '\x{8C25}\x{8C26}\x{8C27}\x{8C28}\x{8C29}\x{8C2A}\x{8C2B}\x{8C2C}\x{8C2D}' . + '\x{8C2E}\x{8C2F}\x{8C30}\x{8C31}\x{8C32}\x{8C33}\x{8C34}\x{8C35}\x{8C36}' . + '\x{8C37}\x{8C39}\x{8C3A}\x{8C3B}\x{8C3C}\x{8C3D}\x{8C3E}\x{8C3F}\x{8C41}' . + '\x{8C42}\x{8C43}\x{8C45}\x{8C46}\x{8C47}\x{8C48}\x{8C49}\x{8C4A}\x{8C4B}' . + '\x{8C4C}\x{8C4D}\x{8C4E}\x{8C4F}\x{8C50}\x{8C54}\x{8C55}\x{8C56}\x{8C57}' . + '\x{8C59}\x{8C5A}\x{8C5B}\x{8C5C}\x{8C5D}\x{8C5E}\x{8C5F}\x{8C60}\x{8C61}' . + '\x{8C62}\x{8C63}\x{8C64}\x{8C65}\x{8C66}\x{8C67}\x{8C68}\x{8C69}\x{8C6A}' . + '\x{8C6B}\x{8C6C}\x{8C6D}\x{8C6E}\x{8C6F}\x{8C70}\x{8C71}\x{8C72}\x{8C73}' . + '\x{8C75}\x{8C76}\x{8C77}\x{8C78}\x{8C79}\x{8C7A}\x{8C7B}\x{8C7D}\x{8C7E}' . + '\x{8C80}\x{8C81}\x{8C82}\x{8C84}\x{8C85}\x{8C86}\x{8C88}\x{8C89}\x{8C8A}' . + '\x{8C8C}\x{8C8D}\x{8C8F}\x{8C90}\x{8C91}\x{8C92}\x{8C93}\x{8C94}\x{8C95}' . + '\x{8C96}\x{8C97}\x{8C98}\x{8C99}\x{8C9A}\x{8C9C}\x{8C9D}\x{8C9E}\x{8C9F}' . + '\x{8CA0}\x{8CA1}\x{8CA2}\x{8CA3}\x{8CA4}\x{8CA5}\x{8CA7}\x{8CA8}\x{8CA9}' . + '\x{8CAA}\x{8CAB}\x{8CAC}\x{8CAD}\x{8CAE}\x{8CAF}\x{8CB0}\x{8CB1}\x{8CB2}' . + '\x{8CB3}\x{8CB4}\x{8CB5}\x{8CB6}\x{8CB7}\x{8CB8}\x{8CB9}\x{8CBA}\x{8CBB}' . + '\x{8CBC}\x{8CBD}\x{8CBE}\x{8CBF}\x{8CC0}\x{8CC1}\x{8CC2}\x{8CC3}\x{8CC4}' . + '\x{8CC5}\x{8CC6}\x{8CC7}\x{8CC8}\x{8CC9}\x{8CCA}\x{8CCC}\x{8CCE}\x{8CCF}' . + '\x{8CD0}\x{8CD1}\x{8CD2}\x{8CD3}\x{8CD4}\x{8CD5}\x{8CD7}\x{8CD9}\x{8CDA}' . + '\x{8CDB}\x{8CDC}\x{8CDD}\x{8CDE}\x{8CDF}\x{8CE0}\x{8CE1}\x{8CE2}\x{8CE3}' . + '\x{8CE4}\x{8CE5}\x{8CE6}\x{8CE7}\x{8CE8}\x{8CEA}\x{8CEB}\x{8CEC}\x{8CED}' . + '\x{8CEE}\x{8CEF}\x{8CF0}\x{8CF1}\x{8CF2}\x{8CF3}\x{8CF4}\x{8CF5}\x{8CF6}' . + '\x{8CF8}\x{8CF9}\x{8CFA}\x{8CFB}\x{8CFC}\x{8CFD}\x{8CFE}\x{8CFF}\x{8D00}' . + '\x{8D02}\x{8D03}\x{8D04}\x{8D05}\x{8D06}\x{8D07}\x{8D08}\x{8D09}\x{8D0A}' . + '\x{8D0B}\x{8D0C}\x{8D0D}\x{8D0E}\x{8D0F}\x{8D10}\x{8D13}\x{8D14}\x{8D15}' . + '\x{8D16}\x{8D17}\x{8D18}\x{8D19}\x{8D1A}\x{8D1B}\x{8D1C}\x{8D1D}\x{8D1E}' . + '\x{8D1F}\x{8D20}\x{8D21}\x{8D22}\x{8D23}\x{8D24}\x{8D25}\x{8D26}\x{8D27}' . + '\x{8D28}\x{8D29}\x{8D2A}\x{8D2B}\x{8D2C}\x{8D2D}\x{8D2E}\x{8D2F}\x{8D30}' . + '\x{8D31}\x{8D32}\x{8D33}\x{8D34}\x{8D35}\x{8D36}\x{8D37}\x{8D38}\x{8D39}' . + '\x{8D3A}\x{8D3B}\x{8D3C}\x{8D3D}\x{8D3E}\x{8D3F}\x{8D40}\x{8D41}\x{8D42}' . + '\x{8D43}\x{8D44}\x{8D45}\x{8D46}\x{8D47}\x{8D48}\x{8D49}\x{8D4A}\x{8D4B}' . + '\x{8D4C}\x{8D4D}\x{8D4E}\x{8D4F}\x{8D50}\x{8D51}\x{8D52}\x{8D53}\x{8D54}' . + '\x{8D55}\x{8D56}\x{8D57}\x{8D58}\x{8D59}\x{8D5A}\x{8D5B}\x{8D5C}\x{8D5D}' . + '\x{8D5E}\x{8D5F}\x{8D60}\x{8D61}\x{8D62}\x{8D63}\x{8D64}\x{8D65}\x{8D66}' . + '\x{8D67}\x{8D68}\x{8D69}\x{8D6A}\x{8D6B}\x{8D6C}\x{8D6D}\x{8D6E}\x{8D6F}' . + '\x{8D70}\x{8D71}\x{8D72}\x{8D73}\x{8D74}\x{8D75}\x{8D76}\x{8D77}\x{8D78}' . + '\x{8D79}\x{8D7A}\x{8D7B}\x{8D7D}\x{8D7E}\x{8D7F}\x{8D80}\x{8D81}\x{8D82}' . + '\x{8D83}\x{8D84}\x{8D85}\x{8D86}\x{8D87}\x{8D88}\x{8D89}\x{8D8A}\x{8D8B}' . + '\x{8D8C}\x{8D8D}\x{8D8E}\x{8D8F}\x{8D90}\x{8D91}\x{8D92}\x{8D93}\x{8D94}' . + '\x{8D95}\x{8D96}\x{8D97}\x{8D98}\x{8D99}\x{8D9A}\x{8D9B}\x{8D9C}\x{8D9D}' . + '\x{8D9E}\x{8D9F}\x{8DA0}\x{8DA1}\x{8DA2}\x{8DA3}\x{8DA4}\x{8DA5}\x{8DA7}' . + '\x{8DA8}\x{8DA9}\x{8DAA}\x{8DAB}\x{8DAC}\x{8DAD}\x{8DAE}\x{8DAF}\x{8DB0}' . + '\x{8DB1}\x{8DB2}\x{8DB3}\x{8DB4}\x{8DB5}\x{8DB6}\x{8DB7}\x{8DB8}\x{8DB9}' . + '\x{8DBA}\x{8DBB}\x{8DBC}\x{8DBD}\x{8DBE}\x{8DBF}\x{8DC1}\x{8DC2}\x{8DC3}' . + '\x{8DC4}\x{8DC5}\x{8DC6}\x{8DC7}\x{8DC8}\x{8DC9}\x{8DCA}\x{8DCB}\x{8DCC}' . + '\x{8DCD}\x{8DCE}\x{8DCF}\x{8DD0}\x{8DD1}\x{8DD2}\x{8DD3}\x{8DD4}\x{8DD5}' . + '\x{8DD6}\x{8DD7}\x{8DD8}\x{8DD9}\x{8DDA}\x{8DDB}\x{8DDC}\x{8DDD}\x{8DDE}' . + '\x{8DDF}\x{8DE0}\x{8DE1}\x{8DE2}\x{8DE3}\x{8DE4}\x{8DE6}\x{8DE7}\x{8DE8}' . + '\x{8DE9}\x{8DEA}\x{8DEB}\x{8DEC}\x{8DED}\x{8DEE}\x{8DEF}\x{8DF0}\x{8DF1}' . + '\x{8DF2}\x{8DF3}\x{8DF4}\x{8DF5}\x{8DF6}\x{8DF7}\x{8DF8}\x{8DF9}\x{8DFA}' . + '\x{8DFB}\x{8DFC}\x{8DFD}\x{8DFE}\x{8DFF}\x{8E00}\x{8E02}\x{8E03}\x{8E04}' . + '\x{8E05}\x{8E06}\x{8E07}\x{8E08}\x{8E09}\x{8E0A}\x{8E0C}\x{8E0D}\x{8E0E}' . + '\x{8E0F}\x{8E10}\x{8E11}\x{8E12}\x{8E13}\x{8E14}\x{8E15}\x{8E16}\x{8E17}' . + '\x{8E18}\x{8E19}\x{8E1A}\x{8E1B}\x{8E1C}\x{8E1D}\x{8E1E}\x{8E1F}\x{8E20}' . + '\x{8E21}\x{8E22}\x{8E23}\x{8E24}\x{8E25}\x{8E26}\x{8E27}\x{8E28}\x{8E29}' . + '\x{8E2A}\x{8E2B}\x{8E2C}\x{8E2D}\x{8E2E}\x{8E2F}\x{8E30}\x{8E31}\x{8E33}' . + '\x{8E34}\x{8E35}\x{8E36}\x{8E37}\x{8E38}\x{8E39}\x{8E3A}\x{8E3B}\x{8E3C}' . + '\x{8E3D}\x{8E3E}\x{8E3F}\x{8E40}\x{8E41}\x{8E42}\x{8E43}\x{8E44}\x{8E45}' . + '\x{8E47}\x{8E48}\x{8E49}\x{8E4A}\x{8E4B}\x{8E4C}\x{8E4D}\x{8E4E}\x{8E50}' . + '\x{8E51}\x{8E52}\x{8E53}\x{8E54}\x{8E55}\x{8E56}\x{8E57}\x{8E58}\x{8E59}' . + '\x{8E5A}\x{8E5B}\x{8E5C}\x{8E5D}\x{8E5E}\x{8E5F}\x{8E60}\x{8E61}\x{8E62}' . + '\x{8E63}\x{8E64}\x{8E65}\x{8E66}\x{8E67}\x{8E68}\x{8E69}\x{8E6A}\x{8E6B}' . + '\x{8E6C}\x{8E6D}\x{8E6F}\x{8E70}\x{8E71}\x{8E72}\x{8E73}\x{8E74}\x{8E76}' . + '\x{8E78}\x{8E7A}\x{8E7B}\x{8E7C}\x{8E7D}\x{8E7E}\x{8E7F}\x{8E80}\x{8E81}' . + '\x{8E82}\x{8E83}\x{8E84}\x{8E85}\x{8E86}\x{8E87}\x{8E88}\x{8E89}\x{8E8A}' . + '\x{8E8B}\x{8E8C}\x{8E8D}\x{8E8E}\x{8E8F}\x{8E90}\x{8E91}\x{8E92}\x{8E93}' . + '\x{8E94}\x{8E95}\x{8E96}\x{8E97}\x{8E98}\x{8E9A}\x{8E9C}\x{8E9D}\x{8E9E}' . + '\x{8E9F}\x{8EA0}\x{8EA1}\x{8EA3}\x{8EA4}\x{8EA5}\x{8EA6}\x{8EA7}\x{8EA8}' . + '\x{8EA9}\x{8EAA}\x{8EAB}\x{8EAC}\x{8EAD}\x{8EAE}\x{8EAF}\x{8EB0}\x{8EB1}' . + '\x{8EB2}\x{8EB4}\x{8EB5}\x{8EB8}\x{8EB9}\x{8EBA}\x{8EBB}\x{8EBC}\x{8EBD}' . + '\x{8EBE}\x{8EBF}\x{8EC0}\x{8EC2}\x{8EC3}\x{8EC5}\x{8EC6}\x{8EC7}\x{8EC8}' . + '\x{8EC9}\x{8ECA}\x{8ECB}\x{8ECC}\x{8ECD}\x{8ECE}\x{8ECF}\x{8ED0}\x{8ED1}' . + '\x{8ED2}\x{8ED3}\x{8ED4}\x{8ED5}\x{8ED6}\x{8ED7}\x{8ED8}\x{8EDA}\x{8EDB}' . + '\x{8EDC}\x{8EDD}\x{8EDE}\x{8EDF}\x{8EE0}\x{8EE1}\x{8EE4}\x{8EE5}\x{8EE6}' . + '\x{8EE7}\x{8EE8}\x{8EE9}\x{8EEA}\x{8EEB}\x{8EEC}\x{8EED}\x{8EEE}\x{8EEF}' . + '\x{8EF1}\x{8EF2}\x{8EF3}\x{8EF4}\x{8EF5}\x{8EF6}\x{8EF7}\x{8EF8}\x{8EF9}' . + '\x{8EFA}\x{8EFB}\x{8EFC}\x{8EFD}\x{8EFE}\x{8EFF}\x{8F00}\x{8F01}\x{8F02}' . + '\x{8F03}\x{8F04}\x{8F05}\x{8F06}\x{8F07}\x{8F08}\x{8F09}\x{8F0A}\x{8F0B}' . + '\x{8F0D}\x{8F0E}\x{8F10}\x{8F11}\x{8F12}\x{8F13}\x{8F14}\x{8F15}\x{8F16}' . + '\x{8F17}\x{8F18}\x{8F1A}\x{8F1B}\x{8F1C}\x{8F1D}\x{8F1E}\x{8F1F}\x{8F20}' . + '\x{8F21}\x{8F22}\x{8F23}\x{8F24}\x{8F25}\x{8F26}\x{8F27}\x{8F28}\x{8F29}' . + '\x{8F2A}\x{8F2B}\x{8F2C}\x{8F2E}\x{8F2F}\x{8F30}\x{8F31}\x{8F32}\x{8F33}' . + '\x{8F34}\x{8F35}\x{8F36}\x{8F37}\x{8F38}\x{8F39}\x{8F3B}\x{8F3C}\x{8F3D}' . + '\x{8F3E}\x{8F3F}\x{8F40}\x{8F42}\x{8F43}\x{8F44}\x{8F45}\x{8F46}\x{8F47}' . + '\x{8F48}\x{8F49}\x{8F4A}\x{8F4B}\x{8F4C}\x{8F4D}\x{8F4E}\x{8F4F}\x{8F50}' . + '\x{8F51}\x{8F52}\x{8F53}\x{8F54}\x{8F55}\x{8F56}\x{8F57}\x{8F58}\x{8F59}' . + '\x{8F5A}\x{8F5B}\x{8F5D}\x{8F5E}\x{8F5F}\x{8F60}\x{8F61}\x{8F62}\x{8F63}' . + '\x{8F64}\x{8F65}\x{8F66}\x{8F67}\x{8F68}\x{8F69}\x{8F6A}\x{8F6B}\x{8F6C}' . + '\x{8F6D}\x{8F6E}\x{8F6F}\x{8F70}\x{8F71}\x{8F72}\x{8F73}\x{8F74}\x{8F75}' . + '\x{8F76}\x{8F77}\x{8F78}\x{8F79}\x{8F7A}\x{8F7B}\x{8F7C}\x{8F7D}\x{8F7E}' . + '\x{8F7F}\x{8F80}\x{8F81}\x{8F82}\x{8F83}\x{8F84}\x{8F85}\x{8F86}\x{8F87}' . + '\x{8F88}\x{8F89}\x{8F8A}\x{8F8B}\x{8F8C}\x{8F8D}\x{8F8E}\x{8F8F}\x{8F90}' . + '\x{8F91}\x{8F92}\x{8F93}\x{8F94}\x{8F95}\x{8F96}\x{8F97}\x{8F98}\x{8F99}' . + '\x{8F9A}\x{8F9B}\x{8F9C}\x{8F9E}\x{8F9F}\x{8FA0}\x{8FA1}\x{8FA2}\x{8FA3}' . + '\x{8FA5}\x{8FA6}\x{8FA7}\x{8FA8}\x{8FA9}\x{8FAA}\x{8FAB}\x{8FAC}\x{8FAD}' . + '\x{8FAE}\x{8FAF}\x{8FB0}\x{8FB1}\x{8FB2}\x{8FB4}\x{8FB5}\x{8FB6}\x{8FB7}' . + '\x{8FB8}\x{8FB9}\x{8FBB}\x{8FBC}\x{8FBD}\x{8FBE}\x{8FBF}\x{8FC0}\x{8FC1}' . + '\x{8FC2}\x{8FC4}\x{8FC5}\x{8FC6}\x{8FC7}\x{8FC8}\x{8FC9}\x{8FCB}\x{8FCC}' . + '\x{8FCD}\x{8FCE}\x{8FCF}\x{8FD0}\x{8FD1}\x{8FD2}\x{8FD3}\x{8FD4}\x{8FD5}' . + '\x{8FD6}\x{8FD7}\x{8FD8}\x{8FD9}\x{8FDA}\x{8FDB}\x{8FDC}\x{8FDD}\x{8FDE}' . + '\x{8FDF}\x{8FE0}\x{8FE1}\x{8FE2}\x{8FE3}\x{8FE4}\x{8FE5}\x{8FE6}\x{8FE8}' . + '\x{8FE9}\x{8FEA}\x{8FEB}\x{8FEC}\x{8FED}\x{8FEE}\x{8FEF}\x{8FF0}\x{8FF1}' . + '\x{8FF2}\x{8FF3}\x{8FF4}\x{8FF5}\x{8FF6}\x{8FF7}\x{8FF8}\x{8FF9}\x{8FFA}' . + '\x{8FFB}\x{8FFC}\x{8FFD}\x{8FFE}\x{8FFF}\x{9000}\x{9001}\x{9002}\x{9003}' . + '\x{9004}\x{9005}\x{9006}\x{9007}\x{9008}\x{9009}\x{900A}\x{900B}\x{900C}' . + '\x{900D}\x{900F}\x{9010}\x{9011}\x{9012}\x{9013}\x{9014}\x{9015}\x{9016}' . + '\x{9017}\x{9018}\x{9019}\x{901A}\x{901B}\x{901C}\x{901D}\x{901E}\x{901F}' . + '\x{9020}\x{9021}\x{9022}\x{9023}\x{9024}\x{9025}\x{9026}\x{9027}\x{9028}' . + '\x{9029}\x{902B}\x{902D}\x{902E}\x{902F}\x{9030}\x{9031}\x{9032}\x{9033}' . + '\x{9034}\x{9035}\x{9036}\x{9038}\x{903A}\x{903B}\x{903C}\x{903D}\x{903E}' . + '\x{903F}\x{9041}\x{9042}\x{9043}\x{9044}\x{9045}\x{9047}\x{9048}\x{9049}' . + '\x{904A}\x{904B}\x{904C}\x{904D}\x{904E}\x{904F}\x{9050}\x{9051}\x{9052}' . + '\x{9053}\x{9054}\x{9055}\x{9056}\x{9057}\x{9058}\x{9059}\x{905A}\x{905B}' . + '\x{905C}\x{905D}\x{905E}\x{905F}\x{9060}\x{9061}\x{9062}\x{9063}\x{9064}' . + '\x{9065}\x{9066}\x{9067}\x{9068}\x{9069}\x{906A}\x{906B}\x{906C}\x{906D}' . + '\x{906E}\x{906F}\x{9070}\x{9071}\x{9072}\x{9073}\x{9074}\x{9075}\x{9076}' . + '\x{9077}\x{9078}\x{9079}\x{907A}\x{907B}\x{907C}\x{907D}\x{907E}\x{907F}' . + '\x{9080}\x{9081}\x{9082}\x{9083}\x{9084}\x{9085}\x{9086}\x{9087}\x{9088}' . + '\x{9089}\x{908A}\x{908B}\x{908C}\x{908D}\x{908E}\x{908F}\x{9090}\x{9091}' . + '\x{9092}\x{9093}\x{9094}\x{9095}\x{9096}\x{9097}\x{9098}\x{9099}\x{909A}' . + '\x{909B}\x{909C}\x{909D}\x{909E}\x{909F}\x{90A0}\x{90A1}\x{90A2}\x{90A3}' . + '\x{90A4}\x{90A5}\x{90A6}\x{90A7}\x{90A8}\x{90A9}\x{90AA}\x{90AC}\x{90AD}' . + '\x{90AE}\x{90AF}\x{90B0}\x{90B1}\x{90B2}\x{90B3}\x{90B4}\x{90B5}\x{90B6}' . + '\x{90B7}\x{90B8}\x{90B9}\x{90BA}\x{90BB}\x{90BC}\x{90BD}\x{90BE}\x{90BF}' . + '\x{90C0}\x{90C1}\x{90C2}\x{90C3}\x{90C4}\x{90C5}\x{90C6}\x{90C7}\x{90C8}' . + '\x{90C9}\x{90CA}\x{90CB}\x{90CE}\x{90CF}\x{90D0}\x{90D1}\x{90D3}\x{90D4}' . + '\x{90D5}\x{90D6}\x{90D7}\x{90D8}\x{90D9}\x{90DA}\x{90DB}\x{90DC}\x{90DD}' . + '\x{90DE}\x{90DF}\x{90E0}\x{90E1}\x{90E2}\x{90E3}\x{90E4}\x{90E5}\x{90E6}' . + '\x{90E7}\x{90E8}\x{90E9}\x{90EA}\x{90EB}\x{90EC}\x{90ED}\x{90EE}\x{90EF}' . + '\x{90F0}\x{90F1}\x{90F2}\x{90F3}\x{90F4}\x{90F5}\x{90F7}\x{90F8}\x{90F9}' . + '\x{90FA}\x{90FB}\x{90FC}\x{90FD}\x{90FE}\x{90FF}\x{9100}\x{9101}\x{9102}' . + '\x{9103}\x{9104}\x{9105}\x{9106}\x{9107}\x{9108}\x{9109}\x{910B}\x{910C}' . + '\x{910D}\x{910E}\x{910F}\x{9110}\x{9111}\x{9112}\x{9113}\x{9114}\x{9115}' . + '\x{9116}\x{9117}\x{9118}\x{9119}\x{911A}\x{911B}\x{911C}\x{911D}\x{911E}' . + '\x{911F}\x{9120}\x{9121}\x{9122}\x{9123}\x{9124}\x{9125}\x{9126}\x{9127}' . + '\x{9128}\x{9129}\x{912A}\x{912B}\x{912C}\x{912D}\x{912E}\x{912F}\x{9130}' . + '\x{9131}\x{9132}\x{9133}\x{9134}\x{9135}\x{9136}\x{9137}\x{9138}\x{9139}' . + '\x{913A}\x{913B}\x{913E}\x{913F}\x{9140}\x{9141}\x{9142}\x{9143}\x{9144}' . + '\x{9145}\x{9146}\x{9147}\x{9148}\x{9149}\x{914A}\x{914B}\x{914C}\x{914D}' . + '\x{914E}\x{914F}\x{9150}\x{9151}\x{9152}\x{9153}\x{9154}\x{9155}\x{9156}' . + '\x{9157}\x{9158}\x{915A}\x{915B}\x{915C}\x{915D}\x{915E}\x{915F}\x{9160}' . + '\x{9161}\x{9162}\x{9163}\x{9164}\x{9165}\x{9166}\x{9167}\x{9168}\x{9169}' . + '\x{916A}\x{916B}\x{916C}\x{916D}\x{916E}\x{916F}\x{9170}\x{9171}\x{9172}' . + '\x{9173}\x{9174}\x{9175}\x{9176}\x{9177}\x{9178}\x{9179}\x{917A}\x{917C}' . + '\x{917D}\x{917E}\x{917F}\x{9180}\x{9181}\x{9182}\x{9183}\x{9184}\x{9185}' . + '\x{9186}\x{9187}\x{9188}\x{9189}\x{918A}\x{918B}\x{918C}\x{918D}\x{918E}' . + '\x{918F}\x{9190}\x{9191}\x{9192}\x{9193}\x{9194}\x{9196}\x{9199}\x{919A}' . + '\x{919B}\x{919C}\x{919D}\x{919E}\x{919F}\x{91A0}\x{91A1}\x{91A2}\x{91A3}' . + '\x{91A5}\x{91A6}\x{91A7}\x{91A8}\x{91AA}\x{91AB}\x{91AC}\x{91AD}\x{91AE}' . + '\x{91AF}\x{91B0}\x{91B1}\x{91B2}\x{91B3}\x{91B4}\x{91B5}\x{91B6}\x{91B7}' . + '\x{91B9}\x{91BA}\x{91BB}\x{91BC}\x{91BD}\x{91BE}\x{91C0}\x{91C1}\x{91C2}' . + '\x{91C3}\x{91C5}\x{91C6}\x{91C7}\x{91C9}\x{91CA}\x{91CB}\x{91CC}\x{91CD}' . + '\x{91CE}\x{91CF}\x{91D0}\x{91D1}\x{91D2}\x{91D3}\x{91D4}\x{91D5}\x{91D7}' . + '\x{91D8}\x{91D9}\x{91DA}\x{91DB}\x{91DC}\x{91DD}\x{91DE}\x{91DF}\x{91E2}' . + '\x{91E3}\x{91E4}\x{91E5}\x{91E6}\x{91E7}\x{91E8}\x{91E9}\x{91EA}\x{91EB}' . + '\x{91EC}\x{91ED}\x{91EE}\x{91F0}\x{91F1}\x{91F2}\x{91F3}\x{91F4}\x{91F5}' . + '\x{91F7}\x{91F8}\x{91F9}\x{91FA}\x{91FB}\x{91FD}\x{91FE}\x{91FF}\x{9200}' . + '\x{9201}\x{9202}\x{9203}\x{9204}\x{9205}\x{9206}\x{9207}\x{9208}\x{9209}' . + '\x{920A}\x{920B}\x{920C}\x{920D}\x{920E}\x{920F}\x{9210}\x{9211}\x{9212}' . + '\x{9214}\x{9215}\x{9216}\x{9217}\x{9218}\x{9219}\x{921A}\x{921B}\x{921C}' . + '\x{921D}\x{921E}\x{9220}\x{9221}\x{9223}\x{9224}\x{9225}\x{9226}\x{9227}' . + '\x{9228}\x{9229}\x{922A}\x{922B}\x{922D}\x{922E}\x{922F}\x{9230}\x{9231}' . + '\x{9232}\x{9233}\x{9234}\x{9235}\x{9236}\x{9237}\x{9238}\x{9239}\x{923A}' . + '\x{923B}\x{923C}\x{923D}\x{923E}\x{923F}\x{9240}\x{9241}\x{9242}\x{9245}' . + '\x{9246}\x{9247}\x{9248}\x{9249}\x{924A}\x{924B}\x{924C}\x{924D}\x{924E}' . + '\x{924F}\x{9250}\x{9251}\x{9252}\x{9253}\x{9254}\x{9255}\x{9256}\x{9257}' . + '\x{9258}\x{9259}\x{925A}\x{925B}\x{925C}\x{925D}\x{925E}\x{925F}\x{9260}' . + '\x{9261}\x{9262}\x{9263}\x{9264}\x{9265}\x{9266}\x{9267}\x{9268}\x{926B}' . + '\x{926C}\x{926D}\x{926E}\x{926F}\x{9270}\x{9272}\x{9273}\x{9274}\x{9275}' . + '\x{9276}\x{9277}\x{9278}\x{9279}\x{927A}\x{927B}\x{927C}\x{927D}\x{927E}' . + '\x{927F}\x{9280}\x{9282}\x{9283}\x{9285}\x{9286}\x{9287}\x{9288}\x{9289}' . + '\x{928A}\x{928B}\x{928C}\x{928D}\x{928E}\x{928F}\x{9290}\x{9291}\x{9292}' . + '\x{9293}\x{9294}\x{9295}\x{9296}\x{9297}\x{9298}\x{9299}\x{929A}\x{929B}' . + '\x{929C}\x{929D}\x{929F}\x{92A0}\x{92A1}\x{92A2}\x{92A3}\x{92A4}\x{92A5}' . + '\x{92A6}\x{92A7}\x{92A8}\x{92A9}\x{92AA}\x{92AB}\x{92AC}\x{92AD}\x{92AE}' . + '\x{92AF}\x{92B0}\x{92B1}\x{92B2}\x{92B3}\x{92B4}\x{92B5}\x{92B6}\x{92B7}' . + '\x{92B8}\x{92B9}\x{92BA}\x{92BB}\x{92BC}\x{92BE}\x{92BF}\x{92C0}\x{92C1}' . + '\x{92C2}\x{92C3}\x{92C4}\x{92C5}\x{92C6}\x{92C7}\x{92C8}\x{92C9}\x{92CA}' . + '\x{92CB}\x{92CC}\x{92CD}\x{92CE}\x{92CF}\x{92D0}\x{92D1}\x{92D2}\x{92D3}' . + '\x{92D5}\x{92D6}\x{92D7}\x{92D8}\x{92D9}\x{92DA}\x{92DC}\x{92DD}\x{92DE}' . + '\x{92DF}\x{92E0}\x{92E1}\x{92E3}\x{92E4}\x{92E5}\x{92E6}\x{92E7}\x{92E8}' . + '\x{92E9}\x{92EA}\x{92EB}\x{92EC}\x{92ED}\x{92EE}\x{92EF}\x{92F0}\x{92F1}' . + '\x{92F2}\x{92F3}\x{92F4}\x{92F5}\x{92F6}\x{92F7}\x{92F8}\x{92F9}\x{92FA}' . + '\x{92FB}\x{92FC}\x{92FD}\x{92FE}\x{92FF}\x{9300}\x{9301}\x{9302}\x{9303}' . + '\x{9304}\x{9305}\x{9306}\x{9307}\x{9308}\x{9309}\x{930A}\x{930B}\x{930C}' . + '\x{930D}\x{930E}\x{930F}\x{9310}\x{9311}\x{9312}\x{9313}\x{9314}\x{9315}' . + '\x{9316}\x{9317}\x{9318}\x{9319}\x{931A}\x{931B}\x{931D}\x{931E}\x{931F}' . + '\x{9320}\x{9321}\x{9322}\x{9323}\x{9324}\x{9325}\x{9326}\x{9327}\x{9328}' . + '\x{9329}\x{932A}\x{932B}\x{932D}\x{932E}\x{932F}\x{9332}\x{9333}\x{9334}' . + '\x{9335}\x{9336}\x{9337}\x{9338}\x{9339}\x{933A}\x{933B}\x{933C}\x{933D}' . + '\x{933E}\x{933F}\x{9340}\x{9341}\x{9342}\x{9343}\x{9344}\x{9345}\x{9346}' . + '\x{9347}\x{9348}\x{9349}\x{934A}\x{934B}\x{934C}\x{934D}\x{934E}\x{934F}' . + '\x{9350}\x{9351}\x{9352}\x{9353}\x{9354}\x{9355}\x{9356}\x{9357}\x{9358}' . + '\x{9359}\x{935A}\x{935B}\x{935C}\x{935D}\x{935E}\x{935F}\x{9360}\x{9361}' . + '\x{9363}\x{9364}\x{9365}\x{9366}\x{9367}\x{9369}\x{936A}\x{936C}\x{936D}' . + '\x{936E}\x{9370}\x{9371}\x{9372}\x{9374}\x{9375}\x{9376}\x{9377}\x{9379}' . + '\x{937A}\x{937B}\x{937C}\x{937D}\x{937E}\x{9380}\x{9382}\x{9383}\x{9384}' . + '\x{9385}\x{9386}\x{9387}\x{9388}\x{9389}\x{938A}\x{938C}\x{938D}\x{938E}' . + '\x{938F}\x{9390}\x{9391}\x{9392}\x{9393}\x{9394}\x{9395}\x{9396}\x{9397}' . + '\x{9398}\x{9399}\x{939A}\x{939B}\x{939D}\x{939E}\x{939F}\x{93A1}\x{93A2}' . + '\x{93A3}\x{93A4}\x{93A5}\x{93A6}\x{93A7}\x{93A8}\x{93A9}\x{93AA}\x{93AC}' . + '\x{93AD}\x{93AE}\x{93AF}\x{93B0}\x{93B1}\x{93B2}\x{93B3}\x{93B4}\x{93B5}' . + '\x{93B6}\x{93B7}\x{93B8}\x{93B9}\x{93BA}\x{93BC}\x{93BD}\x{93BE}\x{93BF}' . + '\x{93C0}\x{93C1}\x{93C2}\x{93C3}\x{93C4}\x{93C5}\x{93C6}\x{93C7}\x{93C8}' . + '\x{93C9}\x{93CA}\x{93CB}\x{93CC}\x{93CD}\x{93CE}\x{93CF}\x{93D0}\x{93D1}' . + '\x{93D2}\x{93D3}\x{93D4}\x{93D5}\x{93D6}\x{93D7}\x{93D8}\x{93D9}\x{93DA}' . + '\x{93DB}\x{93DC}\x{93DD}\x{93DE}\x{93DF}\x{93E1}\x{93E2}\x{93E3}\x{93E4}' . + '\x{93E6}\x{93E7}\x{93E8}\x{93E9}\x{93EA}\x{93EB}\x{93EC}\x{93ED}\x{93EE}' . + '\x{93EF}\x{93F0}\x{93F1}\x{93F2}\x{93F4}\x{93F5}\x{93F6}\x{93F7}\x{93F8}' . + '\x{93F9}\x{93FA}\x{93FB}\x{93FC}\x{93FD}\x{93FE}\x{93FF}\x{9400}\x{9401}' . + '\x{9403}\x{9404}\x{9405}\x{9406}\x{9407}\x{9408}\x{9409}\x{940A}\x{940B}' . + '\x{940C}\x{940D}\x{940E}\x{940F}\x{9410}\x{9411}\x{9412}\x{9413}\x{9414}' . + '\x{9415}\x{9416}\x{9418}\x{9419}\x{941B}\x{941D}\x{9420}\x{9422}\x{9423}' . + '\x{9425}\x{9426}\x{9427}\x{9428}\x{9429}\x{942A}\x{942B}\x{942C}\x{942D}' . + '\x{942E}\x{942F}\x{9430}\x{9431}\x{9432}\x{9433}\x{9434}\x{9435}\x{9436}' . + '\x{9437}\x{9438}\x{9439}\x{943A}\x{943B}\x{943C}\x{943D}\x{943E}\x{943F}' . + '\x{9440}\x{9441}\x{9442}\x{9444}\x{9445}\x{9446}\x{9447}\x{9448}\x{9449}' . + '\x{944A}\x{944B}\x{944C}\x{944D}\x{944F}\x{9450}\x{9451}\x{9452}\x{9453}' . + '\x{9454}\x{9455}\x{9456}\x{9457}\x{9458}\x{9459}\x{945B}\x{945C}\x{945D}' . + '\x{945E}\x{945F}\x{9460}\x{9461}\x{9462}\x{9463}\x{9464}\x{9465}\x{9466}' . + '\x{9467}\x{9468}\x{9469}\x{946A}\x{946B}\x{946D}\x{946E}\x{946F}\x{9470}' . + '\x{9471}\x{9472}\x{9473}\x{9474}\x{9475}\x{9476}\x{9477}\x{9478}\x{9479}' . + '\x{947A}\x{947C}\x{947D}\x{947E}\x{947F}\x{9480}\x{9481}\x{9482}\x{9483}' . + '\x{9484}\x{9485}\x{9486}\x{9487}\x{9488}\x{9489}\x{948A}\x{948B}\x{948C}' . + '\x{948D}\x{948E}\x{948F}\x{9490}\x{9491}\x{9492}\x{9493}\x{9494}\x{9495}' . + '\x{9496}\x{9497}\x{9498}\x{9499}\x{949A}\x{949B}\x{949C}\x{949D}\x{949E}' . + '\x{949F}\x{94A0}\x{94A1}\x{94A2}\x{94A3}\x{94A4}\x{94A5}\x{94A6}\x{94A7}' . + '\x{94A8}\x{94A9}\x{94AA}\x{94AB}\x{94AC}\x{94AD}\x{94AE}\x{94AF}\x{94B0}' . + '\x{94B1}\x{94B2}\x{94B3}\x{94B4}\x{94B5}\x{94B6}\x{94B7}\x{94B8}\x{94B9}' . + '\x{94BA}\x{94BB}\x{94BC}\x{94BD}\x{94BE}\x{94BF}\x{94C0}\x{94C1}\x{94C2}' . + '\x{94C3}\x{94C4}\x{94C5}\x{94C6}\x{94C7}\x{94C8}\x{94C9}\x{94CA}\x{94CB}' . + '\x{94CC}\x{94CD}\x{94CE}\x{94CF}\x{94D0}\x{94D1}\x{94D2}\x{94D3}\x{94D4}' . + '\x{94D5}\x{94D6}\x{94D7}\x{94D8}\x{94D9}\x{94DA}\x{94DB}\x{94DC}\x{94DD}' . + '\x{94DE}\x{94DF}\x{94E0}\x{94E1}\x{94E2}\x{94E3}\x{94E4}\x{94E5}\x{94E6}' . + '\x{94E7}\x{94E8}\x{94E9}\x{94EA}\x{94EB}\x{94EC}\x{94ED}\x{94EE}\x{94EF}' . + '\x{94F0}\x{94F1}\x{94F2}\x{94F3}\x{94F4}\x{94F5}\x{94F6}\x{94F7}\x{94F8}' . + '\x{94F9}\x{94FA}\x{94FB}\x{94FC}\x{94FD}\x{94FE}\x{94FF}\x{9500}\x{9501}' . + '\x{9502}\x{9503}\x{9504}\x{9505}\x{9506}\x{9507}\x{9508}\x{9509}\x{950A}' . + '\x{950B}\x{950C}\x{950D}\x{950E}\x{950F}\x{9510}\x{9511}\x{9512}\x{9513}' . + '\x{9514}\x{9515}\x{9516}\x{9517}\x{9518}\x{9519}\x{951A}\x{951B}\x{951C}' . + '\x{951D}\x{951E}\x{951F}\x{9520}\x{9521}\x{9522}\x{9523}\x{9524}\x{9525}' . + '\x{9526}\x{9527}\x{9528}\x{9529}\x{952A}\x{952B}\x{952C}\x{952D}\x{952E}' . + '\x{952F}\x{9530}\x{9531}\x{9532}\x{9533}\x{9534}\x{9535}\x{9536}\x{9537}' . + '\x{9538}\x{9539}\x{953A}\x{953B}\x{953C}\x{953D}\x{953E}\x{953F}\x{9540}' . + '\x{9541}\x{9542}\x{9543}\x{9544}\x{9545}\x{9546}\x{9547}\x{9548}\x{9549}' . + '\x{954A}\x{954B}\x{954C}\x{954D}\x{954E}\x{954F}\x{9550}\x{9551}\x{9552}' . + '\x{9553}\x{9554}\x{9555}\x{9556}\x{9557}\x{9558}\x{9559}\x{955A}\x{955B}' . + '\x{955C}\x{955D}\x{955E}\x{955F}\x{9560}\x{9561}\x{9562}\x{9563}\x{9564}' . + '\x{9565}\x{9566}\x{9567}\x{9568}\x{9569}\x{956A}\x{956B}\x{956C}\x{956D}' . + '\x{956E}\x{956F}\x{9570}\x{9571}\x{9572}\x{9573}\x{9574}\x{9575}\x{9576}' . + '\x{9577}\x{957A}\x{957B}\x{957C}\x{957D}\x{957F}\x{9580}\x{9581}\x{9582}' . + '\x{9583}\x{9584}\x{9586}\x{9587}\x{9588}\x{9589}\x{958A}\x{958B}\x{958C}' . + '\x{958D}\x{958E}\x{958F}\x{9590}\x{9591}\x{9592}\x{9593}\x{9594}\x{9595}' . + '\x{9596}\x{9598}\x{9599}\x{959A}\x{959B}\x{959C}\x{959D}\x{959E}\x{959F}' . + '\x{95A1}\x{95A2}\x{95A3}\x{95A4}\x{95A5}\x{95A6}\x{95A7}\x{95A8}\x{95A9}' . + '\x{95AA}\x{95AB}\x{95AC}\x{95AD}\x{95AE}\x{95AF}\x{95B0}\x{95B1}\x{95B2}' . + '\x{95B5}\x{95B6}\x{95B7}\x{95B9}\x{95BA}\x{95BB}\x{95BC}\x{95BD}\x{95BE}' . + '\x{95BF}\x{95C0}\x{95C2}\x{95C3}\x{95C4}\x{95C5}\x{95C6}\x{95C7}\x{95C8}' . + '\x{95C9}\x{95CA}\x{95CB}\x{95CC}\x{95CD}\x{95CE}\x{95CF}\x{95D0}\x{95D1}' . + '\x{95D2}\x{95D3}\x{95D4}\x{95D5}\x{95D6}\x{95D7}\x{95D8}\x{95DA}\x{95DB}' . + '\x{95DC}\x{95DE}\x{95DF}\x{95E0}\x{95E1}\x{95E2}\x{95E3}\x{95E4}\x{95E5}' . + '\x{95E6}\x{95E7}\x{95E8}\x{95E9}\x{95EA}\x{95EB}\x{95EC}\x{95ED}\x{95EE}' . + '\x{95EF}\x{95F0}\x{95F1}\x{95F2}\x{95F3}\x{95F4}\x{95F5}\x{95F6}\x{95F7}' . + '\x{95F8}\x{95F9}\x{95FA}\x{95FB}\x{95FC}\x{95FD}\x{95FE}\x{95FF}\x{9600}' . + '\x{9601}\x{9602}\x{9603}\x{9604}\x{9605}\x{9606}\x{9607}\x{9608}\x{9609}' . + '\x{960A}\x{960B}\x{960C}\x{960D}\x{960E}\x{960F}\x{9610}\x{9611}\x{9612}' . + '\x{9613}\x{9614}\x{9615}\x{9616}\x{9617}\x{9618}\x{9619}\x{961A}\x{961B}' . + '\x{961C}\x{961D}\x{961E}\x{961F}\x{9620}\x{9621}\x{9622}\x{9623}\x{9624}' . + '\x{9627}\x{9628}\x{962A}\x{962B}\x{962C}\x{962D}\x{962E}\x{962F}\x{9630}' . + '\x{9631}\x{9632}\x{9633}\x{9634}\x{9635}\x{9636}\x{9637}\x{9638}\x{9639}' . + '\x{963A}\x{963B}\x{963C}\x{963D}\x{963F}\x{9640}\x{9641}\x{9642}\x{9643}' . + '\x{9644}\x{9645}\x{9646}\x{9647}\x{9648}\x{9649}\x{964A}\x{964B}\x{964C}' . + '\x{964D}\x{964E}\x{964F}\x{9650}\x{9651}\x{9652}\x{9653}\x{9654}\x{9655}' . + '\x{9658}\x{9659}\x{965A}\x{965B}\x{965C}\x{965D}\x{965E}\x{965F}\x{9660}' . + '\x{9661}\x{9662}\x{9663}\x{9664}\x{9666}\x{9667}\x{9668}\x{9669}\x{966A}' . + '\x{966B}\x{966C}\x{966D}\x{966E}\x{966F}\x{9670}\x{9671}\x{9672}\x{9673}' . + '\x{9674}\x{9675}\x{9676}\x{9677}\x{9678}\x{967C}\x{967D}\x{967E}\x{9680}' . + '\x{9683}\x{9684}\x{9685}\x{9686}\x{9687}\x{9688}\x{9689}\x{968A}\x{968B}' . + '\x{968D}\x{968E}\x{968F}\x{9690}\x{9691}\x{9692}\x{9693}\x{9694}\x{9695}' . + '\x{9697}\x{9698}\x{9699}\x{969B}\x{969C}\x{969E}\x{96A0}\x{96A1}\x{96A2}' . + '\x{96A3}\x{96A4}\x{96A5}\x{96A6}\x{96A7}\x{96A8}\x{96A9}\x{96AA}\x{96AC}' . + '\x{96AD}\x{96AE}\x{96B0}\x{96B1}\x{96B3}\x{96B4}\x{96B6}\x{96B7}\x{96B8}' . + '\x{96B9}\x{96BA}\x{96BB}\x{96BC}\x{96BD}\x{96BE}\x{96BF}\x{96C0}\x{96C1}' . + '\x{96C2}\x{96C3}\x{96C4}\x{96C5}\x{96C6}\x{96C7}\x{96C8}\x{96C9}\x{96CA}' . + '\x{96CB}\x{96CC}\x{96CD}\x{96CE}\x{96CF}\x{96D0}\x{96D1}\x{96D2}\x{96D3}' . + '\x{96D4}\x{96D5}\x{96D6}\x{96D7}\x{96D8}\x{96D9}\x{96DA}\x{96DB}\x{96DC}' . + '\x{96DD}\x{96DE}\x{96DF}\x{96E0}\x{96E1}\x{96E2}\x{96E3}\x{96E5}\x{96E8}' . + '\x{96E9}\x{96EA}\x{96EB}\x{96EC}\x{96ED}\x{96EE}\x{96EF}\x{96F0}\x{96F1}' . + '\x{96F2}\x{96F3}\x{96F4}\x{96F5}\x{96F6}\x{96F7}\x{96F8}\x{96F9}\x{96FA}' . + '\x{96FB}\x{96FD}\x{96FE}\x{96FF}\x{9700}\x{9701}\x{9702}\x{9703}\x{9704}' . + '\x{9705}\x{9706}\x{9707}\x{9708}\x{9709}\x{970A}\x{970B}\x{970C}\x{970D}' . + '\x{970E}\x{970F}\x{9710}\x{9711}\x{9712}\x{9713}\x{9715}\x{9716}\x{9718}' . + '\x{9719}\x{971C}\x{971D}\x{971E}\x{971F}\x{9720}\x{9721}\x{9722}\x{9723}' . + '\x{9724}\x{9725}\x{9726}\x{9727}\x{9728}\x{9729}\x{972A}\x{972B}\x{972C}' . + '\x{972D}\x{972E}\x{972F}\x{9730}\x{9731}\x{9732}\x{9735}\x{9736}\x{9738}' . + '\x{9739}\x{973A}\x{973B}\x{973C}\x{973D}\x{973E}\x{973F}\x{9742}\x{9743}' . + '\x{9744}\x{9745}\x{9746}\x{9747}\x{9748}\x{9749}\x{974A}\x{974B}\x{974C}' . + '\x{974E}\x{974F}\x{9750}\x{9751}\x{9752}\x{9753}\x{9754}\x{9755}\x{9756}' . + '\x{9758}\x{9759}\x{975A}\x{975B}\x{975C}\x{975D}\x{975E}\x{975F}\x{9760}' . + '\x{9761}\x{9762}\x{9765}\x{9766}\x{9767}\x{9768}\x{9769}\x{976A}\x{976B}' . + '\x{976C}\x{976D}\x{976E}\x{976F}\x{9770}\x{9772}\x{9773}\x{9774}\x{9776}' . + '\x{9777}\x{9778}\x{9779}\x{977A}\x{977B}\x{977C}\x{977D}\x{977E}\x{977F}' . + '\x{9780}\x{9781}\x{9782}\x{9783}\x{9784}\x{9785}\x{9786}\x{9788}\x{978A}' . + '\x{978B}\x{978C}\x{978D}\x{978E}\x{978F}\x{9790}\x{9791}\x{9792}\x{9793}' . + '\x{9794}\x{9795}\x{9796}\x{9797}\x{9798}\x{9799}\x{979A}\x{979C}\x{979D}' . + '\x{979E}\x{979F}\x{97A0}\x{97A1}\x{97A2}\x{97A3}\x{97A4}\x{97A5}\x{97A6}' . + '\x{97A7}\x{97A8}\x{97AA}\x{97AB}\x{97AC}\x{97AD}\x{97AE}\x{97AF}\x{97B2}' . + '\x{97B3}\x{97B4}\x{97B6}\x{97B7}\x{97B8}\x{97B9}\x{97BA}\x{97BB}\x{97BC}' . + '\x{97BD}\x{97BF}\x{97C1}\x{97C2}\x{97C3}\x{97C4}\x{97C5}\x{97C6}\x{97C7}' . + '\x{97C8}\x{97C9}\x{97CA}\x{97CB}\x{97CC}\x{97CD}\x{97CE}\x{97CF}\x{97D0}' . + '\x{97D1}\x{97D3}\x{97D4}\x{97D5}\x{97D6}\x{97D7}\x{97D8}\x{97D9}\x{97DA}' . + '\x{97DB}\x{97DC}\x{97DD}\x{97DE}\x{97DF}\x{97E0}\x{97E1}\x{97E2}\x{97E3}' . + '\x{97E4}\x{97E5}\x{97E6}\x{97E7}\x{97E8}\x{97E9}\x{97EA}\x{97EB}\x{97EC}' . + '\x{97ED}\x{97EE}\x{97EF}\x{97F0}\x{97F1}\x{97F2}\x{97F3}\x{97F4}\x{97F5}' . + '\x{97F6}\x{97F7}\x{97F8}\x{97F9}\x{97FA}\x{97FB}\x{97FD}\x{97FE}\x{97FF}' . + '\x{9800}\x{9801}\x{9802}\x{9803}\x{9804}\x{9805}\x{9806}\x{9807}\x{9808}' . + '\x{9809}\x{980A}\x{980B}\x{980C}\x{980D}\x{980E}\x{980F}\x{9810}\x{9811}' . + '\x{9812}\x{9813}\x{9814}\x{9815}\x{9816}\x{9817}\x{9818}\x{9819}\x{981A}' . + '\x{981B}\x{981C}\x{981D}\x{981E}\x{9820}\x{9821}\x{9822}\x{9823}\x{9824}' . + '\x{9826}\x{9827}\x{9828}\x{9829}\x{982B}\x{982D}\x{982E}\x{982F}\x{9830}' . + '\x{9831}\x{9832}\x{9834}\x{9835}\x{9836}\x{9837}\x{9838}\x{9839}\x{983B}' . + '\x{983C}\x{983D}\x{983F}\x{9840}\x{9841}\x{9843}\x{9844}\x{9845}\x{9846}' . + '\x{9848}\x{9849}\x{984A}\x{984C}\x{984D}\x{984E}\x{984F}\x{9850}\x{9851}' . + '\x{9852}\x{9853}\x{9854}\x{9855}\x{9857}\x{9858}\x{9859}\x{985A}\x{985B}' . + '\x{985C}\x{985D}\x{985E}\x{985F}\x{9860}\x{9861}\x{9862}\x{9863}\x{9864}' . + '\x{9865}\x{9867}\x{9869}\x{986A}\x{986B}\x{986C}\x{986D}\x{986E}\x{986F}' . + '\x{9870}\x{9871}\x{9872}\x{9873}\x{9874}\x{9875}\x{9876}\x{9877}\x{9878}' . + '\x{9879}\x{987A}\x{987B}\x{987C}\x{987D}\x{987E}\x{987F}\x{9880}\x{9881}' . + '\x{9882}\x{9883}\x{9884}\x{9885}\x{9886}\x{9887}\x{9888}\x{9889}\x{988A}' . + '\x{988B}\x{988C}\x{988D}\x{988E}\x{988F}\x{9890}\x{9891}\x{9892}\x{9893}' . + '\x{9894}\x{9895}\x{9896}\x{9897}\x{9898}\x{9899}\x{989A}\x{989B}\x{989C}' . + '\x{989D}\x{989E}\x{989F}\x{98A0}\x{98A1}\x{98A2}\x{98A3}\x{98A4}\x{98A5}' . + '\x{98A6}\x{98A7}\x{98A8}\x{98A9}\x{98AA}\x{98AB}\x{98AC}\x{98AD}\x{98AE}' . + '\x{98AF}\x{98B0}\x{98B1}\x{98B2}\x{98B3}\x{98B4}\x{98B5}\x{98B6}\x{98B8}' . + '\x{98B9}\x{98BA}\x{98BB}\x{98BC}\x{98BD}\x{98BE}\x{98BF}\x{98C0}\x{98C1}' . + '\x{98C2}\x{98C3}\x{98C4}\x{98C5}\x{98C6}\x{98C8}\x{98C9}\x{98CB}\x{98CC}' . + '\x{98CD}\x{98CE}\x{98CF}\x{98D0}\x{98D1}\x{98D2}\x{98D3}\x{98D4}\x{98D5}' . + '\x{98D6}\x{98D7}\x{98D8}\x{98D9}\x{98DA}\x{98DB}\x{98DC}\x{98DD}\x{98DE}' . + '\x{98DF}\x{98E0}\x{98E2}\x{98E3}\x{98E5}\x{98E6}\x{98E7}\x{98E8}\x{98E9}' . + '\x{98EA}\x{98EB}\x{98ED}\x{98EF}\x{98F0}\x{98F2}\x{98F3}\x{98F4}\x{98F5}' . + '\x{98F6}\x{98F7}\x{98F9}\x{98FA}\x{98FC}\x{98FD}\x{98FE}\x{98FF}\x{9900}' . + '\x{9901}\x{9902}\x{9903}\x{9904}\x{9905}\x{9906}\x{9907}\x{9908}\x{9909}' . + '\x{990A}\x{990B}\x{990C}\x{990D}\x{990E}\x{990F}\x{9910}\x{9911}\x{9912}' . + '\x{9913}\x{9914}\x{9915}\x{9916}\x{9917}\x{9918}\x{991A}\x{991B}\x{991C}' . + '\x{991D}\x{991E}\x{991F}\x{9920}\x{9921}\x{9922}\x{9923}\x{9924}\x{9925}' . + '\x{9926}\x{9927}\x{9928}\x{9929}\x{992A}\x{992B}\x{992C}\x{992D}\x{992E}' . + '\x{992F}\x{9930}\x{9931}\x{9932}\x{9933}\x{9934}\x{9935}\x{9936}\x{9937}' . + '\x{9938}\x{9939}\x{993A}\x{993C}\x{993D}\x{993E}\x{993F}\x{9940}\x{9941}' . + '\x{9942}\x{9943}\x{9945}\x{9946}\x{9947}\x{9948}\x{9949}\x{994A}\x{994B}' . + '\x{994C}\x{994E}\x{994F}\x{9950}\x{9951}\x{9952}\x{9953}\x{9954}\x{9955}' . + '\x{9956}\x{9957}\x{9958}\x{9959}\x{995B}\x{995C}\x{995E}\x{995F}\x{9960}' . + '\x{9961}\x{9962}\x{9963}\x{9964}\x{9965}\x{9966}\x{9967}\x{9968}\x{9969}' . + '\x{996A}\x{996B}\x{996C}\x{996D}\x{996E}\x{996F}\x{9970}\x{9971}\x{9972}' . + '\x{9973}\x{9974}\x{9975}\x{9976}\x{9977}\x{9978}\x{9979}\x{997A}\x{997B}' . + '\x{997C}\x{997D}\x{997E}\x{997F}\x{9980}\x{9981}\x{9982}\x{9983}\x{9984}' . + '\x{9985}\x{9986}\x{9987}\x{9988}\x{9989}\x{998A}\x{998B}\x{998C}\x{998D}' . + '\x{998E}\x{998F}\x{9990}\x{9991}\x{9992}\x{9993}\x{9994}\x{9995}\x{9996}' . + '\x{9997}\x{9998}\x{9999}\x{999A}\x{999B}\x{999C}\x{999D}\x{999E}\x{999F}' . + '\x{99A0}\x{99A1}\x{99A2}\x{99A3}\x{99A4}\x{99A5}\x{99A6}\x{99A7}\x{99A8}' . + '\x{99A9}\x{99AA}\x{99AB}\x{99AC}\x{99AD}\x{99AE}\x{99AF}\x{99B0}\x{99B1}' . + '\x{99B2}\x{99B3}\x{99B4}\x{99B5}\x{99B6}\x{99B7}\x{99B8}\x{99B9}\x{99BA}' . + '\x{99BB}\x{99BC}\x{99BD}\x{99BE}\x{99C0}\x{99C1}\x{99C2}\x{99C3}\x{99C4}' . + '\x{99C6}\x{99C7}\x{99C8}\x{99C9}\x{99CA}\x{99CB}\x{99CC}\x{99CD}\x{99CE}' . + '\x{99CF}\x{99D0}\x{99D1}\x{99D2}\x{99D3}\x{99D4}\x{99D5}\x{99D6}\x{99D7}' . + '\x{99D8}\x{99D9}\x{99DA}\x{99DB}\x{99DC}\x{99DD}\x{99DE}\x{99DF}\x{99E1}' . + '\x{99E2}\x{99E3}\x{99E4}\x{99E5}\x{99E7}\x{99E8}\x{99E9}\x{99EA}\x{99EC}' . + '\x{99ED}\x{99EE}\x{99EF}\x{99F0}\x{99F1}\x{99F2}\x{99F3}\x{99F4}\x{99F6}' . + '\x{99F7}\x{99F8}\x{99F9}\x{99FA}\x{99FB}\x{99FC}\x{99FD}\x{99FE}\x{99FF}' . + '\x{9A00}\x{9A01}\x{9A02}\x{9A03}\x{9A04}\x{9A05}\x{9A06}\x{9A07}\x{9A08}' . + '\x{9A09}\x{9A0A}\x{9A0B}\x{9A0C}\x{9A0D}\x{9A0E}\x{9A0F}\x{9A11}\x{9A14}' . + '\x{9A15}\x{9A16}\x{9A19}\x{9A1A}\x{9A1B}\x{9A1C}\x{9A1D}\x{9A1E}\x{9A1F}' . + '\x{9A20}\x{9A21}\x{9A22}\x{9A23}\x{9A24}\x{9A25}\x{9A26}\x{9A27}\x{9A29}' . + '\x{9A2A}\x{9A2B}\x{9A2C}\x{9A2D}\x{9A2E}\x{9A2F}\x{9A30}\x{9A31}\x{9A32}' . + '\x{9A33}\x{9A34}\x{9A35}\x{9A36}\x{9A37}\x{9A38}\x{9A39}\x{9A3A}\x{9A3C}' . + '\x{9A3D}\x{9A3E}\x{9A3F}\x{9A40}\x{9A41}\x{9A42}\x{9A43}\x{9A44}\x{9A45}' . + '\x{9A46}\x{9A47}\x{9A48}\x{9A49}\x{9A4A}\x{9A4B}\x{9A4C}\x{9A4D}\x{9A4E}' . + '\x{9A4F}\x{9A50}\x{9A52}\x{9A53}\x{9A54}\x{9A55}\x{9A56}\x{9A57}\x{9A59}' . + '\x{9A5A}\x{9A5B}\x{9A5C}\x{9A5E}\x{9A5F}\x{9A60}\x{9A61}\x{9A62}\x{9A64}' . + '\x{9A65}\x{9A66}\x{9A67}\x{9A68}\x{9A69}\x{9A6A}\x{9A6B}\x{9A6C}\x{9A6D}' . + '\x{9A6E}\x{9A6F}\x{9A70}\x{9A71}\x{9A72}\x{9A73}\x{9A74}\x{9A75}\x{9A76}' . + '\x{9A77}\x{9A78}\x{9A79}\x{9A7A}\x{9A7B}\x{9A7C}\x{9A7D}\x{9A7E}\x{9A7F}' . + '\x{9A80}\x{9A81}\x{9A82}\x{9A83}\x{9A84}\x{9A85}\x{9A86}\x{9A87}\x{9A88}' . + '\x{9A89}\x{9A8A}\x{9A8B}\x{9A8C}\x{9A8D}\x{9A8E}\x{9A8F}\x{9A90}\x{9A91}' . + '\x{9A92}\x{9A93}\x{9A94}\x{9A95}\x{9A96}\x{9A97}\x{9A98}\x{9A99}\x{9A9A}' . + '\x{9A9B}\x{9A9C}\x{9A9D}\x{9A9E}\x{9A9F}\x{9AA0}\x{9AA1}\x{9AA2}\x{9AA3}' . + '\x{9AA4}\x{9AA5}\x{9AA6}\x{9AA7}\x{9AA8}\x{9AAA}\x{9AAB}\x{9AAC}\x{9AAD}' . + '\x{9AAE}\x{9AAF}\x{9AB0}\x{9AB1}\x{9AB2}\x{9AB3}\x{9AB4}\x{9AB5}\x{9AB6}' . + '\x{9AB7}\x{9AB8}\x{9AB9}\x{9ABA}\x{9ABB}\x{9ABC}\x{9ABE}\x{9ABF}\x{9AC0}' . + '\x{9AC1}\x{9AC2}\x{9AC3}\x{9AC4}\x{9AC5}\x{9AC6}\x{9AC7}\x{9AC9}\x{9ACA}' . + '\x{9ACB}\x{9ACC}\x{9ACD}\x{9ACE}\x{9ACF}\x{9AD0}\x{9AD1}\x{9AD2}\x{9AD3}' . + '\x{9AD4}\x{9AD5}\x{9AD6}\x{9AD8}\x{9AD9}\x{9ADA}\x{9ADB}\x{9ADC}\x{9ADD}' . + '\x{9ADE}\x{9ADF}\x{9AE1}\x{9AE2}\x{9AE3}\x{9AE5}\x{9AE6}\x{9AE7}\x{9AEA}' . + '\x{9AEB}\x{9AEC}\x{9AED}\x{9AEE}\x{9AEF}\x{9AF1}\x{9AF2}\x{9AF3}\x{9AF4}' . + '\x{9AF5}\x{9AF6}\x{9AF7}\x{9AF8}\x{9AF9}\x{9AFA}\x{9AFB}\x{9AFC}\x{9AFD}' . + '\x{9AFE}\x{9AFF}\x{9B01}\x{9B03}\x{9B04}\x{9B05}\x{9B06}\x{9B07}\x{9B08}' . + '\x{9B0A}\x{9B0B}\x{9B0C}\x{9B0D}\x{9B0E}\x{9B0F}\x{9B10}\x{9B11}\x{9B12}' . + '\x{9B13}\x{9B15}\x{9B16}\x{9B17}\x{9B18}\x{9B19}\x{9B1A}\x{9B1C}\x{9B1D}' . + '\x{9B1E}\x{9B1F}\x{9B20}\x{9B21}\x{9B22}\x{9B23}\x{9B24}\x{9B25}\x{9B26}' . + '\x{9B27}\x{9B28}\x{9B29}\x{9B2A}\x{9B2B}\x{9B2C}\x{9B2D}\x{9B2E}\x{9B2F}' . + '\x{9B30}\x{9B31}\x{9B32}\x{9B33}\x{9B35}\x{9B36}\x{9B37}\x{9B38}\x{9B39}' . + '\x{9B3A}\x{9B3B}\x{9B3C}\x{9B3E}\x{9B3F}\x{9B41}\x{9B42}\x{9B43}\x{9B44}' . + '\x{9B45}\x{9B46}\x{9B47}\x{9B48}\x{9B49}\x{9B4A}\x{9B4B}\x{9B4C}\x{9B4D}' . + '\x{9B4E}\x{9B4F}\x{9B51}\x{9B52}\x{9B53}\x{9B54}\x{9B55}\x{9B56}\x{9B58}' . + '\x{9B59}\x{9B5A}\x{9B5B}\x{9B5C}\x{9B5D}\x{9B5E}\x{9B5F}\x{9B60}\x{9B61}' . + '\x{9B63}\x{9B64}\x{9B65}\x{9B66}\x{9B67}\x{9B68}\x{9B69}\x{9B6A}\x{9B6B}' . + '\x{9B6C}\x{9B6D}\x{9B6E}\x{9B6F}\x{9B70}\x{9B71}\x{9B73}\x{9B74}\x{9B75}' . + '\x{9B76}\x{9B77}\x{9B78}\x{9B79}\x{9B7A}\x{9B7B}\x{9B7C}\x{9B7D}\x{9B7E}' . + '\x{9B7F}\x{9B80}\x{9B81}\x{9B82}\x{9B83}\x{9B84}\x{9B85}\x{9B86}\x{9B87}' . + '\x{9B88}\x{9B8A}\x{9B8B}\x{9B8D}\x{9B8E}\x{9B8F}\x{9B90}\x{9B91}\x{9B92}' . + '\x{9B93}\x{9B94}\x{9B95}\x{9B96}\x{9B97}\x{9B98}\x{9B9A}\x{9B9B}\x{9B9C}' . + '\x{9B9D}\x{9B9E}\x{9B9F}\x{9BA0}\x{9BA1}\x{9BA2}\x{9BA3}\x{9BA4}\x{9BA5}' . + '\x{9BA6}\x{9BA7}\x{9BA8}\x{9BA9}\x{9BAA}\x{9BAB}\x{9BAC}\x{9BAD}\x{9BAE}' . + '\x{9BAF}\x{9BB0}\x{9BB1}\x{9BB2}\x{9BB3}\x{9BB4}\x{9BB5}\x{9BB6}\x{9BB7}' . + '\x{9BB8}\x{9BB9}\x{9BBA}\x{9BBB}\x{9BBC}\x{9BBD}\x{9BBE}\x{9BBF}\x{9BC0}' . + '\x{9BC1}\x{9BC3}\x{9BC4}\x{9BC5}\x{9BC6}\x{9BC7}\x{9BC8}\x{9BC9}\x{9BCA}' . + '\x{9BCB}\x{9BCC}\x{9BCD}\x{9BCE}\x{9BCF}\x{9BD0}\x{9BD1}\x{9BD2}\x{9BD3}' . + '\x{9BD4}\x{9BD5}\x{9BD6}\x{9BD7}\x{9BD8}\x{9BD9}\x{9BDA}\x{9BDB}\x{9BDC}' . + '\x{9BDD}\x{9BDE}\x{9BDF}\x{9BE0}\x{9BE1}\x{9BE2}\x{9BE3}\x{9BE4}\x{9BE5}' . + '\x{9BE6}\x{9BE7}\x{9BE8}\x{9BE9}\x{9BEA}\x{9BEB}\x{9BEC}\x{9BED}\x{9BEE}' . + '\x{9BEF}\x{9BF0}\x{9BF1}\x{9BF2}\x{9BF3}\x{9BF4}\x{9BF5}\x{9BF7}\x{9BF8}' . + '\x{9BF9}\x{9BFA}\x{9BFB}\x{9BFC}\x{9BFD}\x{9BFE}\x{9BFF}\x{9C02}\x{9C05}' . + '\x{9C06}\x{9C07}\x{9C08}\x{9C09}\x{9C0A}\x{9C0B}\x{9C0C}\x{9C0D}\x{9C0E}' . + '\x{9C0F}\x{9C10}\x{9C11}\x{9C12}\x{9C13}\x{9C14}\x{9C15}\x{9C16}\x{9C17}' . + '\x{9C18}\x{9C19}\x{9C1A}\x{9C1B}\x{9C1C}\x{9C1D}\x{9C1E}\x{9C1F}\x{9C20}' . + '\x{9C21}\x{9C22}\x{9C23}\x{9C24}\x{9C25}\x{9C26}\x{9C27}\x{9C28}\x{9C29}' . + '\x{9C2A}\x{9C2B}\x{9C2C}\x{9C2D}\x{9C2F}\x{9C30}\x{9C31}\x{9C32}\x{9C33}' . + '\x{9C34}\x{9C35}\x{9C36}\x{9C37}\x{9C38}\x{9C39}\x{9C3A}\x{9C3B}\x{9C3C}' . + '\x{9C3D}\x{9C3E}\x{9C3F}\x{9C40}\x{9C41}\x{9C43}\x{9C44}\x{9C45}\x{9C46}' . + '\x{9C47}\x{9C48}\x{9C49}\x{9C4A}\x{9C4B}\x{9C4C}\x{9C4D}\x{9C4E}\x{9C50}' . + '\x{9C52}\x{9C53}\x{9C54}\x{9C55}\x{9C56}\x{9C57}\x{9C58}\x{9C59}\x{9C5A}' . + '\x{9C5B}\x{9C5C}\x{9C5D}\x{9C5E}\x{9C5F}\x{9C60}\x{9C62}\x{9C63}\x{9C65}' . + '\x{9C66}\x{9C67}\x{9C68}\x{9C69}\x{9C6A}\x{9C6B}\x{9C6C}\x{9C6D}\x{9C6E}' . + '\x{9C6F}\x{9C70}\x{9C71}\x{9C72}\x{9C73}\x{9C74}\x{9C75}\x{9C77}\x{9C78}' . + '\x{9C79}\x{9C7A}\x{9C7C}\x{9C7D}\x{9C7E}\x{9C7F}\x{9C80}\x{9C81}\x{9C82}' . + '\x{9C83}\x{9C84}\x{9C85}\x{9C86}\x{9C87}\x{9C88}\x{9C89}\x{9C8A}\x{9C8B}' . + '\x{9C8C}\x{9C8D}\x{9C8E}\x{9C8F}\x{9C90}\x{9C91}\x{9C92}\x{9C93}\x{9C94}' . + '\x{9C95}\x{9C96}\x{9C97}\x{9C98}\x{9C99}\x{9C9A}\x{9C9B}\x{9C9C}\x{9C9D}' . + '\x{9C9E}\x{9C9F}\x{9CA0}\x{9CA1}\x{9CA2}\x{9CA3}\x{9CA4}\x{9CA5}\x{9CA6}' . + '\x{9CA7}\x{9CA8}\x{9CA9}\x{9CAA}\x{9CAB}\x{9CAC}\x{9CAD}\x{9CAE}\x{9CAF}' . + '\x{9CB0}\x{9CB1}\x{9CB2}\x{9CB3}\x{9CB4}\x{9CB5}\x{9CB6}\x{9CB7}\x{9CB8}' . + '\x{9CB9}\x{9CBA}\x{9CBB}\x{9CBC}\x{9CBD}\x{9CBE}\x{9CBF}\x{9CC0}\x{9CC1}' . + '\x{9CC2}\x{9CC3}\x{9CC4}\x{9CC5}\x{9CC6}\x{9CC7}\x{9CC8}\x{9CC9}\x{9CCA}' . + '\x{9CCB}\x{9CCC}\x{9CCD}\x{9CCE}\x{9CCF}\x{9CD0}\x{9CD1}\x{9CD2}\x{9CD3}' . + '\x{9CD4}\x{9CD5}\x{9CD6}\x{9CD7}\x{9CD8}\x{9CD9}\x{9CDA}\x{9CDB}\x{9CDC}' . + '\x{9CDD}\x{9CDE}\x{9CDF}\x{9CE0}\x{9CE1}\x{9CE2}\x{9CE3}\x{9CE4}\x{9CE5}' . + '\x{9CE6}\x{9CE7}\x{9CE8}\x{9CE9}\x{9CEA}\x{9CEB}\x{9CEC}\x{9CED}\x{9CEE}' . + '\x{9CEF}\x{9CF0}\x{9CF1}\x{9CF2}\x{9CF3}\x{9CF4}\x{9CF5}\x{9CF6}\x{9CF7}' . + '\x{9CF8}\x{9CF9}\x{9CFA}\x{9CFB}\x{9CFC}\x{9CFD}\x{9CFE}\x{9CFF}\x{9D00}' . + '\x{9D01}\x{9D02}\x{9D03}\x{9D04}\x{9D05}\x{9D06}\x{9D07}\x{9D08}\x{9D09}' . + '\x{9D0A}\x{9D0B}\x{9D0F}\x{9D10}\x{9D12}\x{9D13}\x{9D14}\x{9D15}\x{9D16}' . + '\x{9D17}\x{9D18}\x{9D19}\x{9D1A}\x{9D1B}\x{9D1C}\x{9D1D}\x{9D1E}\x{9D1F}' . + '\x{9D20}\x{9D21}\x{9D22}\x{9D23}\x{9D24}\x{9D25}\x{9D26}\x{9D28}\x{9D29}' . + '\x{9D2B}\x{9D2D}\x{9D2E}\x{9D2F}\x{9D30}\x{9D31}\x{9D32}\x{9D33}\x{9D34}' . + '\x{9D36}\x{9D37}\x{9D38}\x{9D39}\x{9D3A}\x{9D3B}\x{9D3D}\x{9D3E}\x{9D3F}' . + '\x{9D40}\x{9D41}\x{9D42}\x{9D43}\x{9D45}\x{9D46}\x{9D47}\x{9D48}\x{9D49}' . + '\x{9D4A}\x{9D4B}\x{9D4C}\x{9D4D}\x{9D4E}\x{9D4F}\x{9D50}\x{9D51}\x{9D52}' . + '\x{9D53}\x{9D54}\x{9D55}\x{9D56}\x{9D57}\x{9D58}\x{9D59}\x{9D5A}\x{9D5B}' . + '\x{9D5C}\x{9D5D}\x{9D5E}\x{9D5F}\x{9D60}\x{9D61}\x{9D62}\x{9D63}\x{9D64}' . + '\x{9D65}\x{9D66}\x{9D67}\x{9D68}\x{9D69}\x{9D6A}\x{9D6B}\x{9D6C}\x{9D6E}' . + '\x{9D6F}\x{9D70}\x{9D71}\x{9D72}\x{9D73}\x{9D74}\x{9D75}\x{9D76}\x{9D77}' . + '\x{9D78}\x{9D79}\x{9D7A}\x{9D7B}\x{9D7C}\x{9D7D}\x{9D7E}\x{9D7F}\x{9D80}' . + '\x{9D81}\x{9D82}\x{9D83}\x{9D84}\x{9D85}\x{9D86}\x{9D87}\x{9D88}\x{9D89}' . + '\x{9D8A}\x{9D8B}\x{9D8C}\x{9D8D}\x{9D8E}\x{9D90}\x{9D91}\x{9D92}\x{9D93}' . + '\x{9D94}\x{9D96}\x{9D97}\x{9D98}\x{9D99}\x{9D9A}\x{9D9B}\x{9D9C}\x{9D9D}' . + '\x{9D9E}\x{9D9F}\x{9DA0}\x{9DA1}\x{9DA2}\x{9DA3}\x{9DA4}\x{9DA5}\x{9DA6}' . + '\x{9DA7}\x{9DA8}\x{9DA9}\x{9DAA}\x{9DAB}\x{9DAC}\x{9DAD}\x{9DAF}\x{9DB0}' . + '\x{9DB1}\x{9DB2}\x{9DB3}\x{9DB4}\x{9DB5}\x{9DB6}\x{9DB7}\x{9DB8}\x{9DB9}' . + '\x{9DBA}\x{9DBB}\x{9DBC}\x{9DBE}\x{9DBF}\x{9DC1}\x{9DC2}\x{9DC3}\x{9DC4}' . + '\x{9DC5}\x{9DC7}\x{9DC8}\x{9DC9}\x{9DCA}\x{9DCB}\x{9DCC}\x{9DCD}\x{9DCE}' . + '\x{9DCF}\x{9DD0}\x{9DD1}\x{9DD2}\x{9DD3}\x{9DD4}\x{9DD5}\x{9DD6}\x{9DD7}' . + '\x{9DD8}\x{9DD9}\x{9DDA}\x{9DDB}\x{9DDC}\x{9DDD}\x{9DDE}\x{9DDF}\x{9DE0}' . + '\x{9DE1}\x{9DE2}\x{9DE3}\x{9DE4}\x{9DE5}\x{9DE6}\x{9DE7}\x{9DE8}\x{9DE9}' . + '\x{9DEB}\x{9DEC}\x{9DED}\x{9DEE}\x{9DEF}\x{9DF0}\x{9DF1}\x{9DF2}\x{9DF3}' . + '\x{9DF4}\x{9DF5}\x{9DF6}\x{9DF7}\x{9DF8}\x{9DF9}\x{9DFA}\x{9DFB}\x{9DFD}' . + '\x{9DFE}\x{9DFF}\x{9E00}\x{9E01}\x{9E02}\x{9E03}\x{9E04}\x{9E05}\x{9E06}' . + '\x{9E07}\x{9E08}\x{9E09}\x{9E0A}\x{9E0B}\x{9E0C}\x{9E0D}\x{9E0F}\x{9E10}' . + '\x{9E11}\x{9E12}\x{9E13}\x{9E14}\x{9E15}\x{9E17}\x{9E18}\x{9E19}\x{9E1A}' . + '\x{9E1B}\x{9E1D}\x{9E1E}\x{9E1F}\x{9E20}\x{9E21}\x{9E22}\x{9E23}\x{9E24}' . + '\x{9E25}\x{9E26}\x{9E27}\x{9E28}\x{9E29}\x{9E2A}\x{9E2B}\x{9E2C}\x{9E2D}' . + '\x{9E2E}\x{9E2F}\x{9E30}\x{9E31}\x{9E32}\x{9E33}\x{9E34}\x{9E35}\x{9E36}' . + '\x{9E37}\x{9E38}\x{9E39}\x{9E3A}\x{9E3B}\x{9E3C}\x{9E3D}\x{9E3E}\x{9E3F}' . + '\x{9E40}\x{9E41}\x{9E42}\x{9E43}\x{9E44}\x{9E45}\x{9E46}\x{9E47}\x{9E48}' . + '\x{9E49}\x{9E4A}\x{9E4B}\x{9E4C}\x{9E4D}\x{9E4E}\x{9E4F}\x{9E50}\x{9E51}' . + '\x{9E52}\x{9E53}\x{9E54}\x{9E55}\x{9E56}\x{9E57}\x{9E58}\x{9E59}\x{9E5A}' . + '\x{9E5B}\x{9E5C}\x{9E5D}\x{9E5E}\x{9E5F}\x{9E60}\x{9E61}\x{9E62}\x{9E63}' . + '\x{9E64}\x{9E65}\x{9E66}\x{9E67}\x{9E68}\x{9E69}\x{9E6A}\x{9E6B}\x{9E6C}' . + '\x{9E6D}\x{9E6E}\x{9E6F}\x{9E70}\x{9E71}\x{9E72}\x{9E73}\x{9E74}\x{9E75}' . + '\x{9E76}\x{9E77}\x{9E79}\x{9E7A}\x{9E7C}\x{9E7D}\x{9E7E}\x{9E7F}\x{9E80}' . + '\x{9E81}\x{9E82}\x{9E83}\x{9E84}\x{9E85}\x{9E86}\x{9E87}\x{9E88}\x{9E89}' . + '\x{9E8A}\x{9E8B}\x{9E8C}\x{9E8D}\x{9E8E}\x{9E91}\x{9E92}\x{9E93}\x{9E94}' . + '\x{9E96}\x{9E97}\x{9E99}\x{9E9A}\x{9E9B}\x{9E9C}\x{9E9D}\x{9E9F}\x{9EA0}' . + '\x{9EA1}\x{9EA3}\x{9EA4}\x{9EA5}\x{9EA6}\x{9EA7}\x{9EA8}\x{9EA9}\x{9EAA}' . + '\x{9EAD}\x{9EAE}\x{9EAF}\x{9EB0}\x{9EB2}\x{9EB3}\x{9EB4}\x{9EB5}\x{9EB6}' . + '\x{9EB7}\x{9EB8}\x{9EBB}\x{9EBC}\x{9EBD}\x{9EBE}\x{9EBF}\x{9EC0}\x{9EC1}' . + '\x{9EC2}\x{9EC3}\x{9EC4}\x{9EC5}\x{9EC6}\x{9EC7}\x{9EC8}\x{9EC9}\x{9ECA}' . + '\x{9ECB}\x{9ECC}\x{9ECD}\x{9ECE}\x{9ECF}\x{9ED0}\x{9ED1}\x{9ED2}\x{9ED3}' . + '\x{9ED4}\x{9ED5}\x{9ED6}\x{9ED7}\x{9ED8}\x{9ED9}\x{9EDA}\x{9EDB}\x{9EDC}' . + '\x{9EDD}\x{9EDE}\x{9EDF}\x{9EE0}\x{9EE1}\x{9EE2}\x{9EE3}\x{9EE4}\x{9EE5}' . + '\x{9EE6}\x{9EE7}\x{9EE8}\x{9EE9}\x{9EEA}\x{9EEB}\x{9EED}\x{9EEE}\x{9EEF}' . + '\x{9EF0}\x{9EF2}\x{9EF3}\x{9EF4}\x{9EF5}\x{9EF6}\x{9EF7}\x{9EF8}\x{9EF9}' . + '\x{9EFA}\x{9EFB}\x{9EFC}\x{9EFD}\x{9EFE}\x{9EFF}\x{9F00}\x{9F01}\x{9F02}' . + '\x{9F04}\x{9F05}\x{9F06}\x{9F07}\x{9F08}\x{9F09}\x{9F0A}\x{9F0B}\x{9F0C}' . + '\x{9F0D}\x{9F0E}\x{9F0F}\x{9F10}\x{9F12}\x{9F13}\x{9F15}\x{9F16}\x{9F17}' . + '\x{9F18}\x{9F19}\x{9F1A}\x{9F1B}\x{9F1C}\x{9F1D}\x{9F1E}\x{9F1F}\x{9F20}' . + '\x{9F22}\x{9F23}\x{9F24}\x{9F25}\x{9F27}\x{9F28}\x{9F29}\x{9F2A}\x{9F2B}' . + '\x{9F2C}\x{9F2D}\x{9F2E}\x{9F2F}\x{9F30}\x{9F31}\x{9F32}\x{9F33}\x{9F34}' . + '\x{9F35}\x{9F36}\x{9F37}\x{9F38}\x{9F39}\x{9F3A}\x{9F3B}\x{9F3C}\x{9F3D}' . + '\x{9F3E}\x{9F3F}\x{9F40}\x{9F41}\x{9F42}\x{9F43}\x{9F44}\x{9F46}\x{9F47}' . + '\x{9F48}\x{9F49}\x{9F4A}\x{9F4B}\x{9F4C}\x{9F4D}\x{9F4E}\x{9F4F}\x{9F50}' . + '\x{9F51}\x{9F52}\x{9F54}\x{9F55}\x{9F56}\x{9F57}\x{9F58}\x{9F59}\x{9F5A}' . + '\x{9F5B}\x{9F5C}\x{9F5D}\x{9F5E}\x{9F5F}\x{9F60}\x{9F61}\x{9F63}\x{9F64}' . + '\x{9F65}\x{9F66}\x{9F67}\x{9F68}\x{9F69}\x{9F6A}\x{9F6B}\x{9F6C}\x{9F6E}' . + '\x{9F6F}\x{9F70}\x{9F71}\x{9F72}\x{9F73}\x{9F74}\x{9F75}\x{9F76}\x{9F77}' . + '\x{9F78}\x{9F79}\x{9F7A}\x{9F7B}\x{9F7C}\x{9F7D}\x{9F7E}\x{9F7F}\x{9F80}' . + '\x{9F81}\x{9F82}\x{9F83}\x{9F84}\x{9F85}\x{9F86}\x{9F87}\x{9F88}\x{9F89}' . + '\x{9F8A}\x{9F8B}\x{9F8C}\x{9F8D}\x{9F8E}\x{9F8F}\x{9F90}\x{9F91}\x{9F92}' . + '\x{9F93}\x{9F94}\x{9F95}\x{9F96}\x{9F97}\x{9F98}\x{9F99}\x{9F9A}\x{9F9B}' . + '\x{9F9C}\x{9F9D}\x{9F9E}\x{9F9F}\x{9FA0}\x{9FA2}\x{9FA4}\x{9FA5}]{1,20}$/iu', +); diff --git a/lib/Zend/Validator/Hostname/Cn.php b/lib/Zend/Validator/Hostname/Cn.php new file mode 100644 index 0000000000000000000000000000000000000000..efb14b1261585430bca16a431c5528fc1fab57f0 --- /dev/null +++ b/lib/Zend/Validator/Hostname/Cn.php @@ -0,0 +1,2189 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Hostname; + +/** + * Resource file for chinese idn validation + * + * @category Zend + * @package Zend_Validate + */ +return array( + 1 => '/^[\x{002d}0-9a-z\x{3447}\x{3473}\x{359E}\x{360E}\x{361A}\x{3918}\x{396E}\x{39CF}\x{39D0}' . + '\x{39DF}\x{3A73}\x{3B4E}\x{3C6E}\x{3CE0}\x{4056}\x{415F}\x{4337}\x{43AC}' . + '\x{43B1}\x{43DD}\x{44D6}\x{464C}\x{4661}\x{4723}\x{4729}\x{477C}\x{478D}' . + '\x{4947}\x{497A}\x{497D}\x{4982}\x{4983}\x{4985}\x{4986}\x{499B}\x{499F}' . + '\x{49B6}\x{49B7}\x{4C77}\x{4C9F}\x{4CA0}\x{4CA1}\x{4CA2}\x{4CA3}\x{4D13}' . + '\x{4D14}\x{4D15}\x{4D16}\x{4D17}\x{4D18}\x{4D19}\x{4DAE}\x{4E00}\x{4E01}' . + '\x{4E02}\x{4E03}\x{4E04}\x{4E05}\x{4E06}\x{4E07}\x{4E08}\x{4E09}\x{4E0A}' . + '\x{4E0B}\x{4E0C}\x{4E0D}\x{4E0E}\x{4E0F}\x{4E10}\x{4E11}\x{4E13}\x{4E14}' . + '\x{4E15}\x{4E16}\x{4E17}\x{4E18}\x{4E19}\x{4E1A}\x{4E1B}\x{4E1C}\x{4E1D}' . + '\x{4E1E}\x{4E1F}\x{4E20}\x{4E21}\x{4E22}\x{4E23}\x{4E24}\x{4E25}\x{4E26}' . + '\x{4E27}\x{4E28}\x{4E2A}\x{4E2B}\x{4E2C}\x{4E2D}\x{4E2E}\x{4E2F}\x{4E30}' . + '\x{4E31}\x{4E32}\x{4E33}\x{4E34}\x{4E35}\x{4E36}\x{4E37}\x{4E38}\x{4E39}' . + '\x{4E3A}\x{4E3B}\x{4E3C}\x{4E3D}\x{4E3E}\x{4E3F}\x{4E40}\x{4E41}\x{4E42}' . + '\x{4E43}\x{4E44}\x{4E45}\x{4E46}\x{4E47}\x{4E48}\x{4E49}\x{4E4A}\x{4E4B}' . + '\x{4E4C}\x{4E4D}\x{4E4E}\x{4E4F}\x{4E50}\x{4E51}\x{4E52}\x{4E53}\x{4E54}' . + '\x{4E56}\x{4E57}\x{4E58}\x{4E59}\x{4E5A}\x{4E5B}\x{4E5C}\x{4E5D}\x{4E5E}' . + '\x{4E5F}\x{4E60}\x{4E61}\x{4E62}\x{4E63}\x{4E64}\x{4E65}\x{4E66}\x{4E67}' . + '\x{4E69}\x{4E6A}\x{4E6B}\x{4E6C}\x{4E6D}\x{4E6E}\x{4E6F}\x{4E70}\x{4E71}' . + '\x{4E72}\x{4E73}\x{4E74}\x{4E75}\x{4E76}\x{4E77}\x{4E78}\x{4E7A}\x{4E7B}' . + '\x{4E7C}\x{4E7D}\x{4E7E}\x{4E7F}\x{4E80}\x{4E81}\x{4E82}\x{4E83}\x{4E84}' . + '\x{4E85}\x{4E86}\x{4E87}\x{4E88}\x{4E89}\x{4E8B}\x{4E8C}\x{4E8D}\x{4E8E}' . + '\x{4E8F}\x{4E90}\x{4E91}\x{4E92}\x{4E93}\x{4E94}\x{4E95}\x{4E97}\x{4E98}' . + '\x{4E99}\x{4E9A}\x{4E9B}\x{4E9C}\x{4E9D}\x{4E9E}\x{4E9F}\x{4EA0}\x{4EA1}' . + '\x{4EA2}\x{4EA4}\x{4EA5}\x{4EA6}\x{4EA7}\x{4EA8}\x{4EA9}\x{4EAA}\x{4EAB}' . + '\x{4EAC}\x{4EAD}\x{4EAE}\x{4EAF}\x{4EB0}\x{4EB1}\x{4EB2}\x{4EB3}\x{4EB4}' . + '\x{4EB5}\x{4EB6}\x{4EB7}\x{4EB8}\x{4EB9}\x{4EBA}\x{4EBB}\x{4EBD}\x{4EBE}' . + '\x{4EBF}\x{4EC0}\x{4EC1}\x{4EC2}\x{4EC3}\x{4EC4}\x{4EC5}\x{4EC6}\x{4EC7}' . + '\x{4EC8}\x{4EC9}\x{4ECA}\x{4ECB}\x{4ECD}\x{4ECE}\x{4ECF}\x{4ED0}\x{4ED1}' . + '\x{4ED2}\x{4ED3}\x{4ED4}\x{4ED5}\x{4ED6}\x{4ED7}\x{4ED8}\x{4ED9}\x{4EDA}' . + '\x{4EDB}\x{4EDC}\x{4EDD}\x{4EDE}\x{4EDF}\x{4EE0}\x{4EE1}\x{4EE2}\x{4EE3}' . + '\x{4EE4}\x{4EE5}\x{4EE6}\x{4EE8}\x{4EE9}\x{4EEA}\x{4EEB}\x{4EEC}\x{4EEF}' . + '\x{4EF0}\x{4EF1}\x{4EF2}\x{4EF3}\x{4EF4}\x{4EF5}\x{4EF6}\x{4EF7}\x{4EFB}' . + '\x{4EFD}\x{4EFF}\x{4F00}\x{4F01}\x{4F02}\x{4F03}\x{4F04}\x{4F05}\x{4F06}' . + '\x{4F08}\x{4F09}\x{4F0A}\x{4F0B}\x{4F0C}\x{4F0D}\x{4F0E}\x{4F0F}\x{4F10}' . + '\x{4F11}\x{4F12}\x{4F13}\x{4F14}\x{4F15}\x{4F17}\x{4F18}\x{4F19}\x{4F1A}' . + '\x{4F1B}\x{4F1C}\x{4F1D}\x{4F1E}\x{4F1F}\x{4F20}\x{4F21}\x{4F22}\x{4F23}' . + '\x{4F24}\x{4F25}\x{4F26}\x{4F27}\x{4F29}\x{4F2A}\x{4F2B}\x{4F2C}\x{4F2D}' . + '\x{4F2E}\x{4F2F}\x{4F30}\x{4F32}\x{4F33}\x{4F34}\x{4F36}\x{4F38}\x{4F39}' . + '\x{4F3A}\x{4F3B}\x{4F3C}\x{4F3D}\x{4F3E}\x{4F3F}\x{4F41}\x{4F42}\x{4F43}' . + '\x{4F45}\x{4F46}\x{4F47}\x{4F48}\x{4F49}\x{4F4A}\x{4F4B}\x{4F4C}\x{4F4D}' . + '\x{4F4E}\x{4F4F}\x{4F50}\x{4F51}\x{4F52}\x{4F53}\x{4F54}\x{4F55}\x{4F56}' . + '\x{4F57}\x{4F58}\x{4F59}\x{4F5A}\x{4F5B}\x{4F5C}\x{4F5D}\x{4F5E}\x{4F5F}' . + '\x{4F60}\x{4F61}\x{4F62}\x{4F63}\x{4F64}\x{4F65}\x{4F66}\x{4F67}\x{4F68}' . + '\x{4F69}\x{4F6A}\x{4F6B}\x{4F6C}\x{4F6D}\x{4F6E}\x{4F6F}\x{4F70}\x{4F72}' . + '\x{4F73}\x{4F74}\x{4F75}\x{4F76}\x{4F77}\x{4F78}\x{4F79}\x{4F7A}\x{4F7B}' . + '\x{4F7C}\x{4F7D}\x{4F7E}\x{4F7F}\x{4F80}\x{4F81}\x{4F82}\x{4F83}\x{4F84}' . + '\x{4F85}\x{4F86}\x{4F87}\x{4F88}\x{4F89}\x{4F8A}\x{4F8B}\x{4F8D}\x{4F8F}' . + '\x{4F90}\x{4F91}\x{4F92}\x{4F93}\x{4F94}\x{4F95}\x{4F96}\x{4F97}\x{4F98}' . + '\x{4F99}\x{4F9A}\x{4F9B}\x{4F9C}\x{4F9D}\x{4F9E}\x{4F9F}\x{4FA0}\x{4FA1}' . + '\x{4FA3}\x{4FA4}\x{4FA5}\x{4FA6}\x{4FA7}\x{4FA8}\x{4FA9}\x{4FAA}\x{4FAB}' . + '\x{4FAC}\x{4FAE}\x{4FAF}\x{4FB0}\x{4FB1}\x{4FB2}\x{4FB3}\x{4FB4}\x{4FB5}' . + '\x{4FB6}\x{4FB7}\x{4FB8}\x{4FB9}\x{4FBA}\x{4FBB}\x{4FBC}\x{4FBE}\x{4FBF}' . + '\x{4FC0}\x{4FC1}\x{4FC2}\x{4FC3}\x{4FC4}\x{4FC5}\x{4FC7}\x{4FC9}\x{4FCA}' . + '\x{4FCB}\x{4FCD}\x{4FCE}\x{4FCF}\x{4FD0}\x{4FD1}\x{4FD2}\x{4FD3}\x{4FD4}' . + '\x{4FD5}\x{4FD6}\x{4FD7}\x{4FD8}\x{4FD9}\x{4FDA}\x{4FDB}\x{4FDC}\x{4FDD}' . + '\x{4FDE}\x{4FDF}\x{4FE0}\x{4FE1}\x{4FE3}\x{4FE4}\x{4FE5}\x{4FE6}\x{4FE7}' . + '\x{4FE8}\x{4FE9}\x{4FEA}\x{4FEB}\x{4FEC}\x{4FED}\x{4FEE}\x{4FEF}\x{4FF0}' . + '\x{4FF1}\x{4FF2}\x{4FF3}\x{4FF4}\x{4FF5}\x{4FF6}\x{4FF7}\x{4FF8}\x{4FF9}' . + '\x{4FFA}\x{4FFB}\x{4FFE}\x{4FFF}\x{5000}\x{5001}\x{5002}\x{5003}\x{5004}' . + '\x{5005}\x{5006}\x{5007}\x{5008}\x{5009}\x{500A}\x{500B}\x{500C}\x{500D}' . + '\x{500E}\x{500F}\x{5011}\x{5012}\x{5013}\x{5014}\x{5015}\x{5016}\x{5017}' . + '\x{5018}\x{5019}\x{501A}\x{501B}\x{501C}\x{501D}\x{501E}\x{501F}\x{5020}' . + '\x{5021}\x{5022}\x{5023}\x{5024}\x{5025}\x{5026}\x{5027}\x{5028}\x{5029}' . + '\x{502A}\x{502B}\x{502C}\x{502D}\x{502E}\x{502F}\x{5030}\x{5031}\x{5032}' . + '\x{5033}\x{5035}\x{5036}\x{5037}\x{5039}\x{503A}\x{503B}\x{503C}\x{503E}' . + '\x{503F}\x{5040}\x{5041}\x{5043}\x{5044}\x{5045}\x{5046}\x{5047}\x{5048}' . + '\x{5049}\x{504A}\x{504B}\x{504C}\x{504D}\x{504E}\x{504F}\x{5051}\x{5053}' . + '\x{5054}\x{5055}\x{5056}\x{5057}\x{5059}\x{505A}\x{505B}\x{505C}\x{505D}' . + '\x{505E}\x{505F}\x{5060}\x{5061}\x{5062}\x{5063}\x{5064}\x{5065}\x{5066}' . + '\x{5067}\x{5068}\x{5069}\x{506A}\x{506B}\x{506C}\x{506D}\x{506E}\x{506F}' . + '\x{5070}\x{5071}\x{5072}\x{5073}\x{5074}\x{5075}\x{5076}\x{5077}\x{5078}' . + '\x{5079}\x{507A}\x{507B}\x{507D}\x{507E}\x{507F}\x{5080}\x{5082}\x{5083}' . + '\x{5084}\x{5085}\x{5086}\x{5087}\x{5088}\x{5089}\x{508A}\x{508B}\x{508C}' . + '\x{508D}\x{508E}\x{508F}\x{5090}\x{5091}\x{5092}\x{5094}\x{5095}\x{5096}' . + '\x{5098}\x{5099}\x{509A}\x{509B}\x{509C}\x{509D}\x{509E}\x{50A2}\x{50A3}' . + '\x{50A4}\x{50A5}\x{50A6}\x{50A7}\x{50A8}\x{50A9}\x{50AA}\x{50AB}\x{50AC}' . + '\x{50AD}\x{50AE}\x{50AF}\x{50B0}\x{50B1}\x{50B2}\x{50B3}\x{50B4}\x{50B5}' . + '\x{50B6}\x{50B7}\x{50B8}\x{50BA}\x{50BB}\x{50BC}\x{50BD}\x{50BE}\x{50BF}' . + '\x{50C0}\x{50C1}\x{50C2}\x{50C4}\x{50C5}\x{50C6}\x{50C7}\x{50C8}\x{50C9}' . + '\x{50CA}\x{50CB}\x{50CC}\x{50CD}\x{50CE}\x{50CF}\x{50D0}\x{50D1}\x{50D2}' . + '\x{50D3}\x{50D4}\x{50D5}\x{50D6}\x{50D7}\x{50D9}\x{50DA}\x{50DB}\x{50DC}' . + '\x{50DD}\x{50DE}\x{50E0}\x{50E3}\x{50E4}\x{50E5}\x{50E6}\x{50E7}\x{50E8}' . + '\x{50E9}\x{50EA}\x{50EC}\x{50ED}\x{50EE}\x{50EF}\x{50F0}\x{50F1}\x{50F2}' . + '\x{50F3}\x{50F5}\x{50F6}\x{50F8}\x{50F9}\x{50FA}\x{50FB}\x{50FC}\x{50FD}' . + '\x{50FE}\x{50FF}\x{5100}\x{5101}\x{5102}\x{5103}\x{5104}\x{5105}\x{5106}' . + '\x{5107}\x{5108}\x{5109}\x{510A}\x{510B}\x{510C}\x{510D}\x{510E}\x{510F}' . + '\x{5110}\x{5111}\x{5112}\x{5113}\x{5114}\x{5115}\x{5116}\x{5117}\x{5118}' . + '\x{5119}\x{511A}\x{511C}\x{511D}\x{511E}\x{511F}\x{5120}\x{5121}\x{5122}' . + '\x{5123}\x{5124}\x{5125}\x{5126}\x{5127}\x{5129}\x{512A}\x{512C}\x{512D}' . + '\x{512E}\x{512F}\x{5130}\x{5131}\x{5132}\x{5133}\x{5134}\x{5135}\x{5136}' . + '\x{5137}\x{5138}\x{5139}\x{513A}\x{513B}\x{513C}\x{513D}\x{513E}\x{513F}' . + '\x{5140}\x{5141}\x{5143}\x{5144}\x{5145}\x{5146}\x{5147}\x{5148}\x{5149}' . + '\x{514B}\x{514C}\x{514D}\x{514E}\x{5150}\x{5151}\x{5152}\x{5154}\x{5155}' . + '\x{5156}\x{5157}\x{5159}\x{515A}\x{515B}\x{515C}\x{515D}\x{515E}\x{515F}' . + '\x{5161}\x{5162}\x{5163}\x{5165}\x{5166}\x{5167}\x{5168}\x{5169}\x{516A}' . + '\x{516B}\x{516C}\x{516D}\x{516E}\x{516F}\x{5170}\x{5171}\x{5173}\x{5174}' . + '\x{5175}\x{5176}\x{5177}\x{5178}\x{5179}\x{517A}\x{517B}\x{517C}\x{517D}' . + '\x{517F}\x{5180}\x{5181}\x{5182}\x{5185}\x{5186}\x{5187}\x{5188}\x{5189}' . + '\x{518A}\x{518B}\x{518C}\x{518D}\x{518F}\x{5190}\x{5191}\x{5192}\x{5193}' . + '\x{5194}\x{5195}\x{5196}\x{5197}\x{5198}\x{5199}\x{519A}\x{519B}\x{519C}' . + '\x{519D}\x{519E}\x{519F}\x{51A0}\x{51A2}\x{51A4}\x{51A5}\x{51A6}\x{51A7}' . + '\x{51A8}\x{51AA}\x{51AB}\x{51AC}\x{51AE}\x{51AF}\x{51B0}\x{51B1}\x{51B2}' . + '\x{51B3}\x{51B5}\x{51B6}\x{51B7}\x{51B9}\x{51BB}\x{51BC}\x{51BD}\x{51BE}' . + '\x{51BF}\x{51C0}\x{51C1}\x{51C3}\x{51C4}\x{51C5}\x{51C6}\x{51C7}\x{51C8}' . + '\x{51C9}\x{51CA}\x{51CB}\x{51CC}\x{51CD}\x{51CE}\x{51CF}\x{51D0}\x{51D1}' . + '\x{51D4}\x{51D5}\x{51D6}\x{51D7}\x{51D8}\x{51D9}\x{51DA}\x{51DB}\x{51DC}' . + '\x{51DD}\x{51DE}\x{51E0}\x{51E1}\x{51E2}\x{51E3}\x{51E4}\x{51E5}\x{51E7}' . + '\x{51E8}\x{51E9}\x{51EA}\x{51EB}\x{51ED}\x{51EF}\x{51F0}\x{51F1}\x{51F3}' . + '\x{51F4}\x{51F5}\x{51F6}\x{51F7}\x{51F8}\x{51F9}\x{51FA}\x{51FB}\x{51FC}' . + '\x{51FD}\x{51FE}\x{51FF}\x{5200}\x{5201}\x{5202}\x{5203}\x{5204}\x{5205}' . + '\x{5206}\x{5207}\x{5208}\x{5209}\x{520A}\x{520B}\x{520C}\x{520D}\x{520E}' . + '\x{520F}\x{5210}\x{5211}\x{5212}\x{5213}\x{5214}\x{5215}\x{5216}\x{5217}' . + '\x{5218}\x{5219}\x{521A}\x{521B}\x{521C}\x{521D}\x{521E}\x{521F}\x{5220}' . + '\x{5221}\x{5222}\x{5223}\x{5224}\x{5225}\x{5226}\x{5228}\x{5229}\x{522A}' . + '\x{522B}\x{522C}\x{522D}\x{522E}\x{522F}\x{5230}\x{5231}\x{5232}\x{5233}' . + '\x{5234}\x{5235}\x{5236}\x{5237}\x{5238}\x{5239}\x{523A}\x{523B}\x{523C}' . + '\x{523D}\x{523E}\x{523F}\x{5240}\x{5241}\x{5242}\x{5243}\x{5244}\x{5245}' . + '\x{5246}\x{5247}\x{5248}\x{5249}\x{524A}\x{524B}\x{524C}\x{524D}\x{524E}' . + '\x{5250}\x{5251}\x{5252}\x{5254}\x{5255}\x{5256}\x{5257}\x{5258}\x{5259}' . + '\x{525A}\x{525B}\x{525C}\x{525D}\x{525E}\x{525F}\x{5260}\x{5261}\x{5262}' . + '\x{5263}\x{5264}\x{5265}\x{5267}\x{5268}\x{5269}\x{526A}\x{526B}\x{526C}' . + '\x{526D}\x{526E}\x{526F}\x{5270}\x{5272}\x{5273}\x{5274}\x{5275}\x{5276}' . + '\x{5277}\x{5278}\x{527A}\x{527B}\x{527C}\x{527D}\x{527E}\x{527F}\x{5280}' . + '\x{5281}\x{5282}\x{5283}\x{5284}\x{5286}\x{5287}\x{5288}\x{5289}\x{528A}' . + '\x{528B}\x{528C}\x{528D}\x{528F}\x{5290}\x{5291}\x{5292}\x{5293}\x{5294}' . + '\x{5295}\x{5296}\x{5297}\x{5298}\x{5299}\x{529A}\x{529B}\x{529C}\x{529D}' . + '\x{529E}\x{529F}\x{52A0}\x{52A1}\x{52A2}\x{52A3}\x{52A5}\x{52A6}\x{52A7}' . + '\x{52A8}\x{52A9}\x{52AA}\x{52AB}\x{52AC}\x{52AD}\x{52AE}\x{52AF}\x{52B0}' . + '\x{52B1}\x{52B2}\x{52B3}\x{52B4}\x{52B5}\x{52B6}\x{52B7}\x{52B8}\x{52B9}' . + '\x{52BA}\x{52BB}\x{52BC}\x{52BD}\x{52BE}\x{52BF}\x{52C0}\x{52C1}\x{52C2}' . + '\x{52C3}\x{52C6}\x{52C7}\x{52C9}\x{52CA}\x{52CB}\x{52CD}\x{52CF}\x{52D0}' . + '\x{52D2}\x{52D3}\x{52D5}\x{52D6}\x{52D7}\x{52D8}\x{52D9}\x{52DA}\x{52DB}' . + '\x{52DC}\x{52DD}\x{52DE}\x{52DF}\x{52E0}\x{52E2}\x{52E3}\x{52E4}\x{52E6}' . + '\x{52E7}\x{52E8}\x{52E9}\x{52EA}\x{52EB}\x{52EC}\x{52ED}\x{52EF}\x{52F0}' . + '\x{52F1}\x{52F2}\x{52F3}\x{52F4}\x{52F5}\x{52F6}\x{52F7}\x{52F8}\x{52F9}' . + '\x{52FA}\x{52FB}\x{52FC}\x{52FD}\x{52FE}\x{52FF}\x{5300}\x{5301}\x{5302}' . + '\x{5305}\x{5306}\x{5307}\x{5308}\x{5309}\x{530A}\x{530B}\x{530C}\x{530D}' . + '\x{530E}\x{530F}\x{5310}\x{5311}\x{5312}\x{5313}\x{5314}\x{5315}\x{5316}' . + '\x{5317}\x{5319}\x{531A}\x{531C}\x{531D}\x{531F}\x{5320}\x{5321}\x{5322}' . + '\x{5323}\x{5324}\x{5325}\x{5326}\x{5328}\x{532A}\x{532B}\x{532C}\x{532D}' . + '\x{532E}\x{532F}\x{5330}\x{5331}\x{5333}\x{5334}\x{5337}\x{5339}\x{533A}' . + '\x{533B}\x{533C}\x{533D}\x{533E}\x{533F}\x{5340}\x{5341}\x{5343}\x{5344}' . + '\x{5345}\x{5346}\x{5347}\x{5348}\x{5349}\x{534A}\x{534B}\x{534C}\x{534D}' . + '\x{534E}\x{534F}\x{5350}\x{5351}\x{5352}\x{5353}\x{5354}\x{5355}\x{5356}' . + '\x{5357}\x{5358}\x{5359}\x{535A}\x{535C}\x{535E}\x{535F}\x{5360}\x{5361}' . + '\x{5362}\x{5363}\x{5364}\x{5365}\x{5366}\x{5367}\x{5369}\x{536B}\x{536C}' . + '\x{536E}\x{536F}\x{5370}\x{5371}\x{5372}\x{5373}\x{5374}\x{5375}\x{5376}' . + '\x{5377}\x{5378}\x{5379}\x{537A}\x{537B}\x{537C}\x{537D}\x{537E}\x{537F}' . + '\x{5381}\x{5382}\x{5383}\x{5384}\x{5385}\x{5386}\x{5387}\x{5388}\x{5389}' . + '\x{538A}\x{538B}\x{538C}\x{538D}\x{538E}\x{538F}\x{5390}\x{5391}\x{5392}' . + '\x{5393}\x{5394}\x{5395}\x{5396}\x{5397}\x{5398}\x{5399}\x{539A}\x{539B}' . + '\x{539C}\x{539D}\x{539E}\x{539F}\x{53A0}\x{53A2}\x{53A3}\x{53A4}\x{53A5}' . + '\x{53A6}\x{53A7}\x{53A8}\x{53A9}\x{53AC}\x{53AD}\x{53AE}\x{53B0}\x{53B1}' . + '\x{53B2}\x{53B3}\x{53B4}\x{53B5}\x{53B6}\x{53B7}\x{53B8}\x{53B9}\x{53BB}' . + '\x{53BC}\x{53BD}\x{53BE}\x{53BF}\x{53C0}\x{53C1}\x{53C2}\x{53C3}\x{53C4}' . + '\x{53C6}\x{53C7}\x{53C8}\x{53C9}\x{53CA}\x{53CB}\x{53CC}\x{53CD}\x{53CE}' . + '\x{53D0}\x{53D1}\x{53D2}\x{53D3}\x{53D4}\x{53D5}\x{53D6}\x{53D7}\x{53D8}' . + '\x{53D9}\x{53DB}\x{53DC}\x{53DF}\x{53E0}\x{53E1}\x{53E2}\x{53E3}\x{53E4}' . + '\x{53E5}\x{53E6}\x{53E8}\x{53E9}\x{53EA}\x{53EB}\x{53EC}\x{53ED}\x{53EE}' . + '\x{53EF}\x{53F0}\x{53F1}\x{53F2}\x{53F3}\x{53F4}\x{53F5}\x{53F6}\x{53F7}' . + '\x{53F8}\x{53F9}\x{53FA}\x{53FB}\x{53FC}\x{53FD}\x{53FE}\x{5401}\x{5402}' . + '\x{5403}\x{5404}\x{5405}\x{5406}\x{5407}\x{5408}\x{5409}\x{540A}\x{540B}' . + '\x{540C}\x{540D}\x{540E}\x{540F}\x{5410}\x{5411}\x{5412}\x{5413}\x{5414}' . + '\x{5415}\x{5416}\x{5417}\x{5418}\x{5419}\x{541B}\x{541C}\x{541D}\x{541E}' . + '\x{541F}\x{5420}\x{5421}\x{5423}\x{5424}\x{5425}\x{5426}\x{5427}\x{5428}' . + '\x{5429}\x{542A}\x{542B}\x{542C}\x{542D}\x{542E}\x{542F}\x{5430}\x{5431}' . + '\x{5432}\x{5433}\x{5434}\x{5435}\x{5436}\x{5437}\x{5438}\x{5439}\x{543A}' . + '\x{543B}\x{543C}\x{543D}\x{543E}\x{543F}\x{5440}\x{5441}\x{5442}\x{5443}' . + '\x{5444}\x{5445}\x{5446}\x{5447}\x{5448}\x{5449}\x{544A}\x{544B}\x{544D}' . + '\x{544E}\x{544F}\x{5450}\x{5451}\x{5452}\x{5453}\x{5454}\x{5455}\x{5456}' . + '\x{5457}\x{5458}\x{5459}\x{545A}\x{545B}\x{545C}\x{545E}\x{545F}\x{5460}' . + '\x{5461}\x{5462}\x{5463}\x{5464}\x{5465}\x{5466}\x{5467}\x{5468}\x{546A}' . + '\x{546B}\x{546C}\x{546D}\x{546E}\x{546F}\x{5470}\x{5471}\x{5472}\x{5473}' . + '\x{5474}\x{5475}\x{5476}\x{5477}\x{5478}\x{5479}\x{547A}\x{547B}\x{547C}' . + '\x{547D}\x{547E}\x{547F}\x{5480}\x{5481}\x{5482}\x{5483}\x{5484}\x{5485}' . + '\x{5486}\x{5487}\x{5488}\x{5489}\x{548B}\x{548C}\x{548D}\x{548E}\x{548F}' . + '\x{5490}\x{5491}\x{5492}\x{5493}\x{5494}\x{5495}\x{5496}\x{5497}\x{5498}' . + '\x{5499}\x{549A}\x{549B}\x{549C}\x{549D}\x{549E}\x{549F}\x{54A0}\x{54A1}' . + '\x{54A2}\x{54A3}\x{54A4}\x{54A5}\x{54A6}\x{54A7}\x{54A8}\x{54A9}\x{54AA}' . + '\x{54AB}\x{54AC}\x{54AD}\x{54AE}\x{54AF}\x{54B0}\x{54B1}\x{54B2}\x{54B3}' . + '\x{54B4}\x{54B6}\x{54B7}\x{54B8}\x{54B9}\x{54BA}\x{54BB}\x{54BC}\x{54BD}' . + '\x{54BE}\x{54BF}\x{54C0}\x{54C1}\x{54C2}\x{54C3}\x{54C4}\x{54C5}\x{54C6}' . + '\x{54C7}\x{54C8}\x{54C9}\x{54CA}\x{54CB}\x{54CC}\x{54CD}\x{54CE}\x{54CF}' . + '\x{54D0}\x{54D1}\x{54D2}\x{54D3}\x{54D4}\x{54D5}\x{54D6}\x{54D7}\x{54D8}' . + '\x{54D9}\x{54DA}\x{54DB}\x{54DC}\x{54DD}\x{54DE}\x{54DF}\x{54E0}\x{54E1}' . + '\x{54E2}\x{54E3}\x{54E4}\x{54E5}\x{54E6}\x{54E7}\x{54E8}\x{54E9}\x{54EA}' . + '\x{54EB}\x{54EC}\x{54ED}\x{54EE}\x{54EF}\x{54F0}\x{54F1}\x{54F2}\x{54F3}' . + '\x{54F4}\x{54F5}\x{54F7}\x{54F8}\x{54F9}\x{54FA}\x{54FB}\x{54FC}\x{54FD}' . + '\x{54FE}\x{54FF}\x{5500}\x{5501}\x{5502}\x{5503}\x{5504}\x{5505}\x{5506}' . + '\x{5507}\x{5508}\x{5509}\x{550A}\x{550B}\x{550C}\x{550D}\x{550E}\x{550F}' . + '\x{5510}\x{5511}\x{5512}\x{5513}\x{5514}\x{5516}\x{5517}\x{551A}\x{551B}' . + '\x{551C}\x{551D}\x{551E}\x{551F}\x{5520}\x{5521}\x{5522}\x{5523}\x{5524}' . + '\x{5525}\x{5526}\x{5527}\x{5528}\x{5529}\x{552A}\x{552B}\x{552C}\x{552D}' . + '\x{552E}\x{552F}\x{5530}\x{5531}\x{5532}\x{5533}\x{5534}\x{5535}\x{5536}' . + '\x{5537}\x{5538}\x{5539}\x{553A}\x{553B}\x{553C}\x{553D}\x{553E}\x{553F}' . + '\x{5540}\x{5541}\x{5542}\x{5543}\x{5544}\x{5545}\x{5546}\x{5548}\x{5549}' . + '\x{554A}\x{554B}\x{554C}\x{554D}\x{554E}\x{554F}\x{5550}\x{5551}\x{5552}' . + '\x{5553}\x{5554}\x{5555}\x{5556}\x{5557}\x{5558}\x{5559}\x{555A}\x{555B}' . + '\x{555C}\x{555D}\x{555E}\x{555F}\x{5561}\x{5562}\x{5563}\x{5564}\x{5565}' . + '\x{5566}\x{5567}\x{5568}\x{5569}\x{556A}\x{556B}\x{556C}\x{556D}\x{556E}' . + '\x{556F}\x{5570}\x{5571}\x{5572}\x{5573}\x{5574}\x{5575}\x{5576}\x{5577}' . + '\x{5578}\x{5579}\x{557B}\x{557C}\x{557D}\x{557E}\x{557F}\x{5580}\x{5581}' . + '\x{5582}\x{5583}\x{5584}\x{5585}\x{5586}\x{5587}\x{5588}\x{5589}\x{558A}' . + '\x{558B}\x{558C}\x{558D}\x{558E}\x{558F}\x{5590}\x{5591}\x{5592}\x{5593}' . + '\x{5594}\x{5595}\x{5596}\x{5597}\x{5598}\x{5599}\x{559A}\x{559B}\x{559C}' . + '\x{559D}\x{559E}\x{559F}\x{55A0}\x{55A1}\x{55A2}\x{55A3}\x{55A4}\x{55A5}' . + '\x{55A6}\x{55A7}\x{55A8}\x{55A9}\x{55AA}\x{55AB}\x{55AC}\x{55AD}\x{55AE}' . + '\x{55AF}\x{55B0}\x{55B1}\x{55B2}\x{55B3}\x{55B4}\x{55B5}\x{55B6}\x{55B7}' . + '\x{55B8}\x{55B9}\x{55BA}\x{55BB}\x{55BC}\x{55BD}\x{55BE}\x{55BF}\x{55C0}' . + '\x{55C1}\x{55C2}\x{55C3}\x{55C4}\x{55C5}\x{55C6}\x{55C7}\x{55C8}\x{55C9}' . + '\x{55CA}\x{55CB}\x{55CC}\x{55CD}\x{55CE}\x{55CF}\x{55D0}\x{55D1}\x{55D2}' . + '\x{55D3}\x{55D4}\x{55D5}\x{55D6}\x{55D7}\x{55D8}\x{55D9}\x{55DA}\x{55DB}' . + '\x{55DC}\x{55DD}\x{55DE}\x{55DF}\x{55E1}\x{55E2}\x{55E3}\x{55E4}\x{55E5}' . + '\x{55E6}\x{55E7}\x{55E8}\x{55E9}\x{55EA}\x{55EB}\x{55EC}\x{55ED}\x{55EE}' . + '\x{55EF}\x{55F0}\x{55F1}\x{55F2}\x{55F3}\x{55F4}\x{55F5}\x{55F6}\x{55F7}' . + '\x{55F9}\x{55FA}\x{55FB}\x{55FC}\x{55FD}\x{55FE}\x{55FF}\x{5600}\x{5601}' . + '\x{5602}\x{5603}\x{5604}\x{5606}\x{5607}\x{5608}\x{5609}\x{560C}\x{560D}' . + '\x{560E}\x{560F}\x{5610}\x{5611}\x{5612}\x{5613}\x{5614}\x{5615}\x{5616}' . + '\x{5617}\x{5618}\x{5619}\x{561A}\x{561B}\x{561C}\x{561D}\x{561E}\x{561F}' . + '\x{5621}\x{5622}\x{5623}\x{5624}\x{5625}\x{5626}\x{5627}\x{5628}\x{5629}' . + '\x{562A}\x{562C}\x{562D}\x{562E}\x{562F}\x{5630}\x{5631}\x{5632}\x{5633}' . + '\x{5634}\x{5635}\x{5636}\x{5638}\x{5639}\x{563A}\x{563B}\x{563D}\x{563E}' . + '\x{563F}\x{5640}\x{5641}\x{5642}\x{5643}\x{5645}\x{5646}\x{5647}\x{5648}' . + '\x{5649}\x{564A}\x{564C}\x{564D}\x{564E}\x{564F}\x{5650}\x{5652}\x{5653}' . + '\x{5654}\x{5655}\x{5657}\x{5658}\x{5659}\x{565A}\x{565B}\x{565C}\x{565D}' . + '\x{565E}\x{5660}\x{5662}\x{5663}\x{5664}\x{5665}\x{5666}\x{5667}\x{5668}' . + '\x{5669}\x{566A}\x{566B}\x{566C}\x{566D}\x{566E}\x{566F}\x{5670}\x{5671}' . + '\x{5672}\x{5673}\x{5674}\x{5676}\x{5677}\x{5678}\x{5679}\x{567A}\x{567B}' . + '\x{567C}\x{567E}\x{567F}\x{5680}\x{5681}\x{5682}\x{5683}\x{5684}\x{5685}' . + '\x{5686}\x{5687}\x{568A}\x{568C}\x{568D}\x{568E}\x{568F}\x{5690}\x{5691}' . + '\x{5692}\x{5693}\x{5694}\x{5695}\x{5697}\x{5698}\x{5699}\x{569A}\x{569B}' . + '\x{569C}\x{569D}\x{569F}\x{56A0}\x{56A1}\x{56A3}\x{56A4}\x{56A5}\x{56A6}' . + '\x{56A7}\x{56A8}\x{56A9}\x{56AA}\x{56AB}\x{56AC}\x{56AD}\x{56AE}\x{56AF}' . + '\x{56B0}\x{56B1}\x{56B2}\x{56B3}\x{56B4}\x{56B5}\x{56B6}\x{56B7}\x{56B8}' . + '\x{56B9}\x{56BB}\x{56BC}\x{56BD}\x{56BE}\x{56BF}\x{56C0}\x{56C1}\x{56C2}' . + '\x{56C3}\x{56C4}\x{56C5}\x{56C6}\x{56C7}\x{56C8}\x{56C9}\x{56CA}\x{56CB}' . + '\x{56CC}\x{56CD}\x{56CE}\x{56D0}\x{56D1}\x{56D2}\x{56D3}\x{56D4}\x{56D5}' . + '\x{56D6}\x{56D7}\x{56D8}\x{56DA}\x{56DB}\x{56DC}\x{56DD}\x{56DE}\x{56DF}' . + '\x{56E0}\x{56E1}\x{56E2}\x{56E3}\x{56E4}\x{56E5}\x{56E7}\x{56E8}\x{56E9}' . + '\x{56EA}\x{56EB}\x{56EC}\x{56ED}\x{56EE}\x{56EF}\x{56F0}\x{56F1}\x{56F2}' . + '\x{56F3}\x{56F4}\x{56F5}\x{56F7}\x{56F9}\x{56FA}\x{56FD}\x{56FE}\x{56FF}' . + '\x{5700}\x{5701}\x{5702}\x{5703}\x{5704}\x{5706}\x{5707}\x{5708}\x{5709}' . + '\x{570A}\x{570B}\x{570C}\x{570D}\x{570E}\x{570F}\x{5710}\x{5712}\x{5713}' . + '\x{5714}\x{5715}\x{5716}\x{5718}\x{5719}\x{571A}\x{571B}\x{571C}\x{571D}' . + '\x{571E}\x{571F}\x{5720}\x{5722}\x{5723}\x{5725}\x{5726}\x{5727}\x{5728}' . + '\x{5729}\x{572A}\x{572B}\x{572C}\x{572D}\x{572E}\x{572F}\x{5730}\x{5731}' . + '\x{5732}\x{5733}\x{5734}\x{5735}\x{5736}\x{5737}\x{5738}\x{5739}\x{573A}' . + '\x{573B}\x{573C}\x{573E}\x{573F}\x{5740}\x{5741}\x{5742}\x{5744}\x{5745}' . + '\x{5746}\x{5747}\x{5749}\x{574A}\x{574B}\x{574C}\x{574D}\x{574E}\x{574F}' . + '\x{5750}\x{5751}\x{5752}\x{5753}\x{5754}\x{5757}\x{5759}\x{575A}\x{575B}' . + '\x{575C}\x{575D}\x{575E}\x{575F}\x{5760}\x{5761}\x{5762}\x{5764}\x{5765}' . + '\x{5766}\x{5767}\x{5768}\x{5769}\x{576A}\x{576B}\x{576C}\x{576D}\x{576F}' . + '\x{5770}\x{5771}\x{5772}\x{5773}\x{5774}\x{5775}\x{5776}\x{5777}\x{5779}' . + '\x{577A}\x{577B}\x{577C}\x{577D}\x{577E}\x{577F}\x{5780}\x{5782}\x{5783}' . + '\x{5784}\x{5785}\x{5786}\x{5788}\x{5789}\x{578A}\x{578B}\x{578C}\x{578D}' . + '\x{578E}\x{578F}\x{5790}\x{5791}\x{5792}\x{5793}\x{5794}\x{5795}\x{5797}' . + '\x{5798}\x{5799}\x{579A}\x{579B}\x{579C}\x{579D}\x{579E}\x{579F}\x{57A0}' . + '\x{57A1}\x{57A2}\x{57A3}\x{57A4}\x{57A5}\x{57A6}\x{57A7}\x{57A9}\x{57AA}' . + '\x{57AB}\x{57AC}\x{57AD}\x{57AE}\x{57AF}\x{57B0}\x{57B1}\x{57B2}\x{57B3}' . + '\x{57B4}\x{57B5}\x{57B6}\x{57B7}\x{57B8}\x{57B9}\x{57BA}\x{57BB}\x{57BC}' . + '\x{57BD}\x{57BE}\x{57BF}\x{57C0}\x{57C1}\x{57C2}\x{57C3}\x{57C4}\x{57C5}' . + '\x{57C6}\x{57C7}\x{57C8}\x{57C9}\x{57CB}\x{57CC}\x{57CD}\x{57CE}\x{57CF}' . + '\x{57D0}\x{57D2}\x{57D3}\x{57D4}\x{57D5}\x{57D6}\x{57D8}\x{57D9}\x{57DA}' . + '\x{57DC}\x{57DD}\x{57DF}\x{57E0}\x{57E1}\x{57E2}\x{57E3}\x{57E4}\x{57E5}' . + '\x{57E6}\x{57E7}\x{57E8}\x{57E9}\x{57EA}\x{57EB}\x{57EC}\x{57ED}\x{57EE}' . + '\x{57EF}\x{57F0}\x{57F1}\x{57F2}\x{57F3}\x{57F4}\x{57F5}\x{57F6}\x{57F7}' . + '\x{57F8}\x{57F9}\x{57FA}\x{57FB}\x{57FC}\x{57FD}\x{57FE}\x{57FF}\x{5800}' . + '\x{5801}\x{5802}\x{5803}\x{5804}\x{5805}\x{5806}\x{5807}\x{5808}\x{5809}' . + '\x{580A}\x{580B}\x{580C}\x{580D}\x{580E}\x{580F}\x{5810}\x{5811}\x{5812}' . + '\x{5813}\x{5814}\x{5815}\x{5816}\x{5819}\x{581A}\x{581B}\x{581C}\x{581D}' . + '\x{581E}\x{581F}\x{5820}\x{5821}\x{5822}\x{5823}\x{5824}\x{5825}\x{5826}' . + '\x{5827}\x{5828}\x{5829}\x{582A}\x{582B}\x{582C}\x{582D}\x{582E}\x{582F}' . + '\x{5830}\x{5831}\x{5832}\x{5833}\x{5834}\x{5835}\x{5836}\x{5837}\x{5838}' . + '\x{5839}\x{583A}\x{583B}\x{583C}\x{583D}\x{583E}\x{583F}\x{5840}\x{5842}' . + '\x{5843}\x{5844}\x{5845}\x{5846}\x{5847}\x{5848}\x{5849}\x{584A}\x{584B}' . + '\x{584C}\x{584D}\x{584E}\x{584F}\x{5851}\x{5852}\x{5853}\x{5854}\x{5855}' . + '\x{5857}\x{5858}\x{5859}\x{585A}\x{585B}\x{585C}\x{585D}\x{585E}\x{585F}' . + '\x{5861}\x{5862}\x{5863}\x{5864}\x{5865}\x{5868}\x{5869}\x{586A}\x{586B}' . + '\x{586C}\x{586D}\x{586E}\x{586F}\x{5870}\x{5871}\x{5872}\x{5873}\x{5874}' . + '\x{5875}\x{5876}\x{5878}\x{5879}\x{587A}\x{587B}\x{587C}\x{587D}\x{587E}' . + '\x{587F}\x{5880}\x{5881}\x{5882}\x{5883}\x{5884}\x{5885}\x{5886}\x{5887}' . + '\x{5888}\x{5889}\x{588A}\x{588B}\x{588C}\x{588D}\x{588E}\x{588F}\x{5890}' . + '\x{5891}\x{5892}\x{5893}\x{5894}\x{5896}\x{5897}\x{5898}\x{5899}\x{589A}' . + '\x{589B}\x{589C}\x{589D}\x{589E}\x{589F}\x{58A0}\x{58A1}\x{58A2}\x{58A3}' . + '\x{58A4}\x{58A5}\x{58A6}\x{58A7}\x{58A8}\x{58A9}\x{58AB}\x{58AC}\x{58AD}' . + '\x{58AE}\x{58AF}\x{58B0}\x{58B1}\x{58B2}\x{58B3}\x{58B4}\x{58B7}\x{58B8}' . + '\x{58B9}\x{58BA}\x{58BB}\x{58BC}\x{58BD}\x{58BE}\x{58BF}\x{58C1}\x{58C2}' . + '\x{58C5}\x{58C6}\x{58C7}\x{58C8}\x{58C9}\x{58CA}\x{58CB}\x{58CE}\x{58CF}' . + '\x{58D1}\x{58D2}\x{58D3}\x{58D4}\x{58D5}\x{58D6}\x{58D7}\x{58D8}\x{58D9}' . + '\x{58DA}\x{58DB}\x{58DD}\x{58DE}\x{58DF}\x{58E0}\x{58E2}\x{58E3}\x{58E4}' . + '\x{58E5}\x{58E7}\x{58E8}\x{58E9}\x{58EA}\x{58EB}\x{58EC}\x{58ED}\x{58EE}' . + '\x{58EF}\x{58F0}\x{58F1}\x{58F2}\x{58F3}\x{58F4}\x{58F6}\x{58F7}\x{58F8}' . + '\x{58F9}\x{58FA}\x{58FB}\x{58FC}\x{58FD}\x{58FE}\x{58FF}\x{5900}\x{5902}' . + '\x{5903}\x{5904}\x{5906}\x{5907}\x{5909}\x{590A}\x{590B}\x{590C}\x{590D}' . + '\x{590E}\x{590F}\x{5910}\x{5912}\x{5914}\x{5915}\x{5916}\x{5917}\x{5918}' . + '\x{5919}\x{591A}\x{591B}\x{591C}\x{591D}\x{591E}\x{591F}\x{5920}\x{5921}' . + '\x{5922}\x{5924}\x{5925}\x{5926}\x{5927}\x{5928}\x{5929}\x{592A}\x{592B}' . + '\x{592C}\x{592D}\x{592E}\x{592F}\x{5930}\x{5931}\x{5932}\x{5934}\x{5935}' . + '\x{5937}\x{5938}\x{5939}\x{593A}\x{593B}\x{593C}\x{593D}\x{593E}\x{593F}' . + '\x{5940}\x{5941}\x{5942}\x{5943}\x{5944}\x{5945}\x{5946}\x{5947}\x{5948}' . + '\x{5949}\x{594A}\x{594B}\x{594C}\x{594D}\x{594E}\x{594F}\x{5950}\x{5951}' . + '\x{5952}\x{5953}\x{5954}\x{5955}\x{5956}\x{5957}\x{5958}\x{595A}\x{595C}' . + '\x{595D}\x{595E}\x{595F}\x{5960}\x{5961}\x{5962}\x{5963}\x{5964}\x{5965}' . + '\x{5966}\x{5967}\x{5968}\x{5969}\x{596A}\x{596B}\x{596C}\x{596D}\x{596E}' . + '\x{596F}\x{5970}\x{5971}\x{5972}\x{5973}\x{5974}\x{5975}\x{5976}\x{5977}' . + '\x{5978}\x{5979}\x{597A}\x{597B}\x{597C}\x{597D}\x{597E}\x{597F}\x{5980}' . + '\x{5981}\x{5982}\x{5983}\x{5984}\x{5985}\x{5986}\x{5987}\x{5988}\x{5989}' . + '\x{598A}\x{598B}\x{598C}\x{598D}\x{598E}\x{598F}\x{5990}\x{5991}\x{5992}' . + '\x{5993}\x{5994}\x{5995}\x{5996}\x{5997}\x{5998}\x{5999}\x{599A}\x{599C}' . + '\x{599D}\x{599E}\x{599F}\x{59A0}\x{59A1}\x{59A2}\x{59A3}\x{59A4}\x{59A5}' . + '\x{59A6}\x{59A7}\x{59A8}\x{59A9}\x{59AA}\x{59AB}\x{59AC}\x{59AD}\x{59AE}' . + '\x{59AF}\x{59B0}\x{59B1}\x{59B2}\x{59B3}\x{59B4}\x{59B5}\x{59B6}\x{59B8}' . + '\x{59B9}\x{59BA}\x{59BB}\x{59BC}\x{59BD}\x{59BE}\x{59BF}\x{59C0}\x{59C1}' . + '\x{59C2}\x{59C3}\x{59C4}\x{59C5}\x{59C6}\x{59C7}\x{59C8}\x{59C9}\x{59CA}' . + '\x{59CB}\x{59CC}\x{59CD}\x{59CE}\x{59CF}\x{59D0}\x{59D1}\x{59D2}\x{59D3}' . + '\x{59D4}\x{59D5}\x{59D6}\x{59D7}\x{59D8}\x{59D9}\x{59DA}\x{59DB}\x{59DC}' . + '\x{59DD}\x{59DE}\x{59DF}\x{59E0}\x{59E1}\x{59E2}\x{59E3}\x{59E4}\x{59E5}' . + '\x{59E6}\x{59E8}\x{59E9}\x{59EA}\x{59EB}\x{59EC}\x{59ED}\x{59EE}\x{59EF}' . + '\x{59F0}\x{59F1}\x{59F2}\x{59F3}\x{59F4}\x{59F5}\x{59F6}\x{59F7}\x{59F8}' . + '\x{59F9}\x{59FA}\x{59FB}\x{59FC}\x{59FD}\x{59FE}\x{59FF}\x{5A00}\x{5A01}' . + '\x{5A02}\x{5A03}\x{5A04}\x{5A05}\x{5A06}\x{5A07}\x{5A08}\x{5A09}\x{5A0A}' . + '\x{5A0B}\x{5A0C}\x{5A0D}\x{5A0E}\x{5A0F}\x{5A10}\x{5A11}\x{5A12}\x{5A13}' . + '\x{5A14}\x{5A15}\x{5A16}\x{5A17}\x{5A18}\x{5A19}\x{5A1A}\x{5A1B}\x{5A1C}' . + '\x{5A1D}\x{5A1E}\x{5A1F}\x{5A20}\x{5A21}\x{5A22}\x{5A23}\x{5A25}\x{5A27}' . + '\x{5A28}\x{5A29}\x{5A2A}\x{5A2B}\x{5A2D}\x{5A2E}\x{5A2F}\x{5A31}\x{5A32}' . + '\x{5A33}\x{5A34}\x{5A35}\x{5A36}\x{5A37}\x{5A38}\x{5A39}\x{5A3A}\x{5A3B}' . + '\x{5A3C}\x{5A3D}\x{5A3E}\x{5A3F}\x{5A40}\x{5A41}\x{5A42}\x{5A43}\x{5A44}' . + '\x{5A45}\x{5A46}\x{5A47}\x{5A48}\x{5A49}\x{5A4A}\x{5A4B}\x{5A4C}\x{5A4D}' . + '\x{5A4E}\x{5A4F}\x{5A50}\x{5A51}\x{5A52}\x{5A53}\x{5A55}\x{5A56}\x{5A57}' . + '\x{5A58}\x{5A5A}\x{5A5B}\x{5A5C}\x{5A5D}\x{5A5E}\x{5A5F}\x{5A60}\x{5A61}' . + '\x{5A62}\x{5A63}\x{5A64}\x{5A65}\x{5A66}\x{5A67}\x{5A68}\x{5A69}\x{5A6A}' . + '\x{5A6B}\x{5A6C}\x{5A6D}\x{5A6E}\x{5A70}\x{5A72}\x{5A73}\x{5A74}\x{5A75}' . + '\x{5A76}\x{5A77}\x{5A78}\x{5A79}\x{5A7A}\x{5A7B}\x{5A7C}\x{5A7D}\x{5A7E}' . + '\x{5A7F}\x{5A80}\x{5A81}\x{5A82}\x{5A83}\x{5A84}\x{5A85}\x{5A86}\x{5A88}' . + '\x{5A89}\x{5A8A}\x{5A8B}\x{5A8C}\x{5A8E}\x{5A8F}\x{5A90}\x{5A91}\x{5A92}' . + '\x{5A93}\x{5A94}\x{5A95}\x{5A96}\x{5A97}\x{5A98}\x{5A99}\x{5A9A}\x{5A9B}' . + '\x{5A9C}\x{5A9D}\x{5A9E}\x{5A9F}\x{5AA0}\x{5AA1}\x{5AA2}\x{5AA3}\x{5AA4}' . + '\x{5AA5}\x{5AA6}\x{5AA7}\x{5AA8}\x{5AA9}\x{5AAA}\x{5AAC}\x{5AAD}\x{5AAE}' . + '\x{5AAF}\x{5AB0}\x{5AB1}\x{5AB2}\x{5AB3}\x{5AB4}\x{5AB5}\x{5AB6}\x{5AB7}' . + '\x{5AB8}\x{5AB9}\x{5ABA}\x{5ABB}\x{5ABC}\x{5ABD}\x{5ABE}\x{5ABF}\x{5AC0}' . + '\x{5AC1}\x{5AC2}\x{5AC3}\x{5AC4}\x{5AC5}\x{5AC6}\x{5AC7}\x{5AC8}\x{5AC9}' . + '\x{5ACA}\x{5ACB}\x{5ACC}\x{5ACD}\x{5ACE}\x{5ACF}\x{5AD1}\x{5AD2}\x{5AD4}' . + '\x{5AD5}\x{5AD6}\x{5AD7}\x{5AD8}\x{5AD9}\x{5ADA}\x{5ADB}\x{5ADC}\x{5ADD}' . + '\x{5ADE}\x{5ADF}\x{5AE0}\x{5AE1}\x{5AE2}\x{5AE3}\x{5AE4}\x{5AE5}\x{5AE6}' . + '\x{5AE7}\x{5AE8}\x{5AE9}\x{5AEA}\x{5AEB}\x{5AEC}\x{5AED}\x{5AEE}\x{5AF1}' . + '\x{5AF2}\x{5AF3}\x{5AF4}\x{5AF5}\x{5AF6}\x{5AF7}\x{5AF8}\x{5AF9}\x{5AFA}' . + '\x{5AFB}\x{5AFC}\x{5AFD}\x{5AFE}\x{5AFF}\x{5B00}\x{5B01}\x{5B02}\x{5B03}' . + '\x{5B04}\x{5B05}\x{5B06}\x{5B07}\x{5B08}\x{5B09}\x{5B0B}\x{5B0C}\x{5B0E}' . + '\x{5B0F}\x{5B10}\x{5B11}\x{5B12}\x{5B13}\x{5B14}\x{5B15}\x{5B16}\x{5B17}' . + '\x{5B18}\x{5B19}\x{5B1A}\x{5B1B}\x{5B1C}\x{5B1D}\x{5B1E}\x{5B1F}\x{5B20}' . + '\x{5B21}\x{5B22}\x{5B23}\x{5B24}\x{5B25}\x{5B26}\x{5B27}\x{5B28}\x{5B29}' . + '\x{5B2A}\x{5B2B}\x{5B2C}\x{5B2D}\x{5B2E}\x{5B2F}\x{5B30}\x{5B31}\x{5B32}' . + '\x{5B33}\x{5B34}\x{5B35}\x{5B36}\x{5B37}\x{5B38}\x{5B3A}\x{5B3B}\x{5B3C}' . + '\x{5B3D}\x{5B3E}\x{5B3F}\x{5B40}\x{5B41}\x{5B42}\x{5B43}\x{5B44}\x{5B45}' . + '\x{5B47}\x{5B48}\x{5B49}\x{5B4A}\x{5B4B}\x{5B4C}\x{5B4D}\x{5B4E}\x{5B50}' . + '\x{5B51}\x{5B53}\x{5B54}\x{5B55}\x{5B56}\x{5B57}\x{5B58}\x{5B59}\x{5B5A}' . + '\x{5B5B}\x{5B5C}\x{5B5D}\x{5B5E}\x{5B5F}\x{5B62}\x{5B63}\x{5B64}\x{5B65}' . + '\x{5B66}\x{5B67}\x{5B68}\x{5B69}\x{5B6A}\x{5B6B}\x{5B6C}\x{5B6D}\x{5B6E}' . + '\x{5B70}\x{5B71}\x{5B72}\x{5B73}\x{5B74}\x{5B75}\x{5B76}\x{5B77}\x{5B78}' . + '\x{5B7A}\x{5B7B}\x{5B7C}\x{5B7D}\x{5B7F}\x{5B80}\x{5B81}\x{5B82}\x{5B83}' . + '\x{5B84}\x{5B85}\x{5B87}\x{5B88}\x{5B89}\x{5B8A}\x{5B8B}\x{5B8C}\x{5B8D}' . + '\x{5B8E}\x{5B8F}\x{5B91}\x{5B92}\x{5B93}\x{5B94}\x{5B95}\x{5B96}\x{5B97}' . + '\x{5B98}\x{5B99}\x{5B9A}\x{5B9B}\x{5B9C}\x{5B9D}\x{5B9E}\x{5B9F}\x{5BA0}' . + '\x{5BA1}\x{5BA2}\x{5BA3}\x{5BA4}\x{5BA5}\x{5BA6}\x{5BA7}\x{5BA8}\x{5BAA}' . + '\x{5BAB}\x{5BAC}\x{5BAD}\x{5BAE}\x{5BAF}\x{5BB0}\x{5BB1}\x{5BB3}\x{5BB4}' . + '\x{5BB5}\x{5BB6}\x{5BB8}\x{5BB9}\x{5BBA}\x{5BBB}\x{5BBD}\x{5BBE}\x{5BBF}' . + '\x{5BC0}\x{5BC1}\x{5BC2}\x{5BC3}\x{5BC4}\x{5BC5}\x{5BC6}\x{5BC7}\x{5BCA}' . + '\x{5BCB}\x{5BCC}\x{5BCD}\x{5BCE}\x{5BCF}\x{5BD0}\x{5BD1}\x{5BD2}\x{5BD3}' . + '\x{5BD4}\x{5BD5}\x{5BD6}\x{5BD8}\x{5BD9}\x{5BDB}\x{5BDC}\x{5BDD}\x{5BDE}' . + '\x{5BDF}\x{5BE0}\x{5BE1}\x{5BE2}\x{5BE3}\x{5BE4}\x{5BE5}\x{5BE6}\x{5BE7}' . + '\x{5BE8}\x{5BE9}\x{5BEA}\x{5BEB}\x{5BEC}\x{5BED}\x{5BEE}\x{5BEF}\x{5BF0}' . + '\x{5BF1}\x{5BF2}\x{5BF3}\x{5BF4}\x{5BF5}\x{5BF6}\x{5BF7}\x{5BF8}\x{5BF9}' . + '\x{5BFA}\x{5BFB}\x{5BFC}\x{5BFD}\x{5BFF}\x{5C01}\x{5C03}\x{5C04}\x{5C05}' . + '\x{5C06}\x{5C07}\x{5C08}\x{5C09}\x{5C0A}\x{5C0B}\x{5C0C}\x{5C0D}\x{5C0E}' . + '\x{5C0F}\x{5C10}\x{5C11}\x{5C12}\x{5C13}\x{5C14}\x{5C15}\x{5C16}\x{5C17}' . + '\x{5C18}\x{5C19}\x{5C1A}\x{5C1C}\x{5C1D}\x{5C1E}\x{5C1F}\x{5C20}\x{5C21}' . + '\x{5C22}\x{5C24}\x{5C25}\x{5C27}\x{5C28}\x{5C2A}\x{5C2B}\x{5C2C}\x{5C2D}' . + '\x{5C2E}\x{5C2F}\x{5C30}\x{5C31}\x{5C32}\x{5C33}\x{5C34}\x{5C35}\x{5C37}' . + '\x{5C38}\x{5C39}\x{5C3A}\x{5C3B}\x{5C3C}\x{5C3D}\x{5C3E}\x{5C3F}\x{5C40}' . + '\x{5C41}\x{5C42}\x{5C43}\x{5C44}\x{5C45}\x{5C46}\x{5C47}\x{5C48}\x{5C49}' . + '\x{5C4A}\x{5C4B}\x{5C4C}\x{5C4D}\x{5C4E}\x{5C4F}\x{5C50}\x{5C51}\x{5C52}' . + '\x{5C53}\x{5C54}\x{5C55}\x{5C56}\x{5C57}\x{5C58}\x{5C59}\x{5C5B}\x{5C5C}' . + '\x{5C5D}\x{5C5E}\x{5C5F}\x{5C60}\x{5C61}\x{5C62}\x{5C63}\x{5C64}\x{5C65}' . + '\x{5C66}\x{5C67}\x{5C68}\x{5C69}\x{5C6A}\x{5C6B}\x{5C6C}\x{5C6D}\x{5C6E}' . + '\x{5C6F}\x{5C70}\x{5C71}\x{5C72}\x{5C73}\x{5C74}\x{5C75}\x{5C76}\x{5C77}' . + '\x{5C78}\x{5C79}\x{5C7A}\x{5C7B}\x{5C7C}\x{5C7D}\x{5C7E}\x{5C7F}\x{5C80}' . + '\x{5C81}\x{5C82}\x{5C83}\x{5C84}\x{5C86}\x{5C87}\x{5C88}\x{5C89}\x{5C8A}' . + '\x{5C8B}\x{5C8C}\x{5C8D}\x{5C8E}\x{5C8F}\x{5C90}\x{5C91}\x{5C92}\x{5C93}' . + '\x{5C94}\x{5C95}\x{5C96}\x{5C97}\x{5C98}\x{5C99}\x{5C9A}\x{5C9B}\x{5C9C}' . + '\x{5C9D}\x{5C9E}\x{5C9F}\x{5CA0}\x{5CA1}\x{5CA2}\x{5CA3}\x{5CA4}\x{5CA5}' . + '\x{5CA6}\x{5CA7}\x{5CA8}\x{5CA9}\x{5CAA}\x{5CAB}\x{5CAC}\x{5CAD}\x{5CAE}' . + '\x{5CAF}\x{5CB0}\x{5CB1}\x{5CB2}\x{5CB3}\x{5CB5}\x{5CB6}\x{5CB7}\x{5CB8}' . + '\x{5CBA}\x{5CBB}\x{5CBC}\x{5CBD}\x{5CBE}\x{5CBF}\x{5CC1}\x{5CC2}\x{5CC3}' . + '\x{5CC4}\x{5CC5}\x{5CC6}\x{5CC7}\x{5CC8}\x{5CC9}\x{5CCA}\x{5CCB}\x{5CCC}' . + '\x{5CCD}\x{5CCE}\x{5CCF}\x{5CD0}\x{5CD1}\x{5CD2}\x{5CD3}\x{5CD4}\x{5CD6}' . + '\x{5CD7}\x{5CD8}\x{5CD9}\x{5CDA}\x{5CDB}\x{5CDC}\x{5CDE}\x{5CDF}\x{5CE0}' . + '\x{5CE1}\x{5CE2}\x{5CE3}\x{5CE4}\x{5CE5}\x{5CE6}\x{5CE7}\x{5CE8}\x{5CE9}' . + '\x{5CEA}\x{5CEB}\x{5CEC}\x{5CED}\x{5CEE}\x{5CEF}\x{5CF0}\x{5CF1}\x{5CF2}' . + '\x{5CF3}\x{5CF4}\x{5CF6}\x{5CF7}\x{5CF8}\x{5CF9}\x{5CFA}\x{5CFB}\x{5CFC}' . + '\x{5CFD}\x{5CFE}\x{5CFF}\x{5D00}\x{5D01}\x{5D02}\x{5D03}\x{5D04}\x{5D05}' . + '\x{5D06}\x{5D07}\x{5D08}\x{5D09}\x{5D0A}\x{5D0B}\x{5D0C}\x{5D0D}\x{5D0E}' . + '\x{5D0F}\x{5D10}\x{5D11}\x{5D12}\x{5D13}\x{5D14}\x{5D15}\x{5D16}\x{5D17}' . + '\x{5D18}\x{5D19}\x{5D1A}\x{5D1B}\x{5D1C}\x{5D1D}\x{5D1E}\x{5D1F}\x{5D20}' . + '\x{5D21}\x{5D22}\x{5D23}\x{5D24}\x{5D25}\x{5D26}\x{5D27}\x{5D28}\x{5D29}' . + '\x{5D2A}\x{5D2C}\x{5D2D}\x{5D2E}\x{5D30}\x{5D31}\x{5D32}\x{5D33}\x{5D34}' . + '\x{5D35}\x{5D36}\x{5D37}\x{5D38}\x{5D39}\x{5D3A}\x{5D3C}\x{5D3D}\x{5D3E}' . + '\x{5D3F}\x{5D40}\x{5D41}\x{5D42}\x{5D43}\x{5D44}\x{5D45}\x{5D46}\x{5D47}' . + '\x{5D48}\x{5D49}\x{5D4A}\x{5D4B}\x{5D4C}\x{5D4D}\x{5D4E}\x{5D4F}\x{5D50}' . + '\x{5D51}\x{5D52}\x{5D54}\x{5D55}\x{5D56}\x{5D58}\x{5D59}\x{5D5A}\x{5D5B}' . + '\x{5D5D}\x{5D5E}\x{5D5F}\x{5D61}\x{5D62}\x{5D63}\x{5D64}\x{5D65}\x{5D66}' . + '\x{5D67}\x{5D68}\x{5D69}\x{5D6A}\x{5D6B}\x{5D6C}\x{5D6D}\x{5D6E}\x{5D6F}' . + '\x{5D70}\x{5D71}\x{5D72}\x{5D73}\x{5D74}\x{5D75}\x{5D76}\x{5D77}\x{5D78}' . + '\x{5D79}\x{5D7A}\x{5D7B}\x{5D7C}\x{5D7D}\x{5D7E}\x{5D7F}\x{5D80}\x{5D81}' . + '\x{5D82}\x{5D84}\x{5D85}\x{5D86}\x{5D87}\x{5D88}\x{5D89}\x{5D8A}\x{5D8B}' . + '\x{5D8C}\x{5D8D}\x{5D8E}\x{5D8F}\x{5D90}\x{5D91}\x{5D92}\x{5D93}\x{5D94}' . + '\x{5D95}\x{5D97}\x{5D98}\x{5D99}\x{5D9A}\x{5D9B}\x{5D9C}\x{5D9D}\x{5D9E}' . + '\x{5D9F}\x{5DA0}\x{5DA1}\x{5DA2}\x{5DA5}\x{5DA6}\x{5DA7}\x{5DA8}\x{5DA9}' . + '\x{5DAA}\x{5DAC}\x{5DAD}\x{5DAE}\x{5DAF}\x{5DB0}\x{5DB1}\x{5DB2}\x{5DB4}' . + '\x{5DB5}\x{5DB6}\x{5DB7}\x{5DB8}\x{5DBA}\x{5DBB}\x{5DBC}\x{5DBD}\x{5DBE}' . + '\x{5DBF}\x{5DC0}\x{5DC1}\x{5DC2}\x{5DC3}\x{5DC5}\x{5DC6}\x{5DC7}\x{5DC8}' . + '\x{5DC9}\x{5DCA}\x{5DCB}\x{5DCC}\x{5DCD}\x{5DCE}\x{5DCF}\x{5DD0}\x{5DD1}' . + '\x{5DD2}\x{5DD3}\x{5DD4}\x{5DD5}\x{5DD6}\x{5DD8}\x{5DD9}\x{5DDB}\x{5DDD}' . + '\x{5DDE}\x{5DDF}\x{5DE0}\x{5DE1}\x{5DE2}\x{5DE3}\x{5DE4}\x{5DE5}\x{5DE6}' . + '\x{5DE7}\x{5DE8}\x{5DE9}\x{5DEA}\x{5DEB}\x{5DEC}\x{5DED}\x{5DEE}\x{5DEF}' . + '\x{5DF0}\x{5DF1}\x{5DF2}\x{5DF3}\x{5DF4}\x{5DF5}\x{5DF7}\x{5DF8}\x{5DF9}' . + '\x{5DFA}\x{5DFB}\x{5DFC}\x{5DFD}\x{5DFE}\x{5DFF}\x{5E00}\x{5E01}\x{5E02}' . + '\x{5E03}\x{5E04}\x{5E05}\x{5E06}\x{5E07}\x{5E08}\x{5E09}\x{5E0A}\x{5E0B}' . + '\x{5E0C}\x{5E0D}\x{5E0E}\x{5E0F}\x{5E10}\x{5E11}\x{5E13}\x{5E14}\x{5E15}' . + '\x{5E16}\x{5E17}\x{5E18}\x{5E19}\x{5E1A}\x{5E1B}\x{5E1C}\x{5E1D}\x{5E1E}' . + '\x{5E1F}\x{5E20}\x{5E21}\x{5E22}\x{5E23}\x{5E24}\x{5E25}\x{5E26}\x{5E27}' . + '\x{5E28}\x{5E29}\x{5E2A}\x{5E2B}\x{5E2C}\x{5E2D}\x{5E2E}\x{5E2F}\x{5E30}' . + '\x{5E31}\x{5E32}\x{5E33}\x{5E34}\x{5E35}\x{5E36}\x{5E37}\x{5E38}\x{5E39}' . + '\x{5E3A}\x{5E3B}\x{5E3C}\x{5E3D}\x{5E3E}\x{5E40}\x{5E41}\x{5E42}\x{5E43}' . + '\x{5E44}\x{5E45}\x{5E46}\x{5E47}\x{5E49}\x{5E4A}\x{5E4B}\x{5E4C}\x{5E4D}' . + '\x{5E4E}\x{5E4F}\x{5E50}\x{5E52}\x{5E53}\x{5E54}\x{5E55}\x{5E56}\x{5E57}' . + '\x{5E58}\x{5E59}\x{5E5A}\x{5E5B}\x{5E5C}\x{5E5D}\x{5E5E}\x{5E5F}\x{5E60}' . + '\x{5E61}\x{5E62}\x{5E63}\x{5E64}\x{5E65}\x{5E66}\x{5E67}\x{5E68}\x{5E69}' . + '\x{5E6A}\x{5E6B}\x{5E6C}\x{5E6D}\x{5E6E}\x{5E6F}\x{5E70}\x{5E71}\x{5E72}' . + '\x{5E73}\x{5E74}\x{5E75}\x{5E76}\x{5E77}\x{5E78}\x{5E79}\x{5E7A}\x{5E7B}' . + '\x{5E7C}\x{5E7D}\x{5E7E}\x{5E7F}\x{5E80}\x{5E81}\x{5E82}\x{5E83}\x{5E84}' . + '\x{5E85}\x{5E86}\x{5E87}\x{5E88}\x{5E89}\x{5E8A}\x{5E8B}\x{5E8C}\x{5E8D}' . + '\x{5E8E}\x{5E8F}\x{5E90}\x{5E91}\x{5E93}\x{5E94}\x{5E95}\x{5E96}\x{5E97}' . + '\x{5E98}\x{5E99}\x{5E9A}\x{5E9B}\x{5E9C}\x{5E9D}\x{5E9E}\x{5E9F}\x{5EA0}' . + '\x{5EA1}\x{5EA2}\x{5EA3}\x{5EA4}\x{5EA5}\x{5EA6}\x{5EA7}\x{5EA8}\x{5EA9}' . + '\x{5EAA}\x{5EAB}\x{5EAC}\x{5EAD}\x{5EAE}\x{5EAF}\x{5EB0}\x{5EB1}\x{5EB2}' . + '\x{5EB3}\x{5EB4}\x{5EB5}\x{5EB6}\x{5EB7}\x{5EB8}\x{5EB9}\x{5EBB}\x{5EBC}' . + '\x{5EBD}\x{5EBE}\x{5EBF}\x{5EC1}\x{5EC2}\x{5EC3}\x{5EC4}\x{5EC5}\x{5EC6}' . + '\x{5EC7}\x{5EC8}\x{5EC9}\x{5ECA}\x{5ECB}\x{5ECC}\x{5ECD}\x{5ECE}\x{5ECF}' . + '\x{5ED0}\x{5ED1}\x{5ED2}\x{5ED3}\x{5ED4}\x{5ED5}\x{5ED6}\x{5ED7}\x{5ED8}' . + '\x{5ED9}\x{5EDA}\x{5EDB}\x{5EDC}\x{5EDD}\x{5EDE}\x{5EDF}\x{5EE0}\x{5EE1}' . + '\x{5EE2}\x{5EE3}\x{5EE4}\x{5EE5}\x{5EE6}\x{5EE7}\x{5EE8}\x{5EE9}\x{5EEA}' . + '\x{5EEC}\x{5EED}\x{5EEE}\x{5EEF}\x{5EF0}\x{5EF1}\x{5EF2}\x{5EF3}\x{5EF4}' . + '\x{5EF5}\x{5EF6}\x{5EF7}\x{5EF8}\x{5EFA}\x{5EFB}\x{5EFC}\x{5EFD}\x{5EFE}' . + '\x{5EFF}\x{5F00}\x{5F01}\x{5F02}\x{5F03}\x{5F04}\x{5F05}\x{5F06}\x{5F07}' . + '\x{5F08}\x{5F0A}\x{5F0B}\x{5F0C}\x{5F0D}\x{5F0F}\x{5F11}\x{5F12}\x{5F13}' . + '\x{5F14}\x{5F15}\x{5F16}\x{5F17}\x{5F18}\x{5F19}\x{5F1A}\x{5F1B}\x{5F1C}' . + '\x{5F1D}\x{5F1E}\x{5F1F}\x{5F20}\x{5F21}\x{5F22}\x{5F23}\x{5F24}\x{5F25}' . + '\x{5F26}\x{5F27}\x{5F28}\x{5F29}\x{5F2A}\x{5F2B}\x{5F2C}\x{5F2D}\x{5F2E}' . + '\x{5F2F}\x{5F30}\x{5F31}\x{5F32}\x{5F33}\x{5F34}\x{5F35}\x{5F36}\x{5F37}' . + '\x{5F38}\x{5F39}\x{5F3A}\x{5F3C}\x{5F3E}\x{5F3F}\x{5F40}\x{5F41}\x{5F42}' . + '\x{5F43}\x{5F44}\x{5F45}\x{5F46}\x{5F47}\x{5F48}\x{5F49}\x{5F4A}\x{5F4B}' . + '\x{5F4C}\x{5F4D}\x{5F4E}\x{5F4F}\x{5F50}\x{5F51}\x{5F52}\x{5F53}\x{5F54}' . + '\x{5F55}\x{5F56}\x{5F57}\x{5F58}\x{5F59}\x{5F5A}\x{5F5B}\x{5F5C}\x{5F5D}' . + '\x{5F5E}\x{5F5F}\x{5F60}\x{5F61}\x{5F62}\x{5F63}\x{5F64}\x{5F65}\x{5F66}' . + '\x{5F67}\x{5F68}\x{5F69}\x{5F6A}\x{5F6B}\x{5F6C}\x{5F6D}\x{5F6E}\x{5F6F}' . + '\x{5F70}\x{5F71}\x{5F72}\x{5F73}\x{5F74}\x{5F75}\x{5F76}\x{5F77}\x{5F78}' . + '\x{5F79}\x{5F7A}\x{5F7B}\x{5F7C}\x{5F7D}\x{5F7E}\x{5F7F}\x{5F80}\x{5F81}' . + '\x{5F82}\x{5F83}\x{5F84}\x{5F85}\x{5F86}\x{5F87}\x{5F88}\x{5F89}\x{5F8A}' . + '\x{5F8B}\x{5F8C}\x{5F8D}\x{5F8E}\x{5F90}\x{5F91}\x{5F92}\x{5F93}\x{5F94}' . + '\x{5F95}\x{5F96}\x{5F97}\x{5F98}\x{5F99}\x{5F9B}\x{5F9C}\x{5F9D}\x{5F9E}' . + '\x{5F9F}\x{5FA0}\x{5FA1}\x{5FA2}\x{5FA5}\x{5FA6}\x{5FA7}\x{5FA8}\x{5FA9}' . + '\x{5FAA}\x{5FAB}\x{5FAC}\x{5FAD}\x{5FAE}\x{5FAF}\x{5FB1}\x{5FB2}\x{5FB3}' . + '\x{5FB4}\x{5FB5}\x{5FB6}\x{5FB7}\x{5FB8}\x{5FB9}\x{5FBA}\x{5FBB}\x{5FBC}' . + '\x{5FBD}\x{5FBE}\x{5FBF}\x{5FC0}\x{5FC1}\x{5FC3}\x{5FC4}\x{5FC5}\x{5FC6}' . + '\x{5FC7}\x{5FC8}\x{5FC9}\x{5FCA}\x{5FCB}\x{5FCC}\x{5FCD}\x{5FCF}\x{5FD0}' . + '\x{5FD1}\x{5FD2}\x{5FD3}\x{5FD4}\x{5FD5}\x{5FD6}\x{5FD7}\x{5FD8}\x{5FD9}' . + '\x{5FDA}\x{5FDC}\x{5FDD}\x{5FDE}\x{5FE0}\x{5FE1}\x{5FE3}\x{5FE4}\x{5FE5}' . + '\x{5FE6}\x{5FE7}\x{5FE8}\x{5FE9}\x{5FEA}\x{5FEB}\x{5FED}\x{5FEE}\x{5FEF}' . + '\x{5FF0}\x{5FF1}\x{5FF2}\x{5FF3}\x{5FF4}\x{5FF5}\x{5FF6}\x{5FF7}\x{5FF8}' . + '\x{5FF9}\x{5FFA}\x{5FFB}\x{5FFD}\x{5FFE}\x{5FFF}\x{6000}\x{6001}\x{6002}' . + '\x{6003}\x{6004}\x{6005}\x{6006}\x{6007}\x{6008}\x{6009}\x{600A}\x{600B}' . + '\x{600C}\x{600D}\x{600E}\x{600F}\x{6010}\x{6011}\x{6012}\x{6013}\x{6014}' . + '\x{6015}\x{6016}\x{6017}\x{6018}\x{6019}\x{601A}\x{601B}\x{601C}\x{601D}' . + '\x{601E}\x{601F}\x{6020}\x{6021}\x{6022}\x{6024}\x{6025}\x{6026}\x{6027}' . + '\x{6028}\x{6029}\x{602A}\x{602B}\x{602C}\x{602D}\x{602E}\x{602F}\x{6030}' . + '\x{6031}\x{6032}\x{6033}\x{6034}\x{6035}\x{6036}\x{6037}\x{6038}\x{6039}' . + '\x{603A}\x{603B}\x{603C}\x{603D}\x{603E}\x{603F}\x{6040}\x{6041}\x{6042}' . + '\x{6043}\x{6044}\x{6045}\x{6046}\x{6047}\x{6048}\x{6049}\x{604A}\x{604B}' . + '\x{604C}\x{604D}\x{604E}\x{604F}\x{6050}\x{6051}\x{6052}\x{6053}\x{6054}' . + '\x{6055}\x{6057}\x{6058}\x{6059}\x{605A}\x{605B}\x{605C}\x{605D}\x{605E}' . + '\x{605F}\x{6062}\x{6063}\x{6064}\x{6065}\x{6066}\x{6067}\x{6068}\x{6069}' . + '\x{606A}\x{606B}\x{606C}\x{606D}\x{606E}\x{606F}\x{6070}\x{6072}\x{6073}' . + '\x{6075}\x{6076}\x{6077}\x{6078}\x{6079}\x{607A}\x{607B}\x{607C}\x{607D}' . + '\x{607E}\x{607F}\x{6080}\x{6081}\x{6082}\x{6083}\x{6084}\x{6085}\x{6086}' . + '\x{6087}\x{6088}\x{6089}\x{608A}\x{608B}\x{608C}\x{608D}\x{608E}\x{608F}' . + '\x{6090}\x{6092}\x{6094}\x{6095}\x{6096}\x{6097}\x{6098}\x{6099}\x{609A}' . + '\x{609B}\x{609C}\x{609D}\x{609E}\x{609F}\x{60A0}\x{60A1}\x{60A2}\x{60A3}' . + '\x{60A4}\x{60A6}\x{60A7}\x{60A8}\x{60AA}\x{60AB}\x{60AC}\x{60AD}\x{60AE}' . + '\x{60AF}\x{60B0}\x{60B1}\x{60B2}\x{60B3}\x{60B4}\x{60B5}\x{60B6}\x{60B7}' . + '\x{60B8}\x{60B9}\x{60BA}\x{60BB}\x{60BC}\x{60BD}\x{60BE}\x{60BF}\x{60C0}' . + '\x{60C1}\x{60C2}\x{60C3}\x{60C4}\x{60C5}\x{60C6}\x{60C7}\x{60C8}\x{60C9}' . + '\x{60CA}\x{60CB}\x{60CC}\x{60CD}\x{60CE}\x{60CF}\x{60D0}\x{60D1}\x{60D3}' . + '\x{60D4}\x{60D5}\x{60D7}\x{60D8}\x{60D9}\x{60DA}\x{60DB}\x{60DC}\x{60DD}' . + '\x{60DF}\x{60E0}\x{60E1}\x{60E2}\x{60E4}\x{60E6}\x{60E7}\x{60E8}\x{60E9}' . + '\x{60EA}\x{60EB}\x{60EC}\x{60ED}\x{60EE}\x{60EF}\x{60F0}\x{60F1}\x{60F2}' . + '\x{60F3}\x{60F4}\x{60F5}\x{60F6}\x{60F7}\x{60F8}\x{60F9}\x{60FA}\x{60FB}' . + '\x{60FC}\x{60FE}\x{60FF}\x{6100}\x{6101}\x{6103}\x{6104}\x{6105}\x{6106}' . + '\x{6108}\x{6109}\x{610A}\x{610B}\x{610C}\x{610D}\x{610E}\x{610F}\x{6110}' . + '\x{6112}\x{6113}\x{6114}\x{6115}\x{6116}\x{6117}\x{6118}\x{6119}\x{611A}' . + '\x{611B}\x{611C}\x{611D}\x{611F}\x{6120}\x{6122}\x{6123}\x{6124}\x{6125}' . + '\x{6126}\x{6127}\x{6128}\x{6129}\x{612A}\x{612B}\x{612C}\x{612D}\x{612E}' . + '\x{612F}\x{6130}\x{6132}\x{6134}\x{6136}\x{6137}\x{613A}\x{613B}\x{613C}' . + '\x{613D}\x{613E}\x{613F}\x{6140}\x{6141}\x{6142}\x{6143}\x{6144}\x{6145}' . + '\x{6146}\x{6147}\x{6148}\x{6149}\x{614A}\x{614B}\x{614C}\x{614D}\x{614E}' . + '\x{614F}\x{6150}\x{6151}\x{6152}\x{6153}\x{6154}\x{6155}\x{6156}\x{6157}' . + '\x{6158}\x{6159}\x{615A}\x{615B}\x{615C}\x{615D}\x{615E}\x{615F}\x{6161}' . + '\x{6162}\x{6163}\x{6164}\x{6165}\x{6166}\x{6167}\x{6168}\x{6169}\x{616A}' . + '\x{616B}\x{616C}\x{616D}\x{616E}\x{6170}\x{6171}\x{6172}\x{6173}\x{6174}' . + '\x{6175}\x{6176}\x{6177}\x{6178}\x{6179}\x{617A}\x{617C}\x{617E}\x{6180}' . + '\x{6181}\x{6182}\x{6183}\x{6184}\x{6185}\x{6187}\x{6188}\x{6189}\x{618A}' . + '\x{618B}\x{618C}\x{618D}\x{618E}\x{618F}\x{6190}\x{6191}\x{6192}\x{6193}' . + '\x{6194}\x{6195}\x{6196}\x{6198}\x{6199}\x{619A}\x{619B}\x{619D}\x{619E}' . + '\x{619F}\x{61A0}\x{61A1}\x{61A2}\x{61A3}\x{61A4}\x{61A5}\x{61A6}\x{61A7}' . + '\x{61A8}\x{61A9}\x{61AA}\x{61AB}\x{61AC}\x{61AD}\x{61AE}\x{61AF}\x{61B0}' . + '\x{61B1}\x{61B2}\x{61B3}\x{61B4}\x{61B5}\x{61B6}\x{61B7}\x{61B8}\x{61BA}' . + '\x{61BC}\x{61BD}\x{61BE}\x{61BF}\x{61C0}\x{61C1}\x{61C2}\x{61C3}\x{61C4}' . + '\x{61C5}\x{61C6}\x{61C7}\x{61C8}\x{61C9}\x{61CA}\x{61CB}\x{61CC}\x{61CD}' . + '\x{61CE}\x{61CF}\x{61D0}\x{61D1}\x{61D2}\x{61D4}\x{61D6}\x{61D7}\x{61D8}' . + '\x{61D9}\x{61DA}\x{61DB}\x{61DC}\x{61DD}\x{61DE}\x{61DF}\x{61E0}\x{61E1}' . + '\x{61E2}\x{61E3}\x{61E4}\x{61E5}\x{61E6}\x{61E7}\x{61E8}\x{61E9}\x{61EA}' . + '\x{61EB}\x{61ED}\x{61EE}\x{61F0}\x{61F1}\x{61F2}\x{61F3}\x{61F5}\x{61F6}' . + '\x{61F7}\x{61F8}\x{61F9}\x{61FA}\x{61FB}\x{61FC}\x{61FD}\x{61FE}\x{61FF}' . + '\x{6200}\x{6201}\x{6202}\x{6203}\x{6204}\x{6206}\x{6207}\x{6208}\x{6209}' . + '\x{620A}\x{620B}\x{620C}\x{620D}\x{620E}\x{620F}\x{6210}\x{6211}\x{6212}' . + '\x{6213}\x{6214}\x{6215}\x{6216}\x{6217}\x{6218}\x{6219}\x{621A}\x{621B}' . + '\x{621C}\x{621D}\x{621E}\x{621F}\x{6220}\x{6221}\x{6222}\x{6223}\x{6224}' . + '\x{6225}\x{6226}\x{6227}\x{6228}\x{6229}\x{622A}\x{622B}\x{622C}\x{622D}' . + '\x{622E}\x{622F}\x{6230}\x{6231}\x{6232}\x{6233}\x{6234}\x{6236}\x{6237}' . + '\x{6238}\x{623A}\x{623B}\x{623C}\x{623D}\x{623E}\x{623F}\x{6240}\x{6241}' . + '\x{6242}\x{6243}\x{6244}\x{6245}\x{6246}\x{6247}\x{6248}\x{6249}\x{624A}' . + '\x{624B}\x{624C}\x{624D}\x{624E}\x{624F}\x{6250}\x{6251}\x{6252}\x{6253}' . + '\x{6254}\x{6255}\x{6256}\x{6258}\x{6259}\x{625A}\x{625B}\x{625C}\x{625D}' . + '\x{625E}\x{625F}\x{6260}\x{6261}\x{6262}\x{6263}\x{6264}\x{6265}\x{6266}' . + '\x{6267}\x{6268}\x{6269}\x{626A}\x{626B}\x{626C}\x{626D}\x{626E}\x{626F}' . + '\x{6270}\x{6271}\x{6272}\x{6273}\x{6274}\x{6275}\x{6276}\x{6277}\x{6278}' . + '\x{6279}\x{627A}\x{627B}\x{627C}\x{627D}\x{627E}\x{627F}\x{6280}\x{6281}' . + '\x{6283}\x{6284}\x{6285}\x{6286}\x{6287}\x{6288}\x{6289}\x{628A}\x{628B}' . + '\x{628C}\x{628E}\x{628F}\x{6290}\x{6291}\x{6292}\x{6293}\x{6294}\x{6295}' . + '\x{6296}\x{6297}\x{6298}\x{6299}\x{629A}\x{629B}\x{629C}\x{629E}\x{629F}' . + '\x{62A0}\x{62A1}\x{62A2}\x{62A3}\x{62A4}\x{62A5}\x{62A7}\x{62A8}\x{62A9}' . + '\x{62AA}\x{62AB}\x{62AC}\x{62AD}\x{62AE}\x{62AF}\x{62B0}\x{62B1}\x{62B2}' . + '\x{62B3}\x{62B4}\x{62B5}\x{62B6}\x{62B7}\x{62B8}\x{62B9}\x{62BA}\x{62BB}' . + '\x{62BC}\x{62BD}\x{62BE}\x{62BF}\x{62C0}\x{62C1}\x{62C2}\x{62C3}\x{62C4}' . + '\x{62C5}\x{62C6}\x{62C7}\x{62C8}\x{62C9}\x{62CA}\x{62CB}\x{62CC}\x{62CD}' . + '\x{62CE}\x{62CF}\x{62D0}\x{62D1}\x{62D2}\x{62D3}\x{62D4}\x{62D5}\x{62D6}' . + '\x{62D7}\x{62D8}\x{62D9}\x{62DA}\x{62DB}\x{62DC}\x{62DD}\x{62DF}\x{62E0}' . + '\x{62E1}\x{62E2}\x{62E3}\x{62E4}\x{62E5}\x{62E6}\x{62E7}\x{62E8}\x{62E9}' . + '\x{62EB}\x{62EC}\x{62ED}\x{62EE}\x{62EF}\x{62F0}\x{62F1}\x{62F2}\x{62F3}' . + '\x{62F4}\x{62F5}\x{62F6}\x{62F7}\x{62F8}\x{62F9}\x{62FA}\x{62FB}\x{62FC}' . + '\x{62FD}\x{62FE}\x{62FF}\x{6300}\x{6301}\x{6302}\x{6303}\x{6304}\x{6305}' . + '\x{6306}\x{6307}\x{6308}\x{6309}\x{630B}\x{630C}\x{630D}\x{630E}\x{630F}' . + '\x{6310}\x{6311}\x{6312}\x{6313}\x{6314}\x{6315}\x{6316}\x{6318}\x{6319}' . + '\x{631A}\x{631B}\x{631C}\x{631D}\x{631E}\x{631F}\x{6320}\x{6321}\x{6322}' . + '\x{6323}\x{6324}\x{6325}\x{6326}\x{6327}\x{6328}\x{6329}\x{632A}\x{632B}' . + '\x{632C}\x{632D}\x{632E}\x{632F}\x{6330}\x{6332}\x{6333}\x{6334}\x{6336}' . + '\x{6338}\x{6339}\x{633A}\x{633B}\x{633C}\x{633D}\x{633E}\x{6340}\x{6341}' . + '\x{6342}\x{6343}\x{6344}\x{6345}\x{6346}\x{6347}\x{6348}\x{6349}\x{634A}' . + '\x{634B}\x{634C}\x{634D}\x{634E}\x{634F}\x{6350}\x{6351}\x{6352}\x{6353}' . + '\x{6354}\x{6355}\x{6356}\x{6357}\x{6358}\x{6359}\x{635A}\x{635C}\x{635D}' . + '\x{635E}\x{635F}\x{6360}\x{6361}\x{6362}\x{6363}\x{6364}\x{6365}\x{6366}' . + '\x{6367}\x{6368}\x{6369}\x{636A}\x{636B}\x{636C}\x{636D}\x{636E}\x{636F}' . + '\x{6370}\x{6371}\x{6372}\x{6373}\x{6374}\x{6375}\x{6376}\x{6377}\x{6378}' . + '\x{6379}\x{637A}\x{637B}\x{637C}\x{637D}\x{637E}\x{6380}\x{6381}\x{6382}' . + '\x{6383}\x{6384}\x{6385}\x{6386}\x{6387}\x{6388}\x{6389}\x{638A}\x{638C}' . + '\x{638D}\x{638E}\x{638F}\x{6390}\x{6391}\x{6392}\x{6394}\x{6395}\x{6396}' . + '\x{6397}\x{6398}\x{6399}\x{639A}\x{639B}\x{639C}\x{639D}\x{639E}\x{639F}' . + '\x{63A0}\x{63A1}\x{63A2}\x{63A3}\x{63A4}\x{63A5}\x{63A6}\x{63A7}\x{63A8}' . + '\x{63A9}\x{63AA}\x{63AB}\x{63AC}\x{63AD}\x{63AE}\x{63AF}\x{63B0}\x{63B1}' . + '\x{63B2}\x{63B3}\x{63B4}\x{63B5}\x{63B6}\x{63B7}\x{63B8}\x{63B9}\x{63BA}' . + '\x{63BC}\x{63BD}\x{63BE}\x{63BF}\x{63C0}\x{63C1}\x{63C2}\x{63C3}\x{63C4}' . + '\x{63C5}\x{63C6}\x{63C7}\x{63C8}\x{63C9}\x{63CA}\x{63CB}\x{63CC}\x{63CD}' . + '\x{63CE}\x{63CF}\x{63D0}\x{63D2}\x{63D3}\x{63D4}\x{63D5}\x{63D6}\x{63D7}' . + '\x{63D8}\x{63D9}\x{63DA}\x{63DB}\x{63DC}\x{63DD}\x{63DE}\x{63DF}\x{63E0}' . + '\x{63E1}\x{63E2}\x{63E3}\x{63E4}\x{63E5}\x{63E6}\x{63E7}\x{63E8}\x{63E9}' . + '\x{63EA}\x{63EB}\x{63EC}\x{63ED}\x{63EE}\x{63EF}\x{63F0}\x{63F1}\x{63F2}' . + '\x{63F3}\x{63F4}\x{63F5}\x{63F6}\x{63F7}\x{63F8}\x{63F9}\x{63FA}\x{63FB}' . + '\x{63FC}\x{63FD}\x{63FE}\x{63FF}\x{6400}\x{6401}\x{6402}\x{6403}\x{6404}' . + '\x{6405}\x{6406}\x{6408}\x{6409}\x{640A}\x{640B}\x{640C}\x{640D}\x{640E}' . + '\x{640F}\x{6410}\x{6411}\x{6412}\x{6413}\x{6414}\x{6415}\x{6416}\x{6417}' . + '\x{6418}\x{6419}\x{641A}\x{641B}\x{641C}\x{641D}\x{641E}\x{641F}\x{6420}' . + '\x{6421}\x{6422}\x{6423}\x{6424}\x{6425}\x{6426}\x{6427}\x{6428}\x{6429}' . + '\x{642A}\x{642B}\x{642C}\x{642D}\x{642E}\x{642F}\x{6430}\x{6431}\x{6432}' . + '\x{6433}\x{6434}\x{6435}\x{6436}\x{6437}\x{6438}\x{6439}\x{643A}\x{643D}' . + '\x{643E}\x{643F}\x{6440}\x{6441}\x{6443}\x{6444}\x{6445}\x{6446}\x{6447}' . + '\x{6448}\x{644A}\x{644B}\x{644C}\x{644D}\x{644E}\x{644F}\x{6450}\x{6451}' . + '\x{6452}\x{6453}\x{6454}\x{6455}\x{6456}\x{6457}\x{6458}\x{6459}\x{645B}' . + '\x{645C}\x{645D}\x{645E}\x{645F}\x{6460}\x{6461}\x{6462}\x{6463}\x{6464}' . + '\x{6465}\x{6466}\x{6467}\x{6468}\x{6469}\x{646A}\x{646B}\x{646C}\x{646D}' . + '\x{646E}\x{646F}\x{6470}\x{6471}\x{6472}\x{6473}\x{6474}\x{6475}\x{6476}' . + '\x{6477}\x{6478}\x{6479}\x{647A}\x{647B}\x{647C}\x{647D}\x{647F}\x{6480}' . + '\x{6481}\x{6482}\x{6483}\x{6484}\x{6485}\x{6487}\x{6488}\x{6489}\x{648A}' . + '\x{648B}\x{648C}\x{648D}\x{648E}\x{648F}\x{6490}\x{6491}\x{6492}\x{6493}' . + '\x{6494}\x{6495}\x{6496}\x{6497}\x{6498}\x{6499}\x{649A}\x{649B}\x{649C}' . + '\x{649D}\x{649E}\x{649F}\x{64A0}\x{64A2}\x{64A3}\x{64A4}\x{64A5}\x{64A6}' . + '\x{64A7}\x{64A8}\x{64A9}\x{64AA}\x{64AB}\x{64AC}\x{64AD}\x{64AE}\x{64B0}' . + '\x{64B1}\x{64B2}\x{64B3}\x{64B4}\x{64B5}\x{64B7}\x{64B8}\x{64B9}\x{64BA}' . + '\x{64BB}\x{64BC}\x{64BD}\x{64BE}\x{64BF}\x{64C0}\x{64C1}\x{64C2}\x{64C3}' . + '\x{64C4}\x{64C5}\x{64C6}\x{64C7}\x{64C9}\x{64CA}\x{64CB}\x{64CC}\x{64CD}' . + '\x{64CE}\x{64CF}\x{64D0}\x{64D1}\x{64D2}\x{64D3}\x{64D4}\x{64D6}\x{64D7}' . + '\x{64D8}\x{64D9}\x{64DA}\x{64DB}\x{64DC}\x{64DD}\x{64DE}\x{64DF}\x{64E0}' . + '\x{64E2}\x{64E3}\x{64E4}\x{64E6}\x{64E7}\x{64E8}\x{64E9}\x{64EA}\x{64EB}' . + '\x{64EC}\x{64ED}\x{64EF}\x{64F0}\x{64F1}\x{64F2}\x{64F3}\x{64F4}\x{64F6}' . + '\x{64F7}\x{64F8}\x{64FA}\x{64FB}\x{64FC}\x{64FD}\x{64FE}\x{64FF}\x{6500}' . + '\x{6501}\x{6503}\x{6504}\x{6505}\x{6506}\x{6507}\x{6508}\x{6509}\x{650B}' . + '\x{650C}\x{650D}\x{650E}\x{650F}\x{6510}\x{6511}\x{6512}\x{6513}\x{6514}' . + '\x{6515}\x{6516}\x{6517}\x{6518}\x{6519}\x{651A}\x{651B}\x{651C}\x{651D}' . + '\x{651E}\x{6520}\x{6521}\x{6522}\x{6523}\x{6524}\x{6525}\x{6526}\x{6527}' . + '\x{6529}\x{652A}\x{652B}\x{652C}\x{652D}\x{652E}\x{652F}\x{6530}\x{6531}' . + '\x{6532}\x{6533}\x{6534}\x{6535}\x{6536}\x{6537}\x{6538}\x{6539}\x{653A}' . + '\x{653B}\x{653C}\x{653D}\x{653E}\x{653F}\x{6541}\x{6543}\x{6544}\x{6545}' . + '\x{6546}\x{6547}\x{6548}\x{6549}\x{654A}\x{654B}\x{654C}\x{654D}\x{654E}' . + '\x{654F}\x{6550}\x{6551}\x{6552}\x{6553}\x{6554}\x{6555}\x{6556}\x{6557}' . + '\x{6558}\x{6559}\x{655B}\x{655C}\x{655D}\x{655E}\x{6560}\x{6561}\x{6562}' . + '\x{6563}\x{6564}\x{6565}\x{6566}\x{6567}\x{6568}\x{6569}\x{656A}\x{656B}' . + '\x{656C}\x{656E}\x{656F}\x{6570}\x{6571}\x{6572}\x{6573}\x{6574}\x{6575}' . + '\x{6576}\x{6577}\x{6578}\x{6579}\x{657A}\x{657B}\x{657C}\x{657E}\x{657F}' . + '\x{6580}\x{6581}\x{6582}\x{6583}\x{6584}\x{6585}\x{6586}\x{6587}\x{6588}' . + '\x{6589}\x{658B}\x{658C}\x{658D}\x{658E}\x{658F}\x{6590}\x{6591}\x{6592}' . + '\x{6593}\x{6594}\x{6595}\x{6596}\x{6597}\x{6598}\x{6599}\x{659B}\x{659C}' . + '\x{659D}\x{659E}\x{659F}\x{65A0}\x{65A1}\x{65A2}\x{65A3}\x{65A4}\x{65A5}' . + '\x{65A6}\x{65A7}\x{65A8}\x{65A9}\x{65AA}\x{65AB}\x{65AC}\x{65AD}\x{65AE}' . + '\x{65AF}\x{65B0}\x{65B1}\x{65B2}\x{65B3}\x{65B4}\x{65B6}\x{65B7}\x{65B8}' . + '\x{65B9}\x{65BA}\x{65BB}\x{65BC}\x{65BD}\x{65BF}\x{65C0}\x{65C1}\x{65C2}' . + '\x{65C3}\x{65C4}\x{65C5}\x{65C6}\x{65C7}\x{65CA}\x{65CB}\x{65CC}\x{65CD}' . + '\x{65CE}\x{65CF}\x{65D0}\x{65D2}\x{65D3}\x{65D4}\x{65D5}\x{65D6}\x{65D7}' . + '\x{65DA}\x{65DB}\x{65DD}\x{65DE}\x{65DF}\x{65E0}\x{65E1}\x{65E2}\x{65E3}' . + '\x{65E5}\x{65E6}\x{65E7}\x{65E8}\x{65E9}\x{65EB}\x{65EC}\x{65ED}\x{65EE}' . + '\x{65EF}\x{65F0}\x{65F1}\x{65F2}\x{65F3}\x{65F4}\x{65F5}\x{65F6}\x{65F7}' . + '\x{65F8}\x{65FA}\x{65FB}\x{65FC}\x{65FD}\x{6600}\x{6601}\x{6602}\x{6603}' . + '\x{6604}\x{6605}\x{6606}\x{6607}\x{6608}\x{6609}\x{660A}\x{660B}\x{660C}' . + '\x{660D}\x{660E}\x{660F}\x{6610}\x{6611}\x{6612}\x{6613}\x{6614}\x{6615}' . + '\x{6616}\x{6618}\x{6619}\x{661A}\x{661B}\x{661C}\x{661D}\x{661F}\x{6620}' . + '\x{6621}\x{6622}\x{6623}\x{6624}\x{6625}\x{6626}\x{6627}\x{6628}\x{6629}' . + '\x{662A}\x{662B}\x{662D}\x{662E}\x{662F}\x{6630}\x{6631}\x{6632}\x{6633}' . + '\x{6634}\x{6635}\x{6636}\x{6639}\x{663A}\x{663C}\x{663D}\x{663E}\x{6640}' . + '\x{6641}\x{6642}\x{6643}\x{6644}\x{6645}\x{6646}\x{6647}\x{6649}\x{664A}' . + '\x{664B}\x{664C}\x{664E}\x{664F}\x{6650}\x{6651}\x{6652}\x{6653}\x{6654}' . + '\x{6655}\x{6656}\x{6657}\x{6658}\x{6659}\x{665A}\x{665B}\x{665C}\x{665D}' . + '\x{665E}\x{665F}\x{6661}\x{6662}\x{6664}\x{6665}\x{6666}\x{6668}\x{6669}' . + '\x{666A}\x{666B}\x{666C}\x{666D}\x{666E}\x{666F}\x{6670}\x{6671}\x{6672}' . + '\x{6673}\x{6674}\x{6675}\x{6676}\x{6677}\x{6678}\x{6679}\x{667A}\x{667B}' . + '\x{667C}\x{667D}\x{667E}\x{667F}\x{6680}\x{6681}\x{6682}\x{6683}\x{6684}' . + '\x{6685}\x{6686}\x{6687}\x{6688}\x{6689}\x{668A}\x{668B}\x{668C}\x{668D}' . + '\x{668E}\x{668F}\x{6690}\x{6691}\x{6693}\x{6694}\x{6695}\x{6696}\x{6697}' . + '\x{6698}\x{6699}\x{669A}\x{669B}\x{669D}\x{669F}\x{66A0}\x{66A1}\x{66A2}' . + '\x{66A3}\x{66A4}\x{66A5}\x{66A6}\x{66A7}\x{66A8}\x{66A9}\x{66AA}\x{66AB}' . + '\x{66AE}\x{66AF}\x{66B0}\x{66B1}\x{66B2}\x{66B3}\x{66B4}\x{66B5}\x{66B6}' . + '\x{66B7}\x{66B8}\x{66B9}\x{66BA}\x{66BB}\x{66BC}\x{66BD}\x{66BE}\x{66BF}' . + '\x{66C0}\x{66C1}\x{66C2}\x{66C3}\x{66C4}\x{66C5}\x{66C6}\x{66C7}\x{66C8}' . + '\x{66C9}\x{66CA}\x{66CB}\x{66CC}\x{66CD}\x{66CE}\x{66CF}\x{66D1}\x{66D2}' . + '\x{66D4}\x{66D5}\x{66D6}\x{66D8}\x{66D9}\x{66DA}\x{66DB}\x{66DC}\x{66DD}' . + '\x{66DE}\x{66E0}\x{66E1}\x{66E2}\x{66E3}\x{66E4}\x{66E5}\x{66E6}\x{66E7}' . + '\x{66E8}\x{66E9}\x{66EA}\x{66EB}\x{66EC}\x{66ED}\x{66EE}\x{66F0}\x{66F1}' . + '\x{66F2}\x{66F3}\x{66F4}\x{66F5}\x{66F6}\x{66F7}\x{66F8}\x{66F9}\x{66FA}' . + '\x{66FB}\x{66FC}\x{66FE}\x{66FF}\x{6700}\x{6701}\x{6703}\x{6704}\x{6705}' . + '\x{6706}\x{6708}\x{6709}\x{670A}\x{670B}\x{670C}\x{670D}\x{670E}\x{670F}' . + '\x{6710}\x{6711}\x{6712}\x{6713}\x{6714}\x{6715}\x{6716}\x{6717}\x{6718}' . + '\x{671A}\x{671B}\x{671C}\x{671D}\x{671E}\x{671F}\x{6720}\x{6721}\x{6722}' . + '\x{6723}\x{6725}\x{6726}\x{6727}\x{6728}\x{672A}\x{672B}\x{672C}\x{672D}' . + '\x{672E}\x{672F}\x{6730}\x{6731}\x{6732}\x{6733}\x{6734}\x{6735}\x{6736}' . + '\x{6737}\x{6738}\x{6739}\x{673A}\x{673B}\x{673C}\x{673D}\x{673E}\x{673F}' . + '\x{6740}\x{6741}\x{6742}\x{6743}\x{6744}\x{6745}\x{6746}\x{6747}\x{6748}' . + '\x{6749}\x{674A}\x{674B}\x{674C}\x{674D}\x{674E}\x{674F}\x{6750}\x{6751}' . + '\x{6752}\x{6753}\x{6754}\x{6755}\x{6756}\x{6757}\x{6758}\x{6759}\x{675A}' . + '\x{675B}\x{675C}\x{675D}\x{675E}\x{675F}\x{6760}\x{6761}\x{6762}\x{6763}' . + '\x{6764}\x{6765}\x{6766}\x{6768}\x{6769}\x{676A}\x{676B}\x{676C}\x{676D}' . + '\x{676E}\x{676F}\x{6770}\x{6771}\x{6772}\x{6773}\x{6774}\x{6775}\x{6776}' . + '\x{6777}\x{6778}\x{6779}\x{677A}\x{677B}\x{677C}\x{677D}\x{677E}\x{677F}' . + '\x{6780}\x{6781}\x{6782}\x{6783}\x{6784}\x{6785}\x{6786}\x{6787}\x{6789}' . + '\x{678A}\x{678B}\x{678C}\x{678D}\x{678E}\x{678F}\x{6790}\x{6791}\x{6792}' . + '\x{6793}\x{6794}\x{6795}\x{6797}\x{6798}\x{6799}\x{679A}\x{679B}\x{679C}' . + '\x{679D}\x{679E}\x{679F}\x{67A0}\x{67A1}\x{67A2}\x{67A3}\x{67A4}\x{67A5}' . + '\x{67A6}\x{67A7}\x{67A8}\x{67AA}\x{67AB}\x{67AC}\x{67AD}\x{67AE}\x{67AF}' . + '\x{67B0}\x{67B1}\x{67B2}\x{67B3}\x{67B4}\x{67B5}\x{67B6}\x{67B7}\x{67B8}' . + '\x{67B9}\x{67BA}\x{67BB}\x{67BC}\x{67BE}\x{67C0}\x{67C1}\x{67C2}\x{67C3}' . + '\x{67C4}\x{67C5}\x{67C6}\x{67C7}\x{67C8}\x{67C9}\x{67CA}\x{67CB}\x{67CC}' . + '\x{67CD}\x{67CE}\x{67CF}\x{67D0}\x{67D1}\x{67D2}\x{67D3}\x{67D4}\x{67D6}' . + '\x{67D8}\x{67D9}\x{67DA}\x{67DB}\x{67DC}\x{67DD}\x{67DE}\x{67DF}\x{67E0}' . + '\x{67E1}\x{67E2}\x{67E3}\x{67E4}\x{67E5}\x{67E6}\x{67E7}\x{67E8}\x{67E9}' . + '\x{67EA}\x{67EB}\x{67EC}\x{67ED}\x{67EE}\x{67EF}\x{67F0}\x{67F1}\x{67F2}' . + '\x{67F3}\x{67F4}\x{67F5}\x{67F6}\x{67F7}\x{67F8}\x{67FA}\x{67FB}\x{67FC}' . + '\x{67FD}\x{67FE}\x{67FF}\x{6800}\x{6802}\x{6803}\x{6804}\x{6805}\x{6806}' . + '\x{6807}\x{6808}\x{6809}\x{680A}\x{680B}\x{680C}\x{680D}\x{680E}\x{680F}' . + '\x{6810}\x{6811}\x{6812}\x{6813}\x{6814}\x{6816}\x{6817}\x{6818}\x{6819}' . + '\x{681A}\x{681B}\x{681C}\x{681D}\x{681F}\x{6820}\x{6821}\x{6822}\x{6823}' . + '\x{6824}\x{6825}\x{6826}\x{6828}\x{6829}\x{682A}\x{682B}\x{682C}\x{682D}' . + '\x{682E}\x{682F}\x{6831}\x{6832}\x{6833}\x{6834}\x{6835}\x{6836}\x{6837}' . + '\x{6838}\x{6839}\x{683A}\x{683B}\x{683C}\x{683D}\x{683E}\x{683F}\x{6840}' . + '\x{6841}\x{6842}\x{6843}\x{6844}\x{6845}\x{6846}\x{6847}\x{6848}\x{6849}' . + '\x{684A}\x{684B}\x{684C}\x{684D}\x{684E}\x{684F}\x{6850}\x{6851}\x{6852}' . + '\x{6853}\x{6854}\x{6855}\x{6856}\x{6857}\x{685B}\x{685D}\x{6860}\x{6861}' . + '\x{6862}\x{6863}\x{6864}\x{6865}\x{6866}\x{6867}\x{6868}\x{6869}\x{686A}' . + '\x{686B}\x{686C}\x{686D}\x{686E}\x{686F}\x{6870}\x{6871}\x{6872}\x{6873}' . + '\x{6874}\x{6875}\x{6876}\x{6877}\x{6878}\x{6879}\x{687B}\x{687C}\x{687D}' . + '\x{687E}\x{687F}\x{6880}\x{6881}\x{6882}\x{6883}\x{6884}\x{6885}\x{6886}' . + '\x{6887}\x{6888}\x{6889}\x{688A}\x{688B}\x{688C}\x{688D}\x{688E}\x{688F}' . + '\x{6890}\x{6891}\x{6892}\x{6893}\x{6894}\x{6896}\x{6897}\x{6898}\x{689A}' . + '\x{689B}\x{689C}\x{689D}\x{689E}\x{689F}\x{68A0}\x{68A1}\x{68A2}\x{68A3}' . + '\x{68A4}\x{68A6}\x{68A7}\x{68A8}\x{68A9}\x{68AA}\x{68AB}\x{68AC}\x{68AD}' . + '\x{68AE}\x{68AF}\x{68B0}\x{68B1}\x{68B2}\x{68B3}\x{68B4}\x{68B5}\x{68B6}' . + '\x{68B7}\x{68B9}\x{68BB}\x{68BC}\x{68BD}\x{68BE}\x{68BF}\x{68C0}\x{68C1}' . + '\x{68C2}\x{68C4}\x{68C6}\x{68C7}\x{68C8}\x{68C9}\x{68CA}\x{68CB}\x{68CC}' . + '\x{68CD}\x{68CE}\x{68CF}\x{68D0}\x{68D1}\x{68D2}\x{68D3}\x{68D4}\x{68D5}' . + '\x{68D6}\x{68D7}\x{68D8}\x{68DA}\x{68DB}\x{68DC}\x{68DD}\x{68DE}\x{68DF}' . + '\x{68E0}\x{68E1}\x{68E3}\x{68E4}\x{68E6}\x{68E7}\x{68E8}\x{68E9}\x{68EA}' . + '\x{68EB}\x{68EC}\x{68ED}\x{68EE}\x{68EF}\x{68F0}\x{68F1}\x{68F2}\x{68F3}' . + '\x{68F4}\x{68F5}\x{68F6}\x{68F7}\x{68F8}\x{68F9}\x{68FA}\x{68FB}\x{68FC}' . + '\x{68FD}\x{68FE}\x{68FF}\x{6901}\x{6902}\x{6903}\x{6904}\x{6905}\x{6906}' . + '\x{6907}\x{6908}\x{690A}\x{690B}\x{690C}\x{690D}\x{690E}\x{690F}\x{6910}' . + '\x{6911}\x{6912}\x{6913}\x{6914}\x{6915}\x{6916}\x{6917}\x{6918}\x{6919}' . + '\x{691A}\x{691B}\x{691C}\x{691D}\x{691E}\x{691F}\x{6920}\x{6921}\x{6922}' . + '\x{6923}\x{6924}\x{6925}\x{6926}\x{6927}\x{6928}\x{6929}\x{692A}\x{692B}' . + '\x{692C}\x{692D}\x{692E}\x{692F}\x{6930}\x{6931}\x{6932}\x{6933}\x{6934}' . + '\x{6935}\x{6936}\x{6937}\x{6938}\x{6939}\x{693A}\x{693B}\x{693C}\x{693D}' . + '\x{693F}\x{6940}\x{6941}\x{6942}\x{6943}\x{6944}\x{6945}\x{6946}\x{6947}' . + '\x{6948}\x{6949}\x{694A}\x{694B}\x{694C}\x{694E}\x{694F}\x{6950}\x{6951}' . + '\x{6952}\x{6953}\x{6954}\x{6955}\x{6956}\x{6957}\x{6958}\x{6959}\x{695A}' . + '\x{695B}\x{695C}\x{695D}\x{695E}\x{695F}\x{6960}\x{6961}\x{6962}\x{6963}' . + '\x{6964}\x{6965}\x{6966}\x{6967}\x{6968}\x{6969}\x{696A}\x{696B}\x{696C}' . + '\x{696D}\x{696E}\x{696F}\x{6970}\x{6971}\x{6972}\x{6973}\x{6974}\x{6975}' . + '\x{6976}\x{6977}\x{6978}\x{6979}\x{697A}\x{697B}\x{697C}\x{697D}\x{697E}' . + '\x{697F}\x{6980}\x{6981}\x{6982}\x{6983}\x{6984}\x{6985}\x{6986}\x{6987}' . + '\x{6988}\x{6989}\x{698A}\x{698B}\x{698C}\x{698D}\x{698E}\x{698F}\x{6990}' . + '\x{6991}\x{6992}\x{6993}\x{6994}\x{6995}\x{6996}\x{6997}\x{6998}\x{6999}' . + '\x{699A}\x{699B}\x{699C}\x{699D}\x{699E}\x{69A0}\x{69A1}\x{69A3}\x{69A4}' . + '\x{69A5}\x{69A6}\x{69A7}\x{69A8}\x{69A9}\x{69AA}\x{69AB}\x{69AC}\x{69AD}' . + '\x{69AE}\x{69AF}\x{69B0}\x{69B1}\x{69B2}\x{69B3}\x{69B4}\x{69B5}\x{69B6}' . + '\x{69B7}\x{69B8}\x{69B9}\x{69BA}\x{69BB}\x{69BC}\x{69BD}\x{69BE}\x{69BF}' . + '\x{69C1}\x{69C2}\x{69C3}\x{69C4}\x{69C5}\x{69C6}\x{69C7}\x{69C8}\x{69C9}' . + '\x{69CA}\x{69CB}\x{69CC}\x{69CD}\x{69CE}\x{69CF}\x{69D0}\x{69D3}\x{69D4}' . + '\x{69D8}\x{69D9}\x{69DA}\x{69DB}\x{69DC}\x{69DD}\x{69DE}\x{69DF}\x{69E0}' . + '\x{69E1}\x{69E2}\x{69E3}\x{69E4}\x{69E5}\x{69E6}\x{69E7}\x{69E8}\x{69E9}' . + '\x{69EA}\x{69EB}\x{69EC}\x{69ED}\x{69EE}\x{69EF}\x{69F0}\x{69F1}\x{69F2}' . + '\x{69F3}\x{69F4}\x{69F5}\x{69F6}\x{69F7}\x{69F8}\x{69FA}\x{69FB}\x{69FC}' . + '\x{69FD}\x{69FE}\x{69FF}\x{6A00}\x{6A01}\x{6A02}\x{6A04}\x{6A05}\x{6A06}' . + '\x{6A07}\x{6A08}\x{6A09}\x{6A0A}\x{6A0B}\x{6A0D}\x{6A0E}\x{6A0F}\x{6A10}' . + '\x{6A11}\x{6A12}\x{6A13}\x{6A14}\x{6A15}\x{6A16}\x{6A17}\x{6A18}\x{6A19}' . + '\x{6A1A}\x{6A1B}\x{6A1D}\x{6A1E}\x{6A1F}\x{6A20}\x{6A21}\x{6A22}\x{6A23}' . + '\x{6A25}\x{6A26}\x{6A27}\x{6A28}\x{6A29}\x{6A2A}\x{6A2B}\x{6A2C}\x{6A2D}' . + '\x{6A2E}\x{6A2F}\x{6A30}\x{6A31}\x{6A32}\x{6A33}\x{6A34}\x{6A35}\x{6A36}' . + '\x{6A38}\x{6A39}\x{6A3A}\x{6A3B}\x{6A3C}\x{6A3D}\x{6A3E}\x{6A3F}\x{6A40}' . + '\x{6A41}\x{6A42}\x{6A43}\x{6A44}\x{6A45}\x{6A46}\x{6A47}\x{6A48}\x{6A49}' . + '\x{6A4B}\x{6A4C}\x{6A4D}\x{6A4E}\x{6A4F}\x{6A50}\x{6A51}\x{6A52}\x{6A54}' . + '\x{6A55}\x{6A56}\x{6A57}\x{6A58}\x{6A59}\x{6A5A}\x{6A5B}\x{6A5D}\x{6A5E}' . + '\x{6A5F}\x{6A60}\x{6A61}\x{6A62}\x{6A63}\x{6A64}\x{6A65}\x{6A66}\x{6A67}' . + '\x{6A68}\x{6A69}\x{6A6A}\x{6A6B}\x{6A6C}\x{6A6D}\x{6A6F}\x{6A71}\x{6A72}' . + '\x{6A73}\x{6A74}\x{6A75}\x{6A76}\x{6A77}\x{6A78}\x{6A79}\x{6A7A}\x{6A7B}' . + '\x{6A7C}\x{6A7D}\x{6A7E}\x{6A7F}\x{6A80}\x{6A81}\x{6A82}\x{6A83}\x{6A84}' . + '\x{6A85}\x{6A87}\x{6A88}\x{6A89}\x{6A8B}\x{6A8C}\x{6A8D}\x{6A8E}\x{6A90}' . + '\x{6A91}\x{6A92}\x{6A93}\x{6A94}\x{6A95}\x{6A96}\x{6A97}\x{6A98}\x{6A9A}' . + '\x{6A9B}\x{6A9C}\x{6A9E}\x{6A9F}\x{6AA0}\x{6AA1}\x{6AA2}\x{6AA3}\x{6AA4}' . + '\x{6AA5}\x{6AA6}\x{6AA7}\x{6AA8}\x{6AA9}\x{6AAB}\x{6AAC}\x{6AAD}\x{6AAE}' . + '\x{6AAF}\x{6AB0}\x{6AB2}\x{6AB3}\x{6AB4}\x{6AB5}\x{6AB6}\x{6AB7}\x{6AB8}' . + '\x{6AB9}\x{6ABA}\x{6ABB}\x{6ABC}\x{6ABD}\x{6ABF}\x{6AC1}\x{6AC2}\x{6AC3}' . + '\x{6AC5}\x{6AC6}\x{6AC7}\x{6ACA}\x{6ACB}\x{6ACC}\x{6ACD}\x{6ACE}\x{6ACF}' . + '\x{6AD0}\x{6AD1}\x{6AD2}\x{6AD3}\x{6AD4}\x{6AD5}\x{6AD6}\x{6AD7}\x{6AD9}' . + '\x{6ADA}\x{6ADB}\x{6ADC}\x{6ADD}\x{6ADE}\x{6ADF}\x{6AE0}\x{6AE1}\x{6AE2}' . + '\x{6AE3}\x{6AE4}\x{6AE5}\x{6AE6}\x{6AE7}\x{6AE8}\x{6AEA}\x{6AEB}\x{6AEC}' . + '\x{6AED}\x{6AEE}\x{6AEF}\x{6AF0}\x{6AF1}\x{6AF2}\x{6AF3}\x{6AF4}\x{6AF5}' . + '\x{6AF6}\x{6AF7}\x{6AF8}\x{6AF9}\x{6AFA}\x{6AFB}\x{6AFC}\x{6AFD}\x{6AFE}' . + '\x{6AFF}\x{6B00}\x{6B01}\x{6B02}\x{6B03}\x{6B04}\x{6B05}\x{6B06}\x{6B07}' . + '\x{6B08}\x{6B09}\x{6B0A}\x{6B0B}\x{6B0C}\x{6B0D}\x{6B0F}\x{6B10}\x{6B11}' . + '\x{6B12}\x{6B13}\x{6B14}\x{6B15}\x{6B16}\x{6B17}\x{6B18}\x{6B19}\x{6B1A}' . + '\x{6B1C}\x{6B1D}\x{6B1E}\x{6B1F}\x{6B20}\x{6B21}\x{6B22}\x{6B23}\x{6B24}' . + '\x{6B25}\x{6B26}\x{6B27}\x{6B28}\x{6B29}\x{6B2A}\x{6B2B}\x{6B2C}\x{6B2D}' . + '\x{6B2F}\x{6B30}\x{6B31}\x{6B32}\x{6B33}\x{6B34}\x{6B36}\x{6B37}\x{6B38}' . + '\x{6B39}\x{6B3A}\x{6B3B}\x{6B3C}\x{6B3D}\x{6B3E}\x{6B3F}\x{6B41}\x{6B42}' . + '\x{6B43}\x{6B44}\x{6B45}\x{6B46}\x{6B47}\x{6B48}\x{6B49}\x{6B4A}\x{6B4B}' . + '\x{6B4C}\x{6B4D}\x{6B4E}\x{6B4F}\x{6B50}\x{6B51}\x{6B52}\x{6B53}\x{6B54}' . + '\x{6B55}\x{6B56}\x{6B59}\x{6B5A}\x{6B5B}\x{6B5C}\x{6B5E}\x{6B5F}\x{6B60}' . + '\x{6B61}\x{6B62}\x{6B63}\x{6B64}\x{6B65}\x{6B66}\x{6B67}\x{6B69}\x{6B6A}' . + '\x{6B6B}\x{6B6D}\x{6B6F}\x{6B70}\x{6B72}\x{6B73}\x{6B74}\x{6B76}\x{6B77}' . + '\x{6B78}\x{6B79}\x{6B7A}\x{6B7B}\x{6B7C}\x{6B7E}\x{6B7F}\x{6B80}\x{6B81}' . + '\x{6B82}\x{6B83}\x{6B84}\x{6B85}\x{6B86}\x{6B87}\x{6B88}\x{6B89}\x{6B8A}' . + '\x{6B8B}\x{6B8C}\x{6B8D}\x{6B8E}\x{6B8F}\x{6B90}\x{6B91}\x{6B92}\x{6B93}' . + '\x{6B94}\x{6B95}\x{6B96}\x{6B97}\x{6B98}\x{6B99}\x{6B9A}\x{6B9B}\x{6B9C}' . + '\x{6B9D}\x{6B9E}\x{6B9F}\x{6BA0}\x{6BA1}\x{6BA2}\x{6BA3}\x{6BA4}\x{6BA5}' . + '\x{6BA6}\x{6BA7}\x{6BA8}\x{6BA9}\x{6BAA}\x{6BAB}\x{6BAC}\x{6BAD}\x{6BAE}' . + '\x{6BAF}\x{6BB0}\x{6BB2}\x{6BB3}\x{6BB4}\x{6BB5}\x{6BB6}\x{6BB7}\x{6BB9}' . + '\x{6BBA}\x{6BBB}\x{6BBC}\x{6BBD}\x{6BBE}\x{6BBF}\x{6BC0}\x{6BC1}\x{6BC2}' . + '\x{6BC3}\x{6BC4}\x{6BC5}\x{6BC6}\x{6BC7}\x{6BC8}\x{6BC9}\x{6BCA}\x{6BCB}' . + '\x{6BCC}\x{6BCD}\x{6BCE}\x{6BCF}\x{6BD0}\x{6BD1}\x{6BD2}\x{6BD3}\x{6BD4}' . + '\x{6BD5}\x{6BD6}\x{6BD7}\x{6BD8}\x{6BD9}\x{6BDA}\x{6BDB}\x{6BDC}\x{6BDD}' . + '\x{6BDE}\x{6BDF}\x{6BE0}\x{6BE1}\x{6BE2}\x{6BE3}\x{6BE4}\x{6BE5}\x{6BE6}' . + '\x{6BE7}\x{6BE8}\x{6BEA}\x{6BEB}\x{6BEC}\x{6BED}\x{6BEE}\x{6BEF}\x{6BF0}' . + '\x{6BF2}\x{6BF3}\x{6BF5}\x{6BF6}\x{6BF7}\x{6BF8}\x{6BF9}\x{6BFB}\x{6BFC}' . + '\x{6BFD}\x{6BFE}\x{6BFF}\x{6C00}\x{6C01}\x{6C02}\x{6C03}\x{6C04}\x{6C05}' . + '\x{6C06}\x{6C07}\x{6C08}\x{6C09}\x{6C0B}\x{6C0C}\x{6C0D}\x{6C0E}\x{6C0F}' . + '\x{6C10}\x{6C11}\x{6C12}\x{6C13}\x{6C14}\x{6C15}\x{6C16}\x{6C18}\x{6C19}' . + '\x{6C1A}\x{6C1B}\x{6C1D}\x{6C1E}\x{6C1F}\x{6C20}\x{6C21}\x{6C22}\x{6C23}' . + '\x{6C24}\x{6C25}\x{6C26}\x{6C27}\x{6C28}\x{6C29}\x{6C2A}\x{6C2B}\x{6C2C}' . + '\x{6C2E}\x{6C2F}\x{6C30}\x{6C31}\x{6C32}\x{6C33}\x{6C34}\x{6C35}\x{6C36}' . + '\x{6C37}\x{6C38}\x{6C3A}\x{6C3B}\x{6C3D}\x{6C3E}\x{6C3F}\x{6C40}\x{6C41}' . + '\x{6C42}\x{6C43}\x{6C44}\x{6C46}\x{6C47}\x{6C48}\x{6C49}\x{6C4A}\x{6C4B}' . + '\x{6C4C}\x{6C4D}\x{6C4E}\x{6C4F}\x{6C50}\x{6C51}\x{6C52}\x{6C53}\x{6C54}' . + '\x{6C55}\x{6C56}\x{6C57}\x{6C58}\x{6C59}\x{6C5A}\x{6C5B}\x{6C5C}\x{6C5D}' . + '\x{6C5E}\x{6C5F}\x{6C60}\x{6C61}\x{6C62}\x{6C63}\x{6C64}\x{6C65}\x{6C66}' . + '\x{6C67}\x{6C68}\x{6C69}\x{6C6A}\x{6C6B}\x{6C6D}\x{6C6F}\x{6C70}\x{6C71}' . + '\x{6C72}\x{6C73}\x{6C74}\x{6C75}\x{6C76}\x{6C77}\x{6C78}\x{6C79}\x{6C7A}' . + '\x{6C7B}\x{6C7C}\x{6C7D}\x{6C7E}\x{6C7F}\x{6C80}\x{6C81}\x{6C82}\x{6C83}' . + '\x{6C84}\x{6C85}\x{6C86}\x{6C87}\x{6C88}\x{6C89}\x{6C8A}\x{6C8B}\x{6C8C}' . + '\x{6C8D}\x{6C8E}\x{6C8F}\x{6C90}\x{6C91}\x{6C92}\x{6C93}\x{6C94}\x{6C95}' . + '\x{6C96}\x{6C97}\x{6C98}\x{6C99}\x{6C9A}\x{6C9B}\x{6C9C}\x{6C9D}\x{6C9E}' . + '\x{6C9F}\x{6CA1}\x{6CA2}\x{6CA3}\x{6CA4}\x{6CA5}\x{6CA6}\x{6CA7}\x{6CA8}' . + '\x{6CA9}\x{6CAA}\x{6CAB}\x{6CAC}\x{6CAD}\x{6CAE}\x{6CAF}\x{6CB0}\x{6CB1}' . + '\x{6CB2}\x{6CB3}\x{6CB4}\x{6CB5}\x{6CB6}\x{6CB7}\x{6CB8}\x{6CB9}\x{6CBA}' . + '\x{6CBB}\x{6CBC}\x{6CBD}\x{6CBE}\x{6CBF}\x{6CC0}\x{6CC1}\x{6CC2}\x{6CC3}' . + '\x{6CC4}\x{6CC5}\x{6CC6}\x{6CC7}\x{6CC8}\x{6CC9}\x{6CCA}\x{6CCB}\x{6CCC}' . + '\x{6CCD}\x{6CCE}\x{6CCF}\x{6CD0}\x{6CD1}\x{6CD2}\x{6CD3}\x{6CD4}\x{6CD5}' . + '\x{6CD6}\x{6CD7}\x{6CD9}\x{6CDA}\x{6CDB}\x{6CDC}\x{6CDD}\x{6CDE}\x{6CDF}' . + '\x{6CE0}\x{6CE1}\x{6CE2}\x{6CE3}\x{6CE4}\x{6CE5}\x{6CE6}\x{6CE7}\x{6CE8}' . + '\x{6CE9}\x{6CEA}\x{6CEB}\x{6CEC}\x{6CED}\x{6CEE}\x{6CEF}\x{6CF0}\x{6CF1}' . + '\x{6CF2}\x{6CF3}\x{6CF5}\x{6CF6}\x{6CF7}\x{6CF8}\x{6CF9}\x{6CFA}\x{6CFB}' . + '\x{6CFC}\x{6CFD}\x{6CFE}\x{6CFF}\x{6D00}\x{6D01}\x{6D03}\x{6D04}\x{6D05}' . + '\x{6D06}\x{6D07}\x{6D08}\x{6D09}\x{6D0A}\x{6D0B}\x{6D0C}\x{6D0D}\x{6D0E}' . + '\x{6D0F}\x{6D10}\x{6D11}\x{6D12}\x{6D13}\x{6D14}\x{6D15}\x{6D16}\x{6D17}' . + '\x{6D18}\x{6D19}\x{6D1A}\x{6D1B}\x{6D1D}\x{6D1E}\x{6D1F}\x{6D20}\x{6D21}' . + '\x{6D22}\x{6D23}\x{6D25}\x{6D26}\x{6D27}\x{6D28}\x{6D29}\x{6D2A}\x{6D2B}' . + '\x{6D2C}\x{6D2D}\x{6D2E}\x{6D2F}\x{6D30}\x{6D31}\x{6D32}\x{6D33}\x{6D34}' . + '\x{6D35}\x{6D36}\x{6D37}\x{6D38}\x{6D39}\x{6D3A}\x{6D3B}\x{6D3C}\x{6D3D}' . + '\x{6D3E}\x{6D3F}\x{6D40}\x{6D41}\x{6D42}\x{6D43}\x{6D44}\x{6D45}\x{6D46}' . + '\x{6D47}\x{6D48}\x{6D49}\x{6D4A}\x{6D4B}\x{6D4C}\x{6D4D}\x{6D4E}\x{6D4F}' . + '\x{6D50}\x{6D51}\x{6D52}\x{6D53}\x{6D54}\x{6D55}\x{6D56}\x{6D57}\x{6D58}' . + '\x{6D59}\x{6D5A}\x{6D5B}\x{6D5C}\x{6D5D}\x{6D5E}\x{6D5F}\x{6D60}\x{6D61}' . + '\x{6D62}\x{6D63}\x{6D64}\x{6D65}\x{6D66}\x{6D67}\x{6D68}\x{6D69}\x{6D6A}' . + '\x{6D6B}\x{6D6C}\x{6D6D}\x{6D6E}\x{6D6F}\x{6D70}\x{6D72}\x{6D73}\x{6D74}' . + '\x{6D75}\x{6D76}\x{6D77}\x{6D78}\x{6D79}\x{6D7A}\x{6D7B}\x{6D7C}\x{6D7D}' . + '\x{6D7E}\x{6D7F}\x{6D80}\x{6D82}\x{6D83}\x{6D84}\x{6D85}\x{6D86}\x{6D87}' . + '\x{6D88}\x{6D89}\x{6D8A}\x{6D8B}\x{6D8C}\x{6D8D}\x{6D8E}\x{6D8F}\x{6D90}' . + '\x{6D91}\x{6D92}\x{6D93}\x{6D94}\x{6D95}\x{6D97}\x{6D98}\x{6D99}\x{6D9A}' . + '\x{6D9B}\x{6D9D}\x{6D9E}\x{6D9F}\x{6DA0}\x{6DA1}\x{6DA2}\x{6DA3}\x{6DA4}' . + '\x{6DA5}\x{6DA6}\x{6DA7}\x{6DA8}\x{6DA9}\x{6DAA}\x{6DAB}\x{6DAC}\x{6DAD}' . + '\x{6DAE}\x{6DAF}\x{6DB2}\x{6DB3}\x{6DB4}\x{6DB5}\x{6DB7}\x{6DB8}\x{6DB9}' . + '\x{6DBA}\x{6DBB}\x{6DBC}\x{6DBD}\x{6DBE}\x{6DBF}\x{6DC0}\x{6DC1}\x{6DC2}' . + '\x{6DC3}\x{6DC4}\x{6DC5}\x{6DC6}\x{6DC7}\x{6DC8}\x{6DC9}\x{6DCA}\x{6DCB}' . + '\x{6DCC}\x{6DCD}\x{6DCE}\x{6DCF}\x{6DD0}\x{6DD1}\x{6DD2}\x{6DD3}\x{6DD4}' . + '\x{6DD5}\x{6DD6}\x{6DD7}\x{6DD8}\x{6DD9}\x{6DDA}\x{6DDB}\x{6DDC}\x{6DDD}' . + '\x{6DDE}\x{6DDF}\x{6DE0}\x{6DE1}\x{6DE2}\x{6DE3}\x{6DE4}\x{6DE5}\x{6DE6}' . + '\x{6DE7}\x{6DE8}\x{6DE9}\x{6DEA}\x{6DEB}\x{6DEC}\x{6DED}\x{6DEE}\x{6DEF}' . + '\x{6DF0}\x{6DF1}\x{6DF2}\x{6DF3}\x{6DF4}\x{6DF5}\x{6DF6}\x{6DF7}\x{6DF8}' . + '\x{6DF9}\x{6DFA}\x{6DFB}\x{6DFC}\x{6DFD}\x{6E00}\x{6E03}\x{6E04}\x{6E05}' . + '\x{6E07}\x{6E08}\x{6E09}\x{6E0A}\x{6E0B}\x{6E0C}\x{6E0D}\x{6E0E}\x{6E0F}' . + '\x{6E10}\x{6E11}\x{6E14}\x{6E15}\x{6E16}\x{6E17}\x{6E19}\x{6E1A}\x{6E1B}' . + '\x{6E1C}\x{6E1D}\x{6E1E}\x{6E1F}\x{6E20}\x{6E21}\x{6E22}\x{6E23}\x{6E24}' . + '\x{6E25}\x{6E26}\x{6E27}\x{6E28}\x{6E29}\x{6E2B}\x{6E2C}\x{6E2D}\x{6E2E}' . + '\x{6E2F}\x{6E30}\x{6E31}\x{6E32}\x{6E33}\x{6E34}\x{6E35}\x{6E36}\x{6E37}' . + '\x{6E38}\x{6E39}\x{6E3A}\x{6E3B}\x{6E3C}\x{6E3D}\x{6E3E}\x{6E3F}\x{6E40}' . + '\x{6E41}\x{6E42}\x{6E43}\x{6E44}\x{6E45}\x{6E46}\x{6E47}\x{6E48}\x{6E49}' . + '\x{6E4A}\x{6E4B}\x{6E4D}\x{6E4E}\x{6E4F}\x{6E50}\x{6E51}\x{6E52}\x{6E53}' . + '\x{6E54}\x{6E55}\x{6E56}\x{6E57}\x{6E58}\x{6E59}\x{6E5A}\x{6E5B}\x{6E5C}' . + '\x{6E5D}\x{6E5E}\x{6E5F}\x{6E60}\x{6E61}\x{6E62}\x{6E63}\x{6E64}\x{6E65}' . + '\x{6E66}\x{6E67}\x{6E68}\x{6E69}\x{6E6A}\x{6E6B}\x{6E6D}\x{6E6E}\x{6E6F}' . + '\x{6E70}\x{6E71}\x{6E72}\x{6E73}\x{6E74}\x{6E75}\x{6E77}\x{6E78}\x{6E79}' . + '\x{6E7E}\x{6E7F}\x{6E80}\x{6E81}\x{6E82}\x{6E83}\x{6E84}\x{6E85}\x{6E86}' . + '\x{6E87}\x{6E88}\x{6E89}\x{6E8A}\x{6E8D}\x{6E8E}\x{6E8F}\x{6E90}\x{6E91}' . + '\x{6E92}\x{6E93}\x{6E94}\x{6E96}\x{6E97}\x{6E98}\x{6E99}\x{6E9A}\x{6E9B}' . + '\x{6E9C}\x{6E9D}\x{6E9E}\x{6E9F}\x{6EA0}\x{6EA1}\x{6EA2}\x{6EA3}\x{6EA4}' . + '\x{6EA5}\x{6EA6}\x{6EA7}\x{6EA8}\x{6EA9}\x{6EAA}\x{6EAB}\x{6EAC}\x{6EAD}' . + '\x{6EAE}\x{6EAF}\x{6EB0}\x{6EB1}\x{6EB2}\x{6EB3}\x{6EB4}\x{6EB5}\x{6EB6}' . + '\x{6EB7}\x{6EB8}\x{6EB9}\x{6EBA}\x{6EBB}\x{6EBC}\x{6EBD}\x{6EBE}\x{6EBF}' . + '\x{6EC0}\x{6EC1}\x{6EC2}\x{6EC3}\x{6EC4}\x{6EC5}\x{6EC6}\x{6EC7}\x{6EC8}' . + '\x{6EC9}\x{6ECA}\x{6ECB}\x{6ECC}\x{6ECD}\x{6ECE}\x{6ECF}\x{6ED0}\x{6ED1}' . + '\x{6ED2}\x{6ED3}\x{6ED4}\x{6ED5}\x{6ED6}\x{6ED7}\x{6ED8}\x{6ED9}\x{6EDA}' . + '\x{6EDC}\x{6EDE}\x{6EDF}\x{6EE0}\x{6EE1}\x{6EE2}\x{6EE4}\x{6EE5}\x{6EE6}' . + '\x{6EE7}\x{6EE8}\x{6EE9}\x{6EEA}\x{6EEB}\x{6EEC}\x{6EED}\x{6EEE}\x{6EEF}' . + '\x{6EF0}\x{6EF1}\x{6EF2}\x{6EF3}\x{6EF4}\x{6EF5}\x{6EF6}\x{6EF7}\x{6EF8}' . + '\x{6EF9}\x{6EFA}\x{6EFB}\x{6EFC}\x{6EFD}\x{6EFE}\x{6EFF}\x{6F00}\x{6F01}' . + '\x{6F02}\x{6F03}\x{6F05}\x{6F06}\x{6F07}\x{6F08}\x{6F09}\x{6F0A}\x{6F0C}' . + '\x{6F0D}\x{6F0E}\x{6F0F}\x{6F10}\x{6F11}\x{6F12}\x{6F13}\x{6F14}\x{6F15}' . + '\x{6F16}\x{6F17}\x{6F18}\x{6F19}\x{6F1A}\x{6F1B}\x{6F1C}\x{6F1D}\x{6F1E}' . + '\x{6F1F}\x{6F20}\x{6F21}\x{6F22}\x{6F23}\x{6F24}\x{6F25}\x{6F26}\x{6F27}' . + '\x{6F28}\x{6F29}\x{6F2A}\x{6F2B}\x{6F2C}\x{6F2D}\x{6F2E}\x{6F2F}\x{6F30}' . + '\x{6F31}\x{6F32}\x{6F33}\x{6F34}\x{6F35}\x{6F36}\x{6F37}\x{6F38}\x{6F39}' . + '\x{6F3A}\x{6F3B}\x{6F3C}\x{6F3D}\x{6F3E}\x{6F3F}\x{6F40}\x{6F41}\x{6F43}' . + '\x{6F44}\x{6F45}\x{6F46}\x{6F47}\x{6F49}\x{6F4B}\x{6F4C}\x{6F4D}\x{6F4E}' . + '\x{6F4F}\x{6F50}\x{6F51}\x{6F52}\x{6F53}\x{6F54}\x{6F55}\x{6F56}\x{6F57}' . + '\x{6F58}\x{6F59}\x{6F5A}\x{6F5B}\x{6F5C}\x{6F5D}\x{6F5E}\x{6F5F}\x{6F60}' . + '\x{6F61}\x{6F62}\x{6F63}\x{6F64}\x{6F65}\x{6F66}\x{6F67}\x{6F68}\x{6F69}' . + '\x{6F6A}\x{6F6B}\x{6F6C}\x{6F6D}\x{6F6E}\x{6F6F}\x{6F70}\x{6F71}\x{6F72}' . + '\x{6F73}\x{6F74}\x{6F75}\x{6F76}\x{6F77}\x{6F78}\x{6F7A}\x{6F7B}\x{6F7C}' . + '\x{6F7D}\x{6F7E}\x{6F7F}\x{6F80}\x{6F81}\x{6F82}\x{6F83}\x{6F84}\x{6F85}' . + '\x{6F86}\x{6F87}\x{6F88}\x{6F89}\x{6F8A}\x{6F8B}\x{6F8C}\x{6F8D}\x{6F8E}' . + '\x{6F8F}\x{6F90}\x{6F91}\x{6F92}\x{6F93}\x{6F94}\x{6F95}\x{6F96}\x{6F97}' . + '\x{6F99}\x{6F9B}\x{6F9C}\x{6F9D}\x{6F9E}\x{6FA0}\x{6FA1}\x{6FA2}\x{6FA3}' . + '\x{6FA4}\x{6FA5}\x{6FA6}\x{6FA7}\x{6FA8}\x{6FA9}\x{6FAA}\x{6FAB}\x{6FAC}' . + '\x{6FAD}\x{6FAE}\x{6FAF}\x{6FB0}\x{6FB1}\x{6FB2}\x{6FB3}\x{6FB4}\x{6FB5}' . + '\x{6FB6}\x{6FB8}\x{6FB9}\x{6FBA}\x{6FBB}\x{6FBC}\x{6FBD}\x{6FBE}\x{6FBF}' . + '\x{6FC0}\x{6FC1}\x{6FC2}\x{6FC3}\x{6FC4}\x{6FC6}\x{6FC7}\x{6FC8}\x{6FC9}' . + '\x{6FCA}\x{6FCB}\x{6FCC}\x{6FCD}\x{6FCE}\x{6FCF}\x{6FD1}\x{6FD2}\x{6FD4}' . + '\x{6FD5}\x{6FD6}\x{6FD7}\x{6FD8}\x{6FD9}\x{6FDA}\x{6FDB}\x{6FDC}\x{6FDD}' . + '\x{6FDE}\x{6FDF}\x{6FE0}\x{6FE1}\x{6FE2}\x{6FE3}\x{6FE4}\x{6FE5}\x{6FE6}' . + '\x{6FE7}\x{6FE8}\x{6FE9}\x{6FEA}\x{6FEB}\x{6FEC}\x{6FED}\x{6FEE}\x{6FEF}' . + '\x{6FF0}\x{6FF1}\x{6FF2}\x{6FF3}\x{6FF4}\x{6FF6}\x{6FF7}\x{6FF8}\x{6FF9}' . + '\x{6FFA}\x{6FFB}\x{6FFC}\x{6FFE}\x{6FFF}\x{7000}\x{7001}\x{7002}\x{7003}' . + '\x{7004}\x{7005}\x{7006}\x{7007}\x{7008}\x{7009}\x{700A}\x{700B}\x{700C}' . + '\x{700D}\x{700E}\x{700F}\x{7011}\x{7012}\x{7014}\x{7015}\x{7016}\x{7017}' . + '\x{7018}\x{7019}\x{701A}\x{701B}\x{701C}\x{701D}\x{701F}\x{7020}\x{7021}' . + '\x{7022}\x{7023}\x{7024}\x{7025}\x{7026}\x{7027}\x{7028}\x{7029}\x{702A}' . + '\x{702B}\x{702C}\x{702D}\x{702E}\x{702F}\x{7030}\x{7031}\x{7032}\x{7033}' . + '\x{7034}\x{7035}\x{7036}\x{7037}\x{7038}\x{7039}\x{703A}\x{703B}\x{703C}' . + '\x{703D}\x{703E}\x{703F}\x{7040}\x{7041}\x{7042}\x{7043}\x{7044}\x{7045}' . + '\x{7046}\x{7048}\x{7049}\x{704A}\x{704C}\x{704D}\x{704F}\x{7050}\x{7051}' . + '\x{7052}\x{7053}\x{7054}\x{7055}\x{7056}\x{7057}\x{7058}\x{7059}\x{705A}' . + '\x{705B}\x{705C}\x{705D}\x{705E}\x{705F}\x{7060}\x{7061}\x{7062}\x{7063}' . + '\x{7064}\x{7065}\x{7066}\x{7067}\x{7068}\x{7069}\x{706A}\x{706B}\x{706C}' . + '\x{706D}\x{706E}\x{706F}\x{7070}\x{7071}\x{7074}\x{7075}\x{7076}\x{7077}' . + '\x{7078}\x{7079}\x{707A}\x{707C}\x{707D}\x{707E}\x{707F}\x{7080}\x{7082}' . + '\x{7083}\x{7084}\x{7085}\x{7086}\x{7087}\x{7088}\x{7089}\x{708A}\x{708B}' . + '\x{708C}\x{708E}\x{708F}\x{7090}\x{7091}\x{7092}\x{7093}\x{7094}\x{7095}' . + '\x{7096}\x{7098}\x{7099}\x{709A}\x{709C}\x{709D}\x{709E}\x{709F}\x{70A0}' . + '\x{70A1}\x{70A2}\x{70A3}\x{70A4}\x{70A5}\x{70A6}\x{70A7}\x{70A8}\x{70A9}' . + '\x{70AB}\x{70AC}\x{70AD}\x{70AE}\x{70AF}\x{70B0}\x{70B1}\x{70B3}\x{70B4}' . + '\x{70B5}\x{70B7}\x{70B8}\x{70B9}\x{70BA}\x{70BB}\x{70BC}\x{70BD}\x{70BE}' . + '\x{70BF}\x{70C0}\x{70C1}\x{70C2}\x{70C3}\x{70C4}\x{70C5}\x{70C6}\x{70C7}' . + '\x{70C8}\x{70C9}\x{70CA}\x{70CB}\x{70CC}\x{70CD}\x{70CE}\x{70CF}\x{70D0}' . + '\x{70D1}\x{70D2}\x{70D3}\x{70D4}\x{70D6}\x{70D7}\x{70D8}\x{70D9}\x{70DA}' . + '\x{70DB}\x{70DC}\x{70DD}\x{70DE}\x{70DF}\x{70E0}\x{70E1}\x{70E2}\x{70E3}' . + '\x{70E4}\x{70E5}\x{70E6}\x{70E7}\x{70E8}\x{70E9}\x{70EA}\x{70EB}\x{70EC}' . + '\x{70ED}\x{70EE}\x{70EF}\x{70F0}\x{70F1}\x{70F2}\x{70F3}\x{70F4}\x{70F5}' . + '\x{70F6}\x{70F7}\x{70F8}\x{70F9}\x{70FA}\x{70FB}\x{70FC}\x{70FD}\x{70FF}' . + '\x{7100}\x{7101}\x{7102}\x{7103}\x{7104}\x{7105}\x{7106}\x{7107}\x{7109}' . + '\x{710A}\x{710B}\x{710C}\x{710D}\x{710E}\x{710F}\x{7110}\x{7111}\x{7112}' . + '\x{7113}\x{7115}\x{7116}\x{7117}\x{7118}\x{7119}\x{711A}\x{711B}\x{711C}' . + '\x{711D}\x{711E}\x{711F}\x{7120}\x{7121}\x{7122}\x{7123}\x{7125}\x{7126}' . + '\x{7127}\x{7128}\x{7129}\x{712A}\x{712B}\x{712C}\x{712D}\x{712E}\x{712F}' . + '\x{7130}\x{7131}\x{7132}\x{7135}\x{7136}\x{7137}\x{7138}\x{7139}\x{713A}' . + '\x{713B}\x{713D}\x{713E}\x{713F}\x{7140}\x{7141}\x{7142}\x{7143}\x{7144}' . + '\x{7145}\x{7146}\x{7147}\x{7148}\x{7149}\x{714A}\x{714B}\x{714C}\x{714D}' . + '\x{714E}\x{714F}\x{7150}\x{7151}\x{7152}\x{7153}\x{7154}\x{7156}\x{7158}' . + '\x{7159}\x{715A}\x{715B}\x{715C}\x{715D}\x{715E}\x{715F}\x{7160}\x{7161}' . + '\x{7162}\x{7163}\x{7164}\x{7165}\x{7166}\x{7167}\x{7168}\x{7169}\x{716A}' . + '\x{716C}\x{716E}\x{716F}\x{7170}\x{7171}\x{7172}\x{7173}\x{7174}\x{7175}' . + '\x{7176}\x{7177}\x{7178}\x{7179}\x{717A}\x{717B}\x{717C}\x{717D}\x{717E}' . + '\x{717F}\x{7180}\x{7181}\x{7182}\x{7183}\x{7184}\x{7185}\x{7186}\x{7187}' . + '\x{7188}\x{7189}\x{718A}\x{718B}\x{718C}\x{718E}\x{718F}\x{7190}\x{7191}' . + '\x{7192}\x{7193}\x{7194}\x{7195}\x{7197}\x{7198}\x{7199}\x{719A}\x{719B}' . + '\x{719C}\x{719D}\x{719E}\x{719F}\x{71A0}\x{71A1}\x{71A2}\x{71A3}\x{71A4}' . + '\x{71A5}\x{71A7}\x{71A8}\x{71A9}\x{71AA}\x{71AC}\x{71AD}\x{71AE}\x{71AF}' . + '\x{71B0}\x{71B1}\x{71B2}\x{71B3}\x{71B4}\x{71B5}\x{71B7}\x{71B8}\x{71B9}' . + '\x{71BA}\x{71BB}\x{71BC}\x{71BD}\x{71BE}\x{71BF}\x{71C0}\x{71C1}\x{71C2}' . + '\x{71C3}\x{71C4}\x{71C5}\x{71C6}\x{71C7}\x{71C8}\x{71C9}\x{71CA}\x{71CB}' . + '\x{71CD}\x{71CE}\x{71CF}\x{71D0}\x{71D1}\x{71D2}\x{71D4}\x{71D5}\x{71D6}' . + '\x{71D7}\x{71D8}\x{71D9}\x{71DA}\x{71DB}\x{71DC}\x{71DD}\x{71DE}\x{71DF}' . + '\x{71E0}\x{71E1}\x{71E2}\x{71E3}\x{71E4}\x{71E5}\x{71E6}\x{71E7}\x{71E8}' . + '\x{71E9}\x{71EA}\x{71EB}\x{71EC}\x{71ED}\x{71EE}\x{71EF}\x{71F0}\x{71F1}' . + '\x{71F2}\x{71F4}\x{71F5}\x{71F6}\x{71F7}\x{71F8}\x{71F9}\x{71FB}\x{71FC}' . + '\x{71FD}\x{71FE}\x{71FF}\x{7201}\x{7202}\x{7203}\x{7204}\x{7205}\x{7206}' . + '\x{7207}\x{7208}\x{7209}\x{720A}\x{720C}\x{720D}\x{720E}\x{720F}\x{7210}' . + '\x{7212}\x{7213}\x{7214}\x{7216}\x{7218}\x{7219}\x{721A}\x{721B}\x{721C}' . + '\x{721D}\x{721E}\x{721F}\x{7221}\x{7222}\x{7223}\x{7226}\x{7227}\x{7228}' . + '\x{7229}\x{722A}\x{722B}\x{722C}\x{722D}\x{722E}\x{7230}\x{7231}\x{7232}' . + '\x{7233}\x{7235}\x{7236}\x{7237}\x{7238}\x{7239}\x{723A}\x{723B}\x{723C}' . + '\x{723D}\x{723E}\x{723F}\x{7240}\x{7241}\x{7242}\x{7243}\x{7244}\x{7246}' . + '\x{7247}\x{7248}\x{7249}\x{724A}\x{724B}\x{724C}\x{724D}\x{724F}\x{7251}' . + '\x{7252}\x{7253}\x{7254}\x{7256}\x{7257}\x{7258}\x{7259}\x{725A}\x{725B}' . + '\x{725C}\x{725D}\x{725E}\x{725F}\x{7260}\x{7261}\x{7262}\x{7263}\x{7264}' . + '\x{7265}\x{7266}\x{7267}\x{7268}\x{7269}\x{726A}\x{726B}\x{726C}\x{726D}' . + '\x{726E}\x{726F}\x{7270}\x{7271}\x{7272}\x{7273}\x{7274}\x{7275}\x{7276}' . + '\x{7277}\x{7278}\x{7279}\x{727A}\x{727B}\x{727C}\x{727D}\x{727E}\x{727F}' . + '\x{7280}\x{7281}\x{7282}\x{7283}\x{7284}\x{7285}\x{7286}\x{7287}\x{7288}' . + '\x{7289}\x{728A}\x{728B}\x{728C}\x{728D}\x{728E}\x{728F}\x{7290}\x{7291}' . + '\x{7292}\x{7293}\x{7294}\x{7295}\x{7296}\x{7297}\x{7298}\x{7299}\x{729A}' . + '\x{729B}\x{729C}\x{729D}\x{729E}\x{729F}\x{72A1}\x{72A2}\x{72A3}\x{72A4}' . + '\x{72A5}\x{72A6}\x{72A7}\x{72A8}\x{72A9}\x{72AA}\x{72AC}\x{72AD}\x{72AE}' . + '\x{72AF}\x{72B0}\x{72B1}\x{72B2}\x{72B3}\x{72B4}\x{72B5}\x{72B6}\x{72B7}' . + '\x{72B8}\x{72B9}\x{72BA}\x{72BB}\x{72BC}\x{72BD}\x{72BF}\x{72C0}\x{72C1}' . + '\x{72C2}\x{72C3}\x{72C4}\x{72C5}\x{72C6}\x{72C7}\x{72C8}\x{72C9}\x{72CA}' . + '\x{72CB}\x{72CC}\x{72CD}\x{72CE}\x{72CF}\x{72D0}\x{72D1}\x{72D2}\x{72D3}' . + '\x{72D4}\x{72D5}\x{72D6}\x{72D7}\x{72D8}\x{72D9}\x{72DA}\x{72DB}\x{72DC}' . + '\x{72DD}\x{72DE}\x{72DF}\x{72E0}\x{72E1}\x{72E2}\x{72E3}\x{72E4}\x{72E5}' . + '\x{72E6}\x{72E7}\x{72E8}\x{72E9}\x{72EA}\x{72EB}\x{72EC}\x{72ED}\x{72EE}' . + '\x{72EF}\x{72F0}\x{72F1}\x{72F2}\x{72F3}\x{72F4}\x{72F5}\x{72F6}\x{72F7}' . + '\x{72F8}\x{72F9}\x{72FA}\x{72FB}\x{72FC}\x{72FD}\x{72FE}\x{72FF}\x{7300}' . + '\x{7301}\x{7303}\x{7304}\x{7305}\x{7306}\x{7307}\x{7308}\x{7309}\x{730A}' . + '\x{730B}\x{730C}\x{730D}\x{730E}\x{730F}\x{7311}\x{7312}\x{7313}\x{7314}' . + '\x{7315}\x{7316}\x{7317}\x{7318}\x{7319}\x{731A}\x{731B}\x{731C}\x{731D}' . + '\x{731E}\x{7320}\x{7321}\x{7322}\x{7323}\x{7324}\x{7325}\x{7326}\x{7327}' . + '\x{7329}\x{732A}\x{732B}\x{732C}\x{732D}\x{732E}\x{7330}\x{7331}\x{7332}' . + '\x{7333}\x{7334}\x{7335}\x{7336}\x{7337}\x{7338}\x{7339}\x{733A}\x{733B}' . + '\x{733C}\x{733D}\x{733E}\x{733F}\x{7340}\x{7341}\x{7342}\x{7343}\x{7344}' . + '\x{7345}\x{7346}\x{7347}\x{7348}\x{7349}\x{734A}\x{734B}\x{734C}\x{734D}' . + '\x{734E}\x{7350}\x{7351}\x{7352}\x{7354}\x{7355}\x{7356}\x{7357}\x{7358}' . + '\x{7359}\x{735A}\x{735B}\x{735C}\x{735D}\x{735E}\x{735F}\x{7360}\x{7361}' . + '\x{7362}\x{7364}\x{7365}\x{7366}\x{7367}\x{7368}\x{7369}\x{736A}\x{736B}' . + '\x{736C}\x{736D}\x{736E}\x{736F}\x{7370}\x{7371}\x{7372}\x{7373}\x{7374}' . + '\x{7375}\x{7376}\x{7377}\x{7378}\x{7379}\x{737A}\x{737B}\x{737C}\x{737D}' . + '\x{737E}\x{737F}\x{7380}\x{7381}\x{7382}\x{7383}\x{7384}\x{7385}\x{7386}' . + '\x{7387}\x{7388}\x{7389}\x{738A}\x{738B}\x{738C}\x{738D}\x{738E}\x{738F}' . + '\x{7390}\x{7391}\x{7392}\x{7393}\x{7394}\x{7395}\x{7396}\x{7397}\x{7398}' . + '\x{7399}\x{739A}\x{739B}\x{739D}\x{739E}\x{739F}\x{73A0}\x{73A1}\x{73A2}' . + '\x{73A3}\x{73A4}\x{73A5}\x{73A6}\x{73A7}\x{73A8}\x{73A9}\x{73AA}\x{73AB}' . + '\x{73AC}\x{73AD}\x{73AE}\x{73AF}\x{73B0}\x{73B1}\x{73B2}\x{73B3}\x{73B4}' . + '\x{73B5}\x{73B6}\x{73B7}\x{73B8}\x{73B9}\x{73BA}\x{73BB}\x{73BC}\x{73BD}' . + '\x{73BE}\x{73BF}\x{73C0}\x{73C2}\x{73C3}\x{73C4}\x{73C5}\x{73C6}\x{73C7}' . + '\x{73C8}\x{73C9}\x{73CA}\x{73CB}\x{73CC}\x{73CD}\x{73CE}\x{73CF}\x{73D0}' . + '\x{73D1}\x{73D2}\x{73D3}\x{73D4}\x{73D5}\x{73D6}\x{73D7}\x{73D8}\x{73D9}' . + '\x{73DA}\x{73DB}\x{73DC}\x{73DD}\x{73DE}\x{73DF}\x{73E0}\x{73E2}\x{73E3}' . + '\x{73E5}\x{73E6}\x{73E7}\x{73E8}\x{73E9}\x{73EA}\x{73EB}\x{73EC}\x{73ED}' . + '\x{73EE}\x{73EF}\x{73F0}\x{73F1}\x{73F2}\x{73F4}\x{73F5}\x{73F6}\x{73F7}' . + '\x{73F8}\x{73F9}\x{73FA}\x{73FC}\x{73FD}\x{73FE}\x{73FF}\x{7400}\x{7401}' . + '\x{7402}\x{7403}\x{7404}\x{7405}\x{7406}\x{7407}\x{7408}\x{7409}\x{740A}' . + '\x{740B}\x{740C}\x{740D}\x{740E}\x{740F}\x{7410}\x{7411}\x{7412}\x{7413}' . + '\x{7414}\x{7415}\x{7416}\x{7417}\x{7419}\x{741A}\x{741B}\x{741C}\x{741D}' . + '\x{741E}\x{741F}\x{7420}\x{7421}\x{7422}\x{7423}\x{7424}\x{7425}\x{7426}' . + '\x{7427}\x{7428}\x{7429}\x{742A}\x{742B}\x{742C}\x{742D}\x{742E}\x{742F}' . + '\x{7430}\x{7431}\x{7432}\x{7433}\x{7434}\x{7435}\x{7436}\x{7437}\x{7438}' . + '\x{743A}\x{743B}\x{743C}\x{743D}\x{743F}\x{7440}\x{7441}\x{7442}\x{7443}' . + '\x{7444}\x{7445}\x{7446}\x{7448}\x{744A}\x{744B}\x{744C}\x{744D}\x{744E}' . + '\x{744F}\x{7450}\x{7451}\x{7452}\x{7453}\x{7454}\x{7455}\x{7456}\x{7457}' . + '\x{7459}\x{745A}\x{745B}\x{745C}\x{745D}\x{745E}\x{745F}\x{7461}\x{7462}' . + '\x{7463}\x{7464}\x{7465}\x{7466}\x{7467}\x{7468}\x{7469}\x{746A}\x{746B}' . + '\x{746C}\x{746D}\x{746E}\x{746F}\x{7470}\x{7471}\x{7472}\x{7473}\x{7474}' . + '\x{7475}\x{7476}\x{7477}\x{7478}\x{7479}\x{747A}\x{747C}\x{747D}\x{747E}' . + '\x{747F}\x{7480}\x{7481}\x{7482}\x{7483}\x{7485}\x{7486}\x{7487}\x{7488}' . + '\x{7489}\x{748A}\x{748B}\x{748C}\x{748D}\x{748E}\x{748F}\x{7490}\x{7491}' . + '\x{7492}\x{7493}\x{7494}\x{7495}\x{7497}\x{7498}\x{7499}\x{749A}\x{749B}' . + '\x{749C}\x{749E}\x{749F}\x{74A0}\x{74A1}\x{74A3}\x{74A4}\x{74A5}\x{74A6}' . + '\x{74A7}\x{74A8}\x{74A9}\x{74AA}\x{74AB}\x{74AC}\x{74AD}\x{74AE}\x{74AF}' . + '\x{74B0}\x{74B1}\x{74B2}\x{74B3}\x{74B4}\x{74B5}\x{74B6}\x{74B7}\x{74B8}' . + '\x{74B9}\x{74BA}\x{74BB}\x{74BC}\x{74BD}\x{74BE}\x{74BF}\x{74C0}\x{74C1}' . + '\x{74C2}\x{74C3}\x{74C4}\x{74C5}\x{74C6}\x{74CA}\x{74CB}\x{74CD}\x{74CE}' . + '\x{74CF}\x{74D0}\x{74D1}\x{74D2}\x{74D3}\x{74D4}\x{74D5}\x{74D6}\x{74D7}' . + '\x{74D8}\x{74D9}\x{74DA}\x{74DB}\x{74DC}\x{74DD}\x{74DE}\x{74DF}\x{74E0}' . + '\x{74E1}\x{74E2}\x{74E3}\x{74E4}\x{74E5}\x{74E6}\x{74E7}\x{74E8}\x{74E9}' . + '\x{74EA}\x{74EC}\x{74ED}\x{74EE}\x{74EF}\x{74F0}\x{74F1}\x{74F2}\x{74F3}' . + '\x{74F4}\x{74F5}\x{74F6}\x{74F7}\x{74F8}\x{74F9}\x{74FA}\x{74FB}\x{74FC}' . + '\x{74FD}\x{74FE}\x{74FF}\x{7500}\x{7501}\x{7502}\x{7503}\x{7504}\x{7505}' . + '\x{7506}\x{7507}\x{7508}\x{7509}\x{750A}\x{750B}\x{750C}\x{750D}\x{750F}' . + '\x{7510}\x{7511}\x{7512}\x{7513}\x{7514}\x{7515}\x{7516}\x{7517}\x{7518}' . + '\x{7519}\x{751A}\x{751B}\x{751C}\x{751D}\x{751E}\x{751F}\x{7521}\x{7522}' . + '\x{7523}\x{7524}\x{7525}\x{7526}\x{7527}\x{7528}\x{7529}\x{752A}\x{752B}' . + '\x{752C}\x{752D}\x{752E}\x{752F}\x{7530}\x{7531}\x{7532}\x{7533}\x{7535}' . + '\x{7536}\x{7537}\x{7538}\x{7539}\x{753A}\x{753B}\x{753C}\x{753D}\x{753E}' . + '\x{753F}\x{7540}\x{7542}\x{7543}\x{7544}\x{7545}\x{7546}\x{7547}\x{7548}' . + '\x{7549}\x{754B}\x{754C}\x{754D}\x{754E}\x{754F}\x{7550}\x{7551}\x{7553}' . + '\x{7554}\x{7556}\x{7557}\x{7558}\x{7559}\x{755A}\x{755B}\x{755C}\x{755D}' . + '\x{755F}\x{7560}\x{7562}\x{7563}\x{7564}\x{7565}\x{7566}\x{7567}\x{7568}' . + '\x{7569}\x{756A}\x{756B}\x{756C}\x{756D}\x{756E}\x{756F}\x{7570}\x{7572}' . + '\x{7574}\x{7575}\x{7576}\x{7577}\x{7578}\x{7579}\x{757C}\x{757D}\x{757E}' . + '\x{757F}\x{7580}\x{7581}\x{7582}\x{7583}\x{7584}\x{7586}\x{7587}\x{7588}' . + '\x{7589}\x{758A}\x{758B}\x{758C}\x{758D}\x{758F}\x{7590}\x{7591}\x{7592}' . + '\x{7593}\x{7594}\x{7595}\x{7596}\x{7597}\x{7598}\x{7599}\x{759A}\x{759B}' . + '\x{759C}\x{759D}\x{759E}\x{759F}\x{75A0}\x{75A1}\x{75A2}\x{75A3}\x{75A4}' . + '\x{75A5}\x{75A6}\x{75A7}\x{75A8}\x{75AA}\x{75AB}\x{75AC}\x{75AD}\x{75AE}' . + '\x{75AF}\x{75B0}\x{75B1}\x{75B2}\x{75B3}\x{75B4}\x{75B5}\x{75B6}\x{75B8}' . + '\x{75B9}\x{75BA}\x{75BB}\x{75BC}\x{75BD}\x{75BE}\x{75BF}\x{75C0}\x{75C1}' . + '\x{75C2}\x{75C3}\x{75C4}\x{75C5}\x{75C6}\x{75C7}\x{75C8}\x{75C9}\x{75CA}' . + '\x{75CB}\x{75CC}\x{75CD}\x{75CE}\x{75CF}\x{75D0}\x{75D1}\x{75D2}\x{75D3}' . + '\x{75D4}\x{75D5}\x{75D6}\x{75D7}\x{75D8}\x{75D9}\x{75DA}\x{75DB}\x{75DD}' . + '\x{75DE}\x{75DF}\x{75E0}\x{75E1}\x{75E2}\x{75E3}\x{75E4}\x{75E5}\x{75E6}' . + '\x{75E7}\x{75E8}\x{75EA}\x{75EB}\x{75EC}\x{75ED}\x{75EF}\x{75F0}\x{75F1}' . + '\x{75F2}\x{75F3}\x{75F4}\x{75F5}\x{75F6}\x{75F7}\x{75F8}\x{75F9}\x{75FA}' . + '\x{75FB}\x{75FC}\x{75FD}\x{75FE}\x{75FF}\x{7600}\x{7601}\x{7602}\x{7603}' . + '\x{7604}\x{7605}\x{7606}\x{7607}\x{7608}\x{7609}\x{760A}\x{760B}\x{760C}' . + '\x{760D}\x{760E}\x{760F}\x{7610}\x{7611}\x{7612}\x{7613}\x{7614}\x{7615}' . + '\x{7616}\x{7617}\x{7618}\x{7619}\x{761A}\x{761B}\x{761C}\x{761D}\x{761E}' . + '\x{761F}\x{7620}\x{7621}\x{7622}\x{7623}\x{7624}\x{7625}\x{7626}\x{7627}' . + '\x{7628}\x{7629}\x{762A}\x{762B}\x{762D}\x{762E}\x{762F}\x{7630}\x{7631}' . + '\x{7632}\x{7633}\x{7634}\x{7635}\x{7636}\x{7637}\x{7638}\x{7639}\x{763A}' . + '\x{763B}\x{763C}\x{763D}\x{763E}\x{763F}\x{7640}\x{7641}\x{7642}\x{7643}' . + '\x{7646}\x{7647}\x{7648}\x{7649}\x{764A}\x{764B}\x{764C}\x{764D}\x{764F}' . + '\x{7650}\x{7652}\x{7653}\x{7654}\x{7656}\x{7657}\x{7658}\x{7659}\x{765A}' . + '\x{765B}\x{765C}\x{765D}\x{765E}\x{765F}\x{7660}\x{7661}\x{7662}\x{7663}' . + '\x{7664}\x{7665}\x{7666}\x{7667}\x{7668}\x{7669}\x{766A}\x{766B}\x{766C}' . + '\x{766D}\x{766E}\x{766F}\x{7670}\x{7671}\x{7672}\x{7674}\x{7675}\x{7676}' . + '\x{7677}\x{7678}\x{7679}\x{767B}\x{767C}\x{767D}\x{767E}\x{767F}\x{7680}' . + '\x{7681}\x{7682}\x{7683}\x{7684}\x{7685}\x{7686}\x{7687}\x{7688}\x{7689}' . + '\x{768A}\x{768B}\x{768C}\x{768E}\x{768F}\x{7690}\x{7691}\x{7692}\x{7693}' . + '\x{7694}\x{7695}\x{7696}\x{7697}\x{7698}\x{7699}\x{769A}\x{769B}\x{769C}' . + '\x{769D}\x{769E}\x{769F}\x{76A0}\x{76A3}\x{76A4}\x{76A6}\x{76A7}\x{76A9}' . + '\x{76AA}\x{76AB}\x{76AC}\x{76AD}\x{76AE}\x{76AF}\x{76B0}\x{76B1}\x{76B2}' . + '\x{76B4}\x{76B5}\x{76B7}\x{76B8}\x{76BA}\x{76BB}\x{76BC}\x{76BD}\x{76BE}' . + '\x{76BF}\x{76C0}\x{76C2}\x{76C3}\x{76C4}\x{76C5}\x{76C6}\x{76C7}\x{76C8}' . + '\x{76C9}\x{76CA}\x{76CD}\x{76CE}\x{76CF}\x{76D0}\x{76D1}\x{76D2}\x{76D3}' . + '\x{76D4}\x{76D5}\x{76D6}\x{76D7}\x{76D8}\x{76DA}\x{76DB}\x{76DC}\x{76DD}' . + '\x{76DE}\x{76DF}\x{76E0}\x{76E1}\x{76E2}\x{76E3}\x{76E4}\x{76E5}\x{76E6}' . + '\x{76E7}\x{76E8}\x{76E9}\x{76EA}\x{76EC}\x{76ED}\x{76EE}\x{76EF}\x{76F0}' . + '\x{76F1}\x{76F2}\x{76F3}\x{76F4}\x{76F5}\x{76F6}\x{76F7}\x{76F8}\x{76F9}' . + '\x{76FA}\x{76FB}\x{76FC}\x{76FD}\x{76FE}\x{76FF}\x{7701}\x{7703}\x{7704}' . + '\x{7705}\x{7706}\x{7707}\x{7708}\x{7709}\x{770A}\x{770B}\x{770C}\x{770D}' . + '\x{770F}\x{7710}\x{7711}\x{7712}\x{7713}\x{7714}\x{7715}\x{7716}\x{7717}' . + '\x{7718}\x{7719}\x{771A}\x{771B}\x{771C}\x{771D}\x{771E}\x{771F}\x{7720}' . + '\x{7722}\x{7723}\x{7725}\x{7726}\x{7727}\x{7728}\x{7729}\x{772A}\x{772C}' . + '\x{772D}\x{772E}\x{772F}\x{7730}\x{7731}\x{7732}\x{7733}\x{7734}\x{7735}' . + '\x{7736}\x{7737}\x{7738}\x{7739}\x{773A}\x{773B}\x{773C}\x{773D}\x{773E}' . + '\x{7740}\x{7741}\x{7743}\x{7744}\x{7745}\x{7746}\x{7747}\x{7748}\x{7749}' . + '\x{774A}\x{774B}\x{774C}\x{774D}\x{774E}\x{774F}\x{7750}\x{7751}\x{7752}' . + '\x{7753}\x{7754}\x{7755}\x{7756}\x{7757}\x{7758}\x{7759}\x{775A}\x{775B}' . + '\x{775C}\x{775D}\x{775E}\x{775F}\x{7760}\x{7761}\x{7762}\x{7763}\x{7765}' . + '\x{7766}\x{7767}\x{7768}\x{7769}\x{776A}\x{776B}\x{776C}\x{776D}\x{776E}' . + '\x{776F}\x{7770}\x{7771}\x{7772}\x{7773}\x{7774}\x{7775}\x{7776}\x{7777}' . + '\x{7778}\x{7779}\x{777A}\x{777B}\x{777C}\x{777D}\x{777E}\x{777F}\x{7780}' . + '\x{7781}\x{7782}\x{7783}\x{7784}\x{7785}\x{7786}\x{7787}\x{7788}\x{7789}' . + '\x{778A}\x{778B}\x{778C}\x{778D}\x{778E}\x{778F}\x{7790}\x{7791}\x{7792}' . + '\x{7793}\x{7794}\x{7795}\x{7797}\x{7798}\x{7799}\x{779A}\x{779B}\x{779C}' . + '\x{779D}\x{779E}\x{779F}\x{77A0}\x{77A1}\x{77A2}\x{77A3}\x{77A5}\x{77A6}' . + '\x{77A7}\x{77A8}\x{77A9}\x{77AA}\x{77AB}\x{77AC}\x{77AD}\x{77AE}\x{77AF}' . + '\x{77B0}\x{77B1}\x{77B2}\x{77B3}\x{77B4}\x{77B5}\x{77B6}\x{77B7}\x{77B8}' . + '\x{77B9}\x{77BA}\x{77BB}\x{77BC}\x{77BD}\x{77BF}\x{77C0}\x{77C2}\x{77C3}' . + '\x{77C4}\x{77C5}\x{77C6}\x{77C7}\x{77C8}\x{77C9}\x{77CA}\x{77CB}\x{77CC}' . + '\x{77CD}\x{77CE}\x{77CF}\x{77D0}\x{77D1}\x{77D3}\x{77D4}\x{77D5}\x{77D6}' . + '\x{77D7}\x{77D8}\x{77D9}\x{77DA}\x{77DB}\x{77DC}\x{77DE}\x{77DF}\x{77E0}' . + '\x{77E1}\x{77E2}\x{77E3}\x{77E5}\x{77E7}\x{77E8}\x{77E9}\x{77EA}\x{77EB}' . + '\x{77EC}\x{77ED}\x{77EE}\x{77EF}\x{77F0}\x{77F1}\x{77F2}\x{77F3}\x{77F6}' . + '\x{77F7}\x{77F8}\x{77F9}\x{77FA}\x{77FB}\x{77FC}\x{77FD}\x{77FE}\x{77FF}' . + '\x{7800}\x{7801}\x{7802}\x{7803}\x{7804}\x{7805}\x{7806}\x{7808}\x{7809}' . + '\x{780A}\x{780B}\x{780C}\x{780D}\x{780E}\x{780F}\x{7810}\x{7811}\x{7812}' . + '\x{7813}\x{7814}\x{7815}\x{7816}\x{7817}\x{7818}\x{7819}\x{781A}\x{781B}' . + '\x{781C}\x{781D}\x{781E}\x{781F}\x{7820}\x{7821}\x{7822}\x{7823}\x{7825}' . + '\x{7826}\x{7827}\x{7828}\x{7829}\x{782A}\x{782B}\x{782C}\x{782D}\x{782E}' . + '\x{782F}\x{7830}\x{7831}\x{7832}\x{7833}\x{7834}\x{7835}\x{7837}\x{7838}' . + '\x{7839}\x{783A}\x{783B}\x{783C}\x{783D}\x{783E}\x{7840}\x{7841}\x{7843}' . + '\x{7844}\x{7845}\x{7847}\x{7848}\x{7849}\x{784A}\x{784C}\x{784D}\x{784E}' . + '\x{7850}\x{7851}\x{7852}\x{7853}\x{7854}\x{7855}\x{7856}\x{7857}\x{7858}' . + '\x{7859}\x{785A}\x{785B}\x{785C}\x{785D}\x{785E}\x{785F}\x{7860}\x{7861}' . + '\x{7862}\x{7863}\x{7864}\x{7865}\x{7866}\x{7867}\x{7868}\x{7869}\x{786A}' . + '\x{786B}\x{786C}\x{786D}\x{786E}\x{786F}\x{7870}\x{7871}\x{7872}\x{7873}' . + '\x{7874}\x{7875}\x{7877}\x{7878}\x{7879}\x{787A}\x{787B}\x{787C}\x{787D}' . + '\x{787E}\x{787F}\x{7880}\x{7881}\x{7882}\x{7883}\x{7884}\x{7885}\x{7886}' . + '\x{7887}\x{7889}\x{788A}\x{788B}\x{788C}\x{788D}\x{788E}\x{788F}\x{7890}' . + '\x{7891}\x{7892}\x{7893}\x{7894}\x{7895}\x{7896}\x{7897}\x{7898}\x{7899}' . + '\x{789A}\x{789B}\x{789C}\x{789D}\x{789E}\x{789F}\x{78A0}\x{78A1}\x{78A2}' . + '\x{78A3}\x{78A4}\x{78A5}\x{78A6}\x{78A7}\x{78A8}\x{78A9}\x{78AA}\x{78AB}' . + '\x{78AC}\x{78AD}\x{78AE}\x{78AF}\x{78B0}\x{78B1}\x{78B2}\x{78B3}\x{78B4}' . + '\x{78B5}\x{78B6}\x{78B7}\x{78B8}\x{78B9}\x{78BA}\x{78BB}\x{78BC}\x{78BD}' . + '\x{78BE}\x{78BF}\x{78C0}\x{78C1}\x{78C3}\x{78C4}\x{78C5}\x{78C6}\x{78C8}' . + '\x{78C9}\x{78CA}\x{78CB}\x{78CC}\x{78CD}\x{78CE}\x{78CF}\x{78D0}\x{78D1}' . + '\x{78D3}\x{78D4}\x{78D5}\x{78D6}\x{78D7}\x{78D8}\x{78D9}\x{78DA}\x{78DB}' . + '\x{78DC}\x{78DD}\x{78DE}\x{78DF}\x{78E0}\x{78E1}\x{78E2}\x{78E3}\x{78E4}' . + '\x{78E5}\x{78E6}\x{78E7}\x{78E8}\x{78E9}\x{78EA}\x{78EB}\x{78EC}\x{78ED}' . + '\x{78EE}\x{78EF}\x{78F1}\x{78F2}\x{78F3}\x{78F4}\x{78F5}\x{78F6}\x{78F7}' . + '\x{78F9}\x{78FA}\x{78FB}\x{78FC}\x{78FD}\x{78FE}\x{78FF}\x{7901}\x{7902}' . + '\x{7903}\x{7904}\x{7905}\x{7906}\x{7907}\x{7909}\x{790A}\x{790B}\x{790C}' . + '\x{790E}\x{790F}\x{7910}\x{7911}\x{7912}\x{7913}\x{7914}\x{7916}\x{7917}' . + '\x{7918}\x{7919}\x{791A}\x{791B}\x{791C}\x{791D}\x{791E}\x{7921}\x{7922}' . + '\x{7923}\x{7924}\x{7925}\x{7926}\x{7927}\x{7928}\x{7929}\x{792A}\x{792B}' . + '\x{792C}\x{792D}\x{792E}\x{792F}\x{7930}\x{7931}\x{7933}\x{7934}\x{7935}' . + '\x{7937}\x{7938}\x{7939}\x{793A}\x{793B}\x{793C}\x{793D}\x{793E}\x{793F}' . + '\x{7940}\x{7941}\x{7942}\x{7943}\x{7944}\x{7945}\x{7946}\x{7947}\x{7948}' . + '\x{7949}\x{794A}\x{794B}\x{794C}\x{794D}\x{794E}\x{794F}\x{7950}\x{7951}' . + '\x{7952}\x{7953}\x{7954}\x{7955}\x{7956}\x{7957}\x{7958}\x{795A}\x{795B}' . + '\x{795C}\x{795D}\x{795E}\x{795F}\x{7960}\x{7961}\x{7962}\x{7963}\x{7964}' . + '\x{7965}\x{7966}\x{7967}\x{7968}\x{7969}\x{796A}\x{796B}\x{796D}\x{796F}' . + '\x{7970}\x{7971}\x{7972}\x{7973}\x{7974}\x{7977}\x{7978}\x{7979}\x{797A}' . + '\x{797B}\x{797C}\x{797D}\x{797E}\x{797F}\x{7980}\x{7981}\x{7982}\x{7983}' . + '\x{7984}\x{7985}\x{7988}\x{7989}\x{798A}\x{798B}\x{798C}\x{798D}\x{798E}' . + '\x{798F}\x{7990}\x{7991}\x{7992}\x{7993}\x{7994}\x{7995}\x{7996}\x{7997}' . + '\x{7998}\x{7999}\x{799A}\x{799B}\x{799C}\x{799F}\x{79A0}\x{79A1}\x{79A2}' . + '\x{79A3}\x{79A4}\x{79A5}\x{79A6}\x{79A7}\x{79A8}\x{79AA}\x{79AB}\x{79AC}' . + '\x{79AD}\x{79AE}\x{79AF}\x{79B0}\x{79B1}\x{79B2}\x{79B3}\x{79B4}\x{79B5}' . + '\x{79B6}\x{79B7}\x{79B8}\x{79B9}\x{79BA}\x{79BB}\x{79BD}\x{79BE}\x{79BF}' . + '\x{79C0}\x{79C1}\x{79C2}\x{79C3}\x{79C5}\x{79C6}\x{79C8}\x{79C9}\x{79CA}' . + '\x{79CB}\x{79CD}\x{79CE}\x{79CF}\x{79D0}\x{79D1}\x{79D2}\x{79D3}\x{79D5}' . + '\x{79D6}\x{79D8}\x{79D9}\x{79DA}\x{79DB}\x{79DC}\x{79DD}\x{79DE}\x{79DF}' . + '\x{79E0}\x{79E1}\x{79E2}\x{79E3}\x{79E4}\x{79E5}\x{79E6}\x{79E7}\x{79E8}' . + '\x{79E9}\x{79EA}\x{79EB}\x{79EC}\x{79ED}\x{79EE}\x{79EF}\x{79F0}\x{79F1}' . + '\x{79F2}\x{79F3}\x{79F4}\x{79F5}\x{79F6}\x{79F7}\x{79F8}\x{79F9}\x{79FA}' . + '\x{79FB}\x{79FC}\x{79FD}\x{79FE}\x{79FF}\x{7A00}\x{7A02}\x{7A03}\x{7A04}' . + '\x{7A05}\x{7A06}\x{7A08}\x{7A0A}\x{7A0B}\x{7A0C}\x{7A0D}\x{7A0E}\x{7A0F}' . + '\x{7A10}\x{7A11}\x{7A12}\x{7A13}\x{7A14}\x{7A15}\x{7A16}\x{7A17}\x{7A18}' . + '\x{7A19}\x{7A1A}\x{7A1B}\x{7A1C}\x{7A1D}\x{7A1E}\x{7A1F}\x{7A20}\x{7A21}' . + '\x{7A22}\x{7A23}\x{7A24}\x{7A25}\x{7A26}\x{7A27}\x{7A28}\x{7A29}\x{7A2A}' . + '\x{7A2B}\x{7A2D}\x{7A2E}\x{7A2F}\x{7A30}\x{7A31}\x{7A32}\x{7A33}\x{7A34}' . + '\x{7A35}\x{7A37}\x{7A39}\x{7A3B}\x{7A3C}\x{7A3D}\x{7A3E}\x{7A3F}\x{7A40}' . + '\x{7A41}\x{7A42}\x{7A43}\x{7A44}\x{7A45}\x{7A46}\x{7A47}\x{7A48}\x{7A49}' . + '\x{7A4A}\x{7A4B}\x{7A4C}\x{7A4D}\x{7A4E}\x{7A50}\x{7A51}\x{7A52}\x{7A53}' . + '\x{7A54}\x{7A55}\x{7A56}\x{7A57}\x{7A58}\x{7A59}\x{7A5A}\x{7A5B}\x{7A5C}' . + '\x{7A5D}\x{7A5E}\x{7A5F}\x{7A60}\x{7A61}\x{7A62}\x{7A65}\x{7A66}\x{7A67}' . + '\x{7A68}\x{7A69}\x{7A6B}\x{7A6C}\x{7A6D}\x{7A6E}\x{7A70}\x{7A71}\x{7A72}' . + '\x{7A73}\x{7A74}\x{7A75}\x{7A76}\x{7A77}\x{7A78}\x{7A79}\x{7A7A}\x{7A7B}' . + '\x{7A7C}\x{7A7D}\x{7A7E}\x{7A7F}\x{7A80}\x{7A81}\x{7A83}\x{7A84}\x{7A85}' . + '\x{7A86}\x{7A87}\x{7A88}\x{7A89}\x{7A8A}\x{7A8B}\x{7A8C}\x{7A8D}\x{7A8E}' . + '\x{7A8F}\x{7A90}\x{7A91}\x{7A92}\x{7A93}\x{7A94}\x{7A95}\x{7A96}\x{7A97}' . + '\x{7A98}\x{7A99}\x{7A9C}\x{7A9D}\x{7A9E}\x{7A9F}\x{7AA0}\x{7AA1}\x{7AA2}' . + '\x{7AA3}\x{7AA4}\x{7AA5}\x{7AA6}\x{7AA7}\x{7AA8}\x{7AA9}\x{7AAA}\x{7AAB}' . + '\x{7AAC}\x{7AAD}\x{7AAE}\x{7AAF}\x{7AB0}\x{7AB1}\x{7AB2}\x{7AB3}\x{7AB4}' . + '\x{7AB5}\x{7AB6}\x{7AB7}\x{7AB8}\x{7ABA}\x{7ABE}\x{7ABF}\x{7AC0}\x{7AC1}' . + '\x{7AC4}\x{7AC5}\x{7AC7}\x{7AC8}\x{7AC9}\x{7ACA}\x{7ACB}\x{7ACC}\x{7ACD}' . + '\x{7ACE}\x{7ACF}\x{7AD0}\x{7AD1}\x{7AD2}\x{7AD3}\x{7AD4}\x{7AD5}\x{7AD6}' . + '\x{7AD8}\x{7AD9}\x{7ADB}\x{7ADC}\x{7ADD}\x{7ADE}\x{7ADF}\x{7AE0}\x{7AE1}' . + '\x{7AE2}\x{7AE3}\x{7AE4}\x{7AE5}\x{7AE6}\x{7AE7}\x{7AE8}\x{7AEA}\x{7AEB}' . + '\x{7AEC}\x{7AED}\x{7AEE}\x{7AEF}\x{7AF0}\x{7AF1}\x{7AF2}\x{7AF3}\x{7AF4}' . + '\x{7AF6}\x{7AF7}\x{7AF8}\x{7AF9}\x{7AFA}\x{7AFB}\x{7AFD}\x{7AFE}\x{7AFF}' . + '\x{7B00}\x{7B01}\x{7B02}\x{7B03}\x{7B04}\x{7B05}\x{7B06}\x{7B08}\x{7B09}' . + '\x{7B0A}\x{7B0B}\x{7B0C}\x{7B0D}\x{7B0E}\x{7B0F}\x{7B10}\x{7B11}\x{7B12}' . + '\x{7B13}\x{7B14}\x{7B15}\x{7B16}\x{7B17}\x{7B18}\x{7B19}\x{7B1A}\x{7B1B}' . + '\x{7B1C}\x{7B1D}\x{7B1E}\x{7B20}\x{7B21}\x{7B22}\x{7B23}\x{7B24}\x{7B25}' . + '\x{7B26}\x{7B28}\x{7B2A}\x{7B2B}\x{7B2C}\x{7B2D}\x{7B2E}\x{7B2F}\x{7B30}' . + '\x{7B31}\x{7B32}\x{7B33}\x{7B34}\x{7B35}\x{7B36}\x{7B37}\x{7B38}\x{7B39}' . + '\x{7B3A}\x{7B3B}\x{7B3C}\x{7B3D}\x{7B3E}\x{7B3F}\x{7B40}\x{7B41}\x{7B43}' . + '\x{7B44}\x{7B45}\x{7B46}\x{7B47}\x{7B48}\x{7B49}\x{7B4A}\x{7B4B}\x{7B4C}' . + '\x{7B4D}\x{7B4E}\x{7B4F}\x{7B50}\x{7B51}\x{7B52}\x{7B54}\x{7B55}\x{7B56}' . + '\x{7B57}\x{7B58}\x{7B59}\x{7B5A}\x{7B5B}\x{7B5C}\x{7B5D}\x{7B5E}\x{7B5F}' . + '\x{7B60}\x{7B61}\x{7B62}\x{7B63}\x{7B64}\x{7B65}\x{7B66}\x{7B67}\x{7B68}' . + '\x{7B69}\x{7B6A}\x{7B6B}\x{7B6C}\x{7B6D}\x{7B6E}\x{7B70}\x{7B71}\x{7B72}' . + '\x{7B73}\x{7B74}\x{7B75}\x{7B76}\x{7B77}\x{7B78}\x{7B79}\x{7B7B}\x{7B7C}' . + '\x{7B7D}\x{7B7E}\x{7B7F}\x{7B80}\x{7B81}\x{7B82}\x{7B83}\x{7B84}\x{7B85}' . + '\x{7B87}\x{7B88}\x{7B89}\x{7B8A}\x{7B8B}\x{7B8C}\x{7B8D}\x{7B8E}\x{7B8F}' . + '\x{7B90}\x{7B91}\x{7B93}\x{7B94}\x{7B95}\x{7B96}\x{7B97}\x{7B98}\x{7B99}' . + '\x{7B9A}\x{7B9B}\x{7B9C}\x{7B9D}\x{7B9E}\x{7B9F}\x{7BA0}\x{7BA1}\x{7BA2}' . + '\x{7BA4}\x{7BA6}\x{7BA7}\x{7BA8}\x{7BA9}\x{7BAA}\x{7BAB}\x{7BAC}\x{7BAD}' . + '\x{7BAE}\x{7BAF}\x{7BB1}\x{7BB3}\x{7BB4}\x{7BB5}\x{7BB6}\x{7BB7}\x{7BB8}' . + '\x{7BB9}\x{7BBA}\x{7BBB}\x{7BBC}\x{7BBD}\x{7BBE}\x{7BBF}\x{7BC0}\x{7BC1}' . + '\x{7BC2}\x{7BC3}\x{7BC4}\x{7BC5}\x{7BC6}\x{7BC7}\x{7BC8}\x{7BC9}\x{7BCA}' . + '\x{7BCB}\x{7BCC}\x{7BCD}\x{7BCE}\x{7BD0}\x{7BD1}\x{7BD2}\x{7BD3}\x{7BD4}' . + '\x{7BD5}\x{7BD6}\x{7BD7}\x{7BD8}\x{7BD9}\x{7BDA}\x{7BDB}\x{7BDC}\x{7BDD}' . + '\x{7BDE}\x{7BDF}\x{7BE0}\x{7BE1}\x{7BE2}\x{7BE3}\x{7BE4}\x{7BE5}\x{7BE6}' . + '\x{7BE7}\x{7BE8}\x{7BE9}\x{7BEA}\x{7BEB}\x{7BEC}\x{7BED}\x{7BEE}\x{7BEF}' . + '\x{7BF0}\x{7BF1}\x{7BF2}\x{7BF3}\x{7BF4}\x{7BF5}\x{7BF6}\x{7BF7}\x{7BF8}' . + '\x{7BF9}\x{7BFB}\x{7BFC}\x{7BFD}\x{7BFE}\x{7BFF}\x{7C00}\x{7C01}\x{7C02}' . + '\x{7C03}\x{7C04}\x{7C05}\x{7C06}\x{7C07}\x{7C08}\x{7C09}\x{7C0A}\x{7C0B}' . + '\x{7C0C}\x{7C0D}\x{7C0E}\x{7C0F}\x{7C10}\x{7C11}\x{7C12}\x{7C13}\x{7C15}' . + '\x{7C16}\x{7C17}\x{7C18}\x{7C19}\x{7C1A}\x{7C1C}\x{7C1D}\x{7C1E}\x{7C1F}' . + '\x{7C20}\x{7C21}\x{7C22}\x{7C23}\x{7C24}\x{7C25}\x{7C26}\x{7C27}\x{7C28}' . + '\x{7C29}\x{7C2A}\x{7C2B}\x{7C2C}\x{7C2D}\x{7C30}\x{7C31}\x{7C32}\x{7C33}' . + '\x{7C34}\x{7C35}\x{7C36}\x{7C37}\x{7C38}\x{7C39}\x{7C3A}\x{7C3B}\x{7C3C}' . + '\x{7C3D}\x{7C3E}\x{7C3F}\x{7C40}\x{7C41}\x{7C42}\x{7C43}\x{7C44}\x{7C45}' . + '\x{7C46}\x{7C47}\x{7C48}\x{7C49}\x{7C4A}\x{7C4B}\x{7C4C}\x{7C4D}\x{7C4E}' . + '\x{7C50}\x{7C51}\x{7C53}\x{7C54}\x{7C56}\x{7C57}\x{7C58}\x{7C59}\x{7C5A}' . + '\x{7C5B}\x{7C5C}\x{7C5E}\x{7C5F}\x{7C60}\x{7C61}\x{7C62}\x{7C63}\x{7C64}' . + '\x{7C65}\x{7C66}\x{7C67}\x{7C68}\x{7C69}\x{7C6A}\x{7C6B}\x{7C6C}\x{7C6D}' . + '\x{7C6E}\x{7C6F}\x{7C70}\x{7C71}\x{7C72}\x{7C73}\x{7C74}\x{7C75}\x{7C77}' . + '\x{7C78}\x{7C79}\x{7C7A}\x{7C7B}\x{7C7C}\x{7C7D}\x{7C7E}\x{7C7F}\x{7C80}' . + '\x{7C81}\x{7C82}\x{7C84}\x{7C85}\x{7C86}\x{7C88}\x{7C89}\x{7C8A}\x{7C8B}' . + '\x{7C8C}\x{7C8D}\x{7C8E}\x{7C8F}\x{7C90}\x{7C91}\x{7C92}\x{7C94}\x{7C95}' . + '\x{7C96}\x{7C97}\x{7C98}\x{7C99}\x{7C9B}\x{7C9C}\x{7C9D}\x{7C9E}\x{7C9F}' . + '\x{7CA0}\x{7CA1}\x{7CA2}\x{7CA3}\x{7CA4}\x{7CA5}\x{7CA6}\x{7CA7}\x{7CA8}' . + '\x{7CA9}\x{7CAA}\x{7CAD}\x{7CAE}\x{7CAF}\x{7CB0}\x{7CB1}\x{7CB2}\x{7CB3}' . + '\x{7CB4}\x{7CB5}\x{7CB6}\x{7CB7}\x{7CB8}\x{7CB9}\x{7CBA}\x{7CBB}\x{7CBC}' . + '\x{7CBD}\x{7CBE}\x{7CBF}\x{7CC0}\x{7CC1}\x{7CC2}\x{7CC3}\x{7CC4}\x{7CC5}' . + '\x{7CC6}\x{7CC7}\x{7CC8}\x{7CC9}\x{7CCA}\x{7CCB}\x{7CCC}\x{7CCD}\x{7CCE}' . + '\x{7CCF}\x{7CD0}\x{7CD1}\x{7CD2}\x{7CD4}\x{7CD5}\x{7CD6}\x{7CD7}\x{7CD8}' . + '\x{7CD9}\x{7CDC}\x{7CDD}\x{7CDE}\x{7CDF}\x{7CE0}\x{7CE2}\x{7CE4}\x{7CE7}' . + '\x{7CE8}\x{7CE9}\x{7CEA}\x{7CEB}\x{7CEC}\x{7CED}\x{7CEE}\x{7CEF}\x{7CF0}' . + '\x{7CF1}\x{7CF2}\x{7CF3}\x{7CF4}\x{7CF5}\x{7CF6}\x{7CF7}\x{7CF8}\x{7CF9}' . + '\x{7CFA}\x{7CFB}\x{7CFD}\x{7CFE}\x{7D00}\x{7D01}\x{7D02}\x{7D03}\x{7D04}' . + '\x{7D05}\x{7D06}\x{7D07}\x{7D08}\x{7D09}\x{7D0A}\x{7D0B}\x{7D0C}\x{7D0D}' . + '\x{7D0E}\x{7D0F}\x{7D10}\x{7D11}\x{7D12}\x{7D13}\x{7D14}\x{7D15}\x{7D16}' . + '\x{7D17}\x{7D18}\x{7D19}\x{7D1A}\x{7D1B}\x{7D1C}\x{7D1D}\x{7D1E}\x{7D1F}' . + '\x{7D20}\x{7D21}\x{7D22}\x{7D24}\x{7D25}\x{7D26}\x{7D27}\x{7D28}\x{7D29}' . + '\x{7D2B}\x{7D2C}\x{7D2E}\x{7D2F}\x{7D30}\x{7D31}\x{7D32}\x{7D33}\x{7D34}' . + '\x{7D35}\x{7D36}\x{7D37}\x{7D38}\x{7D39}\x{7D3A}\x{7D3B}\x{7D3C}\x{7D3D}' . + '\x{7D3E}\x{7D3F}\x{7D40}\x{7D41}\x{7D42}\x{7D43}\x{7D44}\x{7D45}\x{7D46}' . + '\x{7D47}\x{7D49}\x{7D4A}\x{7D4B}\x{7D4C}\x{7D4E}\x{7D4F}\x{7D50}\x{7D51}' . + '\x{7D52}\x{7D53}\x{7D54}\x{7D55}\x{7D56}\x{7D57}\x{7D58}\x{7D59}\x{7D5B}' . + '\x{7D5C}\x{7D5D}\x{7D5E}\x{7D5F}\x{7D60}\x{7D61}\x{7D62}\x{7D63}\x{7D65}' . + '\x{7D66}\x{7D67}\x{7D68}\x{7D69}\x{7D6A}\x{7D6B}\x{7D6C}\x{7D6D}\x{7D6E}' . + '\x{7D6F}\x{7D70}\x{7D71}\x{7D72}\x{7D73}\x{7D74}\x{7D75}\x{7D76}\x{7D77}' . + '\x{7D79}\x{7D7A}\x{7D7B}\x{7D7C}\x{7D7D}\x{7D7E}\x{7D7F}\x{7D80}\x{7D81}' . + '\x{7D83}\x{7D84}\x{7D85}\x{7D86}\x{7D87}\x{7D88}\x{7D89}\x{7D8A}\x{7D8B}' . + '\x{7D8C}\x{7D8D}\x{7D8E}\x{7D8F}\x{7D90}\x{7D91}\x{7D92}\x{7D93}\x{7D94}' . + '\x{7D96}\x{7D97}\x{7D99}\x{7D9B}\x{7D9C}\x{7D9D}\x{7D9E}\x{7D9F}\x{7DA0}' . + '\x{7DA1}\x{7DA2}\x{7DA3}\x{7DA5}\x{7DA6}\x{7DA7}\x{7DA9}\x{7DAA}\x{7DAB}' . + '\x{7DAC}\x{7DAD}\x{7DAE}\x{7DAF}\x{7DB0}\x{7DB1}\x{7DB2}\x{7DB3}\x{7DB4}' . + '\x{7DB5}\x{7DB6}\x{7DB7}\x{7DB8}\x{7DB9}\x{7DBA}\x{7DBB}\x{7DBC}\x{7DBD}' . + '\x{7DBE}\x{7DBF}\x{7DC0}\x{7DC1}\x{7DC2}\x{7DC3}\x{7DC4}\x{7DC5}\x{7DC6}' . + '\x{7DC7}\x{7DC8}\x{7DC9}\x{7DCA}\x{7DCB}\x{7DCC}\x{7DCE}\x{7DCF}\x{7DD0}' . + '\x{7DD1}\x{7DD2}\x{7DD4}\x{7DD5}\x{7DD6}\x{7DD7}\x{7DD8}\x{7DD9}\x{7DDA}' . + '\x{7DDB}\x{7DDD}\x{7DDE}\x{7DDF}\x{7DE0}\x{7DE1}\x{7DE2}\x{7DE3}\x{7DE6}' . + '\x{7DE7}\x{7DE8}\x{7DE9}\x{7DEA}\x{7DEC}\x{7DED}\x{7DEE}\x{7DEF}\x{7DF0}' . + '\x{7DF1}\x{7DF2}\x{7DF3}\x{7DF4}\x{7DF5}\x{7DF6}\x{7DF7}\x{7DF8}\x{7DF9}' . + '\x{7DFA}\x{7DFB}\x{7DFC}\x{7E00}\x{7E01}\x{7E02}\x{7E03}\x{7E04}\x{7E05}' . + '\x{7E06}\x{7E07}\x{7E08}\x{7E09}\x{7E0A}\x{7E0B}\x{7E0C}\x{7E0D}\x{7E0E}' . + '\x{7E0F}\x{7E10}\x{7E11}\x{7E12}\x{7E13}\x{7E14}\x{7E15}\x{7E16}\x{7E17}' . + '\x{7E19}\x{7E1A}\x{7E1B}\x{7E1C}\x{7E1D}\x{7E1E}\x{7E1F}\x{7E20}\x{7E21}' . + '\x{7E22}\x{7E23}\x{7E24}\x{7E25}\x{7E26}\x{7E27}\x{7E28}\x{7E29}\x{7E2A}' . + '\x{7E2B}\x{7E2C}\x{7E2D}\x{7E2E}\x{7E2F}\x{7E30}\x{7E31}\x{7E32}\x{7E33}' . + '\x{7E34}\x{7E35}\x{7E36}\x{7E37}\x{7E38}\x{7E39}\x{7E3A}\x{7E3B}\x{7E3C}' . + '\x{7E3D}\x{7E3E}\x{7E3F}\x{7E40}\x{7E41}\x{7E42}\x{7E43}\x{7E44}\x{7E45}' . + '\x{7E46}\x{7E47}\x{7E48}\x{7E49}\x{7E4C}\x{7E4D}\x{7E4E}\x{7E4F}\x{7E50}' . + '\x{7E51}\x{7E52}\x{7E53}\x{7E54}\x{7E55}\x{7E56}\x{7E57}\x{7E58}\x{7E59}' . + '\x{7E5A}\x{7E5C}\x{7E5D}\x{7E5E}\x{7E5F}\x{7E60}\x{7E61}\x{7E62}\x{7E63}' . + '\x{7E65}\x{7E66}\x{7E67}\x{7E68}\x{7E69}\x{7E6A}\x{7E6B}\x{7E6C}\x{7E6D}' . + '\x{7E6E}\x{7E6F}\x{7E70}\x{7E71}\x{7E72}\x{7E73}\x{7E74}\x{7E75}\x{7E76}' . + '\x{7E77}\x{7E78}\x{7E79}\x{7E7A}\x{7E7B}\x{7E7C}\x{7E7D}\x{7E7E}\x{7E7F}' . + '\x{7E80}\x{7E81}\x{7E82}\x{7E83}\x{7E84}\x{7E85}\x{7E86}\x{7E87}\x{7E88}' . + '\x{7E89}\x{7E8A}\x{7E8B}\x{7E8C}\x{7E8D}\x{7E8E}\x{7E8F}\x{7E90}\x{7E91}' . + '\x{7E92}\x{7E93}\x{7E94}\x{7E95}\x{7E96}\x{7E97}\x{7E98}\x{7E99}\x{7E9A}' . + '\x{7E9B}\x{7E9C}\x{7E9E}\x{7E9F}\x{7EA0}\x{7EA1}\x{7EA2}\x{7EA3}\x{7EA4}' . + '\x{7EA5}\x{7EA6}\x{7EA7}\x{7EA8}\x{7EA9}\x{7EAA}\x{7EAB}\x{7EAC}\x{7EAD}' . + '\x{7EAE}\x{7EAF}\x{7EB0}\x{7EB1}\x{7EB2}\x{7EB3}\x{7EB4}\x{7EB5}\x{7EB6}' . + '\x{7EB7}\x{7EB8}\x{7EB9}\x{7EBA}\x{7EBB}\x{7EBC}\x{7EBD}\x{7EBE}\x{7EBF}' . + '\x{7EC0}\x{7EC1}\x{7EC2}\x{7EC3}\x{7EC4}\x{7EC5}\x{7EC6}\x{7EC7}\x{7EC8}' . + '\x{7EC9}\x{7ECA}\x{7ECB}\x{7ECC}\x{7ECD}\x{7ECE}\x{7ECF}\x{7ED0}\x{7ED1}' . + '\x{7ED2}\x{7ED3}\x{7ED4}\x{7ED5}\x{7ED6}\x{7ED7}\x{7ED8}\x{7ED9}\x{7EDA}' . + '\x{7EDB}\x{7EDC}\x{7EDD}\x{7EDE}\x{7EDF}\x{7EE0}\x{7EE1}\x{7EE2}\x{7EE3}' . + '\x{7EE4}\x{7EE5}\x{7EE6}\x{7EE7}\x{7EE8}\x{7EE9}\x{7EEA}\x{7EEB}\x{7EEC}' . + '\x{7EED}\x{7EEE}\x{7EEF}\x{7EF0}\x{7EF1}\x{7EF2}\x{7EF3}\x{7EF4}\x{7EF5}' . + '\x{7EF6}\x{7EF7}\x{7EF8}\x{7EF9}\x{7EFA}\x{7EFB}\x{7EFC}\x{7EFD}\x{7EFE}' . + '\x{7EFF}\x{7F00}\x{7F01}\x{7F02}\x{7F03}\x{7F04}\x{7F05}\x{7F06}\x{7F07}' . + '\x{7F08}\x{7F09}\x{7F0A}\x{7F0B}\x{7F0C}\x{7F0D}\x{7F0E}\x{7F0F}\x{7F10}' . + '\x{7F11}\x{7F12}\x{7F13}\x{7F14}\x{7F15}\x{7F16}\x{7F17}\x{7F18}\x{7F19}' . + '\x{7F1A}\x{7F1B}\x{7F1C}\x{7F1D}\x{7F1E}\x{7F1F}\x{7F20}\x{7F21}\x{7F22}' . + '\x{7F23}\x{7F24}\x{7F25}\x{7F26}\x{7F27}\x{7F28}\x{7F29}\x{7F2A}\x{7F2B}' . + '\x{7F2C}\x{7F2D}\x{7F2E}\x{7F2F}\x{7F30}\x{7F31}\x{7F32}\x{7F33}\x{7F34}' . + '\x{7F35}\x{7F36}\x{7F37}\x{7F38}\x{7F39}\x{7F3A}\x{7F3D}\x{7F3E}\x{7F3F}' . + '\x{7F40}\x{7F42}\x{7F43}\x{7F44}\x{7F45}\x{7F47}\x{7F48}\x{7F49}\x{7F4A}' . + '\x{7F4B}\x{7F4C}\x{7F4D}\x{7F4E}\x{7F4F}\x{7F50}\x{7F51}\x{7F52}\x{7F53}' . + '\x{7F54}\x{7F55}\x{7F56}\x{7F57}\x{7F58}\x{7F5A}\x{7F5B}\x{7F5C}\x{7F5D}' . + '\x{7F5E}\x{7F5F}\x{7F60}\x{7F61}\x{7F62}\x{7F63}\x{7F64}\x{7F65}\x{7F66}' . + '\x{7F67}\x{7F68}\x{7F69}\x{7F6A}\x{7F6B}\x{7F6C}\x{7F6D}\x{7F6E}\x{7F6F}' . + '\x{7F70}\x{7F71}\x{7F72}\x{7F73}\x{7F74}\x{7F75}\x{7F76}\x{7F77}\x{7F78}' . + '\x{7F79}\x{7F7A}\x{7F7B}\x{7F7C}\x{7F7D}\x{7F7E}\x{7F7F}\x{7F80}\x{7F81}' . + '\x{7F82}\x{7F83}\x{7F85}\x{7F86}\x{7F87}\x{7F88}\x{7F89}\x{7F8A}\x{7F8B}' . + '\x{7F8C}\x{7F8D}\x{7F8E}\x{7F8F}\x{7F91}\x{7F92}\x{7F93}\x{7F94}\x{7F95}' . + '\x{7F96}\x{7F98}\x{7F9A}\x{7F9B}\x{7F9C}\x{7F9D}\x{7F9E}\x{7F9F}\x{7FA0}' . + '\x{7FA1}\x{7FA2}\x{7FA3}\x{7FA4}\x{7FA5}\x{7FA6}\x{7FA7}\x{7FA8}\x{7FA9}' . + '\x{7FAA}\x{7FAB}\x{7FAC}\x{7FAD}\x{7FAE}\x{7FAF}\x{7FB0}\x{7FB1}\x{7FB2}' . + '\x{7FB3}\x{7FB5}\x{7FB6}\x{7FB7}\x{7FB8}\x{7FB9}\x{7FBA}\x{7FBB}\x{7FBC}' . + '\x{7FBD}\x{7FBE}\x{7FBF}\x{7FC0}\x{7FC1}\x{7FC2}\x{7FC3}\x{7FC4}\x{7FC5}' . + '\x{7FC6}\x{7FC7}\x{7FC8}\x{7FC9}\x{7FCA}\x{7FCB}\x{7FCC}\x{7FCD}\x{7FCE}' . + '\x{7FCF}\x{7FD0}\x{7FD1}\x{7FD2}\x{7FD3}\x{7FD4}\x{7FD5}\x{7FD7}\x{7FD8}' . + '\x{7FD9}\x{7FDA}\x{7FDB}\x{7FDC}\x{7FDE}\x{7FDF}\x{7FE0}\x{7FE1}\x{7FE2}' . + '\x{7FE3}\x{7FE5}\x{7FE6}\x{7FE7}\x{7FE8}\x{7FE9}\x{7FEA}\x{7FEB}\x{7FEC}' . + '\x{7FED}\x{7FEE}\x{7FEF}\x{7FF0}\x{7FF1}\x{7FF2}\x{7FF3}\x{7FF4}\x{7FF5}' . + '\x{7FF6}\x{7FF7}\x{7FF8}\x{7FF9}\x{7FFA}\x{7FFB}\x{7FFC}\x{7FFD}\x{7FFE}' . + '\x{7FFF}\x{8000}\x{8001}\x{8002}\x{8003}\x{8004}\x{8005}\x{8006}\x{8007}' . + '\x{8008}\x{8009}\x{800B}\x{800C}\x{800D}\x{800E}\x{800F}\x{8010}\x{8011}' . + '\x{8012}\x{8013}\x{8014}\x{8015}\x{8016}\x{8017}\x{8018}\x{8019}\x{801A}' . + '\x{801B}\x{801C}\x{801D}\x{801E}\x{801F}\x{8020}\x{8021}\x{8022}\x{8023}' . + '\x{8024}\x{8025}\x{8026}\x{8027}\x{8028}\x{8029}\x{802A}\x{802B}\x{802C}' . + '\x{802D}\x{802E}\x{8030}\x{8031}\x{8032}\x{8033}\x{8034}\x{8035}\x{8036}' . + '\x{8037}\x{8038}\x{8039}\x{803A}\x{803B}\x{803D}\x{803E}\x{803F}\x{8041}' . + '\x{8042}\x{8043}\x{8044}\x{8045}\x{8046}\x{8047}\x{8048}\x{8049}\x{804A}' . + '\x{804B}\x{804C}\x{804D}\x{804E}\x{804F}\x{8050}\x{8051}\x{8052}\x{8053}' . + '\x{8054}\x{8055}\x{8056}\x{8057}\x{8058}\x{8059}\x{805A}\x{805B}\x{805C}' . + '\x{805D}\x{805E}\x{805F}\x{8060}\x{8061}\x{8062}\x{8063}\x{8064}\x{8065}' . + '\x{8067}\x{8068}\x{8069}\x{806A}\x{806B}\x{806C}\x{806D}\x{806E}\x{806F}' . + '\x{8070}\x{8071}\x{8072}\x{8073}\x{8074}\x{8075}\x{8076}\x{8077}\x{8078}' . + '\x{8079}\x{807A}\x{807B}\x{807C}\x{807D}\x{807E}\x{807F}\x{8080}\x{8081}' . + '\x{8082}\x{8083}\x{8084}\x{8085}\x{8086}\x{8087}\x{8089}\x{808A}\x{808B}' . + '\x{808C}\x{808D}\x{808F}\x{8090}\x{8091}\x{8092}\x{8093}\x{8095}\x{8096}' . + '\x{8097}\x{8098}\x{8099}\x{809A}\x{809B}\x{809C}\x{809D}\x{809E}\x{809F}' . + '\x{80A0}\x{80A1}\x{80A2}\x{80A3}\x{80A4}\x{80A5}\x{80A9}\x{80AA}\x{80AB}' . + '\x{80AD}\x{80AE}\x{80AF}\x{80B0}\x{80B1}\x{80B2}\x{80B4}\x{80B5}\x{80B6}' . + '\x{80B7}\x{80B8}\x{80BA}\x{80BB}\x{80BC}\x{80BD}\x{80BE}\x{80BF}\x{80C0}' . + '\x{80C1}\x{80C2}\x{80C3}\x{80C4}\x{80C5}\x{80C6}\x{80C7}\x{80C8}\x{80C9}' . + '\x{80CA}\x{80CB}\x{80CC}\x{80CD}\x{80CE}\x{80CF}\x{80D0}\x{80D1}\x{80D2}' . + '\x{80D3}\x{80D4}\x{80D5}\x{80D6}\x{80D7}\x{80D8}\x{80D9}\x{80DA}\x{80DB}' . + '\x{80DC}\x{80DD}\x{80DE}\x{80E0}\x{80E1}\x{80E2}\x{80E3}\x{80E4}\x{80E5}' . + '\x{80E6}\x{80E7}\x{80E8}\x{80E9}\x{80EA}\x{80EB}\x{80EC}\x{80ED}\x{80EE}' . + '\x{80EF}\x{80F0}\x{80F1}\x{80F2}\x{80F3}\x{80F4}\x{80F5}\x{80F6}\x{80F7}' . + '\x{80F8}\x{80F9}\x{80FA}\x{80FB}\x{80FC}\x{80FD}\x{80FE}\x{80FF}\x{8100}' . + '\x{8101}\x{8102}\x{8105}\x{8106}\x{8107}\x{8108}\x{8109}\x{810A}\x{810B}' . + '\x{810C}\x{810D}\x{810E}\x{810F}\x{8110}\x{8111}\x{8112}\x{8113}\x{8114}' . + '\x{8115}\x{8116}\x{8118}\x{8119}\x{811A}\x{811B}\x{811C}\x{811D}\x{811E}' . + '\x{811F}\x{8120}\x{8121}\x{8122}\x{8123}\x{8124}\x{8125}\x{8126}\x{8127}' . + '\x{8128}\x{8129}\x{812A}\x{812B}\x{812C}\x{812D}\x{812E}\x{812F}\x{8130}' . + '\x{8131}\x{8132}\x{8136}\x{8137}\x{8138}\x{8139}\x{813A}\x{813B}\x{813C}' . + '\x{813D}\x{813E}\x{813F}\x{8140}\x{8141}\x{8142}\x{8143}\x{8144}\x{8145}' . + '\x{8146}\x{8147}\x{8148}\x{8149}\x{814A}\x{814B}\x{814C}\x{814D}\x{814E}' . + '\x{814F}\x{8150}\x{8151}\x{8152}\x{8153}\x{8154}\x{8155}\x{8156}\x{8157}' . + '\x{8158}\x{8159}\x{815A}\x{815B}\x{815C}\x{815D}\x{815E}\x{8160}\x{8161}' . + '\x{8162}\x{8163}\x{8164}\x{8165}\x{8166}\x{8167}\x{8168}\x{8169}\x{816A}' . + '\x{816B}\x{816C}\x{816D}\x{816E}\x{816F}\x{8170}\x{8171}\x{8172}\x{8173}' . + '\x{8174}\x{8175}\x{8176}\x{8177}\x{8178}\x{8179}\x{817A}\x{817B}\x{817C}' . + '\x{817D}\x{817E}\x{817F}\x{8180}\x{8181}\x{8182}\x{8183}\x{8185}\x{8186}' . + '\x{8187}\x{8188}\x{8189}\x{818A}\x{818B}\x{818C}\x{818D}\x{818E}\x{818F}' . + '\x{8191}\x{8192}\x{8193}\x{8194}\x{8195}\x{8197}\x{8198}\x{8199}\x{819A}' . + '\x{819B}\x{819C}\x{819D}\x{819E}\x{819F}\x{81A0}\x{81A1}\x{81A2}\x{81A3}' . + '\x{81A4}\x{81A5}\x{81A6}\x{81A7}\x{81A8}\x{81A9}\x{81AA}\x{81AB}\x{81AC}' . + '\x{81AD}\x{81AE}\x{81AF}\x{81B0}\x{81B1}\x{81B2}\x{81B3}\x{81B4}\x{81B5}' . + '\x{81B6}\x{81B7}\x{81B8}\x{81B9}\x{81BA}\x{81BB}\x{81BC}\x{81BD}\x{81BE}' . + '\x{81BF}\x{81C0}\x{81C1}\x{81C2}\x{81C3}\x{81C4}\x{81C5}\x{81C6}\x{81C7}' . + '\x{81C8}\x{81C9}\x{81CA}\x{81CC}\x{81CD}\x{81CE}\x{81CF}\x{81D0}\x{81D1}' . + '\x{81D2}\x{81D4}\x{81D5}\x{81D6}\x{81D7}\x{81D8}\x{81D9}\x{81DA}\x{81DB}' . + '\x{81DC}\x{81DD}\x{81DE}\x{81DF}\x{81E0}\x{81E1}\x{81E2}\x{81E3}\x{81E5}' . + '\x{81E6}\x{81E7}\x{81E8}\x{81E9}\x{81EA}\x{81EB}\x{81EC}\x{81ED}\x{81EE}' . + '\x{81F1}\x{81F2}\x{81F3}\x{81F4}\x{81F5}\x{81F6}\x{81F7}\x{81F8}\x{81F9}' . + '\x{81FA}\x{81FB}\x{81FC}\x{81FD}\x{81FE}\x{81FF}\x{8200}\x{8201}\x{8202}' . + '\x{8203}\x{8204}\x{8205}\x{8206}\x{8207}\x{8208}\x{8209}\x{820A}\x{820B}' . + '\x{820C}\x{820D}\x{820E}\x{820F}\x{8210}\x{8211}\x{8212}\x{8214}\x{8215}' . + '\x{8216}\x{8218}\x{8219}\x{821A}\x{821B}\x{821C}\x{821D}\x{821E}\x{821F}' . + '\x{8220}\x{8221}\x{8222}\x{8223}\x{8225}\x{8226}\x{8227}\x{8228}\x{8229}' . + '\x{822A}\x{822B}\x{822C}\x{822D}\x{822F}\x{8230}\x{8231}\x{8232}\x{8233}' . + '\x{8234}\x{8235}\x{8236}\x{8237}\x{8238}\x{8239}\x{823A}\x{823B}\x{823C}' . + '\x{823D}\x{823E}\x{823F}\x{8240}\x{8242}\x{8243}\x{8244}\x{8245}\x{8246}' . + '\x{8247}\x{8248}\x{8249}\x{824A}\x{824B}\x{824C}\x{824D}\x{824E}\x{824F}' . + '\x{8250}\x{8251}\x{8252}\x{8253}\x{8254}\x{8255}\x{8256}\x{8257}\x{8258}' . + '\x{8259}\x{825A}\x{825B}\x{825C}\x{825D}\x{825E}\x{825F}\x{8260}\x{8261}' . + '\x{8263}\x{8264}\x{8266}\x{8267}\x{8268}\x{8269}\x{826A}\x{826B}\x{826C}' . + '\x{826D}\x{826E}\x{826F}\x{8270}\x{8271}\x{8272}\x{8273}\x{8274}\x{8275}' . + '\x{8276}\x{8277}\x{8278}\x{8279}\x{827A}\x{827B}\x{827C}\x{827D}\x{827E}' . + '\x{827F}\x{8280}\x{8281}\x{8282}\x{8283}\x{8284}\x{8285}\x{8286}\x{8287}' . + '\x{8288}\x{8289}\x{828A}\x{828B}\x{828D}\x{828E}\x{828F}\x{8290}\x{8291}' . + '\x{8292}\x{8293}\x{8294}\x{8295}\x{8296}\x{8297}\x{8298}\x{8299}\x{829A}' . + '\x{829B}\x{829C}\x{829D}\x{829E}\x{829F}\x{82A0}\x{82A1}\x{82A2}\x{82A3}' . + '\x{82A4}\x{82A5}\x{82A6}\x{82A7}\x{82A8}\x{82A9}\x{82AA}\x{82AB}\x{82AC}' . + '\x{82AD}\x{82AE}\x{82AF}\x{82B0}\x{82B1}\x{82B3}\x{82B4}\x{82B5}\x{82B6}' . + '\x{82B7}\x{82B8}\x{82B9}\x{82BA}\x{82BB}\x{82BC}\x{82BD}\x{82BE}\x{82BF}' . + '\x{82C0}\x{82C1}\x{82C2}\x{82C3}\x{82C4}\x{82C5}\x{82C6}\x{82C7}\x{82C8}' . + '\x{82C9}\x{82CA}\x{82CB}\x{82CC}\x{82CD}\x{82CE}\x{82CF}\x{82D0}\x{82D1}' . + '\x{82D2}\x{82D3}\x{82D4}\x{82D5}\x{82D6}\x{82D7}\x{82D8}\x{82D9}\x{82DA}' . + '\x{82DB}\x{82DC}\x{82DD}\x{82DE}\x{82DF}\x{82E0}\x{82E1}\x{82E3}\x{82E4}' . + '\x{82E5}\x{82E6}\x{82E7}\x{82E8}\x{82E9}\x{82EA}\x{82EB}\x{82EC}\x{82ED}' . + '\x{82EE}\x{82EF}\x{82F0}\x{82F1}\x{82F2}\x{82F3}\x{82F4}\x{82F5}\x{82F6}' . + '\x{82F7}\x{82F8}\x{82F9}\x{82FA}\x{82FB}\x{82FD}\x{82FE}\x{82FF}\x{8300}' . + '\x{8301}\x{8302}\x{8303}\x{8304}\x{8305}\x{8306}\x{8307}\x{8308}\x{8309}' . + '\x{830B}\x{830C}\x{830D}\x{830E}\x{830F}\x{8311}\x{8312}\x{8313}\x{8314}' . + '\x{8315}\x{8316}\x{8317}\x{8318}\x{8319}\x{831A}\x{831B}\x{831C}\x{831D}' . + '\x{831E}\x{831F}\x{8320}\x{8321}\x{8322}\x{8323}\x{8324}\x{8325}\x{8326}' . + '\x{8327}\x{8328}\x{8329}\x{832A}\x{832B}\x{832C}\x{832D}\x{832E}\x{832F}' . + '\x{8331}\x{8332}\x{8333}\x{8334}\x{8335}\x{8336}\x{8337}\x{8338}\x{8339}' . + '\x{833A}\x{833B}\x{833C}\x{833D}\x{833E}\x{833F}\x{8340}\x{8341}\x{8342}' . + '\x{8343}\x{8344}\x{8345}\x{8346}\x{8347}\x{8348}\x{8349}\x{834A}\x{834B}' . + '\x{834C}\x{834D}\x{834E}\x{834F}\x{8350}\x{8351}\x{8352}\x{8353}\x{8354}' . + '\x{8356}\x{8357}\x{8358}\x{8359}\x{835A}\x{835B}\x{835C}\x{835D}\x{835E}' . + '\x{835F}\x{8360}\x{8361}\x{8362}\x{8363}\x{8364}\x{8365}\x{8366}\x{8367}' . + '\x{8368}\x{8369}\x{836A}\x{836B}\x{836C}\x{836D}\x{836E}\x{836F}\x{8370}' . + '\x{8371}\x{8372}\x{8373}\x{8374}\x{8375}\x{8376}\x{8377}\x{8378}\x{8379}' . + '\x{837A}\x{837B}\x{837C}\x{837D}\x{837E}\x{837F}\x{8380}\x{8381}\x{8382}' . + '\x{8383}\x{8384}\x{8385}\x{8386}\x{8387}\x{8388}\x{8389}\x{838A}\x{838B}' . + '\x{838C}\x{838D}\x{838E}\x{838F}\x{8390}\x{8391}\x{8392}\x{8393}\x{8394}' . + '\x{8395}\x{8396}\x{8397}\x{8398}\x{8399}\x{839A}\x{839B}\x{839C}\x{839D}' . + '\x{839E}\x{83A0}\x{83A1}\x{83A2}\x{83A3}\x{83A4}\x{83A5}\x{83A6}\x{83A7}' . + '\x{83A8}\x{83A9}\x{83AA}\x{83AB}\x{83AC}\x{83AD}\x{83AE}\x{83AF}\x{83B0}' . + '\x{83B1}\x{83B2}\x{83B3}\x{83B4}\x{83B6}\x{83B7}\x{83B8}\x{83B9}\x{83BA}' . + '\x{83BB}\x{83BC}\x{83BD}\x{83BF}\x{83C0}\x{83C1}\x{83C2}\x{83C3}\x{83C4}' . + '\x{83C5}\x{83C6}\x{83C7}\x{83C8}\x{83C9}\x{83CA}\x{83CB}\x{83CC}\x{83CD}' . + '\x{83CE}\x{83CF}\x{83D0}\x{83D1}\x{83D2}\x{83D3}\x{83D4}\x{83D5}\x{83D6}' . + '\x{83D7}\x{83D8}\x{83D9}\x{83DA}\x{83DB}\x{83DC}\x{83DD}\x{83DE}\x{83DF}' . + '\x{83E0}\x{83E1}\x{83E2}\x{83E3}\x{83E4}\x{83E5}\x{83E7}\x{83E8}\x{83E9}' . + '\x{83EA}\x{83EB}\x{83EC}\x{83EE}\x{83EF}\x{83F0}\x{83F1}\x{83F2}\x{83F3}' . + '\x{83F4}\x{83F5}\x{83F6}\x{83F7}\x{83F8}\x{83F9}\x{83FA}\x{83FB}\x{83FC}' . + '\x{83FD}\x{83FE}\x{83FF}\x{8400}\x{8401}\x{8402}\x{8403}\x{8404}\x{8405}' . + '\x{8406}\x{8407}\x{8408}\x{8409}\x{840A}\x{840B}\x{840C}\x{840D}\x{840E}' . + '\x{840F}\x{8410}\x{8411}\x{8412}\x{8413}\x{8415}\x{8418}\x{8419}\x{841A}' . + '\x{841B}\x{841C}\x{841D}\x{841E}\x{8421}\x{8422}\x{8423}\x{8424}\x{8425}' . + '\x{8426}\x{8427}\x{8428}\x{8429}\x{842A}\x{842B}\x{842C}\x{842D}\x{842E}' . + '\x{842F}\x{8430}\x{8431}\x{8432}\x{8433}\x{8434}\x{8435}\x{8436}\x{8437}' . + '\x{8438}\x{8439}\x{843A}\x{843B}\x{843C}\x{843D}\x{843E}\x{843F}\x{8440}' . + '\x{8441}\x{8442}\x{8443}\x{8444}\x{8445}\x{8446}\x{8447}\x{8448}\x{8449}' . + '\x{844A}\x{844B}\x{844C}\x{844D}\x{844E}\x{844F}\x{8450}\x{8451}\x{8452}' . + '\x{8453}\x{8454}\x{8455}\x{8456}\x{8457}\x{8459}\x{845A}\x{845B}\x{845C}' . + '\x{845D}\x{845E}\x{845F}\x{8460}\x{8461}\x{8462}\x{8463}\x{8464}\x{8465}' . + '\x{8466}\x{8467}\x{8468}\x{8469}\x{846A}\x{846B}\x{846C}\x{846D}\x{846E}' . + '\x{846F}\x{8470}\x{8471}\x{8472}\x{8473}\x{8474}\x{8475}\x{8476}\x{8477}' . + '\x{8478}\x{8479}\x{847A}\x{847B}\x{847C}\x{847D}\x{847E}\x{847F}\x{8480}' . + '\x{8481}\x{8482}\x{8484}\x{8485}\x{8486}\x{8487}\x{8488}\x{8489}\x{848A}' . + '\x{848B}\x{848C}\x{848D}\x{848E}\x{848F}\x{8490}\x{8491}\x{8492}\x{8493}' . + '\x{8494}\x{8496}\x{8497}\x{8498}\x{8499}\x{849A}\x{849B}\x{849C}\x{849D}' . + '\x{849E}\x{849F}\x{84A0}\x{84A1}\x{84A2}\x{84A3}\x{84A4}\x{84A5}\x{84A6}' . + '\x{84A7}\x{84A8}\x{84A9}\x{84AA}\x{84AB}\x{84AC}\x{84AE}\x{84AF}\x{84B0}' . + '\x{84B1}\x{84B2}\x{84B3}\x{84B4}\x{84B5}\x{84B6}\x{84B8}\x{84B9}\x{84BA}' . + '\x{84BB}\x{84BC}\x{84BD}\x{84BE}\x{84BF}\x{84C0}\x{84C1}\x{84C2}\x{84C4}' . + '\x{84C5}\x{84C6}\x{84C7}\x{84C8}\x{84C9}\x{84CA}\x{84CB}\x{84CC}\x{84CD}' . + '\x{84CE}\x{84CF}\x{84D0}\x{84D1}\x{84D2}\x{84D3}\x{84D4}\x{84D5}\x{84D6}' . + '\x{84D7}\x{84D8}\x{84D9}\x{84DB}\x{84DC}\x{84DD}\x{84DE}\x{84DF}\x{84E0}' . + '\x{84E1}\x{84E2}\x{84E3}\x{84E4}\x{84E5}\x{84E6}\x{84E7}\x{84E8}\x{84E9}' . + '\x{84EA}\x{84EB}\x{84EC}\x{84EE}\x{84EF}\x{84F0}\x{84F1}\x{84F2}\x{84F3}' . + '\x{84F4}\x{84F5}\x{84F6}\x{84F7}\x{84F8}\x{84F9}\x{84FA}\x{84FB}\x{84FC}' . + '\x{84FD}\x{84FE}\x{84FF}\x{8500}\x{8501}\x{8502}\x{8503}\x{8504}\x{8506}' . + '\x{8507}\x{8508}\x{8509}\x{850A}\x{850B}\x{850C}\x{850D}\x{850E}\x{850F}' . + '\x{8511}\x{8512}\x{8513}\x{8514}\x{8515}\x{8516}\x{8517}\x{8518}\x{8519}' . + '\x{851A}\x{851B}\x{851C}\x{851D}\x{851E}\x{851F}\x{8520}\x{8521}\x{8522}' . + '\x{8523}\x{8524}\x{8525}\x{8526}\x{8527}\x{8528}\x{8529}\x{852A}\x{852B}' . + '\x{852C}\x{852D}\x{852E}\x{852F}\x{8530}\x{8531}\x{8534}\x{8535}\x{8536}' . + '\x{8537}\x{8538}\x{8539}\x{853A}\x{853B}\x{853C}\x{853D}\x{853E}\x{853F}' . + '\x{8540}\x{8541}\x{8542}\x{8543}\x{8544}\x{8545}\x{8546}\x{8547}\x{8548}' . + '\x{8549}\x{854A}\x{854B}\x{854D}\x{854E}\x{854F}\x{8551}\x{8552}\x{8553}' . + '\x{8554}\x{8555}\x{8556}\x{8557}\x{8558}\x{8559}\x{855A}\x{855B}\x{855C}' . + '\x{855D}\x{855E}\x{855F}\x{8560}\x{8561}\x{8562}\x{8563}\x{8564}\x{8565}' . + '\x{8566}\x{8567}\x{8568}\x{8569}\x{856A}\x{856B}\x{856C}\x{856D}\x{856E}' . + '\x{856F}\x{8570}\x{8571}\x{8572}\x{8573}\x{8574}\x{8575}\x{8576}\x{8577}' . + '\x{8578}\x{8579}\x{857A}\x{857B}\x{857C}\x{857D}\x{857E}\x{8580}\x{8581}' . + '\x{8582}\x{8583}\x{8584}\x{8585}\x{8586}\x{8587}\x{8588}\x{8589}\x{858A}' . + '\x{858B}\x{858C}\x{858D}\x{858E}\x{858F}\x{8590}\x{8591}\x{8592}\x{8594}' . + '\x{8595}\x{8596}\x{8598}\x{8599}\x{859A}\x{859B}\x{859C}\x{859D}\x{859E}' . + '\x{859F}\x{85A0}\x{85A1}\x{85A2}\x{85A3}\x{85A4}\x{85A5}\x{85A6}\x{85A7}' . + '\x{85A8}\x{85A9}\x{85AA}\x{85AB}\x{85AC}\x{85AD}\x{85AE}\x{85AF}\x{85B0}' . + '\x{85B1}\x{85B3}\x{85B4}\x{85B5}\x{85B6}\x{85B7}\x{85B8}\x{85B9}\x{85BA}' . + '\x{85BC}\x{85BD}\x{85BE}\x{85BF}\x{85C0}\x{85C1}\x{85C2}\x{85C3}\x{85C4}' . + '\x{85C5}\x{85C6}\x{85C7}\x{85C8}\x{85C9}\x{85CA}\x{85CB}\x{85CD}\x{85CE}' . + '\x{85CF}\x{85D0}\x{85D1}\x{85D2}\x{85D3}\x{85D4}\x{85D5}\x{85D6}\x{85D7}' . + '\x{85D8}\x{85D9}\x{85DA}\x{85DB}\x{85DC}\x{85DD}\x{85DE}\x{85DF}\x{85E0}' . + '\x{85E1}\x{85E2}\x{85E3}\x{85E4}\x{85E5}\x{85E6}\x{85E7}\x{85E8}\x{85E9}' . + '\x{85EA}\x{85EB}\x{85EC}\x{85ED}\x{85EF}\x{85F0}\x{85F1}\x{85F2}\x{85F4}' . + '\x{85F5}\x{85F6}\x{85F7}\x{85F8}\x{85F9}\x{85FA}\x{85FB}\x{85FD}\x{85FE}' . + '\x{85FF}\x{8600}\x{8601}\x{8602}\x{8604}\x{8605}\x{8606}\x{8607}\x{8608}' . + '\x{8609}\x{860A}\x{860B}\x{860C}\x{860F}\x{8611}\x{8612}\x{8613}\x{8614}' . + '\x{8616}\x{8617}\x{8618}\x{8619}\x{861A}\x{861B}\x{861C}\x{861E}\x{861F}' . + '\x{8620}\x{8621}\x{8622}\x{8623}\x{8624}\x{8625}\x{8626}\x{8627}\x{8628}' . + '\x{8629}\x{862A}\x{862B}\x{862C}\x{862D}\x{862E}\x{862F}\x{8630}\x{8631}' . + '\x{8632}\x{8633}\x{8634}\x{8635}\x{8636}\x{8638}\x{8639}\x{863A}\x{863B}' . + '\x{863C}\x{863D}\x{863E}\x{863F}\x{8640}\x{8641}\x{8642}\x{8643}\x{8644}' . + '\x{8645}\x{8646}\x{8647}\x{8648}\x{8649}\x{864A}\x{864B}\x{864C}\x{864D}' . + '\x{864E}\x{864F}\x{8650}\x{8651}\x{8652}\x{8653}\x{8654}\x{8655}\x{8656}' . + '\x{8658}\x{8659}\x{865A}\x{865B}\x{865C}\x{865D}\x{865E}\x{865F}\x{8660}' . + '\x{8661}\x{8662}\x{8663}\x{8664}\x{8665}\x{8666}\x{8667}\x{8668}\x{8669}' . + '\x{866A}\x{866B}\x{866C}\x{866D}\x{866E}\x{866F}\x{8670}\x{8671}\x{8672}' . + '\x{8673}\x{8674}\x{8676}\x{8677}\x{8678}\x{8679}\x{867A}\x{867B}\x{867C}' . + '\x{867D}\x{867E}\x{867F}\x{8680}\x{8681}\x{8682}\x{8683}\x{8684}\x{8685}' . + '\x{8686}\x{8687}\x{8688}\x{868A}\x{868B}\x{868C}\x{868D}\x{868E}\x{868F}' . + '\x{8690}\x{8691}\x{8693}\x{8694}\x{8695}\x{8696}\x{8697}\x{8698}\x{8699}' . + '\x{869A}\x{869B}\x{869C}\x{869D}\x{869E}\x{869F}\x{86A1}\x{86A2}\x{86A3}' . + '\x{86A4}\x{86A5}\x{86A7}\x{86A8}\x{86A9}\x{86AA}\x{86AB}\x{86AC}\x{86AD}' . + '\x{86AE}\x{86AF}\x{86B0}\x{86B1}\x{86B2}\x{86B3}\x{86B4}\x{86B5}\x{86B6}' . + '\x{86B7}\x{86B8}\x{86B9}\x{86BA}\x{86BB}\x{86BC}\x{86BD}\x{86BE}\x{86BF}' . + '\x{86C0}\x{86C1}\x{86C2}\x{86C3}\x{86C4}\x{86C5}\x{86C6}\x{86C7}\x{86C8}' . + '\x{86C9}\x{86CA}\x{86CB}\x{86CC}\x{86CE}\x{86CF}\x{86D0}\x{86D1}\x{86D2}' . + '\x{86D3}\x{86D4}\x{86D6}\x{86D7}\x{86D8}\x{86D9}\x{86DA}\x{86DB}\x{86DC}' . + '\x{86DD}\x{86DE}\x{86DF}\x{86E1}\x{86E2}\x{86E3}\x{86E4}\x{86E5}\x{86E6}' . + '\x{86E8}\x{86E9}\x{86EA}\x{86EB}\x{86EC}\x{86ED}\x{86EE}\x{86EF}\x{86F0}' . + '\x{86F1}\x{86F2}\x{86F3}\x{86F4}\x{86F5}\x{86F6}\x{86F7}\x{86F8}\x{86F9}' . + '\x{86FA}\x{86FB}\x{86FC}\x{86FE}\x{86FF}\x{8700}\x{8701}\x{8702}\x{8703}' . + '\x{8704}\x{8705}\x{8706}\x{8707}\x{8708}\x{8709}\x{870A}\x{870B}\x{870C}' . + '\x{870D}\x{870E}\x{870F}\x{8710}\x{8711}\x{8712}\x{8713}\x{8714}\x{8715}' . + '\x{8716}\x{8717}\x{8718}\x{8719}\x{871A}\x{871B}\x{871C}\x{871E}\x{871F}' . + '\x{8720}\x{8721}\x{8722}\x{8723}\x{8724}\x{8725}\x{8726}\x{8727}\x{8728}' . + '\x{8729}\x{872A}\x{872B}\x{872C}\x{872D}\x{872E}\x{8730}\x{8731}\x{8732}' . + '\x{8733}\x{8734}\x{8735}\x{8736}\x{8737}\x{8738}\x{8739}\x{873A}\x{873B}' . + '\x{873C}\x{873E}\x{873F}\x{8740}\x{8741}\x{8742}\x{8743}\x{8744}\x{8746}' . + '\x{8747}\x{8748}\x{8749}\x{874A}\x{874C}\x{874D}\x{874E}\x{874F}\x{8750}' . + '\x{8751}\x{8752}\x{8753}\x{8754}\x{8755}\x{8756}\x{8757}\x{8758}\x{8759}' . + '\x{875A}\x{875B}\x{875C}\x{875D}\x{875E}\x{875F}\x{8760}\x{8761}\x{8762}' . + '\x{8763}\x{8764}\x{8765}\x{8766}\x{8767}\x{8768}\x{8769}\x{876A}\x{876B}' . + '\x{876C}\x{876D}\x{876E}\x{876F}\x{8770}\x{8772}\x{8773}\x{8774}\x{8775}' . + '\x{8776}\x{8777}\x{8778}\x{8779}\x{877A}\x{877B}\x{877C}\x{877D}\x{877E}' . + '\x{8780}\x{8781}\x{8782}\x{8783}\x{8784}\x{8785}\x{8786}\x{8787}\x{8788}' . + '\x{8789}\x{878A}\x{878B}\x{878C}\x{878D}\x{878F}\x{8790}\x{8791}\x{8792}' . + '\x{8793}\x{8794}\x{8795}\x{8796}\x{8797}\x{8798}\x{879A}\x{879B}\x{879C}' . + '\x{879D}\x{879E}\x{879F}\x{87A0}\x{87A1}\x{87A2}\x{87A3}\x{87A4}\x{87A5}' . + '\x{87A6}\x{87A7}\x{87A8}\x{87A9}\x{87AA}\x{87AB}\x{87AC}\x{87AD}\x{87AE}' . + '\x{87AF}\x{87B0}\x{87B1}\x{87B2}\x{87B3}\x{87B4}\x{87B5}\x{87B6}\x{87B7}' . + '\x{87B8}\x{87B9}\x{87BA}\x{87BB}\x{87BC}\x{87BD}\x{87BE}\x{87BF}\x{87C0}' . + '\x{87C1}\x{87C2}\x{87C3}\x{87C4}\x{87C5}\x{87C6}\x{87C7}\x{87C8}\x{87C9}' . + '\x{87CA}\x{87CB}\x{87CC}\x{87CD}\x{87CE}\x{87CF}\x{87D0}\x{87D1}\x{87D2}' . + '\x{87D3}\x{87D4}\x{87D5}\x{87D6}\x{87D7}\x{87D8}\x{87D9}\x{87DB}\x{87DC}' . + '\x{87DD}\x{87DE}\x{87DF}\x{87E0}\x{87E1}\x{87E2}\x{87E3}\x{87E4}\x{87E5}' . + '\x{87E6}\x{87E7}\x{87E8}\x{87E9}\x{87EA}\x{87EB}\x{87EC}\x{87ED}\x{87EE}' . + '\x{87EF}\x{87F1}\x{87F2}\x{87F3}\x{87F4}\x{87F5}\x{87F6}\x{87F7}\x{87F8}' . + '\x{87F9}\x{87FA}\x{87FB}\x{87FC}\x{87FD}\x{87FE}\x{87FF}\x{8800}\x{8801}' . + '\x{8802}\x{8803}\x{8804}\x{8805}\x{8806}\x{8808}\x{8809}\x{880A}\x{880B}' . + '\x{880C}\x{880D}\x{880E}\x{880F}\x{8810}\x{8811}\x{8813}\x{8814}\x{8815}' . + '\x{8816}\x{8817}\x{8818}\x{8819}\x{881A}\x{881B}\x{881C}\x{881D}\x{881E}' . + '\x{881F}\x{8820}\x{8821}\x{8822}\x{8823}\x{8824}\x{8825}\x{8826}\x{8827}' . + '\x{8828}\x{8829}\x{882A}\x{882B}\x{882C}\x{882E}\x{882F}\x{8830}\x{8831}' . + '\x{8832}\x{8833}\x{8834}\x{8835}\x{8836}\x{8837}\x{8838}\x{8839}\x{883B}' . + '\x{883C}\x{883D}\x{883E}\x{883F}\x{8840}\x{8841}\x{8842}\x{8843}\x{8844}' . + '\x{8845}\x{8846}\x{8848}\x{8849}\x{884A}\x{884B}\x{884C}\x{884D}\x{884E}' . + '\x{884F}\x{8850}\x{8851}\x{8852}\x{8853}\x{8854}\x{8855}\x{8856}\x{8857}' . + '\x{8859}\x{885A}\x{885B}\x{885D}\x{885E}\x{8860}\x{8861}\x{8862}\x{8863}' . + '\x{8864}\x{8865}\x{8866}\x{8867}\x{8868}\x{8869}\x{886A}\x{886B}\x{886C}' . + '\x{886D}\x{886E}\x{886F}\x{8870}\x{8871}\x{8872}\x{8873}\x{8874}\x{8875}' . + '\x{8876}\x{8877}\x{8878}\x{8879}\x{887B}\x{887C}\x{887D}\x{887E}\x{887F}' . + '\x{8880}\x{8881}\x{8882}\x{8883}\x{8884}\x{8885}\x{8886}\x{8887}\x{8888}' . + '\x{8889}\x{888A}\x{888B}\x{888C}\x{888D}\x{888E}\x{888F}\x{8890}\x{8891}' . + '\x{8892}\x{8893}\x{8894}\x{8895}\x{8896}\x{8897}\x{8898}\x{8899}\x{889A}' . + '\x{889B}\x{889C}\x{889D}\x{889E}\x{889F}\x{88A0}\x{88A1}\x{88A2}\x{88A3}' . + '\x{88A4}\x{88A5}\x{88A6}\x{88A7}\x{88A8}\x{88A9}\x{88AA}\x{88AB}\x{88AC}' . + '\x{88AD}\x{88AE}\x{88AF}\x{88B0}\x{88B1}\x{88B2}\x{88B3}\x{88B4}\x{88B6}' . + '\x{88B7}\x{88B8}\x{88B9}\x{88BA}\x{88BB}\x{88BC}\x{88BD}\x{88BE}\x{88BF}' . + '\x{88C0}\x{88C1}\x{88C2}\x{88C3}\x{88C4}\x{88C5}\x{88C6}\x{88C7}\x{88C8}' . + '\x{88C9}\x{88CA}\x{88CB}\x{88CC}\x{88CD}\x{88CE}\x{88CF}\x{88D0}\x{88D1}' . + '\x{88D2}\x{88D3}\x{88D4}\x{88D5}\x{88D6}\x{88D7}\x{88D8}\x{88D9}\x{88DA}' . + '\x{88DB}\x{88DC}\x{88DD}\x{88DE}\x{88DF}\x{88E0}\x{88E1}\x{88E2}\x{88E3}' . + '\x{88E4}\x{88E5}\x{88E7}\x{88E8}\x{88EA}\x{88EB}\x{88EC}\x{88EE}\x{88EF}' . + '\x{88F0}\x{88F1}\x{88F2}\x{88F3}\x{88F4}\x{88F5}\x{88F6}\x{88F7}\x{88F8}' . + '\x{88F9}\x{88FA}\x{88FB}\x{88FC}\x{88FD}\x{88FE}\x{88FF}\x{8900}\x{8901}' . + '\x{8902}\x{8904}\x{8905}\x{8906}\x{8907}\x{8908}\x{8909}\x{890A}\x{890B}' . + '\x{890C}\x{890D}\x{890E}\x{8910}\x{8911}\x{8912}\x{8913}\x{8914}\x{8915}' . + '\x{8916}\x{8917}\x{8918}\x{8919}\x{891A}\x{891B}\x{891C}\x{891D}\x{891E}' . + '\x{891F}\x{8920}\x{8921}\x{8922}\x{8923}\x{8925}\x{8926}\x{8927}\x{8928}' . + '\x{8929}\x{892A}\x{892B}\x{892C}\x{892D}\x{892E}\x{892F}\x{8930}\x{8931}' . + '\x{8932}\x{8933}\x{8934}\x{8935}\x{8936}\x{8937}\x{8938}\x{8939}\x{893A}' . + '\x{893B}\x{893C}\x{893D}\x{893E}\x{893F}\x{8940}\x{8941}\x{8942}\x{8943}' . + '\x{8944}\x{8945}\x{8946}\x{8947}\x{8948}\x{8949}\x{894A}\x{894B}\x{894C}' . + '\x{894E}\x{894F}\x{8950}\x{8951}\x{8952}\x{8953}\x{8954}\x{8955}\x{8956}' . + '\x{8957}\x{8958}\x{8959}\x{895A}\x{895B}\x{895C}\x{895D}\x{895E}\x{895F}' . + '\x{8960}\x{8961}\x{8962}\x{8963}\x{8964}\x{8966}\x{8967}\x{8968}\x{8969}' . + '\x{896A}\x{896B}\x{896C}\x{896D}\x{896E}\x{896F}\x{8970}\x{8971}\x{8972}' . + '\x{8973}\x{8974}\x{8976}\x{8977}\x{8978}\x{8979}\x{897A}\x{897B}\x{897C}' . + '\x{897E}\x{897F}\x{8980}\x{8981}\x{8982}\x{8983}\x{8984}\x{8985}\x{8986}' . + '\x{8987}\x{8988}\x{8989}\x{898A}\x{898B}\x{898C}\x{898E}\x{898F}\x{8991}' . + '\x{8992}\x{8993}\x{8995}\x{8996}\x{8997}\x{8998}\x{899A}\x{899B}\x{899C}' . + '\x{899D}\x{899E}\x{899F}\x{89A0}\x{89A1}\x{89A2}\x{89A3}\x{89A4}\x{89A5}' . + '\x{89A6}\x{89A7}\x{89A8}\x{89AA}\x{89AB}\x{89AC}\x{89AD}\x{89AE}\x{89AF}' . + '\x{89B1}\x{89B2}\x{89B3}\x{89B5}\x{89B6}\x{89B7}\x{89B8}\x{89B9}\x{89BA}' . + '\x{89BD}\x{89BE}\x{89BF}\x{89C0}\x{89C1}\x{89C2}\x{89C3}\x{89C4}\x{89C5}' . + '\x{89C6}\x{89C7}\x{89C8}\x{89C9}\x{89CA}\x{89CB}\x{89CC}\x{89CD}\x{89CE}' . + '\x{89CF}\x{89D0}\x{89D1}\x{89D2}\x{89D3}\x{89D4}\x{89D5}\x{89D6}\x{89D7}' . + '\x{89D8}\x{89D9}\x{89DA}\x{89DB}\x{89DC}\x{89DD}\x{89DE}\x{89DF}\x{89E0}' . + '\x{89E1}\x{89E2}\x{89E3}\x{89E4}\x{89E5}\x{89E6}\x{89E7}\x{89E8}\x{89E9}' . + '\x{89EA}\x{89EB}\x{89EC}\x{89ED}\x{89EF}\x{89F0}\x{89F1}\x{89F2}\x{89F3}' . + '\x{89F4}\x{89F6}\x{89F7}\x{89F8}\x{89FA}\x{89FB}\x{89FC}\x{89FE}\x{89FF}' . + '\x{8A00}\x{8A01}\x{8A02}\x{8A03}\x{8A04}\x{8A07}\x{8A08}\x{8A09}\x{8A0A}' . + '\x{8A0B}\x{8A0C}\x{8A0D}\x{8A0E}\x{8A0F}\x{8A10}\x{8A11}\x{8A12}\x{8A13}' . + '\x{8A15}\x{8A16}\x{8A17}\x{8A18}\x{8A1A}\x{8A1B}\x{8A1C}\x{8A1D}\x{8A1E}' . + '\x{8A1F}\x{8A22}\x{8A23}\x{8A24}\x{8A25}\x{8A26}\x{8A27}\x{8A28}\x{8A29}' . + '\x{8A2A}\x{8A2C}\x{8A2D}\x{8A2E}\x{8A2F}\x{8A30}\x{8A31}\x{8A32}\x{8A34}' . + '\x{8A35}\x{8A36}\x{8A37}\x{8A38}\x{8A39}\x{8A3A}\x{8A3B}\x{8A3C}\x{8A3E}' . + '\x{8A3F}\x{8A40}\x{8A41}\x{8A42}\x{8A43}\x{8A44}\x{8A45}\x{8A46}\x{8A47}' . + '\x{8A48}\x{8A49}\x{8A4A}\x{8A4C}\x{8A4D}\x{8A4E}\x{8A4F}\x{8A50}\x{8A51}' . + '\x{8A52}\x{8A53}\x{8A54}\x{8A55}\x{8A56}\x{8A57}\x{8A58}\x{8A59}\x{8A5A}' . + '\x{8A5B}\x{8A5C}\x{8A5D}\x{8A5E}\x{8A5F}\x{8A60}\x{8A61}\x{8A62}\x{8A63}' . + '\x{8A65}\x{8A66}\x{8A67}\x{8A68}\x{8A69}\x{8A6A}\x{8A6B}\x{8A6C}\x{8A6D}' . + '\x{8A6E}\x{8A6F}\x{8A70}\x{8A71}\x{8A72}\x{8A73}\x{8A74}\x{8A75}\x{8A76}' . + '\x{8A77}\x{8A79}\x{8A7A}\x{8A7B}\x{8A7C}\x{8A7E}\x{8A7F}\x{8A80}\x{8A81}' . + '\x{8A82}\x{8A83}\x{8A84}\x{8A85}\x{8A86}\x{8A87}\x{8A89}\x{8A8A}\x{8A8B}' . + '\x{8A8C}\x{8A8D}\x{8A8E}\x{8A8F}\x{8A90}\x{8A91}\x{8A92}\x{8A93}\x{8A94}' . + '\x{8A95}\x{8A96}\x{8A97}\x{8A98}\x{8A99}\x{8A9A}\x{8A9B}\x{8A9C}\x{8A9D}' . + '\x{8A9E}\x{8AA0}\x{8AA1}\x{8AA2}\x{8AA3}\x{8AA4}\x{8AA5}\x{8AA6}\x{8AA7}' . + '\x{8AA8}\x{8AA9}\x{8AAA}\x{8AAB}\x{8AAC}\x{8AAE}\x{8AB0}\x{8AB1}\x{8AB2}' . + '\x{8AB3}\x{8AB4}\x{8AB5}\x{8AB6}\x{8AB8}\x{8AB9}\x{8ABA}\x{8ABB}\x{8ABC}' . + '\x{8ABD}\x{8ABE}\x{8ABF}\x{8AC0}\x{8AC1}\x{8AC2}\x{8AC3}\x{8AC4}\x{8AC5}' . + '\x{8AC6}\x{8AC7}\x{8AC8}\x{8AC9}\x{8ACA}\x{8ACB}\x{8ACC}\x{8ACD}\x{8ACE}' . + '\x{8ACF}\x{8AD1}\x{8AD2}\x{8AD3}\x{8AD4}\x{8AD5}\x{8AD6}\x{8AD7}\x{8AD8}' . + '\x{8AD9}\x{8ADA}\x{8ADB}\x{8ADC}\x{8ADD}\x{8ADE}\x{8ADF}\x{8AE0}\x{8AE1}' . + '\x{8AE2}\x{8AE3}\x{8AE4}\x{8AE5}\x{8AE6}\x{8AE7}\x{8AE8}\x{8AE9}\x{8AEA}' . + '\x{8AEB}\x{8AED}\x{8AEE}\x{8AEF}\x{8AF0}\x{8AF1}\x{8AF2}\x{8AF3}\x{8AF4}' . + '\x{8AF5}\x{8AF6}\x{8AF7}\x{8AF8}\x{8AF9}\x{8AFA}\x{8AFB}\x{8AFC}\x{8AFD}' . + '\x{8AFE}\x{8AFF}\x{8B00}\x{8B01}\x{8B02}\x{8B03}\x{8B04}\x{8B05}\x{8B06}' . + '\x{8B07}\x{8B08}\x{8B09}\x{8B0A}\x{8B0B}\x{8B0D}\x{8B0E}\x{8B0F}\x{8B10}' . + '\x{8B11}\x{8B12}\x{8B13}\x{8B14}\x{8B15}\x{8B16}\x{8B17}\x{8B18}\x{8B19}' . + '\x{8B1A}\x{8B1B}\x{8B1C}\x{8B1D}\x{8B1E}\x{8B1F}\x{8B20}\x{8B21}\x{8B22}' . + '\x{8B23}\x{8B24}\x{8B25}\x{8B26}\x{8B27}\x{8B28}\x{8B2A}\x{8B2B}\x{8B2C}' . + '\x{8B2D}\x{8B2E}\x{8B2F}\x{8B30}\x{8B31}\x{8B33}\x{8B34}\x{8B35}\x{8B36}' . + '\x{8B37}\x{8B39}\x{8B3A}\x{8B3B}\x{8B3C}\x{8B3D}\x{8B3E}\x{8B40}\x{8B41}' . + '\x{8B42}\x{8B43}\x{8B44}\x{8B45}\x{8B46}\x{8B47}\x{8B48}\x{8B49}\x{8B4A}' . + '\x{8B4B}\x{8B4C}\x{8B4D}\x{8B4E}\x{8B4F}\x{8B50}\x{8B51}\x{8B52}\x{8B53}' . + '\x{8B54}\x{8B55}\x{8B56}\x{8B57}\x{8B58}\x{8B59}\x{8B5A}\x{8B5B}\x{8B5C}' . + '\x{8B5D}\x{8B5E}\x{8B5F}\x{8B60}\x{8B63}\x{8B64}\x{8B65}\x{8B66}\x{8B67}' . + '\x{8B68}\x{8B6A}\x{8B6B}\x{8B6C}\x{8B6D}\x{8B6E}\x{8B6F}\x{8B70}\x{8B71}' . + '\x{8B73}\x{8B74}\x{8B76}\x{8B77}\x{8B78}\x{8B79}\x{8B7A}\x{8B7B}\x{8B7D}' . + '\x{8B7E}\x{8B7F}\x{8B80}\x{8B82}\x{8B83}\x{8B84}\x{8B85}\x{8B86}\x{8B88}' . + '\x{8B89}\x{8B8A}\x{8B8B}\x{8B8C}\x{8B8E}\x{8B90}\x{8B91}\x{8B92}\x{8B93}' . + '\x{8B94}\x{8B95}\x{8B96}\x{8B97}\x{8B98}\x{8B99}\x{8B9A}\x{8B9C}\x{8B9D}' . + '\x{8B9E}\x{8B9F}\x{8BA0}\x{8BA1}\x{8BA2}\x{8BA3}\x{8BA4}\x{8BA5}\x{8BA6}' . + '\x{8BA7}\x{8BA8}\x{8BA9}\x{8BAA}\x{8BAB}\x{8BAC}\x{8BAD}\x{8BAE}\x{8BAF}' . + '\x{8BB0}\x{8BB1}\x{8BB2}\x{8BB3}\x{8BB4}\x{8BB5}\x{8BB6}\x{8BB7}\x{8BB8}' . + '\x{8BB9}\x{8BBA}\x{8BBB}\x{8BBC}\x{8BBD}\x{8BBE}\x{8BBF}\x{8BC0}\x{8BC1}' . + '\x{8BC2}\x{8BC3}\x{8BC4}\x{8BC5}\x{8BC6}\x{8BC7}\x{8BC8}\x{8BC9}\x{8BCA}' . + '\x{8BCB}\x{8BCC}\x{8BCD}\x{8BCE}\x{8BCF}\x{8BD0}\x{8BD1}\x{8BD2}\x{8BD3}' . + '\x{8BD4}\x{8BD5}\x{8BD6}\x{8BD7}\x{8BD8}\x{8BD9}\x{8BDA}\x{8BDB}\x{8BDC}' . + '\x{8BDD}\x{8BDE}\x{8BDF}\x{8BE0}\x{8BE1}\x{8BE2}\x{8BE3}\x{8BE4}\x{8BE5}' . + '\x{8BE6}\x{8BE7}\x{8BE8}\x{8BE9}\x{8BEA}\x{8BEB}\x{8BEC}\x{8BED}\x{8BEE}' . + '\x{8BEF}\x{8BF0}\x{8BF1}\x{8BF2}\x{8BF3}\x{8BF4}\x{8BF5}\x{8BF6}\x{8BF7}' . + '\x{8BF8}\x{8BF9}\x{8BFA}\x{8BFB}\x{8BFC}\x{8BFD}\x{8BFE}\x{8BFF}\x{8C00}' . + '\x{8C01}\x{8C02}\x{8C03}\x{8C04}\x{8C05}\x{8C06}\x{8C07}\x{8C08}\x{8C09}' . + '\x{8C0A}\x{8C0B}\x{8C0C}\x{8C0D}\x{8C0E}\x{8C0F}\x{8C10}\x{8C11}\x{8C12}' . + '\x{8C13}\x{8C14}\x{8C15}\x{8C16}\x{8C17}\x{8C18}\x{8C19}\x{8C1A}\x{8C1B}' . + '\x{8C1C}\x{8C1D}\x{8C1E}\x{8C1F}\x{8C20}\x{8C21}\x{8C22}\x{8C23}\x{8C24}' . + '\x{8C25}\x{8C26}\x{8C27}\x{8C28}\x{8C29}\x{8C2A}\x{8C2B}\x{8C2C}\x{8C2D}' . + '\x{8C2E}\x{8C2F}\x{8C30}\x{8C31}\x{8C32}\x{8C33}\x{8C34}\x{8C35}\x{8C36}' . + '\x{8C37}\x{8C39}\x{8C3A}\x{8C3B}\x{8C3C}\x{8C3D}\x{8C3E}\x{8C3F}\x{8C41}' . + '\x{8C42}\x{8C43}\x{8C45}\x{8C46}\x{8C47}\x{8C48}\x{8C49}\x{8C4A}\x{8C4B}' . + '\x{8C4C}\x{8C4D}\x{8C4E}\x{8C4F}\x{8C50}\x{8C54}\x{8C55}\x{8C56}\x{8C57}' . + '\x{8C59}\x{8C5A}\x{8C5B}\x{8C5C}\x{8C5D}\x{8C5E}\x{8C5F}\x{8C60}\x{8C61}' . + '\x{8C62}\x{8C63}\x{8C64}\x{8C65}\x{8C66}\x{8C67}\x{8C68}\x{8C69}\x{8C6A}' . + '\x{8C6B}\x{8C6C}\x{8C6D}\x{8C6E}\x{8C6F}\x{8C70}\x{8C71}\x{8C72}\x{8C73}' . + '\x{8C75}\x{8C76}\x{8C77}\x{8C78}\x{8C79}\x{8C7A}\x{8C7B}\x{8C7D}\x{8C7E}' . + '\x{8C80}\x{8C81}\x{8C82}\x{8C84}\x{8C85}\x{8C86}\x{8C88}\x{8C89}\x{8C8A}' . + '\x{8C8C}\x{8C8D}\x{8C8F}\x{8C90}\x{8C91}\x{8C92}\x{8C93}\x{8C94}\x{8C95}' . + '\x{8C96}\x{8C97}\x{8C98}\x{8C99}\x{8C9A}\x{8C9C}\x{8C9D}\x{8C9E}\x{8C9F}' . + '\x{8CA0}\x{8CA1}\x{8CA2}\x{8CA3}\x{8CA4}\x{8CA5}\x{8CA7}\x{8CA8}\x{8CA9}' . + '\x{8CAA}\x{8CAB}\x{8CAC}\x{8CAD}\x{8CAE}\x{8CAF}\x{8CB0}\x{8CB1}\x{8CB2}' . + '\x{8CB3}\x{8CB4}\x{8CB5}\x{8CB6}\x{8CB7}\x{8CB8}\x{8CB9}\x{8CBA}\x{8CBB}' . + '\x{8CBC}\x{8CBD}\x{8CBE}\x{8CBF}\x{8CC0}\x{8CC1}\x{8CC2}\x{8CC3}\x{8CC4}' . + '\x{8CC5}\x{8CC6}\x{8CC7}\x{8CC8}\x{8CC9}\x{8CCA}\x{8CCC}\x{8CCE}\x{8CCF}' . + '\x{8CD0}\x{8CD1}\x{8CD2}\x{8CD3}\x{8CD4}\x{8CD5}\x{8CD7}\x{8CD9}\x{8CDA}' . + '\x{8CDB}\x{8CDC}\x{8CDD}\x{8CDE}\x{8CDF}\x{8CE0}\x{8CE1}\x{8CE2}\x{8CE3}' . + '\x{8CE4}\x{8CE5}\x{8CE6}\x{8CE7}\x{8CE8}\x{8CEA}\x{8CEB}\x{8CEC}\x{8CED}' . + '\x{8CEE}\x{8CEF}\x{8CF0}\x{8CF1}\x{8CF2}\x{8CF3}\x{8CF4}\x{8CF5}\x{8CF6}' . + '\x{8CF8}\x{8CF9}\x{8CFA}\x{8CFB}\x{8CFC}\x{8CFD}\x{8CFE}\x{8CFF}\x{8D00}' . + '\x{8D02}\x{8D03}\x{8D04}\x{8D05}\x{8D06}\x{8D07}\x{8D08}\x{8D09}\x{8D0A}' . + '\x{8D0B}\x{8D0C}\x{8D0D}\x{8D0E}\x{8D0F}\x{8D10}\x{8D13}\x{8D14}\x{8D15}' . + '\x{8D16}\x{8D17}\x{8D18}\x{8D19}\x{8D1A}\x{8D1B}\x{8D1C}\x{8D1D}\x{8D1E}' . + '\x{8D1F}\x{8D20}\x{8D21}\x{8D22}\x{8D23}\x{8D24}\x{8D25}\x{8D26}\x{8D27}' . + '\x{8D28}\x{8D29}\x{8D2A}\x{8D2B}\x{8D2C}\x{8D2D}\x{8D2E}\x{8D2F}\x{8D30}' . + '\x{8D31}\x{8D32}\x{8D33}\x{8D34}\x{8D35}\x{8D36}\x{8D37}\x{8D38}\x{8D39}' . + '\x{8D3A}\x{8D3B}\x{8D3C}\x{8D3D}\x{8D3E}\x{8D3F}\x{8D40}\x{8D41}\x{8D42}' . + '\x{8D43}\x{8D44}\x{8D45}\x{8D46}\x{8D47}\x{8D48}\x{8D49}\x{8D4A}\x{8D4B}' . + '\x{8D4C}\x{8D4D}\x{8D4E}\x{8D4F}\x{8D50}\x{8D51}\x{8D52}\x{8D53}\x{8D54}' . + '\x{8D55}\x{8D56}\x{8D57}\x{8D58}\x{8D59}\x{8D5A}\x{8D5B}\x{8D5C}\x{8D5D}' . + '\x{8D5E}\x{8D5F}\x{8D60}\x{8D61}\x{8D62}\x{8D63}\x{8D64}\x{8D65}\x{8D66}' . + '\x{8D67}\x{8D68}\x{8D69}\x{8D6A}\x{8D6B}\x{8D6C}\x{8D6D}\x{8D6E}\x{8D6F}' . + '\x{8D70}\x{8D71}\x{8D72}\x{8D73}\x{8D74}\x{8D75}\x{8D76}\x{8D77}\x{8D78}' . + '\x{8D79}\x{8D7A}\x{8D7B}\x{8D7D}\x{8D7E}\x{8D7F}\x{8D80}\x{8D81}\x{8D82}' . + '\x{8D83}\x{8D84}\x{8D85}\x{8D86}\x{8D87}\x{8D88}\x{8D89}\x{8D8A}\x{8D8B}' . + '\x{8D8C}\x{8D8D}\x{8D8E}\x{8D8F}\x{8D90}\x{8D91}\x{8D92}\x{8D93}\x{8D94}' . + '\x{8D95}\x{8D96}\x{8D97}\x{8D98}\x{8D99}\x{8D9A}\x{8D9B}\x{8D9C}\x{8D9D}' . + '\x{8D9E}\x{8D9F}\x{8DA0}\x{8DA1}\x{8DA2}\x{8DA3}\x{8DA4}\x{8DA5}\x{8DA7}' . + '\x{8DA8}\x{8DA9}\x{8DAA}\x{8DAB}\x{8DAC}\x{8DAD}\x{8DAE}\x{8DAF}\x{8DB0}' . + '\x{8DB1}\x{8DB2}\x{8DB3}\x{8DB4}\x{8DB5}\x{8DB6}\x{8DB7}\x{8DB8}\x{8DB9}' . + '\x{8DBA}\x{8DBB}\x{8DBC}\x{8DBD}\x{8DBE}\x{8DBF}\x{8DC1}\x{8DC2}\x{8DC3}' . + '\x{8DC4}\x{8DC5}\x{8DC6}\x{8DC7}\x{8DC8}\x{8DC9}\x{8DCA}\x{8DCB}\x{8DCC}' . + '\x{8DCD}\x{8DCE}\x{8DCF}\x{8DD0}\x{8DD1}\x{8DD2}\x{8DD3}\x{8DD4}\x{8DD5}' . + '\x{8DD6}\x{8DD7}\x{8DD8}\x{8DD9}\x{8DDA}\x{8DDB}\x{8DDC}\x{8DDD}\x{8DDE}' . + '\x{8DDF}\x{8DE0}\x{8DE1}\x{8DE2}\x{8DE3}\x{8DE4}\x{8DE6}\x{8DE7}\x{8DE8}' . + '\x{8DE9}\x{8DEA}\x{8DEB}\x{8DEC}\x{8DED}\x{8DEE}\x{8DEF}\x{8DF0}\x{8DF1}' . + '\x{8DF2}\x{8DF3}\x{8DF4}\x{8DF5}\x{8DF6}\x{8DF7}\x{8DF8}\x{8DF9}\x{8DFA}' . + '\x{8DFB}\x{8DFC}\x{8DFD}\x{8DFE}\x{8DFF}\x{8E00}\x{8E02}\x{8E03}\x{8E04}' . + '\x{8E05}\x{8E06}\x{8E07}\x{8E08}\x{8E09}\x{8E0A}\x{8E0C}\x{8E0D}\x{8E0E}' . + '\x{8E0F}\x{8E10}\x{8E11}\x{8E12}\x{8E13}\x{8E14}\x{8E15}\x{8E16}\x{8E17}' . + '\x{8E18}\x{8E19}\x{8E1A}\x{8E1B}\x{8E1C}\x{8E1D}\x{8E1E}\x{8E1F}\x{8E20}' . + '\x{8E21}\x{8E22}\x{8E23}\x{8E24}\x{8E25}\x{8E26}\x{8E27}\x{8E28}\x{8E29}' . + '\x{8E2A}\x{8E2B}\x{8E2C}\x{8E2D}\x{8E2E}\x{8E2F}\x{8E30}\x{8E31}\x{8E33}' . + '\x{8E34}\x{8E35}\x{8E36}\x{8E37}\x{8E38}\x{8E39}\x{8E3A}\x{8E3B}\x{8E3C}' . + '\x{8E3D}\x{8E3E}\x{8E3F}\x{8E40}\x{8E41}\x{8E42}\x{8E43}\x{8E44}\x{8E45}' . + '\x{8E47}\x{8E48}\x{8E49}\x{8E4A}\x{8E4B}\x{8E4C}\x{8E4D}\x{8E4E}\x{8E50}' . + '\x{8E51}\x{8E52}\x{8E53}\x{8E54}\x{8E55}\x{8E56}\x{8E57}\x{8E58}\x{8E59}' . + '\x{8E5A}\x{8E5B}\x{8E5C}\x{8E5D}\x{8E5E}\x{8E5F}\x{8E60}\x{8E61}\x{8E62}' . + '\x{8E63}\x{8E64}\x{8E65}\x{8E66}\x{8E67}\x{8E68}\x{8E69}\x{8E6A}\x{8E6B}' . + '\x{8E6C}\x{8E6D}\x{8E6F}\x{8E70}\x{8E71}\x{8E72}\x{8E73}\x{8E74}\x{8E76}' . + '\x{8E78}\x{8E7A}\x{8E7B}\x{8E7C}\x{8E7D}\x{8E7E}\x{8E7F}\x{8E80}\x{8E81}' . + '\x{8E82}\x{8E83}\x{8E84}\x{8E85}\x{8E86}\x{8E87}\x{8E88}\x{8E89}\x{8E8A}' . + '\x{8E8B}\x{8E8C}\x{8E8D}\x{8E8E}\x{8E8F}\x{8E90}\x{8E91}\x{8E92}\x{8E93}' . + '\x{8E94}\x{8E95}\x{8E96}\x{8E97}\x{8E98}\x{8E9A}\x{8E9C}\x{8E9D}\x{8E9E}' . + '\x{8E9F}\x{8EA0}\x{8EA1}\x{8EA3}\x{8EA4}\x{8EA5}\x{8EA6}\x{8EA7}\x{8EA8}' . + '\x{8EA9}\x{8EAA}\x{8EAB}\x{8EAC}\x{8EAD}\x{8EAE}\x{8EAF}\x{8EB0}\x{8EB1}' . + '\x{8EB2}\x{8EB4}\x{8EB5}\x{8EB8}\x{8EB9}\x{8EBA}\x{8EBB}\x{8EBC}\x{8EBD}' . + '\x{8EBE}\x{8EBF}\x{8EC0}\x{8EC2}\x{8EC3}\x{8EC5}\x{8EC6}\x{8EC7}\x{8EC8}' . + '\x{8EC9}\x{8ECA}\x{8ECB}\x{8ECC}\x{8ECD}\x{8ECE}\x{8ECF}\x{8ED0}\x{8ED1}' . + '\x{8ED2}\x{8ED3}\x{8ED4}\x{8ED5}\x{8ED6}\x{8ED7}\x{8ED8}\x{8EDA}\x{8EDB}' . + '\x{8EDC}\x{8EDD}\x{8EDE}\x{8EDF}\x{8EE0}\x{8EE1}\x{8EE4}\x{8EE5}\x{8EE6}' . + '\x{8EE7}\x{8EE8}\x{8EE9}\x{8EEA}\x{8EEB}\x{8EEC}\x{8EED}\x{8EEE}\x{8EEF}' . + '\x{8EF1}\x{8EF2}\x{8EF3}\x{8EF4}\x{8EF5}\x{8EF6}\x{8EF7}\x{8EF8}\x{8EF9}' . + '\x{8EFA}\x{8EFB}\x{8EFC}\x{8EFD}\x{8EFE}\x{8EFF}\x{8F00}\x{8F01}\x{8F02}' . + '\x{8F03}\x{8F04}\x{8F05}\x{8F06}\x{8F07}\x{8F08}\x{8F09}\x{8F0A}\x{8F0B}' . + '\x{8F0D}\x{8F0E}\x{8F10}\x{8F11}\x{8F12}\x{8F13}\x{8F14}\x{8F15}\x{8F16}' . + '\x{8F17}\x{8F18}\x{8F1A}\x{8F1B}\x{8F1C}\x{8F1D}\x{8F1E}\x{8F1F}\x{8F20}' . + '\x{8F21}\x{8F22}\x{8F23}\x{8F24}\x{8F25}\x{8F26}\x{8F27}\x{8F28}\x{8F29}' . + '\x{8F2A}\x{8F2B}\x{8F2C}\x{8F2E}\x{8F2F}\x{8F30}\x{8F31}\x{8F32}\x{8F33}' . + '\x{8F34}\x{8F35}\x{8F36}\x{8F37}\x{8F38}\x{8F39}\x{8F3B}\x{8F3C}\x{8F3D}' . + '\x{8F3E}\x{8F3F}\x{8F40}\x{8F42}\x{8F43}\x{8F44}\x{8F45}\x{8F46}\x{8F47}' . + '\x{8F48}\x{8F49}\x{8F4A}\x{8F4B}\x{8F4C}\x{8F4D}\x{8F4E}\x{8F4F}\x{8F50}' . + '\x{8F51}\x{8F52}\x{8F53}\x{8F54}\x{8F55}\x{8F56}\x{8F57}\x{8F58}\x{8F59}' . + '\x{8F5A}\x{8F5B}\x{8F5D}\x{8F5E}\x{8F5F}\x{8F60}\x{8F61}\x{8F62}\x{8F63}' . + '\x{8F64}\x{8F65}\x{8F66}\x{8F67}\x{8F68}\x{8F69}\x{8F6A}\x{8F6B}\x{8F6C}' . + '\x{8F6D}\x{8F6E}\x{8F6F}\x{8F70}\x{8F71}\x{8F72}\x{8F73}\x{8F74}\x{8F75}' . + '\x{8F76}\x{8F77}\x{8F78}\x{8F79}\x{8F7A}\x{8F7B}\x{8F7C}\x{8F7D}\x{8F7E}' . + '\x{8F7F}\x{8F80}\x{8F81}\x{8F82}\x{8F83}\x{8F84}\x{8F85}\x{8F86}\x{8F87}' . + '\x{8F88}\x{8F89}\x{8F8A}\x{8F8B}\x{8F8C}\x{8F8D}\x{8F8E}\x{8F8F}\x{8F90}' . + '\x{8F91}\x{8F92}\x{8F93}\x{8F94}\x{8F95}\x{8F96}\x{8F97}\x{8F98}\x{8F99}' . + '\x{8F9A}\x{8F9B}\x{8F9C}\x{8F9E}\x{8F9F}\x{8FA0}\x{8FA1}\x{8FA2}\x{8FA3}' . + '\x{8FA5}\x{8FA6}\x{8FA7}\x{8FA8}\x{8FA9}\x{8FAA}\x{8FAB}\x{8FAC}\x{8FAD}' . + '\x{8FAE}\x{8FAF}\x{8FB0}\x{8FB1}\x{8FB2}\x{8FB4}\x{8FB5}\x{8FB6}\x{8FB7}' . + '\x{8FB8}\x{8FB9}\x{8FBB}\x{8FBC}\x{8FBD}\x{8FBE}\x{8FBF}\x{8FC0}\x{8FC1}' . + '\x{8FC2}\x{8FC4}\x{8FC5}\x{8FC6}\x{8FC7}\x{8FC8}\x{8FC9}\x{8FCB}\x{8FCC}' . + '\x{8FCD}\x{8FCE}\x{8FCF}\x{8FD0}\x{8FD1}\x{8FD2}\x{8FD3}\x{8FD4}\x{8FD5}' . + '\x{8FD6}\x{8FD7}\x{8FD8}\x{8FD9}\x{8FDA}\x{8FDB}\x{8FDC}\x{8FDD}\x{8FDE}' . + '\x{8FDF}\x{8FE0}\x{8FE1}\x{8FE2}\x{8FE3}\x{8FE4}\x{8FE5}\x{8FE6}\x{8FE8}' . + '\x{8FE9}\x{8FEA}\x{8FEB}\x{8FEC}\x{8FED}\x{8FEE}\x{8FEF}\x{8FF0}\x{8FF1}' . + '\x{8FF2}\x{8FF3}\x{8FF4}\x{8FF5}\x{8FF6}\x{8FF7}\x{8FF8}\x{8FF9}\x{8FFA}' . + '\x{8FFB}\x{8FFC}\x{8FFD}\x{8FFE}\x{8FFF}\x{9000}\x{9001}\x{9002}\x{9003}' . + '\x{9004}\x{9005}\x{9006}\x{9007}\x{9008}\x{9009}\x{900A}\x{900B}\x{900C}' . + '\x{900D}\x{900F}\x{9010}\x{9011}\x{9012}\x{9013}\x{9014}\x{9015}\x{9016}' . + '\x{9017}\x{9018}\x{9019}\x{901A}\x{901B}\x{901C}\x{901D}\x{901E}\x{901F}' . + '\x{9020}\x{9021}\x{9022}\x{9023}\x{9024}\x{9025}\x{9026}\x{9027}\x{9028}' . + '\x{9029}\x{902B}\x{902D}\x{902E}\x{902F}\x{9030}\x{9031}\x{9032}\x{9033}' . + '\x{9034}\x{9035}\x{9036}\x{9038}\x{903A}\x{903B}\x{903C}\x{903D}\x{903E}' . + '\x{903F}\x{9041}\x{9042}\x{9043}\x{9044}\x{9045}\x{9047}\x{9048}\x{9049}' . + '\x{904A}\x{904B}\x{904C}\x{904D}\x{904E}\x{904F}\x{9050}\x{9051}\x{9052}' . + '\x{9053}\x{9054}\x{9055}\x{9056}\x{9057}\x{9058}\x{9059}\x{905A}\x{905B}' . + '\x{905C}\x{905D}\x{905E}\x{905F}\x{9060}\x{9061}\x{9062}\x{9063}\x{9064}' . + '\x{9065}\x{9066}\x{9067}\x{9068}\x{9069}\x{906A}\x{906B}\x{906C}\x{906D}' . + '\x{906E}\x{906F}\x{9070}\x{9071}\x{9072}\x{9073}\x{9074}\x{9075}\x{9076}' . + '\x{9077}\x{9078}\x{9079}\x{907A}\x{907B}\x{907C}\x{907D}\x{907E}\x{907F}' . + '\x{9080}\x{9081}\x{9082}\x{9083}\x{9084}\x{9085}\x{9086}\x{9087}\x{9088}' . + '\x{9089}\x{908A}\x{908B}\x{908C}\x{908D}\x{908E}\x{908F}\x{9090}\x{9091}' . + '\x{9092}\x{9093}\x{9094}\x{9095}\x{9096}\x{9097}\x{9098}\x{9099}\x{909A}' . + '\x{909B}\x{909C}\x{909D}\x{909E}\x{909F}\x{90A0}\x{90A1}\x{90A2}\x{90A3}' . + '\x{90A4}\x{90A5}\x{90A6}\x{90A7}\x{90A8}\x{90A9}\x{90AA}\x{90AC}\x{90AD}' . + '\x{90AE}\x{90AF}\x{90B0}\x{90B1}\x{90B2}\x{90B3}\x{90B4}\x{90B5}\x{90B6}' . + '\x{90B7}\x{90B8}\x{90B9}\x{90BA}\x{90BB}\x{90BC}\x{90BD}\x{90BE}\x{90BF}' . + '\x{90C0}\x{90C1}\x{90C2}\x{90C3}\x{90C4}\x{90C5}\x{90C6}\x{90C7}\x{90C8}' . + '\x{90C9}\x{90CA}\x{90CB}\x{90CE}\x{90CF}\x{90D0}\x{90D1}\x{90D3}\x{90D4}' . + '\x{90D5}\x{90D6}\x{90D7}\x{90D8}\x{90D9}\x{90DA}\x{90DB}\x{90DC}\x{90DD}' . + '\x{90DE}\x{90DF}\x{90E0}\x{90E1}\x{90E2}\x{90E3}\x{90E4}\x{90E5}\x{90E6}' . + '\x{90E7}\x{90E8}\x{90E9}\x{90EA}\x{90EB}\x{90EC}\x{90ED}\x{90EE}\x{90EF}' . + '\x{90F0}\x{90F1}\x{90F2}\x{90F3}\x{90F4}\x{90F5}\x{90F7}\x{90F8}\x{90F9}' . + '\x{90FA}\x{90FB}\x{90FC}\x{90FD}\x{90FE}\x{90FF}\x{9100}\x{9101}\x{9102}' . + '\x{9103}\x{9104}\x{9105}\x{9106}\x{9107}\x{9108}\x{9109}\x{910B}\x{910C}' . + '\x{910D}\x{910E}\x{910F}\x{9110}\x{9111}\x{9112}\x{9113}\x{9114}\x{9115}' . + '\x{9116}\x{9117}\x{9118}\x{9119}\x{911A}\x{911B}\x{911C}\x{911D}\x{911E}' . + '\x{911F}\x{9120}\x{9121}\x{9122}\x{9123}\x{9124}\x{9125}\x{9126}\x{9127}' . + '\x{9128}\x{9129}\x{912A}\x{912B}\x{912C}\x{912D}\x{912E}\x{912F}\x{9130}' . + '\x{9131}\x{9132}\x{9133}\x{9134}\x{9135}\x{9136}\x{9137}\x{9138}\x{9139}' . + '\x{913A}\x{913B}\x{913E}\x{913F}\x{9140}\x{9141}\x{9142}\x{9143}\x{9144}' . + '\x{9145}\x{9146}\x{9147}\x{9148}\x{9149}\x{914A}\x{914B}\x{914C}\x{914D}' . + '\x{914E}\x{914F}\x{9150}\x{9151}\x{9152}\x{9153}\x{9154}\x{9155}\x{9156}' . + '\x{9157}\x{9158}\x{915A}\x{915B}\x{915C}\x{915D}\x{915E}\x{915F}\x{9160}' . + '\x{9161}\x{9162}\x{9163}\x{9164}\x{9165}\x{9166}\x{9167}\x{9168}\x{9169}' . + '\x{916A}\x{916B}\x{916C}\x{916D}\x{916E}\x{916F}\x{9170}\x{9171}\x{9172}' . + '\x{9173}\x{9174}\x{9175}\x{9176}\x{9177}\x{9178}\x{9179}\x{917A}\x{917C}' . + '\x{917D}\x{917E}\x{917F}\x{9180}\x{9181}\x{9182}\x{9183}\x{9184}\x{9185}' . + '\x{9186}\x{9187}\x{9188}\x{9189}\x{918A}\x{918B}\x{918C}\x{918D}\x{918E}' . + '\x{918F}\x{9190}\x{9191}\x{9192}\x{9193}\x{9194}\x{9196}\x{9199}\x{919A}' . + '\x{919B}\x{919C}\x{919D}\x{919E}\x{919F}\x{91A0}\x{91A1}\x{91A2}\x{91A3}' . + '\x{91A5}\x{91A6}\x{91A7}\x{91A8}\x{91AA}\x{91AB}\x{91AC}\x{91AD}\x{91AE}' . + '\x{91AF}\x{91B0}\x{91B1}\x{91B2}\x{91B3}\x{91B4}\x{91B5}\x{91B6}\x{91B7}' . + '\x{91B9}\x{91BA}\x{91BB}\x{91BC}\x{91BD}\x{91BE}\x{91C0}\x{91C1}\x{91C2}' . + '\x{91C3}\x{91C5}\x{91C6}\x{91C7}\x{91C9}\x{91CA}\x{91CB}\x{91CC}\x{91CD}' . + '\x{91CE}\x{91CF}\x{91D0}\x{91D1}\x{91D2}\x{91D3}\x{91D4}\x{91D5}\x{91D7}' . + '\x{91D8}\x{91D9}\x{91DA}\x{91DB}\x{91DC}\x{91DD}\x{91DE}\x{91DF}\x{91E2}' . + '\x{91E3}\x{91E4}\x{91E5}\x{91E6}\x{91E7}\x{91E8}\x{91E9}\x{91EA}\x{91EB}' . + '\x{91EC}\x{91ED}\x{91EE}\x{91F0}\x{91F1}\x{91F2}\x{91F3}\x{91F4}\x{91F5}' . + '\x{91F7}\x{91F8}\x{91F9}\x{91FA}\x{91FB}\x{91FD}\x{91FE}\x{91FF}\x{9200}' . + '\x{9201}\x{9202}\x{9203}\x{9204}\x{9205}\x{9206}\x{9207}\x{9208}\x{9209}' . + '\x{920A}\x{920B}\x{920C}\x{920D}\x{920E}\x{920F}\x{9210}\x{9211}\x{9212}' . + '\x{9214}\x{9215}\x{9216}\x{9217}\x{9218}\x{9219}\x{921A}\x{921B}\x{921C}' . + '\x{921D}\x{921E}\x{9220}\x{9221}\x{9223}\x{9224}\x{9225}\x{9226}\x{9227}' . + '\x{9228}\x{9229}\x{922A}\x{922B}\x{922D}\x{922E}\x{922F}\x{9230}\x{9231}' . + '\x{9232}\x{9233}\x{9234}\x{9235}\x{9236}\x{9237}\x{9238}\x{9239}\x{923A}' . + '\x{923B}\x{923C}\x{923D}\x{923E}\x{923F}\x{9240}\x{9241}\x{9242}\x{9245}' . + '\x{9246}\x{9247}\x{9248}\x{9249}\x{924A}\x{924B}\x{924C}\x{924D}\x{924E}' . + '\x{924F}\x{9250}\x{9251}\x{9252}\x{9253}\x{9254}\x{9255}\x{9256}\x{9257}' . + '\x{9258}\x{9259}\x{925A}\x{925B}\x{925C}\x{925D}\x{925E}\x{925F}\x{9260}' . + '\x{9261}\x{9262}\x{9263}\x{9264}\x{9265}\x{9266}\x{9267}\x{9268}\x{926B}' . + '\x{926C}\x{926D}\x{926E}\x{926F}\x{9270}\x{9272}\x{9273}\x{9274}\x{9275}' . + '\x{9276}\x{9277}\x{9278}\x{9279}\x{927A}\x{927B}\x{927C}\x{927D}\x{927E}' . + '\x{927F}\x{9280}\x{9282}\x{9283}\x{9285}\x{9286}\x{9287}\x{9288}\x{9289}' . + '\x{928A}\x{928B}\x{928C}\x{928D}\x{928E}\x{928F}\x{9290}\x{9291}\x{9292}' . + '\x{9293}\x{9294}\x{9295}\x{9296}\x{9297}\x{9298}\x{9299}\x{929A}\x{929B}' . + '\x{929C}\x{929D}\x{929F}\x{92A0}\x{92A1}\x{92A2}\x{92A3}\x{92A4}\x{92A5}' . + '\x{92A6}\x{92A7}\x{92A8}\x{92A9}\x{92AA}\x{92AB}\x{92AC}\x{92AD}\x{92AE}' . + '\x{92AF}\x{92B0}\x{92B1}\x{92B2}\x{92B3}\x{92B4}\x{92B5}\x{92B6}\x{92B7}' . + '\x{92B8}\x{92B9}\x{92BA}\x{92BB}\x{92BC}\x{92BE}\x{92BF}\x{92C0}\x{92C1}' . + '\x{92C2}\x{92C3}\x{92C4}\x{92C5}\x{92C6}\x{92C7}\x{92C8}\x{92C9}\x{92CA}' . + '\x{92CB}\x{92CC}\x{92CD}\x{92CE}\x{92CF}\x{92D0}\x{92D1}\x{92D2}\x{92D3}' . + '\x{92D5}\x{92D6}\x{92D7}\x{92D8}\x{92D9}\x{92DA}\x{92DC}\x{92DD}\x{92DE}' . + '\x{92DF}\x{92E0}\x{92E1}\x{92E3}\x{92E4}\x{92E5}\x{92E6}\x{92E7}\x{92E8}' . + '\x{92E9}\x{92EA}\x{92EB}\x{92EC}\x{92ED}\x{92EE}\x{92EF}\x{92F0}\x{92F1}' . + '\x{92F2}\x{92F3}\x{92F4}\x{92F5}\x{92F6}\x{92F7}\x{92F8}\x{92F9}\x{92FA}' . + '\x{92FB}\x{92FC}\x{92FD}\x{92FE}\x{92FF}\x{9300}\x{9301}\x{9302}\x{9303}' . + '\x{9304}\x{9305}\x{9306}\x{9307}\x{9308}\x{9309}\x{930A}\x{930B}\x{930C}' . + '\x{930D}\x{930E}\x{930F}\x{9310}\x{9311}\x{9312}\x{9313}\x{9314}\x{9315}' . + '\x{9316}\x{9317}\x{9318}\x{9319}\x{931A}\x{931B}\x{931D}\x{931E}\x{931F}' . + '\x{9320}\x{9321}\x{9322}\x{9323}\x{9324}\x{9325}\x{9326}\x{9327}\x{9328}' . + '\x{9329}\x{932A}\x{932B}\x{932D}\x{932E}\x{932F}\x{9332}\x{9333}\x{9334}' . + '\x{9335}\x{9336}\x{9337}\x{9338}\x{9339}\x{933A}\x{933B}\x{933C}\x{933D}' . + '\x{933E}\x{933F}\x{9340}\x{9341}\x{9342}\x{9343}\x{9344}\x{9345}\x{9346}' . + '\x{9347}\x{9348}\x{9349}\x{934A}\x{934B}\x{934C}\x{934D}\x{934E}\x{934F}' . + '\x{9350}\x{9351}\x{9352}\x{9353}\x{9354}\x{9355}\x{9356}\x{9357}\x{9358}' . + '\x{9359}\x{935A}\x{935B}\x{935C}\x{935D}\x{935E}\x{935F}\x{9360}\x{9361}' . + '\x{9363}\x{9364}\x{9365}\x{9366}\x{9367}\x{9369}\x{936A}\x{936C}\x{936D}' . + '\x{936E}\x{9370}\x{9371}\x{9372}\x{9374}\x{9375}\x{9376}\x{9377}\x{9379}' . + '\x{937A}\x{937B}\x{937C}\x{937D}\x{937E}\x{9380}\x{9382}\x{9383}\x{9384}' . + '\x{9385}\x{9386}\x{9387}\x{9388}\x{9389}\x{938A}\x{938C}\x{938D}\x{938E}' . + '\x{938F}\x{9390}\x{9391}\x{9392}\x{9393}\x{9394}\x{9395}\x{9396}\x{9397}' . + '\x{9398}\x{9399}\x{939A}\x{939B}\x{939D}\x{939E}\x{939F}\x{93A1}\x{93A2}' . + '\x{93A3}\x{93A4}\x{93A5}\x{93A6}\x{93A7}\x{93A8}\x{93A9}\x{93AA}\x{93AC}' . + '\x{93AD}\x{93AE}\x{93AF}\x{93B0}\x{93B1}\x{93B2}\x{93B3}\x{93B4}\x{93B5}' . + '\x{93B6}\x{93B7}\x{93B8}\x{93B9}\x{93BA}\x{93BC}\x{93BD}\x{93BE}\x{93BF}' . + '\x{93C0}\x{93C1}\x{93C2}\x{93C3}\x{93C4}\x{93C5}\x{93C6}\x{93C7}\x{93C8}' . + '\x{93C9}\x{93CA}\x{93CB}\x{93CC}\x{93CD}\x{93CE}\x{93CF}\x{93D0}\x{93D1}' . + '\x{93D2}\x{93D3}\x{93D4}\x{93D5}\x{93D6}\x{93D7}\x{93D8}\x{93D9}\x{93DA}' . + '\x{93DB}\x{93DC}\x{93DD}\x{93DE}\x{93DF}\x{93E1}\x{93E2}\x{93E3}\x{93E4}' . + '\x{93E6}\x{93E7}\x{93E8}\x{93E9}\x{93EA}\x{93EB}\x{93EC}\x{93ED}\x{93EE}' . + '\x{93EF}\x{93F0}\x{93F1}\x{93F2}\x{93F4}\x{93F5}\x{93F6}\x{93F7}\x{93F8}' . + '\x{93F9}\x{93FA}\x{93FB}\x{93FC}\x{93FD}\x{93FE}\x{93FF}\x{9400}\x{9401}' . + '\x{9403}\x{9404}\x{9405}\x{9406}\x{9407}\x{9408}\x{9409}\x{940A}\x{940B}' . + '\x{940C}\x{940D}\x{940E}\x{940F}\x{9410}\x{9411}\x{9412}\x{9413}\x{9414}' . + '\x{9415}\x{9416}\x{9418}\x{9419}\x{941B}\x{941D}\x{9420}\x{9422}\x{9423}' . + '\x{9425}\x{9426}\x{9427}\x{9428}\x{9429}\x{942A}\x{942B}\x{942C}\x{942D}' . + '\x{942E}\x{942F}\x{9430}\x{9431}\x{9432}\x{9433}\x{9434}\x{9435}\x{9436}' . + '\x{9437}\x{9438}\x{9439}\x{943A}\x{943B}\x{943C}\x{943D}\x{943E}\x{943F}' . + '\x{9440}\x{9441}\x{9442}\x{9444}\x{9445}\x{9446}\x{9447}\x{9448}\x{9449}' . + '\x{944A}\x{944B}\x{944C}\x{944D}\x{944F}\x{9450}\x{9451}\x{9452}\x{9453}' . + '\x{9454}\x{9455}\x{9456}\x{9457}\x{9458}\x{9459}\x{945B}\x{945C}\x{945D}' . + '\x{945E}\x{945F}\x{9460}\x{9461}\x{9462}\x{9463}\x{9464}\x{9465}\x{9466}' . + '\x{9467}\x{9468}\x{9469}\x{946A}\x{946B}\x{946D}\x{946E}\x{946F}\x{9470}' . + '\x{9471}\x{9472}\x{9473}\x{9474}\x{9475}\x{9476}\x{9477}\x{9478}\x{9479}' . + '\x{947A}\x{947C}\x{947D}\x{947E}\x{947F}\x{9480}\x{9481}\x{9482}\x{9483}' . + '\x{9484}\x{9485}\x{9486}\x{9487}\x{9488}\x{9489}\x{948A}\x{948B}\x{948C}' . + '\x{948D}\x{948E}\x{948F}\x{9490}\x{9491}\x{9492}\x{9493}\x{9494}\x{9495}' . + '\x{9496}\x{9497}\x{9498}\x{9499}\x{949A}\x{949B}\x{949C}\x{949D}\x{949E}' . + '\x{949F}\x{94A0}\x{94A1}\x{94A2}\x{94A3}\x{94A4}\x{94A5}\x{94A6}\x{94A7}' . + '\x{94A8}\x{94A9}\x{94AA}\x{94AB}\x{94AC}\x{94AD}\x{94AE}\x{94AF}\x{94B0}' . + '\x{94B1}\x{94B2}\x{94B3}\x{94B4}\x{94B5}\x{94B6}\x{94B7}\x{94B8}\x{94B9}' . + '\x{94BA}\x{94BB}\x{94BC}\x{94BD}\x{94BE}\x{94BF}\x{94C0}\x{94C1}\x{94C2}' . + '\x{94C3}\x{94C4}\x{94C5}\x{94C6}\x{94C7}\x{94C8}\x{94C9}\x{94CA}\x{94CB}' . + '\x{94CC}\x{94CD}\x{94CE}\x{94CF}\x{94D0}\x{94D1}\x{94D2}\x{94D3}\x{94D4}' . + '\x{94D5}\x{94D6}\x{94D7}\x{94D8}\x{94D9}\x{94DA}\x{94DB}\x{94DC}\x{94DD}' . + '\x{94DE}\x{94DF}\x{94E0}\x{94E1}\x{94E2}\x{94E3}\x{94E4}\x{94E5}\x{94E6}' . + '\x{94E7}\x{94E8}\x{94E9}\x{94EA}\x{94EB}\x{94EC}\x{94ED}\x{94EE}\x{94EF}' . + '\x{94F0}\x{94F1}\x{94F2}\x{94F3}\x{94F4}\x{94F5}\x{94F6}\x{94F7}\x{94F8}' . + '\x{94F9}\x{94FA}\x{94FB}\x{94FC}\x{94FD}\x{94FE}\x{94FF}\x{9500}\x{9501}' . + '\x{9502}\x{9503}\x{9504}\x{9505}\x{9506}\x{9507}\x{9508}\x{9509}\x{950A}' . + '\x{950B}\x{950C}\x{950D}\x{950E}\x{950F}\x{9510}\x{9511}\x{9512}\x{9513}' . + '\x{9514}\x{9515}\x{9516}\x{9517}\x{9518}\x{9519}\x{951A}\x{951B}\x{951C}' . + '\x{951D}\x{951E}\x{951F}\x{9520}\x{9521}\x{9522}\x{9523}\x{9524}\x{9525}' . + '\x{9526}\x{9527}\x{9528}\x{9529}\x{952A}\x{952B}\x{952C}\x{952D}\x{952E}' . + '\x{952F}\x{9530}\x{9531}\x{9532}\x{9533}\x{9534}\x{9535}\x{9536}\x{9537}' . + '\x{9538}\x{9539}\x{953A}\x{953B}\x{953C}\x{953D}\x{953E}\x{953F}\x{9540}' . + '\x{9541}\x{9542}\x{9543}\x{9544}\x{9545}\x{9546}\x{9547}\x{9548}\x{9549}' . + '\x{954A}\x{954B}\x{954C}\x{954D}\x{954E}\x{954F}\x{9550}\x{9551}\x{9552}' . + '\x{9553}\x{9554}\x{9555}\x{9556}\x{9557}\x{9558}\x{9559}\x{955A}\x{955B}' . + '\x{955C}\x{955D}\x{955E}\x{955F}\x{9560}\x{9561}\x{9562}\x{9563}\x{9564}' . + '\x{9565}\x{9566}\x{9567}\x{9568}\x{9569}\x{956A}\x{956B}\x{956C}\x{956D}' . + '\x{956E}\x{956F}\x{9570}\x{9571}\x{9572}\x{9573}\x{9574}\x{9575}\x{9576}' . + '\x{9577}\x{957A}\x{957B}\x{957C}\x{957D}\x{957F}\x{9580}\x{9581}\x{9582}' . + '\x{9583}\x{9584}\x{9586}\x{9587}\x{9588}\x{9589}\x{958A}\x{958B}\x{958C}' . + '\x{958D}\x{958E}\x{958F}\x{9590}\x{9591}\x{9592}\x{9593}\x{9594}\x{9595}' . + '\x{9596}\x{9598}\x{9599}\x{959A}\x{959B}\x{959C}\x{959D}\x{959E}\x{959F}' . + '\x{95A1}\x{95A2}\x{95A3}\x{95A4}\x{95A5}\x{95A6}\x{95A7}\x{95A8}\x{95A9}' . + '\x{95AA}\x{95AB}\x{95AC}\x{95AD}\x{95AE}\x{95AF}\x{95B0}\x{95B1}\x{95B2}' . + '\x{95B5}\x{95B6}\x{95B7}\x{95B9}\x{95BA}\x{95BB}\x{95BC}\x{95BD}\x{95BE}' . + '\x{95BF}\x{95C0}\x{95C2}\x{95C3}\x{95C4}\x{95C5}\x{95C6}\x{95C7}\x{95C8}' . + '\x{95C9}\x{95CA}\x{95CB}\x{95CC}\x{95CD}\x{95CE}\x{95CF}\x{95D0}\x{95D1}' . + '\x{95D2}\x{95D3}\x{95D4}\x{95D5}\x{95D6}\x{95D7}\x{95D8}\x{95DA}\x{95DB}' . + '\x{95DC}\x{95DE}\x{95DF}\x{95E0}\x{95E1}\x{95E2}\x{95E3}\x{95E4}\x{95E5}' . + '\x{95E6}\x{95E7}\x{95E8}\x{95E9}\x{95EA}\x{95EB}\x{95EC}\x{95ED}\x{95EE}' . + '\x{95EF}\x{95F0}\x{95F1}\x{95F2}\x{95F3}\x{95F4}\x{95F5}\x{95F6}\x{95F7}' . + '\x{95F8}\x{95F9}\x{95FA}\x{95FB}\x{95FC}\x{95FD}\x{95FE}\x{95FF}\x{9600}' . + '\x{9601}\x{9602}\x{9603}\x{9604}\x{9605}\x{9606}\x{9607}\x{9608}\x{9609}' . + '\x{960A}\x{960B}\x{960C}\x{960D}\x{960E}\x{960F}\x{9610}\x{9611}\x{9612}' . + '\x{9613}\x{9614}\x{9615}\x{9616}\x{9617}\x{9618}\x{9619}\x{961A}\x{961B}' . + '\x{961C}\x{961D}\x{961E}\x{961F}\x{9620}\x{9621}\x{9622}\x{9623}\x{9624}' . + '\x{9627}\x{9628}\x{962A}\x{962B}\x{962C}\x{962D}\x{962E}\x{962F}\x{9630}' . + '\x{9631}\x{9632}\x{9633}\x{9634}\x{9635}\x{9636}\x{9637}\x{9638}\x{9639}' . + '\x{963A}\x{963B}\x{963C}\x{963D}\x{963F}\x{9640}\x{9641}\x{9642}\x{9643}' . + '\x{9644}\x{9645}\x{9646}\x{9647}\x{9648}\x{9649}\x{964A}\x{964B}\x{964C}' . + '\x{964D}\x{964E}\x{964F}\x{9650}\x{9651}\x{9652}\x{9653}\x{9654}\x{9655}' . + '\x{9658}\x{9659}\x{965A}\x{965B}\x{965C}\x{965D}\x{965E}\x{965F}\x{9660}' . + '\x{9661}\x{9662}\x{9663}\x{9664}\x{9666}\x{9667}\x{9668}\x{9669}\x{966A}' . + '\x{966B}\x{966C}\x{966D}\x{966E}\x{966F}\x{9670}\x{9671}\x{9672}\x{9673}' . + '\x{9674}\x{9675}\x{9676}\x{9677}\x{9678}\x{967C}\x{967D}\x{967E}\x{9680}' . + '\x{9683}\x{9684}\x{9685}\x{9686}\x{9687}\x{9688}\x{9689}\x{968A}\x{968B}' . + '\x{968D}\x{968E}\x{968F}\x{9690}\x{9691}\x{9692}\x{9693}\x{9694}\x{9695}' . + '\x{9697}\x{9698}\x{9699}\x{969B}\x{969C}\x{969E}\x{96A0}\x{96A1}\x{96A2}' . + '\x{96A3}\x{96A4}\x{96A5}\x{96A6}\x{96A7}\x{96A8}\x{96A9}\x{96AA}\x{96AC}' . + '\x{96AD}\x{96AE}\x{96B0}\x{96B1}\x{96B3}\x{96B4}\x{96B6}\x{96B7}\x{96B8}' . + '\x{96B9}\x{96BA}\x{96BB}\x{96BC}\x{96BD}\x{96BE}\x{96BF}\x{96C0}\x{96C1}' . + '\x{96C2}\x{96C3}\x{96C4}\x{96C5}\x{96C6}\x{96C7}\x{96C8}\x{96C9}\x{96CA}' . + '\x{96CB}\x{96CC}\x{96CD}\x{96CE}\x{96CF}\x{96D0}\x{96D1}\x{96D2}\x{96D3}' . + '\x{96D4}\x{96D5}\x{96D6}\x{96D7}\x{96D8}\x{96D9}\x{96DA}\x{96DB}\x{96DC}' . + '\x{96DD}\x{96DE}\x{96DF}\x{96E0}\x{96E1}\x{96E2}\x{96E3}\x{96E5}\x{96E8}' . + '\x{96E9}\x{96EA}\x{96EB}\x{96EC}\x{96ED}\x{96EE}\x{96EF}\x{96F0}\x{96F1}' . + '\x{96F2}\x{96F3}\x{96F4}\x{96F5}\x{96F6}\x{96F7}\x{96F8}\x{96F9}\x{96FA}' . + '\x{96FB}\x{96FD}\x{96FE}\x{96FF}\x{9700}\x{9701}\x{9702}\x{9703}\x{9704}' . + '\x{9705}\x{9706}\x{9707}\x{9708}\x{9709}\x{970A}\x{970B}\x{970C}\x{970D}' . + '\x{970E}\x{970F}\x{9710}\x{9711}\x{9712}\x{9713}\x{9715}\x{9716}\x{9718}' . + '\x{9719}\x{971C}\x{971D}\x{971E}\x{971F}\x{9720}\x{9721}\x{9722}\x{9723}' . + '\x{9724}\x{9725}\x{9726}\x{9727}\x{9728}\x{9729}\x{972A}\x{972B}\x{972C}' . + '\x{972D}\x{972E}\x{972F}\x{9730}\x{9731}\x{9732}\x{9735}\x{9736}\x{9738}' . + '\x{9739}\x{973A}\x{973B}\x{973C}\x{973D}\x{973E}\x{973F}\x{9742}\x{9743}' . + '\x{9744}\x{9745}\x{9746}\x{9747}\x{9748}\x{9749}\x{974A}\x{974B}\x{974C}' . + '\x{974E}\x{974F}\x{9750}\x{9751}\x{9752}\x{9753}\x{9754}\x{9755}\x{9756}' . + '\x{9758}\x{9759}\x{975A}\x{975B}\x{975C}\x{975D}\x{975E}\x{975F}\x{9760}' . + '\x{9761}\x{9762}\x{9765}\x{9766}\x{9767}\x{9768}\x{9769}\x{976A}\x{976B}' . + '\x{976C}\x{976D}\x{976E}\x{976F}\x{9770}\x{9772}\x{9773}\x{9774}\x{9776}' . + '\x{9777}\x{9778}\x{9779}\x{977A}\x{977B}\x{977C}\x{977D}\x{977E}\x{977F}' . + '\x{9780}\x{9781}\x{9782}\x{9783}\x{9784}\x{9785}\x{9786}\x{9788}\x{978A}' . + '\x{978B}\x{978C}\x{978D}\x{978E}\x{978F}\x{9790}\x{9791}\x{9792}\x{9793}' . + '\x{9794}\x{9795}\x{9796}\x{9797}\x{9798}\x{9799}\x{979A}\x{979C}\x{979D}' . + '\x{979E}\x{979F}\x{97A0}\x{97A1}\x{97A2}\x{97A3}\x{97A4}\x{97A5}\x{97A6}' . + '\x{97A7}\x{97A8}\x{97AA}\x{97AB}\x{97AC}\x{97AD}\x{97AE}\x{97AF}\x{97B2}' . + '\x{97B3}\x{97B4}\x{97B6}\x{97B7}\x{97B8}\x{97B9}\x{97BA}\x{97BB}\x{97BC}' . + '\x{97BD}\x{97BF}\x{97C1}\x{97C2}\x{97C3}\x{97C4}\x{97C5}\x{97C6}\x{97C7}' . + '\x{97C8}\x{97C9}\x{97CA}\x{97CB}\x{97CC}\x{97CD}\x{97CE}\x{97CF}\x{97D0}' . + '\x{97D1}\x{97D3}\x{97D4}\x{97D5}\x{97D6}\x{97D7}\x{97D8}\x{97D9}\x{97DA}' . + '\x{97DB}\x{97DC}\x{97DD}\x{97DE}\x{97DF}\x{97E0}\x{97E1}\x{97E2}\x{97E3}' . + '\x{97E4}\x{97E5}\x{97E6}\x{97E7}\x{97E8}\x{97E9}\x{97EA}\x{97EB}\x{97EC}' . + '\x{97ED}\x{97EE}\x{97EF}\x{97F0}\x{97F1}\x{97F2}\x{97F3}\x{97F4}\x{97F5}' . + '\x{97F6}\x{97F7}\x{97F8}\x{97F9}\x{97FA}\x{97FB}\x{97FD}\x{97FE}\x{97FF}' . + '\x{9800}\x{9801}\x{9802}\x{9803}\x{9804}\x{9805}\x{9806}\x{9807}\x{9808}' . + '\x{9809}\x{980A}\x{980B}\x{980C}\x{980D}\x{980E}\x{980F}\x{9810}\x{9811}' . + '\x{9812}\x{9813}\x{9814}\x{9815}\x{9816}\x{9817}\x{9818}\x{9819}\x{981A}' . + '\x{981B}\x{981C}\x{981D}\x{981E}\x{9820}\x{9821}\x{9822}\x{9823}\x{9824}' . + '\x{9826}\x{9827}\x{9828}\x{9829}\x{982B}\x{982D}\x{982E}\x{982F}\x{9830}' . + '\x{9831}\x{9832}\x{9834}\x{9835}\x{9836}\x{9837}\x{9838}\x{9839}\x{983B}' . + '\x{983C}\x{983D}\x{983F}\x{9840}\x{9841}\x{9843}\x{9844}\x{9845}\x{9846}' . + '\x{9848}\x{9849}\x{984A}\x{984C}\x{984D}\x{984E}\x{984F}\x{9850}\x{9851}' . + '\x{9852}\x{9853}\x{9854}\x{9855}\x{9857}\x{9858}\x{9859}\x{985A}\x{985B}' . + '\x{985C}\x{985D}\x{985E}\x{985F}\x{9860}\x{9861}\x{9862}\x{9863}\x{9864}' . + '\x{9865}\x{9867}\x{9869}\x{986A}\x{986B}\x{986C}\x{986D}\x{986E}\x{986F}' . + '\x{9870}\x{9871}\x{9872}\x{9873}\x{9874}\x{9875}\x{9876}\x{9877}\x{9878}' . + '\x{9879}\x{987A}\x{987B}\x{987C}\x{987D}\x{987E}\x{987F}\x{9880}\x{9881}' . + '\x{9882}\x{9883}\x{9884}\x{9885}\x{9886}\x{9887}\x{9888}\x{9889}\x{988A}' . + '\x{988B}\x{988C}\x{988D}\x{988E}\x{988F}\x{9890}\x{9891}\x{9892}\x{9893}' . + '\x{9894}\x{9895}\x{9896}\x{9897}\x{9898}\x{9899}\x{989A}\x{989B}\x{989C}' . + '\x{989D}\x{989E}\x{989F}\x{98A0}\x{98A1}\x{98A2}\x{98A3}\x{98A4}\x{98A5}' . + '\x{98A6}\x{98A7}\x{98A8}\x{98A9}\x{98AA}\x{98AB}\x{98AC}\x{98AD}\x{98AE}' . + '\x{98AF}\x{98B0}\x{98B1}\x{98B2}\x{98B3}\x{98B4}\x{98B5}\x{98B6}\x{98B8}' . + '\x{98B9}\x{98BA}\x{98BB}\x{98BC}\x{98BD}\x{98BE}\x{98BF}\x{98C0}\x{98C1}' . + '\x{98C2}\x{98C3}\x{98C4}\x{98C5}\x{98C6}\x{98C8}\x{98C9}\x{98CB}\x{98CC}' . + '\x{98CD}\x{98CE}\x{98CF}\x{98D0}\x{98D1}\x{98D2}\x{98D3}\x{98D4}\x{98D5}' . + '\x{98D6}\x{98D7}\x{98D8}\x{98D9}\x{98DA}\x{98DB}\x{98DC}\x{98DD}\x{98DE}' . + '\x{98DF}\x{98E0}\x{98E2}\x{98E3}\x{98E5}\x{98E6}\x{98E7}\x{98E8}\x{98E9}' . + '\x{98EA}\x{98EB}\x{98ED}\x{98EF}\x{98F0}\x{98F2}\x{98F3}\x{98F4}\x{98F5}' . + '\x{98F6}\x{98F7}\x{98F9}\x{98FA}\x{98FC}\x{98FD}\x{98FE}\x{98FF}\x{9900}' . + '\x{9901}\x{9902}\x{9903}\x{9904}\x{9905}\x{9906}\x{9907}\x{9908}\x{9909}' . + '\x{990A}\x{990B}\x{990C}\x{990D}\x{990E}\x{990F}\x{9910}\x{9911}\x{9912}' . + '\x{9913}\x{9914}\x{9915}\x{9916}\x{9917}\x{9918}\x{991A}\x{991B}\x{991C}' . + '\x{991D}\x{991E}\x{991F}\x{9920}\x{9921}\x{9922}\x{9923}\x{9924}\x{9925}' . + '\x{9926}\x{9927}\x{9928}\x{9929}\x{992A}\x{992B}\x{992C}\x{992D}\x{992E}' . + '\x{992F}\x{9930}\x{9931}\x{9932}\x{9933}\x{9934}\x{9935}\x{9936}\x{9937}' . + '\x{9938}\x{9939}\x{993A}\x{993C}\x{993D}\x{993E}\x{993F}\x{9940}\x{9941}' . + '\x{9942}\x{9943}\x{9945}\x{9946}\x{9947}\x{9948}\x{9949}\x{994A}\x{994B}' . + '\x{994C}\x{994E}\x{994F}\x{9950}\x{9951}\x{9952}\x{9953}\x{9954}\x{9955}' . + '\x{9956}\x{9957}\x{9958}\x{9959}\x{995B}\x{995C}\x{995E}\x{995F}\x{9960}' . + '\x{9961}\x{9962}\x{9963}\x{9964}\x{9965}\x{9966}\x{9967}\x{9968}\x{9969}' . + '\x{996A}\x{996B}\x{996C}\x{996D}\x{996E}\x{996F}\x{9970}\x{9971}\x{9972}' . + '\x{9973}\x{9974}\x{9975}\x{9976}\x{9977}\x{9978}\x{9979}\x{997A}\x{997B}' . + '\x{997C}\x{997D}\x{997E}\x{997F}\x{9980}\x{9981}\x{9982}\x{9983}\x{9984}' . + '\x{9985}\x{9986}\x{9987}\x{9988}\x{9989}\x{998A}\x{998B}\x{998C}\x{998D}' . + '\x{998E}\x{998F}\x{9990}\x{9991}\x{9992}\x{9993}\x{9994}\x{9995}\x{9996}' . + '\x{9997}\x{9998}\x{9999}\x{999A}\x{999B}\x{999C}\x{999D}\x{999E}\x{999F}' . + '\x{99A0}\x{99A1}\x{99A2}\x{99A3}\x{99A4}\x{99A5}\x{99A6}\x{99A7}\x{99A8}' . + '\x{99A9}\x{99AA}\x{99AB}\x{99AC}\x{99AD}\x{99AE}\x{99AF}\x{99B0}\x{99B1}' . + '\x{99B2}\x{99B3}\x{99B4}\x{99B5}\x{99B6}\x{99B7}\x{99B8}\x{99B9}\x{99BA}' . + '\x{99BB}\x{99BC}\x{99BD}\x{99BE}\x{99C0}\x{99C1}\x{99C2}\x{99C3}\x{99C4}' . + '\x{99C6}\x{99C7}\x{99C8}\x{99C9}\x{99CA}\x{99CB}\x{99CC}\x{99CD}\x{99CE}' . + '\x{99CF}\x{99D0}\x{99D1}\x{99D2}\x{99D3}\x{99D4}\x{99D5}\x{99D6}\x{99D7}' . + '\x{99D8}\x{99D9}\x{99DA}\x{99DB}\x{99DC}\x{99DD}\x{99DE}\x{99DF}\x{99E1}' . + '\x{99E2}\x{99E3}\x{99E4}\x{99E5}\x{99E7}\x{99E8}\x{99E9}\x{99EA}\x{99EC}' . + '\x{99ED}\x{99EE}\x{99EF}\x{99F0}\x{99F1}\x{99F2}\x{99F3}\x{99F4}\x{99F6}' . + '\x{99F7}\x{99F8}\x{99F9}\x{99FA}\x{99FB}\x{99FC}\x{99FD}\x{99FE}\x{99FF}' . + '\x{9A00}\x{9A01}\x{9A02}\x{9A03}\x{9A04}\x{9A05}\x{9A06}\x{9A07}\x{9A08}' . + '\x{9A09}\x{9A0A}\x{9A0B}\x{9A0C}\x{9A0D}\x{9A0E}\x{9A0F}\x{9A11}\x{9A14}' . + '\x{9A15}\x{9A16}\x{9A19}\x{9A1A}\x{9A1B}\x{9A1C}\x{9A1D}\x{9A1E}\x{9A1F}' . + '\x{9A20}\x{9A21}\x{9A22}\x{9A23}\x{9A24}\x{9A25}\x{9A26}\x{9A27}\x{9A29}' . + '\x{9A2A}\x{9A2B}\x{9A2C}\x{9A2D}\x{9A2E}\x{9A2F}\x{9A30}\x{9A31}\x{9A32}' . + '\x{9A33}\x{9A34}\x{9A35}\x{9A36}\x{9A37}\x{9A38}\x{9A39}\x{9A3A}\x{9A3C}' . + '\x{9A3D}\x{9A3E}\x{9A3F}\x{9A40}\x{9A41}\x{9A42}\x{9A43}\x{9A44}\x{9A45}' . + '\x{9A46}\x{9A47}\x{9A48}\x{9A49}\x{9A4A}\x{9A4B}\x{9A4C}\x{9A4D}\x{9A4E}' . + '\x{9A4F}\x{9A50}\x{9A52}\x{9A53}\x{9A54}\x{9A55}\x{9A56}\x{9A57}\x{9A59}' . + '\x{9A5A}\x{9A5B}\x{9A5C}\x{9A5E}\x{9A5F}\x{9A60}\x{9A61}\x{9A62}\x{9A64}' . + '\x{9A65}\x{9A66}\x{9A67}\x{9A68}\x{9A69}\x{9A6A}\x{9A6B}\x{9A6C}\x{9A6D}' . + '\x{9A6E}\x{9A6F}\x{9A70}\x{9A71}\x{9A72}\x{9A73}\x{9A74}\x{9A75}\x{9A76}' . + '\x{9A77}\x{9A78}\x{9A79}\x{9A7A}\x{9A7B}\x{9A7C}\x{9A7D}\x{9A7E}\x{9A7F}' . + '\x{9A80}\x{9A81}\x{9A82}\x{9A83}\x{9A84}\x{9A85}\x{9A86}\x{9A87}\x{9A88}' . + '\x{9A89}\x{9A8A}\x{9A8B}\x{9A8C}\x{9A8D}\x{9A8E}\x{9A8F}\x{9A90}\x{9A91}' . + '\x{9A92}\x{9A93}\x{9A94}\x{9A95}\x{9A96}\x{9A97}\x{9A98}\x{9A99}\x{9A9A}' . + '\x{9A9B}\x{9A9C}\x{9A9D}\x{9A9E}\x{9A9F}\x{9AA0}\x{9AA1}\x{9AA2}\x{9AA3}' . + '\x{9AA4}\x{9AA5}\x{9AA6}\x{9AA7}\x{9AA8}\x{9AAA}\x{9AAB}\x{9AAC}\x{9AAD}' . + '\x{9AAE}\x{9AAF}\x{9AB0}\x{9AB1}\x{9AB2}\x{9AB3}\x{9AB4}\x{9AB5}\x{9AB6}' . + '\x{9AB7}\x{9AB8}\x{9AB9}\x{9ABA}\x{9ABB}\x{9ABC}\x{9ABE}\x{9ABF}\x{9AC0}' . + '\x{9AC1}\x{9AC2}\x{9AC3}\x{9AC4}\x{9AC5}\x{9AC6}\x{9AC7}\x{9AC9}\x{9ACA}' . + '\x{9ACB}\x{9ACC}\x{9ACD}\x{9ACE}\x{9ACF}\x{9AD0}\x{9AD1}\x{9AD2}\x{9AD3}' . + '\x{9AD4}\x{9AD5}\x{9AD6}\x{9AD8}\x{9AD9}\x{9ADA}\x{9ADB}\x{9ADC}\x{9ADD}' . + '\x{9ADE}\x{9ADF}\x{9AE1}\x{9AE2}\x{9AE3}\x{9AE5}\x{9AE6}\x{9AE7}\x{9AEA}' . + '\x{9AEB}\x{9AEC}\x{9AED}\x{9AEE}\x{9AEF}\x{9AF1}\x{9AF2}\x{9AF3}\x{9AF4}' . + '\x{9AF5}\x{9AF6}\x{9AF7}\x{9AF8}\x{9AF9}\x{9AFA}\x{9AFB}\x{9AFC}\x{9AFD}' . + '\x{9AFE}\x{9AFF}\x{9B01}\x{9B03}\x{9B04}\x{9B05}\x{9B06}\x{9B07}\x{9B08}' . + '\x{9B0A}\x{9B0B}\x{9B0C}\x{9B0D}\x{9B0E}\x{9B0F}\x{9B10}\x{9B11}\x{9B12}' . + '\x{9B13}\x{9B15}\x{9B16}\x{9B17}\x{9B18}\x{9B19}\x{9B1A}\x{9B1C}\x{9B1D}' . + '\x{9B1E}\x{9B1F}\x{9B20}\x{9B21}\x{9B22}\x{9B23}\x{9B24}\x{9B25}\x{9B26}' . + '\x{9B27}\x{9B28}\x{9B29}\x{9B2A}\x{9B2B}\x{9B2C}\x{9B2D}\x{9B2E}\x{9B2F}' . + '\x{9B30}\x{9B31}\x{9B32}\x{9B33}\x{9B35}\x{9B36}\x{9B37}\x{9B38}\x{9B39}' . + '\x{9B3A}\x{9B3B}\x{9B3C}\x{9B3E}\x{9B3F}\x{9B41}\x{9B42}\x{9B43}\x{9B44}' . + '\x{9B45}\x{9B46}\x{9B47}\x{9B48}\x{9B49}\x{9B4A}\x{9B4B}\x{9B4C}\x{9B4D}' . + '\x{9B4E}\x{9B4F}\x{9B51}\x{9B52}\x{9B53}\x{9B54}\x{9B55}\x{9B56}\x{9B58}' . + '\x{9B59}\x{9B5A}\x{9B5B}\x{9B5C}\x{9B5D}\x{9B5E}\x{9B5F}\x{9B60}\x{9B61}' . + '\x{9B63}\x{9B64}\x{9B65}\x{9B66}\x{9B67}\x{9B68}\x{9B69}\x{9B6A}\x{9B6B}' . + '\x{9B6C}\x{9B6D}\x{9B6E}\x{9B6F}\x{9B70}\x{9B71}\x{9B73}\x{9B74}\x{9B75}' . + '\x{9B76}\x{9B77}\x{9B78}\x{9B79}\x{9B7A}\x{9B7B}\x{9B7C}\x{9B7D}\x{9B7E}' . + '\x{9B7F}\x{9B80}\x{9B81}\x{9B82}\x{9B83}\x{9B84}\x{9B85}\x{9B86}\x{9B87}' . + '\x{9B88}\x{9B8A}\x{9B8B}\x{9B8D}\x{9B8E}\x{9B8F}\x{9B90}\x{9B91}\x{9B92}' . + '\x{9B93}\x{9B94}\x{9B95}\x{9B96}\x{9B97}\x{9B98}\x{9B9A}\x{9B9B}\x{9B9C}' . + '\x{9B9D}\x{9B9E}\x{9B9F}\x{9BA0}\x{9BA1}\x{9BA2}\x{9BA3}\x{9BA4}\x{9BA5}' . + '\x{9BA6}\x{9BA7}\x{9BA8}\x{9BA9}\x{9BAA}\x{9BAB}\x{9BAC}\x{9BAD}\x{9BAE}' . + '\x{9BAF}\x{9BB0}\x{9BB1}\x{9BB2}\x{9BB3}\x{9BB4}\x{9BB5}\x{9BB6}\x{9BB7}' . + '\x{9BB8}\x{9BB9}\x{9BBA}\x{9BBB}\x{9BBC}\x{9BBD}\x{9BBE}\x{9BBF}\x{9BC0}' . + '\x{9BC1}\x{9BC3}\x{9BC4}\x{9BC5}\x{9BC6}\x{9BC7}\x{9BC8}\x{9BC9}\x{9BCA}' . + '\x{9BCB}\x{9BCC}\x{9BCD}\x{9BCE}\x{9BCF}\x{9BD0}\x{9BD1}\x{9BD2}\x{9BD3}' . + '\x{9BD4}\x{9BD5}\x{9BD6}\x{9BD7}\x{9BD8}\x{9BD9}\x{9BDA}\x{9BDB}\x{9BDC}' . + '\x{9BDD}\x{9BDE}\x{9BDF}\x{9BE0}\x{9BE1}\x{9BE2}\x{9BE3}\x{9BE4}\x{9BE5}' . + '\x{9BE6}\x{9BE7}\x{9BE8}\x{9BE9}\x{9BEA}\x{9BEB}\x{9BEC}\x{9BED}\x{9BEE}' . + '\x{9BEF}\x{9BF0}\x{9BF1}\x{9BF2}\x{9BF3}\x{9BF4}\x{9BF5}\x{9BF7}\x{9BF8}' . + '\x{9BF9}\x{9BFA}\x{9BFB}\x{9BFC}\x{9BFD}\x{9BFE}\x{9BFF}\x{9C02}\x{9C05}' . + '\x{9C06}\x{9C07}\x{9C08}\x{9C09}\x{9C0A}\x{9C0B}\x{9C0C}\x{9C0D}\x{9C0E}' . + '\x{9C0F}\x{9C10}\x{9C11}\x{9C12}\x{9C13}\x{9C14}\x{9C15}\x{9C16}\x{9C17}' . + '\x{9C18}\x{9C19}\x{9C1A}\x{9C1B}\x{9C1C}\x{9C1D}\x{9C1E}\x{9C1F}\x{9C20}' . + '\x{9C21}\x{9C22}\x{9C23}\x{9C24}\x{9C25}\x{9C26}\x{9C27}\x{9C28}\x{9C29}' . + '\x{9C2A}\x{9C2B}\x{9C2C}\x{9C2D}\x{9C2F}\x{9C30}\x{9C31}\x{9C32}\x{9C33}' . + '\x{9C34}\x{9C35}\x{9C36}\x{9C37}\x{9C38}\x{9C39}\x{9C3A}\x{9C3B}\x{9C3C}' . + '\x{9C3D}\x{9C3E}\x{9C3F}\x{9C40}\x{9C41}\x{9C43}\x{9C44}\x{9C45}\x{9C46}' . + '\x{9C47}\x{9C48}\x{9C49}\x{9C4A}\x{9C4B}\x{9C4C}\x{9C4D}\x{9C4E}\x{9C50}' . + '\x{9C52}\x{9C53}\x{9C54}\x{9C55}\x{9C56}\x{9C57}\x{9C58}\x{9C59}\x{9C5A}' . + '\x{9C5B}\x{9C5C}\x{9C5D}\x{9C5E}\x{9C5F}\x{9C60}\x{9C62}\x{9C63}\x{9C65}' . + '\x{9C66}\x{9C67}\x{9C68}\x{9C69}\x{9C6A}\x{9C6B}\x{9C6C}\x{9C6D}\x{9C6E}' . + '\x{9C6F}\x{9C70}\x{9C71}\x{9C72}\x{9C73}\x{9C74}\x{9C75}\x{9C77}\x{9C78}' . + '\x{9C79}\x{9C7A}\x{9C7C}\x{9C7D}\x{9C7E}\x{9C7F}\x{9C80}\x{9C81}\x{9C82}' . + '\x{9C83}\x{9C84}\x{9C85}\x{9C86}\x{9C87}\x{9C88}\x{9C89}\x{9C8A}\x{9C8B}' . + '\x{9C8C}\x{9C8D}\x{9C8E}\x{9C8F}\x{9C90}\x{9C91}\x{9C92}\x{9C93}\x{9C94}' . + '\x{9C95}\x{9C96}\x{9C97}\x{9C98}\x{9C99}\x{9C9A}\x{9C9B}\x{9C9C}\x{9C9D}' . + '\x{9C9E}\x{9C9F}\x{9CA0}\x{9CA1}\x{9CA2}\x{9CA3}\x{9CA4}\x{9CA5}\x{9CA6}' . + '\x{9CA7}\x{9CA8}\x{9CA9}\x{9CAA}\x{9CAB}\x{9CAC}\x{9CAD}\x{9CAE}\x{9CAF}' . + '\x{9CB0}\x{9CB1}\x{9CB2}\x{9CB3}\x{9CB4}\x{9CB5}\x{9CB6}\x{9CB7}\x{9CB8}' . + '\x{9CB9}\x{9CBA}\x{9CBB}\x{9CBC}\x{9CBD}\x{9CBE}\x{9CBF}\x{9CC0}\x{9CC1}' . + '\x{9CC2}\x{9CC3}\x{9CC4}\x{9CC5}\x{9CC6}\x{9CC7}\x{9CC8}\x{9CC9}\x{9CCA}' . + '\x{9CCB}\x{9CCC}\x{9CCD}\x{9CCE}\x{9CCF}\x{9CD0}\x{9CD1}\x{9CD2}\x{9CD3}' . + '\x{9CD4}\x{9CD5}\x{9CD6}\x{9CD7}\x{9CD8}\x{9CD9}\x{9CDA}\x{9CDB}\x{9CDC}' . + '\x{9CDD}\x{9CDE}\x{9CDF}\x{9CE0}\x{9CE1}\x{9CE2}\x{9CE3}\x{9CE4}\x{9CE5}' . + '\x{9CE6}\x{9CE7}\x{9CE8}\x{9CE9}\x{9CEA}\x{9CEB}\x{9CEC}\x{9CED}\x{9CEE}' . + '\x{9CEF}\x{9CF0}\x{9CF1}\x{9CF2}\x{9CF3}\x{9CF4}\x{9CF5}\x{9CF6}\x{9CF7}' . + '\x{9CF8}\x{9CF9}\x{9CFA}\x{9CFB}\x{9CFC}\x{9CFD}\x{9CFE}\x{9CFF}\x{9D00}' . + '\x{9D01}\x{9D02}\x{9D03}\x{9D04}\x{9D05}\x{9D06}\x{9D07}\x{9D08}\x{9D09}' . + '\x{9D0A}\x{9D0B}\x{9D0F}\x{9D10}\x{9D12}\x{9D13}\x{9D14}\x{9D15}\x{9D16}' . + '\x{9D17}\x{9D18}\x{9D19}\x{9D1A}\x{9D1B}\x{9D1C}\x{9D1D}\x{9D1E}\x{9D1F}' . + '\x{9D20}\x{9D21}\x{9D22}\x{9D23}\x{9D24}\x{9D25}\x{9D26}\x{9D28}\x{9D29}' . + '\x{9D2B}\x{9D2D}\x{9D2E}\x{9D2F}\x{9D30}\x{9D31}\x{9D32}\x{9D33}\x{9D34}' . + '\x{9D36}\x{9D37}\x{9D38}\x{9D39}\x{9D3A}\x{9D3B}\x{9D3D}\x{9D3E}\x{9D3F}' . + '\x{9D40}\x{9D41}\x{9D42}\x{9D43}\x{9D45}\x{9D46}\x{9D47}\x{9D48}\x{9D49}' . + '\x{9D4A}\x{9D4B}\x{9D4C}\x{9D4D}\x{9D4E}\x{9D4F}\x{9D50}\x{9D51}\x{9D52}' . + '\x{9D53}\x{9D54}\x{9D55}\x{9D56}\x{9D57}\x{9D58}\x{9D59}\x{9D5A}\x{9D5B}' . + '\x{9D5C}\x{9D5D}\x{9D5E}\x{9D5F}\x{9D60}\x{9D61}\x{9D62}\x{9D63}\x{9D64}' . + '\x{9D65}\x{9D66}\x{9D67}\x{9D68}\x{9D69}\x{9D6A}\x{9D6B}\x{9D6C}\x{9D6E}' . + '\x{9D6F}\x{9D70}\x{9D71}\x{9D72}\x{9D73}\x{9D74}\x{9D75}\x{9D76}\x{9D77}' . + '\x{9D78}\x{9D79}\x{9D7A}\x{9D7B}\x{9D7C}\x{9D7D}\x{9D7E}\x{9D7F}\x{9D80}' . + '\x{9D81}\x{9D82}\x{9D83}\x{9D84}\x{9D85}\x{9D86}\x{9D87}\x{9D88}\x{9D89}' . + '\x{9D8A}\x{9D8B}\x{9D8C}\x{9D8D}\x{9D8E}\x{9D90}\x{9D91}\x{9D92}\x{9D93}' . + '\x{9D94}\x{9D96}\x{9D97}\x{9D98}\x{9D99}\x{9D9A}\x{9D9B}\x{9D9C}\x{9D9D}' . + '\x{9D9E}\x{9D9F}\x{9DA0}\x{9DA1}\x{9DA2}\x{9DA3}\x{9DA4}\x{9DA5}\x{9DA6}' . + '\x{9DA7}\x{9DA8}\x{9DA9}\x{9DAA}\x{9DAB}\x{9DAC}\x{9DAD}\x{9DAF}\x{9DB0}' . + '\x{9DB1}\x{9DB2}\x{9DB3}\x{9DB4}\x{9DB5}\x{9DB6}\x{9DB7}\x{9DB8}\x{9DB9}' . + '\x{9DBA}\x{9DBB}\x{9DBC}\x{9DBE}\x{9DBF}\x{9DC1}\x{9DC2}\x{9DC3}\x{9DC4}' . + '\x{9DC5}\x{9DC7}\x{9DC8}\x{9DC9}\x{9DCA}\x{9DCB}\x{9DCC}\x{9DCD}\x{9DCE}' . + '\x{9DCF}\x{9DD0}\x{9DD1}\x{9DD2}\x{9DD3}\x{9DD4}\x{9DD5}\x{9DD6}\x{9DD7}' . + '\x{9DD8}\x{9DD9}\x{9DDA}\x{9DDB}\x{9DDC}\x{9DDD}\x{9DDE}\x{9DDF}\x{9DE0}' . + '\x{9DE1}\x{9DE2}\x{9DE3}\x{9DE4}\x{9DE5}\x{9DE6}\x{9DE7}\x{9DE8}\x{9DE9}' . + '\x{9DEB}\x{9DEC}\x{9DED}\x{9DEE}\x{9DEF}\x{9DF0}\x{9DF1}\x{9DF2}\x{9DF3}' . + '\x{9DF4}\x{9DF5}\x{9DF6}\x{9DF7}\x{9DF8}\x{9DF9}\x{9DFA}\x{9DFB}\x{9DFD}' . + '\x{9DFE}\x{9DFF}\x{9E00}\x{9E01}\x{9E02}\x{9E03}\x{9E04}\x{9E05}\x{9E06}' . + '\x{9E07}\x{9E08}\x{9E09}\x{9E0A}\x{9E0B}\x{9E0C}\x{9E0D}\x{9E0F}\x{9E10}' . + '\x{9E11}\x{9E12}\x{9E13}\x{9E14}\x{9E15}\x{9E17}\x{9E18}\x{9E19}\x{9E1A}' . + '\x{9E1B}\x{9E1D}\x{9E1E}\x{9E1F}\x{9E20}\x{9E21}\x{9E22}\x{9E23}\x{9E24}' . + '\x{9E25}\x{9E26}\x{9E27}\x{9E28}\x{9E29}\x{9E2A}\x{9E2B}\x{9E2C}\x{9E2D}' . + '\x{9E2E}\x{9E2F}\x{9E30}\x{9E31}\x{9E32}\x{9E33}\x{9E34}\x{9E35}\x{9E36}' . + '\x{9E37}\x{9E38}\x{9E39}\x{9E3A}\x{9E3B}\x{9E3C}\x{9E3D}\x{9E3E}\x{9E3F}' . + '\x{9E40}\x{9E41}\x{9E42}\x{9E43}\x{9E44}\x{9E45}\x{9E46}\x{9E47}\x{9E48}' . + '\x{9E49}\x{9E4A}\x{9E4B}\x{9E4C}\x{9E4D}\x{9E4E}\x{9E4F}\x{9E50}\x{9E51}' . + '\x{9E52}\x{9E53}\x{9E54}\x{9E55}\x{9E56}\x{9E57}\x{9E58}\x{9E59}\x{9E5A}' . + '\x{9E5B}\x{9E5C}\x{9E5D}\x{9E5E}\x{9E5F}\x{9E60}\x{9E61}\x{9E62}\x{9E63}' . + '\x{9E64}\x{9E65}\x{9E66}\x{9E67}\x{9E68}\x{9E69}\x{9E6A}\x{9E6B}\x{9E6C}' . + '\x{9E6D}\x{9E6E}\x{9E6F}\x{9E70}\x{9E71}\x{9E72}\x{9E73}\x{9E74}\x{9E75}' . + '\x{9E76}\x{9E77}\x{9E79}\x{9E7A}\x{9E7C}\x{9E7D}\x{9E7E}\x{9E7F}\x{9E80}' . + '\x{9E81}\x{9E82}\x{9E83}\x{9E84}\x{9E85}\x{9E86}\x{9E87}\x{9E88}\x{9E89}' . + '\x{9E8A}\x{9E8B}\x{9E8C}\x{9E8D}\x{9E8E}\x{9E91}\x{9E92}\x{9E93}\x{9E94}' . + '\x{9E96}\x{9E97}\x{9E99}\x{9E9A}\x{9E9B}\x{9E9C}\x{9E9D}\x{9E9F}\x{9EA0}' . + '\x{9EA1}\x{9EA3}\x{9EA4}\x{9EA5}\x{9EA6}\x{9EA7}\x{9EA8}\x{9EA9}\x{9EAA}' . + '\x{9EAD}\x{9EAE}\x{9EAF}\x{9EB0}\x{9EB2}\x{9EB3}\x{9EB4}\x{9EB5}\x{9EB6}' . + '\x{9EB7}\x{9EB8}\x{9EBB}\x{9EBC}\x{9EBD}\x{9EBE}\x{9EBF}\x{9EC0}\x{9EC1}' . + '\x{9EC2}\x{9EC3}\x{9EC4}\x{9EC5}\x{9EC6}\x{9EC7}\x{9EC8}\x{9EC9}\x{9ECA}' . + '\x{9ECB}\x{9ECC}\x{9ECD}\x{9ECE}\x{9ECF}\x{9ED0}\x{9ED1}\x{9ED2}\x{9ED3}' . + '\x{9ED4}\x{9ED5}\x{9ED6}\x{9ED7}\x{9ED8}\x{9ED9}\x{9EDA}\x{9EDB}\x{9EDC}' . + '\x{9EDD}\x{9EDE}\x{9EDF}\x{9EE0}\x{9EE1}\x{9EE2}\x{9EE3}\x{9EE4}\x{9EE5}' . + '\x{9EE6}\x{9EE7}\x{9EE8}\x{9EE9}\x{9EEA}\x{9EEB}\x{9EED}\x{9EEE}\x{9EEF}' . + '\x{9EF0}\x{9EF2}\x{9EF3}\x{9EF4}\x{9EF5}\x{9EF6}\x{9EF7}\x{9EF8}\x{9EF9}' . + '\x{9EFA}\x{9EFB}\x{9EFC}\x{9EFD}\x{9EFE}\x{9EFF}\x{9F00}\x{9F01}\x{9F02}' . + '\x{9F04}\x{9F05}\x{9F06}\x{9F07}\x{9F08}\x{9F09}\x{9F0A}\x{9F0B}\x{9F0C}' . + '\x{9F0D}\x{9F0E}\x{9F0F}\x{9F10}\x{9F12}\x{9F13}\x{9F15}\x{9F16}\x{9F17}' . + '\x{9F18}\x{9F19}\x{9F1A}\x{9F1B}\x{9F1C}\x{9F1D}\x{9F1E}\x{9F1F}\x{9F20}' . + '\x{9F22}\x{9F23}\x{9F24}\x{9F25}\x{9F27}\x{9F28}\x{9F29}\x{9F2A}\x{9F2B}' . + '\x{9F2C}\x{9F2D}\x{9F2E}\x{9F2F}\x{9F30}\x{9F31}\x{9F32}\x{9F33}\x{9F34}' . + '\x{9F35}\x{9F36}\x{9F37}\x{9F38}\x{9F39}\x{9F3A}\x{9F3B}\x{9F3C}\x{9F3D}' . + '\x{9F3E}\x{9F3F}\x{9F40}\x{9F41}\x{9F42}\x{9F43}\x{9F44}\x{9F46}\x{9F47}' . + '\x{9F48}\x{9F49}\x{9F4A}\x{9F4B}\x{9F4C}\x{9F4D}\x{9F4E}\x{9F4F}\x{9F50}' . + '\x{9F51}\x{9F52}\x{9F54}\x{9F55}\x{9F56}\x{9F57}\x{9F58}\x{9F59}\x{9F5A}' . + '\x{9F5B}\x{9F5C}\x{9F5D}\x{9F5E}\x{9F5F}\x{9F60}\x{9F61}\x{9F63}\x{9F64}' . + '\x{9F65}\x{9F66}\x{9F67}\x{9F68}\x{9F69}\x{9F6A}\x{9F6B}\x{9F6C}\x{9F6E}' . + '\x{9F6F}\x{9F70}\x{9F71}\x{9F72}\x{9F73}\x{9F74}\x{9F75}\x{9F76}\x{9F77}' . + '\x{9F78}\x{9F79}\x{9F7A}\x{9F7B}\x{9F7C}\x{9F7D}\x{9F7E}\x{9F7F}\x{9F80}' . + '\x{9F81}\x{9F82}\x{9F83}\x{9F84}\x{9F85}\x{9F86}\x{9F87}\x{9F88}\x{9F89}' . + '\x{9F8A}\x{9F8B}\x{9F8C}\x{9F8D}\x{9F8E}\x{9F8F}\x{9F90}\x{9F91}\x{9F92}' . + '\x{9F93}\x{9F94}\x{9F95}\x{9F96}\x{9F97}\x{9F98}\x{9F99}\x{9F9A}\x{9F9B}' . + '\x{9F9C}\x{9F9D}\x{9F9E}\x{9F9F}\x{9FA0}\x{9FA2}\x{9FA4}\x{9FA5}]{1,20}$/iu', +); diff --git a/lib/Zend/Validator/Hostname/Com.php b/lib/Zend/Validator/Hostname/Com.php new file mode 100644 index 0000000000000000000000000000000000000000..8fe41e0164e272723187a4ff6fd6776bdda33df9 --- /dev/null +++ b/lib/Zend/Validator/Hostname/Com.php @@ -0,0 +1,186 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Hostname; + +/** + * Resource file for com and net idn validation + * + * @category Zend + * @package Zend_Validate + */ +return array( + 1 => '/^[\x{002d}0-9\x{0400}-\x{052f}]{1,63}$/iu', + 2 => '/^[\x{002d}0-9\x{0370}-\x{03ff}]{1,63}$/iu', + 3 => '/^[\x{002d}0-9a-z\x{ac00}-\x{d7a3}]{1,17}$/iu', + 4 => '/^[\x{002d}0-9a-z·à -öø-ÿÄăąćĉċÄÄđēĕėęěÄğġģĥħĩīÄįıĵķĸĺļľłńņňŋÅÅőœŕŗřśÅşšţťŧũūÅůűųŵŷźżž]{1,63}$/iu', + 5 => '/^[\x{002d}0-9A-Za-z\x{3400}-\x{3401}\x{3404}-\x{3406}\x{340C}\x{3416}\x{341C}' . +'\x{3421}\x{3424}\x{3428}-\x{3429}\x{342B}-\x{342E}\x{3430}-\x{3434}\x{3436}' . +'\x{3438}-\x{343C}\x{343E}\x{3441}-\x{3445}\x{3447}\x{3449}-\x{3451}\x{3453}' . +'\x{3457}-\x{345F}\x{3463}-\x{3467}\x{346E}-\x{3471}\x{3473}-\x{3477}\x{3479}-\x{348E}\x{3491}-\x{3497}' . +'\x{3499}-\x{34A1}\x{34A4}-\x{34AD}\x{34AF}-\x{34B0}\x{34B2}-\x{34BF}\x{34C2}-\x{34C5}\x{34C7}-\x{34CC}' . +'\x{34CE}-\x{34D1}\x{34D3}-\x{34D8}\x{34DA}-\x{34E4}\x{34E7}-\x{34E9}\x{34EC}-\x{34EF}\x{34F1}-\x{34FE}' . +'\x{3500}-\x{3507}\x{350A}-\x{3513}\x{3515}\x{3517}-\x{351A}\x{351C}-\x{351E}\x{3520}-\x{352A}' . +'\x{352C}-\x{3552}\x{3554}-\x{355C}\x{355E}-\x{3567}\x{3569}-\x{3573}\x{3575}-\x{357C}\x{3580}-\x{3588}' . +'\x{358F}-\x{3598}\x{359E}-\x{35AB}\x{35B4}-\x{35CD}\x{35D0}\x{35D3}-\x{35DC}\x{35E2}-\x{35ED}' . +'\x{35F0}-\x{35F6}\x{35FB}-\x{3602}\x{3605}-\x{360E}\x{3610}-\x{3611}\x{3613}-\x{3616}\x{3619}-\x{362D}' . +'\x{362F}-\x{3634}\x{3636}-\x{363B}\x{363F}-\x{3645}\x{3647}-\x{364B}\x{364D}-\x{3653}\x{3655}' . +'\x{3659}-\x{365E}\x{3660}-\x{3665}\x{3667}-\x{367C}\x{367E}\x{3680}-\x{3685}\x{3687}' . +'\x{3689}-\x{3690}\x{3692}-\x{3698}\x{369A}\x{369C}-\x{36AE}\x{36B0}-\x{36BF}\x{36C1}-\x{36C5}' . +'\x{36C9}-\x{36CA}\x{36CD}-\x{36DE}\x{36E1}-\x{36E2}\x{36E5}-\x{36FE}\x{3701}-\x{3713}\x{3715}-\x{371E}' . +'\x{3720}-\x{372C}\x{372E}-\x{3745}\x{3747}-\x{3748}\x{374A}\x{374C}-\x{3759}\x{375B}-\x{3760}' . +'\x{3762}-\x{3767}\x{3769}-\x{3772}\x{3774}-\x{378C}\x{378F}-\x{379C}\x{379F}\x{37A1}-\x{37AD}' . +'\x{37AF}-\x{37B7}\x{37B9}-\x{37C1}\x{37C3}-\x{37C5}\x{37C7}-\x{37D4}\x{37D6}-\x{37E0}\x{37E2}' . +'\x{37E5}-\x{37ED}\x{37EF}-\x{37F6}\x{37F8}-\x{3802}\x{3804}-\x{381D}\x{3820}-\x{3822}\x{3825}-\x{382A}' . +'\x{382D}-\x{382F}\x{3831}-\x{3832}\x{3834}-\x{384C}\x{384E}-\x{3860}\x{3862}-\x{3863}\x{3865}-\x{386B}' . +'\x{386D}-\x{3886}\x{3888}-\x{38A1}\x{38A3}\x{38A5}-\x{38AA}\x{38AC}\x{38AE}-\x{38B0}' . +'\x{38B2}-\x{38B6}\x{38B8}\x{38BA}-\x{38BE}\x{38C0}-\x{38C9}\x{38CB}-\x{38D4}\x{38D8}-\x{38E0}' . +'\x{38E2}-\x{38E6}\x{38EB}-\x{38ED}\x{38EF}-\x{38F2}\x{38F5}-\x{38F7}\x{38FA}-\x{38FF}\x{3901}-\x{392A}' . +'\x{392C}\x{392E}-\x{393B}\x{393E}-\x{3956}\x{395A}-\x{3969}\x{396B}-\x{397A}\x{397C}-\x{3987}' . +'\x{3989}-\x{3998}\x{399A}-\x{39B0}\x{39B2}\x{39B4}-\x{39D0}\x{39D2}-\x{39DA}\x{39DE}-\x{39DF}' . +'\x{39E1}-\x{39EF}\x{39F1}-\x{3A17}\x{3A19}-\x{3A2A}\x{3A2D}-\x{3A40}\x{3A43}-\x{3A4E}\x{3A50}' . +'\x{3A52}-\x{3A5E}\x{3A60}-\x{3A6D}\x{3A6F}-\x{3A77}\x{3A79}-\x{3A82}\x{3A84}-\x{3A85}\x{3A87}-\x{3A89}' . +'\x{3A8B}-\x{3A8F}\x{3A91}-\x{3A93}\x{3A95}-\x{3A96}\x{3A9A}\x{3A9C}-\x{3AA6}\x{3AA8}-\x{3AA9}' . +'\x{3AAB}-\x{3AB1}\x{3AB4}-\x{3ABC}\x{3ABE}-\x{3AC5}\x{3ACA}-\x{3ACB}\x{3ACD}-\x{3AD5}\x{3AD7}-\x{3AE1}' . +'\x{3AE4}-\x{3AE7}\x{3AE9}-\x{3AEC}\x{3AEE}-\x{3AFD}\x{3B01}-\x{3B10}\x{3B12}-\x{3B15}\x{3B17}-\x{3B1E}' . +'\x{3B20}-\x{3B23}\x{3B25}-\x{3B27}\x{3B29}-\x{3B36}\x{3B38}-\x{3B39}\x{3B3B}-\x{3B3C}\x{3B3F}' . +'\x{3B41}-\x{3B44}\x{3B47}-\x{3B4C}\x{3B4E}\x{3B51}-\x{3B55}\x{3B58}-\x{3B62}\x{3B68}-\x{3B72}' . +'\x{3B78}-\x{3B88}\x{3B8B}-\x{3B9F}\x{3BA1}\x{3BA3}-\x{3BBA}\x{3BBC}\x{3BBF}-\x{3BD0}' . +'\x{3BD3}-\x{3BE6}\x{3BEA}-\x{3BFB}\x{3BFE}-\x{3C12}\x{3C14}-\x{3C1B}\x{3C1D}-\x{3C37}\x{3C39}-\x{3C4F}' . +'\x{3C52}\x{3C54}-\x{3C5C}\x{3C5E}-\x{3C68}\x{3C6A}-\x{3C76}\x{3C78}-\x{3C8F}\x{3C91}-\x{3CA8}' . +'\x{3CAA}-\x{3CAD}\x{3CAF}-\x{3CBE}\x{3CC0}-\x{3CC8}\x{3CCA}-\x{3CD3}\x{3CD6}-\x{3CE0}\x{3CE4}-\x{3CEE}' . +'\x{3CF3}-\x{3D0A}\x{3D0E}-\x{3D1E}\x{3D20}-\x{3D21}\x{3D25}-\x{3D38}\x{3D3B}-\x{3D46}\x{3D4A}-\x{3D59}' . +'\x{3D5D}-\x{3D7B}\x{3D7D}-\x{3D81}\x{3D84}-\x{3D88}\x{3D8C}-\x{3D8F}\x{3D91}-\x{3D98}\x{3D9A}-\x{3D9C}' . +'\x{3D9E}-\x{3DA1}\x{3DA3}-\x{3DB0}\x{3DB2}-\x{3DB5}\x{3DB9}-\x{3DBC}\x{3DBE}-\x{3DCB}\x{3DCD}-\x{3DDB}' . +'\x{3DDF}-\x{3DE8}\x{3DEB}-\x{3DF0}\x{3DF3}-\x{3DF9}\x{3DFB}-\x{3DFC}\x{3DFE}-\x{3E05}\x{3E08}-\x{3E33}' . +'\x{3E35}-\x{3E3E}\x{3E40}-\x{3E47}\x{3E49}-\x{3E67}\x{3E6B}-\x{3E6F}\x{3E71}-\x{3E85}\x{3E87}-\x{3E8C}' . +'\x{3E8E}-\x{3E98}\x{3E9A}-\x{3EA1}\x{3EA3}-\x{3EAE}\x{3EB0}-\x{3EB5}\x{3EB7}-\x{3EBA}\x{3EBD}' . +'\x{3EBF}-\x{3EC4}\x{3EC7}-\x{3ECE}\x{3ED1}-\x{3ED7}\x{3ED9}-\x{3EDA}\x{3EDD}-\x{3EE3}\x{3EE7}-\x{3EE8}' . +'\x{3EEB}-\x{3EF2}\x{3EF5}-\x{3EFF}\x{3F01}-\x{3F02}\x{3F04}-\x{3F07}\x{3F09}-\x{3F44}\x{3F46}-\x{3F4E}' . +'\x{3F50}-\x{3F53}\x{3F55}-\x{3F72}\x{3F74}-\x{3F75}\x{3F77}-\x{3F7B}\x{3F7D}-\x{3FB0}\x{3FB6}-\x{3FBF}' . +'\x{3FC1}-\x{3FCF}\x{3FD1}-\x{3FD3}\x{3FD5}-\x{3FDF}\x{3FE1}-\x{400B}\x{400D}-\x{401C}\x{401E}-\x{4024}' . +'\x{4027}-\x{403F}\x{4041}-\x{4060}\x{4062}-\x{4069}\x{406B}-\x{408A}\x{408C}-\x{40A7}\x{40A9}-\x{40B4}' . +'\x{40B6}-\x{40C2}\x{40C7}-\x{40CF}\x{40D1}-\x{40DE}\x{40E0}-\x{40E7}\x{40E9}-\x{40EE}\x{40F0}-\x{40FB}' . +'\x{40FD}-\x{4109}\x{410B}-\x{4115}\x{4118}-\x{411D}\x{411F}-\x{4122}\x{4124}-\x{4133}\x{4136}-\x{4138}' . +'\x{413A}-\x{4148}\x{414A}-\x{4169}\x{416C}-\x{4185}\x{4188}-\x{418B}\x{418D}-\x{41AD}\x{41AF}-\x{41B3}' . +'\x{41B5}-\x{41C3}\x{41C5}-\x{41C9}\x{41CB}-\x{41F2}\x{41F5}-\x{41FE}\x{4200}-\x{4227}\x{422A}-\x{4246}' . +'\x{4248}-\x{4263}\x{4265}-\x{428B}\x{428D}-\x{42A1}\x{42A3}-\x{42C4}\x{42C8}-\x{42DC}\x{42DE}-\x{430A}' . +'\x{430C}-\x{4335}\x{4337}\x{4342}-\x{435F}\x{4361}-\x{439A}\x{439C}-\x{439D}\x{439F}-\x{43A4}' . +'\x{43A6}-\x{43EC}\x{43EF}-\x{4405}\x{4407}-\x{4429}\x{442B}-\x{4455}\x{4457}-\x{4468}\x{446A}-\x{446D}' . +'\x{446F}-\x{4476}\x{4479}-\x{447D}\x{447F}-\x{4486}\x{4488}-\x{4490}\x{4492}-\x{4498}\x{449A}-\x{44AD}' . +'\x{44B0}-\x{44BD}\x{44C1}-\x{44D3}\x{44D6}-\x{44E7}\x{44EA}\x{44EC}-\x{44FA}\x{44FC}-\x{4541}' . +'\x{4543}-\x{454F}\x{4551}-\x{4562}\x{4564}-\x{4575}\x{4577}-\x{45AB}\x{45AD}-\x{45BD}\x{45BF}-\x{45D5}' . +'\x{45D7}-\x{45EC}\x{45EE}-\x{45F2}\x{45F4}-\x{45FA}\x{45FC}-\x{461A}\x{461C}-\x{461D}\x{461F}-\x{4631}' . +'\x{4633}-\x{4649}\x{464C}\x{464E}-\x{4652}\x{4654}-\x{466A}\x{466C}-\x{4675}\x{4677}-\x{467A}' . +'\x{467C}-\x{4694}\x{4696}-\x{46A3}\x{46A5}-\x{46AB}\x{46AD}-\x{46D2}\x{46D4}-\x{4723}\x{4729}-\x{4732}' . +'\x{4734}-\x{4758}\x{475A}\x{475C}-\x{478B}\x{478D}\x{4791}-\x{47B1}\x{47B3}-\x{47F1}' . +'\x{47F3}-\x{480B}\x{480D}-\x{4815}\x{4817}-\x{4839}\x{483B}-\x{4870}\x{4872}-\x{487A}\x{487C}-\x{487F}' . +'\x{4883}-\x{488E}\x{4890}-\x{4896}\x{4899}-\x{48A2}\x{48A4}-\x{48B9}\x{48BB}-\x{48C8}\x{48CA}-\x{48D1}' . +'\x{48D3}-\x{48E5}\x{48E7}-\x{48F2}\x{48F4}-\x{48FF}\x{4901}-\x{4922}\x{4924}-\x{4928}\x{492A}-\x{4931}' . +'\x{4933}-\x{495B}\x{495D}-\x{4978}\x{497A}\x{497D}\x{4982}-\x{4983}\x{4985}-\x{49A8}' . +'\x{49AA}-\x{49AF}\x{49B1}-\x{49B7}\x{49B9}-\x{49BD}\x{49C1}-\x{49C7}\x{49C9}-\x{49CE}\x{49D0}-\x{49E8}' . +'\x{49EA}\x{49EC}\x{49EE}-\x{4A19}\x{4A1B}-\x{4A43}\x{4A45}-\x{4A4D}\x{4A4F}-\x{4A9E}' . +'\x{4AA0}-\x{4AA9}\x{4AAB}-\x{4B4E}\x{4B50}-\x{4B5B}\x{4B5D}-\x{4B69}\x{4B6B}-\x{4BC2}\x{4BC6}-\x{4BE8}' . +'\x{4BEA}-\x{4BFA}\x{4BFC}-\x{4C06}\x{4C08}-\x{4C2D}\x{4C2F}-\x{4C32}\x{4C34}-\x{4C35}\x{4C37}-\x{4C69}' . +'\x{4C6B}-\x{4C73}\x{4C75}-\x{4C86}\x{4C88}-\x{4C97}\x{4C99}-\x{4C9C}\x{4C9F}-\x{4CA3}\x{4CA5}-\x{4CB5}' . +'\x{4CB7}-\x{4CF8}\x{4CFA}-\x{4D27}\x{4D29}-\x{4DAC}\x{4DAE}-\x{4DB1}\x{4DB3}-\x{4DB5}\x{4E00}-\x{4E54}' . +'\x{4E56}-\x{4E89}\x{4E8B}-\x{4EEC}\x{4EEE}-\x{4FAC}\x{4FAE}-\x{503C}\x{503E}-\x{51E5}\x{51E7}-\x{5270}' . +'\x{5272}-\x{56A1}\x{56A3}-\x{5840}\x{5842}-\x{58B5}\x{58B7}-\x{58CB}\x{58CD}-\x{5BC8}\x{5BCA}-\x{5C01}' . +'\x{5C03}-\x{5C25}\x{5C27}-\x{5D5B}\x{5D5D}-\x{5F08}\x{5F0A}-\x{61F3}\x{61F5}-\x{63BA}\x{63BC}-\x{6441}' . +'\x{6443}-\x{657C}\x{657E}-\x{663E}\x{6640}-\x{66FC}\x{66FE}-\x{6728}\x{672A}-\x{6766}\x{6768}-\x{67A8}' . +'\x{67AA}-\x{685B}\x{685D}-\x{685E}\x{6860}-\x{68B9}\x{68BB}-\x{6AC8}\x{6ACA}-\x{6BB0}\x{6BB2}-\x{6C16}' . +'\x{6C18}-\x{6D9B}\x{6D9D}-\x{6E12}\x{6E14}-\x{6E8B}\x{6E8D}-\x{704D}\x{704F}-\x{7113}\x{7115}-\x{713B}' . +'\x{713D}-\x{7154}\x{7156}-\x{729F}\x{72A1}-\x{731E}\x{7320}-\x{7362}\x{7364}-\x{7533}\x{7535}-\x{7551}' . +'\x{7553}-\x{7572}\x{7574}-\x{75E8}\x{75EA}-\x{7679}\x{767B}-\x{783E}\x{7840}-\x{7A62}\x{7A64}-\x{7AC2}' . +'\x{7AC4}-\x{7B06}\x{7B08}-\x{7B79}\x{7B7B}-\x{7BCE}\x{7BD0}-\x{7D99}\x{7D9B}-\x{7E49}\x{7E4C}-\x{8132}' . +'\x{8134}\x{8136}-\x{81D2}\x{81D4}-\x{8216}\x{8218}-\x{822D}\x{822F}-\x{83B4}\x{83B6}-\x{841F}' . +'\x{8421}-\x{86CC}\x{86CE}-\x{874A}\x{874C}-\x{877E}\x{8780}-\x{8A32}\x{8A34}-\x{8B71}\x{8B73}-\x{8B8E}' . +'\x{8B90}-\x{8DE4}\x{8DE6}-\x{8E9A}\x{8E9C}-\x{8EE1}\x{8EE4}-\x{8F0B}\x{8F0D}-\x{8FB9}\x{8FBB}-\x{9038}' . +'\x{903A}-\x{9196}\x{9198}-\x{91A3}\x{91A5}-\x{91B7}\x{91B9}-\x{91C7}\x{91C9}-\x{91E0}\x{91E2}-\x{91FB}' . +'\x{91FD}-\x{922B}\x{922D}-\x{9270}\x{9272}-\x{9420}\x{9422}-\x{9664}\x{9666}-\x{9679}\x{967B}-\x{9770}' . +'\x{9772}-\x{982B}\x{982D}-\x{98ED}\x{98EF}-\x{99C4}\x{99C6}-\x{9A11}\x{9A14}-\x{9A27}\x{9A29}-\x{9D0D}' . +'\x{9D0F}-\x{9D2B}\x{9D2D}-\x{9D8E}\x{9D90}-\x{9DC5}\x{9DC7}-\x{9E77}\x{9E79}-\x{9EB8}\x{9EBB}-\x{9F20}' . +'\x{9F22}-\x{9F61}\x{9F63}-\x{9FA5}\x{FA28}]{1,20}$/iu', + 6 => '/^[\x{002d}0-9A-Za-z]{1,63}$/iu', + 7 => '/^[\x{00A1}-\x{00FF}]{1,63}$/iu', + 8 => '/^[\x{0100}-\x{017f}]{1,63}$/iu', + 9 => '/^[\x{0180}-\x{024f}]{1,63}$/iu', + 10 => '/^[\x{0250}-\x{02af}]{1,63}$/iu', + 11 => '/^[\x{02b0}-\x{02ff}]{1,63}$/iu', + 12 => '/^[\x{0300}-\x{036f}]{1,63}$/iu', + 13 => '/^[\x{0370}-\x{03ff}]{1,63}$/iu', + 14 => '/^[\x{0400}-\x{04ff}]{1,63}$/iu', + 15 => '/^[\x{0500}-\x{052f}]{1,63}$/iu', + 16 => '/^[\x{0530}-\x{058F}]{1,63}$/iu', + 17 => '/^[\x{0590}-\x{05FF}]{1,63}$/iu', + 18 => '/^[\x{0600}-\x{06FF}]{1,63}$/iu', + 19 => '/^[\x{0700}-\x{074F}]{1,63}$/iu', + 20 => '/^[\x{0780}-\x{07BF}]{1,63}$/iu', + 21 => '/^[\x{0900}-\x{097F}]{1,63}$/iu', + 22 => '/^[\x{0980}-\x{09FF}]{1,63}$/iu', + 23 => '/^[\x{0A00}-\x{0A7F}]{1,63}$/iu', + 24 => '/^[\x{0A80}-\x{0AFF}]{1,63}$/iu', + 25 => '/^[\x{0B00}-\x{0B7F}]{1,63}$/iu', + 26 => '/^[\x{0B80}-\x{0BFF}]{1,63}$/iu', + 27 => '/^[\x{0C00}-\x{0C7F}]{1,63}$/iu', + 28 => '/^[\x{0C80}-\x{0CFF}]{1,63}$/iu', + 29 => '/^[\x{0D00}-\x{0D7F}]{1,63}$/iu', + 30 => '/^[\x{0D80}-\x{0DFF}]{1,63}$/iu', + 31 => '/^[\x{0E00}-\x{0E7F}]{1,63}$/iu', + 32 => '/^[\x{0E80}-\x{0EFF}]{1,63}$/iu', + 33 => '/^[\x{0F00}-\x{0FFF}]{1,63}$/iu', + 34 => '/^[\x{1000}-\x{109F}]{1,63}$/iu', + 35 => '/^[\x{10A0}-\x{10FF}]{1,63}$/iu', + 36 => '/^[\x{1100}-\x{11FF}]{1,63}$/iu', + 37 => '/^[\x{1200}-\x{137F}]{1,63}$/iu', + 38 => '/^[\x{13A0}-\x{13FF}]{1,63}$/iu', + 39 => '/^[\x{1400}-\x{167F}]{1,63}$/iu', + 40 => '/^[\x{1680}-\x{169F}]{1,63}$/iu', + 41 => '/^[\x{16A0}-\x{16FF}]{1,63}$/iu', + 42 => '/^[\x{1700}-\x{171F}]{1,63}$/iu', + 43 => '/^[\x{1720}-\x{173F}]{1,63}$/iu', + 44 => '/^[\x{1740}-\x{175F}]{1,63}$/iu', + 45 => '/^[\x{1760}-\x{177F}]{1,63}$/iu', + 46 => '/^[\x{1780}-\x{17FF}]{1,63}$/iu', + 47 => '/^[\x{1800}-\x{18AF}]{1,63}$/iu', + 48 => '/^[\x{1E00}-\x{1EFF}]{1,63}$/iu', + 49 => '/^[\x{1F00}-\x{1FFF}]{1,63}$/iu', + 50 => '/^[\x{2070}-\x{209F}]{1,63}$/iu', + 51 => '/^[\x{2100}-\x{214F}]{1,63}$/iu', + 52 => '/^[\x{2150}-\x{218F}]{1,63}$/iu', + 53 => '/^[\x{2460}-\x{24FF}]{1,63}$/iu', + 54 => '/^[\x{2E80}-\x{2EFF}]{1,63}$/iu', + 55 => '/^[\x{2F00}-\x{2FDF}]{1,63}$/iu', + 56 => '/^[\x{2FF0}-\x{2FFF}]{1,63}$/iu', + 57 => '/^[\x{3040}-\x{309F}]{1,63}$/iu', + 58 => '/^[\x{30A0}-\x{30FF}]{1,63}$/iu', + 59 => '/^[\x{3100}-\x{312F}]{1,63}$/iu', + 60 => '/^[\x{3130}-\x{318F}]{1,63}$/iu', + 61 => '/^[\x{3190}-\x{319F}]{1,63}$/iu', + 62 => '/^[\x{31A0}-\x{31BF}]{1,63}$/iu', + 63 => '/^[\x{31F0}-\x{31FF}]{1,63}$/iu', + 64 => '/^[\x{3200}-\x{32FF}]{1,63}$/iu', + 65 => '/^[\x{3300}-\x{33FF}]{1,63}$/iu', + 66 => '/^[\x{3400}-\x{4DBF}]{1,63}$/iu', + 67 => '/^[\x{4E00}-\x{9FFF}]{1,63}$/iu', + 68 => '/^[\x{A000}-\x{A48F}]{1,63}$/iu', + 69 => '/^[\x{A490}-\x{A4CF}]{1,63}$/iu', + 70 => '/^[\x{AC00}-\x{D7AF}]{1,63}$/iu', + 71 => '/^[\x{D800}-\x{DB7F}]{1,63}$/iu', + 72 => '/^[\x{DC00}-\x{DFFF}]{1,63}$/iu', + 73 => '/^[\x{F900}-\x{FAFF}]{1,63}$/iu', + 74 => '/^[\x{FB00}-\x{FB4F}]{1,63}$/iu', + 75 => '/^[\x{FB50}-\x{FDFF}]{1,63}$/iu', + 76 => '/^[\x{FE20}-\x{FE2F}]{1,63}$/iu', + 77 => '/^[\x{FE70}-\x{FEFF}]{1,63}$/iu', + 78 => '/^[\x{FF00}-\x{FFEF}]{1,63}$/iu', + 79 => '/^[\x{20000}-\x{2A6DF}]{1,63}$/iu', + 80 => '/^[\x{2F800}-\x{2FA1F}]{1,63}$/iu', +); diff --git a/lib/Zend/Validator/Hostname/Jp.php b/lib/Zend/Validator/Hostname/Jp.php new file mode 100644 index 0000000000000000000000000000000000000000..50a4856dbceb5373058ebd649434fd9ca62c39d8 --- /dev/null +++ b/lib/Zend/Validator/Hostname/Jp.php @@ -0,0 +1,729 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Hostname; + +/** + * Resource file for japanese idn validation + * + * @category Zend + * @package Zend_Validate + */ +return array( + 1 => '/^[\x{002d}0-9a-z\x{3005}-\x{3007}\x{3041}-\x{3093}\x{309D}\x{309E}' . + '\x{30A1}-\x{30F6}\x{30FC}' . + '\x{30FD}\x{30FE}\x{4E00}\x{4E01}\x{4E03}\x{4E07}\x{4E08}\x{4E09}\x{4E0A}' . + '\x{4E0B}\x{4E0D}\x{4E0E}\x{4E10}\x{4E11}\x{4E14}\x{4E15}\x{4E16}\x{4E17}' . + '\x{4E18}\x{4E19}\x{4E1E}\x{4E21}\x{4E26}\x{4E2A}\x{4E2D}\x{4E31}\x{4E32}' . + '\x{4E36}\x{4E38}\x{4E39}\x{4E3B}\x{4E3C}\x{4E3F}\x{4E42}\x{4E43}\x{4E45}' . + '\x{4E4B}\x{4E4D}\x{4E4E}\x{4E4F}\x{4E55}\x{4E56}\x{4E57}\x{4E58}\x{4E59}' . + '\x{4E5D}\x{4E5E}\x{4E5F}\x{4E62}\x{4E71}\x{4E73}\x{4E7E}\x{4E80}\x{4E82}' . + '\x{4E85}\x{4E86}\x{4E88}\x{4E89}\x{4E8A}\x{4E8B}\x{4E8C}\x{4E8E}\x{4E91}' . + '\x{4E92}\x{4E94}\x{4E95}\x{4E98}\x{4E99}\x{4E9B}\x{4E9C}\x{4E9E}\x{4E9F}' . + '\x{4EA0}\x{4EA1}\x{4EA2}\x{4EA4}\x{4EA5}\x{4EA6}\x{4EA8}\x{4EAB}\x{4EAC}' . + '\x{4EAD}\x{4EAE}\x{4EB0}\x{4EB3}\x{4EB6}\x{4EBA}\x{4EC0}\x{4EC1}\x{4EC2}' . + '\x{4EC4}\x{4EC6}\x{4EC7}\x{4ECA}\x{4ECB}\x{4ECD}\x{4ECE}\x{4ECF}\x{4ED4}' . + '\x{4ED5}\x{4ED6}\x{4ED7}\x{4ED8}\x{4ED9}\x{4EDD}\x{4EDE}\x{4EDF}\x{4EE3}' . + '\x{4EE4}\x{4EE5}\x{4EED}\x{4EEE}\x{4EF0}\x{4EF2}\x{4EF6}\x{4EF7}\x{4EFB}' . + '\x{4F01}\x{4F09}\x{4F0A}\x{4F0D}\x{4F0E}\x{4F0F}\x{4F10}\x{4F11}\x{4F1A}' . + '\x{4F1C}\x{4F1D}\x{4F2F}\x{4F30}\x{4F34}\x{4F36}\x{4F38}\x{4F3A}\x{4F3C}' . + '\x{4F3D}\x{4F43}\x{4F46}\x{4F47}\x{4F4D}\x{4F4E}\x{4F4F}\x{4F50}\x{4F51}' . + '\x{4F53}\x{4F55}\x{4F57}\x{4F59}\x{4F5A}\x{4F5B}\x{4F5C}\x{4F5D}\x{4F5E}' . + '\x{4F69}\x{4F6F}\x{4F70}\x{4F73}\x{4F75}\x{4F76}\x{4F7B}\x{4F7C}\x{4F7F}' . + '\x{4F83}\x{4F86}\x{4F88}\x{4F8B}\x{4F8D}\x{4F8F}\x{4F91}\x{4F96}\x{4F98}' . + '\x{4F9B}\x{4F9D}\x{4FA0}\x{4FA1}\x{4FAB}\x{4FAD}\x{4FAE}\x{4FAF}\x{4FB5}' . + '\x{4FB6}\x{4FBF}\x{4FC2}\x{4FC3}\x{4FC4}\x{4FCA}\x{4FCE}\x{4FD0}\x{4FD1}' . + '\x{4FD4}\x{4FD7}\x{4FD8}\x{4FDA}\x{4FDB}\x{4FDD}\x{4FDF}\x{4FE1}\x{4FE3}' . + '\x{4FE4}\x{4FE5}\x{4FEE}\x{4FEF}\x{4FF3}\x{4FF5}\x{4FF6}\x{4FF8}\x{4FFA}' . + '\x{4FFE}\x{5005}\x{5006}\x{5009}\x{500B}\x{500D}\x{500F}\x{5011}\x{5012}' . + '\x{5014}\x{5016}\x{5019}\x{501A}\x{501F}\x{5021}\x{5023}\x{5024}\x{5025}' . + '\x{5026}\x{5028}\x{5029}\x{502A}\x{502B}\x{502C}\x{502D}\x{5036}\x{5039}' . + '\x{5043}\x{5047}\x{5048}\x{5049}\x{504F}\x{5050}\x{5055}\x{5056}\x{505A}' . + '\x{505C}\x{5065}\x{506C}\x{5072}\x{5074}\x{5075}\x{5076}\x{5078}\x{507D}' . + '\x{5080}\x{5085}\x{508D}\x{5091}\x{5098}\x{5099}\x{509A}\x{50AC}\x{50AD}' . + '\x{50B2}\x{50B3}\x{50B4}\x{50B5}\x{50B7}\x{50BE}\x{50C2}\x{50C5}\x{50C9}' . + '\x{50CA}\x{50CD}\x{50CF}\x{50D1}\x{50D5}\x{50D6}\x{50DA}\x{50DE}\x{50E3}' . + '\x{50E5}\x{50E7}\x{50ED}\x{50EE}\x{50F5}\x{50F9}\x{50FB}\x{5100}\x{5101}' . + '\x{5102}\x{5104}\x{5109}\x{5112}\x{5114}\x{5115}\x{5116}\x{5118}\x{511A}' . + '\x{511F}\x{5121}\x{512A}\x{5132}\x{5137}\x{513A}\x{513B}\x{513C}\x{513F}' . + '\x{5140}\x{5141}\x{5143}\x{5144}\x{5145}\x{5146}\x{5147}\x{5148}\x{5149}' . + '\x{514B}\x{514C}\x{514D}\x{514E}\x{5150}\x{5152}\x{5154}\x{515A}\x{515C}' . + '\x{5162}\x{5165}\x{5168}\x{5169}\x{516A}\x{516B}\x{516C}\x{516D}\x{516E}' . + '\x{5171}\x{5175}\x{5176}\x{5177}\x{5178}\x{517C}\x{5180}\x{5182}\x{5185}' . + '\x{5186}\x{5189}\x{518A}\x{518C}\x{518D}\x{518F}\x{5190}\x{5191}\x{5192}' . + '\x{5193}\x{5195}\x{5196}\x{5197}\x{5199}\x{51A0}\x{51A2}\x{51A4}\x{51A5}' . + '\x{51A6}\x{51A8}\x{51A9}\x{51AA}\x{51AB}\x{51AC}\x{51B0}\x{51B1}\x{51B2}' . + '\x{51B3}\x{51B4}\x{51B5}\x{51B6}\x{51B7}\x{51BD}\x{51C4}\x{51C5}\x{51C6}' . + '\x{51C9}\x{51CB}\x{51CC}\x{51CD}\x{51D6}\x{51DB}\x{51DC}\x{51DD}\x{51E0}' . + '\x{51E1}\x{51E6}\x{51E7}\x{51E9}\x{51EA}\x{51ED}\x{51F0}\x{51F1}\x{51F5}' . + '\x{51F6}\x{51F8}\x{51F9}\x{51FA}\x{51FD}\x{51FE}\x{5200}\x{5203}\x{5204}' . + '\x{5206}\x{5207}\x{5208}\x{520A}\x{520B}\x{520E}\x{5211}\x{5214}\x{5217}' . + '\x{521D}\x{5224}\x{5225}\x{5227}\x{5229}\x{522A}\x{522E}\x{5230}\x{5233}' . + '\x{5236}\x{5237}\x{5238}\x{5239}\x{523A}\x{523B}\x{5243}\x{5244}\x{5247}' . + '\x{524A}\x{524B}\x{524C}\x{524D}\x{524F}\x{5254}\x{5256}\x{525B}\x{525E}' . + '\x{5263}\x{5264}\x{5265}\x{5269}\x{526A}\x{526F}\x{5270}\x{5271}\x{5272}' . + '\x{5273}\x{5274}\x{5275}\x{527D}\x{527F}\x{5283}\x{5287}\x{5288}\x{5289}' . + '\x{528D}\x{5291}\x{5292}\x{5294}\x{529B}\x{529F}\x{52A0}\x{52A3}\x{52A9}' . + '\x{52AA}\x{52AB}\x{52AC}\x{52AD}\x{52B1}\x{52B4}\x{52B5}\x{52B9}\x{52BC}' . + '\x{52BE}\x{52C1}\x{52C3}\x{52C5}\x{52C7}\x{52C9}\x{52CD}\x{52D2}\x{52D5}' . + '\x{52D7}\x{52D8}\x{52D9}\x{52DD}\x{52DE}\x{52DF}\x{52E0}\x{52E2}\x{52E3}' . + '\x{52E4}\x{52E6}\x{52E7}\x{52F2}\x{52F3}\x{52F5}\x{52F8}\x{52F9}\x{52FA}' . + '\x{52FE}\x{52FF}\x{5301}\x{5302}\x{5305}\x{5306}\x{5308}\x{530D}\x{530F}' . + '\x{5310}\x{5315}\x{5316}\x{5317}\x{5319}\x{531A}\x{531D}\x{5320}\x{5321}' . + '\x{5323}\x{532A}\x{532F}\x{5331}\x{5333}\x{5338}\x{5339}\x{533A}\x{533B}' . + '\x{533F}\x{5340}\x{5341}\x{5343}\x{5345}\x{5346}\x{5347}\x{5348}\x{5349}' . + '\x{534A}\x{534D}\x{5351}\x{5352}\x{5353}\x{5354}\x{5357}\x{5358}\x{535A}' . + '\x{535C}\x{535E}\x{5360}\x{5366}\x{5369}\x{536E}\x{536F}\x{5370}\x{5371}' . + '\x{5373}\x{5374}\x{5375}\x{5377}\x{5378}\x{537B}\x{537F}\x{5382}\x{5384}' . + '\x{5396}\x{5398}\x{539A}\x{539F}\x{53A0}\x{53A5}\x{53A6}\x{53A8}\x{53A9}' . + '\x{53AD}\x{53AE}\x{53B0}\x{53B3}\x{53B6}\x{53BB}\x{53C2}\x{53C3}\x{53C8}' . + '\x{53C9}\x{53CA}\x{53CB}\x{53CC}\x{53CD}\x{53CE}\x{53D4}\x{53D6}\x{53D7}' . + '\x{53D9}\x{53DB}\x{53DF}\x{53E1}\x{53E2}\x{53E3}\x{53E4}\x{53E5}\x{53E8}' . + '\x{53E9}\x{53EA}\x{53EB}\x{53EC}\x{53ED}\x{53EE}\x{53EF}\x{53F0}\x{53F1}' . + '\x{53F2}\x{53F3}\x{53F6}\x{53F7}\x{53F8}\x{53FA}\x{5401}\x{5403}\x{5404}' . + '\x{5408}\x{5409}\x{540A}\x{540B}\x{540C}\x{540D}\x{540E}\x{540F}\x{5410}' . + '\x{5411}\x{541B}\x{541D}\x{541F}\x{5420}\x{5426}\x{5429}\x{542B}\x{542C}' . + '\x{542D}\x{542E}\x{5436}\x{5438}\x{5439}\x{543B}\x{543C}\x{543D}\x{543E}' . + '\x{5440}\x{5442}\x{5446}\x{5448}\x{5449}\x{544A}\x{544E}\x{5451}\x{545F}' . + '\x{5468}\x{546A}\x{5470}\x{5471}\x{5473}\x{5475}\x{5476}\x{5477}\x{547B}' . + '\x{547C}\x{547D}\x{5480}\x{5484}\x{5486}\x{548B}\x{548C}\x{548E}\x{548F}' . + '\x{5490}\x{5492}\x{54A2}\x{54A4}\x{54A5}\x{54A8}\x{54AB}\x{54AC}\x{54AF}' . + '\x{54B2}\x{54B3}\x{54B8}\x{54BC}\x{54BD}\x{54BE}\x{54C0}\x{54C1}\x{54C2}' . + '\x{54C4}\x{54C7}\x{54C8}\x{54C9}\x{54D8}\x{54E1}\x{54E2}\x{54E5}\x{54E6}' . + '\x{54E8}\x{54E9}\x{54ED}\x{54EE}\x{54F2}\x{54FA}\x{54FD}\x{5504}\x{5506}' . + '\x{5507}\x{550F}\x{5510}\x{5514}\x{5516}\x{552E}\x{552F}\x{5531}\x{5533}' . + '\x{5538}\x{5539}\x{553E}\x{5540}\x{5544}\x{5545}\x{5546}\x{554C}\x{554F}' . + '\x{5553}\x{5556}\x{5557}\x{555C}\x{555D}\x{5563}\x{557B}\x{557C}\x{557E}' . + '\x{5580}\x{5583}\x{5584}\x{5587}\x{5589}\x{558A}\x{558B}\x{5598}\x{5599}' . + '\x{559A}\x{559C}\x{559D}\x{559E}\x{559F}\x{55A7}\x{55A8}\x{55A9}\x{55AA}' . + '\x{55AB}\x{55AC}\x{55AE}\x{55B0}\x{55B6}\x{55C4}\x{55C5}\x{55C7}\x{55D4}' . + '\x{55DA}\x{55DC}\x{55DF}\x{55E3}\x{55E4}\x{55F7}\x{55F9}\x{55FD}\x{55FE}' . + '\x{5606}\x{5609}\x{5614}\x{5616}\x{5617}\x{5618}\x{561B}\x{5629}\x{562F}' . + '\x{5631}\x{5632}\x{5634}\x{5636}\x{5638}\x{5642}\x{564C}\x{564E}\x{5650}' . + '\x{565B}\x{5664}\x{5668}\x{566A}\x{566B}\x{566C}\x{5674}\x{5678}\x{567A}' . + '\x{5680}\x{5686}\x{5687}\x{568A}\x{568F}\x{5694}\x{56A0}\x{56A2}\x{56A5}' . + '\x{56AE}\x{56B4}\x{56B6}\x{56BC}\x{56C0}\x{56C1}\x{56C2}\x{56C3}\x{56C8}' . + '\x{56CE}\x{56D1}\x{56D3}\x{56D7}\x{56D8}\x{56DA}\x{56DB}\x{56DE}\x{56E0}' . + '\x{56E3}\x{56EE}\x{56F0}\x{56F2}\x{56F3}\x{56F9}\x{56FA}\x{56FD}\x{56FF}' . + '\x{5700}\x{5703}\x{5704}\x{5708}\x{5709}\x{570B}\x{570D}\x{570F}\x{5712}' . + '\x{5713}\x{5716}\x{5718}\x{571C}\x{571F}\x{5726}\x{5727}\x{5728}\x{572D}' . + '\x{5730}\x{5737}\x{5738}\x{573B}\x{5740}\x{5742}\x{5747}\x{574A}\x{574E}' . + '\x{574F}\x{5750}\x{5751}\x{5761}\x{5764}\x{5766}\x{5769}\x{576A}\x{577F}' . + '\x{5782}\x{5788}\x{5789}\x{578B}\x{5793}\x{57A0}\x{57A2}\x{57A3}\x{57A4}' . + '\x{57AA}\x{57B0}\x{57B3}\x{57C0}\x{57C3}\x{57C6}\x{57CB}\x{57CE}\x{57D2}' . + '\x{57D3}\x{57D4}\x{57D6}\x{57DC}\x{57DF}\x{57E0}\x{57E3}\x{57F4}\x{57F7}' . + '\x{57F9}\x{57FA}\x{57FC}\x{5800}\x{5802}\x{5805}\x{5806}\x{580A}\x{580B}' . + '\x{5815}\x{5819}\x{581D}\x{5821}\x{5824}\x{582A}\x{582F}\x{5830}\x{5831}' . + '\x{5834}\x{5835}\x{583A}\x{583D}\x{5840}\x{5841}\x{584A}\x{584B}\x{5851}' . + '\x{5852}\x{5854}\x{5857}\x{5858}\x{5859}\x{585A}\x{585E}\x{5862}\x{5869}' . + '\x{586B}\x{5870}\x{5872}\x{5875}\x{5879}\x{587E}\x{5883}\x{5885}\x{5893}' . + '\x{5897}\x{589C}\x{589F}\x{58A8}\x{58AB}\x{58AE}\x{58B3}\x{58B8}\x{58B9}' . + '\x{58BA}\x{58BB}\x{58BE}\x{58C1}\x{58C5}\x{58C7}\x{58CA}\x{58CC}\x{58D1}' . + '\x{58D3}\x{58D5}\x{58D7}\x{58D8}\x{58D9}\x{58DC}\x{58DE}\x{58DF}\x{58E4}' . + '\x{58E5}\x{58EB}\x{58EC}\x{58EE}\x{58EF}\x{58F0}\x{58F1}\x{58F2}\x{58F7}' . + '\x{58F9}\x{58FA}\x{58FB}\x{58FC}\x{58FD}\x{5902}\x{5909}\x{590A}\x{590F}' . + '\x{5910}\x{5915}\x{5916}\x{5918}\x{5919}\x{591A}\x{591B}\x{591C}\x{5922}' . + '\x{5925}\x{5927}\x{5929}\x{592A}\x{592B}\x{592C}\x{592D}\x{592E}\x{5931}' . + '\x{5932}\x{5937}\x{5938}\x{593E}\x{5944}\x{5947}\x{5948}\x{5949}\x{594E}' . + '\x{594F}\x{5950}\x{5951}\x{5954}\x{5955}\x{5957}\x{5958}\x{595A}\x{5960}' . + '\x{5962}\x{5965}\x{5967}\x{5968}\x{5969}\x{596A}\x{596C}\x{596E}\x{5973}' . + '\x{5974}\x{5978}\x{597D}\x{5981}\x{5982}\x{5983}\x{5984}\x{598A}\x{598D}' . + '\x{5993}\x{5996}\x{5999}\x{599B}\x{599D}\x{59A3}\x{59A5}\x{59A8}\x{59AC}' . + '\x{59B2}\x{59B9}\x{59BB}\x{59BE}\x{59C6}\x{59C9}\x{59CB}\x{59D0}\x{59D1}' . + '\x{59D3}\x{59D4}\x{59D9}\x{59DA}\x{59DC}\x{59E5}\x{59E6}\x{59E8}\x{59EA}' . + '\x{59EB}\x{59F6}\x{59FB}\x{59FF}\x{5A01}\x{5A03}\x{5A09}\x{5A11}\x{5A18}' . + '\x{5A1A}\x{5A1C}\x{5A1F}\x{5A20}\x{5A25}\x{5A29}\x{5A2F}\x{5A35}\x{5A36}' . + '\x{5A3C}\x{5A40}\x{5A41}\x{5A46}\x{5A49}\x{5A5A}\x{5A62}\x{5A66}\x{5A6A}' . + '\x{5A6C}\x{5A7F}\x{5A92}\x{5A9A}\x{5A9B}\x{5ABC}\x{5ABD}\x{5ABE}\x{5AC1}' . + '\x{5AC2}\x{5AC9}\x{5ACB}\x{5ACC}\x{5AD0}\x{5AD6}\x{5AD7}\x{5AE1}\x{5AE3}' . + '\x{5AE6}\x{5AE9}\x{5AFA}\x{5AFB}\x{5B09}\x{5B0B}\x{5B0C}\x{5B16}\x{5B22}' . + '\x{5B2A}\x{5B2C}\x{5B30}\x{5B32}\x{5B36}\x{5B3E}\x{5B40}\x{5B43}\x{5B45}' . + '\x{5B50}\x{5B51}\x{5B54}\x{5B55}\x{5B57}\x{5B58}\x{5B5A}\x{5B5B}\x{5B5C}' . + '\x{5B5D}\x{5B5F}\x{5B63}\x{5B64}\x{5B65}\x{5B66}\x{5B69}\x{5B6B}\x{5B70}' . + '\x{5B71}\x{5B73}\x{5B75}\x{5B78}\x{5B7A}\x{5B80}\x{5B83}\x{5B85}\x{5B87}' . + '\x{5B88}\x{5B89}\x{5B8B}\x{5B8C}\x{5B8D}\x{5B8F}\x{5B95}\x{5B97}\x{5B98}' . + '\x{5B99}\x{5B9A}\x{5B9B}\x{5B9C}\x{5B9D}\x{5B9F}\x{5BA2}\x{5BA3}\x{5BA4}' . + '\x{5BA5}\x{5BA6}\x{5BAE}\x{5BB0}\x{5BB3}\x{5BB4}\x{5BB5}\x{5BB6}\x{5BB8}' . + '\x{5BB9}\x{5BBF}\x{5BC2}\x{5BC3}\x{5BC4}\x{5BC5}\x{5BC6}\x{5BC7}\x{5BC9}' . + '\x{5BCC}\x{5BD0}\x{5BD2}\x{5BD3}\x{5BD4}\x{5BDB}\x{5BDD}\x{5BDE}\x{5BDF}' . + '\x{5BE1}\x{5BE2}\x{5BE4}\x{5BE5}\x{5BE6}\x{5BE7}\x{5BE8}\x{5BE9}\x{5BEB}' . + '\x{5BEE}\x{5BF0}\x{5BF3}\x{5BF5}\x{5BF6}\x{5BF8}\x{5BFA}\x{5BFE}\x{5BFF}' . + '\x{5C01}\x{5C02}\x{5C04}\x{5C05}\x{5C06}\x{5C07}\x{5C08}\x{5C09}\x{5C0A}' . + '\x{5C0B}\x{5C0D}\x{5C0E}\x{5C0F}\x{5C11}\x{5C13}\x{5C16}\x{5C1A}\x{5C20}' . + '\x{5C22}\x{5C24}\x{5C28}\x{5C2D}\x{5C31}\x{5C38}\x{5C39}\x{5C3A}\x{5C3B}' . + '\x{5C3C}\x{5C3D}\x{5C3E}\x{5C3F}\x{5C40}\x{5C41}\x{5C45}\x{5C46}\x{5C48}' . + '\x{5C4A}\x{5C4B}\x{5C4D}\x{5C4E}\x{5C4F}\x{5C50}\x{5C51}\x{5C53}\x{5C55}' . + '\x{5C5E}\x{5C60}\x{5C61}\x{5C64}\x{5C65}\x{5C6C}\x{5C6E}\x{5C6F}\x{5C71}' . + '\x{5C76}\x{5C79}\x{5C8C}\x{5C90}\x{5C91}\x{5C94}\x{5CA1}\x{5CA8}\x{5CA9}' . + '\x{5CAB}\x{5CAC}\x{5CB1}\x{5CB3}\x{5CB6}\x{5CB7}\x{5CB8}\x{5CBB}\x{5CBC}' . + '\x{5CBE}\x{5CC5}\x{5CC7}\x{5CD9}\x{5CE0}\x{5CE1}\x{5CE8}\x{5CE9}\x{5CEA}' . + '\x{5CED}\x{5CEF}\x{5CF0}\x{5CF6}\x{5CFA}\x{5CFB}\x{5CFD}\x{5D07}\x{5D0B}' . + '\x{5D0E}\x{5D11}\x{5D14}\x{5D15}\x{5D16}\x{5D17}\x{5D18}\x{5D19}\x{5D1A}' . + '\x{5D1B}\x{5D1F}\x{5D22}\x{5D29}\x{5D4B}\x{5D4C}\x{5D4E}\x{5D50}\x{5D52}' . + '\x{5D5C}\x{5D69}\x{5D6C}\x{5D6F}\x{5D73}\x{5D76}\x{5D82}\x{5D84}\x{5D87}' . + '\x{5D8B}\x{5D8C}\x{5D90}\x{5D9D}\x{5DA2}\x{5DAC}\x{5DAE}\x{5DB7}\x{5DBA}' . + '\x{5DBC}\x{5DBD}\x{5DC9}\x{5DCC}\x{5DCD}\x{5DD2}\x{5DD3}\x{5DD6}\x{5DDB}' . + '\x{5DDD}\x{5DDE}\x{5DE1}\x{5DE3}\x{5DE5}\x{5DE6}\x{5DE7}\x{5DE8}\x{5DEB}' . + '\x{5DEE}\x{5DF1}\x{5DF2}\x{5DF3}\x{5DF4}\x{5DF5}\x{5DF7}\x{5DFB}\x{5DFD}' . + '\x{5DFE}\x{5E02}\x{5E03}\x{5E06}\x{5E0B}\x{5E0C}\x{5E11}\x{5E16}\x{5E19}' . + '\x{5E1A}\x{5E1B}\x{5E1D}\x{5E25}\x{5E2B}\x{5E2D}\x{5E2F}\x{5E30}\x{5E33}' . + '\x{5E36}\x{5E37}\x{5E38}\x{5E3D}\x{5E40}\x{5E43}\x{5E44}\x{5E45}\x{5E47}' . + '\x{5E4C}\x{5E4E}\x{5E54}\x{5E55}\x{5E57}\x{5E5F}\x{5E61}\x{5E62}\x{5E63}' . + '\x{5E64}\x{5E72}\x{5E73}\x{5E74}\x{5E75}\x{5E76}\x{5E78}\x{5E79}\x{5E7A}' . + '\x{5E7B}\x{5E7C}\x{5E7D}\x{5E7E}\x{5E7F}\x{5E81}\x{5E83}\x{5E84}\x{5E87}' . + '\x{5E8A}\x{5E8F}\x{5E95}\x{5E96}\x{5E97}\x{5E9A}\x{5E9C}\x{5EA0}\x{5EA6}' . + '\x{5EA7}\x{5EAB}\x{5EAD}\x{5EB5}\x{5EB6}\x{5EB7}\x{5EB8}\x{5EC1}\x{5EC2}' . + '\x{5EC3}\x{5EC8}\x{5EC9}\x{5ECA}\x{5ECF}\x{5ED0}\x{5ED3}\x{5ED6}\x{5EDA}' . + '\x{5EDB}\x{5EDD}\x{5EDF}\x{5EE0}\x{5EE1}\x{5EE2}\x{5EE3}\x{5EE8}\x{5EE9}' . + '\x{5EEC}\x{5EF0}\x{5EF1}\x{5EF3}\x{5EF4}\x{5EF6}\x{5EF7}\x{5EF8}\x{5EFA}' . + '\x{5EFB}\x{5EFC}\x{5EFE}\x{5EFF}\x{5F01}\x{5F03}\x{5F04}\x{5F09}\x{5F0A}' . + '\x{5F0B}\x{5F0C}\x{5F0D}\x{5F0F}\x{5F10}\x{5F11}\x{5F13}\x{5F14}\x{5F15}' . + '\x{5F16}\x{5F17}\x{5F18}\x{5F1B}\x{5F1F}\x{5F25}\x{5F26}\x{5F27}\x{5F29}' . + '\x{5F2D}\x{5F2F}\x{5F31}\x{5F35}\x{5F37}\x{5F38}\x{5F3C}\x{5F3E}\x{5F41}' . + '\x{5F48}\x{5F4A}\x{5F4C}\x{5F4E}\x{5F51}\x{5F53}\x{5F56}\x{5F57}\x{5F59}' . + '\x{5F5C}\x{5F5D}\x{5F61}\x{5F62}\x{5F66}\x{5F69}\x{5F6A}\x{5F6B}\x{5F6C}' . + '\x{5F6D}\x{5F70}\x{5F71}\x{5F73}\x{5F77}\x{5F79}\x{5F7C}\x{5F7F}\x{5F80}' . + '\x{5F81}\x{5F82}\x{5F83}\x{5F84}\x{5F85}\x{5F87}\x{5F88}\x{5F8A}\x{5F8B}' . + '\x{5F8C}\x{5F90}\x{5F91}\x{5F92}\x{5F93}\x{5F97}\x{5F98}\x{5F99}\x{5F9E}' . + '\x{5FA0}\x{5FA1}\x{5FA8}\x{5FA9}\x{5FAA}\x{5FAD}\x{5FAE}\x{5FB3}\x{5FB4}' . + '\x{5FB9}\x{5FBC}\x{5FBD}\x{5FC3}\x{5FC5}\x{5FCC}\x{5FCD}\x{5FD6}\x{5FD7}' . + '\x{5FD8}\x{5FD9}\x{5FDC}\x{5FDD}\x{5FE0}\x{5FE4}\x{5FEB}\x{5FF0}\x{5FF1}' . + '\x{5FF5}\x{5FF8}\x{5FFB}\x{5FFD}\x{5FFF}\x{600E}\x{600F}\x{6010}\x{6012}' . + '\x{6015}\x{6016}\x{6019}\x{601B}\x{601C}\x{601D}\x{6020}\x{6021}\x{6025}' . + '\x{6026}\x{6027}\x{6028}\x{6029}\x{602A}\x{602B}\x{602F}\x{6031}\x{603A}' . + '\x{6041}\x{6042}\x{6043}\x{6046}\x{604A}\x{604B}\x{604D}\x{6050}\x{6052}' . + '\x{6055}\x{6059}\x{605A}\x{605F}\x{6060}\x{6062}\x{6063}\x{6064}\x{6065}' . + '\x{6068}\x{6069}\x{606A}\x{606B}\x{606C}\x{606D}\x{606F}\x{6070}\x{6075}' . + '\x{6077}\x{6081}\x{6083}\x{6084}\x{6089}\x{608B}\x{608C}\x{608D}\x{6092}' . + '\x{6094}\x{6096}\x{6097}\x{609A}\x{609B}\x{609F}\x{60A0}\x{60A3}\x{60A6}' . + '\x{60A7}\x{60A9}\x{60AA}\x{60B2}\x{60B3}\x{60B4}\x{60B5}\x{60B6}\x{60B8}' . + '\x{60BC}\x{60BD}\x{60C5}\x{60C6}\x{60C7}\x{60D1}\x{60D3}\x{60D8}\x{60DA}' . + '\x{60DC}\x{60DF}\x{60E0}\x{60E1}\x{60E3}\x{60E7}\x{60E8}\x{60F0}\x{60F1}' . + '\x{60F3}\x{60F4}\x{60F6}\x{60F7}\x{60F9}\x{60FA}\x{60FB}\x{6100}\x{6101}' . + '\x{6103}\x{6106}\x{6108}\x{6109}\x{610D}\x{610E}\x{610F}\x{6115}\x{611A}' . + '\x{611B}\x{611F}\x{6121}\x{6127}\x{6128}\x{612C}\x{6134}\x{613C}\x{613D}' . + '\x{613E}\x{613F}\x{6142}\x{6144}\x{6147}\x{6148}\x{614A}\x{614B}\x{614C}' . + '\x{614D}\x{614E}\x{6153}\x{6155}\x{6158}\x{6159}\x{615A}\x{615D}\x{615F}' . + '\x{6162}\x{6163}\x{6165}\x{6167}\x{6168}\x{616B}\x{616E}\x{616F}\x{6170}' . + '\x{6171}\x{6173}\x{6174}\x{6175}\x{6176}\x{6177}\x{617E}\x{6182}\x{6187}' . + '\x{618A}\x{618E}\x{6190}\x{6191}\x{6194}\x{6196}\x{6199}\x{619A}\x{61A4}' . + '\x{61A7}\x{61A9}\x{61AB}\x{61AC}\x{61AE}\x{61B2}\x{61B6}\x{61BA}\x{61BE}' . + '\x{61C3}\x{61C6}\x{61C7}\x{61C8}\x{61C9}\x{61CA}\x{61CB}\x{61CC}\x{61CD}' . + '\x{61D0}\x{61E3}\x{61E6}\x{61F2}\x{61F4}\x{61F6}\x{61F7}\x{61F8}\x{61FA}' . + '\x{61FC}\x{61FD}\x{61FE}\x{61FF}\x{6200}\x{6208}\x{6209}\x{620A}\x{620C}' . + '\x{620D}\x{620E}\x{6210}\x{6211}\x{6212}\x{6214}\x{6216}\x{621A}\x{621B}' . + '\x{621D}\x{621E}\x{621F}\x{6221}\x{6226}\x{622A}\x{622E}\x{622F}\x{6230}' . + '\x{6232}\x{6233}\x{6234}\x{6238}\x{623B}\x{623F}\x{6240}\x{6241}\x{6247}' . + '\x{6248}\x{6249}\x{624B}\x{624D}\x{624E}\x{6253}\x{6255}\x{6258}\x{625B}' . + '\x{625E}\x{6260}\x{6263}\x{6268}\x{626E}\x{6271}\x{6276}\x{6279}\x{627C}' . + '\x{627E}\x{627F}\x{6280}\x{6282}\x{6283}\x{6284}\x{6289}\x{628A}\x{6291}' . + '\x{6292}\x{6293}\x{6294}\x{6295}\x{6296}\x{6297}\x{6298}\x{629B}\x{629C}' . + '\x{629E}\x{62AB}\x{62AC}\x{62B1}\x{62B5}\x{62B9}\x{62BB}\x{62BC}\x{62BD}' . + '\x{62C2}\x{62C5}\x{62C6}\x{62C7}\x{62C8}\x{62C9}\x{62CA}\x{62CC}\x{62CD}' . + '\x{62CF}\x{62D0}\x{62D1}\x{62D2}\x{62D3}\x{62D4}\x{62D7}\x{62D8}\x{62D9}' . + '\x{62DB}\x{62DC}\x{62DD}\x{62E0}\x{62E1}\x{62EC}\x{62ED}\x{62EE}\x{62EF}' . + '\x{62F1}\x{62F3}\x{62F5}\x{62F6}\x{62F7}\x{62FE}\x{62FF}\x{6301}\x{6302}' . + '\x{6307}\x{6308}\x{6309}\x{630C}\x{6311}\x{6319}\x{631F}\x{6327}\x{6328}' . + '\x{632B}\x{632F}\x{633A}\x{633D}\x{633E}\x{633F}\x{6349}\x{634C}\x{634D}' . + '\x{634F}\x{6350}\x{6355}\x{6357}\x{635C}\x{6367}\x{6368}\x{6369}\x{636B}' . + '\x{636E}\x{6372}\x{6376}\x{6377}\x{637A}\x{637B}\x{6380}\x{6383}\x{6388}' . + '\x{6389}\x{638C}\x{638E}\x{638F}\x{6392}\x{6396}\x{6398}\x{639B}\x{639F}' . + '\x{63A0}\x{63A1}\x{63A2}\x{63A3}\x{63A5}\x{63A7}\x{63A8}\x{63A9}\x{63AA}' . + '\x{63AB}\x{63AC}\x{63B2}\x{63B4}\x{63B5}\x{63BB}\x{63BE}\x{63C0}\x{63C3}' . + '\x{63C4}\x{63C6}\x{63C9}\x{63CF}\x{63D0}\x{63D2}\x{63D6}\x{63DA}\x{63DB}' . + '\x{63E1}\x{63E3}\x{63E9}\x{63EE}\x{63F4}\x{63F6}\x{63FA}\x{6406}\x{640D}' . + '\x{640F}\x{6413}\x{6416}\x{6417}\x{641C}\x{6426}\x{6428}\x{642C}\x{642D}' . + '\x{6434}\x{6436}\x{643A}\x{643E}\x{6442}\x{644E}\x{6458}\x{6467}\x{6469}' . + '\x{646F}\x{6476}\x{6478}\x{647A}\x{6483}\x{6488}\x{6492}\x{6493}\x{6495}' . + '\x{649A}\x{649E}\x{64A4}\x{64A5}\x{64A9}\x{64AB}\x{64AD}\x{64AE}\x{64B0}' . + '\x{64B2}\x{64B9}\x{64BB}\x{64BC}\x{64C1}\x{64C2}\x{64C5}\x{64C7}\x{64CD}' . + '\x{64D2}\x{64D4}\x{64D8}\x{64DA}\x{64E0}\x{64E1}\x{64E2}\x{64E3}\x{64E6}' . + '\x{64E7}\x{64EC}\x{64EF}\x{64F1}\x{64F2}\x{64F4}\x{64F6}\x{64FA}\x{64FD}' . + '\x{64FE}\x{6500}\x{6505}\x{6518}\x{651C}\x{651D}\x{6523}\x{6524}\x{652A}' . + '\x{652B}\x{652C}\x{652F}\x{6534}\x{6535}\x{6536}\x{6537}\x{6538}\x{6539}' . + '\x{653B}\x{653E}\x{653F}\x{6545}\x{6548}\x{654D}\x{654F}\x{6551}\x{6555}' . + '\x{6556}\x{6557}\x{6558}\x{6559}\x{655D}\x{655E}\x{6562}\x{6563}\x{6566}' . + '\x{656C}\x{6570}\x{6572}\x{6574}\x{6575}\x{6577}\x{6578}\x{6582}\x{6583}' . + '\x{6587}\x{6588}\x{6589}\x{658C}\x{658E}\x{6590}\x{6591}\x{6597}\x{6599}' . + '\x{659B}\x{659C}\x{659F}\x{65A1}\x{65A4}\x{65A5}\x{65A7}\x{65AB}\x{65AC}' . + '\x{65AD}\x{65AF}\x{65B0}\x{65B7}\x{65B9}\x{65BC}\x{65BD}\x{65C1}\x{65C3}' . + '\x{65C4}\x{65C5}\x{65C6}\x{65CB}\x{65CC}\x{65CF}\x{65D2}\x{65D7}\x{65D9}' . + '\x{65DB}\x{65E0}\x{65E1}\x{65E2}\x{65E5}\x{65E6}\x{65E7}\x{65E8}\x{65E9}' . + '\x{65EC}\x{65ED}\x{65F1}\x{65FA}\x{65FB}\x{6602}\x{6603}\x{6606}\x{6607}' . + '\x{660A}\x{660C}\x{660E}\x{660F}\x{6613}\x{6614}\x{661C}\x{661F}\x{6620}' . + '\x{6625}\x{6627}\x{6628}\x{662D}\x{662F}\x{6634}\x{6635}\x{6636}\x{663C}' . + '\x{663F}\x{6641}\x{6642}\x{6643}\x{6644}\x{6649}\x{664B}\x{664F}\x{6652}' . + '\x{665D}\x{665E}\x{665F}\x{6662}\x{6664}\x{6666}\x{6667}\x{6668}\x{6669}' . + '\x{666E}\x{666F}\x{6670}\x{6674}\x{6676}\x{667A}\x{6681}\x{6683}\x{6684}' . + '\x{6687}\x{6688}\x{6689}\x{668E}\x{6691}\x{6696}\x{6697}\x{6698}\x{669D}' . + '\x{66A2}\x{66A6}\x{66AB}\x{66AE}\x{66B4}\x{66B8}\x{66B9}\x{66BC}\x{66BE}' . + '\x{66C1}\x{66C4}\x{66C7}\x{66C9}\x{66D6}\x{66D9}\x{66DA}\x{66DC}\x{66DD}' . + '\x{66E0}\x{66E6}\x{66E9}\x{66F0}\x{66F2}\x{66F3}\x{66F4}\x{66F5}\x{66F7}' . + '\x{66F8}\x{66F9}\x{66FC}\x{66FD}\x{66FE}\x{66FF}\x{6700}\x{6703}\x{6708}' . + '\x{6709}\x{670B}\x{670D}\x{670F}\x{6714}\x{6715}\x{6716}\x{6717}\x{671B}' . + '\x{671D}\x{671E}\x{671F}\x{6726}\x{6727}\x{6728}\x{672A}\x{672B}\x{672C}' . + '\x{672D}\x{672E}\x{6731}\x{6734}\x{6736}\x{6737}\x{6738}\x{673A}\x{673D}' . + '\x{673F}\x{6741}\x{6746}\x{6749}\x{674E}\x{674F}\x{6750}\x{6751}\x{6753}' . + '\x{6756}\x{6759}\x{675C}\x{675E}\x{675F}\x{6760}\x{6761}\x{6762}\x{6763}' . + '\x{6764}\x{6765}\x{676A}\x{676D}\x{676F}\x{6770}\x{6771}\x{6772}\x{6773}' . + '\x{6775}\x{6777}\x{677C}\x{677E}\x{677F}\x{6785}\x{6787}\x{6789}\x{678B}' . + '\x{678C}\x{6790}\x{6795}\x{6797}\x{679A}\x{679C}\x{679D}\x{67A0}\x{67A1}' . + '\x{67A2}\x{67A6}\x{67A9}\x{67AF}\x{67B3}\x{67B4}\x{67B6}\x{67B7}\x{67B8}' . + '\x{67B9}\x{67C1}\x{67C4}\x{67C6}\x{67CA}\x{67CE}\x{67CF}\x{67D0}\x{67D1}' . + '\x{67D3}\x{67D4}\x{67D8}\x{67DA}\x{67DD}\x{67DE}\x{67E2}\x{67E4}\x{67E7}' . + '\x{67E9}\x{67EC}\x{67EE}\x{67EF}\x{67F1}\x{67F3}\x{67F4}\x{67F5}\x{67FB}' . + '\x{67FE}\x{67FF}\x{6802}\x{6803}\x{6804}\x{6813}\x{6816}\x{6817}\x{681E}' . + '\x{6821}\x{6822}\x{6829}\x{682A}\x{682B}\x{6832}\x{6834}\x{6838}\x{6839}' . + '\x{683C}\x{683D}\x{6840}\x{6841}\x{6842}\x{6843}\x{6846}\x{6848}\x{684D}' . + '\x{684E}\x{6850}\x{6851}\x{6853}\x{6854}\x{6859}\x{685C}\x{685D}\x{685F}' . + '\x{6863}\x{6867}\x{6874}\x{6876}\x{6877}\x{687E}\x{687F}\x{6881}\x{6883}' . + '\x{6885}\x{688D}\x{688F}\x{6893}\x{6894}\x{6897}\x{689B}\x{689D}\x{689F}' . + '\x{68A0}\x{68A2}\x{68A6}\x{68A7}\x{68A8}\x{68AD}\x{68AF}\x{68B0}\x{68B1}' . + '\x{68B3}\x{68B5}\x{68B6}\x{68B9}\x{68BA}\x{68BC}\x{68C4}\x{68C6}\x{68C9}' . + '\x{68CA}\x{68CB}\x{68CD}\x{68D2}\x{68D4}\x{68D5}\x{68D7}\x{68D8}\x{68DA}' . + '\x{68DF}\x{68E0}\x{68E1}\x{68E3}\x{68E7}\x{68EE}\x{68EF}\x{68F2}\x{68F9}' . + '\x{68FA}\x{6900}\x{6901}\x{6904}\x{6905}\x{6908}\x{690B}\x{690C}\x{690D}' . + '\x{690E}\x{690F}\x{6912}\x{6919}\x{691A}\x{691B}\x{691C}\x{6921}\x{6922}' . + '\x{6923}\x{6925}\x{6926}\x{6928}\x{692A}\x{6930}\x{6934}\x{6936}\x{6939}' . + '\x{693D}\x{693F}\x{694A}\x{6953}\x{6954}\x{6955}\x{6959}\x{695A}\x{695C}' . + '\x{695D}\x{695E}\x{6960}\x{6961}\x{6962}\x{696A}\x{696B}\x{696D}\x{696E}' . + '\x{696F}\x{6973}\x{6974}\x{6975}\x{6977}\x{6978}\x{6979}\x{697C}\x{697D}' . + '\x{697E}\x{6981}\x{6982}\x{698A}\x{698E}\x{6991}\x{6994}\x{6995}\x{699B}' . + '\x{699C}\x{69A0}\x{69A7}\x{69AE}\x{69B1}\x{69B2}\x{69B4}\x{69BB}\x{69BE}' . + '\x{69BF}\x{69C1}\x{69C3}\x{69C7}\x{69CA}\x{69CB}\x{69CC}\x{69CD}\x{69CE}' . + '\x{69D0}\x{69D3}\x{69D8}\x{69D9}\x{69DD}\x{69DE}\x{69E7}\x{69E8}\x{69EB}' . + '\x{69ED}\x{69F2}\x{69F9}\x{69FB}\x{69FD}\x{69FF}\x{6A02}\x{6A05}\x{6A0A}' . + '\x{6A0B}\x{6A0C}\x{6A12}\x{6A13}\x{6A14}\x{6A17}\x{6A19}\x{6A1B}\x{6A1E}' . + '\x{6A1F}\x{6A21}\x{6A22}\x{6A23}\x{6A29}\x{6A2A}\x{6A2B}\x{6A2E}\x{6A35}' . + '\x{6A36}\x{6A38}\x{6A39}\x{6A3A}\x{6A3D}\x{6A44}\x{6A47}\x{6A48}\x{6A4B}' . + '\x{6A58}\x{6A59}\x{6A5F}\x{6A61}\x{6A62}\x{6A66}\x{6A72}\x{6A78}\x{6A7F}' . + '\x{6A80}\x{6A84}\x{6A8D}\x{6A8E}\x{6A90}\x{6A97}\x{6A9C}\x{6AA0}\x{6AA2}' . + '\x{6AA3}\x{6AAA}\x{6AAC}\x{6AAE}\x{6AB3}\x{6AB8}\x{6ABB}\x{6AC1}\x{6AC2}' . + '\x{6AC3}\x{6AD1}\x{6AD3}\x{6ADA}\x{6ADB}\x{6ADE}\x{6ADF}\x{6AE8}\x{6AEA}' . + '\x{6AFA}\x{6AFB}\x{6B04}\x{6B05}\x{6B0A}\x{6B12}\x{6B16}\x{6B1D}\x{6B1F}' . + '\x{6B20}\x{6B21}\x{6B23}\x{6B27}\x{6B32}\x{6B37}\x{6B38}\x{6B39}\x{6B3A}' . + '\x{6B3D}\x{6B3E}\x{6B43}\x{6B47}\x{6B49}\x{6B4C}\x{6B4E}\x{6B50}\x{6B53}' . + '\x{6B54}\x{6B59}\x{6B5B}\x{6B5F}\x{6B61}\x{6B62}\x{6B63}\x{6B64}\x{6B66}' . + '\x{6B69}\x{6B6A}\x{6B6F}\x{6B73}\x{6B74}\x{6B78}\x{6B79}\x{6B7B}\x{6B7F}' . + '\x{6B80}\x{6B83}\x{6B84}\x{6B86}\x{6B89}\x{6B8A}\x{6B8B}\x{6B8D}\x{6B95}' . + '\x{6B96}\x{6B98}\x{6B9E}\x{6BA4}\x{6BAA}\x{6BAB}\x{6BAF}\x{6BB1}\x{6BB2}' . + '\x{6BB3}\x{6BB4}\x{6BB5}\x{6BB7}\x{6BBA}\x{6BBB}\x{6BBC}\x{6BBF}\x{6BC0}' . + '\x{6BC5}\x{6BC6}\x{6BCB}\x{6BCD}\x{6BCE}\x{6BD2}\x{6BD3}\x{6BD4}\x{6BD8}' . + '\x{6BDB}\x{6BDF}\x{6BEB}\x{6BEC}\x{6BEF}\x{6BF3}\x{6C08}\x{6C0F}\x{6C11}' . + '\x{6C13}\x{6C14}\x{6C17}\x{6C1B}\x{6C23}\x{6C24}\x{6C34}\x{6C37}\x{6C38}' . + '\x{6C3E}\x{6C40}\x{6C41}\x{6C42}\x{6C4E}\x{6C50}\x{6C55}\x{6C57}\x{6C5A}' . + '\x{6C5D}\x{6C5E}\x{6C5F}\x{6C60}\x{6C62}\x{6C68}\x{6C6A}\x{6C70}\x{6C72}' . + '\x{6C73}\x{6C7A}\x{6C7D}\x{6C7E}\x{6C81}\x{6C82}\x{6C83}\x{6C88}\x{6C8C}' . + '\x{6C8D}\x{6C90}\x{6C92}\x{6C93}\x{6C96}\x{6C99}\x{6C9A}\x{6C9B}\x{6CA1}' . + '\x{6CA2}\x{6CAB}\x{6CAE}\x{6CB1}\x{6CB3}\x{6CB8}\x{6CB9}\x{6CBA}\x{6CBB}' . + '\x{6CBC}\x{6CBD}\x{6CBE}\x{6CBF}\x{6CC1}\x{6CC4}\x{6CC5}\x{6CC9}\x{6CCA}' . + '\x{6CCC}\x{6CD3}\x{6CD5}\x{6CD7}\x{6CD9}\x{6CDB}\x{6CDD}\x{6CE1}\x{6CE2}' . + '\x{6CE3}\x{6CE5}\x{6CE8}\x{6CEA}\x{6CEF}\x{6CF0}\x{6CF1}\x{6CF3}\x{6D0B}' . + '\x{6D0C}\x{6D12}\x{6D17}\x{6D19}\x{6D1B}\x{6D1E}\x{6D1F}\x{6D25}\x{6D29}' . + '\x{6D2A}\x{6D2B}\x{6D32}\x{6D33}\x{6D35}\x{6D36}\x{6D38}\x{6D3B}\x{6D3D}' . + '\x{6D3E}\x{6D41}\x{6D44}\x{6D45}\x{6D59}\x{6D5A}\x{6D5C}\x{6D63}\x{6D64}' . + '\x{6D66}\x{6D69}\x{6D6A}\x{6D6C}\x{6D6E}\x{6D74}\x{6D77}\x{6D78}\x{6D79}' . + '\x{6D85}\x{6D88}\x{6D8C}\x{6D8E}\x{6D93}\x{6D95}\x{6D99}\x{6D9B}\x{6D9C}' . + '\x{6DAF}\x{6DB2}\x{6DB5}\x{6DB8}\x{6DBC}\x{6DC0}\x{6DC5}\x{6DC6}\x{6DC7}' . + '\x{6DCB}\x{6DCC}\x{6DD1}\x{6DD2}\x{6DD5}\x{6DD8}\x{6DD9}\x{6DDE}\x{6DE1}' . + '\x{6DE4}\x{6DE6}\x{6DE8}\x{6DEA}\x{6DEB}\x{6DEC}\x{6DEE}\x{6DF1}\x{6DF3}' . + '\x{6DF5}\x{6DF7}\x{6DF9}\x{6DFA}\x{6DFB}\x{6E05}\x{6E07}\x{6E08}\x{6E09}' . + '\x{6E0A}\x{6E0B}\x{6E13}\x{6E15}\x{6E19}\x{6E1A}\x{6E1B}\x{6E1D}\x{6E1F}' . + '\x{6E20}\x{6E21}\x{6E23}\x{6E24}\x{6E25}\x{6E26}\x{6E29}\x{6E2B}\x{6E2C}' . + '\x{6E2D}\x{6E2E}\x{6E2F}\x{6E38}\x{6E3A}\x{6E3E}\x{6E43}\x{6E4A}\x{6E4D}' . + '\x{6E4E}\x{6E56}\x{6E58}\x{6E5B}\x{6E5F}\x{6E67}\x{6E6B}\x{6E6E}\x{6E6F}' . + '\x{6E72}\x{6E76}\x{6E7E}\x{6E7F}\x{6E80}\x{6E82}\x{6E8C}\x{6E8F}\x{6E90}' . + '\x{6E96}\x{6E98}\x{6E9C}\x{6E9D}\x{6E9F}\x{6EA2}\x{6EA5}\x{6EAA}\x{6EAF}' . + '\x{6EB2}\x{6EB6}\x{6EB7}\x{6EBA}\x{6EBD}\x{6EC2}\x{6EC4}\x{6EC5}\x{6EC9}' . + '\x{6ECB}\x{6ECC}\x{6ED1}\x{6ED3}\x{6ED4}\x{6ED5}\x{6EDD}\x{6EDE}\x{6EEC}' . + '\x{6EEF}\x{6EF2}\x{6EF4}\x{6EF7}\x{6EF8}\x{6EFE}\x{6EFF}\x{6F01}\x{6F02}' . + '\x{6F06}\x{6F09}\x{6F0F}\x{6F11}\x{6F13}\x{6F14}\x{6F15}\x{6F20}\x{6F22}' . + '\x{6F23}\x{6F2B}\x{6F2C}\x{6F31}\x{6F32}\x{6F38}\x{6F3E}\x{6F3F}\x{6F41}' . + '\x{6F45}\x{6F54}\x{6F58}\x{6F5B}\x{6F5C}\x{6F5F}\x{6F64}\x{6F66}\x{6F6D}' . + '\x{6F6E}\x{6F6F}\x{6F70}\x{6F74}\x{6F78}\x{6F7A}\x{6F7C}\x{6F80}\x{6F81}' . + '\x{6F82}\x{6F84}\x{6F86}\x{6F8E}\x{6F91}\x{6F97}\x{6FA1}\x{6FA3}\x{6FA4}' . + '\x{6FAA}\x{6FB1}\x{6FB3}\x{6FB9}\x{6FC0}\x{6FC1}\x{6FC2}\x{6FC3}\x{6FC6}' . + '\x{6FD4}\x{6FD5}\x{6FD8}\x{6FDB}\x{6FDF}\x{6FE0}\x{6FE1}\x{6FE4}\x{6FEB}' . + '\x{6FEC}\x{6FEE}\x{6FEF}\x{6FF1}\x{6FF3}\x{6FF6}\x{6FFA}\x{6FFE}\x{7001}' . + '\x{7009}\x{700B}\x{700F}\x{7011}\x{7015}\x{7018}\x{701A}\x{701B}\x{701D}' . + '\x{701E}\x{701F}\x{7026}\x{7027}\x{702C}\x{7030}\x{7032}\x{703E}\x{704C}' . + '\x{7051}\x{7058}\x{7063}\x{706B}\x{706F}\x{7070}\x{7078}\x{707C}\x{707D}' . + '\x{7089}\x{708A}\x{708E}\x{7092}\x{7099}\x{70AC}\x{70AD}\x{70AE}\x{70AF}' . + '\x{70B3}\x{70B8}\x{70B9}\x{70BA}\x{70C8}\x{70CB}\x{70CF}\x{70D9}\x{70DD}' . + '\x{70DF}\x{70F1}\x{70F9}\x{70FD}\x{7109}\x{7114}\x{7119}\x{711A}\x{711C}' . + '\x{7121}\x{7126}\x{7136}\x{713C}\x{7149}\x{714C}\x{714E}\x{7155}\x{7156}' . + '\x{7159}\x{7162}\x{7164}\x{7165}\x{7166}\x{7167}\x{7169}\x{716C}\x{716E}' . + '\x{717D}\x{7184}\x{7188}\x{718A}\x{718F}\x{7194}\x{7195}\x{7199}\x{719F}' . + '\x{71A8}\x{71AC}\x{71B1}\x{71B9}\x{71BE}\x{71C3}\x{71C8}\x{71C9}\x{71CE}' . + '\x{71D0}\x{71D2}\x{71D4}\x{71D5}\x{71D7}\x{71DF}\x{71E0}\x{71E5}\x{71E6}' . + '\x{71E7}\x{71EC}\x{71ED}\x{71EE}\x{71F5}\x{71F9}\x{71FB}\x{71FC}\x{71FF}' . + '\x{7206}\x{720D}\x{7210}\x{721B}\x{7228}\x{722A}\x{722C}\x{722D}\x{7230}' . + '\x{7232}\x{7235}\x{7236}\x{723A}\x{723B}\x{723C}\x{723D}\x{723E}\x{723F}' . + '\x{7240}\x{7246}\x{7247}\x{7248}\x{724B}\x{724C}\x{7252}\x{7258}\x{7259}' . + '\x{725B}\x{725D}\x{725F}\x{7261}\x{7262}\x{7267}\x{7269}\x{7272}\x{7274}' . + '\x{7279}\x{727D}\x{727E}\x{7280}\x{7281}\x{7282}\x{7287}\x{7292}\x{7296}' . + '\x{72A0}\x{72A2}\x{72A7}\x{72AC}\x{72AF}\x{72B2}\x{72B6}\x{72B9}\x{72C2}' . + '\x{72C3}\x{72C4}\x{72C6}\x{72CE}\x{72D0}\x{72D2}\x{72D7}\x{72D9}\x{72DB}' . + '\x{72E0}\x{72E1}\x{72E2}\x{72E9}\x{72EC}\x{72ED}\x{72F7}\x{72F8}\x{72F9}' . + '\x{72FC}\x{72FD}\x{730A}\x{7316}\x{7317}\x{731B}\x{731C}\x{731D}\x{731F}' . + '\x{7325}\x{7329}\x{732A}\x{732B}\x{732E}\x{732F}\x{7334}\x{7336}\x{7337}' . + '\x{733E}\x{733F}\x{7344}\x{7345}\x{734E}\x{734F}\x{7357}\x{7363}\x{7368}' . + '\x{736A}\x{7370}\x{7372}\x{7375}\x{7378}\x{737A}\x{737B}\x{7384}\x{7387}' . + '\x{7389}\x{738B}\x{7396}\x{73A9}\x{73B2}\x{73B3}\x{73BB}\x{73C0}\x{73C2}' . + '\x{73C8}\x{73CA}\x{73CD}\x{73CE}\x{73DE}\x{73E0}\x{73E5}\x{73EA}\x{73ED}' . + '\x{73EE}\x{73F1}\x{73F8}\x{73FE}\x{7403}\x{7405}\x{7406}\x{7409}\x{7422}' . + '\x{7425}\x{7432}\x{7433}\x{7434}\x{7435}\x{7436}\x{743A}\x{743F}\x{7441}' . + '\x{7455}\x{7459}\x{745A}\x{745B}\x{745C}\x{745E}\x{745F}\x{7460}\x{7463}' . + '\x{7464}\x{7469}\x{746A}\x{746F}\x{7470}\x{7473}\x{7476}\x{747E}\x{7483}' . + '\x{748B}\x{749E}\x{74A2}\x{74A7}\x{74B0}\x{74BD}\x{74CA}\x{74CF}\x{74D4}' . + '\x{74DC}\x{74E0}\x{74E2}\x{74E3}\x{74E6}\x{74E7}\x{74E9}\x{74EE}\x{74F0}' . + '\x{74F1}\x{74F2}\x{74F6}\x{74F7}\x{74F8}\x{7503}\x{7504}\x{7505}\x{750C}' . + '\x{750D}\x{750E}\x{7511}\x{7513}\x{7515}\x{7518}\x{751A}\x{751C}\x{751E}' . + '\x{751F}\x{7523}\x{7525}\x{7526}\x{7528}\x{752B}\x{752C}\x{7530}\x{7531}' . + '\x{7532}\x{7533}\x{7537}\x{7538}\x{753A}\x{753B}\x{753C}\x{7544}\x{7546}' . + '\x{7549}\x{754A}\x{754B}\x{754C}\x{754D}\x{754F}\x{7551}\x{7554}\x{7559}' . + '\x{755A}\x{755B}\x{755C}\x{755D}\x{7560}\x{7562}\x{7564}\x{7565}\x{7566}' . + '\x{7567}\x{7569}\x{756A}\x{756B}\x{756D}\x{7570}\x{7573}\x{7574}\x{7576}' . + '\x{7577}\x{7578}\x{757F}\x{7582}\x{7586}\x{7587}\x{7589}\x{758A}\x{758B}' . + '\x{758E}\x{758F}\x{7591}\x{7594}\x{759A}\x{759D}\x{75A3}\x{75A5}\x{75AB}' . + '\x{75B1}\x{75B2}\x{75B3}\x{75B5}\x{75B8}\x{75B9}\x{75BC}\x{75BD}\x{75BE}' . + '\x{75C2}\x{75C3}\x{75C5}\x{75C7}\x{75CA}\x{75CD}\x{75D2}\x{75D4}\x{75D5}' . + '\x{75D8}\x{75D9}\x{75DB}\x{75DE}\x{75E2}\x{75E3}\x{75E9}\x{75F0}\x{75F2}' . + '\x{75F3}\x{75F4}\x{75FA}\x{75FC}\x{75FE}\x{75FF}\x{7601}\x{7609}\x{760B}' . + '\x{760D}\x{761F}\x{7620}\x{7621}\x{7622}\x{7624}\x{7627}\x{7630}\x{7634}' . + '\x{763B}\x{7642}\x{7646}\x{7647}\x{7648}\x{764C}\x{7652}\x{7656}\x{7658}' . + '\x{765C}\x{7661}\x{7662}\x{7667}\x{7668}\x{7669}\x{766A}\x{766C}\x{7670}' . + '\x{7672}\x{7676}\x{7678}\x{767A}\x{767B}\x{767C}\x{767D}\x{767E}\x{7680}' . + '\x{7683}\x{7684}\x{7686}\x{7687}\x{7688}\x{768B}\x{768E}\x{7690}\x{7693}' . + '\x{7696}\x{7699}\x{769A}\x{76AE}\x{76B0}\x{76B4}\x{76B7}\x{76B8}\x{76B9}' . + '\x{76BA}\x{76BF}\x{76C2}\x{76C3}\x{76C6}\x{76C8}\x{76CA}\x{76CD}\x{76D2}' . + '\x{76D6}\x{76D7}\x{76DB}\x{76DC}\x{76DE}\x{76DF}\x{76E1}\x{76E3}\x{76E4}' . + '\x{76E5}\x{76E7}\x{76EA}\x{76EE}\x{76F2}\x{76F4}\x{76F8}\x{76FB}\x{76FE}' . + '\x{7701}\x{7704}\x{7707}\x{7708}\x{7709}\x{770B}\x{770C}\x{771B}\x{771E}' . + '\x{771F}\x{7720}\x{7724}\x{7725}\x{7726}\x{7729}\x{7737}\x{7738}\x{773A}' . + '\x{773C}\x{7740}\x{7747}\x{775A}\x{775B}\x{7761}\x{7763}\x{7765}\x{7766}' . + '\x{7768}\x{776B}\x{7779}\x{777E}\x{777F}\x{778B}\x{778E}\x{7791}\x{779E}' . + '\x{77A0}\x{77A5}\x{77AC}\x{77AD}\x{77B0}\x{77B3}\x{77B6}\x{77B9}\x{77BB}' . + '\x{77BC}\x{77BD}\x{77BF}\x{77C7}\x{77CD}\x{77D7}\x{77DA}\x{77DB}\x{77DC}' . + '\x{77E2}\x{77E3}\x{77E5}\x{77E7}\x{77E9}\x{77ED}\x{77EE}\x{77EF}\x{77F3}' . + '\x{77FC}\x{7802}\x{780C}\x{7812}\x{7814}\x{7815}\x{7820}\x{7825}\x{7826}' . + '\x{7827}\x{7832}\x{7834}\x{783A}\x{783F}\x{7845}\x{785D}\x{786B}\x{786C}' . + '\x{786F}\x{7872}\x{7874}\x{787C}\x{7881}\x{7886}\x{7887}\x{788C}\x{788D}' . + '\x{788E}\x{7891}\x{7893}\x{7895}\x{7897}\x{789A}\x{78A3}\x{78A7}\x{78A9}' . + '\x{78AA}\x{78AF}\x{78B5}\x{78BA}\x{78BC}\x{78BE}\x{78C1}\x{78C5}\x{78C6}' . + '\x{78CA}\x{78CB}\x{78D0}\x{78D1}\x{78D4}\x{78DA}\x{78E7}\x{78E8}\x{78EC}' . + '\x{78EF}\x{78F4}\x{78FD}\x{7901}\x{7907}\x{790E}\x{7911}\x{7912}\x{7919}' . + '\x{7926}\x{792A}\x{792B}\x{792C}\x{793A}\x{793C}\x{793E}\x{7940}\x{7941}' . + '\x{7947}\x{7948}\x{7949}\x{7950}\x{7953}\x{7955}\x{7956}\x{7957}\x{795A}' . + '\x{795D}\x{795E}\x{795F}\x{7960}\x{7962}\x{7965}\x{7968}\x{796D}\x{7977}' . + '\x{797A}\x{797F}\x{7980}\x{7981}\x{7984}\x{7985}\x{798A}\x{798D}\x{798E}' . + '\x{798F}\x{799D}\x{79A6}\x{79A7}\x{79AA}\x{79AE}\x{79B0}\x{79B3}\x{79B9}' . + '\x{79BA}\x{79BD}\x{79BE}\x{79BF}\x{79C0}\x{79C1}\x{79C9}\x{79CB}\x{79D1}' . + '\x{79D2}\x{79D5}\x{79D8}\x{79DF}\x{79E1}\x{79E3}\x{79E4}\x{79E6}\x{79E7}' . + '\x{79E9}\x{79EC}\x{79F0}\x{79FB}\x{7A00}\x{7A08}\x{7A0B}\x{7A0D}\x{7A0E}' . + '\x{7A14}\x{7A17}\x{7A18}\x{7A19}\x{7A1A}\x{7A1C}\x{7A1F}\x{7A20}\x{7A2E}' . + '\x{7A31}\x{7A32}\x{7A37}\x{7A3B}\x{7A3C}\x{7A3D}\x{7A3E}\x{7A3F}\x{7A40}' . + '\x{7A42}\x{7A43}\x{7A46}\x{7A49}\x{7A4D}\x{7A4E}\x{7A4F}\x{7A50}\x{7A57}' . + '\x{7A61}\x{7A62}\x{7A63}\x{7A69}\x{7A6B}\x{7A70}\x{7A74}\x{7A76}\x{7A79}' . + '\x{7A7A}\x{7A7D}\x{7A7F}\x{7A81}\x{7A83}\x{7A84}\x{7A88}\x{7A92}\x{7A93}' . + '\x{7A95}\x{7A96}\x{7A97}\x{7A98}\x{7A9F}\x{7AA9}\x{7AAA}\x{7AAE}\x{7AAF}' . + '\x{7AB0}\x{7AB6}\x{7ABA}\x{7ABF}\x{7AC3}\x{7AC4}\x{7AC5}\x{7AC7}\x{7AC8}' . + '\x{7ACA}\x{7ACB}\x{7ACD}\x{7ACF}\x{7AD2}\x{7AD3}\x{7AD5}\x{7AD9}\x{7ADA}' . + '\x{7ADC}\x{7ADD}\x{7ADF}\x{7AE0}\x{7AE1}\x{7AE2}\x{7AE3}\x{7AE5}\x{7AE6}' . + '\x{7AEA}\x{7AED}\x{7AEF}\x{7AF0}\x{7AF6}\x{7AF8}\x{7AF9}\x{7AFA}\x{7AFF}' . + '\x{7B02}\x{7B04}\x{7B06}\x{7B08}\x{7B0A}\x{7B0B}\x{7B0F}\x{7B11}\x{7B18}' . + '\x{7B19}\x{7B1B}\x{7B1E}\x{7B20}\x{7B25}\x{7B26}\x{7B28}\x{7B2C}\x{7B33}' . + '\x{7B35}\x{7B36}\x{7B39}\x{7B45}\x{7B46}\x{7B48}\x{7B49}\x{7B4B}\x{7B4C}' . + '\x{7B4D}\x{7B4F}\x{7B50}\x{7B51}\x{7B52}\x{7B54}\x{7B56}\x{7B5D}\x{7B65}' . + '\x{7B67}\x{7B6C}\x{7B6E}\x{7B70}\x{7B71}\x{7B74}\x{7B75}\x{7B7A}\x{7B86}' . + '\x{7B87}\x{7B8B}\x{7B8D}\x{7B8F}\x{7B92}\x{7B94}\x{7B95}\x{7B97}\x{7B98}' . + '\x{7B99}\x{7B9A}\x{7B9C}\x{7B9D}\x{7B9F}\x{7BA1}\x{7BAA}\x{7BAD}\x{7BB1}' . + '\x{7BB4}\x{7BB8}\x{7BC0}\x{7BC1}\x{7BC4}\x{7BC6}\x{7BC7}\x{7BC9}\x{7BCB}' . + '\x{7BCC}\x{7BCF}\x{7BDD}\x{7BE0}\x{7BE4}\x{7BE5}\x{7BE6}\x{7BE9}\x{7BED}' . + '\x{7BF3}\x{7BF6}\x{7BF7}\x{7C00}\x{7C07}\x{7C0D}\x{7C11}\x{7C12}\x{7C13}' . + '\x{7C14}\x{7C17}\x{7C1F}\x{7C21}\x{7C23}\x{7C27}\x{7C2A}\x{7C2B}\x{7C37}' . + '\x{7C38}\x{7C3D}\x{7C3E}\x{7C3F}\x{7C40}\x{7C43}\x{7C4C}\x{7C4D}\x{7C4F}' . + '\x{7C50}\x{7C54}\x{7C56}\x{7C58}\x{7C5F}\x{7C60}\x{7C64}\x{7C65}\x{7C6C}' . + '\x{7C73}\x{7C75}\x{7C7E}\x{7C81}\x{7C82}\x{7C83}\x{7C89}\x{7C8B}\x{7C8D}' . + '\x{7C90}\x{7C92}\x{7C95}\x{7C97}\x{7C98}\x{7C9B}\x{7C9F}\x{7CA1}\x{7CA2}' . + '\x{7CA4}\x{7CA5}\x{7CA7}\x{7CA8}\x{7CAB}\x{7CAD}\x{7CAE}\x{7CB1}\x{7CB2}' . + '\x{7CB3}\x{7CB9}\x{7CBD}\x{7CBE}\x{7CC0}\x{7CC2}\x{7CC5}\x{7CCA}\x{7CCE}' . + '\x{7CD2}\x{7CD6}\x{7CD8}\x{7CDC}\x{7CDE}\x{7CDF}\x{7CE0}\x{7CE2}\x{7CE7}' . + '\x{7CEF}\x{7CF2}\x{7CF4}\x{7CF6}\x{7CF8}\x{7CFA}\x{7CFB}\x{7CFE}\x{7D00}' . + '\x{7D02}\x{7D04}\x{7D05}\x{7D06}\x{7D0A}\x{7D0B}\x{7D0D}\x{7D10}\x{7D14}' . + '\x{7D15}\x{7D17}\x{7D18}\x{7D19}\x{7D1A}\x{7D1B}\x{7D1C}\x{7D20}\x{7D21}' . + '\x{7D22}\x{7D2B}\x{7D2C}\x{7D2E}\x{7D2F}\x{7D30}\x{7D32}\x{7D33}\x{7D35}' . + '\x{7D39}\x{7D3A}\x{7D3F}\x{7D42}\x{7D43}\x{7D44}\x{7D45}\x{7D46}\x{7D4B}' . + '\x{7D4C}\x{7D4E}\x{7D4F}\x{7D50}\x{7D56}\x{7D5B}\x{7D5E}\x{7D61}\x{7D62}' . + '\x{7D63}\x{7D66}\x{7D68}\x{7D6E}\x{7D71}\x{7D72}\x{7D73}\x{7D75}\x{7D76}' . + '\x{7D79}\x{7D7D}\x{7D89}\x{7D8F}\x{7D93}\x{7D99}\x{7D9A}\x{7D9B}\x{7D9C}' . + '\x{7D9F}\x{7DA2}\x{7DA3}\x{7DAB}\x{7DAC}\x{7DAD}\x{7DAE}\x{7DAF}\x{7DB0}' . + '\x{7DB1}\x{7DB2}\x{7DB4}\x{7DB5}\x{7DB8}\x{7DBA}\x{7DBB}\x{7DBD}\x{7DBE}' . + '\x{7DBF}\x{7DC7}\x{7DCA}\x{7DCB}\x{7DCF}\x{7DD1}\x{7DD2}\x{7DD5}\x{7DD8}' . + '\x{7DDA}\x{7DDC}\x{7DDD}\x{7DDE}\x{7DE0}\x{7DE1}\x{7DE4}\x{7DE8}\x{7DE9}' . + '\x{7DEC}\x{7DEF}\x{7DF2}\x{7DF4}\x{7DFB}\x{7E01}\x{7E04}\x{7E05}\x{7E09}' . + '\x{7E0A}\x{7E0B}\x{7E12}\x{7E1B}\x{7E1E}\x{7E1F}\x{7E21}\x{7E22}\x{7E23}' . + '\x{7E26}\x{7E2B}\x{7E2E}\x{7E31}\x{7E32}\x{7E35}\x{7E37}\x{7E39}\x{7E3A}' . + '\x{7E3B}\x{7E3D}\x{7E3E}\x{7E41}\x{7E43}\x{7E46}\x{7E4A}\x{7E4B}\x{7E4D}' . + '\x{7E54}\x{7E55}\x{7E56}\x{7E59}\x{7E5A}\x{7E5D}\x{7E5E}\x{7E66}\x{7E67}' . + '\x{7E69}\x{7E6A}\x{7E6D}\x{7E70}\x{7E79}\x{7E7B}\x{7E7C}\x{7E7D}\x{7E7F}' . + '\x{7E82}\x{7E83}\x{7E88}\x{7E89}\x{7E8C}\x{7E8E}\x{7E8F}\x{7E90}\x{7E92}' . + '\x{7E93}\x{7E94}\x{7E96}\x{7E9B}\x{7E9C}\x{7F36}\x{7F38}\x{7F3A}\x{7F45}' . + '\x{7F4C}\x{7F4D}\x{7F4E}\x{7F50}\x{7F51}\x{7F54}\x{7F55}\x{7F58}\x{7F5F}' . + '\x{7F60}\x{7F67}\x{7F68}\x{7F69}\x{7F6A}\x{7F6B}\x{7F6E}\x{7F70}\x{7F72}' . + '\x{7F75}\x{7F77}\x{7F78}\x{7F79}\x{7F82}\x{7F83}\x{7F85}\x{7F86}\x{7F87}' . + '\x{7F88}\x{7F8A}\x{7F8C}\x{7F8E}\x{7F94}\x{7F9A}\x{7F9D}\x{7F9E}\x{7FA3}' . + '\x{7FA4}\x{7FA8}\x{7FA9}\x{7FAE}\x{7FAF}\x{7FB2}\x{7FB6}\x{7FB8}\x{7FB9}' . + '\x{7FBD}\x{7FC1}\x{7FC5}\x{7FC6}\x{7FCA}\x{7FCC}\x{7FD2}\x{7FD4}\x{7FD5}' . + '\x{7FE0}\x{7FE1}\x{7FE6}\x{7FE9}\x{7FEB}\x{7FF0}\x{7FF3}\x{7FF9}\x{7FFB}' . + '\x{7FFC}\x{8000}\x{8001}\x{8003}\x{8004}\x{8005}\x{8006}\x{800B}\x{800C}' . + '\x{8010}\x{8012}\x{8015}\x{8017}\x{8018}\x{8019}\x{801C}\x{8021}\x{8028}' . + '\x{8033}\x{8036}\x{803B}\x{803D}\x{803F}\x{8046}\x{804A}\x{8052}\x{8056}' . + '\x{8058}\x{805A}\x{805E}\x{805F}\x{8061}\x{8062}\x{8068}\x{806F}\x{8070}' . + '\x{8072}\x{8073}\x{8074}\x{8076}\x{8077}\x{8079}\x{807D}\x{807E}\x{807F}' . + '\x{8084}\x{8085}\x{8086}\x{8087}\x{8089}\x{808B}\x{808C}\x{8093}\x{8096}' . + '\x{8098}\x{809A}\x{809B}\x{809D}\x{80A1}\x{80A2}\x{80A5}\x{80A9}\x{80AA}' . + '\x{80AC}\x{80AD}\x{80AF}\x{80B1}\x{80B2}\x{80B4}\x{80BA}\x{80C3}\x{80C4}' . + '\x{80C6}\x{80CC}\x{80CE}\x{80D6}\x{80D9}\x{80DA}\x{80DB}\x{80DD}\x{80DE}' . + '\x{80E1}\x{80E4}\x{80E5}\x{80EF}\x{80F1}\x{80F4}\x{80F8}\x{80FC}\x{80FD}' . + '\x{8102}\x{8105}\x{8106}\x{8107}\x{8108}\x{8109}\x{810A}\x{811A}\x{811B}' . + '\x{8123}\x{8129}\x{812F}\x{8131}\x{8133}\x{8139}\x{813E}\x{8146}\x{814B}' . + '\x{814E}\x{8150}\x{8151}\x{8153}\x{8154}\x{8155}\x{815F}\x{8165}\x{8166}' . + '\x{816B}\x{816E}\x{8170}\x{8171}\x{8174}\x{8178}\x{8179}\x{817A}\x{817F}' . + '\x{8180}\x{8182}\x{8183}\x{8188}\x{818A}\x{818F}\x{8193}\x{8195}\x{819A}' . + '\x{819C}\x{819D}\x{81A0}\x{81A3}\x{81A4}\x{81A8}\x{81A9}\x{81B0}\x{81B3}' . + '\x{81B5}\x{81B8}\x{81BA}\x{81BD}\x{81BE}\x{81BF}\x{81C0}\x{81C2}\x{81C6}' . + '\x{81C8}\x{81C9}\x{81CD}\x{81D1}\x{81D3}\x{81D8}\x{81D9}\x{81DA}\x{81DF}' . + '\x{81E0}\x{81E3}\x{81E5}\x{81E7}\x{81E8}\x{81EA}\x{81ED}\x{81F3}\x{81F4}' . + '\x{81FA}\x{81FB}\x{81FC}\x{81FE}\x{8201}\x{8202}\x{8205}\x{8207}\x{8208}' . + '\x{8209}\x{820A}\x{820C}\x{820D}\x{820E}\x{8210}\x{8212}\x{8216}\x{8217}' . + '\x{8218}\x{821B}\x{821C}\x{821E}\x{821F}\x{8229}\x{822A}\x{822B}\x{822C}' . + '\x{822E}\x{8233}\x{8235}\x{8236}\x{8237}\x{8238}\x{8239}\x{8240}\x{8247}' . + '\x{8258}\x{8259}\x{825A}\x{825D}\x{825F}\x{8262}\x{8264}\x{8266}\x{8268}' . + '\x{826A}\x{826B}\x{826E}\x{826F}\x{8271}\x{8272}\x{8276}\x{8277}\x{8278}' . + '\x{827E}\x{828B}\x{828D}\x{8292}\x{8299}\x{829D}\x{829F}\x{82A5}\x{82A6}' . + '\x{82AB}\x{82AC}\x{82AD}\x{82AF}\x{82B1}\x{82B3}\x{82B8}\x{82B9}\x{82BB}' . + '\x{82BD}\x{82C5}\x{82D1}\x{82D2}\x{82D3}\x{82D4}\x{82D7}\x{82D9}\x{82DB}' . + '\x{82DC}\x{82DE}\x{82DF}\x{82E1}\x{82E3}\x{82E5}\x{82E6}\x{82E7}\x{82EB}' . + '\x{82F1}\x{82F3}\x{82F4}\x{82F9}\x{82FA}\x{82FB}\x{8302}\x{8303}\x{8304}' . + '\x{8305}\x{8306}\x{8309}\x{830E}\x{8316}\x{8317}\x{8318}\x{831C}\x{8323}' . + '\x{8328}\x{832B}\x{832F}\x{8331}\x{8332}\x{8334}\x{8335}\x{8336}\x{8338}' . + '\x{8339}\x{8340}\x{8345}\x{8349}\x{834A}\x{834F}\x{8350}\x{8352}\x{8358}' . + '\x{8373}\x{8375}\x{8377}\x{837B}\x{837C}\x{8385}\x{8387}\x{8389}\x{838A}' . + '\x{838E}\x{8393}\x{8396}\x{839A}\x{839E}\x{839F}\x{83A0}\x{83A2}\x{83A8}' . + '\x{83AA}\x{83AB}\x{83B1}\x{83B5}\x{83BD}\x{83C1}\x{83C5}\x{83CA}\x{83CC}' . + '\x{83CE}\x{83D3}\x{83D6}\x{83D8}\x{83DC}\x{83DF}\x{83E0}\x{83E9}\x{83EB}' . + '\x{83EF}\x{83F0}\x{83F1}\x{83F2}\x{83F4}\x{83F7}\x{83FB}\x{83FD}\x{8403}' . + '\x{8404}\x{8407}\x{840B}\x{840C}\x{840D}\x{840E}\x{8413}\x{8420}\x{8422}' . + '\x{8429}\x{842A}\x{842C}\x{8431}\x{8435}\x{8438}\x{843C}\x{843D}\x{8446}' . + '\x{8449}\x{844E}\x{8457}\x{845B}\x{8461}\x{8462}\x{8463}\x{8466}\x{8469}' . + '\x{846B}\x{846C}\x{846D}\x{846E}\x{846F}\x{8471}\x{8475}\x{8477}\x{8479}' . + '\x{847A}\x{8482}\x{8484}\x{848B}\x{8490}\x{8494}\x{8499}\x{849C}\x{849F}' . + '\x{84A1}\x{84AD}\x{84B2}\x{84B8}\x{84B9}\x{84BB}\x{84BC}\x{84BF}\x{84C1}' . + '\x{84C4}\x{84C6}\x{84C9}\x{84CA}\x{84CB}\x{84CD}\x{84D0}\x{84D1}\x{84D6}' . + '\x{84D9}\x{84DA}\x{84EC}\x{84EE}\x{84F4}\x{84FC}\x{84FF}\x{8500}\x{8506}' . + '\x{8511}\x{8513}\x{8514}\x{8515}\x{8517}\x{8518}\x{851A}\x{851F}\x{8521}' . + '\x{8526}\x{852C}\x{852D}\x{8535}\x{853D}\x{8540}\x{8541}\x{8543}\x{8548}' . + '\x{8549}\x{854A}\x{854B}\x{854E}\x{8555}\x{8557}\x{8558}\x{855A}\x{8563}' . + '\x{8568}\x{8569}\x{856A}\x{856D}\x{8577}\x{857E}\x{8580}\x{8584}\x{8587}' . + '\x{8588}\x{858A}\x{8590}\x{8591}\x{8594}\x{8597}\x{8599}\x{859B}\x{859C}' . + '\x{85A4}\x{85A6}\x{85A8}\x{85A9}\x{85AA}\x{85AB}\x{85AC}\x{85AE}\x{85AF}' . + '\x{85B9}\x{85BA}\x{85C1}\x{85C9}\x{85CD}\x{85CF}\x{85D0}\x{85D5}\x{85DC}' . + '\x{85DD}\x{85E4}\x{85E5}\x{85E9}\x{85EA}\x{85F7}\x{85F9}\x{85FA}\x{85FB}' . + '\x{85FE}\x{8602}\x{8606}\x{8607}\x{860A}\x{860B}\x{8613}\x{8616}\x{8617}' . + '\x{861A}\x{8622}\x{862D}\x{862F}\x{8630}\x{863F}\x{864D}\x{864E}\x{8650}' . + '\x{8654}\x{8655}\x{865A}\x{865C}\x{865E}\x{865F}\x{8667}\x{866B}\x{8671}' . + '\x{8679}\x{867B}\x{868A}\x{868B}\x{868C}\x{8693}\x{8695}\x{86A3}\x{86A4}' . + '\x{86A9}\x{86AA}\x{86AB}\x{86AF}\x{86B0}\x{86B6}\x{86C4}\x{86C6}\x{86C7}' . + '\x{86C9}\x{86CB}\x{86CD}\x{86CE}\x{86D4}\x{86D9}\x{86DB}\x{86DE}\x{86DF}' . + '\x{86E4}\x{86E9}\x{86EC}\x{86ED}\x{86EE}\x{86EF}\x{86F8}\x{86F9}\x{86FB}' . + '\x{86FE}\x{8700}\x{8702}\x{8703}\x{8706}\x{8708}\x{8709}\x{870A}\x{870D}' . + '\x{8711}\x{8712}\x{8718}\x{871A}\x{871C}\x{8725}\x{8729}\x{8734}\x{8737}' . + '\x{873B}\x{873F}\x{8749}\x{874B}\x{874C}\x{874E}\x{8753}\x{8755}\x{8757}' . + '\x{8759}\x{875F}\x{8760}\x{8763}\x{8766}\x{8768}\x{876A}\x{876E}\x{8774}' . + '\x{8776}\x{8778}\x{877F}\x{8782}\x{878D}\x{879F}\x{87A2}\x{87AB}\x{87AF}' . + '\x{87B3}\x{87BA}\x{87BB}\x{87BD}\x{87C0}\x{87C4}\x{87C6}\x{87C7}\x{87CB}' . + '\x{87D0}\x{87D2}\x{87E0}\x{87EF}\x{87F2}\x{87F6}\x{87F7}\x{87F9}\x{87FB}' . + '\x{87FE}\x{8805}\x{880D}\x{880E}\x{880F}\x{8811}\x{8815}\x{8816}\x{8821}' . + '\x{8822}\x{8823}\x{8827}\x{8831}\x{8836}\x{8839}\x{883B}\x{8840}\x{8842}' . + '\x{8844}\x{8846}\x{884C}\x{884D}\x{8852}\x{8853}\x{8857}\x{8859}\x{885B}' . + '\x{885D}\x{885E}\x{8861}\x{8862}\x{8863}\x{8868}\x{886B}\x{8870}\x{8872}' . + '\x{8875}\x{8877}\x{887D}\x{887E}\x{887F}\x{8881}\x{8882}\x{8888}\x{888B}' . + '\x{888D}\x{8892}\x{8896}\x{8897}\x{8899}\x{889E}\x{88A2}\x{88A4}\x{88AB}' . + '\x{88AE}\x{88B0}\x{88B1}\x{88B4}\x{88B5}\x{88B7}\x{88BF}\x{88C1}\x{88C2}' . + '\x{88C3}\x{88C4}\x{88C5}\x{88CF}\x{88D4}\x{88D5}\x{88D8}\x{88D9}\x{88DC}' . + '\x{88DD}\x{88DF}\x{88E1}\x{88E8}\x{88F2}\x{88F3}\x{88F4}\x{88F8}\x{88F9}' . + '\x{88FC}\x{88FD}\x{88FE}\x{8902}\x{8904}\x{8907}\x{890A}\x{890C}\x{8910}' . + '\x{8912}\x{8913}\x{891D}\x{891E}\x{8925}\x{892A}\x{892B}\x{8936}\x{8938}' . + '\x{893B}\x{8941}\x{8943}\x{8944}\x{894C}\x{894D}\x{8956}\x{895E}\x{895F}' . + '\x{8960}\x{8964}\x{8966}\x{896A}\x{896D}\x{896F}\x{8972}\x{8974}\x{8977}' . + '\x{897E}\x{897F}\x{8981}\x{8983}\x{8986}\x{8987}\x{8988}\x{898A}\x{898B}' . + '\x{898F}\x{8993}\x{8996}\x{8997}\x{8998}\x{899A}\x{89A1}\x{89A6}\x{89A7}' . + '\x{89A9}\x{89AA}\x{89AC}\x{89AF}\x{89B2}\x{89B3}\x{89BA}\x{89BD}\x{89BF}' . + '\x{89C0}\x{89D2}\x{89DA}\x{89DC}\x{89DD}\x{89E3}\x{89E6}\x{89E7}\x{89F4}' . + '\x{89F8}\x{8A00}\x{8A02}\x{8A03}\x{8A08}\x{8A0A}\x{8A0C}\x{8A0E}\x{8A10}' . + '\x{8A13}\x{8A16}\x{8A17}\x{8A18}\x{8A1B}\x{8A1D}\x{8A1F}\x{8A23}\x{8A25}' . + '\x{8A2A}\x{8A2D}\x{8A31}\x{8A33}\x{8A34}\x{8A36}\x{8A3A}\x{8A3B}\x{8A3C}' . + '\x{8A41}\x{8A46}\x{8A48}\x{8A50}\x{8A51}\x{8A52}\x{8A54}\x{8A55}\x{8A5B}' . + '\x{8A5E}\x{8A60}\x{8A62}\x{8A63}\x{8A66}\x{8A69}\x{8A6B}\x{8A6C}\x{8A6D}' . + '\x{8A6E}\x{8A70}\x{8A71}\x{8A72}\x{8A73}\x{8A7C}\x{8A82}\x{8A84}\x{8A85}' . + '\x{8A87}\x{8A89}\x{8A8C}\x{8A8D}\x{8A91}\x{8A93}\x{8A95}\x{8A98}\x{8A9A}' . + '\x{8A9E}\x{8AA0}\x{8AA1}\x{8AA3}\x{8AA4}\x{8AA5}\x{8AA6}\x{8AA8}\x{8AAC}' . + '\x{8AAD}\x{8AB0}\x{8AB2}\x{8AB9}\x{8ABC}\x{8ABF}\x{8AC2}\x{8AC4}\x{8AC7}' . + '\x{8ACB}\x{8ACC}\x{8ACD}\x{8ACF}\x{8AD2}\x{8AD6}\x{8ADA}\x{8ADB}\x{8ADC}' . + '\x{8ADE}\x{8AE0}\x{8AE1}\x{8AE2}\x{8AE4}\x{8AE6}\x{8AE7}\x{8AEB}\x{8AED}' . + '\x{8AEE}\x{8AF1}\x{8AF3}\x{8AF7}\x{8AF8}\x{8AFA}\x{8AFE}\x{8B00}\x{8B01}' . + '\x{8B02}\x{8B04}\x{8B07}\x{8B0C}\x{8B0E}\x{8B10}\x{8B14}\x{8B16}\x{8B17}' . + '\x{8B19}\x{8B1A}\x{8B1B}\x{8B1D}\x{8B20}\x{8B21}\x{8B26}\x{8B28}\x{8B2B}' . + '\x{8B2C}\x{8B33}\x{8B39}\x{8B3E}\x{8B41}\x{8B49}\x{8B4C}\x{8B4E}\x{8B4F}' . + '\x{8B56}\x{8B58}\x{8B5A}\x{8B5B}\x{8B5C}\x{8B5F}\x{8B66}\x{8B6B}\x{8B6C}' . + '\x{8B6F}\x{8B70}\x{8B71}\x{8B72}\x{8B74}\x{8B77}\x{8B7D}\x{8B80}\x{8B83}' . + '\x{8B8A}\x{8B8C}\x{8B8E}\x{8B90}\x{8B92}\x{8B93}\x{8B96}\x{8B99}\x{8B9A}' . + '\x{8C37}\x{8C3A}\x{8C3F}\x{8C41}\x{8C46}\x{8C48}\x{8C4A}\x{8C4C}\x{8C4E}' . + '\x{8C50}\x{8C55}\x{8C5A}\x{8C61}\x{8C62}\x{8C6A}\x{8C6B}\x{8C6C}\x{8C78}' . + '\x{8C79}\x{8C7A}\x{8C7C}\x{8C82}\x{8C85}\x{8C89}\x{8C8A}\x{8C8C}\x{8C8D}' . + '\x{8C8E}\x{8C94}\x{8C98}\x{8C9D}\x{8C9E}\x{8CA0}\x{8CA1}\x{8CA2}\x{8CA7}' . + '\x{8CA8}\x{8CA9}\x{8CAA}\x{8CAB}\x{8CAC}\x{8CAD}\x{8CAE}\x{8CAF}\x{8CB0}' . + '\x{8CB2}\x{8CB3}\x{8CB4}\x{8CB6}\x{8CB7}\x{8CB8}\x{8CBB}\x{8CBC}\x{8CBD}' . + '\x{8CBF}\x{8CC0}\x{8CC1}\x{8CC2}\x{8CC3}\x{8CC4}\x{8CC7}\x{8CC8}\x{8CCA}' . + '\x{8CCD}\x{8CCE}\x{8CD1}\x{8CD3}\x{8CDA}\x{8CDB}\x{8CDC}\x{8CDE}\x{8CE0}' . + '\x{8CE2}\x{8CE3}\x{8CE4}\x{8CE6}\x{8CEA}\x{8CED}\x{8CFA}\x{8CFB}\x{8CFC}' . + '\x{8CFD}\x{8D04}\x{8D05}\x{8D07}\x{8D08}\x{8D0A}\x{8D0B}\x{8D0D}\x{8D0F}' . + '\x{8D10}\x{8D13}\x{8D14}\x{8D16}\x{8D64}\x{8D66}\x{8D67}\x{8D6B}\x{8D6D}' . + '\x{8D70}\x{8D71}\x{8D73}\x{8D74}\x{8D77}\x{8D81}\x{8D85}\x{8D8A}\x{8D99}' . + '\x{8DA3}\x{8DA8}\x{8DB3}\x{8DBA}\x{8DBE}\x{8DC2}\x{8DCB}\x{8DCC}\x{8DCF}' . + '\x{8DD6}\x{8DDA}\x{8DDB}\x{8DDD}\x{8DDF}\x{8DE1}\x{8DE3}\x{8DE8}\x{8DEA}' . + '\x{8DEB}\x{8DEF}\x{8DF3}\x{8DF5}\x{8DFC}\x{8DFF}\x{8E08}\x{8E09}\x{8E0A}' . + '\x{8E0F}\x{8E10}\x{8E1D}\x{8E1E}\x{8E1F}\x{8E2A}\x{8E30}\x{8E34}\x{8E35}' . + '\x{8E42}\x{8E44}\x{8E47}\x{8E48}\x{8E49}\x{8E4A}\x{8E4C}\x{8E50}\x{8E55}' . + '\x{8E59}\x{8E5F}\x{8E60}\x{8E63}\x{8E64}\x{8E72}\x{8E74}\x{8E76}\x{8E7C}' . + '\x{8E81}\x{8E84}\x{8E85}\x{8E87}\x{8E8A}\x{8E8B}\x{8E8D}\x{8E91}\x{8E93}' . + '\x{8E94}\x{8E99}\x{8EA1}\x{8EAA}\x{8EAB}\x{8EAC}\x{8EAF}\x{8EB0}\x{8EB1}' . + '\x{8EBE}\x{8EC5}\x{8EC6}\x{8EC8}\x{8ECA}\x{8ECB}\x{8ECC}\x{8ECD}\x{8ED2}' . + '\x{8EDB}\x{8EDF}\x{8EE2}\x{8EE3}\x{8EEB}\x{8EF8}\x{8EFB}\x{8EFC}\x{8EFD}' . + '\x{8EFE}\x{8F03}\x{8F05}\x{8F09}\x{8F0A}\x{8F0C}\x{8F12}\x{8F13}\x{8F14}' . + '\x{8F15}\x{8F19}\x{8F1B}\x{8F1C}\x{8F1D}\x{8F1F}\x{8F26}\x{8F29}\x{8F2A}' . + '\x{8F2F}\x{8F33}\x{8F38}\x{8F39}\x{8F3B}\x{8F3E}\x{8F3F}\x{8F42}\x{8F44}' . + '\x{8F45}\x{8F46}\x{8F49}\x{8F4C}\x{8F4D}\x{8F4E}\x{8F57}\x{8F5C}\x{8F5F}' . + '\x{8F61}\x{8F62}\x{8F63}\x{8F64}\x{8F9B}\x{8F9C}\x{8F9E}\x{8F9F}\x{8FA3}' . + '\x{8FA7}\x{8FA8}\x{8FAD}\x{8FAE}\x{8FAF}\x{8FB0}\x{8FB1}\x{8FB2}\x{8FB7}' . + '\x{8FBA}\x{8FBB}\x{8FBC}\x{8FBF}\x{8FC2}\x{8FC4}\x{8FC5}\x{8FCE}\x{8FD1}' . + '\x{8FD4}\x{8FDA}\x{8FE2}\x{8FE5}\x{8FE6}\x{8FE9}\x{8FEA}\x{8FEB}\x{8FED}' . + '\x{8FEF}\x{8FF0}\x{8FF4}\x{8FF7}\x{8FF8}\x{8FF9}\x{8FFA}\x{8FFD}\x{9000}' . + '\x{9001}\x{9003}\x{9005}\x{9006}\x{900B}\x{900D}\x{900E}\x{900F}\x{9010}' . + '\x{9011}\x{9013}\x{9014}\x{9015}\x{9016}\x{9017}\x{9019}\x{901A}\x{901D}' . + '\x{901E}\x{901F}\x{9020}\x{9021}\x{9022}\x{9023}\x{9027}\x{902E}\x{9031}' . + '\x{9032}\x{9035}\x{9036}\x{9038}\x{9039}\x{903C}\x{903E}\x{9041}\x{9042}' . + '\x{9045}\x{9047}\x{9049}\x{904A}\x{904B}\x{904D}\x{904E}\x{904F}\x{9050}' . + '\x{9051}\x{9052}\x{9053}\x{9054}\x{9055}\x{9056}\x{9058}\x{9059}\x{905C}' . + '\x{905E}\x{9060}\x{9061}\x{9063}\x{9065}\x{9068}\x{9069}\x{906D}\x{906E}' . + '\x{906F}\x{9072}\x{9075}\x{9076}\x{9077}\x{9078}\x{907A}\x{907C}\x{907D}' . + '\x{907F}\x{9080}\x{9081}\x{9082}\x{9083}\x{9084}\x{9087}\x{9089}\x{908A}' . + '\x{908F}\x{9091}\x{90A3}\x{90A6}\x{90A8}\x{90AA}\x{90AF}\x{90B1}\x{90B5}' . + '\x{90B8}\x{90C1}\x{90CA}\x{90CE}\x{90DB}\x{90E1}\x{90E2}\x{90E4}\x{90E8}' . + '\x{90ED}\x{90F5}\x{90F7}\x{90FD}\x{9102}\x{9112}\x{9119}\x{912D}\x{9130}' . + '\x{9132}\x{9149}\x{914A}\x{914B}\x{914C}\x{914D}\x{914E}\x{9152}\x{9154}' . + '\x{9156}\x{9158}\x{9162}\x{9163}\x{9165}\x{9169}\x{916A}\x{916C}\x{9172}' . + '\x{9173}\x{9175}\x{9177}\x{9178}\x{9182}\x{9187}\x{9189}\x{918B}\x{918D}' . + '\x{9190}\x{9192}\x{9197}\x{919C}\x{91A2}\x{91A4}\x{91AA}\x{91AB}\x{91AF}' . + '\x{91B4}\x{91B5}\x{91B8}\x{91BA}\x{91C0}\x{91C1}\x{91C6}\x{91C7}\x{91C8}' . + '\x{91C9}\x{91CB}\x{91CC}\x{91CD}\x{91CE}\x{91CF}\x{91D0}\x{91D1}\x{91D6}' . + '\x{91D8}\x{91DB}\x{91DC}\x{91DD}\x{91DF}\x{91E1}\x{91E3}\x{91E6}\x{91E7}' . + '\x{91F5}\x{91F6}\x{91FC}\x{91FF}\x{920D}\x{920E}\x{9211}\x{9214}\x{9215}' . + '\x{921E}\x{9229}\x{922C}\x{9234}\x{9237}\x{923F}\x{9244}\x{9245}\x{9248}' . + '\x{9249}\x{924B}\x{9250}\x{9257}\x{925A}\x{925B}\x{925E}\x{9262}\x{9264}' . + '\x{9266}\x{9271}\x{927E}\x{9280}\x{9283}\x{9285}\x{9291}\x{9293}\x{9295}' . + '\x{9296}\x{9298}\x{929A}\x{929B}\x{929C}\x{92AD}\x{92B7}\x{92B9}\x{92CF}' . + '\x{92D2}\x{92E4}\x{92E9}\x{92EA}\x{92ED}\x{92F2}\x{92F3}\x{92F8}\x{92FA}' . + '\x{92FC}\x{9306}\x{930F}\x{9310}\x{9318}\x{9319}\x{931A}\x{9320}\x{9322}' . + '\x{9323}\x{9326}\x{9328}\x{932B}\x{932C}\x{932E}\x{932F}\x{9332}\x{9335}' . + '\x{933A}\x{933B}\x{9344}\x{934B}\x{934D}\x{9354}\x{9356}\x{935B}\x{935C}' . + '\x{9360}\x{936C}\x{936E}\x{9375}\x{937C}\x{937E}\x{938C}\x{9394}\x{9396}' . + '\x{9397}\x{939A}\x{93A7}\x{93AC}\x{93AD}\x{93AE}\x{93B0}\x{93B9}\x{93C3}' . + '\x{93C8}\x{93D0}\x{93D1}\x{93D6}\x{93D7}\x{93D8}\x{93DD}\x{93E1}\x{93E4}' . + '\x{93E5}\x{93E8}\x{9403}\x{9407}\x{9410}\x{9413}\x{9414}\x{9418}\x{9419}' . + '\x{941A}\x{9421}\x{942B}\x{9435}\x{9436}\x{9438}\x{943A}\x{9441}\x{9444}' . + '\x{9451}\x{9452}\x{9453}\x{945A}\x{945B}\x{945E}\x{9460}\x{9462}\x{946A}' . + '\x{9470}\x{9475}\x{9477}\x{947C}\x{947D}\x{947E}\x{947F}\x{9481}\x{9577}' . + '\x{9580}\x{9582}\x{9583}\x{9587}\x{9589}\x{958A}\x{958B}\x{958F}\x{9591}' . + '\x{9593}\x{9594}\x{9596}\x{9598}\x{9599}\x{95A0}\x{95A2}\x{95A3}\x{95A4}' . + '\x{95A5}\x{95A7}\x{95A8}\x{95AD}\x{95B2}\x{95B9}\x{95BB}\x{95BC}\x{95BE}' . + '\x{95C3}\x{95C7}\x{95CA}\x{95CC}\x{95CD}\x{95D4}\x{95D5}\x{95D6}\x{95D8}' . + '\x{95DC}\x{95E1}\x{95E2}\x{95E5}\x{961C}\x{9621}\x{9628}\x{962A}\x{962E}' . + '\x{962F}\x{9632}\x{963B}\x{963F}\x{9640}\x{9642}\x{9644}\x{964B}\x{964C}' . + '\x{964D}\x{964F}\x{9650}\x{965B}\x{965C}\x{965D}\x{965E}\x{965F}\x{9662}' . + '\x{9663}\x{9664}\x{9665}\x{9666}\x{966A}\x{966C}\x{9670}\x{9672}\x{9673}' . + '\x{9675}\x{9676}\x{9677}\x{9678}\x{967A}\x{967D}\x{9685}\x{9686}\x{9688}' . + '\x{968A}\x{968B}\x{968D}\x{968E}\x{968F}\x{9694}\x{9695}\x{9697}\x{9698}' . + '\x{9699}\x{969B}\x{969C}\x{96A0}\x{96A3}\x{96A7}\x{96A8}\x{96AA}\x{96B0}' . + '\x{96B1}\x{96B2}\x{96B4}\x{96B6}\x{96B7}\x{96B8}\x{96B9}\x{96BB}\x{96BC}' . + '\x{96C0}\x{96C1}\x{96C4}\x{96C5}\x{96C6}\x{96C7}\x{96C9}\x{96CB}\x{96CC}' . + '\x{96CD}\x{96CE}\x{96D1}\x{96D5}\x{96D6}\x{96D9}\x{96DB}\x{96DC}\x{96E2}' . + '\x{96E3}\x{96E8}\x{96EA}\x{96EB}\x{96F0}\x{96F2}\x{96F6}\x{96F7}\x{96F9}' . + '\x{96FB}\x{9700}\x{9704}\x{9706}\x{9707}\x{9708}\x{970A}\x{970D}\x{970E}' . + '\x{970F}\x{9711}\x{9713}\x{9716}\x{9719}\x{971C}\x{971E}\x{9724}\x{9727}' . + '\x{972A}\x{9730}\x{9732}\x{9738}\x{9739}\x{973D}\x{973E}\x{9742}\x{9744}' . + '\x{9746}\x{9748}\x{9749}\x{9752}\x{9756}\x{9759}\x{975C}\x{975E}\x{9760}' . + '\x{9761}\x{9762}\x{9764}\x{9766}\x{9768}\x{9769}\x{976B}\x{976D}\x{9771}' . + '\x{9774}\x{9779}\x{977A}\x{977C}\x{9781}\x{9784}\x{9785}\x{9786}\x{978B}' . + '\x{978D}\x{978F}\x{9790}\x{9798}\x{979C}\x{97A0}\x{97A3}\x{97A6}\x{97A8}' . + '\x{97AB}\x{97AD}\x{97B3}\x{97B4}\x{97C3}\x{97C6}\x{97C8}\x{97CB}\x{97D3}' . + '\x{97DC}\x{97ED}\x{97EE}\x{97F2}\x{97F3}\x{97F5}\x{97F6}\x{97FB}\x{97FF}' . + '\x{9801}\x{9802}\x{9803}\x{9805}\x{9806}\x{9808}\x{980C}\x{980F}\x{9810}' . + '\x{9811}\x{9812}\x{9813}\x{9817}\x{9818}\x{981A}\x{9821}\x{9824}\x{982C}' . + '\x{982D}\x{9834}\x{9837}\x{9838}\x{983B}\x{983C}\x{983D}\x{9846}\x{984B}' . + '\x{984C}\x{984D}\x{984E}\x{984F}\x{9854}\x{9855}\x{9858}\x{985B}\x{985E}' . + '\x{9867}\x{986B}\x{986F}\x{9870}\x{9871}\x{9873}\x{9874}\x{98A8}\x{98AA}' . + '\x{98AF}\x{98B1}\x{98B6}\x{98C3}\x{98C4}\x{98C6}\x{98DB}\x{98DC}\x{98DF}' . + '\x{98E2}\x{98E9}\x{98EB}\x{98ED}\x{98EE}\x{98EF}\x{98F2}\x{98F4}\x{98FC}' . + '\x{98FD}\x{98FE}\x{9903}\x{9905}\x{9909}\x{990A}\x{990C}\x{9910}\x{9912}' . + '\x{9913}\x{9914}\x{9918}\x{991D}\x{991E}\x{9920}\x{9921}\x{9924}\x{9928}' . + '\x{992C}\x{992E}\x{993D}\x{993E}\x{9942}\x{9945}\x{9949}\x{994B}\x{994C}' . + '\x{9950}\x{9951}\x{9952}\x{9955}\x{9957}\x{9996}\x{9997}\x{9998}\x{9999}' . + '\x{99A5}\x{99A8}\x{99AC}\x{99AD}\x{99AE}\x{99B3}\x{99B4}\x{99BC}\x{99C1}' . + '\x{99C4}\x{99C5}\x{99C6}\x{99C8}\x{99D0}\x{99D1}\x{99D2}\x{99D5}\x{99D8}' . + '\x{99DB}\x{99DD}\x{99DF}\x{99E2}\x{99ED}\x{99EE}\x{99F1}\x{99F2}\x{99F8}' . + '\x{99FB}\x{99FF}\x{9A01}\x{9A05}\x{9A0E}\x{9A0F}\x{9A12}\x{9A13}\x{9A19}' . + '\x{9A28}\x{9A2B}\x{9A30}\x{9A37}\x{9A3E}\x{9A40}\x{9A42}\x{9A43}\x{9A45}' . + '\x{9A4D}\x{9A55}\x{9A57}\x{9A5A}\x{9A5B}\x{9A5F}\x{9A62}\x{9A64}\x{9A65}' . + '\x{9A69}\x{9A6A}\x{9A6B}\x{9AA8}\x{9AAD}\x{9AB0}\x{9AB8}\x{9ABC}\x{9AC0}' . + '\x{9AC4}\x{9ACF}\x{9AD1}\x{9AD3}\x{9AD4}\x{9AD8}\x{9ADE}\x{9ADF}\x{9AE2}' . + '\x{9AE3}\x{9AE6}\x{9AEA}\x{9AEB}\x{9AED}\x{9AEE}\x{9AEF}\x{9AF1}\x{9AF4}' . + '\x{9AF7}\x{9AFB}\x{9B06}\x{9B18}\x{9B1A}\x{9B1F}\x{9B22}\x{9B23}\x{9B25}' . + '\x{9B27}\x{9B28}\x{9B29}\x{9B2A}\x{9B2E}\x{9B2F}\x{9B31}\x{9B32}\x{9B3B}' . + '\x{9B3C}\x{9B41}\x{9B42}\x{9B43}\x{9B44}\x{9B45}\x{9B4D}\x{9B4E}\x{9B4F}' . + '\x{9B51}\x{9B54}\x{9B58}\x{9B5A}\x{9B6F}\x{9B74}\x{9B83}\x{9B8E}\x{9B91}' . + '\x{9B92}\x{9B93}\x{9B96}\x{9B97}\x{9B9F}\x{9BA0}\x{9BA8}\x{9BAA}\x{9BAB}' . + '\x{9BAD}\x{9BAE}\x{9BB4}\x{9BB9}\x{9BC0}\x{9BC6}\x{9BC9}\x{9BCA}\x{9BCF}' . + '\x{9BD1}\x{9BD2}\x{9BD4}\x{9BD6}\x{9BDB}\x{9BE1}\x{9BE2}\x{9BE3}\x{9BE4}' . + '\x{9BE8}\x{9BF0}\x{9BF1}\x{9BF2}\x{9BF5}\x{9C04}\x{9C06}\x{9C08}\x{9C09}' . + '\x{9C0A}\x{9C0C}\x{9C0D}\x{9C10}\x{9C12}\x{9C13}\x{9C14}\x{9C15}\x{9C1B}' . + '\x{9C21}\x{9C24}\x{9C25}\x{9C2D}\x{9C2E}\x{9C2F}\x{9C30}\x{9C32}\x{9C39}' . + '\x{9C3A}\x{9C3B}\x{9C3E}\x{9C46}\x{9C47}\x{9C48}\x{9C52}\x{9C57}\x{9C5A}' . + '\x{9C60}\x{9C67}\x{9C76}\x{9C78}\x{9CE5}\x{9CE7}\x{9CE9}\x{9CEB}\x{9CEC}' . + '\x{9CF0}\x{9CF3}\x{9CF4}\x{9CF6}\x{9D03}\x{9D06}\x{9D07}\x{9D08}\x{9D09}' . + '\x{9D0E}\x{9D12}\x{9D15}\x{9D1B}\x{9D1F}\x{9D23}\x{9D26}\x{9D28}\x{9D2A}' . + '\x{9D2B}\x{9D2C}\x{9D3B}\x{9D3E}\x{9D3F}\x{9D41}\x{9D44}\x{9D46}\x{9D48}' . + '\x{9D50}\x{9D51}\x{9D59}\x{9D5C}\x{9D5D}\x{9D5E}\x{9D60}\x{9D61}\x{9D64}' . + '\x{9D6C}\x{9D6F}\x{9D72}\x{9D7A}\x{9D87}\x{9D89}\x{9D8F}\x{9D9A}\x{9DA4}' . + '\x{9DA9}\x{9DAB}\x{9DAF}\x{9DB2}\x{9DB4}\x{9DB8}\x{9DBA}\x{9DBB}\x{9DC1}' . + '\x{9DC2}\x{9DC4}\x{9DC6}\x{9DCF}\x{9DD3}\x{9DD9}\x{9DE6}\x{9DED}\x{9DEF}' . + '\x{9DF2}\x{9DF8}\x{9DF9}\x{9DFA}\x{9DFD}\x{9E1A}\x{9E1B}\x{9E1E}\x{9E75}' . + '\x{9E78}\x{9E79}\x{9E7D}\x{9E7F}\x{9E81}\x{9E88}\x{9E8B}\x{9E8C}\x{9E91}' . + '\x{9E92}\x{9E93}\x{9E95}\x{9E97}\x{9E9D}\x{9E9F}\x{9EA5}\x{9EA6}\x{9EA9}' . + '\x{9EAA}\x{9EAD}\x{9EB8}\x{9EB9}\x{9EBA}\x{9EBB}\x{9EBC}\x{9EBE}\x{9EBF}' . + '\x{9EC4}\x{9ECC}\x{9ECD}\x{9ECE}\x{9ECF}\x{9ED0}\x{9ED2}\x{9ED4}\x{9ED8}' . + '\x{9ED9}\x{9EDB}\x{9EDC}\x{9EDD}\x{9EDE}\x{9EE0}\x{9EE5}\x{9EE8}\x{9EEF}' . + '\x{9EF4}\x{9EF6}\x{9EF7}\x{9EF9}\x{9EFB}\x{9EFC}\x{9EFD}\x{9F07}\x{9F08}' . + '\x{9F0E}\x{9F13}\x{9F15}\x{9F20}\x{9F21}\x{9F2C}\x{9F3B}\x{9F3E}\x{9F4A}' . + '\x{9F4B}\x{9F4E}\x{9F4F}\x{9F52}\x{9F54}\x{9F5F}\x{9F60}\x{9F61}\x{9F62}' . + '\x{9F63}\x{9F66}\x{9F67}\x{9F6A}\x{9F6C}\x{9F72}\x{9F76}\x{9F77}\x{9F8D}' . + '\x{9F95}\x{9F9C}\x{9F9D}\x{9FA0}]{1,15}$/iu', +); diff --git a/lib/Zend/Validator/Iban.php b/lib/Zend/Validator/Iban.php new file mode 100644 index 0000000000000000000000000000000000000000..c7d9e4b716e96b2c4edd8150d57df7f13442b68f --- /dev/null +++ b/lib/Zend/Validator/Iban.php @@ -0,0 +1,278 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_I18n + */ + +namespace Zend\Validator; + +use Traversable; +use Zend\Stdlib\ArrayUtils; +use Zend\Validator\AbstractValidator; +use Zend\Validator\Exception; + +/** + * Validates IBAN Numbers (International Bank Account Numbers) + * + * @category Zend + * @package Zend_Validate + */ +class Iban extends AbstractValidator +{ + const NOTSUPPORTED = 'ibanNotSupported'; + const SEPANOTSUPPORTED = 'ibanSepaNotSupported'; + const FALSEFORMAT = 'ibanFalseFormat'; + const CHECKFAILED = 'ibanCheckFailed'; + + /** + * Validation failure message template definitions + * + * @var array + */ + protected $messageTemplates = array( + self::NOTSUPPORTED => "Unknown country within the IBAN", + self::SEPANOTSUPPORTED => "Countries outside the Single Euro Payments Area (SEPA) are not supported", + self::FALSEFORMAT => "The input has a false IBAN format", + self::CHECKFAILED => "The input has failed the IBAN check", + ); + + /** + * Optional country code by ISO 3166-1 + * + * @var string|null + */ + protected $countryCode; + + /** + * Optionally allow IBAN codes from non-SEPA countries. Defaults to true + * + * @var bool + */ + protected $allowNonSepa = true; + + /** + * The SEPA country codes + * + * @var array<ISO 3166-1> + */ + protected static $sepaCountries = array( + 'AT', 'BE', 'BG', 'CY', 'CZ', 'DK', 'FO', 'GL', 'EE', 'FI', 'FR', 'DE', + 'GI', 'GR', 'HU', 'IS', 'IE', 'IT', 'LV', 'LI', 'LT', 'LU', 'MT', 'MC', + 'NL', 'NO', 'PL', 'PT', 'RO', 'SK', 'SI', 'ES', 'SE', 'CH', 'GB' + ); + + /** + * IBAN regexes by country code + * + * @var array + */ + protected static $ibanRegex = array( + 'AD' => 'AD[0-9]{2}[0-9]{4}[0-9]{4}[A-Z0-9]{12}', + 'AE' => 'AE[0-9]{2}[0-9]{3}[0-9]{16}', + 'AL' => 'AL[0-9]{2}[0-9]{8}[A-Z0-9]{16}', + 'AT' => 'AT[0-9]{2}[0-9]{5}[0-9]{11}', + 'AZ' => 'AZ[0-9]{2}[A-Z]{4}[A-Z0-9]{20}', + 'BA' => 'BA[0-9]{2}[0-9]{3}[0-9]{3}[0-9]{8}[0-9]{2}', + 'BE' => 'BE[0-9]{2}[0-9]{3}[0-9]{7}[0-9]{2}', + 'BG' => 'BG[0-9]{2}[A-Z]{4}[0-9]{4}[0-9]{2}[A-Z0-9]{8}', + 'BH' => 'BH[0-9]{2}[A-Z]{4}[A-Z0-9]{14}', + 'CH' => 'CH[0-9]{2}[0-9]{5}[A-Z0-9]{12}', + 'CR' => 'CR[0-9]{2}[0-9]{3}[0-9]{14}', + 'CY' => 'CY[0-9]{2}[0-9]{3}[0-9]{5}[A-Z0-9]{16}', + 'CZ' => 'CZ[0-9]{2}[0-9]{20}', + 'DE' => 'DE[0-9]{2}[0-9]{8}[0-9]{10}', + 'DO' => 'DO[0-9]{2}[A-Z0-9]{4}[0-9]{20}', + 'DK' => 'DK[0-9]{2}[0-9]{14}', + 'EE' => 'EE[0-9]{2}[0-9]{2}[0-9]{2}[0-9]{11}[0-9]{1}', + 'ES' => 'ES[0-9]{2}[0-9]{4}[0-9]{4}[0-9]{1}[0-9]{1}[0-9]{10}', + 'FI' => 'FI[0-9]{2}[0-9]{6}[0-9]{7}[0-9]{1}', + 'FO' => 'FO[0-9]{2}[0-9]{4}[0-9]{9}[0-9]{1}', + 'FR' => 'FR[0-9]{2}[0-9]{5}[0-9]{5}[A-Z0-9]{11}[0-9]{2}', + 'GB' => 'GB[0-9]{2}[A-Z]{4}[0-9]{6}[0-9]{8}', + 'GE' => 'GE[0-9]{2}[A-Z]{2}[0-9]{16}', + 'GI' => 'GI[0-9]{2}[A-Z]{4}[A-Z0-9]{15}', + 'GL' => 'GL[0-9]{2}[0-9]{4}[0-9]{9}[0-9]{1}', + 'GR' => 'GR[0-9]{2}[0-9]{3}[0-9]{4}[A-Z0-9]{16}', + 'GT' => 'GT[0-9]{2}[A-Z0-9]{4}[A-Z0-9]{20}', + 'HR' => 'HR[0-9]{2}[0-9]{7}[0-9]{10}', + 'HU' => 'HU[0-9]{2}[0-9]{3}[0-9]{4}[0-9]{1}[0-9]{15}[0-9]{1}', + 'IE' => 'IE[0-9]{2}[A-Z]{4}[0-9]{6}[0-9]{8}', + 'IL' => 'IL[0-9]{2}[0-9]{3}[0-9]{3}[0-9]{13}', + 'IS' => 'IS[0-9]{2}[0-9]{4}[0-9]{2}[0-9]{6}[0-9]{10}', + 'IT' => 'IT[0-9]{2}[A-Z]{1}[0-9]{5}[0-9]{5}[A-Z0-9]{12}', + 'KW' => 'KW[0-9]{2}[A-Z]{4}[0-9]{22}', + 'KZ' => 'KZ[0-9]{2}[0-9]{3}[A-Z0-9]{13}', + 'LB' => 'LB[0-9]{2}[0-9]{4}[A-Z0-9]{20}', + 'LI' => 'LI[0-9]{2}[0-9]{5}[A-Z0-9]{12}', + 'LT' => 'LT[0-9]{2}[0-9]{5}[0-9]{11}', + 'LU' => 'LU[0-9]{2}[0-9]{3}[A-Z0-9]{13}', + 'LV' => 'LV[0-9]{2}[A-Z]{4}[A-Z0-9]{13}', + 'MC' => 'MC[0-9]{2}[0-9]{5}[0-9]{5}[A-Z0-9]{11}[0-9]{2}', + 'MD' => 'MD[0-9]{2}[A-Z0-9]{20}', + 'ME' => 'ME[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}', + 'MK' => 'MK[0-9]{2}[0-9]{3}[A-Z0-9]{10}[0-9]{2}', + 'MR' => 'MR13[0-9]{5}[0-9]{5}[0-9]{11}[0-9]{2}', + 'MT' => 'MT[0-9]{2}[A-Z]{4}[0-9]{5}[A-Z0-9]{18}', + 'MU' => 'MU[0-9]{2}[A-Z]{4}[0-9]{2}[0-9]{2}[0-9]{12}[0-9]{3}[A-Z]{3}', + 'NL' => 'NL[0-9]{2}[A-Z]{4}[0-9]{10}', + 'NO' => 'NO[0-9]{2}[0-9]{4}[0-9]{6}[0-9]{1}', + 'PK' => 'PK[0-9]{2}[A-Z]{4}[A-Z0-9]{16}', + 'PL' => 'PL[0-9]{2}[0-9]{8}[0-9]{16}', + 'PS' => 'PS[0-9]{2}[A-Z]{4}[A-Z0-9]{21}', + 'PT' => 'PT[0-9]{2}[0-9]{4}[0-9]{4}[0-9]{11}[0-9]{2}', + 'RO' => 'RO[0-9]{2}[A-Z]{4}[A-Z0-9]{16}', + 'RS' => 'RS[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}', + 'SA' => 'SA[0-9]{2}[0-9]{2}[A-Z0-9]{18}', + 'SE' => 'SE[0-9]{2}[0-9]{3}[0-9]{16}[0-9]{1}', + 'SI' => 'SI[0-9]{2}[0-9]{5}[0-9]{8}[0-9]{2}', + 'SK' => 'SK[0-9]{2}[0-9]{4}[0-9]{6}[0-9]{10}', + 'SM' => 'SM[0-9]{2}[A-Z]{1}[0-9]{5}[0-9]{5}[A-Z0-9]{12}', + 'TN' => 'TN59[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}', + 'TR' => 'TR[0-9]{2}[0-9]{5}[A-Z0-9]{1}[A-Z0-9]{16}', + 'VG' => 'VG[0-9]{2}[A-Z]{4}[0-9]{16}', + ); + + /** + * Sets validator options + * + * @param array|Traversable $options OPTIONAL + */ + public function __construct($options = array()) + { + if ($options instanceof Traversable) { + $options = ArrayUtils::iteratorToArray($options); + } + + if (array_key_exists('country_code', $options)) { + $this->setCountryCode($options['country_code']); + } + + if (array_key_exists('allow_non_sepa', $options)) { + $this->setAllowNonSepa($options['allow_non_sepa']); + } + + parent::__construct($options); + } + + /** + * Returns the optional country code by ISO 3166-1 + * + * @return string|null + */ + public function getCountryCode() + { + return $this->countryCode; + } + + /** + * Sets an optional country code by ISO 3166-1 + * + * @param string|null $countryCode + * @return Iban provides a fluent interface + * @throws Exception\InvalidArgumentException + */ + public function setCountryCode($countryCode = null) + { + if ($countryCode !== null) { + $countryCode = (string) $countryCode; + + if (!isset(self::$ibanRegex[$countryCode])) { + throw new Exception\InvalidArgumentException( + "Country code '{$countryCode}' invalid by ISO 3166-1 or not supported" + ); + } + } + + $this->countryCode = $countryCode; + return $this; + } + + /** + * Returns the optional allow non-sepa countries setting + * + * @return bool + */ + public function allowNonSepa() + { + return $this->allowNonSepa; + } + + /** + * Sets the optional allow non-sepa countries setting + * + * @param bool $allowNonSepa + * @return Iban provides a fluent interface + */ + public function setAllowNonSepa($allowNonSepa) + { + $this->allowNonSepa = (bool) $allowNonSepa; + return $this; + } + + /** + * Returns true if $value is a valid IBAN + * + * @param string $value + * @return bool + */ + public function isValid($value) + { + if (!is_string($value)) { + $this->error(self::FALSEFORMAT); + return false; + } + + $value = strtoupper($value); + $this->setValue($value); + + $countryCode = $this->getCountryCode(); + if ($countryCode === null) { + $countryCode = substr($value, 0, 2); + } + + if (!array_key_exists($countryCode, self::$ibanRegex)) { + $this->setValue($countryCode); + $this->error(self::NOTSUPPORTED); + return false; + } + + if (!$this->allowNonSepa && !in_array($countryCode, self::$sepaCountries)) { + $this->setValue($countryCode); + $this->error(self::SEPANOTSUPPORTED); + return false; + } + + if (!preg_match('/^' . self::$ibanRegex[$countryCode] . '$/', $value)) { + $this->error(self::FALSEFORMAT); + return false; + } + + $format = substr($value, 4) . substr($value, 0, 4); + $format = str_replace( + array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'), + array('10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', + '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35'), + $format + ); + + $temp = intval(substr($format, 0, 1)); + $len = strlen($format); + for ($x = 1; $x < $len; ++$x) { + $temp *= 10; + $temp += intval(substr($format, $x, 1)); + $temp %= 97; + } + + if ($temp != 1) { + $this->error(self::CHECKFAILED); + return false; + } + + return true; + } +} diff --git a/lib/Zend/Validator/Identical.php b/lib/Zend/Validator/Identical.php new file mode 100644 index 0000000000000000000000000000000000000000..20afe737ae587dd05c1c101f29a913a10091ce1d --- /dev/null +++ b/lib/Zend/Validator/Identical.php @@ -0,0 +1,153 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator; + +use Traversable; +use Zend\Stdlib\ArrayUtils; + +/** + * @category Zend + * @package Zend_Validate + */ +class Identical extends AbstractValidator +{ + /** + * Error codes + * @const string + */ + const NOT_SAME = 'notSame'; + const MISSING_TOKEN = 'missingToken'; + + /** + * Error messages + * @var array + */ + protected $messageTemplates = array( + self::NOT_SAME => "The two given tokens do not match", + self::MISSING_TOKEN => 'No token was provided to match against', + ); + + /** + * @var array + */ + protected $messageVariables = array( + 'token' => 'tokenString' + ); + + /** + * Original token against which to validate + * @var string + */ + protected $tokenString; + protected $token; + protected $strict = true; + + /** + * Sets validator options + * + * @param mixed $token + */ + public function __construct($token = null) + { + if ($token instanceof Traversable) { + $token = ArrayUtils::iteratorToArray($token); + } + + if (is_array($token) && array_key_exists('token', $token)) { + if (array_key_exists('strict', $token)) { + $this->setStrict($token['strict']); + } + + $this->setToken($token['token']); + } elseif (null !== $token) { + $this->setToken($token); + } + + parent::__construct(is_array($token) ? $token : null); + } + + /** + * Retrieve token + * + * @return string + */ + public function getToken() + { + return $this->token; + } + + /** + * Set token against which to compare + * + * @param mixed $token + * @return Identical + */ + public function setToken($token) + { + $this->tokenString = (is_array($token) ? implode($token) : (string) $token); + $this->token = $token; + return $this; + } + + /** + * Returns the strict parameter + * + * @return boolean + */ + public function getStrict() + { + return $this->strict; + } + + /** + * Sets the strict parameter + * + * @param Zend\Validator\Identical + * @return Identical + */ + public function setStrict($strict) + { + $this->strict = (boolean) $strict; + return $this; + } + + /** + * Returns true if and only if a token has been set and the provided value + * matches that token. + * + * @param mixed $value + * @param array $context + * @return boolean + */ + public function isValid($value, $context = null) + { + $this->setValue($value); + + if (($context !== null) && isset($context) && array_key_exists($this->getToken(), $context)) { + $token = $context[$this->getToken()]; + } else { + $token = $this->getToken(); + } + + if ($token === null) { + $this->error(self::MISSING_TOKEN); + return false; + } + + $strict = $this->getStrict(); + if (($strict && ($value !== $token)) || (!$strict && ($value != $token))) { + $this->error(self::NOT_SAME); + return false; + } + + return true; + } +} diff --git a/lib/Zend/Validator/InArray.php b/lib/Zend/Validator/InArray.php new file mode 100644 index 0000000000000000000000000000000000000000..8e89775e3e64aa33649dd38cb5deed637738f182 --- /dev/null +++ b/lib/Zend/Validator/InArray.php @@ -0,0 +1,239 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator; + +use RecursiveArrayIterator; +use RecursiveIteratorIterator; + +/** + * @category Zend + * @package Zend_Validate + */ +class InArray extends AbstractValidator +{ + const NOT_IN_ARRAY = 'notInArray'; + + // Type of Strict check + /** + * standard in_array strict checking value and type + */ + const COMPARE_STRICT = 1; + + /** + * Non strict check but prevents "asdf" == 0 returning TRUE causing false/positive. + * This is the most secure option for non-strict checks and replaces strict = false + * This will only be effective when the input is a string + */ + const COMPARE_NOT_STRICT_AND_PREVENT_STR_TO_INT_VULNERABILITY = 0; + + /** + * Standard non-strict check where "asdf" == 0 returns TRUE + * This will be wanted when comparing "0" against int 0 + */ + const COMPARE_NOT_STRICT = -1; + + + /** + * @var array + */ + protected $messageTemplates = array( + self::NOT_IN_ARRAY => 'The input was not found in the haystack', + ); + + /** + * Haystack of possible values + * + * @var array + */ + protected $haystack; + + /** + * Type of strict check to be used. Due to "foo" == 0 === TRUE with in_array when strict = false, + * an option has been added to prevent this. When $strict = 0/false, the most + * secure non-strict check is implemented. if $strict = -1, the default in_array non-strict + * behaviour is used + * + * @var int + */ + protected $strict = self::COMPARE_NOT_STRICT_AND_PREVENT_STR_TO_INT_VULNERABILITY; + + /** + * Whether a recursive search should be done + * + * @var boolean + */ + protected $recursive = false; + + /** + * Returns the haystack option + * + * @return mixed + * @throws Exception\RuntimeException if haystack option is not set + */ + public function getHaystack() + { + if ($this->haystack == null) { + throw new Exception\RuntimeException('haystack option is mandatory'); + } + return $this->haystack; + } + + /** + * Sets the haystack option + * + * @param mixed $haystack + * @return InArray Provides a fluent interface + */ + public function setHaystack(array $haystack) + { + $this->haystack = $haystack; + return $this; + } + + /** + * Returns the strict option + * + * @return boolean|int + */ + public function getStrict() + { + // To keep BC with new strict modes + if ($this->strict == self::COMPARE_NOT_STRICT_AND_PREVENT_STR_TO_INT_VULNERABILITY + || $this->strict == self::COMPARE_STRICT + ) { + return (bool) $this->strict; + } + return $this->strict; + } + + /** + * Sets the strict option mode + * InArray::CHECK_STRICT | InArray::CHECK_NOT_STRICT_AND_PREVENT_STR_TO_INT_VULNERABILITY | InArray::CHECK_NOT_STRICT + * + * @param int $strict + * @return InArray Provides a fluent interface + * @throws Exception\InvalidArgumentException + */ + public function setStrict($strict) + { + $checkTypes = array( + self::COMPARE_NOT_STRICT_AND_PREVENT_STR_TO_INT_VULNERABILITY, // 0 + self::COMPARE_STRICT, // 1 + self::COMPARE_NOT_STRICT // -1 + ); + + // validate strict value + if (!in_array($strict, $checkTypes)) { + throw new Exception\InvalidArgumentException('Strict option must be one of the COMPARE_ constants'); + } + + $this->strict = $strict; + return $this; + } + + /** + * Returns the recursive option + * + * @return boolean + */ + public function getRecursive() + { + return $this->recursive; + } + + /** + * Sets the recursive option + * + * @param boolean $recursive + * @return InArray Provides a fluent interface + */ + public function setRecursive($recursive) + { + $this->recursive = (boolean) $recursive; + return $this; + } + + /** + * Returns true if and only if $value is contained in the haystack option. If the strict + * option is true, then the type of $value is also checked. + * + * @param mixed $value + * See {@link http://php.net/manual/function.in-array.php#104501} + * @return boolean + */ + public function isValid($value) + { + // we create a copy of the haystack in case we need to modify it + $haystack = $this->getHaystack(); + + // if the input is a string or float, and vulnerability protection is on + // we type cast the input to a string + if (self::COMPARE_NOT_STRICT_AND_PREVENT_STR_TO_INT_VULNERABILITY == $this->strict + && (is_int($value) || is_float($value))) { + $value =(string) $value; + } + + $this->setValue($value); + + if ($this->getRecursive()) { + $iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($haystack)); + foreach ($iterator as $element) { + if (self::COMPARE_STRICT == $this->strict) { + + if ($element === $value) { + return true; + } + + } else { + + // add protection to prevent string to int vuln's + $el = $element; + if (self::COMPARE_NOT_STRICT_AND_PREVENT_STR_TO_INT_VULNERABILITY == $this->strict + && is_string($value) && (is_int($el) || is_float($el)) + ) { + $el = (string)$el; + } + + if ($el == $value) { + return true; + } + + } + } + } else { + + /** + * If the check is not strict, then, to prevent "asdf" being converted to 0 + * and returning a false positive if 0 is in haystack, we type cast + * the haystack to strings. To prevent "56asdf" == 56 === TRUE we also + * type cast values like 56 to strings as well. + * + * This occurs only if the input is a string and a haystack member is an int + */ + if (self::COMPARE_NOT_STRICT_AND_PREVENT_STR_TO_INT_VULNERABILITY == $this->strict + && is_string($value) + ) { + foreach ($haystack as &$h) { + if (is_int($h) || is_float($h)) { + $h = (string)$h; + } + } + } + + if (in_array($value, $haystack, $this->strict == self::COMPARE_STRICT ? true : false)) { + return true; + } + } + + $this->error(self::NOT_IN_ARRAY); + return false; + } +} diff --git a/lib/Zend/Validator/Ip.php b/lib/Zend/Validator/Ip.php new file mode 100644 index 0000000000000000000000000000000000000000..c64573ede799eeeb1c8d77e91a0e7abd4c2b2495 --- /dev/null +++ b/lib/Zend/Validator/Ip.php @@ -0,0 +1,195 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator; + +use Traversable; +use Zend\Stdlib\ArrayUtils; + +/** + * @category Zend + * @package Zend_Validate + */ +class Ip extends AbstractValidator +{ + const INVALID = 'ipInvalid'; + const NOT_IP_ADDRESS = 'notIpAddress'; + + /** + * @var array + */ + protected $messageTemplates = array( + self::INVALID => 'Invalid type given. String expected', + self::NOT_IP_ADDRESS => "The input does not appear to be a valid IP address", + ); + + /** + * Internal options + * + * @var array + */ + protected $options = array( + 'allowipv4' => true, // Enable IPv4 Validation + 'allowipv6' => true, // Enable IPv6 Validation + 'allowipvfuture' => false, // Enable IPvFuture Validation + 'allowliteral' => true, // Enable IPs in literal format (only IPv6 and IPvFuture) + ); + + /** + * Sets the options for this validator + * + * @param array|Traversable $options + * @throws Exception\InvalidArgumentException If there is any kind of IP allowed or $options is not an array or Traversable. + * @return AbstractValidator + */ + public function setOptions($options = array()) + { + parent::setOptions($options); + + if (!$this->options['allowipv4'] && !$this->options['allowipv6'] && !$this->options['allowipvfuture']) { + throw new Exception\InvalidArgumentException('Nothing to validate. Check your options'); + } + + return $this; + } + + /** + * Returns true if and only if $value is a valid IP address + * + * @param mixed $value + * @return boolean + */ + public function isValid($value) + { + if (!is_string($value)) { + $this->error(self::INVALID); + return false; + } + + $this->setValue($value); + + if ($this->options['allowipv4'] && $this->validateIPv4($value)) { + return true; + } else { + if ((bool) $this->options['allowliteral']) { + static $regex = '/^\[(.*)\]$/'; + if ((bool) preg_match($regex, $value, $matches)) { + $value = $matches[1]; + } + } + + if (($this->options['allowipv6'] && $this->validateIPv6($value)) || + ($this->options['allowipvfuture'] && $this->validateIPvFuture($value)) + ) { + return true; + } + } + $this->error(self::NOT_IP_ADDRESS); + return false; + } + + /** + * Validates an IPv4 address + * + * @param string $value + * @return boolean + */ + protected function validateIPv4($value) + { + if (preg_match('/^([01]{8}.){3}[01]{8}$/i', $value)) { + // binary format 00000000.00000000.00000000.00000000 + $value = bindec(substr($value, 0, 8)) . '.' . bindec(substr($value, 9, 8)) . '.' + . bindec(substr($value, 18, 8)) . '.' . bindec(substr($value, 27, 8)); + } elseif (preg_match('/^([0-9]{3}.){3}[0-9]{3}$/i', $value)) { + // octet format 777.777.777.777 + $value = (int) substr($value, 0, 3) . '.' . (int) substr($value, 4, 3) . '.' + . (int) substr($value, 8, 3) . '.' . (int) substr($value, 12, 3); + } elseif (preg_match('/^([0-9a-f]{2}.){3}[0-9a-f]{2}$/i', $value)) { + // hex format ff.ff.ff.ff + $value = hexdec(substr($value, 0, 2)) . '.' . hexdec(substr($value, 3, 2)) . '.' + . hexdec(substr($value, 6, 2)) . '.' . hexdec(substr($value, 9, 2)); + } + + $ip2long = ip2long($value); + if ($ip2long === false) { + return false; + } + + return ($value == long2ip($ip2long)); + } + + /** + * Validates an IPv6 address + * + * @param string $value Value to check against + * @return boolean True when $value is a valid ipv6 address + * False otherwise + */ + protected function validateIPv6($value) + { + if (strlen($value) < 3) { + return $value == '::'; + } + + if (strpos($value, '.')) { + $lastcolon = strrpos($value, ':'); + if (!($lastcolon && $this->validateIPv4(substr($value, $lastcolon + 1)))) { + return false; + } + + $value = substr($value, 0, $lastcolon) . ':0:0'; + } + + if (strpos($value, '::') === false) { + return preg_match('/\A(?:[a-f0-9]{1,4}:){7}[a-f0-9]{1,4}\z/i', $value); + } + + $colonCount = substr_count($value, ':'); + if ($colonCount < 8) { + return preg_match('/\A(?::|(?:[a-f0-9]{1,4}:)+):(?:(?:[a-f0-9]{1,4}:)*[a-f0-9]{1,4})?\z/i', $value); + } + + // special case with ending or starting double colon + if ($colonCount == 8) { + return preg_match('/\A(?:::)?(?:[a-f0-9]{1,4}:){6}[a-f0-9]{1,4}(?:::)?\z/i', $value); + } + + return false; + } + + /** + * Validates an IPvFuture address. + * + * IPvFuture is loosely defined in the Section 3.2.2 of RFC 3986 + * + * @param string $value Value to check against + * @return boolean True when $value is a valid IPvFuture address + * False otherwise + */ + protected function validateIPvFuture($value) + { + /* + * ABNF: + * IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" ) + * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," + * / ";" / "=" + */ + static $regex = '/^v([[:xdigit:]]+)\.[[:alnum:]\-\._~!\$&\'\(\)\*\+,;=:]+$/'; + + $result = (bool)preg_match($regex, $value, $matches); + + /* + * "As such, implementations must not provide the version flag for the + * existing IPv4 and IPv6 literal address forms described below." + */ + return ($result && $matches[1] != 4 && $matches[1] != 6); + } +} diff --git a/lib/Zend/Validator/Isbn.php b/lib/Zend/Validator/Isbn.php new file mode 100644 index 0000000000000000000000000000000000000000..1550083a9f9263fe4a000f1549715c0a10c5e55d --- /dev/null +++ b/lib/Zend/Validator/Isbn.php @@ -0,0 +1,213 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator; + +/** + * @category Zend + * @package Zend_Validate + */ +class Isbn extends AbstractValidator +{ + const AUTO = 'auto'; + const ISBN10 = '10'; + const ISBN13 = '13'; + const INVALID = 'isbnInvalid'; + const NO_ISBN = 'isbnNoIsbn'; + + /** + * Validation failure message template definitions. + * + * @var array + */ + protected $messageTemplates = array( + self::INVALID => "Invalid type given. String or integer expected", + self::NO_ISBN => "The input is not a valid ISBN number", + ); + + protected $options = array( + 'type' => self::AUTO, // Allowed type + 'separator' => '', // Separator character + ); + + /** + * Detect input format. + * + * @return string + */ + protected function detectFormat() + { + // prepare separator and pattern list + $sep = quotemeta($this->getSeparator()); + $patterns = array(); + $lengths = array(); + $type = $this->getType(); + + // check for ISBN-10 + if ($type == self::ISBN10 || $type == self::AUTO) { + if (empty($sep)) { + $pattern = '/^[0-9]{9}[0-9X]{1}$/'; + $length = 10; + } else { + $pattern = "/^[0-9]{1,7}[{$sep}]{1}[0-9]{1,7}[{$sep}]{1}[0-9]{1,7}[{$sep}]{1}[0-9X]{1}$/"; + $length = 13; + } + + $patterns[$pattern] = self::ISBN10; + $lengths[$pattern] = $length; + } + + // check for ISBN-13 + if ($type == self::ISBN13 || $type == self::AUTO) { + if (empty($sep)) { + $pattern = '/^[0-9]{13}$/'; + $length = 13; + } else { + $pattern = "/^[0-9]{1,9}[{$sep}]{1}[0-9]{1,5}[{$sep}]{1}[0-9]{1,9}[{$sep}]{1}[0-9]{1,9}[{$sep}]{1}[0-9]{1}$/"; + $length = 17; + } + + $patterns[$pattern] = self::ISBN13; + $lengths[$pattern] = $length; + } + + // check pattern list + foreach ($patterns as $pattern => $type) { + if ((strlen($this->getValue()) == $lengths[$pattern]) && preg_match($pattern, $this->getValue())) { + return $type; + } + } + + return null; + } + + /** + * Returns true if and only if $value is a valid ISBN. + * + * @param string $value + * @return boolean + */ + public function isValid($value) + { + if (!is_string($value) && !is_int($value)) { + $this->error(self::INVALID); + return false; + } + + $value = (string) $value; + $this->setValue($value); + + switch ($this->detectFormat()) { + case self::ISBN10: + // sum + $isbn10 = str_replace($this->getSeparator(), '', $value); + $sum = 0; + for ($i = 0; $i < 9; $i++) { + $sum += (10 - $i) * $isbn10{$i}; + } + + // checksum + $checksum = 11 - ($sum % 11); + if ($checksum == 11) { + $checksum = '0'; + } elseif ($checksum == 10) { + $checksum = 'X'; + } + break; + + case self::ISBN13: + // sum + $isbn13 = str_replace($this->getSeparator(), '', $value); + $sum = 0; + for ($i = 0; $i < 12; $i++) { + if ($i % 2 == 0) { + $sum += $isbn13{$i}; + } else { + $sum += 3 * $isbn13{$i}; + } + } + // checksum + $checksum = 10 - ($sum % 10); + if ($checksum == 10) { + $checksum = '0'; + } + break; + + default: + $this->error(self::NO_ISBN); + return false; + } + + // validate + if (substr($this->getValue(), -1) != $checksum) { + $this->error(self::NO_ISBN); + return false; + } + return true; + } + + /** + * Set separator characters. + * + * It is allowed only empty string, hyphen and space. + * + * @param string $separator + * @throws Exception\InvalidArgumentException When $separator is not valid + * @return Isbn Provides a fluent interface + */ + public function setSeparator($separator) + { + // check separator + if (!in_array($separator, array('-', ' ', ''))) { + throw new Exception\InvalidArgumentException('Invalid ISBN separator.'); + } + + $this->options['separator'] = $separator; + return $this; + } + + /** + * Get separator characters. + * + * @return string + */ + public function getSeparator() + { + return $this->options['separator']; + } + + /** + * Set allowed ISBN type. + * + * @param string $type + * @throws Exception\InvalidArgumentException When $type is not valid + * @return Isbn Provides a fluent interface + */ + public function setType($type) + { + // check type + if (!in_array($type, array(self::AUTO, self::ISBN10, self::ISBN13))) { + throw new Exception\InvalidArgumentException('Invalid ISBN type'); + } + + $this->options['type'] = $type; + return $this; + } + + /** + * Get allowed ISBN type. + * + * @return string + */ + public function getType() + { + return $this->options['type']; + } +} diff --git a/lib/Zend/Validator/LessThan.php b/lib/Zend/Validator/LessThan.php new file mode 100644 index 0000000000000000000000000000000000000000..c29a2c3781efd99c91aaa43c8da35bec5b44f244 --- /dev/null +++ b/lib/Zend/Validator/LessThan.php @@ -0,0 +1,166 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator; + +use Traversable; +use Zend\Stdlib\ArrayUtils; + +/** + * @category Zend + * @package Zend_Validate + */ +class LessThan extends AbstractValidator +{ + const NOT_LESS = 'notLessThan'; + const NOT_LESS_INCLUSIVE = 'notLessThanInclusive'; + + /** + * Validation failure message template definitions + * + * @var array + */ + protected $messageTemplates = array( + self::NOT_LESS => "The input is not less than '%max%'", + self::NOT_LESS_INCLUSIVE => "The input is not less or equal than '%max%'" + ); + + /** + * Additional variables available for validation failure messages + * + * @var array + */ + protected $messageVariables = array( + 'max' => 'max' + ); + + /** + * Maximum value + * + * @var mixed + */ + protected $max; + + /** + * Whether to do inclusive comparisons, allowing equivalence to max + * + * If false, then strict comparisons are done, and the value may equal + * the max option + * + * @var boolean + */ + protected $inclusive; + + /** + * Sets validator options + * + * @param array|Traversable $options + * @throws Exception\InvalidArgumentException + */ + public function __construct($options = null) + { + if ($options instanceof Traversable) { + $options = ArrayUtils::iteratorToArray($options); + } + if (!is_array($options)) { + $options = func_get_args(); + $temp['max'] = array_shift($options); + + if (!empty($options)) { + $temp['inclusive'] = array_shift($options); + } + + $options = $temp; + } + + if (!array_key_exists('max', $options)) { + throw new Exception\InvalidArgumentException("Missing option 'max'"); + } + + if (!array_key_exists('inclusive', $options)) { + $options['inclusive'] = false; + } + + $this->setMax($options['max']) + ->setInclusive($options['inclusive']); + + parent::__construct($options); + } + + /** + * Returns the max option + * + * @return mixed + */ + public function getMax() + { + return $this->max; + } + + /** + * Sets the max option + * + * @param mixed $max + * @return LessThan Provides a fluent interface + */ + public function setMax($max) + { + $this->max = $max; + return $this; + } + + /** + * Returns the inclusive option + * + * @return boolean + */ + public function getInclusive() + { + return $this->inclusive; + } + + /** + * Sets the inclusive option + * + * @param boolean $inclusive + * @return LessThan Provides a fluent interface + */ + public function setInclusive($inclusive) + { + $this->inclusive = $inclusive; + return $this; + } + + /** + * Returns true if and only if $value is less than max option, inclusively + * when the inclusive option is true + * + * @param mixed $value + * @return boolean + */ + public function isValid($value) + { + $this->setValue($value); + + if ($this->inclusive) { + if ($value > $this->max) { + $this->error(self::NOT_LESS_INCLUSIVE); + return false; + } + } else { + if ($value >= $this->max) { + $this->error(self::NOT_LESS); + return false; + } + } + + return true; + } +} diff --git a/lib/Zend/Validator/NotEmpty.php b/lib/Zend/Validator/NotEmpty.php new file mode 100644 index 0000000000000000000000000000000000000000..1c4c379de5f54c18782220f367ffb533b0f7c566 --- /dev/null +++ b/lib/Zend/Validator/NotEmpty.php @@ -0,0 +1,283 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator; + +use Traversable; +use Zend\Stdlib\ArrayUtils; + +/** + * @category Zend + * @package Zend_Validate + */ +class NotEmpty extends AbstractValidator +{ + const BOOLEAN = 1; + const INTEGER = 2; + const FLOAT = 4; + const STRING = 8; + const ZERO = 16; + const EMPTY_ARRAY = 32; + const NULL = 64; + const PHP = 127; + const SPACE = 128; + const OBJECT = 256; + const OBJECT_STRING = 512; + const OBJECT_COUNT = 1024; + const ALL = 2047; + + const INVALID = 'notEmptyInvalid'; + const IS_EMPTY = 'isEmpty'; + + protected $constants = array( + self::BOOLEAN => 'boolean', + self::INTEGER => 'integer', + self::FLOAT => 'float', + self::STRING => 'string', + self::ZERO => 'zero', + self::EMPTY_ARRAY => 'array', + self::NULL => 'null', + self::PHP => 'php', + self::SPACE => 'space', + self::OBJECT => 'object', + self::OBJECT_STRING => 'objectstring', + self::OBJECT_COUNT => 'objectcount', + self::ALL => 'all', + ); + + /** + * @var array + */ + protected $messageTemplates = array( + self::IS_EMPTY => "Value is required and can't be empty", + self::INVALID => "Invalid type given. String, integer, float, boolean or array expected", + ); + + /** + * Options for this validator + * + * @var array + */ + protected $options = array( + 'type' => 493, // Internal type to detect + ); + + /** + * Constructor + * + * @param array|Traversable|int $options OPTIONAL + */ + public function __construct($options = null) + { + if ($options instanceof Traversable) { + $options = ArrayUtils::iteratorToArray($options); + } + + if (!is_array($options)) { + $options = func_get_args(); + $temp = array(); + if (!empty($options)) { + $temp['type'] = array_shift($options); + } + + $options = $temp; + } + + if (is_array($options)) { + if (!array_key_exists('type', $options)) { + $detected = 0; + $found = false; + foreach ($options as $option) { + if (in_array($option, $this->constants)) { + $found = true; + $detected += array_search($option, $this->constants); + } + } + + if ($found) { + $options['type'] = $detected; + } + } + } + + parent::__construct($options); + } + + /** + * Returns the set types + * + * @return array + */ + public function getType() + { + return $this->options['type']; + } + + /** + * Set the types + * + * @param integer|array $type + * @throws Exception\InvalidArgumentException + * @return NotEmpty + */ + public function setType($type = null) + { + if (is_array($type)) { + $detected = 0; + foreach ($type as $value) { + if (is_int($value)) { + $detected += $value; + } elseif (in_array($value, $this->constants)) { + $detected += array_search($value, $this->constants); + } + } + + $type = $detected; + } elseif (is_string($type) && in_array($type, $this->constants)) { + $type = array_search($type, $this->constants); + } + + if (!is_int($type) || ($type < 0) || ($type > self::ALL)) { + throw new Exception\InvalidArgumentException('Unknown type'); + } + + $this->options['type'] = $type; + return $this; + } + + /** + * Returns true if and only if $value is not an empty value. + * + * @param string $value + * @return boolean + */ + public function isValid($value) + { + if ($value !== null && !is_string($value) && !is_int($value) && !is_float($value) && + !is_bool($value) && !is_array($value) && !is_object($value) + ) { + $this->error(self::INVALID); + return false; + } + + $type = $this->getType(); + $this->setValue($value); + $object = false; + + // OBJECT_COUNT (countable object) + if ($type >= self::OBJECT_COUNT) { + $type -= self::OBJECT_COUNT; + $object = true; + + if (is_object($value) && ($value instanceof \Countable) && (count($value) == 0)) { + $this->error(self::IS_EMPTY); + return false; + } + } + + // OBJECT_STRING (object's toString) + if ($type >= self::OBJECT_STRING) { + $type -= self::OBJECT_STRING; + $object = true; + + if ((is_object($value) && (!method_exists($value, '__toString'))) || + (is_object($value) && (method_exists($value, '__toString')) && (((string) $value) == ""))) { + $this->error(self::IS_EMPTY); + return false; + } + } + + // OBJECT (object) + if ($type >= self::OBJECT) { + $type -= self::OBJECT; + // fall trough, objects are always not empty + } elseif ($object === false) { + // object not allowed but object given -> return false + if (is_object($value)) { + $this->error(self::IS_EMPTY); + return false; + } + } + + // SPACE (' ') + if ($type >= self::SPACE) { + $type -= self::SPACE; + if (is_string($value) && (preg_match('/^\s+$/s', $value))) { + $this->error(self::IS_EMPTY); + return false; + } + } + + // NULL (null) + if ($type >= self::NULL) { + $type -= self::NULL; + if ($value === null) { + $this->error(self::IS_EMPTY); + return false; + } + } + + // EMPTY_ARRAY (array()) + if ($type >= self::EMPTY_ARRAY) { + $type -= self::EMPTY_ARRAY; + if (is_array($value) && ($value == array())) { + $this->error(self::IS_EMPTY); + return false; + } + } + + // ZERO ('0') + if ($type >= self::ZERO) { + $type -= self::ZERO; + if (is_string($value) && ($value == '0')) { + $this->error(self::IS_EMPTY); + return false; + } + } + + // STRING ('') + if ($type >= self::STRING) { + $type -= self::STRING; + if (is_string($value) && ($value == '')) { + $this->error(self::IS_EMPTY); + return false; + } + } + + // FLOAT (0.0) + if ($type >= self::FLOAT) { + $type -= self::FLOAT; + if (is_float($value) && ($value == 0.0)) { + $this->error(self::IS_EMPTY); + return false; + } + } + + // INTEGER (0) + if ($type >= self::INTEGER) { + $type -= self::INTEGER; + if (is_int($value) && ($value == 0)) { + $this->error(self::IS_EMPTY); + return false; + } + } + + // BOOLEAN (false) + if ($type >= self::BOOLEAN) { + $type -= self::BOOLEAN; + if (is_bool($value) && ($value == false)) { + $this->error(self::IS_EMPTY); + return false; + } + } + + return true; + } +} diff --git a/lib/Zend/Validator/Regex.php b/lib/Zend/Validator/Regex.php new file mode 100644 index 0000000000000000000000000000000000000000..e4ced1dddf2750ee5cf8d572201af36ee2952534 --- /dev/null +++ b/lib/Zend/Validator/Regex.php @@ -0,0 +1,142 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator; + +use Traversable; +use Zend\Stdlib\ArrayUtils; +use Zend\Stdlib\ErrorHandler; + +/** + * @category Zend + * @package Zend_Validate + */ +class Regex extends AbstractValidator +{ + const INVALID = 'regexInvalid'; + const NOT_MATCH = 'regexNotMatch'; + const ERROROUS = 'regexErrorous'; + + /** + * @var array + */ + protected $messageTemplates = array( + self::INVALID => "Invalid type given. String, integer or float expected", + self::NOT_MATCH => "The input does not match against pattern '%pattern%'", + self::ERROROUS => "There was an internal error while using the pattern '%pattern%'", + ); + + /** + * @var array + */ + protected $messageVariables = array( + 'pattern' => 'pattern' + ); + + /** + * Regular expression pattern + * + * @var string + */ + protected $pattern; + + /** + * Sets validator options + * + * @param string|Traversable $pattern + * @throws Exception\InvalidArgumentException On missing 'pattern' parameter + */ + public function __construct($pattern) + { + if (is_string($pattern)) { + $this->setPattern($pattern); + parent::__construct(array()); + return; + } + + if ($pattern instanceof Traversable) { + $pattern = ArrayUtils::iteratorToArray($pattern); + } + + if (!is_array($pattern)) { + throw new Exception\InvalidArgumentException('Invalid options provided to constructor'); + } + + if (!array_key_exists('pattern', $pattern)) { + throw new Exception\InvalidArgumentException("Missing option 'pattern'"); + } + + $this->setPattern($pattern['pattern']); + unset($pattern['pattern']); + parent::__construct($pattern); + } + + /** + * Returns the pattern option + * + * @return string + */ + public function getPattern() + { + return $this->pattern; + } + + /** + * Sets the pattern option + * + * @param string $pattern + * @throws Exception\InvalidArgumentException if there is a fatal error in pattern matching + * @return Regex Provides a fluent interface + */ + public function setPattern($pattern) + { + ErrorHandler::start(); + $this->pattern = (string) $pattern; + $status = preg_match($this->pattern, "Test"); + $error = ErrorHandler::stop(); + + if (false === $status) { + throw new Exception\InvalidArgumentException("Internal error parsing the pattern '{$this->pattern}'", 0, $error); + } + + return $this; + } + + /** + * Returns true if and only if $value matches against the pattern option + * + * @param string $value + * @return boolean + */ + public function isValid($value) + { + if (!is_string($value) && !is_int($value) && !is_float($value)) { + $this->error(self::INVALID); + return false; + } + + $this->setValue($value); + + ErrorHandler::start(); + $status = preg_match($this->pattern, $value); + ErrorHandler::stop(); + if (false === $status) { + $this->error(self::ERROROUS); + return false; + } + + if (!$status) { + $this->error(self::NOT_MATCH); + return false; + } + + return true; + } +} diff --git a/lib/Zend/Validator/Sitemap/Changefreq.php b/lib/Zend/Validator/Sitemap/Changefreq.php new file mode 100644 index 0000000000000000000000000000000000000000..66c7c7c9965959784c878fe5f2af4014713e14c5 --- /dev/null +++ b/lib/Zend/Validator/Sitemap/Changefreq.php @@ -0,0 +1,80 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Sitemap; + +use Zend\Validator\AbstractValidator; + +/** + * Validates whether a given value is valid as a sitemap <changefreq> value + * + * @link http://www.sitemaps.org/protocol.php Sitemaps XML format + * + * @category Zend + * @package Zend_Validate + * @subpackage Sitemap + */ +class Changefreq extends AbstractValidator +{ + /** + * Validation key for not valid + * + */ + const NOT_VALID = 'sitemapChangefreqNotValid'; + const INVALID = 'sitemapChangefreqInvalid'; + + /** + * Validation failure message template definitions + * + * @var array + */ + protected $messageTemplates = array( + self::NOT_VALID => "The input is not a valid sitemap changefreq", + self::INVALID => "Invalid type given. String expected", + ); + + /** + * Valid change frequencies + * + * @var array + */ + protected $changeFreqs = array( + 'always', 'hourly', 'daily', 'weekly', + 'monthly', 'yearly', 'never' + ); + + /** + * Validates if a string is valid as a sitemap changefreq + * + * @link http://www.sitemaps.org/protocol.php#changefreqdef <changefreq> + * + * @param string $value value to validate + * @return boolean + */ + public function isValid($value) + { + if (!is_string($value)) { + $this->error(self::INVALID); + return false; + } + + $this->setValue($value); + if (!is_string($value)) { + return false; + } + + if (!in_array($value, $this->changeFreqs, true)) { + $this->error(self::NOT_VALID); + return false; + } + + return true; + } +} diff --git a/lib/Zend/Validator/Sitemap/Lastmod.php b/lib/Zend/Validator/Sitemap/Lastmod.php new file mode 100644 index 0000000000000000000000000000000000000000..8dd46046897400e8e07d23b4fa845430b2daf3cb --- /dev/null +++ b/lib/Zend/Validator/Sitemap/Lastmod.php @@ -0,0 +1,76 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Sitemap; + +use Zend\Stdlib\ErrorHandler; +use Zend\Validator\AbstractValidator; + +/** + * Validates whether a given value is valid as a sitemap <lastmod> value + * + * @link http://www.sitemaps.org/protocol.php Sitemaps XML format + * + * @category Zend + * @package Zend_Validate + * @subpackage Sitemap + */ +class Lastmod extends AbstractValidator +{ + /** + * Regular expression to use when validating + * + */ + const LASTMOD_REGEX = '/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])(T([0-1][0-9]|2[0-3])(:[0-5][0-9])(:[0-5][0-9])?(\\+|-)([0-1][0-9]|2[0-3]):[0-5][0-9])?$/'; + + /** + * Validation key for not valid + * + */ + const NOT_VALID = 'sitemapLastmodNotValid'; + const INVALID = 'sitemapLastmodInvalid'; + + /** + * Validation failure message template definitions + * + * @var array + */ + protected $messageTemplates = array( + self::NOT_VALID => "The input is not a valid sitemap lastmod", + self::INVALID => "Invalid type given. String expected", + ); + + /** + * Validates if a string is valid as a sitemap lastmod + * + * @link http://www.sitemaps.org/protocol.php#lastmoddef <lastmod> + * + * @param string $value value to validate + * @return boolean + */ + public function isValid($value) + { + if (!is_string($value)) { + $this->error(self::INVALID); + return false; + } + + $this->setValue($value); + ErrorHandler::start(); + $result = preg_match(self::LASTMOD_REGEX, $value); + ErrorHandler::stop(); + if ($result != 1) { + $this->error(self::NOT_VALID); + return false; + } + + return true; + } +} diff --git a/lib/Zend/Validator/Sitemap/Loc.php b/lib/Zend/Validator/Sitemap/Loc.php new file mode 100644 index 0000000000000000000000000000000000000000..6a200477ee6ab94fd2b9ceaa24eb0df2938e6575 --- /dev/null +++ b/lib/Zend/Validator/Sitemap/Loc.php @@ -0,0 +1,69 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Sitemap; + +use Zend\Uri; +use Zend\Validator\AbstractValidator; + +/** + * Validates whether a given value is valid as a sitemap <loc> value + * + * @link http://www.sitemaps.org/protocol.php Sitemaps XML format + * + * @see Zend\Uri\Uri + * @category Zend + * @package Zend_Validate + * @subpackage Sitemap + */ +class Loc extends AbstractValidator +{ + /** + * Validation key for not valid + * + */ + const NOT_VALID = 'sitemapLocNotValid'; + const INVALID = 'sitemapLocInvalid'; + + /** + * Validation failure message template definitions + * + * @var array + */ + protected $messageTemplates = array( + self::NOT_VALID => "The input is not a valid sitemap location", + self::INVALID => "Invalid type given. String expected", + ); + + /** + * Validates if a string is valid as a sitemap location + * + * @link http://www.sitemaps.org/protocol.php#locdef <loc> + * + * @param string $value value to validate + * @return boolean + */ + public function isValid($value) + { + if (!is_string($value)) { + $this->error(self::INVALID); + return false; + } + + $this->setValue($value); + $uri = Uri\UriFactory::factory($value); + if (!$uri->isValid()) { + $this->error(self::NOT_VALID); + return false; + } + + return true; + } +} diff --git a/lib/Zend/Validator/Sitemap/Priority.php b/lib/Zend/Validator/Sitemap/Priority.php new file mode 100644 index 0000000000000000000000000000000000000000..113069c56ef07033a5a0410e553dea1c886fe6f1 --- /dev/null +++ b/lib/Zend/Validator/Sitemap/Priority.php @@ -0,0 +1,67 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator\Sitemap; + +use Zend\Validator\AbstractValidator; + +/** + * Validates whether a given value is valid as a sitemap <priority> value + * + * @link http://www.sitemaps.org/protocol.php Sitemaps XML format + * + * @category Zend + * @package Zend_Validate + * @subpackage Sitemap + */ +class Priority extends AbstractValidator +{ + /** + * Validation key for not valid + * + */ + const NOT_VALID = 'sitemapPriorityNotValid'; + const INVALID = 'sitemapPriorityInvalid'; + + /** + * Validation failure message template definitions + * + * @var array + */ + protected $messageTemplates = array( + self::NOT_VALID => "The input is not a valid sitemap priority", + self::INVALID => "Invalid type given. Numeric string, integer or float expected", + ); + + /** + * Validates if a string is valid as a sitemap priority + * + * @link http://www.sitemaps.org/protocol.php#prioritydef <priority> + * + * @param string $value value to validate + * @return boolean + */ + public function isValid($value) + { + if (!is_numeric($value)) { + $this->error(self::INVALID); + return false; + } + + $this->setValue($value); + $value = (float) $value; + if ($value < 0 || $value > 1) { + $this->error(self::NOT_VALID); + return false; + } + + return true; + } +} diff --git a/lib/Zend/Validator/StaticValidator.php b/lib/Zend/Validator/StaticValidator.php new file mode 100644 index 0000000000000000000000000000000000000000..f7ddaab944eafb2a339c6fab2429835efa96bf14 --- /dev/null +++ b/lib/Zend/Validator/StaticValidator.php @@ -0,0 +1,65 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator; + +/** + * @category Zend + * @package Zend_Validate + */ +class StaticValidator +{ + /** + * @var ValidatorPluginManager + */ + protected static $plugins; + + /** + * Set plugin manager to use for locating validators + * + * @param ValidatorPluginManager|null $plugins + * @return void + */ + public static function setPluginManager(ValidatorPluginManager $plugins = null) + { + // Don't share by default to allow different arguments on subsequent calls + if ($plugins instanceof ValidatorPluginManager) { + $plugins->setShareByDefault(false); + } + self::$plugins = $plugins; + } + + /** + * Get plugin manager for locating validators + * + * @return ValidatorPluginManager + */ + public static function getPluginManager() + { + if (null === self::$plugins) { + static::setPluginManager(new ValidatorPluginManager()); + } + return self::$plugins; + } + + /** + * @param mixed $value + * @param string $classBaseName + * @param array $args OPTIONAL + * @return boolean + */ + public static function execute($value, $classBaseName, array $args = array()) + { + $plugins = static::getPluginManager(); + + $validator = $plugins->get($classBaseName, $args); + return $validator->isValid($value); + } +} diff --git a/lib/Zend/Validator/Step.php b/lib/Zend/Validator/Step.php new file mode 100644 index 0000000000000000000000000000000000000000..e598607c52360144775acdf209eacae97331e3f6 --- /dev/null +++ b/lib/Zend/Validator/Step.php @@ -0,0 +1,158 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator; + +use Traversable; + +/** + * @category Zend + * @package Zend_Validate + */ +class Step extends AbstractValidator +{ + const INVALID = 'typeInvalid'; + const NOT_STEP = 'stepInvalid'; + + /** + * @var array + */ + protected $messageTemplates = array( + self::INVALID => "Invalid value given. Scalar expected", + self::NOT_STEP => "The input is not a valid step" + ); + + /** + * @var mixed + */ + protected $baseValue = 0; + + /** + * @var mixed + */ + protected $step = 1; + + /** + * Set default options for this instance + * + * @param array $options + */ + public function __construct($options = array()) + { + if ($options instanceof Traversable) { + $options = iterator_to_array($options); + } elseif (!is_array($options)) { + $options = func_get_args(); + $temp['baseValue'] = array_shift($options); + if (!empty($options)) { + $temp['step'] = array_shift($options); + } + + $options = $temp; + } + + if (isset($options['baseValue'])) { + $this->setBaseValue($options['baseValue']); + } + if (isset($options['step'])) { + $this->setStep($options['step']); + } + + parent::__construct($options); + } + + /** + * Sets the base value from which the step should be computed + * + * @param mixed $baseValue + * @return Step + */ + public function setBaseValue($baseValue) + { + $this->baseValue = $baseValue; + return $this; + } + + /** + * Returns the base value from which the step should be computed + * + * @return string + */ + public function getBaseValue() + { + return $this->baseValue; + } + + /** + * Sets the step value + * + * @param mixed $step + * @return Step + */ + public function setStep($step) + { + $this->step = $step; + return $this; + } + + /** + * Returns the step value + * + * @return string + */ + public function getStep() + { + return $this->step; + } + + /** + * Returns true if $value is a scalar and a valid step value + * + * @param mixed $value + * @return bool + */ + public function isValid($value) + { + if (!is_numeric($value)) { + $this->error(self::INVALID); + return false; + } + + $this->setValue($value); + + $fmod = $this->fmod($value - $this->baseValue, $this->step); + + if ($fmod !== 0.0 && $fmod !== $this->step) { + $this->error(self::NOT_STEP); + return false; + } + + return true; + } + + /** + * replaces the internal fmod function which give wrong results on many cases + * + * @param float $x + * @param float $y + * @return float + */ + protected function fmod($x, $y) + { + if ($y == 0.0) { + return 1.0; + } + + //find the maximum precision from both input params to give accurate results + $precision = strlen(substr($x, strpos($x, '.')+1)) + strlen(substr($y, strpos($y, '.')+1)); + + return round($x - $y * floor($x / $y), $precision); + } +} diff --git a/lib/Zend/Validator/StringLength.php b/lib/Zend/Validator/StringLength.php new file mode 100644 index 0000000000000000000000000000000000000000..781182c19e70e372519a85939277435eb1205455 --- /dev/null +++ b/lib/Zend/Validator/StringLength.php @@ -0,0 +1,197 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator; + +/** + * @category Zend + * @package Zend_Validate + */ +class StringLength extends AbstractValidator +{ + const INVALID = 'stringLengthInvalid'; + const TOO_SHORT = 'stringLengthTooShort'; + const TOO_LONG = 'stringLengthTooLong'; + + /** + * @var array + */ + protected $messageTemplates = array( + self::INVALID => "Invalid type given. String expected", + self::TOO_SHORT => "The input is less than %min% characters long", + self::TOO_LONG => "The input is more than %max% characters long", + ); + + /** + * @var array + */ + protected $messageVariables = array( + 'min' => array('options' => 'min'), + 'max' => array('options' => 'max'), + ); + + protected $options = array( + 'min' => 0, // Minimum length + 'max' => null, // Maximum length, null if there is no length limitation + 'encoding' => null, // Encoding to use + ); + + /** + * Sets validator options + * + * @param integer|array|\Traversable $options + */ + public function __construct($options = array()) + { + if (!is_array($options)) { + $options = func_get_args(); + $temp['min'] = array_shift($options); + if (!empty($options)) { + $temp['max'] = array_shift($options); + } + + if (!empty($options)) { + $temp['encoding'] = array_shift($options); + } + + $options = $temp; + } + + parent::__construct($options); + } + + /** + * Returns the min option + * + * @return integer + */ + public function getMin() + { + return $this->options['min']; + } + + /** + * Sets the min option + * + * @param integer $min + * @throws Exception\InvalidArgumentException + * @return StringLength Provides a fluent interface + */ + public function setMin($min) + { + if (null !== $this->getMax() && $min > $this->getMax()) { + throw new Exception\InvalidArgumentException("The minimum must be less than or equal to the maximum length, but $min >" + . " " . $this->getMax()); + } + + $this->options['min'] = max(0, (integer) $min); + return $this; + } + + /** + * Returns the max option + * + * @return integer|null + */ + public function getMax() + { + return $this->options['max']; + } + + /** + * Sets the max option + * + * @param integer|null $max + * @throws Exception\InvalidArgumentException + * @return StringLength Provides a fluent interface + */ + public function setMax($max) + { + if (null === $max) { + $this->options['max'] = null; + } elseif ($max < $this->getMin()) { + throw new Exception\InvalidArgumentException("The maximum must be greater than or equal to the minimum length, but " + . "$max < " . $this->getMin()); + } else { + $this->options['max'] = (integer) $max; + } + + return $this; + } + + /** + * Returns the actual encoding + * + * @return string + */ + public function getEncoding() + { + return $this->options['encoding']; + } + + /** + * Sets a new encoding to use + * + * @param string $encoding + * @return StringLength + * @throws Exception\InvalidArgumentException + */ + public function setEncoding($encoding = null) + { + if ($encoding !== null) { + $orig = iconv_get_encoding('internal_encoding'); + $result = iconv_set_encoding('internal_encoding', $encoding); + if (!$result) { + throw new Exception\InvalidArgumentException('Given encoding not supported on this OS!'); + } + + iconv_set_encoding('internal_encoding', $orig); + } + + $this->options['encoding'] = $encoding; + return $this; + } + + /** + * Returns true if and only if the string length of $value is at least the min option and + * no greater than the max option (when the max option is not null). + * + * @param string $value + * @return boolean + */ + public function isValid($value) + { + if (!is_string($value)) { + $this->error(self::INVALID); + return false; + } + + $this->setValue($value); + if ($this->getEncoding() !== null) { + $length = iconv_strlen($value, $this->getEncoding()); + } else { + $length = iconv_strlen($value); + } + + if ($length < $this->getMin()) { + $this->error(self::TOO_SHORT); + } + + if (null !== $this->getMax() && $this->getMax() < $length) { + $this->error(self::TOO_LONG); + } + + if (count($this->getMessages())) { + return false; + } else { + return true; + } + } +} diff --git a/lib/Zend/Validator/Uri.php b/lib/Zend/Validator/Uri.php new file mode 100644 index 0000000000000000000000000000000000000000..59ea3b472b8882a3c3be5496471878c85815f0b3 --- /dev/null +++ b/lib/Zend/Validator/Uri.php @@ -0,0 +1,197 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator; + +use Traversable; +use Zend\Uri\Exception\ExceptionInterface as UriException; +use Zend\Uri\Uri as UriHandler; +use Zend\Validator\Exception\InvalidArgumentException; + +/** + * @category Zend + * @package Zend_Validate + */ +class Uri extends AbstractValidator +{ + const INVALID = 'uriInvalid'; + const NOT_URI = 'notUri'; + + /** + * @var array + */ + protected $messageTemplates = array( + self::INVALID => "Invalid type given. String expected", + self::NOT_URI => "The input does not appear to be a valid Uri", + ); + + /** + * @var UriHandler + */ + protected $uriHandler; + + /** + * @var boolean + */ + protected $allowRelative = true; + + /** + * @var boolean + */ + protected $allowAbsolute = true; + + /** + * Sets default option values for this instance + * + * @param array|\Traversable $options + */ + public function __construct($options = array()) + { + if ($options instanceof Traversable) { + $options = iterator_to_array($options); + } elseif (!is_array($options)) { + $options = func_get_args(); + $temp['uriHandler'] = array_shift($options); + if (!empty($options)) { + $temp['allowRelative'] = array_shift($options); + } + if (!empty($options)) { + $temp['allowAbsolute'] = array_shift($options); + } + + $options = $temp; + } + + if (isset($options['uriHandler'])) { + $this->setUriHandler($options['uriHandler']); + } + if (isset($options['allowRelative'])) { + $this->setAllowRelative($options['allowRelative']); + } + if (isset($options['allowAbsolute'])) { + $this->setAllowAbsolute($options['allowAbsolute']); + } + + parent::__construct($options); + } + + /** + * @throws InvalidArgumentException + * @return UriHandler + */ + public function getUriHandler() + { + if (null === $this->uriHandler) { + // Lazy load the base Uri handler + $this->uriHandler = new UriHandler(); + } elseif (is_string($this->uriHandler) && class_exists($this->uriHandler)) { + // Instantiate string Uri handler that references a class + $this->uriHandler = new $this->uriHandler; + } + + if (! $this->uriHandler instanceof UriHandler) { + throw new InvalidArgumentException('URI handler is expected to be a Zend\Uri\Uri object'); + } + + return $this->uriHandler; + } + + /** + * @param UriHandler $uriHandler + * @throws InvalidArgumentException + * @return Uri + */ + public function setUriHandler($uriHandler) + { + if (! is_subclass_of($uriHandler, 'Zend\Uri\Uri')) { + throw new InvalidArgumentException('Expecting a subclass name or instance of Zend\Uri\Uri as $uriHandler'); + } + + $this->uriHandler = $uriHandler; + return $this; + } + + /** + * Returns the allowAbsolute option + * + * @return boolean + */ + public function getAllowAbsolute() + { + return $this->allowAbsolute; + } + + /** + * Sets the allowAbsolute option + * + * @param boolean $allowAbsolute + * @return Uri + */ + public function setAllowAbsolute($allowAbsolute) + { + $this->allowAbsolute = (boolean) $allowAbsolute; + return $this; + } + + /** + * Returns the allowRelative option + * + * @return boolean + */ + public function getAllowRelative() + { + return $this->allowRelative; + } + + /** + * Sets the allowRelative option + * + * @param boolean $allowRelative + * @return Uri + */ + public function setAllowRelative($allowRelative) + { + $this->allowRelative = (boolean) $allowRelative; + return $this; + } + + /** + * Returns true if and only if $value validates as a Uri + * + * @param string $value + * @return boolean + */ + public function isValid($value) + { + if (!is_string($value)) { + $this->error(self::INVALID); + return false; + } + + $uriHandler = $this->getUriHandler(); + try { + $uriHandler->parse($value); + if ($uriHandler->isValid()) { + // It will either be a valid absolute or relative URI + if (($this->allowRelative && $this->allowAbsolute) + || ($this->allowAbsolute && $uriHandler->isAbsolute()) + || ($this->allowRelative && $uriHandler->isValidRelative()) + ) { + return true; + } + } + } catch (UriException $ex) { + // Error parsing URI, it must be invalid + } + + $this->error(self::NOT_URI); + return false; + } +} diff --git a/lib/Zend/Validator/ValidatorChain.php b/lib/Zend/Validator/ValidatorChain.php new file mode 100644 index 0000000000000000000000000000000000000000..51d4ebf708098b38856ad8b123e2c9f3fa03e51c --- /dev/null +++ b/lib/Zend/Validator/ValidatorChain.php @@ -0,0 +1,248 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator; + +use Countable; + +/** + * @category Zend + * @package Zend_Validator + */ +class ValidatorChain implements + Countable, + ValidatorInterface +{ + /** + * @var ValidatorPluginManager + */ + protected $plugins; + + /** + * Validator chain + * + * @var array + */ + protected $validators = array(); + + /** + * Array of validation failure messages + * + * @var array + */ + protected $messages = array(); + + /** + * Return the count of attached validators + * + * @return int + */ + public function count() + { + return count($this->validators); + } + + /** + * Get plugin manager instance + * + * @return ValidatorPluginManager + */ + public function getPluginManager() + { + if (!$this->plugins) { + $this->setPluginManager(new ValidatorPluginManager()); + } + return $this->plugins; + } + + /** + * Set plugin manager instance + * + * @param ValidatorPluginManager $plugins Plugin manager + * @return ValidatorChain + */ + public function setPluginManager(ValidatorPluginManager $plugins) + { + $this->plugins = $plugins; + return $this; + } + + /** + * Retrieve a validator by name + * + * @param string $name Name of validator to return + * @param null|array $options Options to pass to validator constructor (if not already instantiated) + * @return ValidatorInterface + */ + public function plugin($name, array $options = null) + { + $plugins = $this->getPluginManager(); + return $plugins->get($name, $options); + } + + /** + * Adds a validator to the end of the chain + * + * If $breakChainOnFailure is true, then if the validator fails, the next validator in the chain, + * if one exists, will not be executed. + * + * @param ValidatorInterface $validator + * @param boolean $breakChainOnFailure + * @return ValidatorChain Provides a fluent interface + */ + public function addValidator(ValidatorInterface $validator, $breakChainOnFailure = false) + { + $this->validators[] = array( + 'instance' => $validator, + 'breakChainOnFailure' => (boolean)$breakChainOnFailure + ); + return $this; + } + + /** + * Adds a validator to the beginning of the chain + * + * If $breakChainOnFailure is true, then if the validator fails, the next validator in the chain, + * if one exists, will not be executed. + * + * @param ValidatorInterface $validator + * @param boolean $breakChainOnFailure + * @return ValidatorChain Provides a fluent interface + */ + public function prependValidator(ValidatorInterface $validator, $breakChainOnFailure = false) + { + array_unshift($this->validators, + array( + 'instance' => $validator, + 'breakChainOnFailure' => (boolean)$breakChainOnFailure + ) + ); + return $this; + } + + /** + * Use the plugin manager to add a validator by name + * + * @param string $name + * @param array $options + * @param bool $breakChainOnFailure + * @return ValidatorChain + */ + public function addByName($name, $options = array(), $breakChainOnFailure = false) + { + $validator = $this->plugin($name, $options); + $this->addValidator($validator, $breakChainOnFailure); + return $this; + } + + /** + * Use the plugin manager to prepend a validator by name + * + * @param string $name + * @param array $options + * @param bool $breakChainOnFailure + * @return ValidatorChain + */ + public function prependByName($name, $options = array(), $breakChainOnFailure = false) + { + $validator = $this->plugin($name, $options); + $this->prependValidator($validator, $breakChainOnFailure); + return $this; + } + + /** + * Returns true if and only if $value passes all validations in the chain + * + * Validators are run in the order in which they were added to the chain (FIFO). + * + * @param mixed $value + * @param mixed $context Extra "context" to provide the validator + * @return boolean + */ + public function isValid($value, $context = null) + { + $this->messages = array(); + $result = true; + foreach ($this->validators as $element) { + $validator = $element['instance']; + if ($validator->isValid($value, $context)) { + continue; + } + $result = false; + $messages = $validator->getMessages(); + $this->messages = array_replace_recursive($this->messages, $messages); + if ($element['breakChainOnFailure']) { + break; + } + } + return $result; + } + + /** + * Merge the validator chain with the one given in parameter + * + * @param ValidatorChain $validatorChain + * @return ValidatorChain + */ + public function merge(ValidatorChain $validatorChain) + { + foreach ($validatorChain->validators as $validator) { + $this->validators[] = $validator; + } + + return $this; + } + + /** + * Returns array of validation failure messages + * + * @return array + */ + public function getMessages() + { + return $this->messages; + } + + /** + * Get all the validators + * + * @return array + */ + public function getValidators() + { + return $this->validators; + } + + /** + * Invoke chain as command + * + * @param mixed $value + * @return boolean + */ + public function __invoke($value) + { + return $this->isValid($value); + } + + /** + * Prepare validator chain for serialization + * + * Plugin manager (property 'plugins') cannot + * be serialized. On wakeup the property remains unset + * and next invokation to getPluginManager() sets + * the default plugin manager instance (ValidatorPluginManager). + * + * @return array + */ + public function __sleep() + { + return array('validators','messages'); + } +} diff --git a/lib/Zend/Validator/ValidatorInterface.php b/lib/Zend/Validator/ValidatorInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..3179e6a7377da0f7f964dd91268cd2157863a2a0 --- /dev/null +++ b/lib/Zend/Validator/ValidatorInterface.php @@ -0,0 +1,43 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator; + +/** + * @category Zend + * @package Zend_Validate + */ +interface ValidatorInterface +{ + /** + * Returns true if and only if $value meets the validation requirements + * + * If $value fails validation, then this method returns false, and + * getMessages() will return an array of messages that explain why the + * validation failed. + * + * @param mixed $value + * @return boolean + * @throws Exception\RuntimeException If validation of $value is impossible + */ + public function isValid($value); + + /** + * Returns an array of messages that explain why the most recent isValid() + * call returned false. The array keys are validation failure message identifiers, + * and the array values are the corresponding human-readable message strings. + * + * If isValid() was never called or if the most recent isValid() call + * returned true, then this method returns an empty array. + * + * @return array + */ + public function getMessages(); +} diff --git a/lib/Zend/Validator/ValidatorPluginManager.php b/lib/Zend/Validator/ValidatorPluginManager.php new file mode 100644 index 0000000000000000000000000000000000000000..056486d9de31ba267354085714dbe1866bf8ff2b --- /dev/null +++ b/lib/Zend/Validator/ValidatorPluginManager.php @@ -0,0 +1,170 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Validator + */ + +namespace Zend\Validator; + +use Zend\I18n\Translator\TranslatorAwareInterface; +use Zend\ServiceManager\AbstractPluginManager; +use Zend\ServiceManager\ConfigInterface; + +/** + * @category Zend + * @package Zend_Validator + */ +class ValidatorPluginManager extends AbstractPluginManager +{ + /** + * Default set of validators + * + * @var array + */ + protected $invokableClasses = array( + 'alnum' => 'Zend\I18n\Validator\Alnum', + 'alpha' => 'Zend\I18n\Validator\Alpha', + 'barcodecode25interleaved' => 'Zend\Validator\Barcode\Code25interleaved', + 'barcodecode25' => 'Zend\Validator\Barcode\Code25', + 'barcodecode39ext' => 'Zend\Validator\Barcode\Code39ext', + 'barcodecode39' => 'Zend\Validator\Barcode\Code39', + 'barcodecode93ext' => 'Zend\Validator\Barcode\Code93ext', + 'barcodecode93' => 'Zend\Validator\Barcode\Code93', + 'barcodeean12' => 'Zend\Validator\Barcode\Ean12', + 'barcodeean13' => 'Zend\Validator\Barcode\Ean13', + 'barcodeean14' => 'Zend\Validator\Barcode\Ean14', + 'barcodeean18' => 'Zend\Validator\Barcode\Ean18', + 'barcodeean2' => 'Zend\Validator\Barcode\Ean2', + 'barcodeean5' => 'Zend\Validator\Barcode\Ean5', + 'barcodeean8' => 'Zend\Validator\Barcode\Ean8', + 'barcodegtin12' => 'Zend\Validator\Barcode\Gtin12', + 'barcodegtin13' => 'Zend\Validator\Barcode\Gtin13', + 'barcodegtin14' => 'Zend\Validator\Barcode\Gtin14', + 'barcodeidentcode' => 'Zend\Validator\Barcode\Identcode', + 'barcodeintelligentmail' => 'Zend\Validator\Barcode\Intelligentmail', + 'barcodeissn' => 'Zend\Validator\Barcode\Issn', + 'barcodeitf14' => 'Zend\Validator\Barcode\Itf14', + 'barcodeleitcode' => 'Zend\Validator\Barcode\Leitcode', + 'barcodeplanet' => 'Zend\Validator\Barcode\Planet', + 'barcodepostnet' => 'Zend\Validator\Barcode\Postnet', + 'barcoderoyalmail' => 'Zend\Validator\Barcode\Royalmail', + 'barcodesscc' => 'Zend\Validator\Barcode\Sscc', + 'barcodeupca' => 'Zend\Validator\Barcode\Upca', + 'barcodeupce' => 'Zend\Validator\Barcode\Upce', + 'barcode' => 'Zend\Validator\Barcode', + 'between' => 'Zend\Validator\Between', + 'callback' => 'Zend\Validator\Callback', + 'creditcard' => 'Zend\Validator\CreditCard', + 'csrf' => 'Zend\Validator\Csrf', + 'date' => 'Zend\Validator\Date', + 'datestep' => 'Zend\Validator\DateStep', + 'dbnorecordexists' => 'Zend\Validator\Db\NoRecordExists', + 'dbrecordexists' => 'Zend\Validator\Db\RecordExists', + 'digits' => 'Zend\Validator\Digits', + 'emailaddress' => 'Zend\Validator\EmailAddress', + 'explode' => 'Zend\Validator\Explode', + 'filecount' => 'Zend\Validator\File\Count', + 'filecrc32' => 'Zend\Validator\File\Crc32', + 'fileexcludeextension' => 'Zend\Validator\File\ExcludeExtension', + 'fileexcludemimetype' => 'Zend\Validator\File\ExcludeMimeType', + 'fileexists' => 'Zend\Validator\File\Exists', + 'fileextension' => 'Zend\Validator\File\Extension', + 'filefilessize' => 'Zend\Validator\File\FilesSize', + 'filehash' => 'Zend\Validator\File\Hash', + 'fileimagesize' => 'Zend\Validator\File\ImageSize', + 'fileiscompressed' => 'Zend\Validator\File\IsCompressed', + 'fileisimage' => 'Zend\Validator\File\IsImage', + 'filemd5' => 'Zend\Validator\File\Md5', + 'filemimetype' => 'Zend\Validator\File\MimeType', + 'filenotexists' => 'Zend\Validator\File\NotExists', + 'filesha1' => 'Zend\Validator\File\Sha1', + 'filesize' => 'Zend\Validator\File\Size', + 'fileupload' => 'Zend\Validator\File\Upload', + 'filewordcount' => 'Zend\Validator\File\WordCount', + 'float' => 'Zend\I18n\Validator\Float', + 'greaterthan' => 'Zend\Validator\GreaterThan', + 'hex' => 'Zend\Validator\Hex', + 'hostname' => 'Zend\Validator\Hostname', + 'iban' => 'Zend\I18n\Validator\Iban', + 'identical' => 'Zend\Validator\Identical', + 'inarray' => 'Zend\Validator\InArray', + 'int' => 'Zend\I18n\Validator\Int', + 'ip' => 'Zend\Validator\Ip', + 'isbn' => 'Zend\Validator\Isbn', + 'lessthan' => 'Zend\Validator\LessThan', + 'notempty' => 'Zend\Validator\NotEmpty', + 'postcode' => 'Zend\I18n\Validator\PostCode', + 'regex' => 'Zend\Validator\Regex', + 'sitemapchangefreq' => 'Zend\Validator\Sitemap\Changefreq', + 'sitemaplastmod' => 'Zend\Validator\Sitemap\Lastmod', + 'sitemaploc' => 'Zend\Validator\Sitemap\Loc', + 'sitemappriority' => 'Zend\Validator\Sitemap\Priority', + 'stringlength' => 'Zend\Validator\StringLength', + 'step' => 'Zend\Validator\Step', + 'uri' => 'Zend\Validator\Uri', + ); + + /** + * Whether or not to share by default; default to false + * + * @var bool + */ + protected $shareByDefault = false; + + /** + * Constructor + * + * After invoking parent constructor, add an initializer to inject the + * attached translator, if any, to the currently requested helper. + * + * @param null|ConfigInterface $configuration + */ + public function __construct(ConfigInterface $configuration = null) + { + parent::__construct($configuration); + $this->addInitializer(array($this, 'injectTranslator')); + } + + /** + * Inject a validator instance with the registered translator + * + * @param ValidatorInterface $validator + * @return void + */ + public function injectTranslator($validator) + { + if ($validator instanceof TranslatorAwareInterface) { + $locator = $this->getServiceLocator(); + if ($locator && $locator->has('translator')) { + $validator->setTranslator($locator->get('translator')); + } + } + } + + /** + * Validate the plugin + * + * Checks that the validator loaded is an instance of ValidatorInterface. + * + * @param mixed $plugin + * @return void + * @throws Exception\RuntimeException if invalid + */ + public function validatePlugin($plugin) + { + if ($plugin instanceof ValidatorInterface) { + // we're okay + return; + } + + throw new Exception\RuntimeException(sprintf( + 'Plugin of type %s is invalid; must implement %s\ValidatorInterface', + (is_object($plugin) ? get_class($plugin) : gettype($plugin)), + __NAMESPACE__ + )); + } +} diff --git a/lib/Zend/Validator/composer.json b/lib/Zend/Validator/composer.json new file mode 100644 index 0000000000000000000000000000000000000000..015a02a2b04d055396d55f4c294c36295e9fc1d1 --- /dev/null +++ b/lib/Zend/Validator/composer.json @@ -0,0 +1,27 @@ +{ + "name": "zendframework/zend-validator", + "description": "provides a set of commonly needed validators", + "license": "BSD-3-Clause", + "keywords": [ + "zf2", + "validator" + ], + "autoload": { + "psr-0": { + "Zend\\Validator": "" + } + }, + "target-dir": "Zend/Validator", + "require": { + "php": ">=5.3.3", + "zendframework/zend-i18n": "self.version", + "zendframework/zend-stdlib": "self.version" + }, + "require-dev": { + "zendframework/zend-math": "self.version" + }, + "suggest": { + "zendframework/zend-db": "Zend\\Db component", + "zendframework/zend-math": "Zend\\Math component" + } +} diff --git a/pub/.htaccess b/pub/.htaccess index decbf06addf0bdb12b7bcbb373562cfccd4d3e14..51fde249567862173a96581ab99d6b19f96fdb28 100644 --- a/pub/.htaccess +++ b/pub/.htaccess @@ -122,16 +122,6 @@ #RewriteBase /magento/ -############################################ -## uncomment next line to enable light API calls processing - -# RewriteRule ^api/([a-z][0-9a-z_]+)/?$ api.php?type=$1 [QSA,L] - -############################################ -## rewrite API2 calls to api.php (by now it is REST only) - - RewriteRule ^api/rest api.php?type=rest [QSA,L] - ############################################ ## workaround for HTTP authorization ## in CGI environment diff --git a/pub/api.php b/pub/api.php deleted file mode 100644 index 0852d42be606c46a55cb75752c94fc250240f48a..0000000000000000000000000000000000000000 --- a/pub/api.php +++ /dev/null @@ -1,69 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Api2 - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -require dirname(__DIR__) . '/app/bootstrap.php'; - -if (!Mage::isInstalled()) { - echo 'Application is not installed yet, please complete install wizard first.'; - exit; -} - -// emulate index.php entry point for correct URLs generation in API -Mage::register('custom_entry_point', true); -Mage::$headersSentThrowsException = false; -Mage::init('admin'); -Mage::app()->loadAreaPart(Mage_Core_Model_App_Area::AREA_ADMINHTML, Mage_Core_Model_App_Area::PART_EVENTS); - -// query parameter "type" is set by .htaccess rewrite rule -$apiAlias = Mage::app()->getRequest()->getParam('type'); - -// check request could be processed by API2 -if (in_array($apiAlias, Mage_Api2_Model_Server::getApiTypes())) { - /** @var $server Mage_Api2_Model_Server */ - $server = Mage::getSingleton('Mage_Api2_Model_Server'); - - $server->run(); -} else { - /* @var $server Mage_Api_Model_Server */ - $server = Mage::getSingleton('Mage_Api_Model_Server'); - $adapterCode = $server->getAdapterCodeByAlias($apiAlias); - - // if no adapters found in aliases - find it by default, by code - if (null === $adapterCode) { - $adapterCode = $apiAlias; - } - try { - $server->initialize($adapterCode); - $server->run(); - - Mage::app()->getResponse()->sendResponse(); - } catch (Exception $e) { - Mage::logException($e); - - echo $e->getMessage(); - exit; - } -}