From 86bf4833de2e6d308cce65d432d49861cda3ccc7 Mon Sep 17 00:00:00 2001 From: Jens Frank Date: Tue, 23 Mar 2004 22:22:16 +0000 Subject: [PATCH] import PHPTAL NoPEAR 0.7.0 - files --- PHPTAL-NP-0.7.0/COPYING | 504 ++++++++++ PHPTAL-NP-0.7.0/README | 12 + PHPTAL-NP-0.7.0/libs/Algo/Map.php | 206 ++++ PHPTAL-NP-0.7.0/libs/GetText.php | 616 ++++++++++++ PHPTAL-NP-0.7.0/libs/PEAR.php | 945 ++++++++++++++++++ PHPTAL-NP-0.7.0/libs/PHPTAL.php | 288 ++++++ PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute.php | 42 + .../libs/PHPTAL/Attribute/I18N/Attributes.php | 142 +++ .../libs/PHPTAL/Attribute/I18N/Name.php | 42 + .../libs/PHPTAL/Attribute/I18N/Translate.php | 82 ++ .../PHPTAL/Attribute/METAL/Define_macro.php | 36 + .../PHPTAL/Attribute/METAL/Define_slot.php | 40 + .../libs/PHPTAL/Attribute/METAL/Fill_slot.php | 36 + .../libs/PHPTAL/Attribute/METAL/Use_macro.php | 58 ++ .../libs/PHPTAL/Attribute/PHPTAL/Include.php | 42 + .../PHPTAL/Attribute/PHPTAL/Src_include.php | 45 + .../libs/PHPTAL/Attribute/TAL/Attributes.php | 173 ++++ .../libs/PHPTAL/Attribute/TAL/Comment.php | 34 + .../libs/PHPTAL/Attribute/TAL/Condition.php | 43 + .../libs/PHPTAL/Attribute/TAL/Content.php | 52 + .../libs/PHPTAL/Attribute/TAL/Define.php | 51 + .../libs/PHPTAL/Attribute/TAL/Omit_tag.php | 31 + .../libs/PHPTAL/Attribute/TAL/On_error.php | 46 + .../libs/PHPTAL/Attribute/TAL/Repeat.php | 64 ++ .../libs/PHPTAL/Attribute/TAL/Replace.php | 46 + PHPTAL-NP-0.7.0/libs/PHPTAL/Cache.php | 97 ++ PHPTAL-NP-0.7.0/libs/PHPTAL/Context.php | 349 +++++++ PHPTAL-NP-0.7.0/libs/PHPTAL/Expression.php | 369 +++++++ .../libs/PHPTAL/ExpressionFunctions.php | 384 +++++++ PHPTAL-NP-0.7.0/libs/PHPTAL/Filter.php | 62 ++ PHPTAL-NP-0.7.0/libs/PHPTAL/Generator.php | 362 +++++++ PHPTAL-NP-0.7.0/libs/PHPTAL/I18N.php | 16 + PHPTAL-NP-0.7.0/libs/PHPTAL/LoopControler.php | 364 +++++++ PHPTAL-NP-0.7.0/libs/PHPTAL/Macro.php | 107 ++ PHPTAL-NP-0.7.0/libs/PHPTAL/OutputControl.php | 96 ++ PHPTAL-NP-0.7.0/libs/PHPTAL/Parser.php | 515 ++++++++++ PHPTAL-NP-0.7.0/libs/PHPTAL/SourceLocator.php | 62 ++ .../libs/PHPTAL/SourceResolver.php | 63 ++ PHPTAL-NP-0.7.0/libs/PHPTAL/Tag.php | 296 ++++++ PHPTAL-NP-0.7.0/libs/PHPTAL/Template.php | 562 +++++++++++ PHPTAL-NP-0.7.0/libs/PHPTAL/XML_Parser.php | 254 +++++ PHPTAL-NP-0.7.0/libs/Types.php | 100 ++ PHPTAL-NP-0.7.0/libs/Types/Code.php | 219 ++++ PHPTAL-NP-0.7.0/libs/Types/Errors.php | 30 + PHPTAL-NP-0.7.0/libs/Types/Iterator.php | 153 +++ PHPTAL-NP-0.7.0/libs/Types/OArray.php | 408 ++++++++ PHPTAL-NP-0.7.0/libs/Types/ODate.php | 447 +++++++++ PHPTAL-NP-0.7.0/libs/Types/OHash.php | 451 +++++++++ PHPTAL-NP-0.7.0/libs/Types/OString.php | 473 +++++++++ PHPTAL-NP-0.7.0/libs/Types/Ref.php | 145 +++ 50 files changed, 10060 insertions(+) create mode 100644 PHPTAL-NP-0.7.0/COPYING create mode 100644 PHPTAL-NP-0.7.0/README create mode 100644 PHPTAL-NP-0.7.0/libs/Algo/Map.php create mode 100644 PHPTAL-NP-0.7.0/libs/GetText.php create mode 100644 PHPTAL-NP-0.7.0/libs/PEAR.php create mode 100644 PHPTAL-NP-0.7.0/libs/PHPTAL.php create mode 100644 PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute.php create mode 100644 PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/I18N/Attributes.php create mode 100644 PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/I18N/Name.php create mode 100644 PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/I18N/Translate.php create mode 100644 PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/METAL/Define_macro.php create mode 100644 PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/METAL/Define_slot.php create mode 100644 PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/METAL/Fill_slot.php create mode 100644 PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/METAL/Use_macro.php create mode 100644 PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/PHPTAL/Include.php create mode 100644 PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/PHPTAL/Src_include.php create mode 100644 PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Attributes.php create mode 100644 PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Comment.php create mode 100644 PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Condition.php create mode 100644 PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Content.php create mode 100644 PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Define.php create mode 100644 PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Omit_tag.php create mode 100644 PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/On_error.php create mode 100644 PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Repeat.php create mode 100644 PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Replace.php create mode 100644 PHPTAL-NP-0.7.0/libs/PHPTAL/Cache.php create mode 100644 PHPTAL-NP-0.7.0/libs/PHPTAL/Context.php create mode 100644 PHPTAL-NP-0.7.0/libs/PHPTAL/Expression.php create mode 100644 PHPTAL-NP-0.7.0/libs/PHPTAL/ExpressionFunctions.php create mode 100644 PHPTAL-NP-0.7.0/libs/PHPTAL/Filter.php create mode 100644 PHPTAL-NP-0.7.0/libs/PHPTAL/Generator.php create mode 100644 PHPTAL-NP-0.7.0/libs/PHPTAL/I18N.php create mode 100644 PHPTAL-NP-0.7.0/libs/PHPTAL/LoopControler.php create mode 100644 PHPTAL-NP-0.7.0/libs/PHPTAL/Macro.php create mode 100644 PHPTAL-NP-0.7.0/libs/PHPTAL/OutputControl.php create mode 100644 PHPTAL-NP-0.7.0/libs/PHPTAL/Parser.php create mode 100644 PHPTAL-NP-0.7.0/libs/PHPTAL/SourceLocator.php create mode 100644 PHPTAL-NP-0.7.0/libs/PHPTAL/SourceResolver.php create mode 100644 PHPTAL-NP-0.7.0/libs/PHPTAL/Tag.php create mode 100644 PHPTAL-NP-0.7.0/libs/PHPTAL/Template.php create mode 100644 PHPTAL-NP-0.7.0/libs/PHPTAL/XML_Parser.php create mode 100644 PHPTAL-NP-0.7.0/libs/Types.php create mode 100644 PHPTAL-NP-0.7.0/libs/Types/Code.php create mode 100644 PHPTAL-NP-0.7.0/libs/Types/Errors.php create mode 100644 PHPTAL-NP-0.7.0/libs/Types/Iterator.php create mode 100644 PHPTAL-NP-0.7.0/libs/Types/OArray.php create mode 100644 PHPTAL-NP-0.7.0/libs/Types/ODate.php create mode 100644 PHPTAL-NP-0.7.0/libs/Types/OHash.php create mode 100644 PHPTAL-NP-0.7.0/libs/Types/OString.php create mode 100644 PHPTAL-NP-0.7.0/libs/Types/Ref.php diff --git a/PHPTAL-NP-0.7.0/COPYING b/PHPTAL-NP-0.7.0/COPYING new file mode 100644 index 0000000000..d3a38e51b4 --- /dev/null +++ b/PHPTAL-NP-0.7.0/COPYING @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/PHPTAL-NP-0.7.0/README b/PHPTAL-NP-0.7.0/README new file mode 100644 index 0000000000..e910c2e021 --- /dev/null +++ b/PHPTAL-NP-0.7.0/README @@ -0,0 +1,12 @@ +PHPTAL for non PEAR users + +This package contains PHPTAL and its dependencies. + +It also contains the PEAR.php file, used for Error handling in PHPTAL +and its dependencies. + +Installation: + +copy the content of libs in one of your php include path. + + diff --git a/PHPTAL-NP-0.7.0/libs/Algo/Map.php b/PHPTAL-NP-0.7.0/libs/Algo/Map.php new file mode 100644 index 0000000000..eb431b6e68 --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/Algo/Map.php @@ -0,0 +1,206 @@ + +// +// $id$ + +define('ALGO_MAP_VERSION', '0.1.1'); + +/** + * Applies a callback(or code) to the elements of given arrays. + * + * This function acts much like the perl 'map' keyword, it pass through all + * array parameters and apply a callback function to each elements of + * these arrays. + * + * See examples below to an overview of Algo_map() usage. + * + * *IMPORTANT* + * + * Please note that the callback function needs to return something, when you + * don't want your function to return an element or an hashtable, just return + * an empty array(). + * + * + * example 1 : Simple use, this example compose an hashtable with an array. + * + * 1); + * } + * + * $a_pam = array("apple", "pie", "cherry"); + * + * $result = Algo_map('myfunc', $a_pam); + * + * // $result ==> array("apple"=>1, "pie"=>1, "cherry"=>1); + * ?> + * + * You can pass more than one array as parameters. The number of elements of + * each array should be at least equal to the number of elements of the first + * array. + * + * If count($a1) > count($a2), elements of $a2 that doesn't exists + * will be replaced by a false value. + * + * + * example 2 : Using more than one array with Algo_map() + * + * array(1, 4, 12, 32); + * ?> + * + * + * example 3 : Problem of array size + * + * array(1, 4, 12, 32, 0); + * // the fifth element is equal to 0 because the fifth element of $b_nbr + * // doesn't exists and is replaced by false(ie:0) in the callback + * // function. + * ?> + * + * + * example 4 : Defining the function code inside the Algo_map() call + * + * array("b","d"); + * ?> + * + * + * example 5 : Object method callback + * + * + * + * + * @param mixed ... See examples + * @return array + * @author Laurent Bedubourg + * @date 2001-09-20 + */ +function Algo_map() +{ + // we retrieve the list of map arguments + $argv = func_get_args(); + // the first argument is the function name + $func = array_shift($argv); + + if (is_object($func)) { + // if first argument is an object, this map + // has a callback to some method + $obj = $func; + $func = array_shift($argv); + } else if (!function_exists($func)) { + // if the function isn't defined, + // we'll try to create the function + // the first argument was the string + // of function arguments(ie:'$a,$b,$c') + + // The code is the second argument + $code = array_shift($argv); + + // We create the new function + // it will be a lambda style function + $func = create_function($func, $code); + } + + // prepare the result array + $result = array(); + + // we'll apply the new function to + // each element of arrays passed as + // parameters + while (count($argv[0]) > 0) { + // prepare the array of arguments + $fargs = array(); + + for($i = 0; $i < count($argv); $i++) { + // for each array to map + // we add the next element of the + // array to the argument array + $fargs[] = array_shift($argv[$i]); + } + + if (isset($obj)) { + $result = array_merge($result, + call_user_func_array(array($obj,$func), + $fargs)); + } else { + // we merge the result of the function + // with allready found results + $result = array_merge($result, + // call the function with the array + // of arguments + call_user_func_array($func, $fargs)); + } + } + + // let's return the result array + return $result; +} + +?> diff --git a/PHPTAL-NP-0.7.0/libs/GetText.php b/PHPTAL-NP-0.7.0/libs/GetText.php new file mode 100644 index 0000000000..029d51bd88 --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/GetText.php @@ -0,0 +1,616 @@ + +// + +require_once "PEAR.php"; + +define('GETTEXT_NATIVE', 1); +define('GETTEXT_PHP', 2); + +/** + * Generic gettext static class. + * + * This class allows gettext usage with php even if the gettext support is + * not compiled in php. + * + * The developper can choose between the GETTEXT_NATIVE support and the + * GETTEXT_PHP support on initialisation. If native is not supported, the + * system will fall back to PHP support. + * + * On both systems, this package add a variable interpolation system so you can + * translate entire dynamic sentences in stead of peace of sentences. + * + * Small example without pear error lookup : + * + * + * + * A gettext mini-howto should be provided with this package, if you're new + * to gettext usage, please read it to learn how to build a gettext + * translation directory (locale). + * + * @todo Tools to manage gettext files in php. + * + * - non traducted domains / keys + * - modification of keys + * - domain creation, preparation, delete, ... + * - tool to extract required messages from TOF templates + * + * @version 0.5 + * @author Laurent Bedubourg + */ +class GetText +{ + /** + * This method returns current gettext support class. + * + * @return GetText_Support + * @static 1 + * @access private + */ + function &_support($set=false) + { + static $supportObject; + if ($set !== false) { + $supportObject = $set; + } elseif (!isset($supportObject)) { + trigger_error("GetText not initialized !". endl. + "Please call GetText::init() before calling ". + "any GetText function !".endl + , E_USER_ERROR); + } + return $supportObject; + } + + /** + * Initialize gettext package. + * + * This method instantiate the gettext support depending on managerType + * value. + * + * GETTEXT_NATIVE try to use gettext php support and fail back to PHP + * support if not installed. + * + * GETTEXT_PHP explicitely request the usage of PHP support. + * + * @param int $managerType + * Gettext support type. + * + * @access public + * @static 1 + */ + function init($managerType = GETTEXT_NATIVE) + { + if ($managerType == GETTEXT_NATIVE) { + if (function_exists('gettext')) { + return GetText::_support(new GetText_NativeSupport()); + } + } + // fail back to php support + return GetText::_support(new GetText_PHPSupport()); + } + + /** + * Set the language to use for traduction. + * + * @param string $langCode + * The language code usually defined as ll_CC, ll is the two letter + * language code and CC is the two letter country code. + * + * @throws GetText_Error if language is not supported by your system. + */ + function setLanguage($langCode) + { + $support =& GetText::_support(); + return $support->setLanguage($langCode); + } + + /** + * Add a translation domain. + * + * The domain name is usually the name of the .po file you wish to use. + * For example, if you created a file 'locale/ll_CC/LC_MESSAGES/myapp.po', + * you'll use 'myapp' as the domain name. + * + * @param string $domain + * The domain name. + * + * @param string $path optional + * The path to the locale directory (ie: /path/to/locale/) which + * contains ll_CC directories. + */ + function addDomain($domain, $path=false) + { + $support =& GetText::_support(); + return $support->addDomain($domain, $path); + } + + /** + * Retrieve the translation for specified key. + * + * @param string $key + * String to translate using gettext support. + */ + function gettext($key) + { + $support =& GetText::_support(); + return $support->gettext($key); + } + + /** + * Add a variable to gettext interpolation system. + * + * @param string $key + * The variable name. + * + * @param string $value + * The variable value. + */ + function setVar($key, $value) + { + $support =& GetText::_support(); + return $support->setVar($key, $value); + } + + /** + * Add an hashtable of variables. + * + * @param hashtable $hash + * PHP associative array of variables. + */ + function setVars($hash) + { + $support =& GetText::_support(); + return $support->setVars($hash); + } + + /** + * Reset interpolation variables. + */ + function reset() + { + $support =& GetText::_support(); + return $support->reset(); + } +} + + +/** + * Interface to gettext native support. + * + * @author Laurent Bedubourg + * @access private + */ +class GetText_NativeSupport +{ + var $_interpolationVars = array(); + + /** + * Set gettext language code. + * @throws GetText_Error + */ + function setLanguage($langCode) + { + putenv("LANG=$langCode"); + putenv("LC_ALL=$langCode"); + putenv("LANGUAGE=$langCode"); + $set = setlocale(LC_ALL, "$langCode"); + if ($set === false) { + $str = sprintf('Language code "%s" not supported by your system', + $langCode); + $err = new GetText_Error($str); + return PEAR::raiseError($err); + } + } + + /** + * Add a translation domain. + */ + function addDomain($domain, $path=false) + { + if ($path === false) { + bindtextdomain($domain, "./locale/"); + } else { + bindtextdomain($domain, $path); + } + textdomain($domain); + } + + /** + * Retrieve translation for specified key. + * + * @access private + */ + function _getTranslation($key) + { + return gettext($key); + } + + + /** + * Reset interpolation variables. + */ + function reset() + { + $this->_interpolationVars = array(); + } + + /** + * Set an interpolation variable. + */ + function setVar($key, $value) + { + $this->_interpolationVars[$key] = $value; + } + + /** + * Set an associative array of interpolation variables. + */ + function setVars($hash) + { + $this->_interpolationVars = array_merge($this->_interpolationVars, + $hash); + } + + /** + * Retrieve translation for specified key. + * + * @param string $key -- gettext msgid + * @throws GetText_Error + */ + function gettext($key) + { + $value = $this->_getTranslation($key); + if ($value === false) { + $str = sprintf('Unable to locate gettext key "%s"', $key); + $err = new GetText_Error($str); + return PEAR::raiseError($err); + } + + while (preg_match('/\$\{(.*?)\}/sm', $value, $m)) { + list($src, $var) = $m; + + // retrieve variable to interpolate in context, throw an exception + // if not found. + $varValue = $this->_getVar($var); + if ($varValue === false) { + $str = sprintf('Interpolation error, var "%s" not set', $var); + $err = new GetText_Error($str); + return PEAR::raiseError($err); + } + $value = str_replace($src, $varValue, $value); + } + return $value; + } + + /** + * Retrieve an interpolation variable value. + * + * @return mixed + * @access private + */ + function _getVar($name) + { + if (!array_key_exists($name, $this->_interpolationVars)) { + return false; + } + return $this->_interpolationVars[$name]; + } +} + + +/** + * Implementation of GetText support for PHP. + * + * This implementation is abble to cache .po files into php files returning the + * domain translation hashtable. + * + * @access private + * @author Laurent Bedubourg + */ +class GetText_PHPSupport extends GetText_NativeSupport +{ + var $_path = 'locale/'; + var $_langCode = false; + var $_domains = array(); + var $_end = -1; + var $_jobs = array(); + + /** + * Set the translation domain. + * + * @param string $langCode -- language code + * @throws GetText_Error + */ + function setLanguage($langCode) + { + // if language already set, try to reload domains + if ($this->_langCode !== false and $this->_langCode != $langCode) { + foreach ($this->_domains as $domain) { + $this->_jobs[] = array($domain->name, $domain->path); + } + $this->_domains = array(); + $this->_end = -1; + } + + $this->_langCode = $langCode; + + // this allow us to set the language code after + // domain list. + while (count($this->_jobs) > 0) { + list($domain, $path) = array_shift($this->_jobs); + $err = $this->addDomain($domain, $path); + // error raised, break jobs + if (PEAR::isError($err)) { + return $err; + } + } + } + + /** + * Add a translation domain. + * + * @param string $domain -- Domain name + * @param string $path optional -- Repository path + * @throws GetText_Error + */ + function addDomain($domain, $path = "./locale/") + { + if (array_key_exists($domain, $this->_domains)) { + return; + } + + if (!$this->_langCode) { + $this->_jobs[] = array($domain, $path); + return; + } + + $err = $this->_loadDomain($domain, $path); + if (PEAR::isError($err)) { + return $err; + } + + $this->_end++; + } + + /** + * Load a translation domain file. + * + * This method cache the translation hash into a php file unless + * GETTEXT_NO_CACHE is defined. + * + * @param string $domain -- Domain name + * @param string $path optional -- Repository + * @throws GetText_Error + * @access private + */ + function _loadDomain($domain, $path = "./locale") + { + $srcDomain = $path . "/$this->_langCode/LC_MESSAGES/$domain.po"; + $phpDomain = $path . "/$this->_langCode/LC_MESSAGES/$domain.php"; + + if (!file_exists($srcDomain)) { + $str = sprintf('Domain file "%s" not found.', $srcDomain); + $err = new GetText_Error($str); + return PEAR::raiseError($err); + } + + $d = new GetText_Domain(); + $d->name = $domain; + $d->path = $path; + + if (!file_exists($phpDomain) + || (filemtime($phpDomain) < filemtime($srcDomain))) { + + // parse and compile translation table + $parser = new GetText_PHPSupport_Parser(); + $hash = $parser->parse($srcDomain); + if (!defined('GETTEXT_NO_CACHE')) { + $comp = new GetText_PHPSupport_Compiler(); + $err = $comp->compile($hash, $srcDomain); + if (PEAR::isError($err)) { + return $err; + } + } + $d->_keys = $hash; + } else { + $d->_keys = include $phpDomain; + } + $this->_domains[] =& $d; + } + + /** + * Implementation of gettext message retrieval. + */ + function _getTranslation($key) + { + for ($i = $this->_end; $i >= 0; $i--) { + if ($this->_domains[$i]->hasKey($key)) { + return $this->_domains[$i]->get($key); + } + } + return $key; + } +} + +/** + * Class representing a domain file for a specified language. + * + * @access private + * @author Laurent Bedubourg + */ +class GetText_Domain +{ + var $name; + var $path; + + var $_keys = array(); + + function hasKey($key) + { + return array_key_exists($key, $this->_keys); + } + + function get($key) + { + return $this->_keys[$key]; + } +} + +/** + * This class is used to parse gettext '.po' files into php associative arrays. + * + * @access private + * @author Laurent Bedubourg + */ +class GetText_PHPSupport_Parser +{ + var $_hash = array(); + var $_currentKey; + var $_currentValue; + + /** + * Parse specified .po file. + * + * @return hashtable + * @throws GetText_Error + */ + function parse($file) + { + $this->_hash = array(); + $this->_currentKey = false; + $this->_currentValue = ""; + + if (!file_exists($file)) { + $str = sprintf('Unable to locate file "%s"', $file); + $err = new GetText_Error($str); + return PEAR::raiseError($err); + } + $i=0; + $lines = file($file); + foreach ($lines as $line) { + $this->_parseLine($line, ++$i); + } + $this->_storeKey(); + + return $this->_hash; + } + + /** + * Parse one po line. + * + * @access private + */ + function _parseLine($line, $nbr) + { + if (preg_match('/^\s*?#/', $line)) { return; } + if (preg_match('/^\s*?msgid \"(.*?)(?!<\\\)\"/', $line, $m)) { + $this->_storeKey(); + $this->_currentKey = $m[1]; + return; + } + if (preg_match('/^\s*?msgstr \"(.*?)(?!<\\\)\"/', $line, $m)) { + $this->_currentValue .= $m[1]; + return; + } + if (preg_match('/^\s*?\"(.*?)(?!<\\\)\"/', $line, $m)) { + $this->_currentValue .= $m[1]; + return; + } + } + + /** + * Store last key/value pair into building hashtable. + * + * @access private + */ + function _storeKey() + { + if ($this->_currentKey === false) return; + $this->_currentValue = str_replace('\\n', "\n", $this->_currentValue); + $this->_hash[$this->_currentKey] = $this->_currentValue; + $this->_currentKey = false; + $this->_currentValue = ""; + } +} + + +/** + * This class write a php file from a gettext hashtable. + * + * The produced file return the translation hashtable on include. + * + * @throws GetText_Error + * @access private + * @author Laurent Bedubourg + */ +class GetText_PHPSupport_Compiler +{ + /** + * Write hash in an includable php file. + */ + function compile(&$hash, $sourcePath) + { + $destPath = preg_replace('/\.po$/', '.php', $sourcePath); + $fp = @fopen($destPath, "w"); + if (!$fp) { + $str = sprintf('Unable to open "%s" in write mode.', $destPath); + $err = new GetText_Error($str); + return PEAR::raiseError($err); + } + fwrite($fp, ' $value) { + $key = str_replace("'", "\\'", $key); + $value = str_replace("'", "\\'", $value); + fwrite($fp, ' \'' . $key . '\' => \'' . $value . "',\n"); + } + fwrite($fp, ');' . "\n"); + fwrite($fp, '?>'); + fclose($fp); + } +} + +/** + * GetText related error. + */ +class GetText_Error extends PEAR_Error {} + +?> diff --git a/PHPTAL-NP-0.7.0/libs/PEAR.php b/PHPTAL-NP-0.7.0/libs/PEAR.php new file mode 100644 index 0000000000..7f034b7b0a --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/PEAR.php @@ -0,0 +1,945 @@ + | +// | Stig Bakken | +// | Tomas V.V.Cox | +// +----------------------------------------------------------------------+ +// +// $Id$ +// + +define('PEAR_ERROR_RETURN', 1); +define('PEAR_ERROR_PRINT', 2); +define('PEAR_ERROR_TRIGGER', 4); +define('PEAR_ERROR_DIE', 8); +define('PEAR_ERROR_CALLBACK', 16); +define('PEAR_ZE2', (function_exists('version_compare') && + version_compare(zend_version(), "2-dev", "ge"))); + +if (substr(PHP_OS, 0, 3) == 'WIN') { + define('OS_WINDOWS', true); + define('OS_UNIX', false); + define('PEAR_OS', 'Windows'); +} else { + define('OS_WINDOWS', false); + define('OS_UNIX', true); + define('PEAR_OS', 'Unix'); // blatant assumption +} + +$GLOBALS['_PEAR_default_error_mode'] = PEAR_ERROR_RETURN; +$GLOBALS['_PEAR_default_error_options'] = E_USER_NOTICE; +$GLOBALS['_PEAR_destructor_object_list'] = array(); +$GLOBALS['_PEAR_shutdown_funcs'] = array(); +$GLOBALS['_PEAR_error_handler_stack'] = array(); + +ini_set('track_errors', true); + +/** + * Base class for other PEAR classes. Provides rudimentary + * emulation of destructors. + * + * If you want a destructor in your class, inherit PEAR and make a + * destructor method called _yourclassname (same name as the + * constructor, but with a "_" prefix). Also, in your constructor you + * have to call the PEAR constructor: $this->PEAR();. + * The destructor method will be called without parameters. Note that + * at in some SAPI implementations (such as Apache), any output during + * the request shutdown (in which destructors are called) seems to be + * discarded. If you need to get any debug information from your + * destructor, use error_log(), syslog() or something similar. + * + * IMPORTANT! To use the emulated destructors you need to create the + * objects by reference, ej: $obj =& new PEAR_child; + * + * @since PHP 4.0.2 + * @author Stig Bakken + * @see http://pear.php.net/manual/ + */ +class PEAR +{ + // {{{ properties + + /** + * Whether to enable internal debug messages. + * + * @var bool + * @access private + */ + var $_debug = false; + + /** + * Default error mode for this object. + * + * @var int + * @access private + */ + var $_default_error_mode = null; + + /** + * Default error options used for this object when error mode + * is PEAR_ERROR_TRIGGER. + * + * @var int + * @access private + */ + var $_default_error_options = null; + + /** + * Default error handler (callback) for this object, if error mode is + * PEAR_ERROR_CALLBACK. + * + * @var string + * @access private + */ + var $_default_error_handler = ''; + + /** + * Which class to use for error objects. + * + * @var string + * @access private + */ + var $_error_class = 'PEAR_Error'; + + /** + * An array of expected errors. + * + * @var array + * @access private + */ + var $_expected_errors = array(); + + // }}} + + // {{{ constructor + + /** + * Constructor. Registers this object in + * $_PEAR_destructor_object_list for destructor emulation if a + * destructor object exists. + * + * @param string $error_class (optional) which class to use for + * error objects, defaults to PEAR_Error. + * @access public + * @return void + */ + function PEAR($error_class = null) + { + $classname = get_class($this); + if ($this->_debug) { + print "PEAR constructor called, class=$classname\n"; + } + if ($error_class !== null) { + $this->_error_class = $error_class; + } + while ($classname) { + $destructor = "_$classname"; + if (method_exists($this, $destructor)) { + global $_PEAR_destructor_object_list; + $_PEAR_destructor_object_list[] = &$this; + break; + } else { + $classname = get_parent_class($classname); + } + } + } + + // }}} + // {{{ destructor + + /** + * Destructor (the emulated type of...). Does nothing right now, + * but is included for forward compatibility, so subclass + * destructors should always call it. + * + * See the note in the class desciption about output from + * destructors. + * + * @access public + * @return void + */ + function _PEAR() { + if ($this->_debug) { + printf("PEAR destructor called, class=%s\n", get_class($this)); + } + } + + // }}} + // {{{ getStaticProperty() + + /** + * If you have a class that's mostly/entirely static, and you need static + * properties, you can use this method to simulate them. Eg. in your method(s) + * do this: $myVar = &PEAR::getStaticProperty('myVar'); + * You MUST use a reference, or they will not persist! + * + * @access public + * @param string $class The calling classname, to prevent clashes + * @param string $var The variable to retrieve. + * @return mixed A reference to the variable. If not set it will be + * auto initialised to NULL. + */ + function &getStaticProperty($class, $var) + { + static $properties; + return $properties[$class][$var]; + } + + // }}} + // {{{ registerShutdownFunc() + + /** + * Use this function to register a shutdown method for static + * classes. + * + * @access public + * @param mixed $func The function name (or array of class/method) to call + * @param mixed $args The arguments to pass to the function + * @return void + */ + function registerShutdownFunc($func, $args = array()) + { + $GLOBALS['_PEAR_shutdown_funcs'][] = array($func, $args); + } + + // }}} + // {{{ isError() + + /** + * Tell whether a value is a PEAR error. + * + * @param mixed $data the value to test + * @access public + * @return bool true if parameter is an error + */ + function isError($data) { + return (bool)(is_object($data) && + (get_class($data) == 'pear_error' || + is_subclass_of($data, 'pear_error'))); + } + + // }}} + // {{{ setErrorHandling() + + /** + * Sets how errors generated by this DB object should be handled. + * Can be invoked both in objects and statically. If called + * statically, setErrorHandling sets the default behaviour for all + * PEAR objects. If called in an object, setErrorHandling sets + * the default behaviour for that object. + * + * @param int $mode + * One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT, + * PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE or + * PEAR_ERROR_CALLBACK. + * + * @param mixed $options + * When $mode is PEAR_ERROR_TRIGGER, this is the error level (one + * of E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR). + * + * When $mode is PEAR_ERROR_CALLBACK, this parameter is expected + * to be the callback function or method. A callback + * function is a string with the name of the function, a + * callback method is an array of two elements: the element + * at index 0 is the object, and the element at index 1 is + * the name of the method to call in the object. + * + * When $mode is PEAR_ERROR_PRINT or PEAR_ERROR_DIE, this is + * a printf format string used when printing the error + * message. + * + * @access public + * @return void + * @see PEAR_ERROR_RETURN + * @see PEAR_ERROR_PRINT + * @see PEAR_ERROR_TRIGGER + * @see PEAR_ERROR_DIE + * @see PEAR_ERROR_CALLBACK + * + * @since PHP 4.0.5 + */ + + function setErrorHandling($mode = null, $options = null) + { + if (isset($this)) { + $setmode = &$this->_default_error_mode; + $setoptions = &$this->_default_error_options; + } else { + $setmode = &$GLOBALS['_PEAR_default_error_mode']; + $setoptions = &$GLOBALS['_PEAR_default_error_options']; + } + + switch ($mode) { + case PEAR_ERROR_RETURN: + case PEAR_ERROR_PRINT: + case PEAR_ERROR_TRIGGER: + case PEAR_ERROR_DIE: + case null: + $setmode = $mode; + $setoptions = $options; + break; + + case PEAR_ERROR_CALLBACK: + $setmode = $mode; + if ((is_string($options) && function_exists($options)) || + (is_array($options) && method_exists(@$options[0], @$options[1]))) + { + $setoptions = $options; + } else { + trigger_error("invalid error callback", E_USER_WARNING); + } + break; + + default: + trigger_error("invalid error mode", E_USER_WARNING); + break; + } + } + + // }}} + // {{{ expectError() + + /** + * This method is used to tell which errors you expect to get. + * Expected errors are always returned with error mode + * PEAR_ERROR_RETURN. Expected error codes are stored in a stack, + * and this method pushes a new element onto it. The list of + * expected errors are in effect until they are popped off the + * stack with the popExpect() method. + * + * Note that this method can not be called statically + * + * @param mixed $code a single error code or an array of error codes to expect + * + * @return int the new depth of the "expected errors" stack + * @access public + */ + function expectError($code = '*') + { + if (is_array($code)) { + array_push($this->_expected_errors, $code); + } else { + array_push($this->_expected_errors, array($code)); + } + return sizeof($this->_expected_errors); + } + + // }}} + // {{{ popExpect() + + /** + * This method pops one element off the expected error codes + * stack. + * + * @return array the list of error codes that were popped + */ + function popExpect() + { + return array_pop($this->_expected_errors); + } + + // }}} + // {{{ _checkDelExpect() + + /** + * This method checks unsets an error code if available + * + * @param mixed error code + * @return bool true if the error code was unset, false otherwise + * @access private + * @since PHP 4.3.0 + */ + function _checkDelExpect($error_code) + { + $deleted = false; + + foreach ($this->_expected_errors AS $key => $error_array) { + if (in_array($error_code, $error_array)) { + unset($this->_expected_errors[$key][array_search($error_code, $error_array)]); + $deleted = true; + } + + // clean up empty arrays + if (0 == count($this->_expected_errors[$key])) { + unset($this->_expected_errors[$key]); + } + } + return $deleted; + } + + // }}} + // {{{ delExpect() + + /** + * This method deletes all occurences of the specified element from + * the expected error codes stack. + * + * @param mixed $error_code error code that should be deleted + * @return mixed list of error codes that were deleted or error + * @access public + * @since PHP 4.3.0 + */ + function delExpect($error_code) + { + $deleted = false; + + if ((is_array($error_code) && (0 != count($error_code)))) { + // $error_code is a non-empty array here; + // we walk through it trying to unset all + // values + foreach($error_code AS $key => $error) { + if ($this->_checkDelExpect($error)) { + $deleted = true; + } else { + $deleted = false; + } + } + return $deleted ? true : PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME + } elseif (!empty($error_code)) { + // $error_code comes alone, trying to unset it + if ($this->_checkDelExpect($error_code)) { + return true; + } else { + return PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME + } + } else { + // $error_code is empty + return PEAR::raiseError("The expected error you submitted is empty"); // IMPROVE ME + } + } + + // }}} + // {{{ raiseError() + + /** + * This method is a wrapper that returns an instance of the + * configured error class with this object's default error + * handling applied. If the $mode and $options parameters are not + * specified, the object's defaults are used. + * + * @param mixed $message a text error message or a PEAR error object + * + * @param int $code a numeric error code (it is up to your class + * to define these if you want to use codes) + * + * @param int $mode One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT, + * PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE or + * PEAR_ERROR_CALLBACK. + * + * @param mixed $options If $mode is PEAR_ERROR_TRIGGER, this parameter + * specifies the PHP-internal error level (one of + * E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR). + * If $mode is PEAR_ERROR_CALLBACK, this + * parameter specifies the callback function or + * method. In other error modes this parameter + * is ignored. + * + * @param string $userinfo If you need to pass along for example debug + * information, this parameter is meant for that. + * + * @param string $error_class The returned error object will be + * instantiated from this class, if specified. + * + * @param bool $skipmsg If true, raiseError will only pass error codes, + * the error message parameter will be dropped. + * + * @access public + * @return object a PEAR error object + * @see PEAR::setErrorHandling + * @since PHP 4.0.5 + */ + function &raiseError($message = null, + $code = null, + $mode = null, + $options = null, + $userinfo = null, + $error_class = null, + $skipmsg = false) + { + // The error is yet a PEAR error object + if (is_object($message)) { + $code = $message->getCode(); + $userinfo = $message->getUserInfo(); + $error_class = $message->getType(); + $message = $message->getMessage(); + } + + if (isset($this) && isset($this->_expected_errors) && sizeof($this->_expected_errors) > 0 && sizeof($exp = end($this->_expected_errors))) { + if ($exp[0] == "*" || + (is_int(reset($exp)) && in_array($code, $exp)) || + (is_string(reset($exp)) && in_array($message, $exp))) { + $mode = PEAR_ERROR_RETURN; + } + } + // No mode given, try global ones + if ($mode === null) { + // Class error handler + if (isset($this) && isset($this->_default_error_mode)) { + $mode = $this->_default_error_mode; + $options = $this->_default_error_options; + // Global error handler + } elseif (isset($GLOBALS['_PEAR_default_error_mode'])) { + $mode = $GLOBALS['_PEAR_default_error_mode']; + $options = $GLOBALS['_PEAR_default_error_options']; + } + } + + if ($error_class !== null) { + $ec = $error_class; + } elseif (isset($this) && isset($this->_error_class)) { + $ec = $this->_error_class; + } else { + $ec = 'PEAR_Error'; + } + if ($skipmsg) { + return new $ec($code, $mode, $options, $userinfo); + } else { + return new $ec($message, $code, $mode, $options, $userinfo); + } + } + + // }}} + // {{{ throwError() + + /** + * Simpler form of raiseError with fewer options. In most cases + * message, code and userinfo are enough. + * + * @param string $message + * + */ + function &throwError($message = null, + $code = null, + $userinfo = null) + { + if (isset($this)) { + return $this->raiseError($message, $code, null, null, $userinfo); + } else { + return PEAR::raiseError($message, $code, null, null, $userinfo); + } + } + + // }}} + // {{{ pushErrorHandling() + + /** + * Push a new error handler on top of the error handler options stack. With this + * you can easily override the actual error handler for some code and restore + * it later with popErrorHandling. + * + * @param mixed $mode (same as setErrorHandling) + * @param mixed $options (same as setErrorHandling) + * + * @return bool Always true + * + * @see PEAR::setErrorHandling + */ + function pushErrorHandling($mode, $options = null) + { + $stack = &$GLOBALS['_PEAR_error_handler_stack']; + if (isset($this)) { + $def_mode = &$this->_default_error_mode; + $def_options = &$this->_default_error_options; + } else { + $def_mode = &$GLOBALS['_PEAR_default_error_mode']; + $def_options = &$GLOBALS['_PEAR_default_error_options']; + } + $stack[] = array($def_mode, $def_options); + + if (isset($this)) { + $this->setErrorHandling($mode, $options); + } else { + PEAR::setErrorHandling($mode, $options); + } + $stack[] = array($mode, $options); + return true; + } + + // }}} + // {{{ popErrorHandling() + + /** + * Pop the last error handler used + * + * @return bool Always true + * + * @see PEAR::pushErrorHandling + */ + function popErrorHandling() + { + $stack = &$GLOBALS['_PEAR_error_handler_stack']; + array_pop($stack); + list($mode, $options) = $stack[sizeof($stack) - 1]; + array_pop($stack); + if (isset($this)) { + $this->setErrorHandling($mode, $options); + } else { + PEAR::setErrorHandling($mode, $options); + } + return true; + } + + // }}} + // {{{ loadExtension() + + /** + * OS independant PHP extension load. Remember to take care + * on the correct extension name for case sensitive OSes. + * + * @param string $ext The extension name + * @return bool Success or not on the dl() call + */ + function loadExtension($ext) + { + if (!extension_loaded($ext)) { + if (OS_WINDOWS) { + $suffix = '.dll'; + } elseif (PHP_OS == 'HP-UX') { + $suffix = '.sl'; + } elseif (PHP_OS == 'AIX') { + $suffix = '.a'; + } elseif (PHP_OS == 'OSX') { + $suffix = '.bundle'; + } else { + $suffix = '.so'; + } + return @dl('php_'.$ext.$suffix) || @dl($ext.$suffix); + } + return true; + } + + // }}} +} + +// {{{ _PEAR_call_destructors() + +function _PEAR_call_destructors() +{ + global $_PEAR_destructor_object_list; + if (is_array($_PEAR_destructor_object_list) && + sizeof($_PEAR_destructor_object_list)) + { + reset($_PEAR_destructor_object_list); + while (list($k, $objref) = each($_PEAR_destructor_object_list)) { + $classname = get_class($objref); + while ($classname) { + $destructor = "_$classname"; + if (method_exists($objref, $destructor)) { + $objref->$destructor(); + break; + } else { + $classname = get_parent_class($classname); + } + } + } + // Empty the object list to ensure that destructors are + // not called more than once. + $_PEAR_destructor_object_list = array(); + } + + // Now call the shutdown functions + if (is_array($GLOBALS['_PEAR_shutdown_funcs']) AND !empty($GLOBALS['_PEAR_shutdown_funcs'])) { + foreach ($GLOBALS['_PEAR_shutdown_funcs'] as $value) { + call_user_func_array($value[0], $value[1]); + } + } +} + +// }}} + +class PEAR_Error +{ + // {{{ properties + + var $error_message_prefix = ''; + var $mode = PEAR_ERROR_RETURN; + var $level = E_USER_NOTICE; + var $code = -1; + var $message = ''; + var $userinfo = ''; + var $backtrace = null; + + // }}} + // {{{ constructor + + /** + * PEAR_Error constructor + * + * @param string $message message + * + * @param int $code (optional) error code + * + * @param int $mode (optional) error mode, one of: PEAR_ERROR_RETURN, + * PEAR_ERROR_PRINT, PEAR_ERROR_DIE, PEAR_ERROR_TRIGGER or + * PEAR_ERROR_CALLBACK + * + * @param mixed $options (optional) error level, _OR_ in the case of + * PEAR_ERROR_CALLBACK, the callback function or object/method + * tuple. + * + * @param string $userinfo (optional) additional user/debug info + * + * @access public + * + */ + function PEAR_Error($message = 'unknown error', $code = null, + $mode = null, $options = null, $userinfo = null) + { + if ($mode === null) { + $mode = PEAR_ERROR_RETURN; + } + $this->message = $message; + $this->code = $code; + $this->mode = $mode; + $this->userinfo = $userinfo; + if (function_exists("debug_backtrace")) { + $this->backtrace = debug_backtrace(); + } + if ($mode & PEAR_ERROR_CALLBACK) { + $this->level = E_USER_NOTICE; + $this->callback = $options; + } else { + if ($options === null) { + $options = E_USER_NOTICE; + } + $this->level = $options; + $this->callback = null; + } + if ($this->mode & PEAR_ERROR_PRINT) { + if (is_null($options) || is_int($options)) { + $format = "%s"; + } else { + $format = $options; + } + printf($format, $this->getMessage()); + } + if ($this->mode & PEAR_ERROR_TRIGGER) { + trigger_error($this->getMessage(), $this->level); + } + if ($this->mode & PEAR_ERROR_DIE) { + $msg = $this->getMessage(); + if (is_null($options) || is_int($options)) { + $format = "%s"; + if (substr($msg, -1) != "\n") { + $msg .= "\n"; + } + } else { + $format = $options; + } + die(sprintf($format, $msg)); + } + if ($this->mode & PEAR_ERROR_CALLBACK) { + if (is_string($this->callback) && strlen($this->callback)) { + call_user_func($this->callback, $this); + } elseif (is_array($this->callback) && + sizeof($this->callback) == 2 && + is_object($this->callback[0]) && + is_string($this->callback[1]) && + strlen($this->callback[1])) { + @call_user_func($this->callback, $this); + } + } + } + + // }}} + // {{{ getMode() + + /** + * Get the error mode from an error object. + * + * @return int error mode + * @access public + */ + function getMode() { + return $this->mode; + } + + // }}} + // {{{ getCallback() + + /** + * Get the callback function/method from an error object. + * + * @return mixed callback function or object/method array + * @access public + */ + function getCallback() { + return $this->callback; + } + + // }}} + // {{{ getMessage() + + + /** + * Get the error message from an error object. + * + * @return string full error message + * @access public + */ + function getMessage() + { + return ($this->error_message_prefix . $this->message); + } + + + // }}} + // {{{ getCode() + + /** + * Get error code from an error object + * + * @return int error code + * @access public + */ + function getCode() + { + return $this->code; + } + + // }}} + // {{{ getType() + + /** + * Get the name of this error/exception. + * + * @return string error/exception name (type) + * @access public + */ + function getType() + { + return get_class($this); + } + + // }}} + // {{{ getUserInfo() + + /** + * Get additional user-supplied information. + * + * @return string user-supplied information + * @access public + */ + function getUserInfo() + { + return $this->userinfo; + } + + // }}} + // {{{ getDebugInfo() + + /** + * Get additional debug information supplied by the application. + * + * @return string debug information + * @access public + */ + function getDebugInfo() + { + return $this->getUserInfo(); + } + + // }}} + // {{{ getBacktrace() + + /** + * Get the call backtrace from where the error was generated. + * Supported with PHP 4.3.0 or newer. + * + * @param int $frame (optional) what frame to fetch + * @return array Backtrace, or NULL if not available. + * @access public + */ + function getBacktrace($frame = null) + { + if ($frame === null) { + return $this->backtrace; + } + return $this->backtrace[$frame]; + } + + // }}} + // {{{ addUserInfo() + + function addUserInfo($info) + { + if (empty($this->userinfo)) { + $this->userinfo = $info; + } else { + $this->userinfo .= " ** $info"; + } + } + + // }}} + // {{{ toString() + + /** + * Make a string representation of this object. + * + * @return string a string with an object summary + * @access public + */ + function toString() { + $modes = array(); + $levels = array(E_USER_NOTICE => 'notice', + E_USER_WARNING => 'warning', + E_USER_ERROR => 'error'); + if ($this->mode & PEAR_ERROR_CALLBACK) { + if (is_array($this->callback)) { + $callback = get_class($this->callback[0]) . '::' . + $this->callback[1]; + } else { + $callback = $this->callback; + } + return sprintf('[%s: message="%s" code=%d mode=callback '. + 'callback=%s prefix="%s" info="%s"]', + get_class($this), $this->message, $this->code, + $callback, $this->error_message_prefix, + $this->userinfo); + } + if ($this->mode & PEAR_ERROR_PRINT) { + $modes[] = 'print'; + } + if ($this->mode & PEAR_ERROR_TRIGGER) { + $modes[] = 'trigger'; + } + if ($this->mode & PEAR_ERROR_DIE) { + $modes[] = 'die'; + } + if ($this->mode & PEAR_ERROR_RETURN) { + $modes[] = 'return'; + } + return sprintf('[%s: message="%s" code=%d mode=%s level=%s '. + 'prefix="%s" info="%s"]', + get_class($this), $this->message, $this->code, + implode("|", $modes), $levels[$this->level], + $this->error_message_prefix, + $this->userinfo); + } + + // }}} +} + +register_shutdown_function("_PEAR_call_destructors"); + +/* + * Local Variables: + * mode: php + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ +?> diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL.php b/PHPTAL-NP-0.7.0/libs/PHPTAL.php new file mode 100644 index 0000000000..e05e583532 --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/PHPTAL.php @@ -0,0 +1,288 @@ + +// + +/* + * This file: + * + * - Include PHPTAL dependencies + * - Define PHPTAL attributes + * - Define PHPTAL aliases + * - Define PHPTAL rules + * + * @author Laurent Bedubourg + */ + +$__d = dirname(__FILE__); +require_once "PEAR.php"; + +if (OS_WINDOWS) { + define('PHPTAL_PATH_SEP', '\\'); +} else { + define('PHPTAL_PATH_SEP', '/'); +} + +function _phptal_os_path_join() +{ + $args = func_get_args(); + return join(PHPTAL_PATH_SEP, $args); +} + +require_once 'Types/Errors.php'; +require_once 'Types/OString.php'; + +require_once _phptal_os_path_join($__d, 'PHPTAL', 'Cache.php'); +require_once _phptal_os_path_join($__d, 'PHPTAL', 'Context.php'); +require_once _phptal_os_path_join($__d, 'PHPTAL', 'Filter.php'); +require_once _phptal_os_path_join($__d, 'PHPTAL', 'LoopControler.php'); +require_once _phptal_os_path_join($__d, 'PHPTAL', 'OutputControl.php'); +require_once _phptal_os_path_join($__d, 'PHPTAL', 'Template.php'); +require_once _phptal_os_path_join($__d, 'PHPTAL', 'Macro.php'); +require_once _phptal_os_path_join($__d, 'PHPTAL', 'I18N.php'); + +require_once _phptal_os_path_join($__d, 'PHPTAL', 'SourceResolver.php'); +require_once _phptal_os_path_join($__d, 'PHPTAL', 'SourceLocator.php'); + + +define('PHPTAL_VERSION', '0.7.0'); +define('PHPTAL_MARK', str_replace('.', '_', PHPTAL_VERSION) . '_'); +define('PHPTAL_DEFAULT_CACHE_DIR', '/tmp/'); + +/** + * This define is used to select the templates output format. + * + * There's few differences between XHTML and XML but they these differences can + * break some browsers output. + * + * Default PHPTAL output mode is XHTML. + */ +define('PHPTAL_XHTML', 1); + +/** + * This define is used to select the templates output format. + * + * The XML mode does not worry about XHTML specificity and echo every entity + * in a format. + */ +define('PHPTAL_XML', 2); + +/** + * @var _phptal_namespaces + * @type array + * + * This array contains the list of all known attribute namespaces, if an + * attribute belonging to one of this namespaces is not recognized by PHPTAL, + * an exception will be raised. + * + * These namespaces will be drop from resulting xml/xhtml unless the parser + * is told to keep them. + * + * @access private + * @static 1 + */ +global $_phptal_namespaces; +$_phptal_namespaces = array('TAL', 'METAL', 'I18N', 'PHPTAL'); + + +define('_PHPTAL_SURROUND', 1); +define('_PHPTAL_REPLACE', 2); +define('_PHPTAL_CONTENT', 3); + +/** + * @var _phptal_dictionary + * @type hashtable + * + * This dictionary contains ALL known PHPTAL attributes. Unknown attributes + * will be echoed in result as xhtml/xml ones. + * + * The value define how and when the attribute handler will be called during + * code generation. + * + * @access private + * @static 1 + */ +global $_phptal_dictionary; +$_phptal_dictionary = array( + 'TAL:DEFINE' => _PHPTAL_REPLACE, // set a context variable + 'TAL:CONDITION' => _PHPTAL_SURROUND, // print tag content only when condition true + 'TAL:REPEAT' => _PHPTAL_SURROUND, // repeat over an iterable + 'TAL:CONTENT' => _PHPTAL_CONTENT, // replace tag content + 'TAL:REPLACE' => _PHPTAL_REPLACE, // replace entire tag + 'TAL:ATTRIBUTES' => _PHPTAL_REPLACE, // dynamically set tag attributes + 'TAL:OMIT-TAG' => _PHPTAL_SURROUND, // omit to print tag but not its content + 'TAL:COMMENT' => _PHPTAL_SURROUND, // do nothing + 'TAL:ON-ERROR' => _PHPTAL_SURROUND, // replace content with this if error occurs + + 'METAL:DEFINE-MACRO' => _PHPTAL_SURROUND, // define a template macro + 'METAL:USE-MACRO' => _PHPTAL_REPLACE, // use a template macro + 'METAL:DEFINE-SLOT' => _PHPTAL_SURROUND, // define a macro slot + 'METAL:FILL-SLOT' => _PHPTAL_SURROUND, // fill a macro slot + + 'PHPTAL:INCLUDE' => _PHPTAL_REPLACE, // include an external template + 'PHPTAL:SRC-INCLUDE' => _PHPTAL_CONTENT, // include external file without parsing + + 'I18N:TRANSLATE' => _PHPTAL_CONTENT, // translate some data using GetText package + 'I18N:NAME' => _PHPTAL_SURROUND, // prepare a translation name + 'I18N:ATTRIBUTES' => _PHPTAL_REPLACE, // translate tag attributes values +); + +/** + * @var _phptal_aliases + * @type hashtable + * + * Create aliases for attributes. If an alias is found during parsing, the + * matching phptal attribute will be used. + * + * @access private + * @static 1 + */ +global $_phptal_aliases; +$_phptal_aliases = array( + 'TAL:INCLUDE' => 'PHPTAL:INCLUDE', + 'TAL:SRC-INCLUDE'=> 'PHPTAL:SRC-INCLUDE', +); + +/** + * @var _phptal_rules_order + * @type hashtable + * + * This rule associative array represents both ordering and exclusion + * mecanism for template attributes. + * + * All known attributes must appear here and must be associated with + * an occurence priority. + * + * When more than one phptal attribute appear in the same tag, they + * will execute in following order. + * + * @access private + * @static 1 + */ +global $_phptal_rules_order; +$_phptal_rules_order = array( + 'TAL:OMIT-TAG' => 0, // surround -> $tag->disableHeadFootPrint() + + 'TAL:ON-ERROR' => 1, // surround + + 'METAL:DEFINE-MACRO' => 3, // surround + 'TAL:DEFINE' => 3, // replace + 'I18N:NAME' => 3, // replace + 'I18N:TRANSLATE' => 3, // content + + 'TAL:CONDITION' => 4, // surround + + 'TAL:REPEAT' => 5, // surround + + 'I18N:ATTRIBUTES' => 6, // replace + 'TAL:ATTRIBUTES' => 6, // replace + 'TAL:REPLACE' => 6, // replace + 'METAL:USE-MACRO' => 6, // replace + 'PHPTAL:SRC-INCLUDE' => 6, // replace + 'PHPTAL:INCLUDE' => 6, // replace + 'METAL:DEFINE-SLOT' => 6, // replace + 'METAL:FILL-SLOT' => 6, // replace + + 'TAL:CONTENT' => 7, // content + + 'TAL:COMMENT' => 8, // surround +); + +/** + * @var _phptal_xhtml_content_free_tags + * @type array + * + * This array contains XHTML tags that must be echoed in a <tag/> form + * instead of the <tag></tag> form. + * + * In fact, some browsers does not support the later form so PHPTAL + * ensure these tags are correctly echoed. + */ +global $_phptal_xhtml_empty_tags; +$_phptal_xhtml_empty_tags = array( + 'AREA', + 'BASE', + 'BASEFONT', + 'BR', + 'COL', + 'FRAME', + 'HR', + 'IMG', + 'INPUT', + 'ISINDEX', + 'LINK', + 'META', + 'PARAM', +); + +/** + * @var _phptal_xhtml_boolean_attributes + * @type array + * + * This array contains XHTML attributes that must be echoed in a minimized + * form. Some browsers (non HTML4 compliants are unable to interpret those + * attributes. + * + * The output will definitively not be an xml document !! + * PreFilters should be set to modify xhtml input containing these attributes. + */ +global $_phptal_xhtml_boolean_attributes; +$_phptal_xhtml_boolean_attributes = array( + 'compact', + 'nowrap', + 'ismap', + 'declare', + 'noshade', + 'checked', + 'disabled', + 'readonly', + 'multiple', + 'selected', + 'noresize', + 'defer' +); + +/** + * Shortcut to PHPTAL_Template for lazzy ones (me first). + */ +class PHPTAL extends PHPTAL_Template {} + +/** + * PEAR compliant class name. + */ +class HTML_Template_PHPTAL extends PHPTAL_Template {} + +/** + * PEAR compliant class name. + */ +class HTML_Template_PHPTAL_Filter extends PHPTAL_Filter {} + +/** + * PEAR compliant class name. + */ +class HTML_Template_PHPTAL_SourceLocator extends PHPTAL_SourceLocator {} + +/** + * PEAR compliant class name. + */ +class HTML_Template_PHPTAL_SourceResolver extends PHPTAL_SourceResolver {} + + +?> diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute.php new file mode 100644 index 0000000000..c948eda193 --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute.php @@ -0,0 +1,42 @@ + +// + +/** + * Base class for every kind of PHPTAL attribute. + * + * @author Laurent Bedubourg + */ +class PHPTAL_Attribute +{ + var $expression; + + function PHPTAL_Attribute($exp) + { + $this->expression = $exp; + } + + function activate(&$g, &$tag){} + function start(&$g, &$tag){} + function end(&$g, &$tag){} +} + +?> diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/I18N/Attributes.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/I18N/Attributes.php new file mode 100644 index 0000000000..4c12f5e491 --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/I18N/Attributes.php @@ -0,0 +1,142 @@ + +// + +class PHPTAL_Attribute_I18N_Attributes extends PHPTAL_Attribute +{ + var $_overwritten = array(); + + function activate(&$g, &$tag) + { + global $_phptal_xhtml_boolean_attributes; + $g->requireGettext(); + + $g->doPrintString('<', $tag->name()); + + $attributes = $tag->attributes(); + + // prepare expressions for attributes to translate + $exp = new PHPTAL_Expression($g, $tag, $this->expression); + $exp->setPolicy(_PHPTAL_ES_RECEIVER_IS_TEMP); + $err = $exp->prepare(); + if (PEAR::isError($err)) { return $err; } + + // more than one attribute to translate + if ($exp->countSubs() > 0) { + foreach ($exp->subs() as $subExpression) { + $err = $this->_attributeExpression($g, $tag, $subExpression); + if (PEAR::isError($err)) { return $err; } + } + } else { + $err = $this->_attributeExpression($g, $tag, $exp); + if (PEAR::isError($err)) { return $err; } + } + + // echo non overwritten attributes + foreach ($attributes as $key=>$value) { + $test_key = strtolower($key); + if (!in_array($test_key, $this->_overwritten)) { + // beware of xhtml boolean attributes + if ($tag->_parser->_outputMode() == PHPTAL_XHTML + && in_array($test_key, $_phptal_xhtml_boolean_attributes)) { + $g->doPrintString(' '.$key); + } else { + $g->doPrintString(' '.$key.'="'); + $g->doPrintString($value); + $g->doPrintString('"'); + } + } + } + + if ($tag->_isXHTMLEmptyElement()) { + $g->doPrintString(' />'); + return; + } + + if ($tag->hasContent()) { + $g->doPrintString('>'); + } else { + $g->doPrintString('/>'); + } + + $err = $tag->generateContent($g); + if (PEAR::isError($err)) { return $err; } + + if ($tag->hasContent()) { + $g->doPrintString('name(), '>'); + } + } + + function _attributeExpression(&$g, &$tag, &$subExpression) + { + $attributes = $tag->attributes(); + $default = false; + $name = strtolower($subExpression->getReceiver()); + + // set default attribute value in $default variable + if (preg_match('/\bdefault\b/sm', $subExpression->_src)) { + if (!array_key_exists($name, $attributes)) { + $g->doAffectResult('$__default__', 'false'); + } else { + $value = $attributes[$name]; + $value = str_replace('\'', '\\\'', $value); + $g->doAffectResult('$__default__', '\''. $value . '\''); + } + $default = true; + } + + $real = str_replace('__phptales_dd__', ':', $name); + $this->_overwritten[] = $real; + $err = $subExpression->generate(); + if (PEAR::isError($err)) { return $err; } + + $this->_printAttribute($g, $tag, $real, $name, $default); + } + + function _printAttribute(&$g, &$tag, $realName, $varName, $default=false) + { + global $_phptal_xhtml_boolean_attributes; + + // watch boolean attributes on XHTML mode + if ($tag->_parser->_outputMode() == PHPTAL_XHTML + && in_array($realName, $_phptal_xhtml_boolean_attributes)) { + $g->doIf('!PEAR::isError($'.$varName.') && $'.$varName); + $g->doPrintString(' '.$realName); + $g->endBlock(); + } elseif ($default) { + $g->doIf('!PEAR::isError($'.$varName.') && false !== $'.$varName.' && null !== $'.$varName); + $g->doPrintString(' '. $realName . '="'); + $code = sprintf('$__tpl__->_translate(trim($%s))', $varName); + $g->doPrintRes($code, true); + // $g->doPrintVar($varName); + $g->doPrintString('"'); + $g->endBlock(); + } else { + $g->doPrintString(' '. $realName . '="'); + $code = sprintf('$__tpl__->_translate(trim($%s))', $varName); + $g->doPrintRes($code, true); + // $g->doPrintVar($varName); + $g->doPrintString('"'); + } + } +} + +?> diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/I18N/Name.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/I18N/Name.php new file mode 100644 index 0000000000..58970c20ed --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/I18N/Name.php @@ -0,0 +1,42 @@ + +// + +class PHPTAL_Attribute_I18N_Name extends PHPTAL_Attribute +{ + function start(&$g, &$tag) + { + $g->requireGettext(); + $g->doOBStart(); + } + + function end(&$g, &$tag) + { + $temp = $g->newTemporaryVar(); + $g->doOBEnd($temp); + $code = sprintf('$__tpl__->_setTranslateVar(\'%s\', %s)', + $this->expression, + $temp); + $g->execute($code); + } +} + +?> diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/I18N/Translate.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/I18N/Translate.php new file mode 100644 index 0000000000..42c1e805c6 --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/I18N/Translate.php @@ -0,0 +1,82 @@ + +// + +class PHPTAL_Attribute_I18N_Translate extends PHPTAL_Attribute +{ + function activate(&$g, &$tag) + { + $g->requireGettext(); + + if (strlen($this->expression) == 0) { + $key = "'". $this->_preparseGetTextKey($tag) ."'"; + } else { + $exp = new PHPTAL_Expression($g, $tag, $this->expression); + $exp->setPolicy(_PHPTAL_ES_RECEIVER_IS_TEMP); + $key = $g->newTemporaryVar(); + $exp->setReceiver($key); + $err = $exp->generate(); + if (PEAR::isError($err)) { return $err; } + } + + // children may contains i18n:name attributes, + // we ignore output but parse content before calling translation. + $g->doOBStart(); + foreach ($tag->_children as $child) { + $child->generateCode($g); + } + $g->doOBClean(); + // $code = sprintf('$__tpl__->_translate(\'%s\')', $key); + $code = sprintf('$__tpl__->_translate(%s)', $key); + $g->doPrintRes($code, true); + } + + function _preparseGetTextKey(&$tag) + { + $key = ""; + foreach ($tag->_children as $child) { + if ($child->isData()) { + $str = preg_replace('/\s+/sm', ' ', $child->_content); + $key .= trim($str) . ' '; + } else { + $is_i18n_name = false; + // look for i18n:name + foreach ($child->_surround_attributes as $att) { + if (get_class($att) == strtolower("PHPTAL_Attribute_I18N_Name")) { + $key .= '${' . $att->expression . '}'; + $is_i18n_name = true; + } + } + // recursive call to preparse key for non i18n:name tags + if (!$is_i18n_name) { + $key .= PHPTAL_Attribute_I18N_Translate::_preparseGetTextKey($child) . ' '; + } + } + } + + // remove every thing that has more than 1 space + $key = preg_replace('/\s+/sm', ' ', $key); + $key = trim($key); + return $key; + } +} + +?> diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/METAL/Define_macro.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/METAL/Define_macro.php new file mode 100644 index 0000000000..fc06ebce76 --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/METAL/Define_macro.php @@ -0,0 +1,36 @@ + +// + +class PHPTAL_Attribute_METAL_Define_Macro extends PHPTAL_Attribute +{ + function start(&$g, &$tag) + { + $g->doMacroDeclare($this->expression); + } + + function end(&$g, &$tag) + { + $g->doMacroEnd(); + } +} + +?> diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/METAL/Define_slot.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/METAL/Define_slot.php new file mode 100644 index 0000000000..811cd6356a --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/METAL/Define_slot.php @@ -0,0 +1,40 @@ + +// + +class PHPTAL_Attribute_METAL_Define_slot extends PHPTAL_Attribute +{ + function start(&$g, &$tag) + { + $slotName = $this->expression; + $cond = sprintf('$__ctx__->has(\'slots/%s\')', $slotName); + $g->doIf($cond); + $g->doPrintContext('slots/'.$slotName, true); + $g->doElse(); + } + + function end(&$g, &$tag) + { + $g->endBlock(); + } +}; + +?> diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/METAL/Fill_slot.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/METAL/Fill_slot.php new file mode 100644 index 0000000000..b71926c7ee --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/METAL/Fill_slot.php @@ -0,0 +1,36 @@ + +// + +class PHPTAL_Attribute_METAL_Fill_slot extends PHPTAL_Attribute +{ + function start(&$g, &$tag) + { + $g->doOBStart(); + } + + function end(&$g, &$tag) + { + $g->doOBEndInContext('slots/'.$this->expression); + } +} + +?> diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/METAL/Use_macro.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/METAL/Use_macro.php new file mode 100644 index 0000000000..17b4e884c7 --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/METAL/Use_macro.php @@ -0,0 +1,58 @@ + +// + +class PHPTAL_Attribute_METAL_Use_Macro extends PHPTAL_Attribute +{ + function activate(&$g, &$tag) + { + $g->doOBStart(); + $err = $tag->generateContent($g); + if (PEAR::isError($err)) { return $err; } + $g->doOBClean(); + + $path = $g->newTemporaryVar(); + + $g->doAffectResult($path, "'". PHPTAL_ES_path_in_string($this->expression,"'") . "'"); + + $temp = $g->newTemporaryVar(); + + // push error + $g->execute('$__old_error = $__ctx__->_errorRaised'); + $g->execute('$__ctx__->_errorRaised = false'); + + $g->doAffectResult($temp, 'new PHPTAL_Macro($__tpl__, '. $path .')'); + $g->doAffectResult($temp, $temp.'->execute($__tpl__)'); + + $g->doIf('PEAR::isError('.$temp.')'); + $g->execute('$__ctx__->_errorRaised = '.$temp ); + $g->endBlock(); + + $g->doPrintVar($temp, true); + + // restore error + $g->doIf('!$__ctx__->_errorRaised'); + $g->execute('$__ctx__->_errorRaised = $__old_error'); + $g->endBlock(); + } +} + +?> diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/PHPTAL/Include.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/PHPTAL/Include.php new file mode 100644 index 0000000000..6a2927b67a --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/PHPTAL/Include.php @@ -0,0 +1,42 @@ + +// + +class PHPTAL_Attribute_PHPTAL_Include extends PHPTAL_Attribute +{ + function activate(&$g, &$tag) + { + $exp = new PHPTAL_Expression($g, $tag, $this->expression); + $temp = $g->newTemporaryVar(); + $exp->setPolicy(_PHPTAL_ES_RECEIVER_IS_TEMP); + $exp->setReceiver($temp); + $err = $exp->generate(); + if (PEAR::isError($err)) { return $err; } + + $tpl = $g->newTemporaryVar(); + $g->doAffectResult($tpl, 'new PHPTAL_Template('.$temp.', $__tpl__->_repository, $__tpl__->_cacheDir)'); + $g->execute($tpl.'->setParent($__tpl__)'); + $g->execute($tpl.'->setContext($__ctx__)'); + $g->doPrintRes($tpl.'->execute()', true); + } +} + +?> diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/PHPTAL/Src_include.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/PHPTAL/Src_include.php new file mode 100644 index 0000000000..8d367edd1d --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/PHPTAL/Src_include.php @@ -0,0 +1,45 @@ + +// + +class PHPTAL_Attribute_PHPTAL_Src_include extends PHPTAL_Attribute +{ + function activate(&$g, &$tag) + { + $temp = $g->newTemporaryVar(); + + $exp = new PHPTAL_Expression($g, $tag, $this->expression); + $exp->setPolicy(_PHPTAL_ES_RECEIVER_IS_TEMP); + $exp->setReceiver($temp); + $err = $exp->generate(); + if (PEAR::isError($err)) { return $err; } + + $g->doAffectResult($temp, '$__tpl__->realpath('.$temp.')'); + $g->doIf('PEAR::isError('.$temp.')'); + $g->execute('$__ctx__->_errorRaised = true'); + $g->doPrintVar($temp); + $g->doElse(); + $g->doPrintRes('join("", file('.$temp.'))', true); + $g->endBlock(); + } +} + +?> diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Attributes.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Attributes.php new file mode 100644 index 0000000000..42420f88d0 --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Attributes.php @@ -0,0 +1,173 @@ + +// + +/** + * tal:attributes attribute handler. + * + * This template attribute defines xhtml entity attributes. + * + * Assuming link variable : + * + * $link->href = "http://www.google.fr"; + * $link->title = "google search engine"; + * $link->text = "google"; + * + * The template code : + * + * sample text + * + * Will produce : + * + * google + * + * As shown above, non overwritten attributes are keep in result xhtml. + * + * @author Laurent Bedubourg + */ +class PHPTAL_Attribute_TAL_Attributes extends PHPTAL_Attribute +{ + var $_overwritten = array(); + + function activate(&$g, &$tag) + { + global $_phptal_xhtml_boolean_attributes; + + $g->doPrintString('<', $tag->name()); + + $atts = $tag->attributes(); + + $exp = new PHPTAL_Expression($g, $tag, $this->expression); + $exp->setPolicy(_PHPTAL_ES_RECEIVER_IS_TEMP); + $err = $exp->prepare(); + if (PEAR::isError($err)) { return $err; } + + if ($exp->countSubs() > 0) { + foreach ($exp->subs() as $sub) { + $err = $this->_attributeExpression($g, $tag, $sub); + if (PEAR::isError($err)) { return $err; } + } + } else { + $err = $this->_attributeExpression($g, $tag, $exp); + if (PEAR::isError($err)) { return $err; } + } + + // echo non overwritten xhtml attributes + + foreach ($atts as $key=>$value) { + $test_key = strtolower($key); + if (!in_array($test_key, $this->_overwritten)) { + // boolean attributes + if ($tag->_parser->_outputMode() == PHPTAL_XHTML + && in_array($test_key, $_phptal_xhtml_boolean_attributes)) { + $g->doPrintString(' '.$key); + } else { + $g->doPrintString(' '.$key .'="'); + $g->doPrintString($value); + $g->doPrintString('"'); + } + } + } + + if ($tag->_isXHTMLEmptyElement()) { + $g->doPrintString(' />'); + return; + } + + // continue tag show + if ($tag->hasContent()) { + $g->doPrintString('>'); + } else { + $g->doPrintString('/>'); + } + + $err = $tag->generateContent($g); + if (PEAR::isError($err)) { return $err; } + + if ($tag->hasContent()) { + $g->doPrintString('name(), '>'); + } + } + + function _printAttribute(&$g, &$tag, &$realName, &$varName, $default=false) + { + global $_phptal_xhtml_boolean_attributes; + // watch boolean attributes on XHTML mode + if ($tag->_parser->_outputMode() == PHPTAL_XHTML + && in_array($realName, $_phptal_xhtml_boolean_attributes)) { + $g->doIf('!PEAR::isError($'.$varName.') && $'.$varName); + $g->doPrintString(' '.$realName); + $g->endBlock(); + } elseif ($default) { + $g->doIf('!PEAR::isError($'.$varName.') && false !== $'.$varName.' && null !== $'.$varName); + $g->doPrintString(' '. $realName . '="'); + $g->doPrintVar($varName); + $g->doPrintString('"'); + $g->endBlock(); + } else { + $g->doPrintString(' '. $realName . '="'); + $g->doPrintVar($varName); + $g->doPrintString('"'); + } + } + + function _attributeExpression(&$g, &$tag, &$sub) + { + $atts = $tag->attributes(); + $default = false; + $name = strtolower($sub->getReceiver()); + + // default in tal:attributes use default tag attributes + // if (preg_match('/\|\s*?\bdefault\b/sm', $sub->_src)) { + if (preg_match('/\bdefault\b/sm', $sub->_src)) { + // ensure the attribute as a default value set in source + // template + $attrs = $tag->attributes(); + if (!array_key_exists($name, $atts)){ + $g->doAffectResult('$__default__', 'false'); + } else { + // store the default value in __default__ variable + $g->doAffectResult('$__default__', + '\''. str_replace('\'', '\\\'', $atts[$name]) . '\'' ); + } + $default = true; + } + + $real = str_replace('__phptales_dd__', ':', $name); + $this->_overwritten[] = $real; + $err = $sub->generate(); + if (PEAR::isError($err)) { return $err; } + + $this->_printAttribute($g, $tag, $real, $name, $default); + } +} + +?> diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Comment.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Comment.php new file mode 100644 index 0000000000..e739e78f4e --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Comment.php @@ -0,0 +1,34 @@ + +// + +class PHPTAL_Attribute_TAL_Comment extends PHPTAL_Attribute +{ + function start(&$g, &$tag) + { + $g->doComment($this->expression); + } + + function end(&$g, &$tag) + {} +} + +?> diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Condition.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Condition.php new file mode 100644 index 0000000000..be02e50cb8 --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Condition.php @@ -0,0 +1,43 @@ + +// + + +class PHPTAL_Attribute_TAL_Condition extends PHPTAL_Attribute +{ + function start(&$g, &$tag) + { + $exp = new PHPTAL_Expression($g, $tag, $this->expression); + $exp->setPolicy(_PHPTAL_ES_RECEIVER_IS_TEMP); + $test_var = $g->newTemporaryVar(); + $exp->setReceiver($test_var); + $err = $exp->generate(); + if (PEAR::isError($err)) { return $err; } + $g->doIf("!PEAR::isError($test_var) && $test_var"); + } + + function end(&$g, &$tag) + { + $g->endBlock(); + } +}; + +?> diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Content.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Content.php new file mode 100644 index 0000000000..3dfa8269c1 --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Content.php @@ -0,0 +1,52 @@ + +// + +/** + * Handle tal:content attributes + * + * @author Laurent Bedubourg + */ +class PHPTAL_Attribute_TAL_Content extends PHPTAL_Attribute +{ + function activate(&$g, &$tag) + { + if (preg_match('/\|\s*?\bdefault\b/sm', $this->expression)) { + $g->doOBStart(); + foreach ($tag->_children as $child) { + $err = $child->generateCode($g); + if (PEAR::isError($err)) { return $err; } + } + $g->doOBEnd('$__default__'); + $default = true; + } + + $g->setSource($tag->name(), $tag->line); + $exp = new PHPTAL_Expression($g, $tag, $this->expression); + $exp->setPolicy(_PHPTAL_ES_RECEIVER_IS_OUTPUT); + $err = $exp->generate(); + if (PEAR::isError($err)) { return $err; } + + if (isset($default)) { $g->execute('unset($__default__)'); } + } +} + +?> diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Define.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Define.php new file mode 100644 index 0000000000..fdc61214cf --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Define.php @@ -0,0 +1,51 @@ + +// + +class PHPTAL_Attribute_TAL_Define extends PHPTAL_Attribute +{ + function activate(&$g, &$tag) + { + if (preg_match('/\|\s*?\bdefault\b/sm', $this->expression)) { + $g->doOBStart(); + $err = $tag->generateContent($g); + if (PEAR::isError($err)) { return $err; } + $g->doOBEnd('$__default__'); + $default = true; + } + + // use node content to set variable + if (preg_match('/^[a-z0-9_]+$/i', $this->expression)) { + $g->doOBStart(); + $err = $tag->generateContent($g); + if (PEAR::isError($err)) { return $err; } + $g->doOBEndInContext($this->expression); + } else { + $exp = new PHPTAL_Expression($g, $tag, $this->expression); + $exp->setPolicy(_PHPTAL_ES_RECEIVER_IS_CONTEXT); + $err = $exp->generate(); + if (PEAR::isError($err)) { return $err; } + } + if (isset($default)) { $g->execute('unset($__default__)'); } + } +} + +?> diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Omit_tag.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Omit_tag.php new file mode 100644 index 0000000000..71a403a0ed --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Omit_tag.php @@ -0,0 +1,31 @@ + +// + +class PHPTAL_Attribute_TAL_Omit_tag extends PHPTAL_Attribute +{ + function start(&$g, &$tag) + { + $tag->disableHeadFoot(); + } +} + +?> diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/On_error.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/On_error.php new file mode 100644 index 0000000000..397388ec2d --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/On_error.php @@ -0,0 +1,46 @@ + +// + +class PHPTAL_Attribute_TAL_On_Error extends PHPTAL_Attribute +{ + function start(&$g, &$tag) + { + $g->doComment("OnError handling"); + $g->execute('$__ctx__->cleanError()'); + $g->doOBStart(); + } + + function end(&$g, &$tag) + { + $exp = new PHPTAL_Expression($g, $tag, $this->expression); + $g->doIf("\$__ctx__->errorRaised()"); + $g->doOBClean(); + $exp->setPolicy(_PHPTAL_ES_RECEIVER_IS_OUTPUT); + $err = $exp->generate(); + if (PEAR::isError($err)) { return $err; } + $g->doElse(); + $g->doOBPrint(); + $g->endBlock(); + } +} + +?> diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Repeat.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Repeat.php new file mode 100644 index 0000000000..f45548c338 --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Repeat.php @@ -0,0 +1,64 @@ + +// + +class PHPTAL_Attribute_TAL_Repeat extends PHPTAL_Attribute +{ + var $in = "__in__"; + var $out = "__out__"; + + function start(&$g, &$tag) + { + $g->setSource($tag->name(), $tag->line); + + $g->doComment('new loop'); + $exp = new PHPTAL_Expression($g, $tag, $this->expression); + $exp->setPolicy(_PHPTAL_ES_RECEIVER_IS_TEMP); + $err = $exp->prepare(); + if (PEAR::isError($err)) { return $err; } + + $this->out = $exp->getReceiver(); + $temp = $g->newTemporaryVar(); + $exp->setReceiver($temp); + $err = $exp->generate(); // now $temp points to the loop data + if (PEAR::isError($err)) { return $err; } + + $loop = $g->newTemporaryVar(); + $this->loop = $loop; + $g->doAffectResult($loop, + '& new PHPTAL_LoopControler($__ctx__, "'. $this->out . '", ' + . $temp .');'); + $g->doIf('PEAR::isError('.$loop.'->_error)'); + $g->doPrintVar($loop.'->_error'); + $g->doElse(); + // $g->execute($loop.'->prepare()'); + $g->doWhile($loop.'->isValid()'); + + } + + function end(&$g, &$tag) + { + $g->execute($this->loop.'->next()'); + $g->endBlock(); + $g->endBlock(); + $g->doComment('end loop'); + } +} diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Replace.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Replace.php new file mode 100644 index 0000000000..3944622e0e --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/PHPTAL/Attribute/TAL/Replace.php @@ -0,0 +1,46 @@ + +// + +class PHPTAL_Attribute_TAL_Replace extends PHPTAL_Attribute +{ + function activate(&$g, &$tag) + { + if (preg_match('/\|\s*?\bdefault\b/sm', $this->expression)) { + $g->doOBStart(); + foreach ($tag->_children as $child) { + $err = $child->generateCode($g); + if (PEAR::isError($err)) { return $err; } + } + $g->doOBEnd('$__default__'); + $default = true; + } + $g->setSource($tag->name(), $tag->line); + $exp = new PHPTAL_Expression($g, $tag, $this->expression); + $exp->setPolicy(_PHPTAL_ES_RECEIVER_IS_OUTPUT); + $err = $exp->generate(); + if (PEAR::isError($err)) { return $err; } + + if (isset($default)) { $g->execute('unset($__default__)'); } + } +}; + +?> diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Cache.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Cache.php new file mode 100644 index 0000000000..6821789574 --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/PHPTAL/Cache.php @@ -0,0 +1,97 @@ + +// + +/** + * Interface to PHPTAL cache system. + * + * Implement this interface and use PHPTAL_Template::setCacheManager() method + * to intercept macro and template execution with your own cache system. + * + * The aim of this system is to fine grain the caching of PHPTAL results + * allowing the php coder to use whatever cache system he prefers with a + * good granularity as he can cache result of specific templates execution, + * and specific macros calls. + * + * @see Documentation.txt + * @author Laurent Bedubourg + */ +class PHPTAL_Cache +{ + /** + * Called each time a template has to be executed. + * + * This method must return the cache value or the template execution + * return. + * + * function template(&$tpl, $path, &$context) + * { + * // return cache if exists + * // else realy process template + * $res = $tpl->_process(); + * // cache the result if needed + * // and return it + * return $res; + * } + * + * @param PHPTAL_Template -- the template that must be cached/executed + * @param string $path -- the template path + * @param PHPTAL_Context $ctx -- the execution context + * + * @return string + */ + function template(&$tpl, $path, &$context) + { + return $tpl->_process(); + } + + + /** + * Called each time a macro needs to be executed. + * + * This method allow cache on macro result. It must return the cache value + * or at least the macro execution result. + * + * function macro(&$macro, $file, $name, &$context) + * { + * // return cache if exists + * // else really process macro + * $res = $macro->_process(); + * // cache the result if needed + * // and return it + * return $res + * } + * + * + * @param PHPTAL_Macro -- the macro to executed + * @param string $file -- the macro source file + * @param string $name -- the macro name + * @param PHPTAL_Context $context -- the current execution context + * + * @return string + */ + function macro(&$macro, $file, $name, &$context) + { + return $macro->_process(); + } +} + +?> diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Context.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Context.php new file mode 100644 index 0000000000..b41201fc9e --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/PHPTAL/Context.php @@ -0,0 +1,349 @@ + +// + + +// What are Context and Resolvers +// ============================== +// +// In phptal, variables and methods are referenced by path without distinction, +// also, arrays and hashtable elements are accessed using a path like +// myarray/10 to reach the 11's element of myarray or myhash/mykey to +// reach the value of mykey in myhash. +// +// This allow things like 'myobject/mymethod/10/othermethod' which is usefull +// in templates. +// +// The Context is an array containing all template variables. +// When asked to reach a path, it look for the variable type of the first path +// element and generate a resolver matching the variable type. +// Then this resolver is asked to resolve the rest of the path, etc... up to +// the final path element. +// +// Resolver knows how to handle a given path relatively to the object they +// handle. +// +// For instance, an array resolver can handle access to its array elements +// given a key (string) or the element id (int). +// +// The array resolver also bring an array method : count which return the +// number of elements in the array. +// +// Note +// ---- +// +// If a name conflict occurs between an object's variable and one of its +// methods, the variable is return in stead of the method. +// + +/** + * Template context handler. + * + * This object produce a translation between variables passed to the template + * and regular template pathes. + * + * @author Laurent Bedubourg + */ +class PHPTAL_Context +{ + var $_array = array(); + var $_errorRaised = false; + + /** + * Context constructor. + * + * @param hashtable $hash (opt) + */ + function PHPTAL_Context($hash=array()) + { + $this->_array = $hash; + } + + /** + * Set a value by reference. + * + * @param string $path -- Variable path + * @param mixed $value -- Reference to variable. + */ + function setRef($path, &$value) + { + $this->remove($path); + $this->_array[$path] =& $value; + } + + /** + * Set a context variable. + * + * @param string $path -- Variable path + * @param mixed $value -- Value + */ + function set($path, $value) + { + $this->remove($path); + $this->_array[$path] = $value; + } + + /** + * Remove a context variable. + * + * @param string $path -- Context path + */ + function remove($path) + { + if (array_key_exists($path, $this->_array)) { + unset($this->_array[$path]); + } + } + + /** + * Test if the context can resolve specified path. + * + * @param string $path + * Path to a context resource. + * + * @return boolean + */ + function has($path) + { + if (array_key_exists($path, $this->_array)) { + return true; + } + $resp =& PHPTAL_ArrayResolver::get($this->_array, $path); + if (PEAR::isError($resp)) { + return false; + } else if ($resp === null) { + return false; + } + return true; + } + + /** + * Return the context associative object. + */ + function &getHash() + { + return $this->_array; + } + + /** + * Retrieve specified context resource. + * + * @param string $path + * Path to a context resource. + * + * @return mixed + * @throws NameError + */ + function &get($path) + { + if (array_key_exists($path, $this->_array)) { + return $this->_array[$path]; + } + $resp =& PHPTAL_ArrayResolver::get($this->_array, $path); + if (PEAR::isError($resp)) { + $this->_errorRaised = $resp; + } else if ($resp === null) { + $this->_errorRaised = true; + } + return $resp; + } + + /** + * Retrieve specified context resouce as a string object + * + * @param string $path + * Path to a context resource. + * + * @return string + */ + function &getToString($path) + { + $o = $this->get($path); + if (is_object($o) && method_exists($o, "toString")) { + return $o->toString(); + } + if (is_object($o) || is_array($o)) { + ob_start(); + print_r($o); // var_dump($o); + $res = ob_get_contents(); + ob_end_clean(); + return $res; + } + return $o; + } + + /** + * Tells if an error was raised by this context accessing an unknown path. + * + * @return boolean + */ + function errorRaised() + { + $r = $this->_errorRaised; + $this->_errorRaised = false; + return $r; + } + + /** + * Clean error handler. + */ + function cleanError() + { + $this->_errorRaised = false; + } +} + +/** + * Object resolver. + * + * Resolver pathes relatives to object. + * + * @access private + * @author Laurent Bedubourg + */ +class PHPTAL_ObjectResolver +{ + function &get(&$obj, $subpath) + { + list($first, $next) = PHPTAL_path_explode($subpath); + + if (method_exists($obj, $first)) { + // reference to a variable of the handled object + $value =& $obj->$first(); + } elseif (array_key_exists($first, $obj)) { + // reference to an object variable + $value =& $obj->$first; + } elseif (is_a($obj, 'OHash') && $obj->containsKey($first)) { + return $obj->get($first); + } elseif (is_a($obj, 'OArray') && preg_match('/^[0-9]+$/', $first)) { + return $obj->get((int)$first); + } else { + $err = new NameError($subpath . " not found"); + return $err; + } + // more to resolve in value + if ($next) { + return PHPTAL_resolve($next, $value, $obj); + } + return $value; + } +} + + +/** + * Array resolver. + * + * Resolve pathes relative to arrays and hashtables. + * + * @author Laurent Bedubourg + */ +class PHPTAL_ArrayResolver +{ + function &get(&$array, $subpath) + { + list($first, $next) = PHPTAL_path_explode($subpath); + + if ($first == "length" && !$next && !array_key_exists("length", $array)) { + return count($array); + } + + if ($next === false) { + if ($first == 'count') { return count($array); } + if ($first == 'keys') { return array_keys($array); } + if ($first == 'values'){ return array_values($array); } + if (!array_key_exists($first, $array)) { + $err = new NameError("(ArrayResolver) Context does not contains key '$first'"); + return $err; + } + return $array[$first]; + } + + if (!array_key_exists($first, $array)) { + $err = new NameError("(ArrayResolver) Context does not contains key '$first'"); + return $err; + } + $temp =& $array[$first]; + if ($temp) { + return PHPTAL_resolve($next, $temp, $array); + } + } +} + + +/** + * String resolver. + * + * Add method to string type. + */ +class PHPTAL_StringResolver +{ + function get(&$str, $subpath) + { + list($first, $next) = PHPTAL_path_explode($subpath); + if ($next) { + $err = new TypeError("string methods have no sub path (string.$subpath)"); + return $err; + } + if ($first == "len") { + return strlen($str); + } + $err = new NameError("string type has no method named '$first'"); + return $err; + } +}; + +/** + * Retrieve a resolver given a value and a parent. + */ +function &PHPTAL_resolve($path, &$value, &$parent) +{ + if (is_array($value)) return PHPTAL_ArrayResolver::get($value, $path); + if (is_object($value)) return PHPTAL_ObjectResolver::get($value, $path); + if (is_string($value)) return PHPTAL_StringResolver::get($value, $path); + $err = new TypeError("unable to find adequate resolver for '".gettype($value)."' remaining path is '$path'"); + return $err; +} + +/** + * Shift the first elemetn of a phptal path. + * + * Returns an array containing the first element of the path and the rest of + * the path. + */ +function PHPTAL_path_explode($path) +{ + if (preg_match('|^(.*?)\/(.*?)$|', $path, $match)) { + array_shift($match); + return $match; + } else { + return array($path, false); + } + + $pos = strpos($path,"."); + if ($pos !== false) { + $first = substr($path, 0, $pos); + $next = substr($path, $pos+1); + return array($first, $next); + } + return array($path, false); +} + +?> diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Expression.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Expression.php new file mode 100644 index 0000000000..5e4a63d25c --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/PHPTAL/Expression.php @@ -0,0 +1,369 @@ + +// + +define('_PHPTAL_ES_RECEIVER_IS_CONTEXT', 1); +define('_PHPTAL_ES_RECEIVER_IS_NONE', 2); +define('_PHPTAL_ES_RECEIVER_IS_TEMP', 4); +define('_PHPTAL_ES_RECEIVER_IS_OUTPUT', 8); + + +// Important note: +// +// The PHPTALES system works quite well but it's not yet fully optimized, it +// should be refactored at some points of my TODO list. +// + + +class PHPTAL_Expression +{ + var $_tag; + var $_gen; + var $_src; + var $_subs = array(); + var $_policy; + var $_receiver = false; + var $_prepared = false; + var $_structure = false; + + function PHPTAL_Expression(&$generator, &$tag, $str) + { + $this->_tag =& $tag; + $this->_gen =& $generator; + $this->_src = $str; + } + + function setPolicy($policy) + { + $this->_policy = $policy; + } + + /** + * Prepare the expression. + * + * This method explode the expression into sub expression and prepare each + * expression for parsing. + * + * @throws PHPTAL_ExpressionError + * If receiver policy fail. + */ + function prepare() + { + if ($this->_prepared) { return; } + $test = $this->_src; + + // some sub expression detected + while (preg_match('/^(.*?)(?_gen, $this->_tag, $exp); + $x->setPolicy($this->_policy); + $x->setReceiver($this->getReceiver()); + $err = $x->prepare(); + if (PEAR::isError($err)) { + return $err; + } + $this->_subs[] = $x; + + $test = substr($test, strlen($src)); + } + // if subs, insert last one + if ($this->countSubs() > 0 && strlen(trim($test)) > 0) { + $exp = $test; + $x = new PHPTAL_Expression($this->_gen, $this->_tag, $exp); + $x->setPolicy($this->_policy); + $x->setReceiver($this->getReceiver()); + $err = $x->prepare(); + if (PEAR::isError($err)) { + return $err; + } + $this->_subs[] = $x; + } else { + // otherwise, just remove expression delimiters from source + // and apply the receiver policy + $exp = $test; + $exp = str_replace(';;', ';', $exp); + $this->_src = $exp; + if (strlen($exp) == 0) return; + + $err = $this->_extractReceiver(); + if (PEAR::isError($err)){ + return $err; + } + + if (!$this->_receiver + && ($this->_policy & _PHPTAL_ES_RECEIVER_IS_CONTEXT + || $this->_policy & _PHPTAL_ES_RECEIVER_IS_TEMP)) { + $str = sprintf('Receiver required in expression \'%s\' from %s:%d', + $this->_src, + $this->_tag->_parser->_file, + $this->_tag->line); + $err = new PHPTAL_ExpressionError($str); + return PEAR::raiseError($err); + } + + if ($this->_policy & _PHPTAL_ES_RECEIVER_IS_NONE && $this->_receiver) { + $str = sprintf('Unexpected receiver \'%s\' in expression \'%s\' from %s:%d', + $this->_receiver, + $this->_src, + $this->_tag->_parser->_file, + $this->_tag->line); + $err = new PHPTAL_ExpressionError($str); + return PEAR::raiseError($err); + } + } + + $this->_prepared = true; + } + + function _extractReceiver() + { + global $_phptal_es_namespaces; + + $this->_src = preg_replace('/^\s+/sm', '', $this->_src); + if (preg_match('/^([a-z:A-Z_0-9]+)\s+([^\|].*?)$/sm', $this->_src, $m)) { + // the receiver looks like xxxx:aaaa + // + // we must ensure that it's not a known phptales namespaces + if (preg_match('/^([a-zA-Z_0-9]+):/', $m[1], $sub)) { + $ns = $sub[1]; + // known namespace, just break + if (function_exists('phptal_es_'.$ns)) { + // in_array(strtolower($ns), $_phptal_es_namespaces)) { + return; + } + } + + if ($this->_receiver) { + $str = sprintf('Receiver already set to \'%s\' in \'%s\'', + $this->_receiver, + $this->_src); + $err = new PHPTAL_ExpressionError($str); + return PEAR::raiseError($err); + } + + $this->_receiver = $m[1]; + // + // that the way to replace : in setters (usually this this should + // only be used under tal:attributes tag !!!! + // + $this->_receiver = str_replace(':', '__phptales_dd__', $this->_receiver); + $this->_src = $m[2]; + if ($this->_receiver == "structure") { + $this->_structure = true; + $this->_receiver = false; + $this->_extractReceiver(); + } + } + } + + /** + * Retrieve the number of sub expressions. + */ + function countSubs() + { + return count($this->_subs); + } + + function &subs() + { + return $this->_subs; + } + + /** + * Returns true if a receiver is set for this expression. + */ + function hasReceiver() + { + return $this->_receiver != false; + } + + /** + * Retrieve receiver's name. + */ + function getReceiver() + { + return $this->_receiver; + } + + /** + * Set expression receiver. + */ + function setReceiver($name) + { + $this->_receiver = $name; + } + + /** + * Generate php code for this expression. + */ + function generate() + { + $err = $this->prepare(); + if (PEAR::isError($err)) { + return $err; + } + + if ($this->countSubs() > 0) { + foreach ($this->_subs as $sub) { + $err = $sub->generate(); + if (PEAR::isError($err)) { + return $err; + } + } + } else { + $exp = $this->_src; + if (strlen($exp) == 0) return; + + // expression may be composed of alternatives | list of expression + // they are evaluated with a specific policy : _PHPTAL_ES_SEQUENCE + // + // 'string:' break the sequence as no alternative exists after a + // string which is always true. + if (preg_match('/\s*?\|\s*?string:/sm', $exp, $m)) { + $search = $m[0]; + $str = strpos($exp, $search); + // $str = strpos($exp, ' | string:'); + // if ($str !== false) { + $seq = preg_split('/(\s*?\|\s*?)/sm', substr($exp, 0, $str)); + $seq[]= substr($exp, $str + 2); + } else { + $seq = preg_split('/(\s*?\|\s*?)/sm', $exp); + } + + // not a sequence + if (count($seq) == 1) { + $code = PHPTAL_Expression::_GetCode($this, $exp); + if (PEAR::isError($code)) { return $code; } + + $temp = $this->_gen->newTemporaryVar(); + $this->_gen->doAffectResult($temp, $code); + return $this->_useResult($temp); + } else { + return $this->_evaluateSequence($seq); + } + } + } + + + function _evaluateSequence($seq) + { + $temp = $this->_gen->newTemporaryVar(); + $this->_gen->doIf('!$__ctx__->_errorRaised'); + $this->_gen->doDo(); + foreach ($seq as $s) { + // skip empty parts + if (strlen(trim($s)) > 0) { + $code = PHPTAL_Expression::_GetCode($this, $s); + if (PEAR::isError($code)) { return $code; } + + $this->_gen->doUnset($temp); + $this->_gen->doAffectResult($temp, $code); + $this->_gen->doIf('!PEAR::isError(' . $temp . ') && ' . + // $temp .' != false && '. + $temp . ' !== null'); + $this->_gen->execute('$__ctx__->_errorRaised = false'); + $this->_gen->execute('break'); + $this->_gen->endBlock(); + } + } + $this->_gen->doEndDoWhile('0'); + // test errorRaised + $this->_gen->doElse(); + + // $this->_gen->doAffectResult($temp, '""'); // $__ctx__->_errorRaised'); + $this->_gen->doAffectResult($temp, '$__ctx__->_errorRaised'); + $this->_gen->execute('$__ctx__->_errorRaised = false'); + $this->_gen->endBlock(); + // ---------------- + + $err = $this->_useResult($temp); + + // $this->_gen->endBlock(); + return $err; + } + + function _useResult($temp) + { + if ($this->_policy & _PHPTAL_ES_RECEIVER_IS_TEMP) { + $this->_gen->doReference($this->_receiver, $temp); + } else if ($this->_policy & _PHPTAL_ES_RECEIVER_IS_OUTPUT) { + $this->_gen->doPrintVar($temp, $this->_structure); + } else if ($this->_policy & _PHPTAL_ES_RECEIVER_IS_CONTEXT) { + $this->_gen->doContextSet($this->_receiver, $temp); + } else { + $err = new PHPTAL_ExpressionError("Expression '$this->_src' Don't know what to do with result."); + return PEAR::raiseError($err); + } + } + + /** + * Retrieve a function namespace for given string and the associated + * expression. + * + * Examples: + * + * The function namespace of 'php:XXXX' is 'php' + * The function namespace of 'XXXX' is 'path' + * The function namespace of 'foo:bar::baz' is 'foo' + * + * @param string $str + * Expression string without receiver + * + * @return array + * An array composed as follow : array('ns', 'exp'), + * Where 'ns' is the function namespace and 'exp', is the + * source string without the 'ns:' part. + */ + function _FindFunctionNamespace($str) + { + $str = preg_replace('/^\s/sm', '', $str); + if (preg_match('/^([a-z0-9\-]+):(?!>:)(.*?)$/ism', $str, $m)) { + list($ns, $path) = array_slice($m, 1); + $ns = str_replace('-', '_', $ns); + return array($ns, $path); + } + return array('path', $str); + } + + /** + * Get the code for a ns:args string. + */ + function _GetCode(&$exp, $str) + { + list($ns, $args) = PHPTAL_Expression::_FindFunctionNamespace($str); + $func = "PHPTAL_ES_$ns"; + if (!function_exists($func)) { + $err = new PHPTAL_ExpressionError("Unknown function $func in '$str'"); + return PEAR::raiseError($err); + } + return $func($exp, $args); + } +} + +/** + * Thrown on expression parsing error. + */ +class PHPTAL_ExpressionError extends PEAR_Error +{ +} + +?> diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/ExpressionFunctions.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/ExpressionFunctions.php new file mode 100644 index 0000000000..238a15dd9d --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/PHPTAL/ExpressionFunctions.php @@ -0,0 +1,384 @@ + +// + +/** + * @var $_phptal_es_namespaces + * @type array + * + * This array contains phptales namespaces, it means php:, string:, exists:, + * not: and path: at this time. + */ +global $_phptal_es_namespaces; +$_phptal_es_namespaces = array('not', 'php', 'string', 'exists', 'path', 'not-exists'); + +/** + * @var $_phptal_es_keywords + * @type array + * + * List of reserved phptales keywords. + */ +global $_phptal_es_keywords; +$_phptal_es_keywords = array('nothing', 'default', 'structure'); + +global $_phptal_es_php_types; +$_phptal_es_php_types = array('true', 'false', 'null'); + +/** + * string: expression type + */ +function PHPTAL_ES_string(&$exp, $value) +{ + $value = PHPTAL_ES_path_in_string($value); + // $value = str_replace('$$', '\$\$', $value); + $value = '"' . $value . '"'; + $value = preg_replace('/^\" ?\"\. /', '', $value); + $value = preg_replace('/\.\"\"$/', '', $value); + return $value; +} + +/** + * not: expression type + */ +function PHPTAL_ES_not(&$exp, $value) +{ + return "! " . PHPTAL_ES_path($exp, $value); +} + +/** + * not-exists: expression type + */ +function PHPTAL_ES_not_exists(&$exp, $value) +{ + return "! " . PHPTAL_ES_exists($exp, $value); +} + +/** + * path: expression type + * + * @todo default -- existing text inside tag + * options -- ?? keyword arguments passed to template ?? + * repeat -- repeat variables + * attrs -- initial values of tag attributes + * CONTEXTS -- list of standard names (above list) in case one of these + * names was hidden by a local variable. + */ +function PHPTAL_ES_path(&$exp, $value) +{ + $value = trim($value); + // special case : 'string' authorized + if ($value[0] == "'") { return PHPTAL_ES_path_in_string($value,"'"); } + // number case + if (preg_match('/^[0-9\.]*$/', $value)) { return $value; } + // php constants are accessed though @ keyword + if (preg_match('/^@[_a-z][0-9a-z_]*$/i', $value)) { return substr($value, 1); } + if ($value == "nothing") { return 'null'; } + if ($value == "default") { return '$__default__'; } + $value = PHPTAL_ES_path_in_string($value); + return '$__ctx__->get("'. $value .'")'; +} + + +function PHPTAL_ES_path_toString(&$exp, $value) +{ + $value = trim($value); + if ($value == "nothing") { return 'null'; } + if ($value == "default") { return '$__default__'; } + if (preg_match('/^@[_a-z][0-9a-z_]*$/i', $value)) { return substr($value, 1); } + return '$__ctx__->getToString("'. $value .'")'; +} + + +/** + * exists: expression type + */ +function PHPTAL_ES_exists(&$exp, $value) +{ + return '$__ctx__->has("'. trim($value). '")'; +} + +/** + * php: expression type + */ +function PHPTAL_ES_php(&$exp, $str) +{ + $parser = new PHPTAL_ES_PHP_Parser($exp, $str); + return $parser->evaluate(); +} + + +// +// utility functions (internal) +// + +function PHPTAL_ES_path_in_string($arg, $c='"') +{ + list($match,$repl) = _PHPTAL_context_accessed($arg); + for ($i=0; $i_exp =& $expression; + $this->_gen =& $expression->_gen; + $this->_str = $str; + } + + function evaluate() + { + $value = $this->_str; + $strings = array(); + + // extract strings and replace context calls + if (preg_match_all('/(\'.*?(?_php_test_modifiers($value); + $value = $this->_php_vars($value); + + // restore strings + $i = 0; + foreach ($strings as $str) { + $value = str_replace('#_STRING_'. $i . '_#', $str, $value); + $i++; + } + + $i = 0; + foreach ($contexts as $c) { + $value = str_replace('#_CONTEXT_' . $i . '_#', PHPTAL_ES_path($this->_exp, $c), $value); + $i++; + } + + // experimental, compile php: content + + require_once "Types/Code.php"; + + $code = new Code(); + $code->setCode($value .";"); + $err = $code->compile(); + if (PEAR::isError($err)) { + return $this->_raiseCompileError($value, $err); + } + + return $value; + } + + function _php_test_modifiers($exp) + { + $exp = preg_replace('/\bnot\b/i', ' !', $exp); + $exp = preg_replace('/\bne\b/i', ' != ', $exp); + $exp = preg_replace('/\band\b/i', ' && ', $exp); + $exp = preg_replace('/\bor\b/i', ' || ', $exp); + $exp = preg_replace('/\blt\b/i', ' < ', $exp); + $exp = preg_replace('/\bgt\b/i', ' > ', $exp); + $exp = preg_replace('/\bge\b/i', ' >= ', $exp); + $exp = preg_replace('/\ble\b/i', ' <= ', $exp); + $exp = preg_replace('/\beq\b/i', ' == ', $exp); + return $exp; + } + + function _php_vars($arg) + { + $arg = preg_replace('/\s*\/\s*/',' / ', $arg); + $arg = preg_replace("/\s*\(\s*/","(", $arg ); + $arg = preg_replace('/\s*\)\s*/',') ', $arg ); + $arg = preg_replace('/\s*\[\s*/','[', $arg ); + $arg = preg_replace('/\s*\]\s*/',']', $arg ); + $arg = preg_replace('/\s*,\s*/',' , ', $arg ); + + $result = ""; + $path = false; + $last_path = false; + $last_was_array = false; + + $i = 0; + while ($i < strlen($arg)) { + $c = $arg[$i]; + if (preg_match('/[a-z_]/i', $c)) { + $path .= $c; + } else if (preg_match('/[0-9]/', $c) && $path) { + $path .= $c; + } else if (preg_match('/[\/\.]/', $c) && $path) { + $last_path = $path; + $path .= $c; + } else if (preg_match('/[\/\.]/', $c) && $this->_last_was_array) { + $result .= '->'; + } else if ($c == '(') { + if ($last_path) { + $result .= $this->pathRequest($last_path); + $result .= '->'; + $path = substr($path, strlen($last_path) +1); + $last_path = false; + } + $result .= $path . '('; + $this->_last_was_array = false; + $path = false; + } else if ($c == '#') { + if ($path) { + $result .= $this->pathRequest($path); + $path = false; + $last_path = false; + } + $next = strpos($arg, '#', $i+1); + $result .= substr($arg, $i, $next - $i +1); + $i = $next; + } else if ($c == ':') { + if ($arg[$i+1] != ':') { // error + } + $i++; + $result .= $path; + $result .= '::'; + $path = false; + $last_path = false; + + } else if ($c == '@') { + // access to defined variable, append to result + // up to non word character + $i++; // skip @ character + do { + $c = $arg[$i]; + $result .= $c; + $i++; + } while ($i < strlen($arg) && preg_match('/[a-z_0-9]/i', $arg[$i])); + $i--; // reset last character + + } else { + if ($path) { + $result .= $this->pathRequest($path); + $path = false; + } + $result .= $c; + if ($c == ']') { + $last_path = false; + $path = false; + $this->_last_was_array = true; + } else { + $this->_last_was_array = false; + } + } + $i++; + } + + // don't forget the last bit + if (isset($path) && $path) { + $result .= $this->pathRequest($path); + } + + return $result; + } + + function pathRequest($path) + { + global $_phptal_es_php_types; + + if (!preg_match('/[a-z]/i', $path)){ + return $path; + } + if ($this->_last_was_array) { + return str_replace('.', '->', $path); + } + if (in_array($path, $_phptal_es_php_types)) { + return $path; + } + + $concatenate = false; + $path = str_replace('.','/', $path); + if (substr($path,-1) == '/') { + $path = substr($path, 0, -1); + $concatenate = true; + } + + if (array_key_exists($path, $this->_aliases)) { + $res = $this->_aliases[$path]; + } else { + $res = $this->_gen->newTemporaryVar(); + $this->_aliases[$path] = $res; + $this->_gen->doContextGet($res, $path); + } + + if ($concatenate) { + $res .= ' .'; + } + return $res; + } + + function _raiseCompileError($code, $err) + { + $str = sprintf("Expression 'php:' compilation error in %s:%d".endl, + $this->_exp->_tag->_parser->_file, + $this->_exp->_tag->line); + return PEAR::raiseError($str); + } +} + + +?> diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Filter.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Filter.php new file mode 100644 index 0000000000..00c983d89c --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/PHPTAL/Filter.php @@ -0,0 +1,62 @@ +)/sm', '', $data); + * } + * } + * + * $tpl = PHPTAL('mytemplate.html'); + * $tpl->addInputFilter( new MyFilter() ); + * echo $tpl->execute(); + * + * ?> + * + * @author Laurent Bedubourg + */ +class PHPTAL_Filter +{ + /** + * Filter some template source string. + * + * @param PHPTAL_Template $tpl + * The template which invoked this filter. + * + * @param string $data + * Data to filter. + * + * @param int $mode + * PHPTAL_PRE_FILTER | PHPTAL_POST_FILTER depending if this filter + * is registered as a pre-filter or as a post-filter. + * + */ + function filter(&$tpl, $data, $mode) + { + return $data; + } +} + +?> diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Generator.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Generator.php new file mode 100644 index 0000000000..e0c90e9e77 --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/PHPTAL/Generator.php @@ -0,0 +1,362 @@ + +// + +class PHPTAL_Generator +{ + var $_temp_id = 0; + var $_str_buffer = ""; + var $_tab = ""; + var $_tab_save = ""; + var $_code = ""; + var $_closed = false; + var $_fname; + var $_funcName; + + var $_macros = array(); + var $_stacks = array(); + var $_current_macro = false; + + var $_gettext_required = false; + + var $_headers = false; + + function PHPTAL_Generator($fname, $func_name) + { + $this->_fname = $fname; + $this->_funcName = $func_name; + $this->appendln('doComment(str_pad("", 78, "-")); + $this->doComment("This code was generate by PHPTAL based on the template source file :"); + $this->doComment("$fname"); + $this->doComment(str_pad("", 78, "-")); + $this->appendln(); + $this->appendln('function ', $func_name, '(&$__tpl__)'); + $this->appendln('{'); + $this->tabInc(); + $this->appendln('$__ctx__ =& $__tpl__->getContext();'); + $this->appendln('$__out__ = new PHPTAL_OutputControl($__ctx__, $__tpl__->getEncoding());'); + $this->appendln('$__ctx__->set("repeat", array());'); + } + + function setHeaders($h) + { + $this->_headers = $h; + if ($this->_headers) { + $this->doHeadersPrint(); + } + } + + function requireGettext() + { + $this->_gettext_required = true; + } + + function getCode() + { + if (!$this->_closed) { + $this->_flushOutput(); + $this->appendln('return $__out__->toString();'); + $this->endBlock(); + + foreach ($this->_macros as $name=>$code) { + $this->_code .= $code; + } + if ($this->_gettext_required) { + $this->_code = preg_replace('/^<\?php/sm', + '_code, + 1); + } + $this->append('?>'); + $this->_closed = true; + } + return $this->_code; + } + + function execute($code) + { + $this->_flushOutput(); + $this->appendln(trim($code), ";"); + } + + function doComment($str) + { + $this->_flushOutput(); + $this->appendln('// ',$str); + } + + function setSource($tagName, $line) + { + $this->doComment('TAG ' . $tagName . ' AT LINE ' . $line); + $this->appendln('$_src_tag = "'. $tagName. '"; ', '$_src_line = '. $line. ';'); + } + + // loop + function doDo() + { + $this->_flushOutput(); + $this->appendln("do {"); + $this->tabInc(); + } + + function doEndDoWhile($condition) + { + $this->tabDec(); + $this->appendln("} while($condition);"); + } + + function doWhile($condition) + { + $this->_flushOutput(); + $this->appendln("while ($condition) {"); + $this->tabInc(); + } + + // conditionals + function doIf($condition) + { + $this->_flushOutput(); + $this->appendln("if ($condition) {"); + $this->tabInc(); + } + + function doElseIf($condition) + { + $this->_str_buffer = ""; + $this->endBlock(); + $this->appendln("else if ($condition) {"); + $this->tabInc(); + } + + function doElse() + { + $this->endBlock(); + $this->appendln("else {"); + $this->tabInc(); + } + + // + function doMacroDeclare($name) + { + $this->_flushOutput(); + $this->_stacks[] = $this->_code; + $this->_code = ""; + $this->_current_macro = $name; + $this->_tab_save = $this->_tab; + $this->_tab = ""; + $this->appendln('function ', $this->_funcName,'_',$name, '(&$__tpl__)'); + $this->appendln('{'); + $this->tabInc(); + $this->appendln('$__ctx__ =& $__tpl__->getContext();'); + $this->appendln('$__out__ = new PHPTAL_OutputControl($__ctx__, $__tpl__->getEncoding());'); + if ($this->_headers) { + $this->doHeadersPrint(); + } + } + + function doHeadersPrint() + { + $this->_flushOutput(); + $this->doIf('! $__tpl__->_headers'); + $str = str_replace("'", "\\'", $this->_headers); + $str = "'" . $str . "'"; + $str = PHPTAL_ES_path_in_string($str, "'"); + $this->appendln('$__tpl__->_headers = ' . $str .';'); + $this->endBlock(); + } + + function doMacroEnd() + { + $this->_flushOutput(); + $this->appendln('return $__out__->toString();'); + $this->endBlock(); + $this->_macros[$this->_current_macro] = $this->_code; + $this->_code = array_pop($this->_stacks); + $this->_current_macro = false; + $this->_tab = $this->_tab_save; + } + + function doAffectResult($dest, $code) + { + if ($dest[0] != '$') { $dest = '$'.$dest; } + // test & + $this->appendln("$dest = $code;"); + } + + // + function doPrintString() + { + $args = func_get_args(); + $this->_str_buffer .= join("", $args); + // $this->appendln('$__out__->write(', $str, ');'); + } + + function doPrintVar($var, $structure=false) + { + $this->_flushOutput(); + if ($var[0] != '$') { + $var = '$' . $var; + } + if ($structure) { + $this->appendln('$__out__->writeStructure(', $var, ');'); + } else { + $this->appendln('$__out__->write(', $var, ');'); + } + } + + function doPrintRes($code, $structure=false) + { + $this->_flushOutput(); + if ($structure) { + $this->appendln('$__out__->writeStructure(', $code, ');'); + } else { + $this->appendln('$__out__->write(', $code, ');'); + } + } + + function doPrintContext($path, $structure=false) + { + $code = sprintf('$__ctx__->get(\'%s\')', $path); + $this->doPrintRes($code, $structure); + } + + // output buffering control + function doOBStart() + { + $this->_flushOutput(); + $this->appendln('$__out__->pushBuffer();'); + } + + function doOBEnd($dest) + { + $this->_flushOutput(); + // test & + $this->appendln($dest, ' =& $__out__->popBuffer();'); + } + + function doOBClean() + { + $this->_flushOutput(); + $this->appendln('$__out__->popBuffer();'); + } + + function doOBPrint() + { + $this->_flushOutput(); + $this->appendln('$__out__->writeStructure($__out__->popBuffer());'); + } + + function doOBEndInContext($dest) + { + $this->doContextSet($dest, '$__out__->popBuffer()'); + } + + // + function doReference($dest, $source) + { + $this->_flushOutput(); + if ($dest[0] != '$') { $dest = '$'.$dest; } + if ($source[0] != '$') { $source = '$'.$source; } + // test & + $this->appendln("$dest =& $source;"); + } + + function doUnset($var) + { + $this->appendln("unset($var);"); + } + + // create a new temporary variable (non context) and return its name + function newTemporaryVar() + { + return '$temp_' . $this->_temp_id++; + } + + function releaseTemporaryVar($name) + { + $this->doUnset($name); + } + + // context methods + + function doContextSet($out, $code) + { + $this->_flushOutput(); + if ($out[0] != '$') + { $out = '"'.$out.'"'; } + // test & (Ref) + $this->appendln("\$__ctx__->setRef($out, $code);"); + } + + function doContextGet($out, $path) + { + $this->_flushOutput(); + if ($out[0] != '$') + { $out = '$' . $out; } + // test & + $this->appendln("$out =& \$__ctx__->get(\"$path\");"); + } + + function endBlock() + { + $this->tabDec(); + $this->appendln('}'); + } + + function tabInc() + { + $this->_flushOutput(); + $this->_tab .= " "; + } + + function tabDec() + { + $this->_flushOutput(); + $this->_tab = substr($this->_tab, 4); + } + + function appendln() + { + $args = func_get_args(); + $str = join("", $args); + $this->_code .= $this->_tab . $str . "\n"; + } + + function append() + { + $args = func_get_args(); + $str = join("", $args); + $this->_code .= $this->_tab . $str; + } + + function _flushOutput() + { + if ($this->_str_buffer == "") return; + $this->_str_buffer = str_replace("'", "\\'", $this->_str_buffer); + $this->_str_buffer = "'" . $this->_str_buffer . "'"; + $this->_str_buffer = PHPTAL_ES_path_in_string($this->_str_buffer, "'"); + $this->appendln('$__out__->writeStructure(', $this->_str_buffer, ');'); + $this->_str_buffer = ""; + } +} + +?> diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/I18N.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/I18N.php new file mode 100644 index 0000000000..cf03650272 --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/PHPTAL/I18N.php @@ -0,0 +1,16 @@ + diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/LoopControler.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/LoopControler.php new file mode 100644 index 0000000000..fdb8d7a96d --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/PHPTAL/LoopControler.php @@ -0,0 +1,364 @@ + +// + +require_once "Types/OArray.php"; +require_once "Types/OHash.php"; +require_once "Types/Iterator.php"; + +/** + * Template loop execution controler. + * + * This object is instantiated by the template on each loop. + * + * LoopControlers accept different types of loop target. + * + * - array + * - objects having an getNewIterator() method returning an Iterator object. + * - Iterator objects which produce isValid(), next(), key() and index() + * methods. + * please note that key() return index() for non associative data. + * + * Other types are rejected by the loop controler on runtime producing + * a TypeError exception. + * + * The loop controler install its iterator under the path "repeat/item" + * where "item" is the name of the output var (defined in the template). + * + * Thus, the template can access differents methods of the iterator: + * repeat/someitem/key + * repeat/someitem/index + * repeat/someitem/next + * repeat/someitem/last + * + * If not all of these methods are implemented in iterators, ask + * iterator maintainers. + * + * @author Laurent Bedubourg + * + */ +class PHPTAL_LoopControler +{ + var $_context; + var $_data; + var $_data_name; + var $_iterator; + var $_error; + + /** + * Controler constructor. + * + * @param PHPTAL_Context $context + * The template context. + * @param string $data_name + * The item data name. + * @param mixed $data + * Loop resource. + */ + function PHPTAL_LoopControler(&$context, $data_name, $data) + { + $this->_context =& $context; + $this->_data =& $data; + $this->_data_name = $data_name; + + // ensure that data is not an error + if (PEAR::isError($data)) { + $this->_error =& $data; + return $data; + } + + // accepted objects + // + // - iteratable implementing getNewIterator() method + // - iterator implementing next(), isValid() and index() methods + // - db_result produced by PEAR::DB package + // + if (is_object($data)) { + if (method_exists($data, "getNewIterator")) { + + $this->_iterator =& $data->getNewIterator(); + + } elseif (is_a("iterator", $data) + || (method_exists($data, 'next') + && method_exists($data, 'isValid') + && method_exists($data, 'index'))) { + + $this->_iterator =& $data; + + } elseif (get_class($data) == 'db_result') { + + $this->_iterator = new PHPTAL_DBResultIterator($data); + + } else { + + $err = new TypeError("PHPTAL loop controler received a non Iterable object (" + . get_class($data) . ")"); + $this->_error =& $err; + return PEAR::raiseError($err); + } + } elseif (is_array($data)) { + // + // array are accepted thanks to OArrayIterator + // + reset($data); + if (count($data) > 0 && array_key_exists(0, $data)) { + // echo "OArray::iterator", RxObject::ClassName($data), endl; + $this->_data = new OArray($data); + $this->_iterator =& $this->_data->getNewIterator(); + } else { + // echo "OHash::iterator", RxObject::ClassName($data), endl; + $this->_data = new OHash($data); + $this->_iterator =& $this->_data->getNewIterator(); + } + } else { + $err = new TypeError("phptal loop controler received a non Iterable value (" + . gettype($data) . ")"); + $this->_error =& $err; + return PEAR::raiseError($err); + } + + // + // install loop in repeat context array + // + $repeat =& $this->_context->get("repeat"); + if (array_key_exists($this->_data_name, $repeat)) { + unset($repeat[$this->_data_name]); + } + $repeat[$this->_data_name] =& $this; + + // $this->_context->setRef($this->_data_name, $temp); + $temp =& $this->_iterator->value(); + $this->_context->set($this->_data_name, $temp); + return $temp; + } + + /** + * Return current item index. + * + * @return int + */ + function index() + { + return $this->_iterator->index(); + } + + /** + * Return current item key or index for non associative iterators. + * + * @return mixed + */ + function key() + { + if (method_exists($this->_iterator, "key")) { + return $this->_iterator->key(); + } else { + return $this->_iterator->index(); + } + } + + /** + * Index is in range(0, length-1), the number in in range(1, length). + * + * @return int + */ + function number() + { + return $this->index() + 1; + } + + /** + * Return true if index is even. + * + * @return boolean + */ + function even() + { + return !$this->odd(); + } + + /** + * Return true if index is odd. + * + * @return boolean + */ + function odd() + { + return ($this->index() % 2); + } + + /** + * Return true if at the begining of the loop. + * + * @return boolean + */ + function start() + { + return ($this->index() == 0); + } + + /** + * Return true if at the end of the loop (no more item). + * + * @return boolean + */ + function end() + { + return ($this->length() == $this->number()); + } + + function isValid() + { + return $this->_iterator->isValid(); + } + + /** + * Return the length of the data (total number of iterations). + * + * @return int + */ + function length() + { + return $this->_data->size(); + } + + /** + * Retrieve next iterator value. + * + * @return mixed + */ + function &next() + { + $temp =& $this->_iterator->next(); + if (!$this->_iterator->isValid()) { + return false; + } + + // $this->_context->setRef($this->_data_name, $temp); + $this->_context->set($this->_data_name, $temp); + return $temp; + } +}; + + +/** + * Iterator for DB_Result PEAR object. + * + * This class is an implementation of the Iterator Interface + * for DB_Result objects produced by the usage of PEAR::DB package. + * + * @author Laurent Bedubourg + */ +class PHPTAL_DBResultIterator extends Iterator +{ + var $_src; + var $_index = -1; + var $_end = false; + var $_value; + + /** + * Iterator constructor. + * + * @param DB_Result $result + * The query result. + */ + function PHPTAL_DBResultIterator(&$result) + { + $this->_src =& $result; + $this->reset(); + } + + function reset() + { + if ($this->size() == 0) { + $this->_end = true; + return; + } + + $this->_index = 0; + $this->_end = false; + unset($this->_value); + $this->_value = $this->_src->fetchRow(); + } + + /** + * Return the number of rows in this result. + * + * @return int + */ + function size() + { + if (!isset($this->_size)) { + $this->_size = $this->_src->numRows(); + } + return $this->_size; + } + + /** + * Returns true if end of iterator has not been reached yet. + */ + function isValid() + { + return !$this->_end; + } + + /** + * Return the next row in this result. + * + * This method calls fetchRow() on the DB_Result, the return type depends + * of the DB_result->fetchmod. Please specify it before executing the + * template. + * + * @return mixed + */ + function &next() + { + if ($this->_end || ++ $this->_index >= $this->size()) { + $this->_end = true; + return false; + } + + unset($this->_value); + $this->_value = $this->_src->fetchRow(); + return $this->_value; + } + + /** + * Return current row. + * + * @return mixed + */ + function &value() + { + return $this->_value; + } + + /** + * Return current row index in resultset. + * + * @return int + */ + function index() + { + return $this->_index; + } +} + +?> diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Macro.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Macro.php new file mode 100644 index 0000000000..facdd03780 --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/PHPTAL/Macro.php @@ -0,0 +1,107 @@ + +// + +/* + * Macro invoker. + */ +class PHPTAL_Macro extends PHPTAL_Template +{ + var $_path = false; + var $_name; + + /** + * Macro constructor. + * + * @param PHPTAL_Template $caller + * The macro caller may be a template or a macro. + * @param string $path + * The macro path/name + */ + function PHPTAL_Macro(&$caller, $path) + { + $this->_name = $path; + + // extract macro path part, if none found, we'll assume macro is + // in the caller template. + + if (preg_match('/(.*?)\/([a-zA-Z0-9_]*?)$/', $this->_name, $match)) { + list(, $this->_path, $this->_name) = $match; + } else { + $this->_sourceFile = $caller->_sourceFile; + } + + // call parent constructor + $this->PHPTAL_Template($this->_path, + $caller->_repository, + $caller->_cacheDir); + + $this->setParent($caller); + $this->setEncoding($caller->getEncoding()); + } + + /** + * Execute macro with caller context. + * + * @return string + */ + function execute() + { + if ($this->_path !== false) { + $err = $this->_prepare(); + if (PEAR::isError($err)) { + return $err; + } + } + return $this->_cacheManager->macro($this, + $this->_sourceFile, + $this->_name, + $this->_parent->getContext()); + } + + /** + * Really process macro parsing/invocation. + * + * @return string + */ + function _process() + { + if ($this->_path !== false) { + $err = $this->_load(); + if (PEAR::isError($err)) { + return $err; + } + } else { + $this->_funcName = $this->_parent->_funcName; + } + + $func = $this->_funcName . '_' . $this->_name; + + if (!function_exists($func)) { + $err = "Unknown macro '$this->_name'"; + return PEAR::raiseError($err); + } + + return $func($this->_parent); + } +} + +?> diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/OutputControl.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/OutputControl.php new file mode 100644 index 0000000000..ce3c3403d6 --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/PHPTAL/OutputControl.php @@ -0,0 +1,96 @@ + +// + +class PHPTAL_OutputControl +{ + var $_buffer = ""; + var $_buffers = array(); + var $_quoteStyle = ENT_COMPAT; + var $_encoding = 'UTF-8'; + var $_context; + + function PHPTAL_OutputControl(&$context, $encoding='UTF-8') + { + $this->_context = $context; + $this->_encoding = $encoding; + } + + function pushBuffer() + { + $this->_buffers[] = $this->_buffer; + $this->_buffer = ""; + } + + function popBuffer() + { + $res = $this->_buffer; + $this->_buffer = array_pop($this->_buffers); + return $res; + } + + function write(&$str) + { + if (is_object($str)) { + if (PEAR::isError($str)) { + $str = "[". get_class($str) . ": " . $str->message . "]"; + // $this->_context->cleanError(); + } else { + $str = Types::toString($str); + } + } + + if (defined("PHPTAL_DIRECT_OUTPUT") && count($this->_buffers) == 0) { + // echo htmlentities($str); + // support for cyrillic strings thanks to Igor E. Poteryaev + echo htmlentities($str, $this->_quoteStyle, $this->_encoding); + } else { + // $this->_buffer .= htmlentities($str); + // support for cyrillic strings thanks to Igor E. Poteryaev + $this->_buffer .= htmlentities($str, $this->_quoteStyle, $this->_encoding); + } + } + + function writeStructure($str) + { + if (is_object($str)) { + if (PEAR::isError($str)) { + $str = "[" . $str->message . "]"; + // $this->_context->cleanError(); + } else { + $str = Types::toString($str); + } + } + + if (defined("PHPTAL_DIRECT_OUTPUT") && count($this->_buffers) == 0) { + echo $str; + } else { + $this->_buffer .= $str; + } + } + + function &toString() + { + return $this->_buffer; + } +} + +?> diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Parser.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Parser.php new file mode 100644 index 0000000000..f113c5d2d5 --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/PHPTAL/Parser.php @@ -0,0 +1,515 @@ + +// + +$__d = dirname(__FILE__); +require_once _phptal_os_path_join($__d, 'XML_Parser.php'); +require_once _phptal_os_path_join($__d, 'Attribute.php'); +require_once _phptal_os_path_join($__d, 'Expression.php'); +require_once _phptal_os_path_join($__d, 'ExpressionFunctions.php'); +require_once _phptal_os_path_join($__d, 'Generator.php'); +require_once _phptal_os_path_join($__d, 'Tag.php'); + +$_t = _phptal_os_path_join($__d, 'Attribute', 'TAL'); +require_once _phptal_os_path_join($_t, 'Attributes.php'); +require_once _phptal_os_path_join($_t, 'Comment.php'); +require_once _phptal_os_path_join($_t, 'Content.php'); +require_once _phptal_os_path_join($_t, 'Condition.php'); +require_once _phptal_os_path_join($_t, 'Define.php'); +require_once _phptal_os_path_join($_t, 'Omit_tag.php'); +require_once _phptal_os_path_join($_t, 'Replace.php'); +require_once _phptal_os_path_join($_t, 'On_error.php'); +require_once _phptal_os_path_join($_t, 'Repeat.php'); + +$_t = _phptal_os_path_join($__d, 'Attribute', 'PHPTAL'); +require_once _phptal_os_path_join($_t, 'Include.php'); +require_once _phptal_os_path_join($_t, 'Src_include.php'); + +$_t = _phptal_os_path_join($__d, 'Attribute', 'METAL'); +require_once _phptal_os_path_join($_t, 'Define_macro.php'); +require_once _phptal_os_path_join($_t, 'Use_macro.php'); +require_once _phptal_os_path_join($_t, 'Define_slot.php'); +require_once _phptal_os_path_join($_t, 'Fill_slot.php'); + +$_t = _phptal_os_path_join($__d, 'Attribute', 'I18N'); +require_once _phptal_os_path_join($_t, 'Translate.php'); +require_once _phptal_os_path_join($_t, 'Name.php'); +require_once _phptal_os_path_join($_t, 'Attributes.php'); + + +/** + * PHPTAL template parser. + * + * This object implements PHPTAL_XML_Parser interface and will accept only + * well formed xml templates. + * + * + * Parser object has two aims : + * + * - generate the template structure tree + * - generate the php source code this structure represents + * + * Once this job is accomplished, the parser object should be destroyed and + * MUST NOT be used to parse another template. It's a one time and drop + * object. + * + * + * Note about code generation : + * + * The final source code is ready to write into a php file. + * + * The code generation process requires a function name which should represent + * the template unique id (Template class makes an md5 over the source file + * path to create this id). + * + * @version 0.1 + * @author Laurent Bedubourg + */ +class PHPTAL_Parser extends PHPTAL_XML_Parser +{ + // root gat + var $_root; + // document headers (string) + var $_headers = false; + var $_started = false; + + var $_docType; + var $_inDocType; + + // current tag + var $_current; + + // source file name + var $_file; + + // activate xhtml empty tags lookup + var $_outputFormat = PHPTAL_XHTML; + + // keep xmlns:* attributes ? + var $_keepXMLNS = false; + + /** + * Parse a template string. + * + * @param string $file + * The template source file. + * @param string $src + * The template source. + * + * @throws PHPTAL_ParseError + */ + function parse($file, $src) + { + $this->_file = $file; + $this->_initRoot(); + return $this->parseString($src, true); + } + + /** + * Generate php code. + * + * After template parsing, this method must be called to generate php code + * from the template tree. + * + * @param string func_name + * The template function name + * + * @access private + * @return string + */ + function generateCode($func_name) + { + $gen = new PHPTAL_Generator($this->_file, $func_name); + $gen->setHeaders($this->_headers); + $err = $this->_root->generateCode($gen); + if (PEAR::isError($err)) { + return $err; + } + return $gen->getCode(); + } + + /** + * Return a string representation of the underlying xhtml tree. + * + * This method is for debug purpose. + * + * @access private + * @return string + */ + function toString() + { + $buf = new StringBuffer(); + $buf->appendln('Template tree [\'', $this->_file, '\']'); + $buf->append($this->_root->toString()); + return $buf->toString(); + } + + + // ---------------------------------------------------------------------- + // Private methods + // ---------------------------------------------------------------------- + + /** + * Initialize root node. + * + * @access private + */ + function _initRoot() + { + $this->_headers = ""; + $this->_started = false; + $this->_root = new PHPTAL_Tag($this, "#root", array()); + $this->_current =& $this->_root; + } + + /** + * Push a node as the current one. + * + * @param PHPTAL_Node tag + * @access private + */ + function _push(&$tag) + { + $this->_current->addChild($tag); + unset($this->_current); + $this->_current =& $tag; + } + + /** + * Push a node into the current one. + * + * @param PHPTAL_Node tag + * @access private + */ + function _pushChild(&$tag) + { + $this->_current->addChild($tag); + } + + /** + * Pop the last node (go up a level in tree). + * + * @access private + */ + function _pop() + { + $temp =& $this->_current; + unset($this->_current); + if ($temp != $this->_root) { + $this->_current =& $temp->getParent(); + } else { + $this->_current =& $this->_root; + } + } + + /* + * getter/setter for the output mode. + * + * @param int $mode optional + * PHPTAL_XML or PHPTAL_XHTML + */ + function _outputMode($mode=false) + { + if ($mode !== false) { + $this->_outputFormat = $mode; + } + return $this->_outputFormat; + } + + // ---------------------------------------------------------------------- + // XML callbacks methods + // ---------------------------------------------------------------------- + + /** + * xml callback + * + * @access private + */ + function onElementStart($name, $attributes) + { + global $_phptal_namespaces; + + $this->_started = true; + + if (strpos($name, ':') !== false) { + list($domain, $extend) = split(':', strtoupper($name)); + if (($extend == 'BLOCK') && (in_array($domain, $_phptal_namespaces))) { + $attributes = PHPTAL_Parser::extendZptBlockAttributes($domain, $attributes); + $attributes['tal:omit-tag'] = ''; + } + } + + // separate phptal attributes from xhtml ones + // if an attribute is not found, an error is raised. + $split = PHPTAL_Parser::TemplateAttributes($attributes); + if (PEAR::isError($split)) { + return $split; + } + + // no error, the returned value is a tuple + list($phptal, $attributes) = $split; + + // sort phptal attributes + $phptal = PHPTAL_Parser::OrderTemplateAttributes($phptal); + if (PEAR::isError($phptal)) { + return $phptal; + } + + // create the tag and add its template attributes + $tag = new PHPTAL_Tag($this, $name, $attributes); + foreach ($phptal as $t) { + $tag->appendTemplateAttribute($t); + unset($t); // $t is appended by reference + } + + $tag->line = $this->getLineNumber(); + $this->_push($tag); + } + + /** + * Extends ZPT attributes withing a *:block element so these attributes can + * be used by phptal parser. + * + * @access private + */ + function extendZptBlockAttributes($domain, $attributes) + { + global $_phptal_dictionary; + $result = array(); + foreach ($attributes as $key => $value) { + $expected = strtoupper("$domain:$key"); + if (array_key_exists($expected, $_phptal_dictionary)) { + $result[$expected] = $value; + } + } + return $result; + } + + /** + * xml callback + * + * @access private + */ + function onElementData($data) + { + // ${xxxx} variables are evaluated during code + // generation whithin the CodeGenerator under the + // printString() method. + $tag = new PHPTAL_Tag($this, "#cdata", array()); + $tag->setContent($data); + $this->_pushChild($tag); + } + + /** + * xml callback + * + * @access private + */ + function onSpecific($data) + { + // fix xml parser '&' => '&' automatic conversion + $data = str_replace('&', '&', $data); + + if ($this->_current->name() == "#root" && !$this->_started) { + $this->_headers .= $data; + return; + } + $tag = new PHPTAL_Tag($this, "#cdata", array()); + $tag->setContent($data); + $this->_pushChild($tag); + } + + /** + * xml callback + * + * @access private + */ + function onElementClose($name) + { + if ($this->_current == null) { + return $this->_raiseNoTagExpected($name); + } + if ($this->_current->name() != $name) { + return $this->_raiseUnexpectedTagClosure($name); + } + $this->_pop(); + } + + // ---------------------------------------------------------------------- + // Static methods + // ---------------------------------------------------------------------- + + /** + * Lookup template attributes in given hashtable. + * + * This method separate xml attributes from template attributes + * and return an array composed of the array of formers and the array of + * laters. + * + * @access private + * @static 1 + * + * @param hashtable attrs + * Attributes hash + * + * @return array + */ + function TemplateAttributes($attrs) + { + global $_phptal_dictionary, $_phptal_aliases, $_phptal_namespaces; + $phptal = array(); + $att = array(); + + foreach ($attrs as $key=>$exp) { + + $test_key = strtoupper($key); + $ns = preg_replace('/(:.*?)$/', '', $test_key); + $sns = preg_replace('/^(.*?:)/', '', $test_key); + // dictionary lookup + if (array_key_exists($test_key, $_phptal_dictionary)) { + $phptal[$test_key] = $exp; + } + // alias lookup + elseif (array_key_exists($test_key, $_phptal_aliases)) { + $phptal[ $_phptal_aliases[$test_key] ] = $exp; + } + // the namespace is known but the the attribute is not + elseif (in_array($ns, $_phptal_namespaces)) { + return $this->_raiseUnknownAttribute($test_key); + } + // regular xml/xhtml attribute (skip namespaces declaration) + elseif ($ns !== 'XMLNS' || $this->_keepXMLNS + || !in_array($sns, $_phptal_namespaces)) { + $att[$key] = $exp; + } + } + return array($phptal, $att); + } + + /** + * Order phptal attributes array using $_phptal_rules_order array. + * + * @static 1 + * @access private + * + * @param array phptal + * Array of phptal attributes (will be modified) + */ + function OrderTemplateAttributes(&$phptal) + { + global $_phptal_rules_order, $_phptal_dictionary; + + // order elements by their name using the rule table + $result = array(); + foreach ($phptal as $akey=>$exp) { + + // retrieve attribute handler class + $class = "PHPTAL_ATTRIBUTE_" . str_replace(":", "_", $akey); + $class = str_replace("-", "_", $class); + if (!class_exists($class)) { + return $this->_raiseAttributeNotFound($akey, $class); + } + + $hdl = new $class($exp); + $hdl->name = $akey; + $hdl->_phptal_type = $_phptal_dictionary[$akey]; + + // resolve attributes conflict + $pos = $_phptal_rules_order[$akey]; + if (array_key_exists($pos, $result)) { + return $this->_raiseAttConflict($akey, $result[$pos]->name); + } + + // order elements by their order rule + $result[$_phptal_rules_order[$akey]] = $hdl; + unset($hdl); + } + return $result; + } + + // ---------------------------------------------------------------------- + // Errors raising methods + // ---------------------------------------------------------------------- + + function _raiseAttributeNotFound($att, $class) + { + $str = sprintf("Attribute '%s' exists in dictionary but class '%s' ". + "was not found", + $att, $class); + $err = new PHPTAL_ParseError($str); + return PEAR::raiseError($err); + } + + function _raiseUnknownAttribute($att) + { + $str = sprintf("Unknown PHPTAL attribute '%s' in %s at line %d", + $att, $this->_file, $this->getLineNumber()); + $err = new PHPTAL_UnknownAttribute($str); + return PEAR::raiseError($err); + } + + function _raiseUnexpectedTagClosure($name) + { + $str = sprintf("Non matching tag '%s' error in xml file '%s' at line %d" + . endl . "waiting for end of tag '%s' declared at line %d.", + $name, $this->_file, $this->getLineNumber(), + $this->_current->name(), $this->_current->line); + $err = new PHPTAL_ParseError($str); + return PEAR::raiseError($err); + } + + function _raiseNoTagExpected($name) + { + $str = sprintf("Bad xml error in xml file '%s' at line %d". endl + ."Found closing tag '%s' while no current tag is waited.", + $this->_file, $this->getLineNumber(), $name); + $err = new PHPTAL_ParseError($str); + return PEAR::raiseError($err); + } + + function _raiseAttConflict($a2, $a1) + { + $str = sprintf('Template Attribute conflict in \'%s\' at line %d'. endl + . ' %s must not be used in the same tag as %s', + $this->_file, $this->getLineNumber(), $a1, $a2); + $err = new PHPTAL_AttributeConflict($str); + return PEAR::raiseError($err); + } +}; + +/** + * Error raised at parse time when some bad xml is found or when some tag + * is unknown or is badly used. + */ +class PHPTAL_ParseError extends PEAR_Error {} + +/** + * Error raised when an unknown PHPTAL tag is requested by the template. + */ +class PHPTAL_UnknownAttribute extends PHPTAL_ParseError {} + +/** + * Error raised when a template attribute conflicts with another one. + */ +class PHPTAL_AttributeConflict extends PHPTAL_ParseError {} + + +?> diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/SourceLocator.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/SourceLocator.php new file mode 100644 index 0000000000..e28147942f --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/PHPTAL/SourceLocator.php @@ -0,0 +1,62 @@ + + */ +class PHPTAL_SourceLocator +{ + var $path; + + function PHPTAL_SourceLocator($path) + { + $this->path = $path; + } + + /** + * Returns an absolute path to this resource. + * + * The result of this method is used to generate some unique + * md5 value which represent the template php function name + * and the intermediate php file name. + * + * @return string + */ + function realPath() + { + return $this->path; + } + + /** + * Return source last modified date in a filemtime format. + * + * The result is compared to php intermediate mtime to decide + * weither or not to re-parse the template source. + * + * @return int + */ + function lastModified() + { + return filemtime($this->path); + } + + /** + * Return the template source. + * + * This method is invoqued if the template has to be parsed. + * + * @return string + */ + function data() + { + return join('', file($this->path)); + } +} + +?> diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/SourceResolver.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/SourceResolver.php new file mode 100644 index 0000000000..735a161160 --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/PHPTAL/SourceResolver.php @@ -0,0 +1,63 @@ + + */ +class PHPTAL_SourceResolver +{ + /** + * Resolve a template source path. + * + * This method is invoked each time a template source has to be + * located. + * + * This method must returns a PHPTAL_SourceLocator object which + * 'point' to the template source and is able to retrieve it. + * + * If the resolver does not handle this kind of path, it must return + * 'false' so PHPTAL will ask other resolvers. + * + * @param string $path -- path to resolve + * + * @param string $repository -- templates repository if specified on + * on template creation. + * + * @param string $callerPath -- caller realpath when a template look + * for an external template or macro, + * this should be usefull for relative urls + * + * @return PHPTAL_SourceLocator | false + */ + function resolve($path, $repository=false, $callerPath=false) + { + // first look at an absolute path + $pathes = array($path); + // search in the caller directory + if ($callerPath) { + $pathes[] = dirname($callerPath) . PHPTAL_PATH_SEP . $path; + } + // search in the template repository + if ($repository) { + $pathes[] = $repository . PHPTAL_PATH_SEP . $path; + } + // search in the defined repository + if (defined('PHPTAL_REPOSITORY')) { + $pathes[] = PHPTAL_REPOSITORY . PHPTAL_PATH_SEP . $path; + } + foreach ($pathes as $ftest) { + if (file_exists($ftest)) { + $realpath = realpath($ftest); + $locator = new PHPTAL_SourceLocator($realpath); + return $locator; + } + } + return false; + } +} + +?> diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Tag.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Tag.php new file mode 100644 index 0000000000..253c7399f3 --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/PHPTAL/Tag.php @@ -0,0 +1,296 @@ + +// + +/** + * Represents an xhtml entity. + * + * To obtain a fine granularity of code generation the Tag code generation + * process is divided into logical sub sequences. + * + * surround head // call surround attributes + * replace // call replace and skip head -> foo sequence + * || head // echo tag start (see disableHeadFoot()) + * content // call content replace and skip cdata seq + * || cdata && child // echo tag content and generate children code + * foot // echo tag end (see disableHeadFoot()) + * surround foot // call surround attributes + * + * + * Some attributes like 'omit' requires to disable the head / foot sequences + * whithout touching content sequences, the disableHeadFoot() method must be + * used in that aim. + * + * @version 0.1 + * @author Laurent Bedubourg + */ +class PHPTAL_Tag +{ + /** + * @var int $line The template line which produced this tag. + */ + var $line = 0; + + // tree properties + + var $_name = "#cdata"; + var $_attrs = array(); + var $_children = array(); + var $_content = ""; + var $_parent = null; + + // template system properties + + var $_parser; + var $_replace_attributes = array(); + var $_content_attributes = array(); + var $_surround_attributes = array(); + var $_head_foot_disabled = false; + + + /** + * Tag constructor. + * + * @param string $name + * The tag name. + * + * @param hashtable $attrs + * Tag xhtml attributes. + */ + function PHPTAL_Tag(&$parser, $name, $attrs) + { + $this->_parser =& $parser; + $this->_name = $name; + $this->_attrs = $attrs; + } + + function appendTemplateAttribute(&$hdlr) + { + switch ($hdlr->_phptal_type) + { + case _PHPTAL_REPLACE: + $this->_replace_attributes[] =& $hdlr; + break; + case _PHPTAL_CONTENT: + $this->_content_attributes[] =& $hdlr; + break; + case _PHPTAL_SURROUND: + $this->_surround_attributes[] =& $hdlr; + break; + default: + return PEAR::raiseError( + "PHPTAL internal error : bad attribute type : " + . get_class($hdlr)); + } + } + + function name() + { + return $this->_name; + } + + function isData() + { + return $this->_name == "#cdata"; + } + + function attributes() + { + return $this->_attrs; + } + + function setParent(&$node) + { + $this->_parent =& $node; + } + + function &getParent() + { + return $this->_parent; + } + + function addChild(&$node) + { + $node->setParent($this); + $this->_children[] = &$node; + } + + function setContent($str) + { + $this->_content = $str; + } + + function hasContent() + { + return (count($this->_content_attributes) == 0 + || count($this->_children) == 0 + || strlen($this->_content) == 0); + } + + function toString($tab="") + { + $buf = new StringBuffer(); + $buf->appendln($tab, '+ node ', $this->name()); + for ($i=0; $i < count($this->_children); $i++) { + $child =& $this->_children[$i]; + $buf->append($child->toString($tab . " ")); + unset($child); + } + return $buf->toString(); + } + + function generateCode(&$g) + { + // if text node, just print the content and return + if ($this->_name == "#cdata") { + $g->doPrintString($this->_content); + return; + } + + if ($this->_name == "#root") { + return $this->generateContent($g); + } + + // if replace attributes exists, they will handle + // this tag rendering + if (count($this->_replace_attributes) > 0) { + $err = $this->surroundHead($g); + if (PEAR::isError($err)) { return $err; } + + for ($i=0; $i_replace_attributes); $i++) { + $h =& $this->_replace_attributes[$i]; + $err = $h->activate($g, $this); + if (PEAR::isError($err)) { return $err; } + unset($h); + } + return $this->surroundFoot($g); + } + + $err = $this->surroundHead($g); + if (PEAR::isError($err)) { return $err; } + + $this->printHead($g); + + $err = $this->generateContent($g); + if (PEAR::isError($err)) { return $err; } + + $this->printFoot($g); + + $err = $this->surroundFoot($g); + if (PEAR::isError($err)) { return $err; } + } + + function printHead(&$g) + { + if ($this->headFootDisabled()) return; + + $g->doPrintString('<', $this->_name); + + $this->printAttributes($g); + + if ($this->hasContent() && !$this->_isXHTMLEmptyElement()) { + $g->doPrintString('>'); + } else { + $g->doPrintString('/>'); + } + } + + function printFoot(&$g) + { + if ($this->headFootDisabled()) return; + + if ($this->hasContent() && !$this->_isXHTMLEmptyElement()) { + $g->doPrintString('_name, '>'); + } + } + + function printAttributes(&$g) + { + global $_phptal_xhtml_boolean_attributes; + foreach ($this->_attrs as $key=>$value) { + if ($this->_parser->_outputMode() == PHPTAL_XHTML + && in_array(strtolower($key), $_phptal_xhtml_boolean_attributes)) { + $g->doPrintString(" $key"); + } else { + $g->doPrintString(" $key=\"$value\""); + } + } + } + + function surroundHead(&$g) + { + // if some surround attributes, we activate + // their header method + for ($i=0; $i_surround_attributes); $i++) { + $h =& $this->_surround_attributes[$i]; + $err = $h->start($g, $this); + if (PEAR::isError($err)) { return $err; } + unset($h); + } + } + + function surroundFoot(&$g) + { + // close surrounders in reverse order of course + for ($i = (count($this->_surround_attributes)-1); $i >= 0; $i--) { + $err = $this->_surround_attributes[$i]->end($g, $this); + if (PEAR::isError($err)) { return $err; } + } + } + + function generateContent(&$g) + { + if (count($this->_content_attributes) > 0) { + // time for content attributes, + foreach ($this->_content_attributes as $h) { + $err = $h->activate($g, $this); + if (PEAR::isError($err)) { return $err; } + } + } else { + // if none, we just ask children to generate their code + foreach ($this->_children as $child) { + $err = $child->generateCode($g); + if (PEAR::isError($err)) { return $err; } + } + } + } + + function disableHeadFoot() + { + $this->_head_foot_disabled = true; + } + + function headFootDisabled() + { + return $this->_head_foot_disabled;print_r($this->_root); + } + + function _isXHTMLEmptyElement() + { + global $_phptal_xhtml_empty_tags; + if ($this->_parser->_outputMode() != PHPTAL_XHTML) { + return false; + } + return in_array(strtoupper($this->name()), $_phptal_xhtml_empty_tags); + } +} + +?> diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/Template.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/Template.php new file mode 100644 index 0000000000..cef3465da8 --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/PHPTAL/Template.php @@ -0,0 +1,562 @@ + +// + + +class PHPTAL_Template +{ + var $_ctx; + var $_code; + var $_codeFile; + var $_funcName; + var $_sourceFile; + var $_error = false; + var $_repository = false; + var $_cacheDir = false; + var $_parent = false; + var $_parentPath = false; + var $_prepared = false; + var $_cacheManager; + + var $_outputMode = PHPTAL_XHTML; + + var $_inputFilters; + var $_outputFilters; + var $_resolvers; + var $_locator; + + var $_headers = false; + + var $_translator; + + var $_encoding = 'UTF-8'; + + /** + * Template object constructor. + * + * @param string $file -- The source file name + * @param string $repository optional -- Your templates root. + * @param string $cache_dir optional -- Intermediate php code repository. + */ + function PHPTAL_Template($file, $repository=false, $cache_dir=false) + { + $this->_sourceFile = $file; + $this->_repository = $repository; + + // deduce intermediate php code cache directory + if (!$cache_dir) { + if (defined('PHPTAL_CACHE_DIR')) { + $cache_dir = PHPTAL_CACHE_DIR; + } else { + $cache_dir = PHPTAL_DEFAULT_CACHE_DIR; + } + } + $this->_cacheDir = $cache_dir; + + // instantiate a new context for this template + // !!! this context may be overwritten by a parent context + $this->_ctx = new PHPTAL_Context(); + + // create resolver vector and the default filesystem resolver + $this->_resolvers = new OArray(); + $this->_resolvers->push(new PHPTAL_SourceResolver()); + + // vector for source filters + $this->_inputFilters = new OArray(); + $this->_outputFilters = new OArray(); + + // if no cache manager set, we instantiate default dummy one + if (!isset($this->_cacheManager)) { + $this->_cacheManager = new PHPTAL_Cache(); + } + } + + /** + * Set template ouput type. + * + * Default output is XHTML, so you'll have to call this method only for + * specific xml documents with PHPTAL_XML parameter. + * + * @param int $mode -- output mode (PHPTAL_XML) as default system use XHTML + */ + function setOutputMode($mode) + { + $this->_outputMode = $mode; + } + + /** + * Replace template context with specified hashtable. + * + * @param hash hashtable -- Associative array. + */ + function setAll($hash) + { + $this->_ctx = new PHPTAL_Context($hash); + } + + /** + * Set a template context value. + * + * @param string $key -- The context key + * @param mixed $value -- The context value + */ + function set($name, $value) + { + $this->_ctx->set($name, $value); + } + + /** + * Set a template context value by reference. + * + * @param string $name -- The template context key + * @param mixed $value -- The template context value + */ + function setRef($name, &$value) + { + $this->_ctx->setRef($name, $value); + } + + /** + * Retrieve template context object. + * + * @return PHPTAL_Context + */ + function &getContext() + { + return $this->_ctx; + } + + /** + * Set the template context object. + * + * @param PHPTAL_Context $ctx -- The context object + */ + function setContext(&$ctx) + { + $this->_ctx =& $ctx; + } + + /** + * Set the cache manager to use for Template an Macro calls. + * + * @param PHPTAL_Cache $mngr -- Cache object that will be used to cache + * template and macros results. + */ + function setCacheManager(&$mngr) + { + $this->_cacheManager =& $mngr; + } + + /** + * Retrieve the cache manager used in this template. + * + * @return PHPTAL_Cache + */ + function &getCacheManager() + { + return $this->_cacheManager; + } + + /** + * Set the I18N implementation to use in this template. + * + * @param PHPTAL_I18N $tr -- I18N implementation + */ + function setTranslator(&$tr) + { + $this->_translator =& $tr; + } + + /** + * The translator used by this template. + * + * @return PHPTAL_I18N + */ + function &getTranslator() + { + return $this->_translator; + } + + /** + * Test if the template file exists. + * @deprecated use isValid() instead + * @return boolean + */ + function fileExists() + { + return $this->isValid(); + } + + /** + * Test if the template resource exists. + * + * @return boolean + */ + function isValid() + { + if (isset($this->_locator)) { + return true; + } + + // use template resolvers to locate template source data + // in most cases, there will be only one resolver in the + // resolvers list (the default one) which look on the file + // system. + + $i = $this->_resolvers->getNewIterator(); + while ($i->isValid()) { + $resolver =& $i->value(); + $locator =& $resolver->resolve($this->_sourceFile, + $this->_repository, + $this->_parentPath); + if ($locator && !PEAR::isError($locator)) { + $this->_locator =& $locator; + $this->_real_path = $this->_locator->realPath(); + return true; + } + $i->next(); + } + return false; + } + + /** + * Add a source resolver to the template. + * + * @param PHPTAL_SourceResolver $resolver + * The source resolver. + */ + function addSourceResolver(&$resolver) + { + $this->_resolvers->pushRef($resolver); + } + + /** + * Add filter to this template input filters list. + * + * @param PHPTAL_Filter $filter + * A filter which will be invoked on template source. + */ + function addInputFilter(&$filter) + { + $this->_inputFilters->pushRef($filter); + } + + /** + * Add an output filter to this template output filters list. + * + * @param PHPTAL_Filter $filter + * A filter which will be invoked on template output. + */ + function addOutputFilter(&$filter) + { + $this->_outputFilters->pushRef($filter); + } + + /** + * Retrieve the source template real path. + * + * This method store its result internally if no $file attribute is + * specified (work on template internals). + * + * If a file name is specified, this method will try to locate it + * exploring current path (PWD), the current template location, + * the repository and parent template location. + * + * @param string $file optional + * some file name to locate. + * + * @throws FileNotFound + * @return string + */ + function realpath($file=false) + { + // real template path + if (!$file) { + if ($this->isValid()) { + return $this->_real_path; + } else { + $ex = new FileNotFound($this->_sourceFile . ' not found'); + return PEAR::raiseError($ex); + } + } + + // + // path to some file relative to this template + // + $i = $this->_resolvers->getNewIterator(); + while ($i->isValid()) { + $resolver =& $i->value(); + $locator =& $resolver->resolve($file, + $this->_repository, + $this->_real_path); + if ($locator) { + return $locator->realPath(); + } + $i->next(); + } + + $ex = new FileNotFound($file . ' not found'); + return PEAR::raiseError($ex); + } + + /** + * Set the template result encoding. + * + * Changing this encoding will change htmlentities behaviour. + * + * Example: + * + * $tpl->setEncoding('ISO-8859-1"); + * + * See http://fr2.php.net/manual/en/function.htmlentities.php for a list of + * supported encodings. + * + * @param $enc string Template encoding + */ + function setEncoding($enc) + { + $this->_encoding = $enc; + } + + /** + * Retrieve the template result encoding. + * + * @return string + */ + function getEncoding() + { + return $this->_encoding; + } + + // ---------------------------------------------------------------------- + // private / protected methods + // ---------------------------------------------------------------------- + + /** + * Set the called template. (internal) + * + * @access package + */ + function setParent(&$tpl) + { + $this->_parent =& $tpl; + $this->_resolvers = $tpl->_resolvers; + $this->_inputFilters = $tpl->_inputFilters; + $this->_parentPath = $tpl->realPath(); + $this->_cacheManager =& $tpl->getCacheManager(); + $this->_translator =& $tpl->_translator; + $this->setOutputMode($tpl->_outputMode); + } + + /** + * Prepare template execution. + * + * @access private + */ + function _prepare() + { + if ($this->_prepared) return; + $this->_sourceFile = $this->realpath(); + + // ensure that no error remain + if (PEAR::isError($this->_sourceFile)) { + return $this->_sourceFile; + } + $this->_funcName = "tpl_" . PHPTAL_MARK . md5($this->_sourceFile); + $this->_codeFile = $this->_cacheDir . $this->_funcName . '.php'; + $this->_prepared = true; + } + + /** + * Generate php code from template source + * + * @access private + * @throws PHPTALParseException + */ + function _generateCode() + { + require_once _phptal_os_path_join(dirname(__FILE__), 'Parser.php'); + + $parser = new PHPTAL_Parser(); + $parser->_outputMode($this->_outputMode); + $data = $this->_locator->data(); + + // activate prefilters on data + $i = $this->_inputFilters->getNewIterator(); + while ($i->isValid()){ + $filter =& $i->value(); + $data = $filter->filter($data); + $i->next(); + } + + // parse source + $result = $parser->parse($this->_real_path, $data); + if (PEAR::isError($result)) { + return $result; + } + + // generate and store intermediate php code + $this->_code = $parser->generateCode($this->_funcName); + if (PEAR::isError($this->_code)) { + return $this->_code; + } + } + + /** + * Load cached php code + * + * @access private + */ + function _loadCachedCode() + { + include_once($this->_codeFile); + $this->_code = "#loaded"; + } + + /** + * Cache generated php code. + * + * @access private + */ + function _cacheCode() + { + $fp = @fopen($this->_codeFile, "w"); + if (!$fp) { + return PEAR::raiseError($php_errormsg); + } + fwrite($fp, $this->_code); + fclose($fp); + } + + /** + * Load or generate php code. + * + * @access private + */ + function _load() + { + if (isset($this->_code) && !PEAR::isError($this->_code)) { + return; + } + + if (!defined('PHPTAL_NO_CACHE') + && file_exists($this->_codeFile) + && filemtime($this->_codeFile) >= $this->_locator->lastModified()) { + return $this->_loadCachedCode(); + } + + $err = $this->_generateCode(); + if (PEAR::isError($err)) { + return $err; + } + + $err = $this->_cacheCode(); + if (PEAR::isError($err)) { + return $err; + } + + $err = $this->_loadCachedCode(); + if (PEAR::isError($err)) { + return $err; + } + } + + /** + * Execute template with prepared context. + * + * This method execute the template file and returns the produced string. + * + * @return string + * @throws + */ + function execute() + { + $err = $this->_prepare(); + if (PEAR::isError($err)) { + $this->_ctx->_errorRaised = true; + return $err; + } + return $this->_cacheManager->template($this, + $this->_sourceFile, + $this->_ctx); + } + + /** + * Really load/parse/execute the template and process output filters. + * + * This method is called by cache manager to retrieve the real template + * execution value. + * + * IMPORTANT : The result is post-filtered here ! + * + * @return string + * @access private + */ + function _process() + { + $err = $this->_load(); + if (PEAR::isError($err)) { + $this->_ctx->_errorRaised = true; + return $err; + } + + $this->_ctx->_errorRaised = false; + $func = $this->_funcName; + if (!function_exists($func)) { + $err = "Template function '$func' not found (template source : $this->_sourceFile"; + return PEAR::raiseError($err); + } + + // ensure translator exists + if (!isset($this->_translator)) { + $this->_translator = new PHPTAL_I18N(); + } + + $res = $func($this); + if ($this->_headers) { + $res = $this->_headers . $res; + } + + // activate post filters + $i = $this->_outputFilters->getNewIterator(); + while ($i->isValid()) { + $filter =& $i->value(); + $res = $filter->filter($this, $res, PHPTAL_POST_FILTER); + $i->next(); + } + return $res; + } + + function _translate($key) + { + return $this->_translator->translate($key); + } + + function _setTranslateVar($name, $value) + { + if (is_object($value)) { + $value = $value->toString(); + } + $this->_translator->set($name, $value); + } +} + +?> diff --git a/PHPTAL-NP-0.7.0/libs/PHPTAL/XML_Parser.php b/PHPTAL-NP-0.7.0/libs/PHPTAL/XML_Parser.php new file mode 100644 index 0000000000..ee636b53cc --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/PHPTAL/XML_Parser.php @@ -0,0 +1,254 @@ + +// + +require_once "Types/Errors.php"; + +/** + * PHPTAL internal xml parser. + * + * Note: + * + * I didn't use the XML/Parser package because of reference problems due to + * call_user_func and call_user_method. + * + * This problem should vanished with automatic object referencing in php4.4 + * (ZendEngine2) remind me to remove this parser at this time. + * + * + * This class uses "xml_*" php functions to parse xml data. + * + * To create a new xml parser, extends this class and implements following + * methods. + * + * - onElementStart($tag, $attributes) + * - onElementClose($tag) + * - onElementData($data) + * - onSpecific($data) + * + * Here's an exemple of xml parser implementation. + * + * :", $data, endl; + * } + * }; + * + * // MyParser usage : + * $p = new MyParser(); + * $p->parse( $myString ); + * + * ?> + * + * @author Laurent Bedubourg + */ +class PHPTAL_XML_Parser +{ + var $_file = '#string'; + var $_tags = array(); + var $_parser; + var $_error; + var $_xmlErrors = array( + XML_ERROR_NONE => "XML_ERROR_NONE", + XML_ERROR_NO_MEMORY => "XML_ERROR_NO_MEMORY", + XML_ERROR_SYNTAX => "XML_ERROR_SYNTAX", + XML_ERROR_NO_ELEMENTS => "XML_ERROR_NO_ELEMENTS", + XML_ERROR_INVALID_TOKEN => "XML_ERROR_INVALID_TOKEN", + XML_ERROR_UNCLOSED_TOKEN => "XML_ERROR_UNCLOSED_TOKEN", + XML_ERROR_PARTIAL_CHAR => "XML_ERROR_PARTIAL_CHAR", + XML_ERROR_TAG_MISMATCH => "XML_ERROR_TAG_MISMATCH", + XML_ERROR_DUPLICATE_ATTRIBUTE => "XML_ERROR_DUPLICATE_ATTRIBUTE", + XML_ERROR_JUNK_AFTER_DOC_ELEMENT => "XML_ERROR_JUNK_AFTER_DOC_ELEMENT", + XML_ERROR_PARAM_ENTITY_REF => "XML_ERROR_PARAM_ENTITY_REF", + XML_ERROR_UNDEFINED_ENTITY => "XML_ERROR_UNDEFINED_ENTITY", + XML_ERROR_RECURSIVE_ENTITY_REF => "XML_ERROR_RECURSIVE_ENTITY_REF", + XML_ERROR_ASYNC_ENTITY => "XML_ERROR_ASYNC_ENTITY", + XML_ERROR_BAD_CHAR_REF => "XML_ERROR_BAD_CHAR_REF", + XML_ERROR_BINARY_ENTITY_REF => "XML_ERROR_BINARY_ENTITY_REF", + XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF => "XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF", + XML_ERROR_MISPLACED_XML_PI => "XML_ERROR_MISPLACED_XML_PI", + XML_ERROR_UNKNOWN_ENCODING => "XML_ERROR_UNKNOWN_ENCODING", + XML_ERROR_INCORRECT_ENCODING => "XML_ERROR_INCORRECT_ENCODING", + XML_ERROR_UNCLOSED_CDATA_SECTION => "XML_ERROR_UNCLOSED_CDATA_SECTION", + XML_ERROR_EXTERNAL_ENTITY_HANDLING => "XML_ERROR_EXTERNAL_ENTITY_HANDLING", + ); + + /** + * XML parser constructor. + */ + function PHPTAL_XML_Parser() + { + $this->__construct(); + } + + /** + * XML parser php4.4 constructor. + */ + function __construct() + { + $this->_parser = xml_parser_create(); + xml_set_object($this->_parser, $this); + xml_set_element_handler($this->_parser, "_onElementStart", "_onElementClose"); + xml_set_character_data_handler($this->_parser, "_onElementData"); + xml_set_default_handler($this->_parser, "_onSpecific"); + xml_parser_set_option($this->_parser, XML_OPTION_CASE_FOLDING, 0); + } + + /** + * Parse specified data and call parser implementation of callback methods. + * + * @param data string Xml data to parse. + */ + function _parse($data, $eof=true) + { + $data = str_replace('&','&', $data); + if (!xml_parse($this->_parser, $data)) { + // PHPTAL errors first + if (PEAR::isError($this->_error)) { + return $this->_error; + } + // then look for parser errors + $err = xml_get_error_code($this->_parser); + return PEAR::raiseError($this->_xmlErrors[$err] + .' in '.$this->_file + .' around line '.$this->getLineNumber()); + } + if (PEAR::isError($this->_error)) { + return $this->_error; + } + return true; + } + + function parseString($data) + { + return $this->_parse($data, true); + } + + function parseFile($path) + { + $this->_file = $path; + $fp = @fopen($path, "r"); + if (!$fp) { + return PEAR::raiseError($php_errormsg); + } + while ($data = fread($fp, 1024)) { + $err = $this->_parse($data, feof($fp)); + if (PEAR::isError($err)) { + fclose($fp); + return $err; + } + } + fclose($fp); + } + + function _onElementStart($parser, $tag, $attributes) + { + if (PEAR::isError($this->_error)) return; + $this->_error = $this->onElementStart($tag, $attributes); + } + + function _onElementClose($parser, $tag) + { + if (PEAR::isError($this->_error)) return; + $this->_error = $this->onElementClose($tag); + } + + function _onElementData($parser, $data) + { + if (PEAR::isError($this->_error)) return; + $this->_error = $this->onElementData($data); + } + + function _onSpecific($parser, $data) + { + if (PEAR::isError($this->_error)) return; + $this->_error = $this->onSpecific($data); + } + + /** + * Return current parser line number. + * + * @return int + */ + function getLineNumber() + { + return xml_get_current_line_number($this->_parser); + } + + // + // ABSTRACT METHODS + // + + /** + * Abstract callback called when a new xml tag is opened. + * + * @param string tag Tag name + * @param hashtable attributes Associative array of attributes + */ + function onElementStart($tag, $attributes){} + + /** + * Abstract callback called when a tag is closed. + * + * @param string tag Tag name + */ + function onElementClose($tag){} + + /** + * Abstract callback called when some #cdata is found. + * + * @param string data Content + */ + function onElementData($data){} + + /** + * Abstract callback called when non tags entities appear in the document. + * + * This method is called by <% %> and other specific things like + * . + * + * @param string data strange data content. + */ + function onSpecific($data){} +} + +?> diff --git a/PHPTAL-NP-0.7.0/libs/Types.php b/PHPTAL-NP-0.7.0/libs/Types.php new file mode 100644 index 0000000000..a39bcf0b7c --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/Types.php @@ -0,0 +1,100 @@ + +// + +/** + * Static class used in common types internals. + * + * @static + * @author Laurent Bedubourg + */ +class Types +{ + /** + * Generate a string representation of specified variable. + * + * @param mixed $var -- variable to represent in a string form. + * @static + */ + function toString(&$var) + { + if (is_object($var)) { + return Types::_objToString($var); + } elseif (is_array($var)) { + if (array_key_exists(0, $var) || count($var) == 0) { + return Types::_arrayToString($var); + } else { + return Types::_hashToString($var); + } + } elseif (is_resource($var)) { + return '#'.gettype($var).'#'; + } + return $var; + } + + /** + * Generate a string representation of an object calling its toString + * method of using its class name. + * + * @access protected + * @static + */ + function _objToString(&$var) + { + if (method_exists($var, "toString")) { + return $var->toString(); + } else { + return '<' . get_class($var) . ' instance>'; + } + } + + /** + * Generate a string representation of a php array. + * + * @access protected + * @static + */ + function _arrayToString(&$var) + { + $values = array(); + foreach ($var as $val) { + $values[] = Types::toString($val); + } + return '[' . join(', ', $values) . ']'; + } + + /** + * Generate a string representation of an associative array. + * + * @access protected + * @static + */ + function _hashToString(&$var) + { + $values = array(); + foreach ($var as $key=>$val) { + $values[] = '\''. $key . '\': ' . Types::toString($val); + } + return '{' . join(', ', $values) . '}'; + } +} + +?> diff --git a/PHPTAL-NP-0.7.0/libs/Types/Code.php b/PHPTAL-NP-0.7.0/libs/Types/Code.php new file mode 100644 index 0000000000..a122229bb6 --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/Types/Code.php @@ -0,0 +1,219 @@ + +// +// $id$ + +require_once "Types/OString.php"; +require_once "Types/OHash.php"; + +/** + * Common php string that extract parameters from an associative array. + * + * This string is appended to the begin of the produced php function. It + * takes function context argument and extract it in named variables. + * + * @access private + */ +define('_TYPES_CODE_EXTRACT_CODE_CONTEXT_', +'// BEGIN EXTRACT __context__ +if (is_array($__context__)) { extract($__context__); } +if (is_object($__context__)) { extract($__context__->toHash()); } +// END EXTRACT __context__ +'); + +/** + * Code class handle and evaluate php code. + * + * The aim of this class is to dynamically generate executable php code from + * php string. + * + * This kind of object can be safely serialized as the code it represents is + * stored in the _code member variable. + * + * When setting code to this object, a new anonymous function is created + * waiting to be invoqued using the execute() method. + * + * As we can't know how many parameters this function should take, a 'context' + * hashtable is used as only parameter. This hash may contains any number + * of arguments with var name compliant keys. + * + * Code object automatically append 'extract' code string to produced code. + * + * It's up to the code to assert parameters using 'isset()' php function. + * + * setCode('return $foo . $bar . $baz;'); + * $res = $o_code->execute( + * 'foo', 'foo value ', + * 'baz', 'bar value ', + * 'baz', 'baz value' + * ); + * + * // will print 'foo value bar value baz value' + * echo $res, end; + * ?> + * + * @author Laurent Bedubourg + */ +class Code +{ + var $_code; + var $_function; + var $_compiled = false; + + /** + * Construct a new code object. + * + * @param mixed $code (optional) + * php code string or object implementing toString method. + */ + function Code($code=false) + { + $this->__construct($code); + } + + function __construct($code=false) + { + if (!$code) { + return $this; + } + if (is_object($code) && get_class($code) == 'code') { + $this->_code = $code->getCode(); + } else { + $this->setCode(Types::toString($code)); + } + } + + /** + * Execute code with specific context. + * + * @param mixed ... + * The function execution context. This may be an associative + * array, an OHash object, a list of key/value pairs that will + * be transformed into an associative array + * + * @return mixed The execution result. + */ + function &execute() + { + if (!$this->_compiled) { + $err =& $this->compile(); + if (PEAR::isError($err)) { + return $err; + } + } + $argv = func_get_args(); + $argc = func_num_args(); + switch ($argc) { + case 1: + $context = $argv[0]; + break; + default: + $context = OHash::ArrayToHash($argv); + break; + } + $func = $this->_function; + return $func($context); + } + + /** + * Compile php code. + * + * This function may produce parse errors. + * + * @throws CodeError + */ + function compile() + { + ob_start(); + $this->_function = create_function('$__context__', $this->_code); + $ret = ob_get_contents(); + ob_end_clean(); + + if (!$this->_function) { + return PEAR::raiseError($ret); + } + + $this->_compiled = true; + } + + /** + * Set function code. + * + * @param string $str + * The php code string + */ + function setCode($str) + { + // add extract code to function code + $str = _TYPES_CODE_EXTRACT_CODE_CONTEXT_ . $str; + $this->_code = $str; + } + + /** + * Retrieve code. + * + * @return string + */ + function getCode() + { + return $this->_code; + } + + /** + * On serialization, we store only code, not additional variables. + * + * @access private + */ + function __sleep() + { + return array("_code"); + } + + /** + * Make a string representation of this object. + * + * @return string + */ + function toString() + { + if ($this->_compiled) { + return '_function.'\'>'; + } else { + return ''; + } + } +} + +/** + * Code compilation error. + * + * This error handles parse errors an other problems that may occurs while + * compiling a php code. + */ +class CodeError extends PEAR_Error +{ +} + +?> diff --git a/PHPTAL-NP-0.7.0/libs/Types/Errors.php b/PHPTAL-NP-0.7.0/libs/Types/Errors.php new file mode 100644 index 0000000000..b15ee91bf6 --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/Types/Errors.php @@ -0,0 +1,30 @@ + diff --git a/PHPTAL-NP-0.7.0/libs/Types/Iterator.php b/PHPTAL-NP-0.7.0/libs/Types/Iterator.php new file mode 100644 index 0000000000..ef55e2874c --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/Types/Iterator.php @@ -0,0 +1,153 @@ + +// + +/** + * Iterable interface. + * + * An iterable object can produce Iterator(s) related to itself. + * + * @author Laurent Bedubourg + */ +class Iterable +{ + /** + * Retrieve iterable size. + */ + function size(){} + + /** + * Get an initialized iterator for this object. + */ + function &getNewIterator(){} +} + + +/** + * Iterator interface. + * + * This class provides common methods for Iterator objects. + * + * An iterator is a 'pointer' to a data item extracted from some collection of + * resources. + * + * The aim of Iterator is to allow some abstraction between your program + * resources and the way you fetch these resources. + * + * Thus, you can loop over a file content and later replace this file with a + * database backend whithout changing the program logic. + * + * @author Laurent Bedubourg + */ +class Iterator +{ + /** + * Reset iterator to first item. + * + * This method should throw an exception for once only iterators. + * + * @throws ResetFailed + */ + function reset() + { + return PEAR::raiseError('\'reset\' method not implemented'); + } + + /** + * Test if current item is not the end of iterator. + * + * @return boolean + */ + function isValid() + { + return PEAR::raiseError('\'isValid\' method not implemented'); + } + + /** + * Iterate on the next element and returns the next item. + * + * @return mixed (by reference) + */ + function &next() + { + return PEAR::raiseError('\'next\' method not implemented'); + } + + // ---------------------------------------------------------------------- + // getters + // ---------------------------------------------------------------------- + + /** + * Retrieve the current item index. + * + * @return int + */ + function index() + { + return PEAR::raiseError('\'index\' method not implemented'); + } + + /** + * Retrieve current item value. + * + * @return mixed (by reference) + */ + function &value() + { + return PEAR::raiseError('\'value\' method not implemented'); + } + + // ---------------------------------------------------------------------- + // optional methods + // ---------------------------------------------------------------------- + + /** + * (optional) Additional index for hashes. + * + * @return string + */ + function key() + { + return $this->index(); + } + + /** + * (optional) Remove the current value from container. + * + * Implement this method only when the iterator can do a secured remove + * without breaking other iterators works. + */ + function remove() + { + return PEAR::raiseError('\'remove\' method not implemented'); + } +} + +/** + * Exception thrown by iterators that can be reseted only once. + * + * @author Laurent Bedubourg + */ +class ResetFailed extends PEAR_Error +{ +} + +?> diff --git a/PHPTAL-NP-0.7.0/libs/Types/OArray.php b/PHPTAL-NP-0.7.0/libs/Types/OArray.php new file mode 100644 index 0000000000..5bb4577370 --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/Types/OArray.php @@ -0,0 +1,408 @@ + +// + +require_once "Types.php"; +require_once "Types/Errors.php"; +require_once "Types/Ref.php"; +require_once "Types/Iterator.php"; + +/** + * Class wrapper for oriented object arrays. + * + * This class implements a simple interface quite like java to handle array in + * a good old oo way. + * + * @author Laurent Bedubourg + */ +class OArray extends Iterable +{ + var $_array; + var $_size = 0; + + /** + * OArray constructor. + * + * @param array $array optional + * The php array this vector will manage. + */ + function OArray($array=array()) + { + $this->__construct($array); + } + + /** + * OArray php4.4 compliant constructor. + * + * @param array $array optional + * The php array this vector will manage. + */ + function __construct($array=array()) + { + $this->_array = array(); + for ($i = 0; $i < count($array); $i++) { + $this->pushRef($array[$i]); + } + } + + /** + * Retrieve an iterator ready to used. + * @return ArrayIterator + */ + function getNewIterator() + { + return new ArrayIterator($this); + } + + /** + * Returns the vector number of elements. + * @return int + */ + function size() + { + return count($this->_array); + } + + /** + * Returns true if this vector is empty, false otherwise. + * @return boolean + */ + function isEmpty() + { + return $this->size() == 0; + } + + /** + * Retrieve element at specified index. + * @return mixed + * @throws OutOfBounds + */ + function &get($i) + { + if ($i > $this->size() || $i < 0) { + $err = new OutOfBounds("OArray index out of bounds ($i)"); + // return EX::raise($err); + return PEAR::raiseError($err); + } + return $this->_array[$i]->obj; + } + + /** + * Retrieve index of specified element. + * + * @return int The element index of false if element not in vector. + */ + function indexOf($element) + { + for ($i=0; $i < count($this->_array); $i++) { + if ($this->_array[$i]->obj === $element) { + return $i; + } + } + return false; + } + + /** + * Set the item at specified index. + * + * @throws OutOfBounds if index is greated that vector limit + * @return Old element + */ + function &set($i, $item) + { + return $this->setRef($i, $item); + } + + /** + * Set the item at specified index (by reference). + * + * @throws OutOfBounds if index is greated that vector limit + * @return Old element + */ + function &setRef($i, &$item) + { + if ($i > $this->size() || $i < 0) { + $err = new OutOfBounds("OArray index out of bounds ($i)"); + // return EX::raise($err); + return PEAR::raiseError($err); + } + $temp = $this->_array[$i]; + $this->_array[$i] = Ref($item); + return $temp->obj; + } + + /** + * Test if the vector contains the specified element. + * + * @param mixed $item The item we look for. + */ + function contains($o) + { + for ($i = 0; $i < $this->size(); $i++) { + if ($this->_array[$i]->obj === $o) return true; + } + return false; + } + + /** + * Add an element to the vector. + * + * @param mixed $o The item to add. + */ + function add($o) + { + $this->push($o); + } + + /** + * Remove object from this vector. + * + * @param mixed $o Object to remove. + * @return boolean true if object removed false if not found + */ + function remove($o) + { + $i = $this->indexOf($o); + if ($i !== false) { + $this->removeIndex($i); + return true; + } + return false; + } + + /** + * Remove specified index from vector. + * + * @param int $i Index + * @throws OutOfBounds + */ + function removeIndex($i) + { + if ($i > $this->size() || $i < 0 ) { + $err = new OutOfBounds("OArray index out of bounds ($i)"); + // return EX::raise($err); + return PEAR::raiseError($err); + } + + // $this->_array = array_splice($this->_array, $i, 1); + array_splice($this->_array, $i, 1); + } + + /** + * Clear vector. + */ + function clear() + { + $this->_array = array(); + } + + /** + * Add an element at the end of the vector (same as add()). + * + * @param mixed $o Item to append to vector. + */ + function push($o) + { + array_push($this->_array, Ref($o)); + } + + /** + * Add an element at the end of the vector (same as add()). + * + * @param mixed $o Item to append to vector. + */ + function pushRef(&$o) + { + $this->_array[] = Ref($o); + } + + /** + * Retrieve vector values. + * + * The returned array contains references to internal data. + * + * @return array + */ + function &values() + { + $v = array(); + for ($i = 0; $i < $this->size(); $i++) { + $v[] =& $this->_array[$i]->obj; + } + return $v; + } + + /** + * Remove the last element of the vector and returns it. + * + * @return mixed + */ + function &pop() + { + $ref = array_pop($this->_array); + return $ref->obj; + } + + /** + * Extract and return first element of OArray. + * @return mixed + */ + function &shift() + { + $ref = array_shift($this->_array); + return$ $ref->obj; + } + + /** + * Retrieve a php array for this vector. + * + * @return array + */ + function &toArray() + { + return $this->values(); + } + + /** + * Retrieve a string representation of the array. + */ + function toString() + { + return Types::_arrayToString($this->values()); + } +}; + +/** + * OArray itertor class. + * + * This kind of iterators are used to walk throug a OArray object. + * + * @author Laurent Bedubourg + */ +class ArrayIterator extends Iterator +{ + var $_src; + var $_values; + var $_value; + var $_i; + + /** + * Iterator constructor. + * + * @param mixed $oarray OArray object or php array. + */ + function ArrayIterator(&$oarray) + { + return $this->__construct($oarray); + } + + /** + * PHP 4.4 compliant constructor. + * + * @param mixed $oarray OArray object or php array. + */ + function __construct(&$oarray) + { + if (is_array($oarray)) { + $this->_src = new OArray($oarray); + } else if (is_a($oarray, 'OArray')) { + $this->_src = &$oarray; + } else { + // ignore error, should throw a bad type error or something like + // that but pear does not handle errors in constructors yet + $err = new TypeError("ArrayIterator requires OArray object or php array.", + PEAR_ERROR_DIE); + // return EX::raise($err); + return PEAR::raiseError($err); + } + $this->reset(); + } + + /** + * Reset iterator to first array position. + */ + function reset() + { + $this->_i = 0; + $this->_end = false; + $this->_values = $this->_src->_array; + if (count($this->_values) == 0) { + $this->_end = true; + return; + } + + $this->_value = $this->_values[0]; + } + + /** + * Returns next vector item value. + * + * @return mixed + * @throws OutOfBounds if iterator overpass the vector size. + */ + function &next() + { + if ($this->_end || ++$this->_i >= count($this->_values)) { + $this->_end = true; + return null; + } + + $this->_value = $this->_values[$this->_i]; + return $this->_value->obj; + } + + /** + * Test if the iteractor has not reached its end. + * @return boolean + */ + function isValid() + { + return !$this->_end; + } + + /** + * Retrieve current iterator index. + * @return int + */ + function index() + { + return $this->_i; + } + + /** + * Retrieve the current iterator value. + * @return mixed + */ + function &value() + { + return $this->_value->obj; + } + + /** + * Delete current index. + */ + function remove() + { + $this->_src->remove($this->_value->obj); + } +} + +?> diff --git a/PHPTAL-NP-0.7.0/libs/Types/ODate.php b/PHPTAL-NP-0.7.0/libs/Types/ODate.php new file mode 100644 index 0000000000..c63f75d6df --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/Types/ODate.php @@ -0,0 +1,447 @@ + +// +// $id$ + +/** + * Generic date part format. + */ +define('TYPES_DATE_FMT_DATE', '%1$04s-%2$02s-%3$02s'); +/** + * French date part format. + */ +define('TYPES_DATE_FMT_DATE_FR', '%3$02s/%2$02s/%1$04s'); +/** + * Hours format. + */ +define('TYPES_DATA_FMT_HOUR', '%4$02s:%5$02s:%6$02s'); + +/** + * Simple date manipulation object. + * + * Note: + * ----- + * + * ODate::toString() can take a sprintf() format string as first parameter. + * + * @author Laurent Bedubourg + */ +class ODate +{ + var $_year = 0; + var $_month = 0; + var $_day = 0; + var $_hours = 0; + var $_minutes = 0; + var $_seconds = 0; + + /** + * ODate constructor. + * + * This constructor is for php v4.4 compliance. + * + * @param int $y optional -- year + * @param int $mt optional -- month + * @param int $d optional -- day + * @param int $h optional -- hour + * @param int $m optional -- minutes + * @param int $s optional -- seconds + */ + function __construct($y=0, $mt=0, $d=0, + $h=0, $m=0, $s=0) + { + $this->setYear($y); + $this->setMonth($mt); + $this->setDay($d); + $this->setHours($h); + $this->setMinutes($m); + $this->setSeconds($s); + } + + /** + * ODate constructor. + * + * @param int $y optional -- year + * @param int $mt optional -- month + * @param int $d optional -- day + * @param int $h optional -- hour + * @param int $m optional -- minutes + * @param int $s optional -- seconds + */ + function ODate($y=0, $mt=0, $d=0, + $h=0, $m=0, $s=0) + { + $this->__construct($y, $mt, $d, $h, $m, $s); + } + + /** + * Add a date to current date. + */ + function add($date) + { + $this->inc($date->getYear(), + $date->getMonth(), + $date->getDay(), + $date->getHours(), + $date->getMinutes(), + $date->getSeconds()); + } + + /** + * Add values to this date. + * + * @param int $y optional -- year + * @param int $mt optional -- month + * @param int $d optional -- day + * @param int $h optional -- hour + * @param int $m optional -- minutes + * @param int $s optional -- seconds + */ + function inc($y,$mt,$d,$h,$m,$s) + { + $this->addSeconds($s); + $this->addMinutes($m); + $this->addHours($h); + $this->addDays($d); + $this->addMonths($mt); + $this->addYears($y); + } + + /** + * Set date part. + * + * @param int $y -- year + * @param int $mt -- month + * @param int $d -- day + */ + function setDate($y,$m,$d) + { + $this->setYear($y); + $this->setMonth($m); + $this->setDay($d); + } + + /** + * Set time part. + * + * @param int $h -- hour + * @param int $m -- minutes + * @param int $s -- seconds + */ + function setTime($y,$m,$d) + { + $this->setHours($h); + $this->setMinutes($m); + $this->setSeconds($s); + } + + /** + * Add some years to this date. + * + * @param int $y -- year + */ + function addYears($y) + { + $this->_year += $y; + } + + /** + * Add some months to this date. + * + * @param int $m -- month + */ + function addMonths($m) + { + $this->_month += $m; + if ($this->_month > 12) { + $this->addYears($this->_month / 12); + $this->_month = $this->_month % 12; + } + } + + /** + * Add some days to this date. + * + * @param int $d -- days + */ + function addDays($d) + { + $m = 0; + $this->_day += $d; + $m = $this->numberOfMonthDays(); + while ($this->_day > $m) { + $this->addMonths(1); + $this->_day -= $m; + $m = $this->numberOfMonthDays(); + } + } + + /** + * Add some hours to this date. + * + * @param int $h -- hours + */ + function addHours($h) + { + $this->_hours += $h; + if ($this->_hours >= 24) { + $this->addDays($this->_hours / 24); + $this->_hours = $this->_hours % 24; + } + } + + /** + * Add minutes to this date. + * + * @param int $m -- minutes + */ + function addMinutes($m) + { + $this->_minutes += $m; + if ($this->_minutes >= 60) { + $this->addHours($this->_minutes / 60); + $this->_minutes = $this->_minutes % 60; + } + } + + /** + * Add seconds to this date. + * + * @param int $s -- seconds + */ + function addSeconds($s) + { + $this->_seconds += $s; + if ($this->_seconds >= 60) { + $this->addMinutes($this->_seconds / 60); + $this->_seconds = $this->_seconds % 60; + } + } + + /** + * Return true if bissextile year. + * + * @return boolean + */ + function isBissextile() + { + if ($this->_year % 400 == 0) return true; + if ($this->_year % 100 == 0) return false; + if ($this->_year % 4 == 0) return true; + return false; + } + + /** + * Get the number of days in current month + * + * @return int + */ + function numberOfMonthDays() + { + if ($this->_month == 2 && $this->isBissextile()) { + return 29; + } + $DOM = array(-1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31); + return $DOM[$this->_month]; + } + + /** + * Set now time values to this object. + */ + function setNow() + { + $d = getdate(); + $this->setSeconds($d['seconds']); + $this->setMinutes($d['minutes']); + $this->setHours($d['hours']); + $this->setDay($d['mday']); + $this->setMonth($d['mon']); + $this->setYear($d['year']); + } + + /** + * Ensure that date is correct. + */ + function cleanup() + { + $this->add(0,0,0,0,0,0); + } + + /** + * Compare with another date, return < 0 if less, == 0 if equals, > 0 if + * greater. + * + * @param ODate $date -- date to compare with + * + * @return int (strcmp) + */ + function compare($date) + { + return strcmp($this->toNumericString(), + $date->toNumericString()); + } + + /** + * Return a concatenation of date fields (numeric date). + * + * @return string + */ + function toNumericString() + { + return (int)"$this->_year$this->_month$this->_day". + "$this->_hours$this->_minutes$this->_seconds"; + } + + /** + * Simple date format. + * + * @param string $format optional + * Format to pass to sprintf (ex:"%04d-%02d-%02d %02d:%02d:%02d") + * + * @return string + */ + function toString($format="%04d-%02d-%02d %02d:%02d:%02d") + { + $this->cleanup(); + return sprintf($format, + $this->_year, + $this->_month, + $this->_day, + $this->_hours, + $this->_minutes, + $this->_seconds); + } + + + // + // OTHER GETTER SETTERS + // + + /** + * Retrieve year. + * @return int + */ + function getYear() + { + return $this->_year; + } + + /** + * Retrieve month. + * @return int + */ + function getMonth() + { + return $this->_month; + } + + /** + * Retrieve day. + * @return int + */ + function getDay() + { + return $this->_day; + } + + /** + * Retrieve hour. + * @return int + */ + function getHours() + { + return $this->_hours; + } + + /** + * Retrieve minutes. + * @return int + */ + function getMinutes() + { + return $this->_minutes; + } + + /** + * Retrieve seconds. + * @return int + */ + function getSeconds() + { + return $this->_seconds; + } + + /** + * Set year. + * @param int $y -- year + */ + function setYear($y) + { + $this->_year = $y; + } + + /** + * Set month. + * @param int $m -- month + */ + function setMonth($m) + { + $this->_month = $m; + } + + /** + * Set day. + * @param int $d -- day + */ + function setDay($d) + { + $this->_day = $d; + } + + /** + * Set hours. + * @param int $h -- hours + */ + function setHours($h) + { + $this->_hours = $h; + } + + /** + * Set minutes. + * @param int $m -- minutes + */ + function setMinutes($m) + { + $this->_minutes = $m; + } + + /** + * Set seconds. + * @param int $s -- seconds + */ + function setSeconds($s) + { + $this->_seconds = $s; + } +} + +?> diff --git a/PHPTAL-NP-0.7.0/libs/Types/OHash.php b/PHPTAL-NP-0.7.0/libs/Types/OHash.php new file mode 100644 index 0000000000..53b0a757bb --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/Types/OHash.php @@ -0,0 +1,451 @@ + +// + +require_once "Types.php"; +require_once "Types/Errors.php"; +require_once "Types/Ref.php"; + +/** + * Wrapper for oriented object associative arrays. + * + * This class implements a simple interface quite like java to handle + * associatives arrays (Hashtables). + * + * Note: + * + * Some problems may occurs with object references until php4.4 to avoid + * unwanted object copy, use setRef() method with objects or pass Ref objects + * to set(). + * + * @author Laurent Bedubourg + */ +class OHash +{ + var $_hash; + + /** + * OHash constructor. + * + * php4.4 compliant constructor + * + * @param array $array optional -- An associative php array + */ + function __construct($array=array()) + { + $this->_hash = array(); + $keys = array_keys($array); + foreach ($keys as $key) { + $this->_hash[$key] = ref($array[$key]); + } + } + + /** + * OHash constructor. + * + * php4.4 compliant constructor + * + * @param array $array optional -- An associative php array + */ + function OHash($array=array()) + { + $this->__construct($array); + } + + /** + * Set a value in this hash. + * + * @param string $key + * @param string $value + */ + function set($key, $value) + { + $this->_hash[$key] = ref($value); + } + + /** + * Reference set. + * + * Until php4.4, it's the only way to avoid object/variable copy. + * + * @param string $key + * @param reference $value + */ + function setRef($key, &$value) + { + $this->_hash[$key] = ref($value); + } + + /** + * Set a map of values. + * + * @param mixed $hash An Hash object or an associative php array. + */ + function setAll($hash) + { + if (!is_array($hash) && is_a($hash, 'OHash')) { + $hash = $hash->toHash(); + } + $keys = array_keys($hash); + foreach ($keys as $key) { + $this->_hash[$key] = ref($hash[$key]); + } + } + + /** + * Retrieve value associated to specified key. + * + * @param string $key + * @return reference + */ + function &get($key) + { + if ($this->containsKey($key)) { + return $this->_hash[$key]->obj; + } + return null; + } + + /** + * Remove element associated to specified key from hash. + * + * @param string $key + */ + function remove($key) + { + $keys = $this->keys(); + $i = array_search($key, $keys); + if ($i !== false) { + // unset hash element to fix many bugs that should appear while + // iterating and using references to this element. + unset($this->_hash[$key]); + // return array_splice($this->_hash, $i, 1); + } + } + + /** + * Remove an element from the Hash. + * + * @param mixed $o -- Element to remove from Hash + */ + function removeElement(&$o) + { + $i = 0; + $found = false; + foreach ($this->_hash as $key => $value) { + if ($value->obj === $o || $value == $o) { + $found = $i; + break; + } + $i++; + } + if ($found !== false) { + return array_splice($this->_hash, $found, 1); + } + } + + /** + * Returns true is hashtable empty. + * + * @return boolean + */ + function isEmpty() + { + return $this->size() == 0; + } + + /** + * Retrieve hash size (number of elements). + * + * @return int + */ + function size() + { + return count($this->_hash); + } + + /** + * Retrieve hash values array. + * + * @return hashtable + */ + function &values() + { + $v = array(); + foreach ($this->_hash as $key => $ref) { + $v[] =& $ref->obj; + } + return $v; + } + + /** + * Retrieve hash keys array. + * + * @return array + */ + function keys() + { + return array_keys($this->_hash); + } + + /** + * Retrieve an hash iterator ready to use. + * + * @return HashIterator + */ + function getNewIterator() + { + return new HashIterator($this); + } + + /** + * Test if this hash contains specified key. + * + * @param string $key + * @return boolean + */ + function containsKey($key) + { + return array_key_exists($key, $this->_hash); + } + + /** + * Test if this hash contains specified value. + * + * @param mixed $value -- The value to search + * @return boolean + */ + function containsValue($value) + { + foreach ($this->_hash as $k => $v) { + if ($v->obj === $value || $v == $value) { + return true; + } + } + return false; + } + + /** + * Returns the php array (hashtable) handled by this object. + * + * @return hashtable + */ + function &toHash() + { + $result = array(); + foreach ($this->_hash as $key => $value) { + $result[$key] =& $value->obj; + } + return $result; + } + + /** + * Create an Hash object from a simple php array variable. + * + * This method assumes that the array is composed of serial key, value + * elements. For each pair of array element, the former will be used as key + * and the latter as value. + * + * @param array $array -- php array. + * + * @return Hash + * @static 1 + */ + function ArrayToHash($array) + { + $h = new OHash(); + while (count($array) > 1) { + $key = array_shift($array); + $h->set($key, array_shift($array)); + } + return $h; + } + + /** + * Generate and return a string representation of this hashtable. + * + * @return string + */ + function toString() + { + return Types::_hashToString($this->toHash()); + } + + /** + * Sort hashtable on its keys. + */ + function sort() + { + ksort($this->_hash); + } +} + + +/** + * Hash iterator. + * + * This kind of iterators are used to walk throug Hash objects. + * + * @author Laurent Bedubourg + */ +class HashIterator +{ + var $_src; + var $_values; + var $_keys; + var $_key; + var $_value; + var $_i = -1; + var $_end = false; + + /** + * Iterator constructor. + * + * @param mixed $hash -- OHash object or associative php array. + */ + function HashIterator(&$hash) + { + return $this->__construct($hash); + } + + /** + * Iterator php4.4 compliant constructor. + * + * @param mixed $hash -- OHash object or associative php array. + * + * @throws TypeError + * When $hash is not an array or an Hash object. + */ + function __construct(&$hash) + { + if (is_array($hash)) { + $this->_src = new OHash($hash); + } else if (is_a($hash, 'ohash')) { + $this->_src = &$hash; + } else { + $err = new TypeError('HashIterator requires associative array or OHash'); + // return EX::raise($err); + die($err->toString()); + return PEAR::raiseError($err); + } + $this->reset(); + } + + // + // iterator logics + // + + /** + * Reset iterator to first element. + */ + function reset() + { + // store a copy of hash references so a modification of source data + // won't affect iterator. + $this->_values = $this->_src->_hash; + $this->_keys = $this->_src->keys(); + + if (count($this->_keys) == 0) { + $this->_end = true; + return; + } + + $this->_i = 0; + $this->_end = false; + $this->_key = $this->_keys[0]; + $this->_value = $this->_values[$this->_key]; + } + + /** + * Test is end of iterator is not reached. + */ + function isValid() + { + return !$this->_end; + } + + /** + * Return next Hash item. + * + * This method also set _key and _value. + * + * @return mixed (by reference) or false if end reached + */ + function &next() + { + if ($this->_end || ++$this->_i >= count($this->_keys)){ + $this->_end = true; + return null; + } + + $this->_key = $this->_keys[$this->_i]; + $this->_value = $this->_values[$this->_key]; + return $this->_value->obj; + } + + // + // getters + // + + /** + * Return current iterator key. + * + * @return string + */ + function key() + { + return $this->_key; + } + + /** + * Return current index (position in iteration). + * + * @return int + */ + function index() + { + return $this->_i; + } + + /** + * Return current iterator value. + * + * @return mixed + */ + function &value() + { + return $this->_value->obj; + } + + // + // optional implementations + // + + /** + * Remove current iterated item from source. + */ + function remove() + { + $this->_src->remove($this->_key); + } +} + +?> diff --git a/PHPTAL-NP-0.7.0/libs/Types/OString.php b/PHPTAL-NP-0.7.0/libs/Types/OString.php new file mode 100644 index 0000000000..b3345dbedb --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/Types/OString.php @@ -0,0 +1,473 @@ + +// + + +require_once "Types.php"; +require_once "Types/Errors.php"; + +/** + * Represents end of line string sequence '\n' of '
' depending on + * script context. + */ +if (!defined('endl')) { + if (isset($GLOBALS['REQUEST_URI'])) { + define('endl', "
\n"); + } else { + define('endl', "\n"); + } +} + +/** + * Object String wrapper class. + * + * This class is an attempt to normalize php strings in an oo way. + * + * PHP string related functions have different arguments scheme that decrease + * code readability in OO programs. This class provides some php functions + * in a comprehensible String class. + * + * The second interest reside in the StringIterator class which normalize + * iteration over strings just like any other iterable object. + * + * @author Laurent Bedubourg + */ +class OString +{ + var $_str; + + /** + * String constructor. + * + * @param mixed $str + * May be an object from a class implementing the + * 'toString()' method or a php variable that can be + * casted into a string. + */ + function OString($str="") + { + return $this->__construct($str); + } + + /** + * String php4.4 constructor. + * + * @param mixed $str + * May be an object from a class implementing the + * 'toString()' method or a php variable that can be + * casted into a string. + * + * @throws TypeError + */ + function __construct($str="") + { + if (is_object($str)) { + if (!method_exists($str, "toString")) { + $err = new TypeError('String constructor requires string or ' + . ' object implementing toString() method.', + PEAR_ERROR_DIE); + // return EX::raise($err); + return PEAR::raiseError($err); + } + $this->_str = $str->toString(); + } else { + $this->_str = $str; + } + } + + /** + * Append string values of arguments to this string. + * + * @param mixed ... + * php variables or objects implementing the toString() + * method. + */ + function append() + { + $args = func_get_args(); + foreach ($args as $arg) { + if (is_object($arg)) { + $this->_str .= $arg->toString(); + } else { + $this->_str .= $arg; + } + } + } + + /** + * Retrieve char at specified position. + * + * @param int $i Character position + * @return char + */ + function charAt($i) + { + return $this->_str[$i]; + } + + /** + * Find first index of needle in current string. + * + * Return the first position of needle in string or *false* if + * not found. + * + * @param mixed $needle object implementing toString or php variable. + * @param int $pos Search start position + * @return int + */ + function indexOf($needle, $pos=0) + { + if (is_object($needle)) { $needle = $needle->toString(); } + return strpos($this->_str, $needle, $pos); + } + + /** + * Find last occurence of needle in current string. + * + * Returns the last position of needle in string or *false* if + * not found. + * + * @param mixed needle object implementing toString or php variable. + * @return int + */ + function lastIndexOf($needle) + { + if (is_object($needle)) { $needle = $needle->toString(); } + return strrpos($this->_str, $needle); + } + + /** + * Returns true if the string match the specified regex. + * + * @param mixed $regex object implementing toString or php string. + * @return boolean + */ + function matches($regex) + { + if (is_object($regex)) { $regex = $regex->toString(); } + return preg_match($regex, $this->_str); + } + + /** + * Returns true if the string contains specified substring. + * + * @param mixed $str object implementing toString or php string. + * @return boolean + */ + function contains($str) + { + if (is_object($str)){ $str = $str->toString(); } + return (strpos($this->_str, $str) !== false); + } + + /** + * Returns true if the string begins with specified token. + * + * @param mixed $str object implementing toString or php string. + * @return boolean + */ + function startsWith($str) + { + if (is_object($str)){ $str = $str->toString(); } + return preg_match('|^'. preg_quote($str) . '|', $this->_str); + } + + /** + * Returns true if the string ends with specified token. + * + * @param mixed $str object implementing toString or php string. + * @return boolean + */ + function endsWith($str) + { + if (is_object($str)){ $str = $str->toString(); } + return preg_match('|'. preg_quote($str) . '$|', $this->_str); + } + + /** + * Replace occurences of 'old' with 'new'. + * + * @param mixed $old token to replace + * @param mixed $new new token + * @return string + */ + function replace($old, $new) + { + if (is_object($old)){ $old = $old->toString(); } + if (is_object($new)){ $new = $new->toString(); } + return str_replace($old, $new, $this->_str); + } + + /** + * Split this string using specified separator. + * + * @param mixed $sep Separator token + * + * @return array of phpstrings + */ + function split($sep) + { + if (is_object($sep)){ $sep = $sep->toString(); } + return split($sep, $this->_str); + } + + /** + * Retrieve a sub string. + * + * @param int $start + * start offset + * + * @param int $end + * End offset (up to end if no specified) + * + * @return string + */ + function substr($start, $end=false) + { + if ($end === false){ return substr($this->_str, $start); } + return substr($this->_str, $start, ($end-$start)); + } + + /** + * Retrieve a sub string giving its length. + * + * @param int $start + * start offset + * + * @param int $length + * length from the start offset + * + * @return string + */ + function extract($start, $length) + { + return substr($this->_str, $start, $length); + } + + /** + * Return this string lower cased. + * @return string + */ + function toLowerCase() + { + return strtolower($this->_str); + } + + /** + * Return this string upper cased. + * @return string + */ + function toUpperCase() + { + return strtoupper($this->_str); + } + + /** + * Remove white characters from the beginning and the end of the string. + * @return string + */ + function trim() + { + return trim($this->_str); + } + + /** + * Test if this string equals specified object. + * + * @param mixed $o + * php string or object implementing the toString() method. + * @return boolean + */ + function equals($o) + { + if (is_object($o)) { + return $this->_str == $str->toString(); + } else { + return $this->_str == $o; + } + } + + /** + * Return the length of this string. + * @return int + */ + function length() + { + return strlen($this->_str); + } + + /** + * Return the php string handled by this object + * @return string + */ + function toString() + { + return $this->_str; + } + + /** + * Create a string iterator for this String object. + * + * StringIterators iterate at a character level. + * + * @return StringIterator + */ + function &getNewIterator() + { + return new StringIterator($this); + } +} + +/** + * String buffer class. + * + * This class represents a buffer that concatenate appended string or objects + * into a simple php string. + * + * @author Laurent Bedubourg + */ +class StringBuffer extends OString +{ + /** + * Append some elements to the buffer with an endl terminator. + * + * @param mixed ... + * List of php variables and/or objects implementing the + * toString() method. + */ + function appendln() + { + $args = func_get_args(); + foreach ($args as $arg) { + if (is_object($arg)) { + $this->_str .= $arg->toString(); + } else { + $this->_str .= $arg; + } + } + $this->_str .= endl; + } +} + +/** + * Iterator for php strings and objects implementing toString method. + * + * @author Laurent Bedubourg + */ +class StringIterator +{ + var $_str; + var $_index = -1; + var $_end = false; + var $_value; + + /** + * Constructor a string iterator. + * + * @param mixed $str + * String object, string variable, or Object implementing + * the toString() method. + */ + function StringIterator(&$str) + { + $this->__construct($str); + } + + /** + * Constructor a string iterator. + * + * @param mixed $str + * object implementing toString or php string variable + */ + function __construct(&$str) + { + if (is_object($str)) { + $this->_string = new OString($str->toString()); + } else if (is_string($str)) { + $this->_string = new OString($str); + } + $this->reset(); + } + + /** + * Reset iterator to the begining of the string. + * + * If empty string, this iterator assume it is at the end of string. + */ + function reset() + { + $this->_end = false; + $this->_index = 0; + if ($this->_string->length() == 0) { + $this->_end = true; + } else { + $this->_value = $this->_string->charAt(0); + } + } + + /** + * Return next character. + * + * @return char + */ + function next() + { + if ($this->_end || ++$this->_index >= $this->_string->length()) { + $this->_end = true; + return null; + } + + $this->_value = $this->_string->charAt($this->_index); + return $this->_value; + } + + /** + * Return true if the end of the string is not reached yet. + * + * @return boolean + */ + function isValid() + { + return !$this->_end; + } + + /** + * Retrieve current iterator index. + * + * @return int + */ + function index() + { + return $this->_index; + } + + /** + * Retrieve current iterator value. + * + * @return char + */ + function value() + { + return $this->_value; + } +} + +?> diff --git a/PHPTAL-NP-0.7.0/libs/Types/Ref.php b/PHPTAL-NP-0.7.0/libs/Types/Ref.php new file mode 100644 index 0000000000..0f81dc762d --- /dev/null +++ b/PHPTAL-NP-0.7.0/libs/Types/Ref.php @@ -0,0 +1,145 @@ + +// + +/** + * Create a new Ref object referencing specified object or variable. + * + * Any modification of the source object modify the Refence content, any + * modification of the reference obj modify the source object. + * + * The referenced object can be reached using the reference object using the + * 'obj' property. + * + * obj->doBar(); // call doBar() on $a + * + * ?> + * + * @param mixed $obj -- the object or variable to reference. + * @return Ref + */ +function ref(&$obj) +{ + return new Ref($obj); +} + +/** + * Returns true if the object is a Ref object. + * + * @param mixed $obj -- any variable that must be tested. + * + * @return boolean + */ +function is_ref($obj) +{ + return is_object($obj) && get_class($obj) == "ref"; +} + + +/** + * Reference class. + * + * There's a lot to say about references in PHP. The main problem come from the + * fact that until ZendEngine2, objects are copied if not referenced. + * + * This class helps keeping references to objects even while modifying arrays. + * + * Example : + * + * If an array stores objects, using array_values will copy its + * elements. + * + * If an array stores Ref objects referencing real objects, array_values copy + * Ref objects but these copies still reference the source object. + * + * Until ZendEngine2, it is safer to use Ref objects in stead of object + * references. + * + * push(Ref($a)); + * + * ?> + * + * Important : + * + * This object will have no meaning in php 4.4 as PHP will then use references + * everywhere objects are involved. + * + * @author Laurent Bedubourg + */ +class Ref +{ + /** + * php reference to data. + */ + var $obj; + + /** + * Reference constructor. + * + * Important: + * + * If $r is a reference, the new reference will just be a copy of the + * parameter. + * + * A Ref cannot reference a Ref. + * + * @param mixed $r -- the object or data to reference. + */ + function Ref(&$r) + { + if (is_ref($r)) { + $this->obj =& $r->obj; + } else { + $this->obj =& $r; + } + } + + /** + * Retrieve the type or the referenced variable. + * + * @return string + */ + function type() + { + return gettype($this->obj); + } + + /** + * Return the class name of the referenced variable (if object). + * + * @return string (empty if not an object) + */ + function getClassName() + { + return get_class($this->obj); + } +} + +?> -- 2.20.1