Version Description
12/12/2016
* Plugin released for beta testing
=
Download this release
Release Info
Developer | amazonlinkbuilder |
Plugin | Amazon Associates Link Builder |
Version | 1.0 |
Comparing to | |
See all releases |
Version 1.0
- COPYING.txt +286 -0
- NOTICE.txt +77 -0
- aalb_admin_item_search_items.hbs +15 -0
- aalb_config.php +221 -0
- admin/aalb_admin.php +166 -0
- admin/css/aalb_admin.css +369 -0
- admin/js/aalb_admin.js +336 -0
- admin/partials/aalb_meta_box.php +91 -0
- admin/sidebar/aalb_sidebar.php +129 -0
- admin/sidebar/js/aalb_credentials.js +54 -0
- admin/sidebar/js/aalb_template.js +88 -0
- admin/sidebar/partials/aalb_about.php +141 -0
- admin/sidebar/partials/aalb_admin_ui_common.php +27 -0
- admin/sidebar/partials/aalb_credentials.php +115 -0
- admin/sidebar/partials/aalb_templates.php +191 -0
- admin/sidebar/partials/aalb_ui_common.php +33 -0
- amazon-associates-link-builder.php +112 -0
- bin/install-wp-tests.sh +118 -0
- css/aalb_basics.css +83 -0
- includes/aalb_activator.php +93 -0
- includes/aalb_autoloader.php +69 -0
- includes/aalb_cache_loader.php +85 -0
- includes/aalb_cache_template_loader.php +50 -0
- includes/aalb_config_loader.php +72 -0
- includes/aalb_deactivator.php +60 -0
- includes/aalb_helper.php +166 -0
- includes/aalb_hook_loader.php +82 -0
- includes/aalb_manager.php +79 -0
- includes/aalb_remote_loader.php +89 -0
- includes/aalb_template_engine.php +128 -0
- lib/js/jssha2/license.txt +25 -0
- lib/js/jssha2/sha2.js +144 -0
- lib/php/Mustache/Autoloader.php +74 -0
- lib/php/Mustache/Cache.php +36 -0
- lib/php/Mustache/Cache/AbstractCache.php +60 -0
- lib/php/Mustache/Cache/FilesystemCache.php +155 -0
- lib/php/Mustache/Cache/NoopCache.php +47 -0
- lib/php/Mustache/Compiler.php +684 -0
- lib/php/Mustache/Context.php +242 -0
- lib/php/Mustache/Engine.php +787 -0
- lib/php/Mustache/Exception.php +18 -0
- lib/php/Mustache/Exception/InvalidArgumentException.php +18 -0
- lib/php/Mustache/Exception/LogicException.php +18 -0
- lib/php/Mustache/Exception/RuntimeException.php +18 -0
- lib/php/Mustache/Exception/SyntaxException.php +36 -0
- lib/php/Mustache/Exception/UnknownFilterException.php +32 -0
- lib/php/Mustache/Exception/UnknownHelperException.php +32 -0
- lib/php/Mustache/Exception/UnknownTemplateException.php +32 -0
- lib/php/Mustache/HelperCollection.php +172 -0
- lib/php/Mustache/LICENSE +21 -0
- lib/php/Mustache/LambdaHelper.php +76 -0
- lib/php/Mustache/Loader.php +27 -0
- lib/php/Mustache/Loader/ArrayLoader.php +79 -0
- lib/php/Mustache/Loader/CascadingLoader.php +69 -0
- lib/php/Mustache/Loader/FilesystemLoader.php +124 -0
- lib/php/Mustache/Loader/InlineLoader.php +123 -0
- lib/php/Mustache/Loader/MutableLoader.php +31 -0
- lib/php/Mustache/Loader/StringLoader.php +39 -0
- lib/php/Mustache/Logger.php +126 -0
- lib/php/Mustache/Logger/AbstractLogger.php +121 -0
- lib/php/Mustache/Logger/StreamLogger.php +194 -0
- lib/php/Mustache/Parser.php +317 -0
- lib/php/Mustache/Template.php +180 -0
- lib/php/Mustache/Tokenizer.php +322 -0
- lib/php/Paapi/aalb_paapi_helper.php +131 -0
- lib/php/aalb_internationalization_helper.php +84 -0
- lib/php/aalb_tracking_api_helper.php +120 -0
- lib/php/aalb_validation_helper.php +97 -0
- lib/php/aalb_xml_helper.php +246 -0
- readme.txt +110 -0
- shortcode/aalb_shortcode.php +240 -0
- shortcode/aalb_shortcode_loader.php +74 -0
- template/PriceLink.css +0 -0
- template/PriceLink.mustache +7 -0
- template/ProductAd.css +229 -0
- template/ProductAd.mustache +141 -0
- template/ProductCarousel.css +230 -0
- template/ProductCarousel.mustache +142 -0
- template/ProductGrid.css +230 -0
- template/ProductGrid.mustache +144 -0
COPYING.txt
ADDED
@@ -0,0 +1,286 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
GNU GENERAL PUBLIC LICENSE
|
2 |
+
Version 2, June 1991
|
3 |
+
|
4 |
+
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
5 |
+
51 Franklin St, Fifth Floor, Boston, MA 02110, USA
|
6 |
+
|
7 |
+
Everyone is permitted to copy and distribute verbatim copies
|
8 |
+
of this license document, but changing it is not allowed.
|
9 |
+
|
10 |
+
Preamble
|
11 |
+
|
12 |
+
The licenses for most software are designed to take away your
|
13 |
+
freedom to share and change it. By contrast, the GNU General Public
|
14 |
+
License is intended to guarantee your freedom to share and change free
|
15 |
+
software--to make sure the software is free for all its users. This
|
16 |
+
General Public License applies to most of the Free Software
|
17 |
+
Foundation's software and to any other program whose authors commit to
|
18 |
+
using it. (Some other Free Software Foundation software is covered by
|
19 |
+
the GNU Library General Public License instead.) You can apply it to
|
20 |
+
your programs, too.
|
21 |
+
|
22 |
+
When we speak of free software, we are referring to freedom, not
|
23 |
+
price. Our General Public Licenses are designed to make sure that you
|
24 |
+
have the freedom to distribute copies of free software (and charge for
|
25 |
+
this service if you wish), that you receive source code or can get it
|
26 |
+
if you want it, that you can change the software or use pieces of it
|
27 |
+
in new free programs; and that you know you can do these things.
|
28 |
+
|
29 |
+
To protect your rights, we need to make restrictions that forbid
|
30 |
+
anyone to deny you these rights or to ask you to surrender the rights.
|
31 |
+
These restrictions translate to certain responsibilities for you if you
|
32 |
+
distribute copies of the software, or if you modify it.
|
33 |
+
|
34 |
+
For example, if you distribute copies of such a program, whether
|
35 |
+
gratis or for a fee, you must give the recipients all the rights that
|
36 |
+
you have. You must make sure that they, too, receive or can get the
|
37 |
+
source code. And you must show them these terms so they know their
|
38 |
+
rights.
|
39 |
+
|
40 |
+
We protect your rights with two steps: (1) copyright the software, and
|
41 |
+
(2) offer you this license which gives you legal permission to copy,
|
42 |
+
distribute and/or modify the software.
|
43 |
+
|
44 |
+
Also, for each author's protection and ours, we want to make certain
|
45 |
+
that everyone understands that there is no warranty for this free
|
46 |
+
software. If the software is modified by someone else and passed on, we
|
47 |
+
want its recipients to know that what they have is not the original, so
|
48 |
+
that any problems introduced by others will not reflect on the original
|
49 |
+
authors' reputations.
|
50 |
+
|
51 |
+
Finally, any free program is threatened constantly by software
|
52 |
+
patents. We wish to avoid the danger that redistributors of a free
|
53 |
+
program will individually obtain patent licenses, in effect making the
|
54 |
+
program proprietary. To prevent this, we have made it clear that any
|
55 |
+
patent must be licensed for everyone's free use or not licensed at all.
|
56 |
+
|
57 |
+
The precise terms and conditions for copying, distribution and
|
58 |
+
modification follow.
|
59 |
+
|
60 |
+
GNU GENERAL PUBLIC LICENSE
|
61 |
+
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
62 |
+
|
63 |
+
0. This License applies to any program or other work which contains
|
64 |
+
a notice placed by the copyright holder saying it may be distributed
|
65 |
+
under the terms of this General Public License. The "Program", below,
|
66 |
+
refers to any such program or work, and a "work based on the Program"
|
67 |
+
means either the Program or any derivative work under copyright law:
|
68 |
+
that is to say, a work containing the Program or a portion of it,
|
69 |
+
either verbatim or with modifications and/or translated into another
|
70 |
+
language. (Hereinafter, translation is included without limitation in
|
71 |
+
the term "modification".) Each licensee is addressed as "you".
|
72 |
+
|
73 |
+
Activities other than copying, distribution and modification are not
|
74 |
+
covered by this License; they are outside its scope. The act of
|
75 |
+
running the Program is not restricted, and the output from the Program
|
76 |
+
is covered only if its contents constitute a work based on the
|
77 |
+
Program (independent of having been made by running the Program).
|
78 |
+
Whether that is true depends on what the Program does.
|
79 |
+
|
80 |
+
1. You may copy and distribute verbatim copies of the Program's
|
81 |
+
source code as you receive it, in any medium, provided that you
|
82 |
+
conspicuously and appropriately publish on each copy an appropriate
|
83 |
+
copyright notice and disclaimer of warranty; keep intact all the
|
84 |
+
notices that refer to this License and to the absence of any warranty;
|
85 |
+
and give any other recipients of the Program a copy of this License
|
86 |
+
along with the Program.
|
87 |
+
|
88 |
+
You may charge a fee for the physical act of transferring a copy, and
|
89 |
+
you may at your option offer warranty protection in exchange for a fee.
|
90 |
+
|
91 |
+
2. You may modify your copy or copies of the Program or any portion
|
92 |
+
of it, thus forming a work based on the Program, and copy and
|
93 |
+
distribute such modifications or work under the terms of Section 1
|
94 |
+
above, provided that you also meet all of these conditions:
|
95 |
+
|
96 |
+
a) You must cause the modified files to carry prominent notices
|
97 |
+
stating that you changed the files and the date of any change.
|
98 |
+
|
99 |
+
b) You must cause any work that you distribute or publish, that in
|
100 |
+
whole or in part contains or is derived from the Program or any
|
101 |
+
part thereof, to be licensed as a whole at no charge to all third
|
102 |
+
parties under the terms of this License.
|
103 |
+
|
104 |
+
c) If the modified program normally reads commands interactively
|
105 |
+
when run, you must cause it, when started running for such
|
106 |
+
interactive use in the most ordinary way, to print or display an
|
107 |
+
announcement including an appropriate copyright notice and a
|
108 |
+
notice that there is no warranty (or else, saying that you provide
|
109 |
+
a warranty) and that users may redistribute the program under
|
110 |
+
these conditions, and telling the user how to view a copy of this
|
111 |
+
License. (Exception: if the Program itself is interactive but
|
112 |
+
does not normally print such an announcement, your work based on
|
113 |
+
the Program is not required to print an announcement.)
|
114 |
+
|
115 |
+
These requirements apply to the modified work as a whole. If
|
116 |
+
identifiable sections of that work are not derived from the Program,
|
117 |
+
and can be reasonably considered independent and separate works in
|
118 |
+
themselves, then this License, and its terms, do not apply to those
|
119 |
+
sections when you distribute them as separate works. But when you
|
120 |
+
distribute the same sections as part of a whole which is a work based
|
121 |
+
on the Program, the distribution of the whole must be on the terms of
|
122 |
+
this License, whose permissions for other licensees extend to the
|
123 |
+
entire whole, and thus to each and every part regardless of who wrote it.
|
124 |
+
Thus, it is not the intent of this section to claim rights or contest
|
125 |
+
your rights to work written entirely by you; rather, the intent is to
|
126 |
+
exercise the right to control the distribution of derivative or
|
127 |
+
collective works based on the Program.
|
128 |
+
|
129 |
+
In addition, mere aggregation of another work not based on the Program
|
130 |
+
with the Program (or with a work based on the Program) on a volume of
|
131 |
+
a storage or distribution medium does not bring the other work under
|
132 |
+
the scope of this License.
|
133 |
+
|
134 |
+
3. You may copy and distribute the Program (or a work based on it,
|
135 |
+
under Section 2) in object code or executable form under the terms of
|
136 |
+
Sections 1 and 2 above provided that you also do one of the following:
|
137 |
+
|
138 |
+
a) Accompany it with the complete corresponding machine-readable
|
139 |
+
source code, which must be distributed under the terms of Sections
|
140 |
+
1 and 2 above on a medium customarily used for software interchange; or,
|
141 |
+
|
142 |
+
b) Accompany it with a written offer, valid for at least three
|
143 |
+
years, to give any third party, for a charge no more than your
|
144 |
+
cost of physically performing source distribution, a complete
|
145 |
+
machine-readable copy of the corresponding source code, to be
|
146 |
+
distributed under the terms of Sections 1 and 2 above on a medium
|
147 |
+
customarily used for software interchange; or,
|
148 |
+
|
149 |
+
c) Accompany it with the information you received as to the offer
|
150 |
+
to distribute corresponding source code. (This alternative is
|
151 |
+
allowed only for noncommercial distribution and only if you
|
152 |
+
received the program in object code or executable form with such
|
153 |
+
an offer, in accord with Subsection b above.)
|
154 |
+
|
155 |
+
The source code for a work means the preferred form of the work for
|
156 |
+
making modifications to it. For an executable work, complete source
|
157 |
+
code means all the source code for all modules it contains, plus any
|
158 |
+
associated interface definition files, plus the scripts used to
|
159 |
+
control compilation and installation of the executable. However, as a
|
160 |
+
special exception, the source code distributed need not include
|
161 |
+
anything that is normally distributed (in either source or binary
|
162 |
+
form) with the major components (compiler, kernel, and so on) of the
|
163 |
+
operating system on which the executable runs, unless that component
|
164 |
+
itself accompanies the executable.
|
165 |
+
|
166 |
+
If distribution of executable or object code is made by offering
|
167 |
+
access to copy from a designated place, then offering equivalent
|
168 |
+
access to copy the source code from the same place counts as
|
169 |
+
distribution of the source code, even though third parties are not
|
170 |
+
compelled to copy the source along with the object code.
|
171 |
+
|
172 |
+
4. You may not copy, modify, sublicense, or distribute the Program
|
173 |
+
except as expressly provided under this License. Any attempt
|
174 |
+
otherwise to copy, modify, sublicense or distribute the Program is
|
175 |
+
void, and will automatically terminate your rights under this License.
|
176 |
+
However, parties who have received copies, or rights, from you under
|
177 |
+
this License will not have their licenses terminated so long as such
|
178 |
+
parties remain in full compliance.
|
179 |
+
|
180 |
+
5. You are not required to accept this License, since you have not
|
181 |
+
signed it. However, nothing else grants you permission to modify or
|
182 |
+
distribute the Program or its derivative works. These actions are
|
183 |
+
prohibited by law if you do not accept this License. Therefore, by
|
184 |
+
modifying or distributing the Program (or any work based on the
|
185 |
+
Program), you indicate your acceptance of this License to do so, and
|
186 |
+
all its terms and conditions for copying, distributing or modifying
|
187 |
+
the Program or works based on it.
|
188 |
+
|
189 |
+
6. Each time you redistribute the Program (or any work based on the
|
190 |
+
Program), the recipient automatically receives a license from the
|
191 |
+
original licensor to copy, distribute or modify the Program subject to
|
192 |
+
these terms and conditions. You may not impose any further
|
193 |
+
restrictions on the recipients' exercise of the rights granted herein.
|
194 |
+
You are not responsible for enforcing compliance by third parties to
|
195 |
+
this License.
|
196 |
+
|
197 |
+
7. If, as a consequence of a court judgment or allegation of patent
|
198 |
+
infringement or for any other reason (not limited to patent issues),
|
199 |
+
conditions are imposed on you (whether by court order, agreement or
|
200 |
+
otherwise) that contradict the conditions of this License, they do not
|
201 |
+
excuse you from the conditions of this License. If you cannot
|
202 |
+
distribute so as to satisfy simultaneously your obligations under this
|
203 |
+
License and any other pertinent obligations, then as a consequence you
|
204 |
+
may not distribute the Program at all. For example, if a patent
|
205 |
+
license would not permit royalty-free redistribution of the Program by
|
206 |
+
all those who receive copies directly or indirectly through you, then
|
207 |
+
the only way you could satisfy both it and this License would be to
|
208 |
+
refrain entirely from distribution of the Program.
|
209 |
+
|
210 |
+
If any portion of this section is held invalid or unenforceable under
|
211 |
+
any particular circumstance, the balance of the section is intended to
|
212 |
+
apply and the section as a whole is intended to apply in other
|
213 |
+
circumstances.
|
214 |
+
|
215 |
+
It is not the purpose of this section to induce you to infringe any
|
216 |
+
patents or other property right claims or to contest validity of any
|
217 |
+
such claims; this section has the sole purpose of protecting the
|
218 |
+
integrity of the free software distribution system, which is
|
219 |
+
implemented by public license practices. Many people have made
|
220 |
+
generous contributions to the wide range of software distributed
|
221 |
+
through that system in reliance on consistent application of that
|
222 |
+
system; it is up to the author/donor to decide if he or she is willing
|
223 |
+
to distribute software through any other system and a licensee cannot
|
224 |
+
impose that choice.
|
225 |
+
|
226 |
+
This section is intended to make thoroughly clear what is believed to
|
227 |
+
be a consequence of the rest of this License.
|
228 |
+
|
229 |
+
8. If the distribution and/or use of the Program is restricted in
|
230 |
+
certain countries either by patents or by copyrighted interfaces, the
|
231 |
+
original copyright holder who places the Program under this License
|
232 |
+
may add an explicit geographical distribution limitation excluding
|
233 |
+
those countries, so that distribution is permitted only in or among
|
234 |
+
countries not thus excluded. In such case, this License incorporates
|
235 |
+
the limitation as if written in the body of this License.
|
236 |
+
|
237 |
+
9. The Free Software Foundation may publish revised and/or new versions
|
238 |
+
of the General Public License from time to time. Such new versions will
|
239 |
+
be similar in spirit to the present version, but may differ in detail to
|
240 |
+
address new problems or concerns.
|
241 |
+
|
242 |
+
Each version is given a distinguishing version number. If the Program
|
243 |
+
specifies a version number of this License which applies to it and "any
|
244 |
+
later version", you have the option of following the terms and conditions
|
245 |
+
either of that version or of any later version published by the Free
|
246 |
+
Software Foundation. If the Program does not specify a version number of
|
247 |
+
this License, you may choose any version ever published by the Free Software
|
248 |
+
Foundation.
|
249 |
+
|
250 |
+
10. If you wish to incorporate parts of the Program into other free
|
251 |
+
programs whose distribution conditions are different, write to the author
|
252 |
+
to ask for permission. For software which is copyrighted by the Free
|
253 |
+
Software Foundation, write to the Free Software Foundation; we sometimes
|
254 |
+
make exceptions for this. Our decision will be guided by the two goals
|
255 |
+
of preserving the free status of all derivatives of our free software and
|
256 |
+
of promoting the sharing and reuse of software generally.
|
257 |
+
|
258 |
+
NO WARRANTY
|
259 |
+
|
260 |
+
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
261 |
+
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
262 |
+
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
263 |
+
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
264 |
+
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
265 |
+
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
266 |
+
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
267 |
+
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
268 |
+
REPAIR OR CORRECTION.
|
269 |
+
|
270 |
+
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
271 |
+
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
272 |
+
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
273 |
+
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
274 |
+
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
275 |
+
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
276 |
+
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
277 |
+
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
278 |
+
POSSIBILITY OF SUCH DAMAGES.
|
279 |
+
|
280 |
+
END OF TERMS AND CONDITIONS
|
281 |
+
|
282 |
+
|
283 |
+
Note: Other license terms may apply to certain, identified software files contained
|
284 |
+
within or distributed with the accompanying software if such terms are included in
|
285 |
+
the directory containing the accompanying software. Such other license terms will
|
286 |
+
then apply in lieu of the terms of the software license above.
|
NOTICE.txt
ADDED
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
AmazonAssociatesLinkBuilder
|
2 |
+
Copyright 2016-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
3 |
+
|
4 |
+
The Amazon Associates Link Builder plugin includes the following third-party software/licensing:
|
5 |
+
|
6 |
+
** sha2.js
|
7 |
+
Copyright (c) 2003-2004, Angel Marin
|
8 |
+
All rights reserved.
|
9 |
+
|
10 |
+
Redistribution and use in source and binary forms, with or without modification,
|
11 |
+
are permitted provided that the following conditions are met:
|
12 |
+
|
13 |
+
* Redistributions of source code must retain the above copyright notice, this
|
14 |
+
list of conditions and the following disclaimer.
|
15 |
+
* Redistributions in binary form must reproduce the above copyright notice,
|
16 |
+
this list of conditions and the following disclaimer in the documentation
|
17 |
+
and/or other materials provided with the distribution.
|
18 |
+
* Neither the name of the <ORGANIZATION> nor the names of its contributors may
|
19 |
+
be used to endorse or promote products derived from this software without
|
20 |
+
specific prior written permission.
|
21 |
+
|
22 |
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
23 |
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
24 |
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
25 |
+
IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
26 |
+
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
27 |
+
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
28 |
+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
29 |
+
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
30 |
+
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
31 |
+
OF THE POSSIBILITY OF SUCH DAMAGE.
|
32 |
+
|
33 |
+
** jCarouselLite - v1.1 - http://www.gmarwaha.com/jquery/jcarousellite/
|
34 |
+
Copyright (c) 2006-2014 Ganeshji Marwaha
|
35 |
+
|
36 |
+
Permission is hereby granted, free of charge, to any person
|
37 |
+
obtaining a copy of this software and associated documentation
|
38 |
+
files (the "Software"), to deal in the Software without
|
39 |
+
restriction, including without limitation the rights to use,
|
40 |
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
41 |
+
copies of the Software, and to permit persons to whom the
|
42 |
+
Software is furnished to do so, subject to the following
|
43 |
+
conditions:
|
44 |
+
|
45 |
+
The above copyright notice and this permission notice shall be
|
46 |
+
included in all copies or substantial portions of the Software.
|
47 |
+
|
48 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
49 |
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
50 |
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
51 |
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
52 |
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
53 |
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
54 |
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
55 |
+
OTHER DEALINGS IN THE SOFTWARE.
|
56 |
+
|
57 |
+
|
58 |
+
** Mustache - MIT License (MIT)
|
59 |
+
Copyright (c) 2010-2015 Justin Hileman
|
60 |
+
|
61 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
62 |
+
of this software and associated documentation files (the "Software"), to deal
|
63 |
+
in the Software without restriction, including without limitation the rights
|
64 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
65 |
+
copies of the Software, and to permit persons to whom the Software is
|
66 |
+
furnished to do so, subject to the following conditions:
|
67 |
+
|
68 |
+
The above copyright notice and this permission notice shall be included in all
|
69 |
+
copies or substantial portions of the Software.
|
70 |
+
|
71 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
72 |
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
73 |
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
74 |
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
75 |
+
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
76 |
+
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
77 |
+
OR OTHER DEALINGS IN THE SOFTWARE.
|
aalb_admin_item_search_items.hbs
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<div class="aalb-modal-box">
|
2 |
+
{{#each this}}
|
3 |
+
<div class="aalb-admin-item-search-items-item" data-asin="{{asin}}">
|
4 |
+
<div class="aalb-admin-item-search-items-item-img">
|
5 |
+
<img id="aalb-admin-item-search-items-item-img" src="{{image}}">
|
6 |
+
</div>
|
7 |
+
<div class="aalb-admin-item-search-items-item-title">
|
8 |
+
{{title}}
|
9 |
+
</div>
|
10 |
+
<div class="aalb-admin-item-search-items-item-price">
|
11 |
+
{{price}}
|
12 |
+
</div>
|
13 |
+
</div>
|
14 |
+
{{/each}}
|
15 |
+
</div>
|
aalb_config.php
ADDED
@@ -0,0 +1,221 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
Copyright 2016-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
5 |
+
|
6 |
+
Licensed under the GNU General Public License as published by the Free Software Foundation,
|
7 |
+
Version 2.0 (the "License"). You may not use this file except in compliance with the License.
|
8 |
+
A copy of the License is located in the "license" file accompanying this file.
|
9 |
+
|
10 |
+
This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
11 |
+
either express or implied. See the License for the specific language governing permissions
|
12 |
+
and limitations under the License.
|
13 |
+
*/
|
14 |
+
|
15 |
+
//version
|
16 |
+
define('AALB_PLUGIN_VERSION','1.1.0-beta-1');
|
17 |
+
|
18 |
+
//paths
|
19 |
+
define('AALB_PLUGIN_DIR', plugin_dir_path( __FILE__ ));
|
20 |
+
define('AALB_PLUGIN_URL', plugin_dir_url( __FILE__ ));
|
21 |
+
|
22 |
+
//Project Title
|
23 |
+
define('AALB_PROJECT_TITLE', 'Associates Link Builder');
|
24 |
+
|
25 |
+
/**
|
26 |
+
* File paths
|
27 |
+
*/
|
28 |
+
|
29 |
+
//Library
|
30 |
+
define('MUSTACHE_AUTOLOADER_PHP', AALB_PLUGIN_DIR .'lib/php/Mustache/Autoloader.php');
|
31 |
+
define('AALB_PAAPI_HELPER_PHP', AALB_PLUGIN_DIR .'lib/php/Paapi/aalb_paapi_helper.php');
|
32 |
+
define('AALB_VALIDATION_HELPER_PHP', AALB_PLUGIN_DIR .'lib/php/aalb_validation_helper.php');
|
33 |
+
define('AALB_XML_HELPER_PHP', AALB_PLUGIN_DIR .'lib/php/aalb_xml_helper.php');
|
34 |
+
define('AALB_TRACKING_API_HELPER_PHP', AALB_PLUGIN_DIR .'lib/php/aalb_tracking_api_helper.php');
|
35 |
+
|
36 |
+
//Shortcode
|
37 |
+
define('AALB_SHORTCODE_PHP', AALB_PLUGIN_DIR .'shortcode/aalb_shortcode.php');
|
38 |
+
define('AALB_SHORTCODE_LOADER', AALB_PLUGIN_DIR . 'shortcode/aalb_shortcode_loader.php');
|
39 |
+
|
40 |
+
//Shortcodes supported
|
41 |
+
define('AALB_SHORTCODE_AMAZON_LINK', 'amazon_link');
|
42 |
+
|
43 |
+
//Admin
|
44 |
+
define('AALB_SIDEBAR_PHP', AALB_PLUGIN_DIR .'admin/sidebar/aalb_sidebar.php');
|
45 |
+
define('AALB_ADMIN_PHP', AALB_PLUGIN_DIR .'admin/aalb_admin.php');
|
46 |
+
define('AALB_ABOUT_PHP', AALB_PLUGIN_DIR . 'admin/sidebar/partials/aalb_about.php');
|
47 |
+
define('AALB_CREDENTIALS_PHP', AALB_PLUGIN_DIR . 'admin/sidebar/partials/aalb_credentials.php');
|
48 |
+
define('AALB_TEMPLATE_PHP', AALB_PLUGIN_DIR . 'admin/sidebar/partials/aalb_templates.php');
|
49 |
+
|
50 |
+
//Directories
|
51 |
+
define('AALB_TEMPLATE_DIR', AALB_PLUGIN_DIR . 'template/');
|
52 |
+
define('AALB_ADMIN_DIR', AALB_PLUGIN_DIR . 'admin/');
|
53 |
+
define('AALB_SIDEBAR_DIR', AALB_PLUGIN_DIR . 'admin/sidebar/');
|
54 |
+
define('AALB_INCLUDES_DIR', AALB_PLUGIN_DIR . 'includes/');
|
55 |
+
define('AALB_PAAPI_DIR', AALB_PLUGIN_DIR . 'lib/php/Paapi/');
|
56 |
+
define('AALB_SHORTCODE_DIR', AALB_PLUGIN_DIR . 'shortcode/');
|
57 |
+
define('AALB_LIBRARY_DIR', AALB_PLUGIN_DIR . 'lib/php/');
|
58 |
+
|
59 |
+
//Includes
|
60 |
+
define('AALB_ACTIVATOR_PHP', AALB_PLUGIN_DIR . 'includes/aalb_activator.php');
|
61 |
+
define('AALB_DEACTIVATOR_PHP', AALB_PLUGIN_DIR . 'includes/aalb_deactivator.php');
|
62 |
+
define('AALB_MANAGER', AALB_PLUGIN_DIR . 'includes/aalb_manager.php');
|
63 |
+
define('AALB_HOOK_LOADER', AALB_PLUGIN_DIR . 'includes/aalb_hook_loader.php');
|
64 |
+
define('AALB_CACHE_LOADER', AALB_PLUGIN_DIR . 'includes/aalb_cache_loader.php');
|
65 |
+
define('AALB_REMOTE_LOADER', AALB_PLUGIN_DIR . 'includes/aalb_remote_loader.php');
|
66 |
+
define('AALB_AUTOLOADER', AALB_PLUGIN_DIR . 'includes/aalb_autoloader.php');
|
67 |
+
|
68 |
+
//Partials
|
69 |
+
define('AALB_META_BOX_PARTIAL', AALB_PLUGIN_DIR . 'admin/partials/aalb_meta_box.php');
|
70 |
+
|
71 |
+
//Proxy
|
72 |
+
define('AALB_PROXY_URL', AALB_PLUGIN_URL . 'lib/php/Paapi/aalb_paapi_proxy.php');
|
73 |
+
|
74 |
+
//Tracking API Endpoint
|
75 |
+
define('AALB_TRACKING_API_ENDPOINT', 'https://rx5hfxbp45.execute-api.us-east-1.amazonaws.com/aalb/');
|
76 |
+
define('AALB_TRACKING_API_SOURCE_TOOL_QUERY_PARAM', 'source-tool=aalb');
|
77 |
+
define('AALB_TRACKING_API_ACCESS_KEY_QUERY_PARAM', 'aws-access-key-id=');
|
78 |
+
|
79 |
+
//Wordpress Pages
|
80 |
+
define('WP_POST', 'post.php');
|
81 |
+
define('WP_POST_NEW', 'post-new.php');
|
82 |
+
|
83 |
+
/**
|
84 |
+
* Styles and scripts
|
85 |
+
*/
|
86 |
+
|
87 |
+
//Local Styles
|
88 |
+
define('AALB_ADMIN_CSS', AALB_PLUGIN_URL . 'admin/css/aalb_admin.css');
|
89 |
+
define('AALB_TEMPLATE_URL',AALB_PLUGIN_URL . 'template/');
|
90 |
+
define('AALB_BASICS_CSS', AALB_PLUGIN_URL . 'css/aalb_basics.css');
|
91 |
+
|
92 |
+
//Local Scripts
|
93 |
+
define('AALB_SHA2_JS', AALB_PLUGIN_URL . 'lib/js/jssha2/sha2.js');
|
94 |
+
define('AALB_ADMIN_JS', AALB_PLUGIN_URL . 'admin/js/aalb_admin.js');
|
95 |
+
define('AALB_ADMIN_ITEM_SEARCH_ITEMS_URL', AALB_PLUGIN_URL . 'aalb_admin_item_search_items.hbs');
|
96 |
+
define('AALB_TEMPLATE_JS', AALB_PLUGIN_URL . 'admin/sidebar/js/aalb_template.js');
|
97 |
+
define('AALB_CREDENTIALS_JS', AALB_PLUGIN_URL . 'admin/sidebar/js/aalb_credentials.js');
|
98 |
+
|
99 |
+
//External Scripts
|
100 |
+
define('HANDLEBARS_JS', 'https://d8fd03967nrad.cloudfront.net/libs/handlebars.js/4.0.5/handlebars.min.js');
|
101 |
+
define('CODEMIRROR_JS', 'https://d8fd03967nrad.cloudfront.net/libs/codemirror/5.13.2/codemirror.min.js');
|
102 |
+
define('CODEMIRROR_MODE_XML_JS', 'https://d8fd03967nrad.cloudfront.net/libs/codemirror/5.13.2/mode/xml/xml.min.js');
|
103 |
+
define('CODEMIRROR_MODE_CSS_JS', 'https://d8fd03967nrad.cloudfront.net/libs/codemirror/5.13.2/mode/css/css.min.js');
|
104 |
+
|
105 |
+
//External Styles
|
106 |
+
define('FONT_AWESOME_CSS', 'https://d8fd03967nrad.cloudfront.net/libs/font-awesome/4.5.0/css/font-awesome.min.css');
|
107 |
+
define('CODEMIRROR_CSS', 'https://d8fd03967nrad.cloudfront.net/libs/codemirror/5.13.2/codemirror.min.css');
|
108 |
+
|
109 |
+
/**
|
110 |
+
* Icons
|
111 |
+
*/
|
112 |
+
define('AALB_SECURE_HOSTNAME', 'https://images-na.ssl-images-amazon.com/');
|
113 |
+
define('AALB_NORMAL_HOSTNAME', 'http://g-ecx.images-amazon.com/');
|
114 |
+
define('AALB_ICON_LOCATION', 'images/G/01/PAAPI/AmazonAssociatesLinkBuilder/icon-2._V276841048_.png');
|
115 |
+
define('AALB_ADMIN_ICON_LOCATION', 'images/G/01/PAAPI/AmazonAssociatesLinkBuilder/icon._V278877987_.png');
|
116 |
+
//AALB_ICON URL is generated by wordpress at run-time by checking the remotehost's encryption. Image source has different URLs depending upon the encryption used.
|
117 |
+
if(is_ssl()){
|
118 |
+
define('AALB_ICON', AALB_SECURE_HOSTNAME . AALB_ICON_LOCATION);
|
119 |
+
} else {
|
120 |
+
define('AALB_ICON', AALB_NORMAL_HOSTNAME . AALB_ICON_LOCATION);
|
121 |
+
}
|
122 |
+
define('AALB_ADMIN_ICON', AALB_SECURE_HOSTNAME . AALB_ADMIN_ICON_LOCATION);
|
123 |
+
|
124 |
+
|
125 |
+
/**
|
126 |
+
* Constants
|
127 |
+
*/
|
128 |
+
|
129 |
+
//Search result items. Paapi returns 10 items by default.
|
130 |
+
define('AALB_MAX_SEARCH_RESULT_ITEMS', 9);
|
131 |
+
//List of Default Amazon Template names
|
132 |
+
define('AALB_AMAZON_TEMPLATE_NAMES', 'ProductCarousel,ProductGrid,ProductAd,PriceLink');
|
133 |
+
|
134 |
+
//Database keys
|
135 |
+
define('AALB_TEMPLATE_NAMES', 'aalb_template_names');
|
136 |
+
define('AALB_MARKETPLACE_NAMES', 'aalb_marketplace_names');
|
137 |
+
define('AALB_DEFAULT_TEMPLATE', 'aalb_default_template');
|
138 |
+
define('AALB_DEFAULT_STORE_ID', 'aalb_default_store_id');
|
139 |
+
define('AALB_DEFAULT_MARKETPLACE', 'aalb_default_marketplace');
|
140 |
+
define('AALB_AWS_ACCESS_KEY', 'aalb_aws_access_key');
|
141 |
+
define('AALB_AWS_SECRET_KEY', 'aalb_aws_secret_key');
|
142 |
+
define('AALB_CRED_CONFIG_GROUP', 'aalb_cred_config_group');
|
143 |
+
define('AALB_STORE_ID_NAMES', 'aalb_store_id_names');
|
144 |
+
|
145 |
+
//Masking constant
|
146 |
+
define('AALB_AWS_SECRET_KEY_MASK', '••••••••••••••••••••••••••••••••••••••••');
|
147 |
+
|
148 |
+
|
149 |
+
//Defaults in case DB doesn't contain them.
|
150 |
+
define('AALB_DEFAULT_TEMPLATE_NAME', 'ProductCarousel');
|
151 |
+
define('AALB_DEFAULT_MARKETPLACE_NAME', 'US');
|
152 |
+
define('AALB_DEFAULT_STORE_ID_NAME', 'not-specified');
|
153 |
+
|
154 |
+
//Marketplaces
|
155 |
+
define('MARKETPLACES_URL', 'https://webservices.amazon.com/scratchpad/assets/config/config.json');
|
156 |
+
|
157 |
+
//PAAPI
|
158 |
+
define('PAAPI_URI', '/onca/xml');
|
159 |
+
define('PAAPI_TRANSFER_PROTOCOL', 'https://');
|
160 |
+
define('PAAPI_URL_QUERY_SEPARATOR', '?');
|
161 |
+
define('PAAPI_SERVICE', 'AWSECommerceService');
|
162 |
+
define('PAAPI_VERSION', '2013-08-01');
|
163 |
+
define('PAAPI_URL_REGEX', '^https:\\/\\/(.*)\\/onca\\/xml\\?(.*)$');
|
164 |
+
|
165 |
+
//HTTP Status Codes
|
166 |
+
define('HTTP_SUCCESS', '200');
|
167 |
+
define('HTTP_SUCCESS_MESSAGE', '<h4>Request Successful</h4>');
|
168 |
+
define('HTTP_BAD_REQUEST', '400');
|
169 |
+
define('HTTP_BAD_REQUEST_MESSAGE', '<h4>Your AWS Access Key Id is not registered as an Amazon Associate. Please register as an associate at the respective endpoint.</h4>');
|
170 |
+
define('HTTP_FORBIDDEN', '403');
|
171 |
+
define('HTTP_FORBIDDEN_MESSAGE', '<h4>The AWS Access Key or Secret Key you provided does not exist in our records. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.</h4>');
|
172 |
+
define('HTTP_INTERNAL_SERVER_ERROR', '500');
|
173 |
+
define('HTTP_INTERNAL_SERVER_ERROR_MESSAGE', '<h4>Internal server error</h4>');
|
174 |
+
define('HTTP_THROTTLE', '503');
|
175 |
+
define('HTTP_THROTTLE_MESSAGE', '<h4>You are submitting requests too quickly. Please retry your requests at a slower rate.</h4>');
|
176 |
+
|
177 |
+
/**
|
178 |
+
* Cipher
|
179 |
+
*/
|
180 |
+
//Make a key of length 32 byte.
|
181 |
+
//Specify your unique encryption key here.
|
182 |
+
define('AALB_ENCRYPTION_KEY', 'put your unique phrase here');
|
183 |
+
//Default Encryption Key. Do NOT change this.
|
184 |
+
define('AALB_ENCRYPTION_KEY_DEFAULT', 'put your unique phrase here');
|
185 |
+
|
186 |
+
//Make IV of 16 bytes
|
187 |
+
define('AALB_ENCRYPTION_IV', '0123456789ABCDEF');
|
188 |
+
|
189 |
+
//Algorithm to use
|
190 |
+
define('AALB_ENCRYPTION_ALGORITHM', 'aes-256-cbc');
|
191 |
+
|
192 |
+
//Caching Requirements
|
193 |
+
//====================
|
194 |
+
//As defined by the Product Advertising API License Agreement at https://affiliate-program.amazon.com/gp/advertising/api/detail/agreement.html,
|
195 |
+
//Dated Jul 22, 2016, Section 4(n) and 4(o), caching of product information is permitted upto a maximum of 24-hours.
|
196 |
+
//Further, if the product price is not refreshed every one hour, the displayed price should be accompanied with a timestamp when the price was read.
|
197 |
+
//Note that the plugin uses a two tier cache. It caches the ASINs as well as the rendered templates.
|
198 |
+
//At any given time the sum of ASIN cache TTL and Rendered AdUnit cache TTL should be less than or equal to one hour.
|
199 |
+
//The below configuration is compliant with the License Agreement. Any modification may result in the violation of the license agreement.
|
200 |
+
define('AALB_CACHE_FOR_ASIN_RAWINFO_TTL', 30*MINUTE_IN_SECONDS);
|
201 |
+
define('AALB_CACHE_FOR_ASIN_ADUNIT_TTL', 30*MINUTE_IN_SECONDS);
|
202 |
+
|
203 |
+
//Translation keys
|
204 |
+
define('CHECK_ON_AMAZON','Check on Amazon');
|
205 |
+
define('OUT_OF_STOCK','Out of stock');
|
206 |
+
|
207 |
+
//Marketplaces supported for translations
|
208 |
+
define('US','US');
|
209 |
+
define('FR','FR');
|
210 |
+
define('IT','IT');
|
211 |
+
define('DE','DE');
|
212 |
+
define('ES','ES');
|
213 |
+
define('BR','BR');
|
214 |
+
define('CA','CA');
|
215 |
+
define('CN','CN');
|
216 |
+
define('IN','IN');
|
217 |
+
define('JP','JP');
|
218 |
+
define('MX','MX');
|
219 |
+
define('UK','UK');
|
220 |
+
|
221 |
+
?>
|
admin/aalb_admin.php
ADDED
@@ -0,0 +1,166 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
Copyright 2016-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
5 |
+
|
6 |
+
Licensed under the GNU General Public License as published by the Free Software Foundation,
|
7 |
+
Version 2.0 (the "License"). You may not use this file except in compliance with the License.
|
8 |
+
A copy of the License is located in the "license" file accompanying this file.
|
9 |
+
|
10 |
+
This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
11 |
+
either express or implied. See the License for the specific language governing permissions
|
12 |
+
and limitations under the License.
|
13 |
+
*/
|
14 |
+
|
15 |
+
/**
|
16 |
+
* The class responsible for handling all the functionalities in the admin area.
|
17 |
+
* Enqueues the styles and scripts for post.php and post-new.php.
|
18 |
+
* Fetches the marketplace endpoints from external json file.
|
19 |
+
* Handles UI in the admin area by providing a meta box and an asin button in the html text editor.
|
20 |
+
*
|
21 |
+
* @since 1.0.0
|
22 |
+
* @package AmazonAssociatesLinkBuilder
|
23 |
+
* @subpackage AmazonAssociatesLinkBuilder/admin
|
24 |
+
*/
|
25 |
+
class Aalb_Admin {
|
26 |
+
|
27 |
+
private $paapi_helper;
|
28 |
+
private $remote_loader;
|
29 |
+
private $tracking_api_helper;
|
30 |
+
|
31 |
+
public function __construct() {
|
32 |
+
$this->paapi_helper = new Aalb_Paapi_Helper();
|
33 |
+
$this->remote_loader = new Aalb_Remote_Loader();
|
34 |
+
$this->tracking_api_helper = new Aalb_Tracking_Api_Helper();
|
35 |
+
add_action('admin_notices', array($this, 'aalb_plugin_activation')) ;
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Show warning message if the AWS Credentials are not yet set upon activation
|
40 |
+
*
|
41 |
+
* @since 1.0.0
|
42 |
+
*/
|
43 |
+
public function aalb_plugin_activation() {
|
44 |
+
if(get_option(AALB_AWS_ACCESS_KEY) == '' or get_option(AALB_AWS_SECRET_KEY) == '') {
|
45 |
+
echo "<div class=\"notice notice-error\"><h3>Amazon Associates Link Builder Important Message!</h3><p>Please Note - You need to add your Access Key ID and Secret Access Key in the plugin settings page for adding links to Amazon using Amazon Associates Link Builder plugin.</p></div>";
|
46 |
+
}
|
47 |
+
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Adding CSS for post and post-new pages
|
51 |
+
*
|
52 |
+
* @since 1.0.0
|
53 |
+
* @param string $hook The name of the WordPress action that is being registered.
|
54 |
+
*/
|
55 |
+
public function enqueue_styles($hook) {
|
56 |
+
if(WP_POST != $hook && WP_POST_NEW != $hook){return;}
|
57 |
+
wp_enqueue_style('aalb_basics_css', AALB_BASICS_CSS );
|
58 |
+
wp_enqueue_style('aalb_admin_css', AALB_ADMIN_CSS);
|
59 |
+
wp_enqueue_style('font_awesome_css', FONT_AWESOME_CSS);
|
60 |
+
wp_enqueue_style('thickbox');
|
61 |
+
}
|
62 |
+
|
63 |
+
/**
|
64 |
+
* Adding JS for post and post-new pages
|
65 |
+
*
|
66 |
+
* @since 1.0.0
|
67 |
+
* @param string $hook The name of the WordPress action that is being registered.
|
68 |
+
*/
|
69 |
+
public function enqueue_scripts($hook) {
|
70 |
+
if(WP_POST != $hook && WP_POST_NEW != $hook){return;}
|
71 |
+
wp_enqueue_style('thickbox');
|
72 |
+
wp_enqueue_script('jquery');
|
73 |
+
wp_enqueue_script('handlebars_js', HANDLEBARS_JS);
|
74 |
+
wp_enqueue_script('aalb_sha2_js', AALB_SHA2_JS);
|
75 |
+
|
76 |
+
wp_enqueue_script('aalb_admin_js', AALB_ADMIN_JS, array('handlebars_js', 'jquery', 'aalb_sha2_js'));
|
77 |
+
wp_enqueue_style('thickbox');
|
78 |
+
wp_localize_script('aalb_admin_js', 'api_pref', $this->get_paapi_pref());
|
79 |
+
}
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Returns data to be localized in the script.
|
83 |
+
* Makes the variable values in PHP to be used in Javascript.
|
84 |
+
*
|
85 |
+
* @since 1.0.0
|
86 |
+
* @return array Data to be localized in the script
|
87 |
+
*/
|
88 |
+
private function get_paapi_pref() {
|
89 |
+
return array(
|
90 |
+
'template_url' => AALB_ADMIN_ITEM_SEARCH_ITEMS_URL,
|
91 |
+
'max_search_result_items' => AALB_MAX_SEARCH_RESULT_ITEMS,
|
92 |
+
'store_id' => get_option(AALB_DEFAULT_STORE_ID),
|
93 |
+
'marketplace' => get_option(AALB_DEFAULT_MARKETPLACE),
|
94 |
+
'ajax_url' => admin_url('admin-ajax.php'),
|
95 |
+
'action' => 'get_item_search_result',
|
96 |
+
'item_search_nonce' => wp_create_nonce('aalb-item-search-nonce'),
|
97 |
+
'AALB_SHORTCODE_AMAZON_LINK' => AALB_SHORTCODE_AMAZON_LINK
|
98 |
+
);
|
99 |
+
}
|
100 |
+
|
101 |
+
/**
|
102 |
+
* Prints the aalb-admin sidebar search box.
|
103 |
+
*
|
104 |
+
* @since 1.0.0
|
105 |
+
* @param WP_Post $post The object for the current post/page.
|
106 |
+
*/
|
107 |
+
function admin_display_callback($post) {
|
108 |
+
require_once(AALB_META_BOX_PARTIAL);
|
109 |
+
}
|
110 |
+
|
111 |
+
/**
|
112 |
+
* Asin button in text editor for putting the shortcode template
|
113 |
+
*
|
114 |
+
* @since 1.0.0
|
115 |
+
*/
|
116 |
+
function add_quicktags() {
|
117 |
+
if (wp_script_is('quicktags')){
|
118 |
+
?>
|
119 |
+
<script type="text/javascript">
|
120 |
+
QTags.addButton( 'aalb_asin_button', 'asins', '[amazon_link asins="" template="" marketplace="" link_id=""]', '', '', 'Amazon Link');
|
121 |
+
</script>
|
122 |
+
<?php
|
123 |
+
}
|
124 |
+
}
|
125 |
+
|
126 |
+
/**
|
127 |
+
* Supports the ajax request for item search.
|
128 |
+
*
|
129 |
+
* @since 1.0.0
|
130 |
+
*/
|
131 |
+
public function get_item_search_result() {
|
132 |
+
$nonce = $_GET['item_search_nonce'];
|
133 |
+
|
134 |
+
//verify the user making the request.
|
135 |
+
if(!wp_verify_nonce($nonce, 'aalb-item-search-nonce')) {
|
136 |
+
die('Not authorised to make a request');
|
137 |
+
}
|
138 |
+
|
139 |
+
//Only allow users who can edit post to make the request.
|
140 |
+
if(current_user_can('edit_posts')) {
|
141 |
+
$url = $this->paapi_helper->get_item_search_url($_GET['keywords'], $_GET['marketplace'], $_GET['store_id']);
|
142 |
+
try{
|
143 |
+
echo $this->remote_loader->load($url);
|
144 |
+
} catch(Exception $e){
|
145 |
+
echo $this->paapi_helper->get_error_message($e->getMessage());
|
146 |
+
}
|
147 |
+
}
|
148 |
+
|
149 |
+
wp_die();
|
150 |
+
}
|
151 |
+
|
152 |
+
/**
|
153 |
+
* Supports the ajax request for get link id API
|
154 |
+
*
|
155 |
+
* @since 1.0.0
|
156 |
+
*/
|
157 |
+
public function get_link_code() {
|
158 |
+
|
159 |
+
$shortcode_params_json_string = $_POST['shortcode_params'];
|
160 |
+
$shortcode_name = $_POST['shortcode_name'];
|
161 |
+
|
162 |
+
echo $this->tracking_api_helper->get_link_id($shortcode_name, $shortcode_params_json_string);
|
163 |
+
wp_die();
|
164 |
+
}
|
165 |
+
}
|
166 |
+
?>
|
admin/css/aalb_admin.css
ADDED
@@ -0,0 +1,369 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*
|
2 |
+
Copyright 2016-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
3 |
+
|
4 |
+
Licensed under the GNU General Public License as published by the Free Software Foundation,
|
5 |
+
Version 2.0 (the "License"). You may not use this file except in compliance with the License.
|
6 |
+
A copy of the License is located in the "license" file accompanying this file.
|
7 |
+
|
8 |
+
This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
9 |
+
either express or implied. See the License for the specific language governing permissions
|
10 |
+
and limitations under the License.
|
11 |
+
*/
|
12 |
+
|
13 |
+
#aalb-admin-searchbox {
|
14 |
+
display: inline;
|
15 |
+
}
|
16 |
+
|
17 |
+
img#aalb-admin-searchbox-amzlogo {
|
18 |
+
width: 30px;
|
19 |
+
height: 30px;
|
20 |
+
padding: 0px;
|
21 |
+
}
|
22 |
+
|
23 |
+
input#aalb-admin-input-search {
|
24 |
+
vertical-align: top;
|
25 |
+
margin-left: 3px;
|
26 |
+
margin-right: 3px;
|
27 |
+
height: 28px;
|
28 |
+
}
|
29 |
+
|
30 |
+
|
31 |
+
a#aalb-admin-button-create-amazon-shortcode {
|
32 |
+
box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.4) inset;
|
33 |
+
background: transparent linear-gradient(to bottom, #F7DFA5, #F0C14B) repeat scroll 0% 0%;
|
34 |
+
background-color: transparent;
|
35 |
+
background-image: linear-gradient(to bottom, #F7DFA5, #F0C14B);
|
36 |
+
background-repeat: repeat;
|
37 |
+
background-attachment: scroll;
|
38 |
+
background-position: 0% 0%;
|
39 |
+
background-clip: border-box;
|
40 |
+
background-origin: padding-box;
|
41 |
+
background-size: auto auto;
|
42 |
+
border-color: #A88734 #9C7E31 #846A29;
|
43 |
+
border-top-color: #A88734;
|
44 |
+
border-right-color: #9C7E31;
|
45 |
+
border-bottom-color: #846A29;
|
46 |
+
border-left-color: #9C7E31;
|
47 |
+
color: #111;
|
48 |
+
}
|
49 |
+
|
50 |
+
html, body
|
51 |
+
{
|
52 |
+
width: 100%;
|
53 |
+
height: 100%;
|
54 |
+
margin: 0;
|
55 |
+
padding: 0;
|
56 |
+
}
|
57 |
+
|
58 |
+
#TB_ajaxContent {
|
59 |
+
height:90%;
|
60 |
+
width:95%;
|
61 |
+
}
|
62 |
+
|
63 |
+
#aalb-admin-popup-container {
|
64 |
+
height: 100%;
|
65 |
+
width: 100%;
|
66 |
+
}
|
67 |
+
|
68 |
+
#aalb-admin-popup-content {
|
69 |
+
padding-top: 30px;
|
70 |
+
height: 50%;
|
71 |
+
width: 100%;
|
72 |
+
}
|
73 |
+
|
74 |
+
.aalb-modal-box {
|
75 |
+
width:100%;
|
76 |
+
height: 100%;
|
77 |
+
}
|
78 |
+
|
79 |
+
.aalb-admin-alert {
|
80 |
+
padding: 15px;
|
81 |
+
margin-bottom: 20px;
|
82 |
+
border: 1px solid transparent;
|
83 |
+
border-radius: 4px;
|
84 |
+
}
|
85 |
+
|
86 |
+
.aalb-admin-alert {
|
87 |
+
text-shadow: 0px 1px 0px rgba(255, 255, 255, 0.2);
|
88 |
+
box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.25) inset, 0px 1px 2px rgba(0, 0, 0, 0.05);
|
89 |
+
}
|
90 |
+
|
91 |
+
.aalb-admin-alert-info {
|
92 |
+
color: #E77600;
|
93 |
+
background-color: #FEF8F2;
|
94 |
+
border-color: #E77600;
|
95 |
+
}
|
96 |
+
|
97 |
+
.aalb-admin-alert-info {
|
98 |
+
background-image: linear-gradient(to bottom, #FEF8F2 0px, #FFF1E3 100%);
|
99 |
+
background-repeat: repeat-x;
|
100 |
+
border-color: #E77600;
|
101 |
+
}
|
102 |
+
|
103 |
+
#aalb-add-shortcode-alert{
|
104 |
+
color: #E77600;
|
105 |
+
padding: 2px;
|
106 |
+
display: inline;
|
107 |
+
padding-left: 10px;
|
108 |
+
opacity: 0;
|
109 |
+
}
|
110 |
+
|
111 |
+
.aalb-admin-icon {
|
112 |
+
padding-right: 5px;
|
113 |
+
height: 20%;
|
114 |
+
display: inline;
|
115 |
+
}
|
116 |
+
|
117 |
+
.aalb-admin-item-search-loading {
|
118 |
+
margin-top: 20px;
|
119 |
+
}
|
120 |
+
|
121 |
+
.aalb-admin-item-search {
|
122 |
+
width:100%;
|
123 |
+
height: 90%;
|
124 |
+
display: none;
|
125 |
+
padding-top: 3%;
|
126 |
+
}
|
127 |
+
|
128 |
+
.aalb-admin-item-search-items {
|
129 |
+
width:100%;
|
130 |
+
height: 100%;
|
131 |
+
margin: 2px;
|
132 |
+
padding: 0;
|
133 |
+
-moz-column-gap: 8px;
|
134 |
+
-webkit-column-gap: 8px;
|
135 |
+
column-gap: 8px;
|
136 |
+
-moz-column-count: 3;
|
137 |
+
-webkit-column-count: 3;
|
138 |
+
column-count: 3;
|
139 |
+
}
|
140 |
+
|
141 |
+
.aalb-admin-item-search-items-item {
|
142 |
+
display: inline-block;
|
143 |
+
background: #fff;
|
144 |
+
padding: 5px;
|
145 |
+
margin: 0 0 5px;
|
146 |
+
width: 100%;
|
147 |
+
height:30%;
|
148 |
+
-moz-box-sizing: border-box;
|
149 |
+
-webkit-box-sizing: border-box;
|
150 |
+
box-sizing: border-box;
|
151 |
+
box-shadow: 2px 2px 4px 0 #ccc;
|
152 |
+
border: 1px solid #CCC;
|
153 |
+
border-radius: 4px;
|
154 |
+
cursor: pointer;
|
155 |
+
}
|
156 |
+
|
157 |
+
.aalb-admin-item-search-items-item-img{
|
158 |
+
float:left;
|
159 |
+
padding-right: 5px;
|
160 |
+
width: 25%;
|
161 |
+
height: 100%;
|
162 |
+
}
|
163 |
+
|
164 |
+
#aalb-admin-item-search-items-item-img{
|
165 |
+
max-width:100%;
|
166 |
+
height:100%;
|
167 |
+
display:block;
|
168 |
+
margin-left:auto;
|
169 |
+
margin-right:auto;
|
170 |
+
}
|
171 |
+
|
172 |
+
.aalb-admin-item-search-items-item-title {
|
173 |
+
font-weight: bold;
|
174 |
+
word-break: break-all;
|
175 |
+
font-size: 1em;
|
176 |
+
/* hide text if it more than N lines */
|
177 |
+
overflow: hidden;
|
178 |
+
/* for set '...' in absolute position */
|
179 |
+
position: relative;
|
180 |
+
/* use this value to count block height */
|
181 |
+
line-height: 1.2em;
|
182 |
+
/* max-height = line-height (1.2) * lines max number (2) */
|
183 |
+
max-height: 2.4em;
|
184 |
+
/* fix problem when last visible word doesn't adjoin right side */
|
185 |
+
text-align: justify;
|
186 |
+
/* place for '...' */
|
187 |
+
margin-right: -1em;
|
188 |
+
padding-right: 1em;
|
189 |
+
}
|
190 |
+
|
191 |
+
/* create the ... */
|
192 |
+
.aalb-admin-item-search-items-item-title:before {
|
193 |
+
/* points in the end */
|
194 |
+
content: '...';
|
195 |
+
/* absolute position */
|
196 |
+
position: absolute;
|
197 |
+
/* set position to right bottom corner of block */
|
198 |
+
right: 0;
|
199 |
+
bottom: 0;
|
200 |
+
}
|
201 |
+
|
202 |
+
/* hide ... if we have text, which is less than or equal to max lines */
|
203 |
+
.aalb-admin-item-search-items-item-title:after {
|
204 |
+
/* points in the end */
|
205 |
+
content: '';
|
206 |
+
/* absolute position */
|
207 |
+
position: absolute;
|
208 |
+
/* set position to right bottom corner of text */
|
209 |
+
right: 0;
|
210 |
+
/* set width and height */
|
211 |
+
width: 1em;
|
212 |
+
height: 1em;
|
213 |
+
margin-top: 0.2em;
|
214 |
+
/* bg color = bg color under block */
|
215 |
+
background: white;
|
216 |
+
}
|
217 |
+
|
218 |
+
.aalb-admin-item-search-items-item-price {
|
219 |
+
font-size: 1em;
|
220 |
+
color: #b12704;
|
221 |
+
font-weight: bold;
|
222 |
+
}
|
223 |
+
|
224 |
+
.aalb-admin-item-search-items-item:hover {
|
225 |
+
background-image: linear-gradient(to bottom, #FEF8F2 0px, #FFF1E3 100%);
|
226 |
+
background-repeat: repeat-x;
|
227 |
+
border-color: #E77600;
|
228 |
+
}
|
229 |
+
|
230 |
+
.aalb-admin-popup-shortocde-wrapper {
|
231 |
+
display: block;
|
232 |
+
width: 100%;
|
233 |
+
}
|
234 |
+
|
235 |
+
.aalb-admin-popup-shortcode-options {
|
236 |
+
padding-top: 3%;
|
237 |
+
width:100%;
|
238 |
+
-moz-column-gap: 10px;
|
239 |
+
-webkit-column-gap: 10px;
|
240 |
+
column-gap: 10px;
|
241 |
+
-moz-column-count: 3;
|
242 |
+
-webkit-column-count: 3;
|
243 |
+
column-count: 3;
|
244 |
+
}
|
245 |
+
|
246 |
+
.aalb-admin-popup-shortcode-options label {
|
247 |
+
display: block;
|
248 |
+
text-align: left;
|
249 |
+
}
|
250 |
+
|
251 |
+
.aalb-admin-item-search-templates {
|
252 |
+
width:100%;
|
253 |
+
}
|
254 |
+
|
255 |
+
.aalb-admin-popup-store {
|
256 |
+
width:100%;
|
257 |
+
}
|
258 |
+
|
259 |
+
.aalb-admin-item-search-marketplaces {
|
260 |
+
width:100%;
|
261 |
+
}
|
262 |
+
|
263 |
+
.aalb-add-shortcode-button {
|
264 |
+
padding-top: 20px;
|
265 |
+
}
|
266 |
+
|
267 |
+
.aalb-admin-popup-options {
|
268 |
+
position:relative;
|
269 |
+
}
|
270 |
+
|
271 |
+
#aalb-admin-popup-input-search {
|
272 |
+
position:absolute;
|
273 |
+
width:100%;
|
274 |
+
left: 0;
|
275 |
+
margin-top: 1%;
|
276 |
+
height:33px;
|
277 |
+
vertical-align: middle;
|
278 |
+
}
|
279 |
+
|
280 |
+
#aalb-admin-popup-search-button {
|
281 |
+
position:absolute;
|
282 |
+
right:0;
|
283 |
+
}
|
284 |
+
|
285 |
+
.aalb-selected {
|
286 |
+
height:auto;
|
287 |
+
width:100%;
|
288 |
+
padding-top: 10px;
|
289 |
+
padding-bottom: 10px;
|
290 |
+
}
|
291 |
+
|
292 |
+
.aalb-selected label {
|
293 |
+
display: block;
|
294 |
+
text-align: left;
|
295 |
+
padding: 15px 0px;
|
296 |
+
}
|
297 |
+
|
298 |
+
.aalb-selected-item {
|
299 |
+
border: 1px solid #eee;
|
300 |
+
float: left;
|
301 |
+
margin: 4px 4px 4px 4px;
|
302 |
+
position: relative;
|
303 |
+
width: 10%;
|
304 |
+
padding: 4px;
|
305 |
+
font-family: Helvetica;
|
306 |
+
}
|
307 |
+
|
308 |
+
.aalb-selected-item:hover {
|
309 |
+
border: 1px solid #900;
|
310 |
+
}
|
311 |
+
|
312 |
+
.aalb-selected-item-img {
|
313 |
+
display:block;
|
314 |
+
margin-top:auto;
|
315 |
+
margin-bottom:auto;
|
316 |
+
height:90px;
|
317 |
+
margin-left:auto;
|
318 |
+
margin-right:auto;
|
319 |
+
max-width:100%;
|
320 |
+
}
|
321 |
+
|
322 |
+
.aalb-selected-item-img-wrap {
|
323 |
+
position: relative;
|
324 |
+
height: 100%;
|
325 |
+
}
|
326 |
+
.aalb-selected-item-close {
|
327 |
+
position: absolute;
|
328 |
+
top: -12px;
|
329 |
+
right: -12px;
|
330 |
+
z-index: 100;
|
331 |
+
color: #FFF;
|
332 |
+
border-radius: 10px;
|
333 |
+
display: block;
|
334 |
+
height: 20px;
|
335 |
+
width: 20px;
|
336 |
+
text-align: center;
|
337 |
+
line-height: 20px;
|
338 |
+
font-size: 20px;
|
339 |
+
font-weight: bold;
|
340 |
+
cursor: pointer;
|
341 |
+
box-shadow: 1px 1px 4px #000;
|
342 |
+
background-color: #a50200;
|
343 |
+
background-image: -webkit-linear-gradient(top,#cb0400,#a50200);
|
344 |
+
background-image: linear-gradient(to bottom,#cb0400,#a50200);
|
345 |
+
}
|
346 |
+
|
347 |
+
.aalb-selected-item-title h3{
|
348 |
+
margin: 2px 3px 0 2px;
|
349 |
+
font-size: 8px;
|
350 |
+
line-height: 12px;
|
351 |
+
color: #000;
|
352 |
+
position: relative;
|
353 |
+
text-align: center;
|
354 |
+
display: block;
|
355 |
+
overflow: hidden;
|
356 |
+
height: 35px;
|
357 |
+
}
|
358 |
+
|
359 |
+
.aalb-selected-item-price {
|
360 |
+
text-align: center;
|
361 |
+
color: #900;
|
362 |
+
font-weight: bold;
|
363 |
+
margin: 2px;
|
364 |
+
}
|
365 |
+
|
366 |
+
|
367 |
+
.aalb-selected-asin {
|
368 |
+
display:none;
|
369 |
+
}
|
admin/js/aalb_admin.js
ADDED
@@ -0,0 +1,336 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*
|
2 |
+
Copyright 2016-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
3 |
+
|
4 |
+
Licensed under the GNU General Public License as published by the Free Software Foundation,
|
5 |
+
Version 2.0 (the "License"). You may not use this file except in compliance with the License.
|
6 |
+
A copy of the License is located in the "license" file accompanying this file.
|
7 |
+
|
8 |
+
This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
9 |
+
either express or implied. See the License for the specific language governing permissions
|
10 |
+
and limitations under the License.
|
11 |
+
*/
|
12 |
+
|
13 |
+
var template;
|
14 |
+
var TB_WIDTH,TB_HEIGHT;
|
15 |
+
var tb_remove;
|
16 |
+
var link_id = "";
|
17 |
+
var AALB_SHORTCODE_AMAZON_LINK=api_pref.AALB_SHORTCODE_AMAZON_LINK; //constant value from server side is reused here
|
18 |
+
|
19 |
+
jQuery(document).ready(function() {
|
20 |
+
// http://stackoverflow.com/questions/5557641/how-can-i-reset-div-to-its-original-state-after-it-has-been-modified-by-java
|
21 |
+
jQuery("#aalb-admin-popup-content").data('old-state', jQuery("#aalb-admin-popup-content").html());
|
22 |
+
|
23 |
+
//Load the search result template
|
24 |
+
jQuery.get( api_pref.template_url, function(data) {
|
25 |
+
template = Handlebars.compile(data);
|
26 |
+
});
|
27 |
+
|
28 |
+
//Resize thickbox on window resize
|
29 |
+
jQuery(window).on('resize',resize_thickbox);
|
30 |
+
|
31 |
+
//Storing the tb_remove function of Thickbox.js
|
32 |
+
var old_tb_remove = window.tb_remove;
|
33 |
+
|
34 |
+
//Custom tb_remove function
|
35 |
+
tb_remove = function() {
|
36 |
+
//call actual tb_remove
|
37 |
+
old_tb_remove();
|
38 |
+
//custom actions to execute
|
39 |
+
jQuery(".aalb-selected-item").each(function(){
|
40 |
+
aalb_remove_selected_item(this);
|
41 |
+
});
|
42 |
+
};
|
43 |
+
});
|
44 |
+
|
45 |
+
/**
|
46 |
+
* Resizing thickbox on change in window dimensions
|
47 |
+
* Setting a max width and height of 1280x800 px for readability and to lessen distortion
|
48 |
+
*/
|
49 |
+
function resize_thickbox(){
|
50 |
+
TB_WIDTH=Math.min(1280,0.6*jQuery(window).width());
|
51 |
+
TB_HEIGHT=Math.min(800,0.9*jQuery(window).height());
|
52 |
+
jQuery(document).find('#TB_ajaxContent').width(TB_WIDTH-35).height(TB_HEIGHT-90);
|
53 |
+
jQuery(document).find('#TB_window').width(TB_WIDTH).height(TB_HEIGHT);
|
54 |
+
jQuery(document).find('#TB_window').css({marginLeft: '-' + TB_WIDTH / 2 + 'px',top: TB_HEIGHT/12});
|
55 |
+
jQuery(document).find('#TB_window').removeClass();
|
56 |
+
}
|
57 |
+
|
58 |
+
/**
|
59 |
+
* Ensure a button click on a return key press event
|
60 |
+
*
|
61 |
+
* @param HTML_DOM_EVENT event OnKeyPress event
|
62 |
+
* @param HTML_DOM_OBJECT button_to_click Button id to click on a return key press event
|
63 |
+
*/
|
64 |
+
function aalb_submit_event(event,button_to_click) {
|
65 |
+
//Code for the RETURN key is 13
|
66 |
+
if(event.keyCode==13) {
|
67 |
+
event.preventDefault();
|
68 |
+
jQuery('#'+button_to_click).click();
|
69 |
+
}
|
70 |
+
}
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Removes the selected HTML element
|
74 |
+
*
|
75 |
+
* @param HTML_DOM_OBJECT element HTML element to be removed
|
76 |
+
*/
|
77 |
+
function aalb_remove_selected_item(element) {
|
78 |
+
jQuery(element).remove();
|
79 |
+
}
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Display pop up thickbox
|
83 |
+
*/
|
84 |
+
function aalb_admin_show_create_shortcode_popup() {
|
85 |
+
// http://stackoverflow.com/questions/5557641/how-can-i-reset-div-to-its-original-state-after-it-has-been-modified-by-java
|
86 |
+
jQuery("#aalb-admin-popup-content").html(jQuery("#aalb-admin-popup-content").data('old-state'));
|
87 |
+
var keywords = jQuery("#aalb-admin-input-search").val();
|
88 |
+
if (keywords) {
|
89 |
+
// Showing the TB and resetting the width - http://wordpress.stackexchange.com/questions/114107/thickbox-width-cant-be-changed-in-admin
|
90 |
+
tb_show('Add Amazon Associates Link Builder Shortcode', '#TB_inline?inlineId=aalb-admin-popup-container',false);
|
91 |
+
resize_thickbox();
|
92 |
+
|
93 |
+
// Getting the ItemSearch results
|
94 |
+
aalb_admin_get_item_search_items(jQuery("#aalb-admin-input-search").val());
|
95 |
+
jQuery("#aalb-admin-popup-input-search").attr('value',keywords);
|
96 |
+
|
97 |
+
} else {
|
98 |
+
alert("Please enter the keywords");
|
99 |
+
jQuery("#aalb-admin-input-search").focus();
|
100 |
+
}
|
101 |
+
|
102 |
+
}
|
103 |
+
|
104 |
+
/**
|
105 |
+
* Search items from within the thickbox
|
106 |
+
*/
|
107 |
+
function aalb_admin_popup_search_items() {
|
108 |
+
var keywords = jQuery("#aalb-admin-popup-input-search").val();
|
109 |
+
jQuery("#aalb-admin-popup-content").html(jQuery("#aalb-admin-popup-content").data('old-state'));
|
110 |
+
if (keywords) {
|
111 |
+
// Getting the ItemSearch results
|
112 |
+
aalb_admin_get_item_search_items(keywords);
|
113 |
+
jQuery("#aalb-admin-popup-input-search").attr('value',keywords);
|
114 |
+
|
115 |
+
} else {
|
116 |
+
alert("Please enter the keywords");
|
117 |
+
jQuery("#aalb-admin-popup-input-search").focus();
|
118 |
+
}
|
119 |
+
}
|
120 |
+
|
121 |
+
/**
|
122 |
+
* Search items for the keywords and display it in the pop up thickbox
|
123 |
+
*
|
124 |
+
* @param String keywords Items to search for.
|
125 |
+
*/
|
126 |
+
function aalb_admin_get_item_search_items(keywords) {
|
127 |
+
marketplace = aalb_get_selected_marketplace();
|
128 |
+
marketplace = marketplace ? marketplace : api_pref.marketplace;
|
129 |
+
jQuery.get( api_pref.ajax_url, { "action" : api_pref.action, "item_search_nonce" : api_pref.item_search_nonce, "keywords" : keywords, "marketplace" : marketplace, "store_id" : api_pref.store_id}, function(xml) {
|
130 |
+
var items_xml = jQuery(xml).find("Item");
|
131 |
+
if(items_xml.length>0) {
|
132 |
+
var items = [];
|
133 |
+
var i=0;
|
134 |
+
items_xml.each(function() {
|
135 |
+
//selecting maximum of max_search_result_items elements
|
136 |
+
if(i<api_pref.max_search_result_items){
|
137 |
+
var item = {};
|
138 |
+
item.asin = jQuery(this).find("ASIN").text();
|
139 |
+
item.title = jQuery(this).find("Title").text();
|
140 |
+
item.image = jQuery(this).find("LargeImage").first().find("URL").text();
|
141 |
+
item.price = jQuery(this).find("LowestNewPrice").find("FormattedPrice").text();
|
142 |
+
items.push(item);
|
143 |
+
}
|
144 |
+
i++;
|
145 |
+
});
|
146 |
+
|
147 |
+
var html = template(items);
|
148 |
+
jQuery(".aalb-admin-item-search-items").append(html);
|
149 |
+
jQuery("#aalb-admin-popup-more-results").attr('href',jQuery(xml).find("MoreSearchResultsUrl").text());
|
150 |
+
jQuery(".aalb-admin-item-search-loading").slideUp("slow");
|
151 |
+
jQuery(".aalb-admin-item-search").fadeIn("slow");
|
152 |
+
jQuery(".aalb-admin-item-search-items-item").on("click", function() {
|
153 |
+
var dataAsin = jQuery(this).attr("data-asin");
|
154 |
+
var productImage = jQuery(this).find("img").attr("src");
|
155 |
+
var productTitle = jQuery(this).find("div.aalb-admin-item-search-items-item-title").text();
|
156 |
+
var productPrice = jQuery(this).find("div.aalb-admin-item-search-items-item-price").text();
|
157 |
+
|
158 |
+
var selectedAsinHTML = '<div class="aalb-selected-item" onclick="aalb_remove_selected_item(this)"';
|
159 |
+
selectedAsinHTML += ' data-asin="' + dataAsin + '">';
|
160 |
+
selectedAsinHTML += '<div class="aalb-selected-item-img-wrap"><span class="aalb-selected-item-close">×</span>';
|
161 |
+
selectedAsinHTML += '<img class="aalb-selected-item-img" src="' + productImage + '"></img></div>';
|
162 |
+
selectedAsinHTML += '<div class="aalb-selected-item-title"><h3>' + productTitle + '</h3>';
|
163 |
+
selectedAsinHTML += '<p class="aalb-selected-item-price">' + productPrice + '<br></p></div>';
|
164 |
+
|
165 |
+
jQuery(".aalb-selected").append(selectedAsinHTML);
|
166 |
+
});
|
167 |
+
} else {
|
168 |
+
errors_xml = jQuery(xml).find("Error");
|
169 |
+
if(errors_xml.length > 0) {
|
170 |
+
var htmlerror = "";
|
171 |
+
errors_xml.each(function() {
|
172 |
+
htmlerror += jQuery(this).find("Message").text() + "<br>";
|
173 |
+
});
|
174 |
+
jQuery(".aalb-admin-item-search-loading").html(htmlerror);
|
175 |
+
} else {
|
176 |
+
jQuery(".aalb-admin-item-search-loading").html(xml);
|
177 |
+
}
|
178 |
+
}
|
179 |
+
});
|
180 |
+
jQuery("#aalb-add-shortcode-button").unbind().click(function(){
|
181 |
+
var selectedAsins=aalb_get_selected_asins();
|
182 |
+
if(selectedAsins){
|
183 |
+
jQuery("#aalb-add-shortcode-alert").fadeTo("fast",1);
|
184 |
+
aalb_add_shortcode(AALB_SHORTCODE_AMAZON_LINK);
|
185 |
+
}else{
|
186 |
+
alert("Please select atleast one product for display");
|
187 |
+
}
|
188 |
+
});
|
189 |
+
}
|
190 |
+
|
191 |
+
/**
|
192 |
+
* Adds the given shortcode to the editor
|
193 |
+
*
|
194 |
+
* @param String Shortcode type to be added
|
195 |
+
*/
|
196 |
+
function aalb_add_shortcode(shortcodeName) {
|
197 |
+
var shortcodeJson;
|
198 |
+
if(shortcodeName == AALB_SHORTCODE_AMAZON_LINK) {
|
199 |
+
var selectedAsins=aalb_get_selected_asins();
|
200 |
+
var selectedTemplate=aalb_get_selected_template();
|
201 |
+
var selectedStore=aalb_get_selected_store();
|
202 |
+
var selectedMarketplace=aalb_get_selected_marketplace_abbreviation();
|
203 |
+
|
204 |
+
shortcodeJson = {
|
205 |
+
"name" : AALB_SHORTCODE_AMAZON_LINK,
|
206 |
+
"params" : {
|
207 |
+
"asins" : selectedAsins,
|
208 |
+
"template" : selectedTemplate,
|
209 |
+
"store" : selectedStore,
|
210 |
+
"marketplace" : selectedMarketplace,
|
211 |
+
}
|
212 |
+
};
|
213 |
+
aalb_get_link_id(shortcodeJson);
|
214 |
+
}
|
215 |
+
else {
|
216 |
+
console.log("Invalid Shortcode provided!");
|
217 |
+
return;
|
218 |
+
}
|
219 |
+
}
|
220 |
+
|
221 |
+
/**
|
222 |
+
* Handler function when the Add Shortcode button is clicked
|
223 |
+
* and link id is retrieved.
|
224 |
+
*
|
225 |
+
* @param Object shortcodeJson Object describing the shortcode
|
226 |
+
*/
|
227 |
+
function aalb_add_shortcode_click_handler(shortcodeJson) {
|
228 |
+
aalb_create_shortcode(shortcodeJson);
|
229 |
+
tb_remove();
|
230 |
+
}
|
231 |
+
|
232 |
+
/**
|
233 |
+
* Builds shortcode from given JSON
|
234 |
+
*
|
235 |
+
* @param Object shortcodeJson Object describing the shortcode
|
236 |
+
*
|
237 |
+
* @return String returns the Shortcode String
|
238 |
+
*/
|
239 |
+
function buildShortcode(shortcodeJson) {
|
240 |
+
var shortcodeParamsString = "";
|
241 |
+
for (var shortcodeParam in shortcodeJson.params) {
|
242 |
+
if( shortcodeJson.params.hasOwnProperty(shortcodeParam) ) {
|
243 |
+
shortcodeParamsString += " " + shortcodeParam + "='" + shortcodeJson.params[shortcodeParam] + "'";
|
244 |
+
}
|
245 |
+
}
|
246 |
+
|
247 |
+
var shortcodeString = "[" + shortcodeJson.name + shortcodeParamsString + "]";
|
248 |
+
return shortcodeString;
|
249 |
+
}
|
250 |
+
|
251 |
+
/**
|
252 |
+
* Get unique link id whenever add shortcode button is clicked
|
253 |
+
*
|
254 |
+
* @param Object shortcodeJson Object describing the shortcode
|
255 |
+
*/
|
256 |
+
function aalb_get_link_id(shortcodeJson){
|
257 |
+
jQuery.post( api_pref.ajax_url, { "action" : "get_link_code", "shortcode_name":shortcodeJson.name, "shortcode_params":shortcodeJson.params}, function(json) {
|
258 |
+
link_id = json;
|
259 |
+
shortcodeJson.params.link_id=link_id;
|
260 |
+
jQuery("#aalb-add-shortcode-alert").fadeTo("slow",0);
|
261 |
+
aalb_add_shortcode_click_handler(shortcodeJson);
|
262 |
+
});
|
263 |
+
}
|
264 |
+
|
265 |
+
/**
|
266 |
+
* Add the shortcode to the display editor
|
267 |
+
*
|
268 |
+
* @param Object shortcodeJson Object describing the shortcode
|
269 |
+
*/
|
270 |
+
function aalb_create_shortcode(shortcodeJson) {
|
271 |
+
send_to_editor(buildShortcode(shortcodeJson));
|
272 |
+
}
|
273 |
+
|
274 |
+
/**
|
275 |
+
* Get the selected Asins
|
276 |
+
*
|
277 |
+
* @return String Selected Asins
|
278 |
+
*/
|
279 |
+
function aalb_get_selected_asins() {
|
280 |
+
var selectedAsins = "";
|
281 |
+
jQuery(".aalb-selected-item").each(function(){
|
282 |
+
selectedAsins += jQuery(this).attr("data-asin") + ",";
|
283 |
+
});
|
284 |
+
return selectedAsins.slice(0,-1);
|
285 |
+
}
|
286 |
+
|
287 |
+
/**
|
288 |
+
* Get the selected Template style
|
289 |
+
*
|
290 |
+
* @ereturn String Selected Template style
|
291 |
+
*/
|
292 |
+
function aalb_get_selected_template() {
|
293 |
+
var selectedTemplate = "";
|
294 |
+
var $selectedTemplate = jQuery("#aalb_template_names_list option:selected");
|
295 |
+
if ($selectedTemplate.length > 0) {
|
296 |
+
selectedTemplate = $selectedTemplate.val();
|
297 |
+
}
|
298 |
+
return selectedTemplate;
|
299 |
+
}
|
300 |
+
|
301 |
+
/**
|
302 |
+
* Get the selected associate tag
|
303 |
+
*
|
304 |
+
* @return String Selected Associate tag
|
305 |
+
*/
|
306 |
+
function aalb_get_selected_store() {
|
307 |
+
return jQuery('#aalb-admin-popup-store-id').val();
|
308 |
+
}
|
309 |
+
|
310 |
+
/**
|
311 |
+
* Get the selected marketplace
|
312 |
+
*
|
313 |
+
* @return String Selected Marketplace to search the product
|
314 |
+
*/
|
315 |
+
function aalb_get_selected_marketplace() {
|
316 |
+
var selectedMarketplace = "";
|
317 |
+
var $selectedMarketplace = jQuery("#aalb_marketplace_names_list option:selected");
|
318 |
+
if ($selectedMarketplace.length > 0) {
|
319 |
+
selectedMarketplace = $selectedMarketplace.val();
|
320 |
+
}
|
321 |
+
return selectedMarketplace;
|
322 |
+
}
|
323 |
+
|
324 |
+
/**
|
325 |
+
* Get the selected marketplace abbreviation
|
326 |
+
*
|
327 |
+
* @return String Selected Marketplace abbreviation for the shortcode
|
328 |
+
*/
|
329 |
+
function aalb_get_selected_marketplace_abbreviation() {
|
330 |
+
var selectedMarketplace = "";
|
331 |
+
var $selectedMarketplace = jQuery("#aalb_marketplace_names_list option:selected");
|
332 |
+
if ($selectedMarketplace.length > 0) {
|
333 |
+
selectedMarketplace = $selectedMarketplace.text();
|
334 |
+
}
|
335 |
+
return selectedMarketplace;
|
336 |
+
}
|
admin/partials/aalb_meta_box.php
ADDED
@@ -0,0 +1,91 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
Copyright 2016-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
5 |
+
|
6 |
+
Licensed under the GNU General Public License as published by the Free Software Foundation,
|
7 |
+
Version 2.0 (the "License"). You may not use this file except in compliance with the License.
|
8 |
+
A copy of the License is located in the "license" file accompanying this file.
|
9 |
+
|
10 |
+
This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
11 |
+
either express or implied. See the License for the specific language governing permissions
|
12 |
+
and limitations under the License.
|
13 |
+
*/
|
14 |
+
|
15 |
+
$aalb_template_names = get_option(AALB_TEMPLATE_NAMES);
|
16 |
+
$config_loader = new Aalb_Config_Loader();
|
17 |
+
$aalb_marketplace_names = $config_loader->fetch_marketplaces();
|
18 |
+
$helper = new Aalb_Helper();
|
19 |
+
$aalb_store_id_names = $helper->get_store_ids_array();
|
20 |
+
?>
|
21 |
+
<div id="aalb-admin-searchbox">
|
22 |
+
<img src=<?=AALB_ADMIN_ICON?> id="aalb-admin-searchbox-amzlogo"><input type="text" id="aalb-admin-input-search" name="aalb-admin-input-search" placeholder="Enter keyword(s)" onkeypress='aalb_submit_event(event,"aalb-admin-button-create-amazon-shortcode")'/><a class="button" title="Add Amazon Associates Link Builder Shortcode" id="aalb-admin-button-create-amazon-shortcode" onclick="aalb_admin_show_create_shortcode_popup()">Search</a>
|
23 |
+
</div>
|
24 |
+
<div id="aalb-admin-popup-container" style="display:none;">
|
25 |
+
<div class="aalb-admin-popup-options">
|
26 |
+
<input type="text" id="aalb-admin-popup-input-search" name="aalb-admin-popup-input-search" placeholder="Enter keyword(s)" onkeypress='aalb_submit_event(event,"aalb-admin-popup-search-button")'/>
|
27 |
+
<button class="aalb-btn aalb-btn-primary" id="aalb-admin-popup-search-button" type="button" onclick="aalb_admin_popup_search_items()" style="margin-top:1%">Search</button>
|
28 |
+
</div><!--end .aalb-admin-popup-options-->
|
29 |
+
<div id="aalb-admin-popup-content">
|
30 |
+
<div class="aalb-admin-alert aalb-admin-alert-info aalb-admin-item-search-loading"><div class="aalb-admin-icon"><i class="fa fa-spinner fa-pulse"></i></div>Searching relevant products from Amazon
|
31 |
+
</div><!--end .aalb-admin-item-search-loading-->
|
32 |
+
<div class="aalb-admin-item-search">
|
33 |
+
Click to select product(s) to advertise
|
34 |
+
<div class="aalb-admin-item-search-items"></div>
|
35 |
+
<a href="#" target="_blank" id="aalb-admin-popup-more-results" class="pull-right">Check more search results on Amazon</a>
|
36 |
+
</div><!--end .aalb-admin-item-serch-->
|
37 |
+
</div><!--end .aalb-admin-popup-content-->
|
38 |
+
<div class="aalb-selected">
|
39 |
+
<label>List of Selected Products</label>
|
40 |
+
</div>
|
41 |
+
<div class="aalb-admin-popup-shortocde-wrapper">
|
42 |
+
<div class="aalb-admin-popup-shortcode-options">
|
43 |
+
<div class="aalb-admin-item-search-templates">
|
44 |
+
<label>Ad Template</label>
|
45 |
+
<?php $aalb_default_template=get_option(AALB_DEFAULT_TEMPLATE,AALB_DEFAULT_TEMPLATE_NAME);?>
|
46 |
+
<select id="aalb_template_names_list" name="aalb_template_names_list" style="width:100%">
|
47 |
+
<?php
|
48 |
+
foreach ($aalb_template_names as $aalb_template_name) {
|
49 |
+
?>
|
50 |
+
<option value="<?=$aalb_template_name?>" <?php selected($aalb_default_template,$aalb_template_name); ?>><?=$aalb_template_name?></option>
|
51 |
+
<?php
|
52 |
+
}
|
53 |
+
?>
|
54 |
+
</select>
|
55 |
+
</div>
|
56 |
+
<div class="aalb-admin-popup-store">
|
57 |
+
<label>Associate ID</label>
|
58 |
+
<?php $aalb_default_store_id=get_option(AALB_DEFAULT_STORE_ID,AALB_DEFAULT_STORE_ID_NAME);?>
|
59 |
+
<select id="aalb-admin-popup-store-id" name="aalb-admin-popup-store-id" style="width:100%">
|
60 |
+
<?php
|
61 |
+
foreach ($aalb_store_id_names as $aalb_store_id) {
|
62 |
+
?>
|
63 |
+
<option value="<?=$aalb_store_id?>" <?php selected($aalb_default_store_id,$aalb_store_id); ?>><?=$aalb_store_id?></option>
|
64 |
+
<?php
|
65 |
+
}
|
66 |
+
?>
|
67 |
+
</select>
|
68 |
+
</div>
|
69 |
+
<div class="aalb-admin-item-search-marketplaces">
|
70 |
+
<label>Marketplace</label>
|
71 |
+
<?php $aalb_default_marketplace=get_option(AALB_DEFAULT_MARKETPLACE,AALB_DEFAULT_MARKETPLACE_NAME);?>
|
72 |
+
<select id="aalb_marketplace_names_list" name="aalb_marketplace_names_list" style="width:100%">
|
73 |
+
<?php
|
74 |
+
foreach ($aalb_marketplace_names as $aalb_marketplace => $aalb_marketplace_abbr) {
|
75 |
+
?>
|
76 |
+
<option value="<?=$aalb_marketplace?>" <?php selected($aalb_default_marketplace,$aalb_marketplace_abbr); ?>><?=$aalb_marketplace_abbr?></option>
|
77 |
+
<?php
|
78 |
+
}
|
79 |
+
?>
|
80 |
+
</select>
|
81 |
+
</div>
|
82 |
+
</div>
|
83 |
+
</div><!--end .aalb-admin-popup-shortcode-options-->
|
84 |
+
<div class="aalb-add-shortcode-button">
|
85 |
+
<button class="aalb-btn aalb-btn-primary" id="aalb-add-shortcode-button" type="button">Add Shortcode</button>
|
86 |
+
<div id="aalb-add-shortcode-alert"><div class="aalb-admin-icon"><i class="fa fa-spinner fa-pulse"></i></div>Creating shortcode. Please wait....
|
87 |
+
</div>
|
88 |
+
</div><!--end .aalb-add-shortcode-button-->
|
89 |
+
</div><!--end .aalb-admin-popup-container-->
|
90 |
+
<?php
|
91 |
+
?>
|
admin/sidebar/aalb_sidebar.php
ADDED
@@ -0,0 +1,129 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
Copyright 2016-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
5 |
+
|
6 |
+
Licensed under the GNU General Public License as published by the Free Software Foundation,
|
7 |
+
Version 2.0 (the "License"). You may not use this file except in compliance with the License.
|
8 |
+
A copy of the License is located in the "license" file accompanying this file.
|
9 |
+
|
10 |
+
This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
11 |
+
either express or implied. See the License for the specific language governing permissions
|
12 |
+
and limitations under the License.
|
13 |
+
*/
|
14 |
+
|
15 |
+
/**
|
16 |
+
* The class for adding menu and submenu pages on the sidebar.
|
17 |
+
* Registers the settings using the Wordpress Settings API for suing in the partials
|
18 |
+
*
|
19 |
+
* @since 1.0.0
|
20 |
+
* @package AmazonAssociatesLinkBuilder
|
21 |
+
* @subpackage AmazonAssociatesLinkBuilder/admin/sidebar
|
22 |
+
*/
|
23 |
+
class Aalb_Sidebar {
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Adds categories to the menu page
|
27 |
+
*
|
28 |
+
* @since 1.0.0
|
29 |
+
*/
|
30 |
+
public function register_sidebar_config_page() {
|
31 |
+
// Create new top-level menu
|
32 |
+
add_menu_page(AALB_PROJECT_TITLE, AALB_PROJECT_TITLE, 'manage_options', 'associates-link-builder-about', array($this, 'about_callback'), AALB_ICON);
|
33 |
+
add_submenu_page('associates-link-builder-about', 'Configure ' . AALB_PROJECT_TITLE . ' About', 'About', 'manage_options', 'associates-link-builder-about', array($this, 'about_callback'));
|
34 |
+
add_submenu_page('associates-link-builder-about', 'Configure ' . AALB_PROJECT_TITLE . ' Settings', 'Settings', 'manage_options', 'associates-link-builder-settings', array($this, 'settings_callback'));
|
35 |
+
add_submenu_page('associates-link-builder-about', 'Configure ' . AALB_PROJECT_TITLE . ' Templates', 'Templates', 'manage_options', 'associates-link-builder-templates', array($this, 'templates_callback'));
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Registers credentials to the config group
|
40 |
+
*
|
41 |
+
* @since 1.0.0
|
42 |
+
*/
|
43 |
+
public function register_cred_config_group() {
|
44 |
+
// Register Credentials
|
45 |
+
register_setting(AALB_CRED_CONFIG_GROUP, AALB_AWS_ACCESS_KEY, array($this, 'validate_access_key'));
|
46 |
+
register_setting(AALB_CRED_CONFIG_GROUP, AALB_AWS_SECRET_KEY, array($this, 'validate_secret_key'));
|
47 |
+
register_setting(AALB_CRED_CONFIG_GROUP, AALB_DEFAULT_STORE_ID);
|
48 |
+
register_setting(AALB_CRED_CONFIG_GROUP, AALB_DEFAULT_MARKETPLACE);
|
49 |
+
register_setting(AALB_CRED_CONFIG_GROUP, AALB_DEFAULT_TEMPLATE);
|
50 |
+
register_setting(AALB_CRED_CONFIG_GROUP, AALB_STORE_ID_NAMES);
|
51 |
+
}
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Load the about page partial
|
55 |
+
* Callbacks to load the page makes the url to use the slug, making it clean.
|
56 |
+
*
|
57 |
+
* @since 1.0.0
|
58 |
+
*/
|
59 |
+
public function about_callback() {
|
60 |
+
require_once(AALB_ABOUT_PHP);
|
61 |
+
}
|
62 |
+
|
63 |
+
/**
|
64 |
+
* Load the settings page partial
|
65 |
+
* The page to save the credentials and default settings of the admin.
|
66 |
+
*
|
67 |
+
* @since 1.0.0
|
68 |
+
*/
|
69 |
+
public function settings_callback() {
|
70 |
+
require_once(AALB_CREDENTIALS_PHP);
|
71 |
+
}
|
72 |
+
|
73 |
+
/**
|
74 |
+
* Load the template page partial
|
75 |
+
* The page to make changes to the templates, add new templates or remove existing templates.
|
76 |
+
*
|
77 |
+
* @since 1.0.0
|
78 |
+
*/
|
79 |
+
public function templates_callback() {
|
80 |
+
require_once(AALB_TEMPLATE_PHP);
|
81 |
+
}
|
82 |
+
|
83 |
+
/**
|
84 |
+
* Sanitize the access key provided by the admin.
|
85 |
+
* Encrypt the access key and store in the db.
|
86 |
+
*
|
87 |
+
* @since 1.0.0
|
88 |
+
* @param string $input Access key input by the user.
|
89 |
+
*/
|
90 |
+
public function validate_access_key($input) {
|
91 |
+
$old_data = get_option(AALB_AWS_ACCESS_KEY);
|
92 |
+
return $this->encrypt_keys($input, $old_data);
|
93 |
+
}
|
94 |
+
|
95 |
+
/**
|
96 |
+
* Sanitize the secret key provided by the admin.
|
97 |
+
* Encrypt the secret key and store in the db.
|
98 |
+
*
|
99 |
+
* @since 1.0.0
|
100 |
+
* @param string $input Secret key input by the user.
|
101 |
+
*/
|
102 |
+
public function validate_secret_key($input) {
|
103 |
+
$old_data = get_option(AALB_AWS_SECRET_KEY);
|
104 |
+
return $this->encrypt_keys($input, $old_data);
|
105 |
+
}
|
106 |
+
|
107 |
+
/**
|
108 |
+
* Encrypt the keys provided by the user.
|
109 |
+
* If the data already exists in the database, then do not retrieve and print it on the viewer page.
|
110 |
+
* Else encrypt the data and store it in the db.
|
111 |
+
*
|
112 |
+
* @since 1.0.0
|
113 |
+
* @param string $input Key input by the user to encrypt.
|
114 |
+
* @param string $old_data The data if already stored in the database.
|
115 |
+
*/
|
116 |
+
private function encrypt_keys($input, $old_data) {
|
117 |
+
if (!isset($input) || trim($input) === '') {
|
118 |
+
return $input;
|
119 |
+
} elseif ($input == AALB_AWS_SECRET_KEY_MASK){
|
120 |
+
return $old_data;
|
121 |
+
}
|
122 |
+
|
123 |
+
$output = base64_encode(openssl_encrypt($input, AALB_ENCRYPTION_ALGORITHM, AALB_ENCRYPTION_KEY, 0, AALB_ENCRYPTION_IV));
|
124 |
+
return $output;
|
125 |
+
}
|
126 |
+
|
127 |
+
}
|
128 |
+
|
129 |
+
?>
|
admin/sidebar/js/aalb_credentials.js
ADDED
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*
|
2 |
+
Copyright 2016-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
3 |
+
|
4 |
+
Licensed under the GNU General Public License as published by the Free Software Foundation,
|
5 |
+
Version 2.0 (the "License"). You may not use this file except in compliance with the License.
|
6 |
+
A copy of the License is located in the "license" file accompanying this file.
|
7 |
+
|
8 |
+
This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
9 |
+
either express or implied. See the License for the specific language governing permissions
|
10 |
+
and limitations under the License.
|
11 |
+
*/
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Update the Default Store ID dropdown onchange
|
15 |
+
*
|
16 |
+
* @param HTML DOM OBJECT element list of store IDs in "Store IDs" field
|
17 |
+
*/
|
18 |
+
function aalb_credentials_store_ids_onchange(element) {
|
19 |
+
var aalb_store_ids = element.value;
|
20 |
+
var aalb_store_ids_array = aalb_store_ids.trim().split(/[\n]+/);
|
21 |
+
//Selected Store ID
|
22 |
+
var aalb_store_ids_selected = jQuery('#aalb_default_store_id').val();
|
23 |
+
var aalb_store_id_dropdown_html = "";
|
24 |
+
for(var i = 0; i < aalb_store_ids_array.length; i++) {
|
25 |
+
if(aalb_store_ids_array[i].length>0){
|
26 |
+
aalb_store_ids_array[i] = aalb_store_ids_array[i].trim();
|
27 |
+
aalb_store_id_dropdown_html += "<option value='" + aalb_store_ids_array[i] + "'>" + aalb_store_ids_array[i] + "</option>\n";
|
28 |
+
} else {
|
29 |
+
//Remove empty lines
|
30 |
+
aalb_store_ids_array.splice(i,1);
|
31 |
+
}
|
32 |
+
}
|
33 |
+
jQuery('#aalb_store_id_names').val(aalb_store_ids_array.join("\r\n"));
|
34 |
+
//Set the HTML of select dropdown with updated store ids
|
35 |
+
jQuery('#aalb_default_store_id').html(aalb_store_id_dropdown_html);
|
36 |
+
//Select the previously selected option value if it exists in the new list
|
37 |
+
if (aalb_store_ids_selected.length > 0 && jQuery.inArray(aalb_store_ids_selected, aalb_store_ids_array) > 0){
|
38 |
+
jQuery('#aalb_default_store_id').val(aalb_store_ids_selected);
|
39 |
+
} else {
|
40 |
+
//If no value is selected, automatically selects first element.
|
41 |
+
jQuery("#aalb_default_store_id").val(jQuery("#aalb_default_store_id option:first").val());
|
42 |
+
}
|
43 |
+
}
|
44 |
+
/**
|
45 |
+
* OnClick Handler for aalb terms and conditions checkbox.
|
46 |
+
*
|
47 |
+
*/
|
48 |
+
jQuery('#aalb-terms-checkbox').click(function(){
|
49 |
+
if(jQuery(this).is(':checked')){
|
50 |
+
jQuery("#submit").removeAttr('disabled');
|
51 |
+
} else {
|
52 |
+
jQuery('#submit').attr('disabled','disabled');
|
53 |
+
}
|
54 |
+
});
|
admin/sidebar/js/aalb_template.js
ADDED
@@ -0,0 +1,88 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*
|
2 |
+
Copyright 2016-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
3 |
+
|
4 |
+
Licensed under the GNU General Public License as published by the Free Software Foundation,
|
5 |
+
Version 2.0 (the "License"). You may not use this file except in compliance with the License.
|
6 |
+
A copy of the License is located in the "license" file accompanying this file.
|
7 |
+
|
8 |
+
This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
9 |
+
either express or implied. See the License for the specific language governing permissions
|
10 |
+
and limitations under the License.
|
11 |
+
*/
|
12 |
+
|
13 |
+
var codeMirrorHtml = CodeMirror.fromTextArea(document.getElementById('aalb_template_template_html_box'), {
|
14 |
+
lineNumbers: true,
|
15 |
+
value: "",
|
16 |
+
mode: "xml"
|
17 |
+
});
|
18 |
+
|
19 |
+
var codeMirrorCss = CodeMirror.fromTextArea(document.getElementById('aalb_template_template_css_box'), {
|
20 |
+
lineNumbers: true,
|
21 |
+
value: "",
|
22 |
+
mode: "css"
|
23 |
+
});
|
24 |
+
|
25 |
+
jQuery.ajaxSetup ({
|
26 |
+
//Disable caching of AJAX responses
|
27 |
+
cache: false
|
28 |
+
});
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Trigger onChange event of the template select dropdown on page load
|
32 |
+
*/
|
33 |
+
jQuery(document).ready(function() {
|
34 |
+
if(jQuery('#aalb_template_list_select').val() != 'new') {
|
35 |
+
jQuery("#aalb_template_list_select").trigger("change");
|
36 |
+
}
|
37 |
+
});
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Set the JS and CSS of the particular template in the respective text area
|
41 |
+
*
|
42 |
+
* @param HTML DOM OBJECT element Selected Template name
|
43 |
+
*/
|
44 |
+
function aalb_template_select_template_onchange(element) {
|
45 |
+
if (element.value == 'new') {
|
46 |
+
codeMirrorCss.setValue('');
|
47 |
+
codeMirrorHtml.setValue('');
|
48 |
+
jQuery('#aalb_template_name').removeAttr("readonly");
|
49 |
+
jQuery('#aalb_template_name').val('');
|
50 |
+
jQuery('#clone_template').attr('disabled','disabled');
|
51 |
+
} else {
|
52 |
+
jQuery('#clone_template').removeAttr('disabled');
|
53 |
+
jQuery('#aalb_template_name').val(element.value);
|
54 |
+
jQuery('#aalb_template_name').attr("readonly", "readonly");
|
55 |
+
base = wp_opt.plugin_url + "template/" + element.value;
|
56 |
+
jQuery.get(base+".css", function(data) {
|
57 |
+
codeMirrorCss.setValue(data);
|
58 |
+
});
|
59 |
+
jQuery.get(base+".mustache", function(data) {
|
60 |
+
codeMirrorHtml.setValue(data);
|
61 |
+
});
|
62 |
+
//Make the Amazon Default templates as Read-Only
|
63 |
+
if(wp_opt.aalb_default_templates.split(",").indexOf(element.value)>=0) {
|
64 |
+
codeMirrorHtml.setOption("readOnly", true);
|
65 |
+
codeMirrorCss.setOption("readOnly", true);
|
66 |
+
}
|
67 |
+
}
|
68 |
+
}
|
69 |
+
|
70 |
+
/**
|
71 |
+
* Clones an existing template into a new one.
|
72 |
+
*
|
73 |
+
*/
|
74 |
+
function clone_existing_template() {
|
75 |
+
var templateNameToClone = jQuery('#aalb_template_list_select').val();
|
76 |
+
jQuery('#aalb_template_list_select').val('new');
|
77 |
+
jQuery('#aalb_template_name').removeAttr("readonly");
|
78 |
+
jQuery('#aalb_template_name').val('CopyOf-' + templateNameToClone);
|
79 |
+
jQuery('#clone_template').attr('disabled','disabled');
|
80 |
+
//Add CSS Prefix for Amazon Default Templates to prevent style overlapping for clones
|
81 |
+
if(wp_opt.aalb_default_templates.split(",").indexOf(templateNameToClone)>=0) {
|
82 |
+
var randomNumForPrefix = Math.floor((Math.random() * 1000) + 1);
|
83 |
+
var prefixRegExObject = new RegExp('aalb-', "g");
|
84 |
+
var prefixReplaceValue = 'aalb-' + randomNumForPrefix + '-';
|
85 |
+
codeMirrorHtml.setValue(codeMirrorHtml.getValue().replace(prefixRegExObject, prefixReplaceValue));
|
86 |
+
codeMirrorCss.setValue(codeMirrorCss.getValue().replace(prefixRegExObject, prefixReplaceValue));
|
87 |
+
}
|
88 |
+
}
|
admin/sidebar/partials/aalb_about.php
ADDED
@@ -0,0 +1,141 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
Copyright 2016-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
5 |
+
|
6 |
+
Licensed under the GNU General Public License as published by the Free Software Foundation,
|
7 |
+
Version 2.0 (the "License"). You may not use this file except in compliance with the License.
|
8 |
+
A copy of the License is located in the "license" file accompanying this file.
|
9 |
+
|
10 |
+
This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
11 |
+
either express or implied. See the License for the specific language governing permissions
|
12 |
+
and limitations under the License.
|
13 |
+
*/
|
14 |
+
|
15 |
+
include 'aalb_admin_ui_common.php'; ?>
|
16 |
+
<div class="wrap">
|
17 |
+
<h2><?=AALB_PROJECT_TITLE?></h2>
|
18 |
+
<div class="card" style="max-width:100%;">
|
19 |
+
<h2>About Amazon Associates Program</h2>
|
20 |
+
<p>
|
21 |
+
The Amazon Associates Program is one of the original affiliate marketing programs. Available in geographies across the globe, the Amazon Associates Program has been partnering with content creators to help them monetize their passions since 1996. To learn more about the Amazon Associates Program, please click <a target="_blank" href="https://affiliate-program.amazon.com/">here</a>.
|
22 |
+
</p>
|
23 |
+
<h2>About Amazon Associates Link Builder </h2>
|
24 |
+
<p>
|
25 |
+
Link Builder is the official free Amazon Associates Program plugin for WordPress. The plugin enables you to search for products in the Amazon catalog, access real-time price and availability information, and easily create links in your posts to products on Amazon.com. You will be able to generate text links, create custom ad units, or take advantage of out-of-the-box widgets that we’ve designed and included with the plugin.
|
26 |
+
</p>
|
27 |
+
<b>Note</b>
|
28 |
+
<ul>
|
29 |
+
<li>
|
30 |
+
You must review and accept the Amazon Associates Link Builder Conditions of Use as applicable for your region – <a target="_blank" href="https://s3.amazonaws.com/aalb-public-resources/documents/AssociatesLinkBuilder-ConditionsOfUse-US.pdf">US</a>, <a target="_blank" href="https://s3.amazonaws.com/aalb-public-resources/documents/AssociatesLinkBuilder-ConditionsOfUse-CA.pdf">CA</a>, <a target="_blank" href="https://s3.amazonaws.com/aalb-public-resources/documents/AssociatesLinkBuilder-ConditionsOfUse-EU.pdf">EU</a>.
|
31 |
+
</li>
|
32 |
+
<li>
|
33 |
+
The plugin is currently in beta form. We intend to regularly add new features and enhancements throughout the beta period and beyond, and welcome your feedback and input.
|
34 |
+
</li>
|
35 |
+
</ul>
|
36 |
+
<h2>Getting Started</h2>
|
37 |
+
<h3>Step 1 - Become an Associate</h3>
|
38 |
+
<p>
|
39 |
+
To become an Associate, create an Amazon Associates account using URL for your country:
|
40 |
+
</p>
|
41 |
+
<table border="0" cellpadding="10">
|
42 |
+
<tr>
|
43 |
+
<td><b>Brazil</b></td>
|
44 |
+
<td>
|
45 |
+
<a href="https://associados.amazon.com.br/" target="_blank">https://associados.amazon.com.br/</a>
|
46 |
+
</td>
|
47 |
+
</tr>
|
48 |
+
<tr>
|
49 |
+
<td><b>Canada</b></td>
|
50 |
+
<td>
|
51 |
+
<a href="https://associates.amazon.ca/" target="_blank">https://associates.amazon.ca/</a>
|
52 |
+
</td>
|
53 |
+
</tr>
|
54 |
+
<tr>
|
55 |
+
<td><b>China</b></td>
|
56 |
+
<td>
|
57 |
+
<a href="https://associates.amazon.cn/" target="_blank">https://associates.amazon.cn/</a>
|
58 |
+
</td>
|
59 |
+
</tr>
|
60 |
+
<tr>
|
61 |
+
<td><b>France</b></td>
|
62 |
+
<td>
|
63 |
+
<a href="http://partenaires.amazon.fr/" target="_blank">http://partenaires.amazon.fr/</a>
|
64 |
+
</td>
|
65 |
+
</tr>
|
66 |
+
<tr>
|
67 |
+
<td><b>Germany</b></td>
|
68 |
+
<td>
|
69 |
+
<a href="https://partnernet.amazon.de/" target="_blank">https://partnernet.amazon.de/</a>
|
70 |
+
</td>
|
71 |
+
</tr>
|
72 |
+
<tr>
|
73 |
+
<td><b>India</b></td>
|
74 |
+
<td>
|
75 |
+
<a href="http://affiliate-program.amazon.in/" target="_blank">http://affiliate-program.amazon.in/</a>
|
76 |
+
</td>
|
77 |
+
</tr>
|
78 |
+
<tr>
|
79 |
+
<td><b>Italy</b></td>
|
80 |
+
<td>
|
81 |
+
<a href="https://programma-affiliazione.amazon.it/" target="_blank">https://programma-affiliazione.amazon.it/</a>
|
82 |
+
</td>
|
83 |
+
</tr>
|
84 |
+
<tr>
|
85 |
+
<td><b>Japan</b></td>
|
86 |
+
<td>
|
87 |
+
<a href="https://affiliate.amazon.co.jp/" target="_blank">https://affiliate.amazon.co.jp/</a>
|
88 |
+
</td>
|
89 |
+
</tr>
|
90 |
+
<tr>
|
91 |
+
<td><b>Mexico</b></td>
|
92 |
+
<td>
|
93 |
+
<a href="https://afiliados.amazon.com.mx/" target="_blank">https://afiliados.amazon.com.mx/</a>
|
94 |
+
</td>
|
95 |
+
</tr>
|
96 |
+
<tr>
|
97 |
+
<td><b>Spain</b></td>
|
98 |
+
<td>
|
99 |
+
<a href="https://afiliados.amazon.es/" target="_blank">https://afiliados.amazon.es/</a>
|
100 |
+
</td>
|
101 |
+
</tr>
|
102 |
+
<tr>
|
103 |
+
<td><b>United Kingdom</b></td>
|
104 |
+
<td>
|
105 |
+
<a href="https://affiliate-program.amazon.co.uk/" target="_blank">https://affiliate-program.amazon.co.uk/</a>
|
106 |
+
</td>
|
107 |
+
</tr>
|
108 |
+
<tr>
|
109 |
+
<td><b>United States</b></td>
|
110 |
+
<td>
|
111 |
+
<a href="https://affiliate-program.amazon.com/" target="_blank">https://affiliate-program.amazon.com/</a>
|
112 |
+
</td>
|
113 |
+
</tr>
|
114 |
+
</table>
|
115 |
+
<p>
|
116 |
+
Your Associate ID works only in the country in which you register. If you’d like to be an Associate in more than one country, please register separately for each country.
|
117 |
+
</p>
|
118 |
+
<h3>Step 2 - Sign up for the Amazon Product Advertising API</h3>
|
119 |
+
<p>
|
120 |
+
Sign up for the Amazon Product Advertising API by following the instructions listed <a target="_blank" href="http://docs.aws.amazon.com/AWSECommerceService/latest/DG/CHAP_GettingStarted.html">here</a>. The Amazon Product Advertising API is a popular e-commerce service, powering Amazon-integrated experiences around the world, serving tens of thousands of applications and more than 1 billion API requests every day. It exposes a web-service, which allows Associates to programmatically search and look up items in the Amazon product catalog. The Link Builder plugin integrates the Product Advertising API, allowing you to access Amazon.com product catalog data without requiring additional software development.
|
121 |
+
</p>
|
122 |
+
<h3>Step 3 - Configure plugin for first use </h3>
|
123 |
+
<p>
|
124 |
+
Use the Associates Link Builder->Settings screen to configure the plugin.
|
125 |
+
</p>
|
126 |
+
<ol>
|
127 |
+
<li>Set Access Key ID and Secret Access Key in the Settings section. These credentials are used to invoke requests to the Amazon Product Advertising API for fetching information on an item.</li>
|
128 |
+
<li>Set default Associate ID. Associate ID is used to monitor traffic and sales from your links to Amazon. You can also define a list of valid Associate IDs (store ids or tracking ids). You should create a new tracking ID in your Amazon Associates account for using it as Associate ID in the plugin.</li>
|
129 |
+
<li>Set the default Amazon marketplace based on the Amazon Associates Program for which you are registered (for example, if you’ve signed up for the Amazon Associates Program in UK, then your default marketplace selection should be UK) and select an appropriate template for rendering your ads.</li>
|
130 |
+
</ol>
|
131 |
+
<p>
|
132 |
+
That's it! You’re all set to start adding Amazon affiliate links to your posts using the Amazon Associates Link Builder plugin!
|
133 |
+
</p>
|
134 |
+
<h2>User Guide</h2>
|
135 |
+
<p>
|
136 |
+
Review <a target="_blank" href="https://s3.amazonaws.com/aalb-public-resources/documents/AssociatesLinkBuilder-UserGuide.pdf">Link Builder User Guide</a> for more information on getting started and key features of the plugin.
|
137 |
+
</p>
|
138 |
+
<h2>Support</h2>
|
139 |
+
<p>If you get stuck, or have any questions, you can ask for help in the [Amazon Associates Link Builder plugin forum](https://wordpress.org/support/plugin/amazon-link-builder). </p>
|
140 |
+
</div>
|
141 |
+
</div>
|
admin/sidebar/partials/aalb_admin_ui_common.php
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
Copyright 2016-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
5 |
+
|
6 |
+
Licensed under the GNU General Public License as published by the Free Software Foundation,
|
7 |
+
Version 2.0 (the "License"). You may not use this file except in compliance with the License.
|
8 |
+
A copy of the License is located in the "license" file accompanying this file.
|
9 |
+
|
10 |
+
This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
11 |
+
either express or implied. See the License for the specific language governing permissions
|
12 |
+
and limitations under the License.
|
13 |
+
*/
|
14 |
+
|
15 |
+
//File with common functionalities for Admin pages.
|
16 |
+
|
17 |
+
include 'aalb_ui_common.php';
|
18 |
+
|
19 |
+
if (!is_admin())
|
20 |
+
die("Permission Denied");
|
21 |
+
|
22 |
+
if (!is_ssl()) {
|
23 |
+
//action when page is NOT using SSL
|
24 |
+
aalb_warning_notice('Adminstration of plugin should be done over a secure network. Please switch to HTTPS.');
|
25 |
+
}
|
26 |
+
|
27 |
+
?>
|
admin/sidebar/partials/aalb_credentials.php
ADDED
@@ -0,0 +1,115 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
Copyright 2016-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
5 |
+
|
6 |
+
Licensed under the GNU General Public License as published by the Free Software Foundation,
|
7 |
+
Version 2.0 (the "License"). You may not use this file except in compliance with the License.
|
8 |
+
A copy of the License is located in the "license" file accompanying this file.
|
9 |
+
|
10 |
+
This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
11 |
+
either express or implied. See the License for the specific language governing permissions
|
12 |
+
and limitations under the License.
|
13 |
+
*/
|
14 |
+
|
15 |
+
include 'aalb_admin_ui_common.php';
|
16 |
+
$helper = new Aalb_Helper();
|
17 |
+
$aalb_store_id_names = $helper->get_store_ids_array();
|
18 |
+
wp_enqueue_script('jquery');
|
19 |
+
wp_enqueue_script('aalb_credentials_js', AALB_CREDENTIALS_JS, array('jquery'));
|
20 |
+
wp_localize_script('aalb_credentials_js', 'wp_opt', array('plugin_url' => AALB_PLUGIN_URL));
|
21 |
+
?>
|
22 |
+
|
23 |
+
<div class="wrap">
|
24 |
+
<h2>Settings for <?=AALB_PROJECT_TITLE?></h2>
|
25 |
+
<br>
|
26 |
+
<form method="post" action="options.php">
|
27 |
+
<?php settings_fields(AALB_CRED_CONFIG_GROUP);do_settings_sections(AALB_CRED_CONFIG_GROUP);?>
|
28 |
+
<table class="widefat fixed">
|
29 |
+
<tr>
|
30 |
+
<th scope="row" style="width:15%;">Access Key ID</th>
|
31 |
+
<td style="vertical-align:middle;"><input type="text" name="aalb_aws_access_key" style="width:90%" value="<?php echo esc_attr(openssl_decrypt(base64_decode(get_option(AALB_AWS_ACCESS_KEY)), AALB_ENCRYPTION_ALGORITHM, AALB_ENCRYPTION_KEY, 0, AALB_ENCRYPTION_IV)); ?>" /></td>
|
32 |
+
<td>Your Access Key ID that you generated after signing up for the Amazon Product Advertising API. If you have not already signed up for the Amazon Product Advertising API, you can do so by following instructions listed <a href="http://docs.aws.amazon.com/AWSECommerceService/latest/DG/CHAP_GettingStarted.html" target="_blank">here</a>.</td>
|
33 |
+
</tr>
|
34 |
+
<tr>
|
35 |
+
<th scope="row" style="width:15%;">Secret Access Key</th>
|
36 |
+
<?php $secret_key = get_option(AALB_AWS_SECRET_KEY);
|
37 |
+
if($secret_key)
|
38 |
+
$secret_key = AALB_AWS_SECRET_KEY_MASK;
|
39 |
+
?>
|
40 |
+
<td style="vertical-align:middle;"><input type="password" name="aalb_aws_secret_key" style="width:90%" value="<?php echo esc_attr($secret_key); ?>" autocomplete="off"/></td>
|
41 |
+
<td>A key that is used in conjunction with the Access Key ID to cryptographically sign an API request. To retrieve your Access Key ID or Secret Access Key, go to <a href="https://affiliate-program.amazon.com/gp/advertising/api/detail/your-account.html" target="_blank">Manage Your Account</a>. The plugin uses a default encryption key for encrypting the Secret Key. You can change the key using AALB_ENCRYPTION_KEY parameter defined in /aalb_config.php.</td>
|
42 |
+
</tr>
|
43 |
+
<tr>
|
44 |
+
<th scope="row" style="width:15%;">Associate ID</th>
|
45 |
+
<td style="width:90%;vertical-align:middle;">
|
46 |
+
<textarea type="text" id="aalb_store_id_names" name="aalb_store_id_names" style="width:90%" value="<?php echo esc_attr(get_option(AALB_STORE_ID_NAMES)); ?>" onchange="aalb_credentials_store_ids_onchange(this)"><?php echo esc_attr(get_option(AALB_STORE_ID_NAMES)); ?></textarea>
|
47 |
+
</td>
|
48 |
+
<td>Associate ID is used to monitor traffic and sales from your links to Amazon. You can add one store id or tracking id per row. You are recommended to create a new tracking ID in your Amazon Associates account for using it as Associate ID in the plugin.</td>
|
49 |
+
</tr>
|
50 |
+
<tr>
|
51 |
+
<th scope="row" style="width:15%;">Default Associate ID</th>
|
52 |
+
<td style="vertical-align:middle;">
|
53 |
+
<?php $default_store_id=get_option(AALB_DEFAULT_STORE_ID,AALB_DEFAULT_STORE_ID_NAME);?>
|
54 |
+
<select id="aalb_default_store_id" name="aalb_default_store_id" style="width:90%">
|
55 |
+
<?php
|
56 |
+
foreach ($aalb_store_id_names as $store_id) {
|
57 |
+
echo '<option value="' . $store_id . '"';
|
58 |
+
selected($default_store_id,$store_id);
|
59 |
+
echo '>'. $store_id . '</option>\n';
|
60 |
+
}
|
61 |
+
?>
|
62 |
+
</select>
|
63 |
+
</td>
|
64 |
+
<td>The Associate ID that will be used for tagging the affiliate links generated by the plugin if no tag is specified in the short code.</td>
|
65 |
+
</tr>
|
66 |
+
<tr>
|
67 |
+
<th scope="row" style="width:15%;">Default Marketplace</th>
|
68 |
+
<td style="vertical-align:middle;">
|
69 |
+
<?php $default_marketplace=get_option(AALB_DEFAULT_MARKETPLACE,AALB_DEFAULT_MARKETPLACE_NAME);?>
|
70 |
+
<select name="aalb_default_marketplace" style="width:90%">
|
71 |
+
<?php
|
72 |
+
$config_loader = new Aalb_Config_Loader();
|
73 |
+
$aalb_marketplace_names = $config_loader->fetch_marketplaces();
|
74 |
+
foreach ($aalb_marketplace_names as $marketplace) {
|
75 |
+
echo '<option value="' . $marketplace . '"';
|
76 |
+
selected($default_marketplace,$marketplace);
|
77 |
+
echo '>'. $marketplace . '</option>\n';
|
78 |
+
}
|
79 |
+
?>
|
80 |
+
</select>
|
81 |
+
</td>
|
82 |
+
<td>Set the default Amazon marketplace based on the Amazon website that is identified in your Associates Account (for instance, if you have signed up for Amazon.co.uk site, then your default marketplace selection should be UK).</td>
|
83 |
+
</tr>
|
84 |
+
<tr>
|
85 |
+
<th scope="row" style="width:15%;">Default Template</th>
|
86 |
+
<td style="vertical-align:middle;">
|
87 |
+
<?php $default_template=get_option(AALB_DEFAULT_TEMPLATE,AALB_DEFAULT_TEMPLATE_NAME);?>
|
88 |
+
<select name="aalb_default_template" style="width:90%">
|
89 |
+
<?php
|
90 |
+
$templates=get_option(AALB_TEMPLATE_NAMES,$default_template);
|
91 |
+
foreach ($templates as $template) {
|
92 |
+
echo '<option value="' . $template . '"';
|
93 |
+
selected($default_template,$template);
|
94 |
+
echo '>'. $template . '</option>\n';
|
95 |
+
}
|
96 |
+
?>
|
97 |
+
</select>
|
98 |
+
</td>
|
99 |
+
<td>The ad template that will be used for rendering the ad if no template is specified in the short code.</td>
|
100 |
+
</tr>
|
101 |
+
</table>
|
102 |
+
<br>
|
103 |
+
<table>
|
104 |
+
<tr>
|
105 |
+
<th scope="row" style="width:1%;">
|
106 |
+
<input id="aalb-terms-checkbox" type="checkbox" name="demo-checkbox" value="1" <?php checked( '1', get_option(AALB_CHECKBOX_DEFAULT1) ); ?>/>
|
107 |
+
</th>
|
108 |
+
<td style="vertical-align:middle;">
|
109 |
+
Check here to indicate that you have read and agree to the Amazon Associates Link Builder Conditions of Use as applicable for your region - <a target="_blank" href="https://s3.amazonaws.com/aalb-public-resources/documents/AssociatesLinkBuilder-ConditionsOfUse-US.pdf">US</a>, <a target="_blank" href="https://s3.amazonaws.com/aalb-public-resources/documents/AssociatesLinkBuilder-ConditionsOfUse-CA.pdf">CA</a>, <a target="_blank" href="https://s3.amazonaws.com/aalb-public-resources/documents/AssociatesLinkBuilder-ConditionsOfUse-EU.pdf">EU</a>.
|
110 |
+
</td>
|
111 |
+
</tr>
|
112 |
+
</table>
|
113 |
+
<?php submit_button('Save Changes', 'primary', 'submit', true, array( 'disabled' => 'disabled' )); ?>
|
114 |
+
</form>
|
115 |
+
</div>
|
admin/sidebar/partials/aalb_templates.php
ADDED
@@ -0,0 +1,191 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
Copyright 2016-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
5 |
+
|
6 |
+
Licensed under the GNU General Public License as published by the Free Software Foundation,
|
7 |
+
Version 2.0 (the "License"). You may not use this file except in compliance with the License.
|
8 |
+
A copy of the License is located in the "license" file accompanying this file.
|
9 |
+
|
10 |
+
This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
11 |
+
either express or implied. See the License for the specific language governing permissions
|
12 |
+
and limitations under the License.
|
13 |
+
*/
|
14 |
+
|
15 |
+
include 'aalb_admin_ui_common.php';
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Verifies whether file exists and is writable
|
19 |
+
*
|
20 |
+
* @since 1.0.0
|
21 |
+
* @param string $file Name of the file
|
22 |
+
* @return bool TRUE if file exists and is writable or if it's a new file which, throws exception otherwise
|
23 |
+
*/
|
24 |
+
function aalb_verify_file_is_writable($file) {
|
25 |
+
if(is_file($file) and !is_writable($file))
|
26 |
+
throw new Exception("Save Failed. The existing file " . $file . " is not writable.");
|
27 |
+
|
28 |
+
return true;
|
29 |
+
}
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Writes content to a file
|
33 |
+
*
|
34 |
+
* @since 1.0.0
|
35 |
+
* @param string $file Name of the file
|
36 |
+
* @param string $content Content to be written
|
37 |
+
* @return bool TRUE if write was successful, throws exception otherwise
|
38 |
+
*/
|
39 |
+
function aalb_write_to_file($file,$content) {
|
40 |
+
if(file_put_contents($file, $content)===FALSE)
|
41 |
+
throw new Exception("Save Failed. Error writing contents to file: " . $file);
|
42 |
+
|
43 |
+
return true;
|
44 |
+
}
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Saves new or updates existing template.
|
48 |
+
* Writes template CSS and HTML into files.
|
49 |
+
*
|
50 |
+
* @since 1.0.0
|
51 |
+
* @param string $file Name of the file without .extension
|
52 |
+
* @param string $conntent_html HTML content to be saved
|
53 |
+
* @param string $content_css CSS content to be saved
|
54 |
+
*/
|
55 |
+
function aalb_save_template($file, $content_html, $content_css) {
|
56 |
+
$file_mustache = $file . ".mustache";
|
57 |
+
$file_css = $file. ".css";
|
58 |
+
try{
|
59 |
+
if((aalb_verify_file_is_writable($file_css) and aalb_verify_file_is_writable($file_mustache))) {
|
60 |
+
//Both files are (existing and writable) or (a new file is specified)
|
61 |
+
if(aalb_write_to_file($file_mustache, $content_html) and aalb_write_to_file($file_css, $content_css)) {
|
62 |
+
//Both files were saved successfully
|
63 |
+
//Else case never occurs as an exception is thrown in false case
|
64 |
+
$saveFailed = false;
|
65 |
+
aalb_success_notice("Template Saved Successfully");
|
66 |
+
}
|
67 |
+
}
|
68 |
+
} catch(Exception $e) {
|
69 |
+
throw new Exception($e->getMessage());
|
70 |
+
}
|
71 |
+
}
|
72 |
+
|
73 |
+
//Flag to check if the save is failed.
|
74 |
+
$saveFailed = false;
|
75 |
+
$aalb_template_names = get_option(AALB_TEMPLATE_NAMES);
|
76 |
+
|
77 |
+
if (!empty($_POST["submit"])) {
|
78 |
+
$aalb_template_name = stripslashes($_POST["aalb_template_name"]);
|
79 |
+
$aalb_template_template_html_box = stripslashes($_POST["aalb_template_template_html_box"]);
|
80 |
+
$aalb_template_template_css_box = stripslashes($_POST["aalb_template_template_css_box"]);
|
81 |
+
$dir = AALB_TEMPLATE_DIR;
|
82 |
+
if ($_POST["submit"] == "Save") {
|
83 |
+
if ($_POST["aalb_template_list"] == "new") {
|
84 |
+
if (empty($aalb_template_name)) {
|
85 |
+
aalb_error_notice("Please define the template name for the new template");
|
86 |
+
} elseif (!ctype_alnum(str_replace(array('-', '_'), '', $aalb_template_name))) {
|
87 |
+
//The template name can only be alphanumeric characters plus hyphens (-) and underscores (_)
|
88 |
+
aalb_error_notice("Save Failed. Only alphanumeric characters allowed for template name.");
|
89 |
+
} else {
|
90 |
+
if (!is_dir($dir) or !is_writable($dir)) {
|
91 |
+
aalb_error_notice($dir . " doesn't exist or is not writable. Please set up the directory permissions correctly.");
|
92 |
+
} else {
|
93 |
+
//Check if template of that name already exists
|
94 |
+
if (in_array($aalb_template_name, $aalb_template_names)) {
|
95 |
+
aalb_error_notice("Save Failed. A template with the name \"". $aalb_template_name . "\" already exists. Please specify some other name for the template");
|
96 |
+
//Ensures state is saved even on save failures
|
97 |
+
$saveFailed = true;
|
98 |
+
} else {
|
99 |
+
try {
|
100 |
+
aalb_save_template($dir . $aalb_template_name, $aalb_template_template_html_box, $aalb_template_template_css_box);
|
101 |
+
array_push($aalb_template_names, $aalb_template_name);
|
102 |
+
update_option('aalb_template_names', $aalb_template_names);
|
103 |
+
} catch (Exception $e) {
|
104 |
+
aalb_error_notice($e->getMessage());
|
105 |
+
}
|
106 |
+
}
|
107 |
+
}
|
108 |
+
}
|
109 |
+
} else {
|
110 |
+
try {
|
111 |
+
aalb_save_template($dir . $aalb_template_name, $aalb_template_template_html_box, $aalb_template_template_css_box);
|
112 |
+
//clears the cached rendered templates whenever the template is modified
|
113 |
+
$helper = new Aalb_Helper();
|
114 |
+
$helper->clear_cache_for_template($aalb_template_name);
|
115 |
+
} catch (Exception $e) {
|
116 |
+
aalb_error_notice($e->getMessage());
|
117 |
+
}
|
118 |
+
}
|
119 |
+
} elseif ($_POST["submit"] == "Remove") {
|
120 |
+
if ($_POST["aalb_template_list"] == "new") {
|
121 |
+
aalb_error_notice("Cannot remove new template. Please select a valid template to remove.");
|
122 |
+
} else {
|
123 |
+
$aalb_template_names = array_diff($aalb_template_names, array($aalb_template_name));
|
124 |
+
update_option('aalb_template_names', $aalb_template_names);
|
125 |
+
if (unlink($dir . $aalb_template_name . ".mustache")) {
|
126 |
+
aalb_success_notice("Successfully removed Template HTML");
|
127 |
+
} else {
|
128 |
+
aalb_error_notice("Couldn't remove Template HTML. Please manually remove " . $dir . $aalb_template_name . ".mustache");
|
129 |
+
}
|
130 |
+
if (unlink($dir . $aalb_template_name . ".css")) {
|
131 |
+
aalb_success_notice("Successfully removed Template CSS");
|
132 |
+
} else {
|
133 |
+
aalb_error_notice("Couldn't remove Template CSS. Please manually remove " . $dir . $aalb_template_name . ".css");
|
134 |
+
}
|
135 |
+
$aalb_template_name = "";
|
136 |
+
$aalb_template_template_html_box = "";
|
137 |
+
$aalb_template_template_css_box = "";
|
138 |
+
}
|
139 |
+
}
|
140 |
+
}
|
141 |
+
|
142 |
+
wp_enqueue_script('jquery');
|
143 |
+
wp_enqueue_script('codemirror_js', CODEMIRROR_JS);
|
144 |
+
wp_enqueue_script('codemirror_mode_xml_js', CODEMIRROR_MODE_XML_JS);
|
145 |
+
wp_enqueue_script('codemirror_mode_css_js', CODEMIRROR_MODE_CSS_JS);
|
146 |
+
wp_enqueue_style('codemirror_css', CODEMIRROR_CSS);
|
147 |
+
|
148 |
+
wp_enqueue_script('aalb_template_js', AALB_TEMPLATE_JS, array('jquery', 'codemirror_js', 'codemirror_mode_xml_js', 'codemirror_mode_css_js'));
|
149 |
+
wp_localize_script('aalb_template_js', 'wp_opt', array('plugin_url' => AALB_PLUGIN_URL, 'aalb_default_templates' => AALB_AMAZON_TEMPLATE_NAMES));
|
150 |
+
|
151 |
+
?>
|
152 |
+
<div class="wrap">
|
153 |
+
<h2>Templates for <?=AALB_PROJECT_TITLE?></h2>
|
154 |
+
<br>
|
155 |
+
<form method="post">
|
156 |
+
<table class="widefat fixed">
|
157 |
+
<tr>
|
158 |
+
<th scope="row" style="width:15%;">Select Template</th>
|
159 |
+
<td>
|
160 |
+
<select id="aalb_template_list_select" name="aalb_template_list" style="width:50%" onchange="aalb_template_select_template_onchange(this)">
|
161 |
+
<option value="new">Create new template</option>
|
162 |
+
<?php
|
163 |
+
foreach ($aalb_template_names as $aalb_template) {
|
164 |
+
?>
|
165 |
+
<option value="<?=$aalb_template?>" <?php $saveFailed===false ? selected($aalb_template, $aalb_template_name) : selected($aalb_template, "") ?>><?=$aalb_template?></option>
|
166 |
+
<?php
|
167 |
+
}
|
168 |
+
?>
|
169 |
+
</select>
|
170 |
+
<input type="button" name="clone" id="clone_template" class="button button-secondary" value="Clone" onclick="clone_existing_template()" disabled>
|
171 |
+
</td>
|
172 |
+
</tr>
|
173 |
+
<tr>
|
174 |
+
<th scope="row" style="width:15%;">Set a name for your template</th>
|
175 |
+
<td><input type="text" id="aalb_template_name" name="aalb_template_name" style="width:50%" value="<?=$aalb_template_name?>" /></td>
|
176 |
+
</tr>
|
177 |
+
<tr>
|
178 |
+
<th scope="row" style="width:15%;">Add HTML for your template</th>
|
179 |
+
<td><textarea id="aalb_template_template_html_box" name="aalb_template_template_html_box"><?=$aalb_template_template_html_box?></textarea></td>
|
180 |
+
</tr>
|
181 |
+
<tr>
|
182 |
+
<th scope="row" style="width:15%;">Add CSS for your template</th>
|
183 |
+
<td><textarea id="aalb_template_template_css_box" name="aalb_template_template_css_box"><?=$aalb_template_template_css_box?></textarea></td>
|
184 |
+
</tr>
|
185 |
+
</table>
|
186 |
+
<p class="submit">
|
187 |
+
<input name="submit" id="submit_save" class="button button-primary" value="Save" type="submit">
|
188 |
+
<input name="submit" id="submit_remove" class="button button-secondary" value="Remove" type="submit">
|
189 |
+
</p>
|
190 |
+
</form>
|
191 |
+
</div>
|
admin/sidebar/partials/aalb_ui_common.php
ADDED
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
Copyright 2016-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
5 |
+
|
6 |
+
Licensed under the GNU General Public License as published by the Free Software Foundation,
|
7 |
+
Version 2.0 (the "License"). You may not use this file except in compliance with the License.
|
8 |
+
A copy of the License is located in the "license" file accompanying this file.
|
9 |
+
|
10 |
+
This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
11 |
+
either express or implied. See the License for the specific language governing permissions
|
12 |
+
and limitations under the License.
|
13 |
+
*/
|
14 |
+
|
15 |
+
//some commonly used UI functionality
|
16 |
+
|
17 |
+
function aalb_info_notice($message) {
|
18 |
+
echo "<div class=\"notice notice-info is-dismissible\"><p>INFO - " . $message . "</p></div>";
|
19 |
+
}
|
20 |
+
|
21 |
+
function aalb_warning_notice($message) {
|
22 |
+
echo "<div class=\"notice notice-warning\"><p>WARNING - " . $message . "</p></div>";
|
23 |
+
}
|
24 |
+
|
25 |
+
function aalb_error_notice($message) {
|
26 |
+
echo "<div class=\"notice notice-error\"><p>ERROR - " . $message . "</p></div>";
|
27 |
+
}
|
28 |
+
|
29 |
+
function aalb_success_notice($message) {
|
30 |
+
echo "<div class=\"notice notice-success is-dismissible\"><p>SUCCESS - " . $message . "</p></div>";
|
31 |
+
}
|
32 |
+
|
33 |
+
?>
|
amazon-associates-link-builder.php
ADDED
@@ -0,0 +1,112 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* @package AmazonAssociatesLinkBuilder
|
4 |
+
*
|
5 |
+
*/
|
6 |
+
|
7 |
+
/*
|
8 |
+
Plugin Name: Amazon Associates Link Builder
|
9 |
+
Description: Amazon Associates Link Builder is the official free Amazon Associates Program plugin for WordPress. The plugin enables you to search for products in the Amazon catalog, access real-time price and availability information, and easily create links in your posts to products on Amazon.com. You will be able to generate text links, create custom ad units, or take advantage of out-of-the-box widgets that we’ve designed and included with the plugin.
|
10 |
+
Version: 1.0
|
11 |
+
Author: Amazon Associates Program
|
12 |
+
Author URI: https://affiliate-program.amazon.com/
|
13 |
+
License: GPLv2
|
14 |
+
*/
|
15 |
+
|
16 |
+
/*
|
17 |
+
Copyright 2016-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
18 |
+
|
19 |
+
Licensed under the GNU General Public License as published by the Free Software Foundation,
|
20 |
+
Version 2.0 (the "License"). You may not use this file except in compliance with the License.
|
21 |
+
A copy of the License is located in the "license" file accompanying this file.
|
22 |
+
|
23 |
+
This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
24 |
+
either express or implied. See the License for the specific language governing permissions
|
25 |
+
and limitations under the License.
|
26 |
+
*/
|
27 |
+
|
28 |
+
if ( ! defined( 'WPINC' ) ) {
|
29 |
+
die;
|
30 |
+
}
|
31 |
+
|
32 |
+
require_once( plugin_dir_path( __FILE__ ) . 'aalb_config.php');
|
33 |
+
|
34 |
+
add_filter( 'plugin_action_links_' . plugin_basename(__FILE__), 'add_action_links' );
|
35 |
+
function add_action_links ( $links ) {
|
36 |
+
$mylinks = array(
|
37 |
+
'<a href="' . admin_url( 'admin.php?page=associates-link-builder-about' ) . '">About</a>',
|
38 |
+
'<a href="' . admin_url( 'admin.php?page=associates-link-builder-settings' ) . '">Settings</a>',
|
39 |
+
'<a href="' . admin_url( 'admin.php?page=associates-link-builder-templates' ) . '">Templates</a>',
|
40 |
+
|
41 |
+
);
|
42 |
+
return array_merge( $links, $mylinks );
|
43 |
+
}
|
44 |
+
|
45 |
+
/**
|
46 |
+
* Autoload the files required for the plugin.
|
47 |
+
*
|
48 |
+
* @since 1.0.0
|
49 |
+
*/
|
50 |
+
function aalb_autoload() {
|
51 |
+
//Load the autoloader for mustache.
|
52 |
+
require_once(MUSTACHE_AUTOLOADER_PHP);
|
53 |
+
Mustache_Autoloader::register();
|
54 |
+
|
55 |
+
//Load the autoloader for plugin files.
|
56 |
+
require_once(AALB_AUTOLOADER);
|
57 |
+
Aalb_Autoloader::register();
|
58 |
+
}
|
59 |
+
|
60 |
+
aalb_autoload();
|
61 |
+
|
62 |
+
/**
|
63 |
+
* The code to run on activation
|
64 |
+
*
|
65 |
+
* @since 1.0.0
|
66 |
+
*/
|
67 |
+
function aalb_activate() {
|
68 |
+
$aalb_activator = new Aalb_Activator();
|
69 |
+
$aalb_activator->load_templates();
|
70 |
+
$aalb_activator->load_db_keys();
|
71 |
+
$aalb_activator->load_store_ids();
|
72 |
+
}
|
73 |
+
|
74 |
+
register_activation_hook( __FILE__, 'aalb_activate' );
|
75 |
+
|
76 |
+
/**
|
77 |
+
* The code to run on deactivation
|
78 |
+
*
|
79 |
+
* @since 1.0.0
|
80 |
+
*/
|
81 |
+
function aalb_deactivate() {
|
82 |
+
$aalb_deactivator = new Aalb_Deactivator();
|
83 |
+
$aalb_deactivator->remove_cache();
|
84 |
+
}
|
85 |
+
|
86 |
+
register_deactivation_hook( __FILE__, 'aalb_deactivate' );
|
87 |
+
|
88 |
+
/**
|
89 |
+
* The code to run on uninstalltion
|
90 |
+
*
|
91 |
+
* @since 1.0.0
|
92 |
+
*/
|
93 |
+
function aalb_uninstall() {
|
94 |
+
$aalb_deactivator = new Aalb_Deactivator();
|
95 |
+
$aalb_deactivator->remove_settings();
|
96 |
+
}
|
97 |
+
|
98 |
+
register_uninstall_hook( __FILE__, 'aalb_uninstall' );
|
99 |
+
|
100 |
+
/**
|
101 |
+
* Execute the plugin
|
102 |
+
*
|
103 |
+
* @since 1.0.0
|
104 |
+
*/
|
105 |
+
function aalb_execute() {
|
106 |
+
$aalb_manager = new Aalb_Manager();
|
107 |
+
$aalb_manager->execute();
|
108 |
+
}
|
109 |
+
|
110 |
+
aalb_execute();
|
111 |
+
|
112 |
+
?>
|
bin/install-wp-tests.sh
ADDED
@@ -0,0 +1,118 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/env bash
|
2 |
+
|
3 |
+
if [ $# -lt 3 ]; then
|
4 |
+
echo "usage: $0 <db-name> <db-user> <db-pass> [db-host] [wp-version]"
|
5 |
+
exit 1
|
6 |
+
fi
|
7 |
+
|
8 |
+
DB_NAME=$1
|
9 |
+
DB_USER=$2
|
10 |
+
DB_PASS=$3
|
11 |
+
DB_HOST=${4-localhost}
|
12 |
+
WP_VERSION=${5-latest}
|
13 |
+
|
14 |
+
WP_TESTS_DIR=${WP_TESTS_DIR-/tmp/wordpress-tests-lib}
|
15 |
+
WP_CORE_DIR=${WP_CORE_DIR-/tmp/wordpress/}
|
16 |
+
|
17 |
+
download() {
|
18 |
+
if [ `which curl` ]; then
|
19 |
+
curl -s "$1" > "$2";
|
20 |
+
elif [ `which wget` ]; then
|
21 |
+
wget -nv -O "$2" "$1"
|
22 |
+
fi
|
23 |
+
}
|
24 |
+
|
25 |
+
if [[ $WP_VERSION =~ [0-9]+\.[0-9]+(\.[0-9]+)? ]]; then
|
26 |
+
WP_TESTS_TAG="tags/$WP_VERSION"
|
27 |
+
elif [[ $WP_VERSION == 'nightly' || $WP_VERSION == 'trunk' ]]; then
|
28 |
+
WP_TESTS_TAG="trunk"
|
29 |
+
else
|
30 |
+
# http serves a single offer, whereas https serves multiple. we only want one
|
31 |
+
download http://api.wordpress.org/core/version-check/1.7/ /tmp/wp-latest.json
|
32 |
+
grep '[0-9]+\.[0-9]+(\.[0-9]+)?' /tmp/wp-latest.json
|
33 |
+
LATEST_VERSION=$(grep -o '"version":"[^"]*' /tmp/wp-latest.json | sed 's/"version":"//')
|
34 |
+
if [[ -z "$LATEST_VERSION" ]]; then
|
35 |
+
echo "Latest WordPress version could not be found"
|
36 |
+
exit 1
|
37 |
+
fi
|
38 |
+
WP_TESTS_TAG="tags/$LATEST_VERSION"
|
39 |
+
fi
|
40 |
+
|
41 |
+
set -ex
|
42 |
+
|
43 |
+
install_wp() {
|
44 |
+
|
45 |
+
if [ -d $WP_CORE_DIR ]; then
|
46 |
+
return;
|
47 |
+
fi
|
48 |
+
|
49 |
+
mkdir -p $WP_CORE_DIR
|
50 |
+
|
51 |
+
if [[ $WP_VERSION == 'nightly' || $WP_VERSION == 'trunk' ]]; then
|
52 |
+
mkdir -p /tmp/wordpress-nightly
|
53 |
+
download https://wordpress.org/nightly-builds/wordpress-latest.zip /tmp/wordpress-nightly/wordpress-nightly.zip
|
54 |
+
unzip -q /tmp/wordpress-nightly/wordpress-nightly.zip -d /tmp/wordpress-nightly/
|
55 |
+
mv /tmp/wordpress-nightly/wordpress/* $WP_CORE_DIR
|
56 |
+
else
|
57 |
+
if [ $WP_VERSION == 'latest' ]; then
|
58 |
+
local ARCHIVE_NAME='latest'
|
59 |
+
else
|
60 |
+
local ARCHIVE_NAME="wordpress-$WP_VERSION"
|
61 |
+
fi
|
62 |
+
download https://wordpress.org/${ARCHIVE_NAME}.tar.gz /tmp/wordpress.tar.gz
|
63 |
+
tar --strip-components=1 -zxmf /tmp/wordpress.tar.gz -C $WP_CORE_DIR
|
64 |
+
fi
|
65 |
+
|
66 |
+
download https://raw.github.com/markoheijnen/wp-mysqli/master/db.php $WP_CORE_DIR/wp-content/db.php
|
67 |
+
}
|
68 |
+
|
69 |
+
install_test_suite() {
|
70 |
+
# portable in-place argument for both GNU sed and Mac OSX sed
|
71 |
+
if [[ $(uname -s) == 'Darwin' ]]; then
|
72 |
+
local ioption='-i .bak'
|
73 |
+
else
|
74 |
+
local ioption='-i'
|
75 |
+
fi
|
76 |
+
|
77 |
+
# set up testing suite if it doesn't yet exist
|
78 |
+
if [ ! -d $WP_TESTS_DIR ]; then
|
79 |
+
# set up testing suite
|
80 |
+
mkdir -p $WP_TESTS_DIR
|
81 |
+
svn co --quiet https://develop.svn.wordpress.org/${WP_TESTS_TAG}/tests/phpunit/includes/ $WP_TESTS_DIR/includes
|
82 |
+
fi
|
83 |
+
|
84 |
+
if [ ! -f wp-tests-config.php ]; then
|
85 |
+
download https://develop.svn.wordpress.org/${WP_TESTS_TAG}/wp-tests-config-sample.php "$WP_TESTS_DIR"/wp-tests-config.php
|
86 |
+
sed $ioption "s:dirname( __FILE__ ) . '/src/':'$WP_CORE_DIR':" "$WP_TESTS_DIR"/wp-tests-config.php
|
87 |
+
sed $ioption "s/youremptytestdbnamehere/$DB_NAME/" "$WP_TESTS_DIR"/wp-tests-config.php
|
88 |
+
sed $ioption "s/yourusernamehere/$DB_USER/" "$WP_TESTS_DIR"/wp-tests-config.php
|
89 |
+
sed $ioption "s/yourpasswordhere/$DB_PASS/" "$WP_TESTS_DIR"/wp-tests-config.php
|
90 |
+
sed $ioption "s|localhost|${DB_HOST}|" "$WP_TESTS_DIR"/wp-tests-config.php
|
91 |
+
fi
|
92 |
+
|
93 |
+
}
|
94 |
+
|
95 |
+
install_db() {
|
96 |
+
# parse DB_HOST for port or socket references
|
97 |
+
local PARTS=(${DB_HOST//\:/ })
|
98 |
+
local DB_HOSTNAME=${PARTS[0]};
|
99 |
+
local DB_SOCK_OR_PORT=${PARTS[1]};
|
100 |
+
local EXTRA=""
|
101 |
+
|
102 |
+
if ! [ -z $DB_HOSTNAME ] ; then
|
103 |
+
if [ $(echo $DB_SOCK_OR_PORT | grep -e '^[0-9]\{1,\}$') ]; then
|
104 |
+
EXTRA=" --host=$DB_HOSTNAME --port=$DB_SOCK_OR_PORT --protocol=tcp"
|
105 |
+
elif ! [ -z $DB_SOCK_OR_PORT ] ; then
|
106 |
+
EXTRA=" --socket=$DB_SOCK_OR_PORT"
|
107 |
+
elif ! [ -z $DB_HOSTNAME ] ; then
|
108 |
+
EXTRA=" --host=$DB_HOSTNAME --protocol=tcp"
|
109 |
+
fi
|
110 |
+
fi
|
111 |
+
|
112 |
+
# create database
|
113 |
+
mysqladmin create $DB_NAME --user="$DB_USER" --password="$DB_PASS"$EXTRA
|
114 |
+
}
|
115 |
+
|
116 |
+
install_wp
|
117 |
+
install_test_suite
|
118 |
+
install_db
|
css/aalb_basics.css
ADDED
@@ -0,0 +1,83 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*
|
2 |
+
Copyright 2016-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
3 |
+
|
4 |
+
Licensed under the GNU General Public License as published by the Free Software Foundation,
|
5 |
+
Version 2.0 (the "License"). You may not use this file except in compliance with the License.
|
6 |
+
A copy of the License is located in the "license" file accompanying this file.
|
7 |
+
|
8 |
+
This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
9 |
+
either express or implied. See the License for the specific language governing permissions
|
10 |
+
and limitations under the License.
|
11 |
+
*/
|
12 |
+
|
13 |
+
.aalb-btn {
|
14 |
+
padding: 6px 12px;
|
15 |
+
padding-top: 6px;
|
16 |
+
padding-right: 12px;
|
17 |
+
padding-bottom: 6px;
|
18 |
+
padding-left: 12px;
|
19 |
+
margin-bottom: 0px;
|
20 |
+
font-size: 14px;
|
21 |
+
font-weight: normal;
|
22 |
+
line-height: 1.42857;
|
23 |
+
text-align: center;
|
24 |
+
white-space: nowrap;
|
25 |
+
vertical-align: middle;
|
26 |
+
cursor: pointer;
|
27 |
+
-moz-user-select: none;
|
28 |
+
background-image: none;
|
29 |
+
border: 1px solid transparent;
|
30 |
+
border-top-width: 1px;
|
31 |
+
border-right-width: 1px;
|
32 |
+
border-bottom-width: 1px;
|
33 |
+
border-left-width: 1px;
|
34 |
+
border-top-style: solid;
|
35 |
+
border-right-style: solid;
|
36 |
+
border-bottom-style: solid;
|
37 |
+
border-left-style: solid;
|
38 |
+
border-top-color: transparent;
|
39 |
+
border-right-color: transparent;
|
40 |
+
border-bottom-color: transparent;
|
41 |
+
border-left-color: transparent;
|
42 |
+
-moz-border-top-color: none;
|
43 |
+
-moz-border-right-color: none;
|
44 |
+
-moz-border-bottom-color: none;
|
45 |
+
-moz-border-left-color: none;
|
46 |
+
border-image-source: none;
|
47 |
+
border-image-slice: 100% 100% 100% 100%;
|
48 |
+
border-image-width: 1 1 1 1;
|
49 |
+
border-image-outset: 0 0 0 0;
|
50 |
+
border-image-repeat: stretch stretch;
|
51 |
+
border-radius: 4px;
|
52 |
+
border-top-left-radius: 4px;
|
53 |
+
border-top-right-radius: 4px;
|
54 |
+
border-bottom-right-radius: 4px;
|
55 |
+
border-bottom-left-radius: 4px;
|
56 |
+
}
|
57 |
+
|
58 |
+
.aalb-btn-primary {
|
59 |
+
box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.4) inset;
|
60 |
+
background: transparent linear-gradient(to bottom, #F7DFA5, #F0C14B) repeat scroll 0% 0%;
|
61 |
+
background-color: transparent;
|
62 |
+
background-image: linear-gradient(to bottom, #F7DFA5, #F0C14B);
|
63 |
+
background-repeat: repeat;
|
64 |
+
background-attachment: scroll;
|
65 |
+
background-position: 0% 0%;
|
66 |
+
background-clip: border-box;
|
67 |
+
background-origin: padding-box;
|
68 |
+
background-size: auto auto;
|
69 |
+
border-color: #A88734 #9C7E31 #846A29;
|
70 |
+
border-top-color: #A88734;
|
71 |
+
border-right-color: #9C7E31;
|
72 |
+
border-bottom-color: #846A29;
|
73 |
+
border-left-color: #9C7E31;
|
74 |
+
color: #111;
|
75 |
+
}
|
76 |
+
|
77 |
+
.pull-right {
|
78 |
+
float:right;
|
79 |
+
}
|
80 |
+
|
81 |
+
.pull-left {
|
82 |
+
float:left;
|
83 |
+
}
|
includes/aalb_activator.php
ADDED
@@ -0,0 +1,93 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
Copyright 2016-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
5 |
+
|
6 |
+
Licensed under the GNU General Public License as published by the Free Software Foundation,
|
7 |
+
Version 2.0 (the "License"). You may not use this file except in compliance with the License.
|
8 |
+
A copy of the License is located in the "license" file accompanying this file.
|
9 |
+
|
10 |
+
This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
11 |
+
either express or implied. See the License for the specific language governing permissions
|
12 |
+
and limitations under the License.
|
13 |
+
*/
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Fired during the plugin activation
|
17 |
+
*
|
18 |
+
* Gets the template names from the template directory and loads it into the database.
|
19 |
+
*
|
20 |
+
* @since 1.0.0
|
21 |
+
* @package AmazonAssociatesLinkBuilder
|
22 |
+
* @subpackage AmazonAssociatesLinkBuilder/includes
|
23 |
+
*/
|
24 |
+
class Aalb_Activator {
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Add the template names to the database from the filesystem.
|
28 |
+
*
|
29 |
+
* @since 1.0.0
|
30 |
+
*/
|
31 |
+
public function load_templates() {
|
32 |
+
$aalb_templates = array();
|
33 |
+
if ($handle = opendir(AALB_TEMPLATE_DIR)) {
|
34 |
+
while (false !== ($entry = readdir($handle))) {
|
35 |
+
if ($this->aalb_get_file_extension($entry) == "css") {
|
36 |
+
$aalb_templates[] = $this->aalb_get_file_name($entry);
|
37 |
+
}
|
38 |
+
}
|
39 |
+
closedir($handle);
|
40 |
+
}
|
41 |
+
update_option(AALB_TEMPLATE_NAMES, $aalb_templates);
|
42 |
+
}
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Add the aws key options into the database on activation.
|
46 |
+
* This solves the problem of encryption as wordpress called an update option before calling
|
47 |
+
* add option while sanitizing.
|
48 |
+
* https://codex.wordpress.org/Function_Reference/register_setting
|
49 |
+
*
|
50 |
+
* @since 1.0.0
|
51 |
+
*/
|
52 |
+
public function load_db_keys() {
|
53 |
+
if(!get_option(AALB_AWS_ACCESS_KEY)) {
|
54 |
+
update_option(AALB_AWS_ACCESS_KEY, '');
|
55 |
+
}
|
56 |
+
if(!get_option(AALB_AWS_SECRET_KEY)) {
|
57 |
+
update_option(AALB_AWS_SECRET_KEY, '');
|
58 |
+
}
|
59 |
+
}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Init store ids key and add todatabase.
|
63 |
+
*
|
64 |
+
* @since 1.0.0
|
65 |
+
*/
|
66 |
+
public function load_store_ids() {
|
67 |
+
update_option(AALB_STORE_IDS, '');
|
68 |
+
}
|
69 |
+
|
70 |
+
/**
|
71 |
+
* Gets the extension of the file
|
72 |
+
*
|
73 |
+
* @since 1.0.0
|
74 |
+
* @param string $file_name Name of the file
|
75 |
+
* @return string Extension of the file
|
76 |
+
*/
|
77 |
+
function aalb_get_file_extension($file_name) {
|
78 |
+
return substr(strrchr($file_name,'.'),1);
|
79 |
+
}
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Gets the name of the file without the extension
|
83 |
+
*
|
84 |
+
* @since 1.0.0
|
85 |
+
* @param string $file_name Name of the file
|
86 |
+
* @return string Name of the file without the extension
|
87 |
+
*/
|
88 |
+
function aalb_get_file_name($file_name) {
|
89 |
+
return substr($file_name, 0, strlen($file_name) - strlen(strrchr($file_name,'.')));
|
90 |
+
}
|
91 |
+
}
|
92 |
+
|
93 |
+
?>
|
includes/aalb_autoloader.php
ADDED
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
Copyright 2016-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
5 |
+
|
6 |
+
Licensed under the GNU General Public License as published by the Free Software Foundation,
|
7 |
+
Version 2.0 (the "License"). You may not use this file except in compliance with the License.
|
8 |
+
A copy of the License is located in the "license" file accompanying this file.
|
9 |
+
|
10 |
+
This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
11 |
+
either express or implied. See the License for the specific language governing permissions
|
12 |
+
and limitations under the License.
|
13 |
+
*/
|
14 |
+
|
15 |
+
/**
|
16 |
+
* The class reponsible for auto-loading files.
|
17 |
+
*
|
18 |
+
* Loads the class with respect to their respective directories.
|
19 |
+
*
|
20 |
+
* @since 1.0.0
|
21 |
+
* @package AmazonAssociatesLinkBuilder
|
22 |
+
* @subpackage AmazonAssociatesLinkBuilder/includes
|
23 |
+
*/
|
24 |
+
class Aalb_Autoloader {
|
25 |
+
|
26 |
+
private $dir;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Register the autoloader for a directory in the plugin.
|
30 |
+
*
|
31 |
+
* @since 1.0.0
|
32 |
+
* @param string $dir Path of the directory.
|
33 |
+
*/
|
34 |
+
public function __construct($dir = '') {
|
35 |
+
if(!empty($dir)) {
|
36 |
+
$this->dir = $dir;
|
37 |
+
}
|
38 |
+
|
39 |
+
spl_autoload_register(array($this, 'autoload'));
|
40 |
+
}
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Make instances of the autoloaders for each directory in the plugin.
|
44 |
+
*
|
45 |
+
* @since 1.0.0
|
46 |
+
*/
|
47 |
+
public static function register() {
|
48 |
+
new self(AALB_INCLUDES_DIR);
|
49 |
+
new self(AALB_ADMIN_DIR);
|
50 |
+
new self(AALB_SIDEBAR_DIR);
|
51 |
+
new self(AALB_PAAPI_DIR);
|
52 |
+
new self(AALB_SHORTCODE_DIR);
|
53 |
+
new self(AALB_LIBRARY_DIR);
|
54 |
+
}
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Callback function of spl_autoload_register to autoload the class.
|
58 |
+
*
|
59 |
+
* @since 1.0.0
|
60 |
+
* @param string $class Name of the class to autoload.
|
61 |
+
*/
|
62 |
+
public function autoload($class) {
|
63 |
+
$path = $this->dir . strtolower($class) . '.php';
|
64 |
+
if(file_exists($path)) {
|
65 |
+
require_once($path);
|
66 |
+
}
|
67 |
+
}
|
68 |
+
}
|
69 |
+
?>
|
includes/aalb_cache_loader.php
ADDED
@@ -0,0 +1,85 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
Copyright 2016-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
5 |
+
|
6 |
+
Licensed under the GNU General Public License as published by the Free Software Foundation,
|
7 |
+
Version 2.0 (the "License"). You may not use this file except in compliance with the License.
|
8 |
+
A copy of the License is located in the "license" file accompanying this file.
|
9 |
+
|
10 |
+
This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
11 |
+
either express or implied. See the License for the specific language governing permissions
|
12 |
+
and limitations under the License.
|
13 |
+
*/
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Fired while making a GET request.
|
17 |
+
*
|
18 |
+
* Generic class that can be used by any class to get the data from the cache.
|
19 |
+
* If the data is not available in the cache, a remote GET request is made.
|
20 |
+
*
|
21 |
+
* @since 1.0.0
|
22 |
+
* @package AmazonAssociatesLinkBuilder
|
23 |
+
* @subpackage AmazonAssociatesLinkBuilder/includes
|
24 |
+
*/
|
25 |
+
class Aalb_Cache_Loader {
|
26 |
+
|
27 |
+
public $loader;
|
28 |
+
protected $helper;
|
29 |
+
|
30 |
+
public function __construct($loader) {
|
31 |
+
$this->loader = $loader;
|
32 |
+
$this->helper = new Aalb_Helper();
|
33 |
+
}
|
34 |
+
|
35 |
+
/**
|
36 |
+
* If the information is in the cache, then retrieve the information from the cache.
|
37 |
+
* Else get the information by making a GET request.
|
38 |
+
*
|
39 |
+
* @param string $key Unique identification of the information.
|
40 |
+
* @param string $url URL for making a request.
|
41 |
+
* @return string GET Response.
|
42 |
+
*/
|
43 |
+
public function load($key, $url) {
|
44 |
+
$info = $this->lookup($key);
|
45 |
+
if($info !== false){
|
46 |
+
return $info;
|
47 |
+
} else {
|
48 |
+
return $this->load_and_save($key,$url);
|
49 |
+
}
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Lookup in the cache for a particular key.
|
54 |
+
* If the key exists in the cache, the data is return.
|
55 |
+
* Else false is returned.
|
56 |
+
*
|
57 |
+
* @param string $key Unique identification of the information.
|
58 |
+
* @return string Data in the cache.
|
59 |
+
*/
|
60 |
+
private function lookup($key) {
|
61 |
+
return get_transient($key);
|
62 |
+
}
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Load the information with a GET request and save it in the cache. Return the loaded information.
|
66 |
+
*
|
67 |
+
* @param string $key Unique identification of the information.
|
68 |
+
* @param string $url URL for making a request.
|
69 |
+
* @return string GET Response.
|
70 |
+
*/
|
71 |
+
private function load_and_save($key, $url) {
|
72 |
+
$info = $this->loader->load($url);
|
73 |
+
|
74 |
+
//use wordpress linkcode
|
75 |
+
$info = str_replace('linkCode%3Dxm2', 'linkCode%3Dalb', $info);
|
76 |
+
$info = str_replace('linkCode=xm2', 'linkCode=alb', $info);
|
77 |
+
|
78 |
+
$this->helper->clear_expired_transients_at_intervals();
|
79 |
+
set_transient($key, $info, AALB_CACHE_FOR_ASIN_RAWINFO_TTL);
|
80 |
+
|
81 |
+
return $info;
|
82 |
+
}
|
83 |
+
}
|
84 |
+
|
85 |
+
?>
|
includes/aalb_cache_template_loader.php
ADDED
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
Copyright 2016-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
5 |
+
|
6 |
+
Licensed under the GNU General Public License as published by the Free Software Foundation,
|
7 |
+
Version 2.0 (the "License"). You may not use this file except in compliance with the License.
|
8 |
+
A copy of the License is located in the "license" file accompanying this file.
|
9 |
+
|
10 |
+
This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
11 |
+
either express or implied. See the License for the specific language governing permissions
|
12 |
+
and limitations under the License.
|
13 |
+
*/
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Cache Loader for rendered templates.
|
17 |
+
*
|
18 |
+
* Loads ands saves the display unit in the cache.
|
19 |
+
*
|
20 |
+
* @since 1.0.0
|
21 |
+
* @package AmazonAssociatesLinkBuilder
|
22 |
+
* @subpackage AmazonAssociatesLinkBuilder/includes
|
23 |
+
*/
|
24 |
+
class Aalb_Cache_Template_Loader {
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Get the html of the display unit from the cache
|
28 |
+
*
|
29 |
+
* @since 1.0.0
|
30 |
+
* @param string $key Unique Key for the display unit in cache.
|
31 |
+
* @return string HTML of the display unit.
|
32 |
+
*/
|
33 |
+
public function get_display_unit($key) {
|
34 |
+
return get_transient($key);
|
35 |
+
}
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Get the product information.
|
39 |
+
*
|
40 |
+
* @since 1.0.0
|
41 |
+
* @param string $key Unique identification of the product.
|
42 |
+
* @param string $display_unit HTML of the display unit to save in the cache.
|
43 |
+
*/
|
44 |
+
public function save_display_unit($key, $display_unit) {
|
45 |
+
set_transient($key, $display_unit, AALB_CACHE_FOR_ASIN_ADUNIT_TTL);
|
46 |
+
}
|
47 |
+
|
48 |
+
}
|
49 |
+
|
50 |
+
?>
|
includes/aalb_config_loader.php
ADDED
@@ -0,0 +1,72 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
Copyright 2016-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
5 |
+
|
6 |
+
Licensed under the GNU General Public License as published by the Free Software Foundation,
|
7 |
+
Version 2.0 (the "License"). You may not use this file except in compliance with the License.
|
8 |
+
A copy of the License is located in the "license" file accompanying this file.
|
9 |
+
|
10 |
+
This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
11 |
+
either express or implied. See the License for the specific language governing permissions
|
12 |
+
and limitations under the License.
|
13 |
+
*/
|
14 |
+
|
15 |
+
/**
|
16 |
+
* The class reponsible for getting all the configuration
|
17 |
+
*
|
18 |
+
* Loads the class with respect to their respective directories.
|
19 |
+
*
|
20 |
+
* @since 1.0.0
|
21 |
+
* @package AmazonAssociatesLinkBuilder
|
22 |
+
* @subpackage AmazonAssociatesLinkBuilder/includes
|
23 |
+
*/
|
24 |
+
class Aalb_Config_Loader {
|
25 |
+
|
26 |
+
private $cache_loader;
|
27 |
+
|
28 |
+
public function __construct() {
|
29 |
+
$this->cache_loader = new Aalb_Cache_Loader(new Aalb_Remote_Loader());
|
30 |
+
}
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Updating marketplaces from the external config file and storing it in the database.
|
34 |
+
*
|
35 |
+
* If some error occurs while fetching from external source, the error message
|
36 |
+
* will be logged and marketplace endpoints would be retrieved from database.
|
37 |
+
*
|
38 |
+
* @since 1.0.0
|
39 |
+
*/
|
40 |
+
public function fetch_marketplaces() {
|
41 |
+
try{
|
42 |
+
$body = $this->cache_loader->load(AALB_MARKETPLACE_NAMES, MARKETPLACES_URL);
|
43 |
+
return $this->parse_json($body);
|
44 |
+
} catch(Exception $e) {
|
45 |
+
error_log($e->getMessage());
|
46 |
+
return get_option(AALB_MARKETPLACE_NAMES);
|
47 |
+
}
|
48 |
+
}
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Parse the json file and extract the marketplace endpoints
|
52 |
+
*
|
53 |
+
* @since 1.0.0
|
54 |
+
* @param string $json_body Json retrieved from the server to parse.
|
55 |
+
* @return array Mapping of marketplace endpoint and its abbreviation.
|
56 |
+
*/
|
57 |
+
private function parse_json($json_body) {
|
58 |
+
$body = json_decode($json_body,true);
|
59 |
+
if(json_last_error() !== JSON_ERROR_NONE) {
|
60 |
+
throw new Exception('Invalid Json returned by server' . json_last_error());
|
61 |
+
}
|
62 |
+
$marketplaces_info = $body['Local']['Marketplace'];
|
63 |
+
$updated_marketplace = [];
|
64 |
+
foreach ($marketplaces_info as $key => $value) {
|
65 |
+
$updated_marketplace[substr($value['Endpoint'],0,strpos($value['Endpoint'],'/'))] = $key;
|
66 |
+
}
|
67 |
+
update_option(AALB_MARKETPLACE_NAMES, $updated_marketplace);
|
68 |
+
|
69 |
+
return $updated_marketplace;
|
70 |
+
}
|
71 |
+
}
|
72 |
+
?>
|
includes/aalb_deactivator.php
ADDED
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
Copyright 2016-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
5 |
+
|
6 |
+
Licensed under the GNU General Public License as published by the Free Software Foundation,
|
7 |
+
Version 2.0 (the "License"). You may not use this file except in compliance with the License.
|
8 |
+
A copy of the License is located in the "license" file accompanying this file.
|
9 |
+
|
10 |
+
This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
11 |
+
either express or implied. See the License for the specific language governing permissions
|
12 |
+
and limitations under the License.
|
13 |
+
*/
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Fired during the plugin deactivation
|
17 |
+
*
|
18 |
+
* @since 1.0.0
|
19 |
+
* @package AmazonAssociatesLinkBuilder
|
20 |
+
* @subpackage AmazonAssociatesLinkBuilder/includes
|
21 |
+
*/
|
22 |
+
class Aalb_Deactivator {
|
23 |
+
|
24 |
+
protected $helper;
|
25 |
+
|
26 |
+
public function __construct() {
|
27 |
+
$this->helper = new Aalb_Helper();
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Remove the settings stored by the admin in the database
|
32 |
+
*
|
33 |
+
* @since 1.0.0
|
34 |
+
*/
|
35 |
+
public function remove_settings() {
|
36 |
+
global $wpdb;
|
37 |
+
|
38 |
+
$statement = 'DELETE from wp_options
|
39 |
+
WHERE option_name like %s';
|
40 |
+
$settings = "aalb%";
|
41 |
+
$prepared_statement = $wpdb->prepare($statement, $settings);
|
42 |
+
|
43 |
+
try {
|
44 |
+
$wpdb->query($prepared_statement);
|
45 |
+
} catch(Exception $e) {
|
46 |
+
error_log('Unable to clear settings. Query failed with the Exception ' . $e->getMessage());
|
47 |
+
}
|
48 |
+
}
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Remove the cache stored in the database.
|
52 |
+
*
|
53 |
+
* @since 1.0.0
|
54 |
+
*/
|
55 |
+
public function remove_cache() {
|
56 |
+
$this->helper->clear_cache_for_substring('');
|
57 |
+
}
|
58 |
+
}
|
59 |
+
|
60 |
+
?>
|
includes/aalb_helper.php
ADDED
@@ -0,0 +1,166 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
Copyright 2016-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
5 |
+
|
6 |
+
Licensed under the GNU General Public License as published by the Free Software Foundation,
|
7 |
+
Version 2.0 (the "License"). You may not use this file except in compliance with the License.
|
8 |
+
A copy of the License is located in the "license" file accompanying this file.
|
9 |
+
|
10 |
+
This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
11 |
+
either express or implied. See the License for the specific language governing permissions
|
12 |
+
and limitations under the License.
|
13 |
+
*/
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Hepler class for commonly used functions in the plugin.
|
17 |
+
*
|
18 |
+
* @since 1.0.0
|
19 |
+
* @package AmazonAssociatesLinkBuilder
|
20 |
+
* @subpackage AmazonAssociatesLinkBuilder/includes
|
21 |
+
*/
|
22 |
+
class Aalb_Helper{
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Build key for storing rendered template in cache.
|
26 |
+
*
|
27 |
+
* @since 1.0.0
|
28 |
+
* @param string $asins List of hyphen separated asins.
|
29 |
+
* @param string $marketplace Marketplace of the asin to look into.
|
30 |
+
* @param string $store The identifier of the store to be used for current adunit
|
31 |
+
* @param string $template Template to render the display unit.
|
32 |
+
* @return string Template cache key.
|
33 |
+
*/
|
34 |
+
public function build_template_cache_key($asins, $marketplace, $store, $template) {
|
35 |
+
return 'aalb' . '-' . $asins . '-' . $marketplace . '-' . $store . '-' . $template;
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Build key for storing product information in cache.
|
40 |
+
*
|
41 |
+
* @since 1.0.0
|
42 |
+
* @param string $asins List of hyphen separated asins.
|
43 |
+
* @param string $marketplace Marketplace of the asin to look into.
|
44 |
+
* @param string $store The identifier of the store to be used for current adunit
|
45 |
+
* @return string Products information cache key.
|
46 |
+
*/
|
47 |
+
public function build_products_cache_key($asins, $marketplace, $store) {
|
48 |
+
return 'aalb' . '-' . $asins . '-' . $marketplace . '-' . $store;
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Clears the cache for the given template name
|
53 |
+
*
|
54 |
+
* @since 1.0.0
|
55 |
+
* @param string $template The template to clear the cache for
|
56 |
+
*/
|
57 |
+
public function clear_cache_for_template($template) {
|
58 |
+
$this->clear_cache_for_substring($template);
|
59 |
+
}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Clear the cache for keys which contain the given substring
|
63 |
+
*
|
64 |
+
* @since 1.0.0
|
65 |
+
* @param string $substring The subtring which is a part of the keys to be cleared
|
66 |
+
*/
|
67 |
+
public function clear_cache_for_substring($substring) {
|
68 |
+
global $wpdb;
|
69 |
+
|
70 |
+
$statement = 'DELETE from wp_options
|
71 |
+
WHERE option_name like %s or option_name like %s';
|
72 |
+
$transient_timeout_cache = '_transient_timeout_aalb%' . $substring . '%';
|
73 |
+
$transient_cache = '_transient_aalb%' . $substring . '%';
|
74 |
+
$prepared_statement = $wpdb->prepare($statement, $transient_timeout_cache, $transient_cache);
|
75 |
+
|
76 |
+
try {
|
77 |
+
$wpdb->query($prepared_statement);
|
78 |
+
} catch(Exception $e) {
|
79 |
+
error_log('Unable to clear cache. Query to clear cache for substring ' . $substring . ' failed with the Exception ' . $e->getMessage());
|
80 |
+
}
|
81 |
+
}
|
82 |
+
|
83 |
+
/**
|
84 |
+
* Clear the dead expired transients from cache at intervals
|
85 |
+
*
|
86 |
+
* @since 1.0.0
|
87 |
+
*/
|
88 |
+
public function clear_expired_transients_at_intervals() {
|
89 |
+
$randomNumber = rand(1,50);
|
90 |
+
// Clear the expired transients approximately once in 50 requests.
|
91 |
+
if($randomNumber == 25) {
|
92 |
+
$this->clear_expired_transients();
|
93 |
+
}
|
94 |
+
}
|
95 |
+
|
96 |
+
/**
|
97 |
+
* Clear the dead expired transients from cache
|
98 |
+
*
|
99 |
+
* @since 1.0.0
|
100 |
+
*/
|
101 |
+
public function clear_expired_transients() {
|
102 |
+
global $wpdb;
|
103 |
+
|
104 |
+
$transients_prefix = esc_sql( "_transient_timeout_aalb%" );
|
105 |
+
$sql = $wpdb -> prepare (
|
106 |
+
'
|
107 |
+
SELECT option_name
|
108 |
+
FROM wp_options
|
109 |
+
WHERE option_name LIKE %s
|
110 |
+
',
|
111 |
+
$transients_prefix
|
112 |
+
);
|
113 |
+
$transients = $wpdb -> get_col( $sql );
|
114 |
+
foreach( $transients as $transient ) {
|
115 |
+
// Strip away the WordPress prefix in order to arrive at the transient key.
|
116 |
+
$key = str_replace( '_transient_timeout_', '', $transient );
|
117 |
+
delete_transient($key);
|
118 |
+
}
|
119 |
+
wp_cache_flush();
|
120 |
+
}
|
121 |
+
|
122 |
+
/**
|
123 |
+
* Displays error messages in preview mode only
|
124 |
+
*
|
125 |
+
* @since 1.0.0
|
126 |
+
* @param string $error_message Error message to be displayed
|
127 |
+
*/
|
128 |
+
public function show_error_in_preview($error_message) {
|
129 |
+
if (is_preview()) {
|
130 |
+
//If it's preview mode
|
131 |
+
echo "<br><font color='red'><b>" . $error_message . "</b></font>";
|
132 |
+
}
|
133 |
+
}
|
134 |
+
|
135 |
+
/**
|
136 |
+
* Returns the Store IDs Array.
|
137 |
+
* Returns AALB_DEFAULT_STORE_ID_NAME if the nothing is specified.
|
138 |
+
*
|
139 |
+
* @since 1.0.0
|
140 |
+
*/
|
141 |
+
public function get_store_ids_array(){
|
142 |
+
return explode("\r\n", strlen(get_option(AALB_STORE_ID_NAMES))?get_option(AALB_STORE_ID_NAMES):AALB_DEFAULT_STORE_ID_NAME);
|
143 |
+
}
|
144 |
+
|
145 |
+
/**
|
146 |
+
* Fetches the current plugins version number
|
147 |
+
*
|
148 |
+
* @since 1.0.0
|
149 |
+
* @return string Version number of the plugin
|
150 |
+
*/
|
151 |
+
function get_plugin_version() {
|
152 |
+
return AALB_PLUGIN_VERSION;
|
153 |
+
}
|
154 |
+
|
155 |
+
/**
|
156 |
+
* Fetches the Wordpress version number
|
157 |
+
*
|
158 |
+
* @since 1.0.0
|
159 |
+
* @return string Version number of Wordpress
|
160 |
+
*/
|
161 |
+
function get_wordpress_version() {
|
162 |
+
global $wp_version;
|
163 |
+
return $wp_version;
|
164 |
+
}
|
165 |
+
}
|
166 |
+
?>
|
includes/aalb_hook_loader.php
ADDED
@@ -0,0 +1,82 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
Copyright 2016-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
5 |
+
|
6 |
+
Licensed under the GNU General Public License as published by the Free Software Foundation,
|
7 |
+
Version 2.0 (the "License"). You may not use this file except in compliance with the License.
|
8 |
+
A copy of the License is located in the "license" file accompanying this file.
|
9 |
+
|
10 |
+
This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
11 |
+
either express or implied. See the License for the specific language governing permissions
|
12 |
+
and limitations under the License.
|
13 |
+
*/
|
14 |
+
|
15 |
+
/**
|
16 |
+
* The class that loads all the hooks.
|
17 |
+
*
|
18 |
+
* @since 1.0.0
|
19 |
+
* @package AmazonAssociatesLinkBuilder
|
20 |
+
* @subpackage AmazonAssociatesLinkBuilder/includes
|
21 |
+
*/
|
22 |
+
class Aalb_Hook_Loader {
|
23 |
+
|
24 |
+
protected $actions;
|
25 |
+
|
26 |
+
public function __construct() {
|
27 |
+
$this->actions = array();
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Add a new action to the collection to be registered with WordPress.
|
32 |
+
*
|
33 |
+
* @since 1.0.0
|
34 |
+
* @param string $hook The name of the WordPress action that is being registered.
|
35 |
+
* @param object $component A reference to the instance of the object on which the action is defined.
|
36 |
+
* @param string $callback The name of the function definition on the $component.
|
37 |
+
* @param int $priority Optional. he priority at which the function should be fired. Default is 10.
|
38 |
+
* @param int $accepted_args Optional. The number of arguments that should be passed to the $callback. Default is 1.
|
39 |
+
*/
|
40 |
+
public function add_action( $hook, $component, $callback, $priority = 10, $accepted_args = 1 ) {
|
41 |
+
$this->actions = $this->add( $this->actions, $hook, $component, $callback, $priority, $accepted_args );
|
42 |
+
}
|
43 |
+
|
44 |
+
/**
|
45 |
+
* A utility function that is used to register the actions and hooks into a single
|
46 |
+
* collection.
|
47 |
+
*
|
48 |
+
* @since 1.0.0
|
49 |
+
* @access private
|
50 |
+
* @param array $hooks The collection of hooks that is being registered (that is, actions or filters).
|
51 |
+
* @param string $hook The name of the WordPress filter that is being registered.
|
52 |
+
* @param object $component A reference to the instance of the object on which the filter is defined.
|
53 |
+
* @param string $callback The name of the function definition on the $component.
|
54 |
+
* @param int $priority The priority at which the function should be fired.
|
55 |
+
* @param int $accepted_args The number of arguments that should be passed to the $callback.
|
56 |
+
* @return array The collection of actions and filters registered with WordPress.
|
57 |
+
*/
|
58 |
+
private function add( $hooks, $hook, $component, $callback, $priority, $accepted_args ) {
|
59 |
+
$hooks[] = array(
|
60 |
+
'hook' => $hook,
|
61 |
+
'component' => $component,
|
62 |
+
'callback' => $callback,
|
63 |
+
'priority' => $priority,
|
64 |
+
'accepted_args' => $accepted_args
|
65 |
+
);
|
66 |
+
return $hooks;
|
67 |
+
}
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Register the filters and actions with WordPress.
|
71 |
+
*
|
72 |
+
* @since 1.0.0
|
73 |
+
*/
|
74 |
+
public function execute() {
|
75 |
+
foreach ( $this->actions as $hook ) {
|
76 |
+
add_action( $hook['hook'], array( $hook['component'], $hook['callback'] ), $hook['priority'], $hook['accepted_args'] );
|
77 |
+
}
|
78 |
+
}
|
79 |
+
|
80 |
+
}
|
81 |
+
|
82 |
+
?>
|
includes/aalb_manager.php
ADDED
@@ -0,0 +1,79 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
Copyright 2016-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
5 |
+
|
6 |
+
Licensed under the GNU General Public License as published by the Free Software Foundation,
|
7 |
+
Version 2.0 (the "License"). You may not use this file except in compliance with the License.
|
8 |
+
A copy of the License is located in the "license" file accompanying this file.
|
9 |
+
|
10 |
+
This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
11 |
+
either express or implied. See the License for the specific language governing permissions
|
12 |
+
and limitations under the License.
|
13 |
+
*/
|
14 |
+
|
15 |
+
/**
|
16 |
+
* The class that manages all the events of the wordpress.
|
17 |
+
*
|
18 |
+
* @since 1.0.0
|
19 |
+
* @package AmazonAssociatesLinkBuilder
|
20 |
+
* @subpackage AmazonAssociatesLinkBuilder/includes
|
21 |
+
*/
|
22 |
+
class Aalb_Manager {
|
23 |
+
|
24 |
+
protected $hook_loader;
|
25 |
+
protected $shortcode_loader;
|
26 |
+
|
27 |
+
public function __construct() {
|
28 |
+
$this->hook_loader = new Aalb_Hook_Loader();
|
29 |
+
$this->shortcode_loader = new Aalb_Shortcode_Loader();
|
30 |
+
|
31 |
+
//add the hooks specific to admin.
|
32 |
+
$this->add_admin_hooks();
|
33 |
+
|
34 |
+
//add the hooks for shortcode rendering.
|
35 |
+
$this->register_shortcode_hooks();
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Add the hooks in the admin section
|
40 |
+
*
|
41 |
+
* @since 1.0.0
|
42 |
+
*/
|
43 |
+
private function add_admin_hooks() {
|
44 |
+
$aalb_admin = new Aalb_Admin();
|
45 |
+
$this->hook_loader->add_action( 'admin_enqueue_scripts', $aalb_admin, 'enqueue_styles' );
|
46 |
+
$this->hook_loader->add_action( 'admin_enqueue_scripts', $aalb_admin, 'enqueue_scripts' );
|
47 |
+
$this->hook_loader->add_action( 'admin_print_footer_scripts', $aalb_admin, 'add_quicktags');
|
48 |
+
$this->hook_loader->add_action( 'wp_ajax_get_item_search_result', $aalb_admin, 'get_item_search_result');
|
49 |
+
$this->hook_loader->add_action( 'wp_ajax_get_link_code', $aalb_admin, 'get_link_code');
|
50 |
+
$this->hook_loader->add_action( 'media_buttons', $aalb_admin, 'admin_display_callback');
|
51 |
+
|
52 |
+
$aalb_sidebar = new Aalb_Sidebar();
|
53 |
+
$this->hook_loader->add_action( 'admin_init', $aalb_sidebar, 'register_cred_config_group');
|
54 |
+
$this->hook_loader->add_action( 'admin_menu', $aalb_sidebar, 'register_sidebar_config_page');
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Add the hooks for the shortcode rendering.
|
59 |
+
*
|
60 |
+
* @since 1.0.0
|
61 |
+
*/
|
62 |
+
private function register_shortcode_hooks() {
|
63 |
+
$aalb_shortcode = $this->shortcode_loader->get_shortcode();
|
64 |
+
$this->hook_loader->add_action('wp_enqueue_scripts', $aalb_shortcode, 'enqueue_styles');
|
65 |
+
}
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Execute all the wordpress hooks and shortcodes.
|
69 |
+
*
|
70 |
+
* @since 1.0.0
|
71 |
+
*/
|
72 |
+
public function execute() {
|
73 |
+
$this->hook_loader->execute();
|
74 |
+
$this->shortcode_loader->add_shortcode();
|
75 |
+
}
|
76 |
+
|
77 |
+
}
|
78 |
+
|
79 |
+
?>
|
includes/aalb_remote_loader.php
ADDED
@@ -0,0 +1,89 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
Copyright 2016-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
5 |
+
|
6 |
+
Licensed under the GNU General Public License as published by the Free Software Foundation,
|
7 |
+
Version 2.0 (the "License"). You may not use this file except in compliance with the License.
|
8 |
+
A copy of the License is located in the "license" file accompanying this file.
|
9 |
+
|
10 |
+
This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
11 |
+
either express or implied. See the License for the specific language governing permissions
|
12 |
+
and limitations under the License.
|
13 |
+
*/
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Fired while making a GET request.
|
17 |
+
*
|
18 |
+
* Generic class that can be used by any class to make a GET request call.
|
19 |
+
*
|
20 |
+
* @since 1.0.0
|
21 |
+
* @package AmazonAssociatesLinkBuilder
|
22 |
+
* @subpackage AmazonAssociatesLinkBuilder/includes
|
23 |
+
*/
|
24 |
+
class Aalb_Remote_Loader {
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Load the information by making a GET request.
|
28 |
+
*
|
29 |
+
* @since 1.0.0
|
30 |
+
* @param string $url URL for making a request.
|
31 |
+
* @return string GET response body.
|
32 |
+
*/
|
33 |
+
public function load($url) {
|
34 |
+
$response = $this->fetch($url);
|
35 |
+
return $this->verify($response);
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Load the information by making a POST request.
|
40 |
+
*
|
41 |
+
* @since 1.0.0
|
42 |
+
* @param string $url URL for making a request.
|
43 |
+
* @param string $body Body of the POST request.
|
44 |
+
* @return string POST response body.
|
45 |
+
*/
|
46 |
+
public function post($url, $body) {
|
47 |
+
$response = wp_remote_post($url, array('body' => $body));
|
48 |
+
return $this->verify($response);
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Make a GET request and return the response.
|
53 |
+
*
|
54 |
+
* @since 1.0.0
|
55 |
+
* @param string $url URL for making a request.
|
56 |
+
* @return string GET Response.
|
57 |
+
*/
|
58 |
+
private function fetch($url) {
|
59 |
+
return wp_remote_get($url);
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Verify the response the throw exceptions accordingly.
|
64 |
+
* Return only the response body.
|
65 |
+
*
|
66 |
+
* @since 1.0.0
|
67 |
+
* @param string $response Whole response including headers,body and footers.
|
68 |
+
* @return string Response body.
|
69 |
+
*/
|
70 |
+
private function verify($response) {
|
71 |
+
if(is_wp_error($response)) {
|
72 |
+
$error_message = $response->get_error_message();
|
73 |
+
throw new Exception('HTTP Request failed! ' . $error_message);
|
74 |
+
}
|
75 |
+
$code = $response['response']['code'];
|
76 |
+
if($code != HTTP_SUCCESS) {
|
77 |
+
throw new Exception($code);
|
78 |
+
}
|
79 |
+
$response_body = wp_remote_retrieve_body($response);
|
80 |
+
if(!isset($response_body) || trim($response_body)==='') {
|
81 |
+
throw new Exception('Response body is empty');
|
82 |
+
}
|
83 |
+
|
84 |
+
return $response_body;
|
85 |
+
}
|
86 |
+
|
87 |
+
}
|
88 |
+
|
89 |
+
?>
|
includes/aalb_template_engine.php
ADDED
@@ -0,0 +1,128 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
Copyright 2016-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
5 |
+
|
6 |
+
Licensed under the GNU General Public License as published by the Free Software Foundation,
|
7 |
+
Version 2.0 (the "License"). You may not use this file except in compliance with the License.
|
8 |
+
A copy of the License is located in the "license" file accompanying this file.
|
9 |
+
|
10 |
+
This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
11 |
+
either express or implied. See the License for the specific language governing permissions
|
12 |
+
and limitations under the License.
|
13 |
+
*/
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Template engine to render the product in the particular display unit.
|
17 |
+
*
|
18 |
+
* @since 1.0.0
|
19 |
+
* @package AmazonAssociatesLinkBuilder
|
20 |
+
* @subpackage AmazonAssociatesLinkBuilder/includes
|
21 |
+
*/
|
22 |
+
class Aalb_Template_Engine {
|
23 |
+
|
24 |
+
protected $xml_loader;
|
25 |
+
protected $cache_template_loader;
|
26 |
+
protected $mustache;
|
27 |
+
protected $xml_helper;
|
28 |
+
|
29 |
+
public function __construct() {
|
30 |
+
$this->xml_loader = new Aalb_Cache_Loader(new Aalb_Remote_Loader());
|
31 |
+
$this->cache_template_loader = new Aalb_Cache_Template_Loader();
|
32 |
+
$this->mustache = new Mustache_Engine(array('loader' => new Mustache_Loader_FilesystemLoader(AALB_TEMPLATE_DIR)));
|
33 |
+
$this->xml_helper = new Aalb_Xml_Helper();
|
34 |
+
}
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Render the products into the display unit.
|
38 |
+
* If the display unit exists in the cache return the display unit.
|
39 |
+
* Else get the xml and render the product.
|
40 |
+
*
|
41 |
+
* @since 1.0.0
|
42 |
+
* @param string $display_key Key of the display unit.
|
43 |
+
* @param string $products_key Key of the combined products.
|
44 |
+
* @param string $template Template to render the display unit.
|
45 |
+
* @param string $url Url to get the product from if not present in cache.
|
46 |
+
* @return string HTML of the disply unit.
|
47 |
+
*/
|
48 |
+
public function render($display_key, $products_key, $template, $url, $marketplace) {
|
49 |
+
if(false === ($display_unit = $this->cache_template_loader->get_display_unit($display_key) ) ) {
|
50 |
+
$products = $this->get_products($products_key, $url);
|
51 |
+
$xml = $this->parse($products);
|
52 |
+
$items = $this->get_items($xml);
|
53 |
+
|
54 |
+
//Add Click URL Prefix to required hyperlinks
|
55 |
+
$items = $this->xml_helper->prefix_click_URL($items);
|
56 |
+
//Add custom nodes to the XML
|
57 |
+
$custom_items = $this->xml_helper->add_custom_nodes($items, $marketplace);
|
58 |
+
|
59 |
+
$display_unit = $this->render_xml($custom_items, $template);
|
60 |
+
$this->cache_template_loader->save_display_unit($display_key, $display_unit);
|
61 |
+
}
|
62 |
+
return $display_unit;
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Get the products information.
|
67 |
+
*
|
68 |
+
* @since 1.0.0
|
69 |
+
* @param string $key Unique identification of the product.
|
70 |
+
* @param string $url Signed URL for the PAAPI request.
|
71 |
+
* @return string Xml response from PAAPI.
|
72 |
+
*/
|
73 |
+
private function get_products($key, $url) {
|
74 |
+
return $this->xml_loader->load($key, $url);
|
75 |
+
}
|
76 |
+
|
77 |
+
/**
|
78 |
+
* Convert the well-formed xml string into a SimpleXMLElement object.
|
79 |
+
*
|
80 |
+
* @since 1.0.0
|
81 |
+
* @param string $xml_string Well-formed XML string
|
82 |
+
* @return SimpleXMLElement Php xml object.
|
83 |
+
*/
|
84 |
+
private function parse($xml_string) {
|
85 |
+
libxml_use_internal_errors(true);
|
86 |
+
$xml = simplexml_load_string($xml_string);
|
87 |
+
|
88 |
+
if($xml === false) {
|
89 |
+
throw new Exception('Failed Loading XML');
|
90 |
+
}
|
91 |
+
|
92 |
+
if(isset($xml->Items->Request->Errors->Error)) {
|
93 |
+
throw new Exception($xml->Items->Request->Errors->Error->Code);
|
94 |
+
}
|
95 |
+
|
96 |
+
return $xml;
|
97 |
+
}
|
98 |
+
|
99 |
+
/**
|
100 |
+
* Return the Item attribute contained in the xml.
|
101 |
+
*
|
102 |
+
* @since 1.0.0
|
103 |
+
* @param SimpleXMLElement $xml Well-formed XML string
|
104 |
+
* @return SimpleXMLElement Php xml object of the Items attribute.
|
105 |
+
*/
|
106 |
+
private function get_items($xml) {
|
107 |
+
return $xml->Items;
|
108 |
+
}
|
109 |
+
|
110 |
+
/**
|
111 |
+
* Render the xml with a specific template.
|
112 |
+
*
|
113 |
+
* @since 1.0.0
|
114 |
+
* @param array $items Each key consists of an item information object.
|
115 |
+
* @param string $template Template in which the content has to be rendered.
|
116 |
+
* @return string HTML of the display unit.
|
117 |
+
*/
|
118 |
+
private function render_xml($items, $template) {
|
119 |
+
try {
|
120 |
+
$template = $this->mustache->loadTemplate($template);
|
121 |
+
} catch (Mustache_Exception_UnknownTemplateException $e) {
|
122 |
+
$template = $this->mustache->loadTemplate(get_option(AALB_DEFAULT_TEMPLATE,AALB_DEFAULT_TEMPLATE_NAME));
|
123 |
+
}
|
124 |
+
|
125 |
+
return $template->render(array('StoreId' => get_option(AALB_DEFAULT_STORE_ID),'Items' => $items));
|
126 |
+
}
|
127 |
+
}
|
128 |
+
?>
|
lib/js/jssha2/license.txt
ADDED
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Copyright (c) 2003-2004, Angel Marin
|
2 |
+
All rights reserved.
|
3 |
+
|
4 |
+
Redistribution and use in source and binary forms, with or without modification,
|
5 |
+
are permitted provided that the following conditions are met:
|
6 |
+
|
7 |
+
* Redistributions of source code must retain the above copyright notice, this
|
8 |
+
list of conditions and the following disclaimer.
|
9 |
+
* Redistributions in binary form must reproduce the above copyright notice,
|
10 |
+
this list of conditions and the following disclaimer in the documentation
|
11 |
+
and/or other materials provided with the distribution.
|
12 |
+
* Neither the name of the <ORGANIZATION> nor the names of its contributors may
|
13 |
+
be used to endorse or promote products derived from this software without
|
14 |
+
specific prior written permission.
|
15 |
+
|
16 |
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
17 |
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
18 |
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
19 |
+
IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
20 |
+
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
21 |
+
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
22 |
+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
23 |
+
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
24 |
+
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
25 |
+
OF THE POSSIBILITY OF SUCH DAMAGE.
|
lib/js/jssha2/sha2.js
ADDED
@@ -0,0 +1,144 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/* A JavaScript implementation of the Secure Hash Standard
|
2 |
+
* Version 0.3 Copyright Angel Marin 2003-2004 - http://anmar.eu.org/
|
3 |
+
* Distributed under the BSD License
|
4 |
+
* Some bits taken from Paul Johnston's SHA-1 implementation
|
5 |
+
*/
|
6 |
+
var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */
|
7 |
+
var hexcase = 0;/* hex output format. 0 - lowercase; 1 - uppercase */
|
8 |
+
|
9 |
+
function safe_add (x, y) {
|
10 |
+
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
|
11 |
+
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
|
12 |
+
return (msw << 16) | (lsw & 0xFFFF);
|
13 |
+
}
|
14 |
+
|
15 |
+
function S (X, n) {return ( X >>> n ) | (X << (32 - n));}
|
16 |
+
|
17 |
+
function R (X, n) {return ( X >>> n );}
|
18 |
+
|
19 |
+
function Ch(x, y, z) {return ((x & y) ^ ((~x) & z));}
|
20 |
+
|
21 |
+
function Maj(x, y, z) {return ((x & y) ^ (x & z) ^ (y & z));}
|
22 |
+
|
23 |
+
function Sigma0256(x) {return (S(x, 2) ^ S(x, 13) ^ S(x, 22));}
|
24 |
+
|
25 |
+
function Sigma1256(x) {return (S(x, 6) ^ S(x, 11) ^ S(x, 25));}
|
26 |
+
|
27 |
+
function Gamma0256(x) {return (S(x, 7) ^ S(x, 18) ^ R(x, 3));}
|
28 |
+
|
29 |
+
function Gamma1256(x) {return (S(x, 17) ^ S(x, 19) ^ R(x, 10));}
|
30 |
+
|
31 |
+
function Sigma0512(x) {return (S(x, 28) ^ S(x, 34) ^ S(x, 39));}
|
32 |
+
|
33 |
+
function Sigma1512(x) {return (S(x, 14) ^ S(x, 18) ^ S(x, 41));}
|
34 |
+
|
35 |
+
function Gamma0512(x) {return (S(x, 1) ^ S(x, 8) ^ R(x, 7));}
|
36 |
+
|
37 |
+
function Gamma1512(x) {return (S(x, 19) ^ S(x, 61) ^ R(x, 6));}
|
38 |
+
|
39 |
+
function core_sha256 (m, l) {
|
40 |
+
var K = new Array(0x428A2F98,0x71374491,0xB5C0FBCF,0xE9B5DBA5,0x3956C25B,0x59F111F1,0x923F82A4,0xAB1C5ED5,0xD807AA98,0x12835B01,0x243185BE,0x550C7DC3,0x72BE5D74,0x80DEB1FE,0x9BDC06A7,0xC19BF174,0xE49B69C1,0xEFBE4786,0xFC19DC6,0x240CA1CC,0x2DE92C6F,0x4A7484AA,0x5CB0A9DC,0x76F988DA,0x983E5152,0xA831C66D,0xB00327C8,0xBF597FC7,0xC6E00BF3,0xD5A79147,0x6CA6351,0x14292967,0x27B70A85,0x2E1B2138,0x4D2C6DFC,0x53380D13,0x650A7354,0x766A0ABB,0x81C2C92E,0x92722C85,0xA2BFE8A1,0xA81A664B,0xC24B8B70,0xC76C51A3,0xD192E819,0xD6990624,0xF40E3585,0x106AA070,0x19A4C116,0x1E376C08,0x2748774C,0x34B0BCB5,0x391C0CB3,0x4ED8AA4A,0x5B9CCA4F,0x682E6FF3,0x748F82EE,0x78A5636F,0x84C87814,0x8CC70208,0x90BEFFFA,0xA4506CEB,0xBEF9A3F7,0xC67178F2);
|
41 |
+
var HASH = new Array(0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19);
|
42 |
+
var W = new Array(64);
|
43 |
+
var a, b, c, d, e, f, g, h, i, j;
|
44 |
+
var T1, T2;
|
45 |
+
|
46 |
+
/* append padding */
|
47 |
+
m[l >> 5] |= 0x80 << (24 - l % 32);
|
48 |
+
m[((l + 64 >> 9) << 4) + 15] = l;
|
49 |
+
|
50 |
+
for ( var i = 0; i<m.length; i+=16 ) {
|
51 |
+
a = HASH[0];
|
52 |
+
b = HASH[1];
|
53 |
+
c = HASH[2];
|
54 |
+
d = HASH[3];
|
55 |
+
e = HASH[4];
|
56 |
+
f = HASH[5];
|
57 |
+
g = HASH[6];
|
58 |
+
h = HASH[7];
|
59 |
+
|
60 |
+
for ( var j = 0; j<64; j++) {
|
61 |
+
if (j < 16) W[j] = m[j + i];
|
62 |
+
else W[j] = safe_add(safe_add(safe_add(Gamma1256(W[j - 2]), W[j - 7]), Gamma0256(W[j - 15])), W[j - 16]);
|
63 |
+
|
64 |
+
T1 = safe_add(safe_add(safe_add(safe_add(h, Sigma1256(e)), Ch(e, f, g)), K[j]), W[j]);
|
65 |
+
T2 = safe_add(Sigma0256(a), Maj(a, b, c));
|
66 |
+
|
67 |
+
h = g;
|
68 |
+
g = f;
|
69 |
+
f = e;
|
70 |
+
e = safe_add(d, T1);
|
71 |
+
d = c;
|
72 |
+
c = b;
|
73 |
+
b = a;
|
74 |
+
a = safe_add(T1, T2);
|
75 |
+
}
|
76 |
+
|
77 |
+
HASH[0] = safe_add(a, HASH[0]);
|
78 |
+
HASH[1] = safe_add(b, HASH[1]);
|
79 |
+
HASH[2] = safe_add(c, HASH[2]);
|
80 |
+
HASH[3] = safe_add(d, HASH[3]);
|
81 |
+
HASH[4] = safe_add(e, HASH[4]);
|
82 |
+
HASH[5] = safe_add(f, HASH[5]);
|
83 |
+
HASH[6] = safe_add(g, HASH[6]);
|
84 |
+
HASH[7] = safe_add(h, HASH[7]);
|
85 |
+
}
|
86 |
+
return HASH;
|
87 |
+
}
|
88 |
+
|
89 |
+
function core_sha512 (m, l) {
|
90 |
+
var K = new Array(0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, 0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694, 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, 0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, 0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4, 0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70, 0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df, 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b, 0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30, 0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8, 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8, 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, 0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec, 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b, 0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, 0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b, 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c, 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817);
|
91 |
+
var HASH = new Array(0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, 0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179);
|
92 |
+
var W = new Array(80);
|
93 |
+
var a, b, c, d, e, f, g, h, i, j;
|
94 |
+
var T1, T2;
|
95 |
+
|
96 |
+
}
|
97 |
+
|
98 |
+
function str2binb (str) {
|
99 |
+
var bin = Array();
|
100 |
+
var mask = (1 << chrsz) - 1;
|
101 |
+
for(var i = 0; i < str.length * chrsz; i += chrsz)
|
102 |
+
bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (24 - i%32);
|
103 |
+
return bin;
|
104 |
+
}
|
105 |
+
|
106 |
+
function binb2str (bin) {
|
107 |
+
var str = "";
|
108 |
+
var mask = (1 << chrsz) - 1;
|
109 |
+
for(var i = 0; i < bin.length * 32; i += chrsz)
|
110 |
+
str += String.fromCharCode((bin[i>>5] >>> (24 - i%32)) & mask);
|
111 |
+
return str;
|
112 |
+
}
|
113 |
+
|
114 |
+
function binb2hex (binarray) {
|
115 |
+
var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
|
116 |
+
var str = "";
|
117 |
+
for(var i = 0; i < binarray.length * 4; i++)
|
118 |
+
{
|
119 |
+
str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) +
|
120 |
+
hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF);
|
121 |
+
}
|
122 |
+
return str;
|
123 |
+
}
|
124 |
+
|
125 |
+
function binb2b64 (binarray) {
|
126 |
+
var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
127 |
+
var str = "";
|
128 |
+
for(var i = 0; i < binarray.length * 4; i += 3)
|
129 |
+
{
|
130 |
+
var triplet = (((binarray[i >> 2] >> 8 * (3 - i %4)) & 0xFF) << 16)
|
131 |
+
| (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 )
|
132 |
+
| ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF);
|
133 |
+
for(var j = 0; j < 4; j++)
|
134 |
+
{
|
135 |
+
if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
|
136 |
+
else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
|
137 |
+
}
|
138 |
+
}
|
139 |
+
return str;
|
140 |
+
}
|
141 |
+
|
142 |
+
function hex_sha256(s){return binb2hex(core_sha256(str2binb(s),s.length * chrsz));}
|
143 |
+
function b64_sha256(s){return binb2b64(core_sha256(str2binb(s),s.length * chrsz));}
|
144 |
+
function str_sha256(s){return binb2str(core_sha256(str2binb(s),s.length * chrsz));}
|
lib/php/Mustache/Autoloader.php
ADDED
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of Mustache.php.
|
5 |
+
*
|
6 |
+
* (c) 2010-2015 Justin Hileman
|
7 |
+
*
|
8 |
+
* For the full copyright and license information, please view the LICENSE
|
9 |
+
* file that was distributed with this source code.
|
10 |
+
*/
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Mustache class autoloader.
|
14 |
+
*/
|
15 |
+
class Mustache_Autoloader
|
16 |
+
{
|
17 |
+
private $baseDir;
|
18 |
+
|
19 |
+
/**
|
20 |
+
* Autoloader constructor.
|
21 |
+
*
|
22 |
+
* @param string $baseDir Mustache library base directory (default: dirname(__FILE__).'/..')
|
23 |
+
*/
|
24 |
+
public function __construct($baseDir = null)
|
25 |
+
{
|
26 |
+
if ($baseDir === null) {
|
27 |
+
$baseDir = dirname(__FILE__) . '/..';
|
28 |
+
}
|
29 |
+
|
30 |
+
// realpath doesn't always work, for example, with stream URIs
|
31 |
+
$realDir = realpath($baseDir);
|
32 |
+
if (is_dir($realDir)) {
|
33 |
+
$this->baseDir = $realDir;
|
34 |
+
} else {
|
35 |
+
$this->baseDir = $baseDir;
|
36 |
+
}
|
37 |
+
}
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Register a new instance as an SPL autoloader.
|
41 |
+
*
|
42 |
+
* @param string $baseDir Mustache library base directory (default: dirname(__FILE__).'/..')
|
43 |
+
*
|
44 |
+
* @return Mustache_Autoloader Registered Autoloader instance
|
45 |
+
*/
|
46 |
+
public static function register($baseDir = null)
|
47 |
+
{
|
48 |
+
$loader = new self($baseDir);
|
49 |
+
spl_autoload_register(array($loader, 'autoload'));
|
50 |
+
|
51 |
+
return $loader;
|
52 |
+
}
|
53 |
+
|
54 |
+
/**
|
55 |
+
* Autoload Mustache classes.
|
56 |
+
*
|
57 |
+
* @param string $class
|
58 |
+
*/
|
59 |
+
public function autoload($class)
|
60 |
+
{
|
61 |
+
if ($class[0] === '\\') {
|
62 |
+
$class = substr($class, 1);
|
63 |
+
}
|
64 |
+
|
65 |
+
if (strpos($class, 'Mustache') !== 0) {
|
66 |
+
return;
|
67 |
+
}
|
68 |
+
|
69 |
+
$file = sprintf('%s/%s.php', $this->baseDir, str_replace('_', '/', $class));
|
70 |
+
if (is_file($file)) {
|
71 |
+
require $file;
|
72 |
+
}
|
73 |
+
}
|
74 |
+
}
|
lib/php/Mustache/Cache.php
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of Mustache.php.
|
5 |
+
*
|
6 |
+
* (c) 2010-2015 Justin Hileman
|
7 |
+
*
|
8 |
+
* For the full copyright and license information, please view the LICENSE
|
9 |
+
* file that was distributed with this source code.
|
10 |
+
*/
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Mustache Cache interface.
|
14 |
+
*
|
15 |
+
* Interface for caching and loading Mustache_Template classes
|
16 |
+
* generated by the Mustache_Compiler.
|
17 |
+
*/
|
18 |
+
interface Mustache_Cache
|
19 |
+
{
|
20 |
+
/**
|
21 |
+
* Load a compiled Mustache_Template class from cache.
|
22 |
+
*
|
23 |
+
* @param string $key
|
24 |
+
*
|
25 |
+
* @return bool indicates successfully class load
|
26 |
+
*/
|
27 |
+
public function load($key);
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Cache and load a compiled Mustache_Template class.
|
31 |
+
*
|
32 |
+
* @param string $key
|
33 |
+
* @param string $value
|
34 |
+
*/
|
35 |
+
public function cache($key, $value);
|
36 |
+
}
|
lib/php/Mustache/Cache/AbstractCache.php
ADDED
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of Mustache.php.
|
5 |
+
*
|
6 |
+
* (c) 2010-2015 Justin Hileman
|
7 |
+
*
|
8 |
+
* For the full copyright and license information, please view the LICENSE
|
9 |
+
* file that was distributed with this source code.
|
10 |
+
*/
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Abstract Mustache Cache class.
|
14 |
+
*
|
15 |
+
* Provides logging support to child implementations.
|
16 |
+
*
|
17 |
+
* @abstract
|
18 |
+
*/
|
19 |
+
abstract class Mustache_Cache_AbstractCache implements Mustache_Cache
|
20 |
+
{
|
21 |
+
private $logger = null;
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Get the current logger instance.
|
25 |
+
*
|
26 |
+
* @return Mustache_Logger|Psr\Log\LoggerInterface
|
27 |
+
*/
|
28 |
+
public function getLogger()
|
29 |
+
{
|
30 |
+
return $this->logger;
|
31 |
+
}
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Set a logger instance.
|
35 |
+
*
|
36 |
+
* @param Mustache_Logger|Psr\Log\LoggerInterface $logger
|
37 |
+
*/
|
38 |
+
public function setLogger($logger = null)
|
39 |
+
{
|
40 |
+
if ($logger !== null && !($logger instanceof Mustache_Logger || is_a($logger, 'Psr\\Log\\LoggerInterface'))) {
|
41 |
+
throw new Mustache_Exception_InvalidArgumentException('Expected an instance of Mustache_Logger or Psr\\Log\\LoggerInterface.');
|
42 |
+
}
|
43 |
+
|
44 |
+
$this->logger = $logger;
|
45 |
+
}
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Add a log record if logging is enabled.
|
49 |
+
*
|
50 |
+
* @param int $level The logging level
|
51 |
+
* @param string $message The log message
|
52 |
+
* @param array $context The log context
|
53 |
+
*/
|
54 |
+
protected function log($level, $message, array $context = array())
|
55 |
+
{
|
56 |
+
if (isset($this->logger)) {
|
57 |
+
$this->logger->log($level, $message, $context);
|
58 |
+
}
|
59 |
+
}
|
60 |
+
}
|
lib/php/Mustache/Cache/FilesystemCache.php
ADDED
@@ -0,0 +1,155 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of Mustache.php.
|
5 |
+
*
|
6 |
+
* (c) 2010-2015 Justin Hileman
|
7 |
+
*
|
8 |
+
* For the full copyright and license information, please view the LICENSE
|
9 |
+
* file that was distributed with this source code.
|
10 |
+
*/
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Mustache Cache filesystem implementation.
|
14 |
+
*
|
15 |
+
* A FilesystemCache instance caches Mustache Template classes from the filesystem by name:
|
16 |
+
*
|
17 |
+
* $cache = new Mustache_Cache_FilesystemCache(dirname(__FILE__).'/cache');
|
18 |
+
* $cache->cache($className, $compiledSource);
|
19 |
+
*
|
20 |
+
* The FilesystemCache benefits from any opcode caching that may be setup in your environment. So do that, k?
|
21 |
+
*/
|
22 |
+
class Mustache_Cache_FilesystemCache extends Mustache_Cache_AbstractCache
|
23 |
+
{
|
24 |
+
private $baseDir;
|
25 |
+
private $fileMode;
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Filesystem cache constructor.
|
29 |
+
*
|
30 |
+
* @param string $baseDir Directory for compiled templates.
|
31 |
+
* @param int $fileMode Override default permissions for cache files. Defaults to using the system-defined umask.
|
32 |
+
*/
|
33 |
+
public function __construct($baseDir, $fileMode = null)
|
34 |
+
{
|
35 |
+
$this->baseDir = $baseDir;
|
36 |
+
$this->fileMode = $fileMode;
|
37 |
+
}
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Load the class from cache using `require_once`.
|
41 |
+
*
|
42 |
+
* @param string $key
|
43 |
+
*
|
44 |
+
* @return bool
|
45 |
+
*/
|
46 |
+
public function load($key)
|
47 |
+
{
|
48 |
+
$fileName = $this->getCacheFilename($key);
|
49 |
+
if (!is_file($fileName)) {
|
50 |
+
return false;
|
51 |
+
}
|
52 |
+
|
53 |
+
require_once $fileName;
|
54 |
+
|
55 |
+
return true;
|
56 |
+
}
|
57 |
+
|
58 |
+
/**
|
59 |
+
* Cache and load the compiled class.
|
60 |
+
*
|
61 |
+
* @param string $key
|
62 |
+
* @param string $value
|
63 |
+
*/
|
64 |
+
public function cache($key, $value)
|
65 |
+
{
|
66 |
+
$fileName = $this->getCacheFilename($key);
|
67 |
+
|
68 |
+
$this->log(
|
69 |
+
Mustache_Logger::DEBUG,
|
70 |
+
'Writing to template cache: "{fileName}"',
|
71 |
+
array('fileName' => $fileName)
|
72 |
+
);
|
73 |
+
|
74 |
+
$this->writeFile($fileName, $value);
|
75 |
+
$this->load($key);
|
76 |
+
}
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Build the cache filename.
|
80 |
+
* Subclasses should override for custom cache directory structures.
|
81 |
+
*
|
82 |
+
* @param string $name
|
83 |
+
*
|
84 |
+
* @return string
|
85 |
+
*/
|
86 |
+
protected function getCacheFilename($name)
|
87 |
+
{
|
88 |
+
return sprintf('%s/%s.php', $this->baseDir, $name);
|
89 |
+
}
|
90 |
+
|
91 |
+
/**
|
92 |
+
* Create cache directory.
|
93 |
+
*
|
94 |
+
* @throws Mustache_Exception_RuntimeException If unable to create directory
|
95 |
+
*
|
96 |
+
* @param string $fileName
|
97 |
+
*
|
98 |
+
* @return string
|
99 |
+
*/
|
100 |
+
private function buildDirectoryForFilename($fileName)
|
101 |
+
{
|
102 |
+
$dirName = dirname($fileName);
|
103 |
+
if (!is_dir($dirName)) {
|
104 |
+
$this->log(
|
105 |
+
Mustache_Logger::INFO,
|
106 |
+
'Creating Mustache template cache directory: "{dirName}"',
|
107 |
+
array('dirName' => $dirName)
|
108 |
+
);
|
109 |
+
|
110 |
+
@mkdir($dirName, 0777, true);
|
111 |
+
if (!is_dir($dirName)) {
|
112 |
+
throw new Mustache_Exception_RuntimeException(sprintf('Failed to create cache directory "%s".', $dirName));
|
113 |
+
}
|
114 |
+
}
|
115 |
+
|
116 |
+
return $dirName;
|
117 |
+
}
|
118 |
+
|
119 |
+
/**
|
120 |
+
* Write cache file.
|
121 |
+
*
|
122 |
+
* @throws Mustache_Exception_RuntimeException If unable to write file
|
123 |
+
*
|
124 |
+
* @param string $fileName
|
125 |
+
* @param string $value
|
126 |
+
*/
|
127 |
+
private function writeFile($fileName, $value)
|
128 |
+
{
|
129 |
+
$dirName = $this->buildDirectoryForFilename($fileName);
|
130 |
+
|
131 |
+
$this->log(
|
132 |
+
Mustache_Logger::DEBUG,
|
133 |
+
'Caching compiled template to "{fileName}"',
|
134 |
+
array('fileName' => $fileName)
|
135 |
+
);
|
136 |
+
|
137 |
+
$tempFile = tempnam($dirName, basename($fileName));
|
138 |
+
if (false !== @file_put_contents($tempFile, $value)) {
|
139 |
+
if (@rename($tempFile, $fileName)) {
|
140 |
+
$mode = isset($this->fileMode) ? $this->fileMode : (0666 & ~umask());
|
141 |
+
@chmod($fileName, $mode);
|
142 |
+
|
143 |
+
return;
|
144 |
+
}
|
145 |
+
|
146 |
+
$this->log(
|
147 |
+
Mustache_Logger::ERROR,
|
148 |
+
'Unable to rename Mustache temp cache file: "{tempName}" -> "{fileName}"',
|
149 |
+
array('tempName' => $tempFile, 'fileName' => $fileName)
|
150 |
+
);
|
151 |
+
}
|
152 |
+
|
153 |
+
throw new Mustache_Exception_RuntimeException(sprintf('Failed to write cache file "%s".', $fileName));
|
154 |
+
}
|
155 |
+
}
|
lib/php/Mustache/Cache/NoopCache.php
ADDED
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of Mustache.php.
|
5 |
+
*
|
6 |
+
* (c) 2010-2015 Justin Hileman
|
7 |
+
*
|
8 |
+
* For the full copyright and license information, please view the LICENSE
|
9 |
+
* file that was distributed with this source code.
|
10 |
+
*/
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Mustache Cache in-memory implementation.
|
14 |
+
*
|
15 |
+
* The in-memory cache is used for uncached lambda section templates. It's also useful during development, but is not
|
16 |
+
* recommended for production use.
|
17 |
+
*/
|
18 |
+
class Mustache_Cache_NoopCache extends Mustache_Cache_AbstractCache
|
19 |
+
{
|
20 |
+
/**
|
21 |
+
* Loads nothing. Move along.
|
22 |
+
*
|
23 |
+
* @param string $key
|
24 |
+
*
|
25 |
+
* @return bool
|
26 |
+
*/
|
27 |
+
public function load($key)
|
28 |
+
{
|
29 |
+
return false;
|
30 |
+
}
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Loads the compiled Mustache Template class without caching.
|
34 |
+
*
|
35 |
+
* @param string $key
|
36 |
+
* @param string $value
|
37 |
+
*/
|
38 |
+
public function cache($key, $value)
|
39 |
+
{
|
40 |
+
$this->log(
|
41 |
+
Mustache_Logger::WARNING,
|
42 |
+
'Template cache disabled, evaluating "{className}" class at runtime',
|
43 |
+
array('className' => $key)
|
44 |
+
);
|
45 |
+
eval('?>' . $value);
|
46 |
+
}
|
47 |
+
}
|
lib/php/Mustache/Compiler.php
ADDED
@@ -0,0 +1,684 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of Mustache.php.
|
5 |
+
*
|
6 |
+
* (c) 2010-2015 Justin Hileman
|
7 |
+
*
|
8 |
+
* For the full copyright and license information, please view the LICENSE
|
9 |
+
* file that was distributed with this source code.
|
10 |
+
*/
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Mustache Compiler class.
|
14 |
+
*
|
15 |
+
* This class is responsible for turning a Mustache token parse tree into normal PHP source code.
|
16 |
+
*/
|
17 |
+
class Mustache_Compiler
|
18 |
+
{
|
19 |
+
private $pragmas;
|
20 |
+
private $defaultPragmas = array();
|
21 |
+
private $sections;
|
22 |
+
private $blocks;
|
23 |
+
private $source;
|
24 |
+
private $indentNextLine;
|
25 |
+
private $customEscape;
|
26 |
+
private $entityFlags;
|
27 |
+
private $charset;
|
28 |
+
private $strictCallables;
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Compile a Mustache token parse tree into PHP source code.
|
32 |
+
*
|
33 |
+
* @param string $source Mustache Template source code
|
34 |
+
* @param string $tree Parse tree of Mustache tokens
|
35 |
+
* @param string $name Mustache Template class name
|
36 |
+
* @param bool $customEscape (default: false)
|
37 |
+
* @param string $charset (default: 'UTF-8')
|
38 |
+
* @param bool $strictCallables (default: false)
|
39 |
+
* @param int $entityFlags (default: ENT_COMPAT)
|
40 |
+
*
|
41 |
+
* @return string Generated PHP source code
|
42 |
+
*/
|
43 |
+
public function compile($source, array $tree, $name, $customEscape = false, $charset = 'UTF-8', $strictCallables = false, $entityFlags = ENT_COMPAT)
|
44 |
+
{
|
45 |
+
$this->pragmas = $this->defaultPragmas;
|
46 |
+
$this->sections = array();
|
47 |
+
$this->blocks = array();
|
48 |
+
$this->source = $source;
|
49 |
+
$this->indentNextLine = true;
|
50 |
+
$this->customEscape = $customEscape;
|
51 |
+
$this->entityFlags = $entityFlags;
|
52 |
+
$this->charset = $charset;
|
53 |
+
$this->strictCallables = $strictCallables;
|
54 |
+
|
55 |
+
return $this->writeCode($tree, $name);
|
56 |
+
}
|
57 |
+
|
58 |
+
/**
|
59 |
+
* Enable pragmas across all templates, regardless of the presence of pragma
|
60 |
+
* tags in the individual templates.
|
61 |
+
*
|
62 |
+
* @internal Users should set global pragmas in Mustache_Engine, not here :)
|
63 |
+
*
|
64 |
+
* @param string[] $pragmas
|
65 |
+
*/
|
66 |
+
public function setPragmas(array $pragmas)
|
67 |
+
{
|
68 |
+
$this->pragmas = array();
|
69 |
+
foreach ($pragmas as $pragma) {
|
70 |
+
$this->pragmas[$pragma] = true;
|
71 |
+
}
|
72 |
+
$this->defaultPragmas = $this->pragmas;
|
73 |
+
}
|
74 |
+
|
75 |
+
/**
|
76 |
+
* Helper function for walking the Mustache token parse tree.
|
77 |
+
*
|
78 |
+
* @throws Mustache_Exception_SyntaxException upon encountering unknown token types.
|
79 |
+
*
|
80 |
+
* @param array $tree Parse tree of Mustache tokens
|
81 |
+
* @param int $level (default: 0)
|
82 |
+
*
|
83 |
+
* @return string Generated PHP source code
|
84 |
+
*/
|
85 |
+
private function walk(array $tree, $level = 0)
|
86 |
+
{
|
87 |
+
$code = '';
|
88 |
+
$level++;
|
89 |
+
foreach ($tree as $node) {
|
90 |
+
switch ($node[Mustache_Tokenizer::TYPE]) {
|
91 |
+
case Mustache_Tokenizer::T_PRAGMA:
|
92 |
+
$this->pragmas[$node[Mustache_Tokenizer::NAME]] = true;
|
93 |
+
break;
|
94 |
+
|
95 |
+
case Mustache_Tokenizer::T_SECTION:
|
96 |
+
$code .= $this->section(
|
97 |
+
$node[Mustache_Tokenizer::NODES],
|
98 |
+
$node[Mustache_Tokenizer::NAME],
|
99 |
+
isset($node[Mustache_Tokenizer::FILTERS]) ? $node[Mustache_Tokenizer::FILTERS] : array(),
|
100 |
+
$node[Mustache_Tokenizer::INDEX],
|
101 |
+
$node[Mustache_Tokenizer::END],
|
102 |
+
$node[Mustache_Tokenizer::OTAG],
|
103 |
+
$node[Mustache_Tokenizer::CTAG],
|
104 |
+
$level
|
105 |
+
);
|
106 |
+
break;
|
107 |
+
|
108 |
+
case Mustache_Tokenizer::T_INVERTED:
|
109 |
+
$code .= $this->invertedSection(
|
110 |
+
$node[Mustache_Tokenizer::NODES],
|
111 |
+
$node[Mustache_Tokenizer::NAME],
|
112 |
+
isset($node[Mustache_Tokenizer::FILTERS]) ? $node[Mustache_Tokenizer::FILTERS] : array(),
|
113 |
+
$level
|
114 |
+
);
|
115 |
+
break;
|
116 |
+
|
117 |
+
case Mustache_Tokenizer::T_PARTIAL:
|
118 |
+
$code .= $this->partial(
|
119 |
+
$node[Mustache_Tokenizer::NAME],
|
120 |
+
isset($node[Mustache_Tokenizer::INDENT]) ? $node[Mustache_Tokenizer::INDENT] : '',
|
121 |
+
$level
|
122 |
+
);
|
123 |
+
break;
|
124 |
+
|
125 |
+
case Mustache_Tokenizer::T_PARENT:
|
126 |
+
$code .= $this->parent(
|
127 |
+
$node[Mustache_Tokenizer::NAME],
|
128 |
+
isset($node[Mustache_Tokenizer::INDENT]) ? $node[Mustache_Tokenizer::INDENT] : '',
|
129 |
+
$node[Mustache_Tokenizer::NODES],
|
130 |
+
$level
|
131 |
+
);
|
132 |
+
break;
|
133 |
+
|
134 |
+
case Mustache_Tokenizer::T_BLOCK_ARG:
|
135 |
+
$code .= $this->blockArg(
|
136 |
+
$node[Mustache_Tokenizer::NODES],
|
137 |
+
$node[Mustache_Tokenizer::NAME],
|
138 |
+
$node[Mustache_Tokenizer::INDEX],
|
139 |
+
$node[Mustache_Tokenizer::END],
|
140 |
+
$node[Mustache_Tokenizer::OTAG],
|
141 |
+
$node[Mustache_Tokenizer::CTAG],
|
142 |
+
$level
|
143 |
+
);
|
144 |
+
break;
|
145 |
+
|
146 |
+
case Mustache_Tokenizer::T_BLOCK_VAR:
|
147 |
+
$code .= $this->blockVar(
|
148 |
+
$node[Mustache_Tokenizer::NODES],
|
149 |
+
$node[Mustache_Tokenizer::NAME],
|
150 |
+
$node[Mustache_Tokenizer::INDEX],
|
151 |
+
$node[Mustache_Tokenizer::END],
|
152 |
+
$node[Mustache_Tokenizer::OTAG],
|
153 |
+
$node[Mustache_Tokenizer::CTAG],
|
154 |
+
$level
|
155 |
+
);
|
156 |
+
break;
|
157 |
+
|
158 |
+
case Mustache_Tokenizer::T_COMMENT:
|
159 |
+
break;
|
160 |
+
|
161 |
+
case Mustache_Tokenizer::T_ESCAPED:
|
162 |
+
case Mustache_Tokenizer::T_UNESCAPED:
|
163 |
+
case Mustache_Tokenizer::T_UNESCAPED_2:
|
164 |
+
$code .= $this->variable(
|
165 |
+
$node[Mustache_Tokenizer::NAME],
|
166 |
+
isset($node[Mustache_Tokenizer::FILTERS]) ? $node[Mustache_Tokenizer::FILTERS] : array(),
|
167 |
+
$node[Mustache_Tokenizer::TYPE] === Mustache_Tokenizer::T_ESCAPED,
|
168 |
+
$level
|
169 |
+
);
|
170 |
+
break;
|
171 |
+
|
172 |
+
case Mustache_Tokenizer::T_TEXT:
|
173 |
+
$code .= $this->text($node[Mustache_Tokenizer::VALUE], $level);
|
174 |
+
break;
|
175 |
+
|
176 |
+
default:
|
177 |
+
throw new Mustache_Exception_SyntaxException(sprintf('Unknown token type: %s', $node[Mustache_Tokenizer::TYPE]), $node);
|
178 |
+
}
|
179 |
+
}
|
180 |
+
|
181 |
+
return $code;
|
182 |
+
}
|
183 |
+
|
184 |
+
const KLASS = '<?php
|
185 |
+
|
186 |
+
class %s extends Mustache_Template
|
187 |
+
{
|
188 |
+
private $lambdaHelper;%s
|
189 |
+
|
190 |
+
public function renderInternal(Mustache_Context $context, $indent = \'\')
|
191 |
+
{
|
192 |
+
$this->lambdaHelper = new Mustache_LambdaHelper($this->mustache, $context);
|
193 |
+
$buffer = \'\';
|
194 |
+
$newContext = array();
|
195 |
+
%s
|
196 |
+
|
197 |
+
return $buffer;
|
198 |
+
}
|
199 |
+
%s
|
200 |
+
%s
|
201 |
+
}';
|
202 |
+
|
203 |
+
const KLASS_NO_LAMBDAS = '<?php
|
204 |
+
|
205 |
+
class %s extends Mustache_Template
|
206 |
+
{%s
|
207 |
+
public function renderInternal(Mustache_Context $context, $indent = \'\')
|
208 |
+
{
|
209 |
+
$buffer = \'\';
|
210 |
+
$newContext = array();
|
211 |
+
%s
|
212 |
+
|
213 |
+
return $buffer;
|
214 |
+
}
|
215 |
+
}';
|
216 |
+
|
217 |
+
const STRICT_CALLABLE = 'protected $strictCallables = true;';
|
218 |
+
|
219 |
+
/**
|
220 |
+
* Generate Mustache Template class PHP source.
|
221 |
+
*
|
222 |
+
* @param array $tree Parse tree of Mustache tokens
|
223 |
+
* @param string $name Mustache Template class name
|
224 |
+
*
|
225 |
+
* @return string Generated PHP source code
|
226 |
+
*/
|
227 |
+
private function writeCode($tree, $name)
|
228 |
+
{
|
229 |
+
$code = $this->walk($tree);
|
230 |
+
$sections = implode("\n", $this->sections);
|
231 |
+
$blocks = implode("\n", $this->blocks);
|
232 |
+
$klass = empty($this->sections) && empty($this->blocks) ? self::KLASS_NO_LAMBDAS : self::KLASS;
|
233 |
+
|
234 |
+
$callable = $this->strictCallables ? $this->prepare(self::STRICT_CALLABLE) : '';
|
235 |
+
|
236 |
+
return sprintf($this->prepare($klass, 0, false, true), $name, $callable, $code, $sections, $blocks);
|
237 |
+
}
|
238 |
+
|
239 |
+
const BLOCK_VAR = '
|
240 |
+
$blockFunction = $context->findInBlock(%s);
|
241 |
+
if (is_callable($blockFunction)) {
|
242 |
+
$buffer .= call_user_func($blockFunction, $context);
|
243 |
+
} else {%s
|
244 |
+
}
|
245 |
+
';
|
246 |
+
|
247 |
+
/**
|
248 |
+
* Generate Mustache Template inheritance block variable PHP source.
|
249 |
+
*
|
250 |
+
* @param array $nodes Array of child tokens
|
251 |
+
* @param string $id Section name
|
252 |
+
* @param int $start Section start offset
|
253 |
+
* @param int $end Section end offset
|
254 |
+
* @param string $otag Current Mustache opening tag
|
255 |
+
* @param string $ctag Current Mustache closing tag
|
256 |
+
* @param int $level
|
257 |
+
*
|
258 |
+
* @return string Generated PHP source code
|
259 |
+
*/
|
260 |
+
private function blockVar($nodes, $id, $start, $end, $otag, $ctag, $level)
|
261 |
+
{
|
262 |
+
$id = var_export($id, true);
|
263 |
+
|
264 |
+
return sprintf($this->prepare(self::BLOCK_VAR, $level), $id, $this->walk($nodes, $level));
|
265 |
+
}
|
266 |
+
|
267 |
+
const BLOCK_ARG = '$newContext[%s] = array($this, \'block%s\');';
|
268 |
+
|
269 |
+
/**
|
270 |
+
* Generate Mustache Template inheritance block argument PHP source.
|
271 |
+
*
|
272 |
+
* @param array $nodes Array of child tokens
|
273 |
+
* @param string $id Section name
|
274 |
+
* @param int $start Section start offset
|
275 |
+
* @param int $end Section end offset
|
276 |
+
* @param string $otag Current Mustache opening tag
|
277 |
+
* @param string $ctag Current Mustache closing tag
|
278 |
+
* @param int $level
|
279 |
+
*
|
280 |
+
* @return string Generated PHP source code
|
281 |
+
*/
|
282 |
+
private function blockArg($nodes, $id, $start, $end, $otag, $ctag, $level)
|
283 |
+
{
|
284 |
+
$key = $this->block($nodes);
|
285 |
+
$keystr = var_export($key, true);
|
286 |
+
$id = var_export($id, true);
|
287 |
+
|
288 |
+
return sprintf($this->prepare(self::BLOCK_ARG, 1), $id, $key);
|
289 |
+
}
|
290 |
+
|
291 |
+
const BLOCK_FUNCTION = '
|
292 |
+
public function block%s($context)
|
293 |
+
{
|
294 |
+
$indent = $buffer = \'\';%s
|
295 |
+
|
296 |
+
return $buffer;
|
297 |
+
}
|
298 |
+
';
|
299 |
+
|
300 |
+
/**
|
301 |
+
* Generate Mustache Template inheritance block function PHP source.
|
302 |
+
*
|
303 |
+
* @param array $nodes Array of child tokens
|
304 |
+
*
|
305 |
+
* @return string key of new block function
|
306 |
+
*/
|
307 |
+
private function block($nodes)
|
308 |
+
{
|
309 |
+
$code = $this->walk($nodes, 0);
|
310 |
+
$key = ucfirst(md5($code));
|
311 |
+
|
312 |
+
if (!isset($this->blocks[$key])) {
|
313 |
+
$this->blocks[$key] = sprintf($this->prepare(self::BLOCK_FUNCTION, 0), $key, $code);
|
314 |
+
}
|
315 |
+
|
316 |
+
return $key;
|
317 |
+
}
|
318 |
+
|
319 |
+
const SECTION_CALL = '
|
320 |
+
// %s section
|
321 |
+
$value = $context->%s(%s);%s
|
322 |
+
$buffer .= $this->section%s($context, $indent, $value);
|
323 |
+
';
|
324 |
+
|
325 |
+
const SECTION = '
|
326 |
+
private function section%s(Mustache_Context $context, $indent, $value)
|
327 |
+
{
|
328 |
+
$buffer = \'\';
|
329 |
+
if (%s) {
|
330 |
+
$source = %s;
|
331 |
+
$result = call_user_func($value, $source, %s);
|
332 |
+
if (strpos($result, \'{{\') === false) {
|
333 |
+
$buffer .= $result;
|
334 |
+
} else {
|
335 |
+
$buffer .= $this->mustache
|
336 |
+
->loadLambda((string) $result%s)
|
337 |
+
->renderInternal($context);
|
338 |
+
}
|
339 |
+
} elseif (!empty($value)) {
|
340 |
+
$values = $this->isIterable($value) ? $value : array($value);
|
341 |
+
foreach ($values as $value) {
|
342 |
+
$context->push($value);
|
343 |
+
%s
|
344 |
+
$context->pop();
|
345 |
+
}
|
346 |
+
}
|
347 |
+
|
348 |
+
return $buffer;
|
349 |
+
}
|
350 |
+
';
|
351 |
+
|
352 |
+
/**
|
353 |
+
* Generate Mustache Template section PHP source.
|
354 |
+
*
|
355 |
+
* @param array $nodes Array of child tokens
|
356 |
+
* @param string $id Section name
|
357 |
+
* @param string[] $filters Array of filters
|
358 |
+
* @param int $start Section start offset
|
359 |
+
* @param int $end Section end offset
|
360 |
+
* @param string $otag Current Mustache opening tag
|
361 |
+
* @param string $ctag Current Mustache closing tag
|
362 |
+
* @param int $level
|
363 |
+
* @param bool $arg (default: false)
|
364 |
+
*
|
365 |
+
* @return string Generated section PHP source code
|
366 |
+
*/
|
367 |
+
private function section($nodes, $id, $filters, $start, $end, $otag, $ctag, $level, $arg = false)
|
368 |
+
{
|
369 |
+
$source = var_export(substr($this->source, $start, $end - $start), true);
|
370 |
+
$callable = $this->getCallable();
|
371 |
+
|
372 |
+
if ($otag !== '{{' || $ctag !== '}}') {
|
373 |
+
$delimTag = var_export(sprintf('{{= %s %s =}}', $otag, $ctag), true);
|
374 |
+
$helper = sprintf('$this->lambdaHelper->withDelimiters(%s)', $delimTag);
|
375 |
+
$delims = ', ' . $delimTag;
|
376 |
+
} else {
|
377 |
+
$helper = '$this->lambdaHelper';
|
378 |
+
$delims = '';
|
379 |
+
}
|
380 |
+
|
381 |
+
$key = ucfirst(md5($delims . "\n" . $source));
|
382 |
+
|
383 |
+
if (!isset($this->sections[$key])) {
|
384 |
+
$this->sections[$key] = sprintf($this->prepare(self::SECTION), $key, $callable, $source, $helper, $delims, $this->walk($nodes, 2));
|
385 |
+
}
|
386 |
+
|
387 |
+
if ($arg === true) {
|
388 |
+
return $key;
|
389 |
+
} else {
|
390 |
+
$method = $this->getFindMethod($id);
|
391 |
+
$id = var_export($id, true);
|
392 |
+
$filters = $this->getFilters($filters, $level);
|
393 |
+
|
394 |
+
return sprintf($this->prepare(self::SECTION_CALL, $level), $id, $method, $id, $filters, $key);
|
395 |
+
}
|
396 |
+
}
|
397 |
+
|
398 |
+
const INVERTED_SECTION = '
|
399 |
+
// %s inverted section
|
400 |
+
$value = $context->%s(%s);%s
|
401 |
+
if (empty($value)) {
|
402 |
+
%s
|
403 |
+
}
|
404 |
+
';
|
405 |
+
|
406 |
+
/**
|
407 |
+
* Generate Mustache Template inverted section PHP source.
|
408 |
+
*
|
409 |
+
* @param array $nodes Array of child tokens
|
410 |
+
* @param string $id Section name
|
411 |
+
* @param string[] $filters Array of filters
|
412 |
+
* @param int $level
|
413 |
+
*
|
414 |
+
* @return string Generated inverted section PHP source code
|
415 |
+
*/
|
416 |
+
private function invertedSection($nodes, $id, $filters, $level)
|
417 |
+
{
|
418 |
+
$method = $this->getFindMethod($id);
|
419 |
+
$id = var_export($id, true);
|
420 |
+
$filters = $this->getFilters($filters, $level);
|
421 |
+
|
422 |
+
return sprintf($this->prepare(self::INVERTED_SECTION, $level), $id, $method, $id, $filters, $this->walk($nodes, $level));
|
423 |
+
}
|
424 |
+
|
425 |
+
const PARTIAL_INDENT = ', $indent . %s';
|
426 |
+
const PARTIAL = '
|
427 |
+
if ($partial = $this->mustache->loadPartial(%s)) {
|
428 |
+
$buffer .= $partial->renderInternal($context%s);
|
429 |
+
}
|
430 |
+
';
|
431 |
+
|
432 |
+
/**
|
433 |
+
* Generate Mustache Template partial call PHP source.
|
434 |
+
*
|
435 |
+
* @param string $id Partial name
|
436 |
+
* @param string $indent Whitespace indent to apply to partial
|
437 |
+
* @param int $level
|
438 |
+
*
|
439 |
+
* @return string Generated partial call PHP source code
|
440 |
+
*/
|
441 |
+
private function partial($id, $indent, $level)
|
442 |
+
{
|
443 |
+
if ($indent !== '') {
|
444 |
+
$indentParam = sprintf(self::PARTIAL_INDENT, var_export($indent, true));
|
445 |
+
} else {
|
446 |
+
$indentParam = '';
|
447 |
+
}
|
448 |
+
|
449 |
+
return sprintf(
|
450 |
+
$this->prepare(self::PARTIAL, $level),
|
451 |
+
var_export($id, true),
|
452 |
+
$indentParam
|
453 |
+
);
|
454 |
+
}
|
455 |
+
|
456 |
+
const PARENT = '
|
457 |
+
%s
|
458 |
+
|
459 |
+
if ($parent = $this->mustache->LoadPartial(%s)) {
|
460 |
+
$context->pushBlockContext($newContext);
|
461 |
+
$buffer .= $parent->renderInternal($context, $indent);
|
462 |
+
$context->popBlockContext();
|
463 |
+
}
|
464 |
+
';
|
465 |
+
|
466 |
+
/**
|
467 |
+
* Generate Mustache Template inheritance parent call PHP source.
|
468 |
+
*
|
469 |
+
* @param string $id Parent tag name
|
470 |
+
* @param string $indent Whitespace indent to apply to parent
|
471 |
+
* @param array $children Child nodes
|
472 |
+
* @param int $level
|
473 |
+
*
|
474 |
+
* @return string Generated PHP source code
|
475 |
+
*/
|
476 |
+
private function parent($id, $indent, array $children, $level)
|
477 |
+
{
|
478 |
+
$realChildren = array_filter($children, array(__CLASS__, 'onlyBlockArgs'));
|
479 |
+
|
480 |
+
return sprintf(
|
481 |
+
$this->prepare(self::PARENT, $level),
|
482 |
+
$this->walk($realChildren, $level),
|
483 |
+
var_export($id, true),
|
484 |
+
var_export($indent, true)
|
485 |
+
);
|
486 |
+
}
|
487 |
+
|
488 |
+
/**
|
489 |
+
* Helper method for filtering out non-block-arg tokens.
|
490 |
+
*
|
491 |
+
* @param array $node
|
492 |
+
*
|
493 |
+
* @return bool True if $node is a block arg token.
|
494 |
+
*/
|
495 |
+
private static function onlyBlockArgs(array $node)
|
496 |
+
{
|
497 |
+
return $node[Mustache_Tokenizer::TYPE] === Mustache_Tokenizer::T_BLOCK_ARG;
|
498 |
+
}
|
499 |
+
|
500 |
+
const VARIABLE = '
|
501 |
+
$value = $this->resolveValue($context->%s(%s), $context);%s
|
502 |
+
$buffer .= %s%s;
|
503 |
+
';
|
504 |
+
|
505 |
+
/**
|
506 |
+
* Generate Mustache Template variable interpolation PHP source.
|
507 |
+
*
|
508 |
+
* @param string $id Variable name
|
509 |
+
* @param string[] $filters Array of filters
|
510 |
+
* @param bool $escape Escape the variable value for output?
|
511 |
+
* @param int $level
|
512 |
+
*
|
513 |
+
* @return string Generated variable interpolation PHP source
|
514 |
+
*/
|
515 |
+
private function variable($id, $filters, $escape, $level)
|
516 |
+
{
|
517 |
+
$method = $this->getFindMethod($id);
|
518 |
+
$id = ($method !== 'last') ? var_export($id, true) : '';
|
519 |
+
$filters = $this->getFilters($filters, $level);
|
520 |
+
$value = $escape ? $this->getEscape() : '$value';
|
521 |
+
|
522 |
+
return sprintf($this->prepare(self::VARIABLE, $level), $method, $id, $filters, $this->flushIndent(), $value);
|
523 |
+
}
|
524 |
+
|
525 |
+
const FILTER = '
|
526 |
+
$filter = $context->%s(%s);
|
527 |
+
if (!(%s)) {
|
528 |
+
throw new Mustache_Exception_UnknownFilterException(%s);
|
529 |
+
}
|
530 |
+
$value = call_user_func($filter, $value);%s
|
531 |
+
';
|
532 |
+
|
533 |
+
/**
|
534 |
+
* Generate Mustache Template variable filtering PHP source.
|
535 |
+
*
|
536 |
+
* @param string[] $filters Array of filters
|
537 |
+
* @param int $level
|
538 |
+
*
|
539 |
+
* @return string Generated filter PHP source
|
540 |
+
*/
|
541 |
+
private function getFilters(array $filters, $level)
|
542 |
+
{
|
543 |
+
if (empty($filters)) {
|
544 |
+
return '';
|
545 |
+
}
|
546 |
+
|
547 |
+
$name = array_shift($filters);
|
548 |
+
$method = $this->getFindMethod($name);
|
549 |
+
$filter = ($method !== 'last') ? var_export($name, true) : '';
|
550 |
+
$callable = $this->getCallable('$filter');
|
551 |
+
$msg = var_export($name, true);
|
552 |
+
|
553 |
+
return sprintf($this->prepare(self::FILTER, $level), $method, $filter, $callable, $msg, $this->getFilters($filters, $level));
|
554 |
+
}
|
555 |
+
|
556 |
+
const LINE = '$buffer .= "\n";';
|
557 |
+
const TEXT = '$buffer .= %s%s;';
|
558 |
+
|
559 |
+
/**
|
560 |
+
* Generate Mustache Template output Buffer call PHP source.
|
561 |
+
*
|
562 |
+
* @param string $text
|
563 |
+
* @param int $level
|
564 |
+
*
|
565 |
+
* @return string Generated output Buffer call PHP source
|
566 |
+
*/
|
567 |
+
private function text($text, $level)
|
568 |
+
{
|
569 |
+
$indentNextLine = (substr($text, -1) === "\n");
|
570 |
+
$code = sprintf($this->prepare(self::TEXT, $level), $this->flushIndent(), var_export($text, true));
|
571 |
+
$this->indentNextLine = $indentNextLine;
|
572 |
+
|
573 |
+
return $code;
|
574 |
+
}
|
575 |
+
|
576 |
+
/**
|
577 |
+
* Prepare PHP source code snippet for output.
|
578 |
+
*
|
579 |
+
* @param string $text
|
580 |
+
* @param int $bonus Additional indent level (default: 0)
|
581 |
+
* @param bool $prependNewline Prepend a newline to the snippet? (default: true)
|
582 |
+
* @param bool $appendNewline Append a newline to the snippet? (default: false)
|
583 |
+
*
|
584 |
+
* @return string PHP source code snippet
|
585 |
+
*/
|
586 |
+
private function prepare($text, $bonus = 0, $prependNewline = true, $appendNewline = false)
|
587 |
+
{
|
588 |
+
$text = ($prependNewline ? "\n" : '') . trim($text);
|
589 |
+
if ($prependNewline) {
|
590 |
+
$bonus++;
|
591 |
+
}
|
592 |
+
if ($appendNewline) {
|
593 |
+
$text .= "\n";
|
594 |
+
}
|
595 |
+
|
596 |
+
return preg_replace("/\n( {8})?/", "\n" . str_repeat(' ', $bonus * 4), $text);
|
597 |
+
}
|
598 |
+
|
599 |
+
const DEFAULT_ESCAPE = 'htmlspecialchars(%s, %s, %s)';
|
600 |
+
const CUSTOM_ESCAPE = 'call_user_func($this->mustache->getEscape(), %s)';
|
601 |
+
|
602 |
+
/**
|
603 |
+
* Get the current escaper.
|
604 |
+
*
|
605 |
+
* @param string $value (default: '$value')
|
606 |
+
*
|
607 |
+
* @return string Either a custom callback, or an inline call to `htmlspecialchars`
|
608 |
+
*/
|
609 |
+
private function getEscape($value = '$value')
|
610 |
+
{
|
611 |
+
if ($this->customEscape) {
|
612 |
+
return sprintf(self::CUSTOM_ESCAPE, $value);
|
613 |
+
}
|
614 |
+
|
615 |
+
return sprintf(self::DEFAULT_ESCAPE, $value, var_export($this->entityFlags, true), var_export($this->charset, true));
|
616 |
+
}
|
617 |
+
|
618 |
+
/**
|
619 |
+
* Select the appropriate Context `find` method for a given $id.
|
620 |
+
*
|
621 |
+
* The return value will be one of `find`, `findDot` or `last`.
|
622 |
+
*
|
623 |
+
* @see Mustache_Context::find
|
624 |
+
* @see Mustache_Context::findDot
|
625 |
+
* @see Mustache_Context::last
|
626 |
+
*
|
627 |
+
* @param string $id Variable name
|
628 |
+
*
|
629 |
+
* @return string `find` method name
|
630 |
+
*/
|
631 |
+
private function getFindMethod($id)
|
632 |
+
{
|
633 |
+
if ($id === '.') {
|
634 |
+
return 'last';
|
635 |
+
}
|
636 |
+
|
637 |
+
if (isset($this->pragmas[Mustache_Engine::PRAGMA_ANCHORED_DOT]) && $this->pragmas[Mustache_Engine::PRAGMA_ANCHORED_DOT]) {
|
638 |
+
if (substr($id, 0, 1) === '.') {
|
639 |
+
return 'findAnchoredDot';
|
640 |
+
}
|
641 |
+
}
|
642 |
+
|
643 |
+
if (strpos($id, '.') === false) {
|
644 |
+
return 'find';
|
645 |
+
}
|
646 |
+
|
647 |
+
return 'findDot';
|
648 |
+
}
|
649 |
+
|
650 |
+
const IS_CALLABLE = '!is_string(%s) && is_callable(%s)';
|
651 |
+
const STRICT_IS_CALLABLE = 'is_object(%s) && is_callable(%s)';
|
652 |
+
|
653 |
+
/**
|
654 |
+
* Helper function to compile strict vs lax "is callable" logic.
|
655 |
+
*
|
656 |
+
* @param string $variable (default: '$value')
|
657 |
+
*
|
658 |
+
* @return string "is callable" logic
|
659 |
+
*/
|
660 |
+
private function getCallable($variable = '$value')
|
661 |
+
{
|
662 |
+
$tpl = $this->strictCallables ? self::STRICT_IS_CALLABLE : self::IS_CALLABLE;
|
663 |
+
|
664 |
+
return sprintf($tpl, $variable, $variable);
|
665 |
+
}
|
666 |
+
|
667 |
+
const LINE_INDENT = '$indent . ';
|
668 |
+
|
669 |
+
/**
|
670 |
+
* Get the current $indent prefix to write to the buffer.
|
671 |
+
*
|
672 |
+
* @return string "$indent . " or ""
|
673 |
+
*/
|
674 |
+
private function flushIndent()
|
675 |
+
{
|
676 |
+
if (!$this->indentNextLine) {
|
677 |
+
return '';
|
678 |
+
}
|
679 |
+
|
680 |
+
$this->indentNextLine = false;
|
681 |
+
|
682 |
+
return self::LINE_INDENT;
|
683 |
+
}
|
684 |
+
}
|
lib/php/Mustache/Context.php
ADDED
@@ -0,0 +1,242 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of Mustache.php.
|
5 |
+
*
|
6 |
+
* (c) 2010-2015 Justin Hileman
|
7 |
+
*
|
8 |
+
* For the full copyright and license information, please view the LICENSE
|
9 |
+
* file that was distributed with this source code.
|
10 |
+
*/
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Mustache Template rendering Context.
|
14 |
+
*/
|
15 |
+
class Mustache_Context
|
16 |
+
{
|
17 |
+
private $stack = array();
|
18 |
+
private $blockStack = array();
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Mustache rendering Context constructor.
|
22 |
+
*
|
23 |
+
* @param mixed $context Default rendering context (default: null)
|
24 |
+
*/
|
25 |
+
public function __construct($context = null)
|
26 |
+
{
|
27 |
+
if ($context !== null) {
|
28 |
+
$this->stack = array($context);
|
29 |
+
}
|
30 |
+
}
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Push a new Context frame onto the stack.
|
34 |
+
*
|
35 |
+
* @param mixed $value Object or array to use for context
|
36 |
+
*/
|
37 |
+
public function push($value)
|
38 |
+
{
|
39 |
+
array_push($this->stack, $value);
|
40 |
+
}
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Push a new Context frame onto the block context stack.
|
44 |
+
*
|
45 |
+
* @param mixed $value Object or array to use for block context
|
46 |
+
*/
|
47 |
+
public function pushBlockContext($value)
|
48 |
+
{
|
49 |
+
array_push($this->blockStack, $value);
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Pop the last Context frame from the stack.
|
54 |
+
*
|
55 |
+
* @return mixed Last Context frame (object or array)
|
56 |
+
*/
|
57 |
+
public function pop()
|
58 |
+
{
|
59 |
+
return array_pop($this->stack);
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Pop the last block Context frame from the stack.
|
64 |
+
*
|
65 |
+
* @return mixed Last block Context frame (object or array)
|
66 |
+
*/
|
67 |
+
public function popBlockContext()
|
68 |
+
{
|
69 |
+
return array_pop($this->blockStack);
|
70 |
+
}
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Get the last Context frame.
|
74 |
+
*
|
75 |
+
* @return mixed Last Context frame (object or array)
|
76 |
+
*/
|
77 |
+
public function last()
|
78 |
+
{
|
79 |
+
return end($this->stack);
|
80 |
+
}
|
81 |
+
|
82 |
+
/**
|
83 |
+
* Find a variable in the Context stack.
|
84 |
+
*
|
85 |
+
* Starting with the last Context frame (the context of the innermost section), and working back to the top-level
|
86 |
+
* rendering context, look for a variable with the given name:
|
87 |
+
*
|
88 |
+
* * If the Context frame is an associative array which contains the key $id, returns the value of that element.
|
89 |
+
* * If the Context frame is an object, this will check first for a public method, then a public property named
|
90 |
+
* $id. Failing both of these, it will try `__isset` and `__get` magic methods.
|
91 |
+
* * If a value named $id is not found in any Context frame, returns an empty string.
|
92 |
+
*
|
93 |
+
* @param string $id Variable name
|
94 |
+
*
|
95 |
+
* @return mixed Variable value, or '' if not found
|
96 |
+
*/
|
97 |
+
public function find($id)
|
98 |
+
{
|
99 |
+
return $this->findVariableInStack($id, $this->stack);
|
100 |
+
}
|
101 |
+
|
102 |
+
/**
|
103 |
+
* Find a 'dot notation' variable in the Context stack.
|
104 |
+
*
|
105 |
+
* Note that dot notation traversal bubbles through scope differently than the regular find method. After finding
|
106 |
+
* the initial chunk of the dotted name, each subsequent chunk is searched for only within the value of the previous
|
107 |
+
* result. For example, given the following context stack:
|
108 |
+
*
|
109 |
+
* $data = array(
|
110 |
+
* 'name' => 'Fred',
|
111 |
+
* 'child' => array(
|
112 |
+
* 'name' => 'Bob'
|
113 |
+
* ),
|
114 |
+
* );
|
115 |
+
*
|
116 |
+
* ... and the Mustache following template:
|
117 |
+
*
|
118 |
+
* {{ child.name }}
|
119 |
+
*
|
120 |
+
* ... the `name` value is only searched for within the `child` value of the global Context, not within parent
|
121 |
+
* Context frames.
|
122 |
+
*
|
123 |
+
* @param string $id Dotted variable selector
|
124 |
+
*
|
125 |
+
* @return mixed Variable value, or '' if not found
|
126 |
+
*/
|
127 |
+
public function findDot($id)
|
128 |
+
{
|
129 |
+
$chunks = explode('.', $id);
|
130 |
+
$first = array_shift($chunks);
|
131 |
+
$value = $this->findVariableInStack($first, $this->stack);
|
132 |
+
|
133 |
+
foreach ($chunks as $chunk) {
|
134 |
+
if ($value === '') {
|
135 |
+
return $value;
|
136 |
+
}
|
137 |
+
|
138 |
+
$value = $this->findVariableInStack($chunk, array($value));
|
139 |
+
}
|
140 |
+
|
141 |
+
return $value;
|
142 |
+
}
|
143 |
+
|
144 |
+
/**
|
145 |
+
* Find an 'anchored dot notation' variable in the Context stack.
|
146 |
+
*
|
147 |
+
* This is the same as findDot(), except it looks in the top of the context
|
148 |
+
* stack for the first value, rather than searching the whole context stack
|
149 |
+
* and starting from there.
|
150 |
+
*
|
151 |
+
* @see Mustache_Context::findDot
|
152 |
+
*
|
153 |
+
* @throws Mustache_Exception_InvalidArgumentException if given an invalid anchored dot $id.
|
154 |
+
*
|
155 |
+
* @param string $id Dotted variable selector
|
156 |
+
*
|
157 |
+
* @return mixed Variable value, or '' if not found
|
158 |
+
*/
|
159 |
+
public function findAnchoredDot($id)
|
160 |
+
{
|
161 |
+
$chunks = explode('.', $id);
|
162 |
+
$first = array_shift($chunks);
|
163 |
+
if ($first !== '') {
|
164 |
+
throw new Mustache_Exception_InvalidArgumentException(sprintf('Unexpected id for findAnchoredDot: %s', $id));
|
165 |
+
}
|
166 |
+
|
167 |
+
$value = $this->last();
|
168 |
+
|
169 |
+
foreach ($chunks as $chunk) {
|
170 |
+
if ($value === '') {
|
171 |
+
return $value;
|
172 |
+
}
|
173 |
+
|
174 |
+
$value = $this->findVariableInStack($chunk, array($value));
|
175 |
+
}
|
176 |
+
|
177 |
+
return $value;
|
178 |
+
}
|
179 |
+
|
180 |
+
/**
|
181 |
+
* Find an argument in the block context stack.
|
182 |
+
*
|
183 |
+
* @param string $id
|
184 |
+
*
|
185 |
+
* @return mixed Variable value, or '' if not found.
|
186 |
+
*/
|
187 |
+
public function findInBlock($id)
|
188 |
+
{
|
189 |
+
foreach ($this->blockStack as $context) {
|
190 |
+
if (array_key_exists($id, $context)) {
|
191 |
+
return $context[$id];
|
192 |
+
}
|
193 |
+
}
|
194 |
+
|
195 |
+
return '';
|
196 |
+
}
|
197 |
+
|
198 |
+
/**
|
199 |
+
* Helper function to find a variable in the Context stack.
|
200 |
+
*
|
201 |
+
* @see Mustache_Context::find
|
202 |
+
*
|
203 |
+
* @param string $id Variable name
|
204 |
+
* @param array $stack Context stack
|
205 |
+
*
|
206 |
+
* @return mixed Variable value, or '' if not found
|
207 |
+
*/
|
208 |
+
private function findVariableInStack($id, array $stack)
|
209 |
+
{
|
210 |
+
for ($i = count($stack) - 1; $i >= 0; $i--) {
|
211 |
+
$frame = &$stack[$i];
|
212 |
+
|
213 |
+
switch (gettype($frame)) {
|
214 |
+
case 'object':
|
215 |
+
if (!($frame instanceof Closure)) {
|
216 |
+
// Note that is_callable() *will not work here*
|
217 |
+
// See https://github.com/bobthecow/mustache.php/wiki/Magic-Methods
|
218 |
+
if (method_exists($frame, $id)) {
|
219 |
+
return $frame->$id();
|
220 |
+
}
|
221 |
+
|
222 |
+
if (isset($frame->$id)) {
|
223 |
+
return $frame->$id;
|
224 |
+
}
|
225 |
+
|
226 |
+
if ($frame instanceof ArrayAccess && isset($frame[$id])) {
|
227 |
+
return $frame[$id];
|
228 |
+
}
|
229 |
+
}
|
230 |
+
break;
|
231 |
+
|
232 |
+
case 'array':
|
233 |
+
if (array_key_exists($id, $frame)) {
|
234 |
+
return $frame[$id];
|
235 |
+
}
|
236 |
+
break;
|
237 |
+
}
|
238 |
+
}
|
239 |
+
|
240 |
+
return '';
|
241 |
+
}
|
242 |
+
}
|
lib/php/Mustache/Engine.php
ADDED
@@ -0,0 +1,787 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of Mustache.php.
|
5 |
+
*
|
6 |
+
* (c) 2010-2015 Justin Hileman
|
7 |
+
*
|
8 |
+
* For the full copyright and license information, please view the LICENSE
|
9 |
+
* file that was distributed with this source code.
|
10 |
+
*/
|
11 |
+
|
12 |
+
/**
|
13 |
+
* A Mustache implementation in PHP.
|
14 |
+
*
|
15 |
+
* {@link http://defunkt.github.com/mustache}
|
16 |
+
*
|
17 |
+
* Mustache is a framework-agnostic logic-less templating language. It enforces separation of view
|
18 |
+
* logic from template files. In fact, it is not even possible to embed logic in the template.
|
19 |
+
*
|
20 |
+
* This is very, very rad.
|
21 |
+
*
|
22 |
+
* @author Justin Hileman {@link http://justinhileman.com}
|
23 |
+
*/
|
24 |
+
class Mustache_Engine
|
25 |
+
{
|
26 |
+
const VERSION = '2.10.0';
|
27 |
+
const SPEC_VERSION = '1.1.2';
|
28 |
+
|
29 |
+
const PRAGMA_FILTERS = 'FILTERS';
|
30 |
+
const PRAGMA_BLOCKS = 'BLOCKS';
|
31 |
+
const PRAGMA_ANCHORED_DOT = 'ANCHORED-DOT';
|
32 |
+
|
33 |
+
// Known pragmas
|
34 |
+
private static $knownPragmas = array(
|
35 |
+
self::PRAGMA_FILTERS => true,
|
36 |
+
self::PRAGMA_BLOCKS => true,
|
37 |
+
self::PRAGMA_ANCHORED_DOT => true,
|
38 |
+
);
|
39 |
+
|
40 |
+
// Template cache
|
41 |
+
private $templates = array();
|
42 |
+
|
43 |
+
// Environment
|
44 |
+
private $templateClassPrefix = '__Mustache_';
|
45 |
+
private $cache;
|
46 |
+
private $lambdaCache;
|
47 |
+
private $cacheLambdaTemplates = false;
|
48 |
+
private $loader;
|
49 |
+
private $partialsLoader;
|
50 |
+
private $helpers;
|
51 |
+
private $escape;
|
52 |
+
private $entityFlags = ENT_COMPAT;
|
53 |
+
private $charset = 'UTF-8';
|
54 |
+
private $logger;
|
55 |
+
private $strictCallables = false;
|
56 |
+
private $pragmas = array();
|
57 |
+
|
58 |
+
// Services
|
59 |
+
private $tokenizer;
|
60 |
+
private $parser;
|
61 |
+
private $compiler;
|
62 |
+
|
63 |
+
/**
|
64 |
+
* Mustache class constructor.
|
65 |
+
*
|
66 |
+
* Passing an $options array allows overriding certain Mustache options during instantiation:
|
67 |
+
*
|
68 |
+
* $options = array(
|
69 |
+
* // The class prefix for compiled templates. Defaults to '__Mustache_'.
|
70 |
+
* 'template_class_prefix' => '__MyTemplates_',
|
71 |
+
*
|
72 |
+
* // A Mustache cache instance or a cache directory string for compiled templates.
|
73 |
+
* // Mustache will not cache templates unless this is set.
|
74 |
+
* 'cache' => dirname(__FILE__).'/tmp/cache/mustache',
|
75 |
+
*
|
76 |
+
* // Override default permissions for cache files. Defaults to using the system-defined umask. It is
|
77 |
+
* // *strongly* recommended that you configure your umask properly rather than overriding permissions here.
|
78 |
+
* 'cache_file_mode' => 0666,
|
79 |
+
*
|
80 |
+
* // Optionally, enable caching for lambda section templates. This is generally not recommended, as lambda
|
81 |
+
* // sections are often too dynamic to benefit from caching.
|
82 |
+
* 'cache_lambda_templates' => true,
|
83 |
+
*
|
84 |
+
* // A Mustache template loader instance. Uses a StringLoader if not specified.
|
85 |
+
* 'loader' => new Mustache_Loader_FilesystemLoader(dirname(__FILE__).'/views'),
|
86 |
+
*
|
87 |
+
* // A Mustache loader instance for partials.
|
88 |
+
* 'partials_loader' => new Mustache_Loader_FilesystemLoader(dirname(__FILE__).'/views/partials'),
|
89 |
+
*
|
90 |
+
* // An array of Mustache partials. Useful for quick-and-dirty string template loading, but not as
|
91 |
+
* // efficient or lazy as a Filesystem (or database) loader.
|
92 |
+
* 'partials' => array('foo' => file_get_contents(dirname(__FILE__).'/views/partials/foo.mustache')),
|
93 |
+
*
|
94 |
+
* // An array of 'helpers'. Helpers can be global variables or objects, closures (e.g. for higher order
|
95 |
+
* // sections), or any other valid Mustache context value. They will be prepended to the context stack,
|
96 |
+
* // so they will be available in any template loaded by this Mustache instance.
|
97 |
+
* 'helpers' => array('i18n' => function ($text) {
|
98 |
+
* // do something translatey here...
|
99 |
+
* }),
|
100 |
+
*
|
101 |
+
* // An 'escape' callback, responsible for escaping double-mustache variables.
|
102 |
+
* 'escape' => function ($value) {
|
103 |
+
* return htmlspecialchars($buffer, ENT_COMPAT, 'UTF-8');
|
104 |
+
* },
|
105 |
+
*
|
106 |
+
* // Type argument for `htmlspecialchars`. Defaults to ENT_COMPAT. You may prefer ENT_QUOTES.
|
107 |
+
* 'entity_flags' => ENT_QUOTES,
|
108 |
+
*
|
109 |
+
* // Character set for `htmlspecialchars`. Defaults to 'UTF-8'. Use 'UTF-8'.
|
110 |
+
* 'charset' => 'ISO-8859-1',
|
111 |
+
*
|
112 |
+
* // A Mustache Logger instance. No logging will occur unless this is set. Using a PSR-3 compatible
|
113 |
+
* // logging library -- such as Monolog -- is highly recommended. A simple stream logger implementation is
|
114 |
+
* // available as well:
|
115 |
+
* 'logger' => new Mustache_Logger_StreamLogger('php://stderr'),
|
116 |
+
*
|
117 |
+
* // Only treat Closure instances and invokable classes as callable. If true, values like
|
118 |
+
* // `array('ClassName', 'methodName')` and `array($classInstance, 'methodName')`, which are traditionally
|
119 |
+
* // "callable" in PHP, are not called to resolve variables for interpolation or section contexts. This
|
120 |
+
* // helps protect against arbitrary code execution when user input is passed directly into the template.
|
121 |
+
* // This currently defaults to false, but will default to true in v3.0.
|
122 |
+
* 'strict_callables' => true,
|
123 |
+
*
|
124 |
+
* // Enable pragmas across all templates, regardless of the presence of pragma tags in the individual
|
125 |
+
* // templates.
|
126 |
+
* 'pragmas' => [Mustache_Engine::PRAGMA_FILTERS],
|
127 |
+
* );
|
128 |
+
*
|
129 |
+
* @throws Mustache_Exception_InvalidArgumentException If `escape` option is not callable.
|
130 |
+
*
|
131 |
+
* @param array $options (default: array())
|
132 |
+
*/
|
133 |
+
public function __construct(array $options = array())
|
134 |
+
{
|
135 |
+
if (isset($options['template_class_prefix'])) {
|
136 |
+
$this->templateClassPrefix = $options['template_class_prefix'];
|
137 |
+
}
|
138 |
+
|
139 |
+
if (isset($options['cache'])) {
|
140 |
+
$cache = $options['cache'];
|
141 |
+
|
142 |
+
if (is_string($cache)) {
|
143 |
+
$mode = isset($options['cache_file_mode']) ? $options['cache_file_mode'] : null;
|
144 |
+
$cache = new Mustache_Cache_FilesystemCache($cache, $mode);
|
145 |
+
}
|
146 |
+
|
147 |
+
$this->setCache($cache);
|
148 |
+
}
|
149 |
+
|
150 |
+
if (isset($options['cache_lambda_templates'])) {
|
151 |
+
$this->cacheLambdaTemplates = (bool) $options['cache_lambda_templates'];
|
152 |
+
}
|
153 |
+
|
154 |
+
if (isset($options['loader'])) {
|
155 |
+
$this->setLoader($options['loader']);
|
156 |
+
}
|
157 |
+
|
158 |
+
if (isset($options['partials_loader'])) {
|
159 |
+
$this->setPartialsLoader($options['partials_loader']);
|
160 |
+
}
|
161 |
+
|
162 |
+
if (isset($options['partials'])) {
|
163 |
+
$this->setPartials($options['partials']);
|
164 |
+
}
|
165 |
+
|
166 |
+
if (isset($options['helpers'])) {
|
167 |
+
$this->setHelpers($options['helpers']);
|
168 |
+
}
|
169 |
+
|
170 |
+
if (isset($options['escape'])) {
|
171 |
+
if (!is_callable($options['escape'])) {
|
172 |
+
throw new Mustache_Exception_InvalidArgumentException('Mustache Constructor "escape" option must be callable');
|
173 |
+
}
|
174 |
+
|
175 |
+
$this->escape = $options['escape'];
|
176 |
+
}
|
177 |
+
|
178 |
+
if (isset($options['entity_flags'])) {
|
179 |
+
$this->entityFlags = $options['entity_flags'];
|
180 |
+
}
|
181 |
+
|
182 |
+
if (isset($options['charset'])) {
|
183 |
+
$this->charset = $options['charset'];
|
184 |
+
}
|
185 |
+
|
186 |
+
if (isset($options['logger'])) {
|
187 |
+
$this->setLogger($options['logger']);
|
188 |
+
}
|
189 |
+
|
190 |
+
if (isset($options['strict_callables'])) {
|
191 |
+
$this->strictCallables = $options['strict_callables'];
|
192 |
+
}
|
193 |
+
|
194 |
+
if (isset($options['pragmas'])) {
|
195 |
+
foreach ($options['pragmas'] as $pragma) {
|
196 |
+
if (!isset(self::$knownPragmas[$pragma])) {
|
197 |
+
throw new Mustache_Exception_InvalidArgumentException(sprintf('Unknown pragma: "%s".', $pragma));
|
198 |
+
}
|
199 |
+
$this->pragmas[$pragma] = true;
|
200 |
+
}
|
201 |
+
}
|
202 |
+
}
|
203 |
+
|
204 |
+
/**
|
205 |
+
* Shortcut 'render' invocation.
|
206 |
+
*
|
207 |
+
* Equivalent to calling `$mustache->loadTemplate($template)->render($context);`
|
208 |
+
*
|
209 |
+
* @see Mustache_Engine::loadTemplate
|
210 |
+
* @see Mustache_Template::render
|
211 |
+
*
|
212 |
+
* @param string $template
|
213 |
+
* @param mixed $context (default: array())
|
214 |
+
*
|
215 |
+
* @return string Rendered template
|
216 |
+
*/
|
217 |
+
public function render($template, $context = array())
|
218 |
+
{
|
219 |
+
return $this->loadTemplate($template)->render($context);
|
220 |
+
}
|
221 |
+
|
222 |
+
/**
|
223 |
+
* Get the current Mustache escape callback.
|
224 |
+
*
|
225 |
+
* @return callable|null
|
226 |
+
*/
|
227 |
+
public function getEscape()
|
228 |
+
{
|
229 |
+
return $this->escape;
|
230 |
+
}
|
231 |
+
|
232 |
+
/**
|
233 |
+
* Get the current Mustache entitity type to escape.
|
234 |
+
*
|
235 |
+
* @return int
|
236 |
+
*/
|
237 |
+
public function getEntityFlags()
|
238 |
+
{
|
239 |
+
return $this->entityFlags;
|
240 |
+
}
|
241 |
+
|
242 |
+
/**
|
243 |
+
* Get the current Mustache character set.
|
244 |
+
*
|
245 |
+
* @return string
|
246 |
+
*/
|
247 |
+
public function getCharset()
|
248 |
+
{
|
249 |
+
return $this->charset;
|
250 |
+
}
|
251 |
+
|
252 |
+
/**
|
253 |
+
* Get the current globally enabled pragmas.
|
254 |
+
*
|
255 |
+
* @return array
|
256 |
+
*/
|
257 |
+
public function getPragmas()
|
258 |
+
{
|
259 |
+
return array_keys($this->pragmas);
|
260 |
+
}
|
261 |
+
|
262 |
+
/**
|
263 |
+
* Set the Mustache template Loader instance.
|
264 |
+
*
|
265 |
+
* @param Mustache_Loader $loader
|
266 |
+
*/
|
267 |
+
public function setLoader(Mustache_Loader $loader)
|
268 |
+
{
|
269 |
+
$this->loader = $loader;
|
270 |
+
}
|
271 |
+
|
272 |
+
/**
|
273 |
+
* Get the current Mustache template Loader instance.
|
274 |
+
*
|
275 |
+
* If no Loader instance has been explicitly specified, this method will instantiate and return
|
276 |
+
* a StringLoader instance.
|
277 |
+
*
|
278 |
+
* @return Mustache_Loader
|
279 |
+
*/
|
280 |
+
public function getLoader()
|
281 |
+
{
|
282 |
+
if (!isset($this->loader)) {
|
283 |
+
$this->loader = new Mustache_Loader_StringLoader();
|
284 |
+
}
|
285 |
+
|
286 |
+
return $this->loader;
|
287 |
+
}
|
288 |
+
|
289 |
+
/**
|
290 |
+
* Set the Mustache partials Loader instance.
|
291 |
+
*
|
292 |
+
* @param Mustache_Loader $partialsLoader
|
293 |
+
*/
|
294 |
+
public function setPartialsLoader(Mustache_Loader $partialsLoader)
|
295 |
+
{
|
296 |
+
$this->partialsLoader = $partialsLoader;
|
297 |
+
}
|
298 |
+
|
299 |
+
/**
|
300 |
+
* Get the current Mustache partials Loader instance.
|
301 |
+
*
|
302 |
+
* If no Loader instance has been explicitly specified, this method will instantiate and return
|
303 |
+
* an ArrayLoader instance.
|
304 |
+
*
|
305 |
+
* @return Mustache_Loader
|
306 |
+
*/
|
307 |
+
public function getPartialsLoader()
|
308 |
+
{
|
309 |
+
if (!isset($this->partialsLoader)) {
|
310 |
+
$this->partialsLoader = new Mustache_Loader_ArrayLoader();
|
311 |
+
}
|
312 |
+
|
313 |
+
return $this->partialsLoader;
|
314 |
+
}
|
315 |
+
|
316 |
+
/**
|
317 |
+
* Set partials for the current partials Loader instance.
|
318 |
+
*
|
319 |
+
* @throws Mustache_Exception_RuntimeException If the current Loader instance is immutable
|
320 |
+
*
|
321 |
+
* @param array $partials (default: array())
|
322 |
+
*/
|
323 |
+
public function setPartials(array $partials = array())
|
324 |
+
{
|
325 |
+
if (!isset($this->partialsLoader)) {
|
326 |
+
$this->partialsLoader = new Mustache_Loader_ArrayLoader();
|
327 |
+
}
|
328 |
+
|
329 |
+
if (!$this->partialsLoader instanceof Mustache_Loader_MutableLoader) {
|
330 |
+
throw new Mustache_Exception_RuntimeException('Unable to set partials on an immutable Mustache Loader instance');
|
331 |
+
}
|
332 |
+
|
333 |
+
$this->partialsLoader->setTemplates($partials);
|
334 |
+
}
|
335 |
+
|
336 |
+
/**
|
337 |
+
* Set an array of Mustache helpers.
|
338 |
+
*
|
339 |
+
* An array of 'helpers'. Helpers can be global variables or objects, closures (e.g. for higher order sections), or
|
340 |
+
* any other valid Mustache context value. They will be prepended to the context stack, so they will be available in
|
341 |
+
* any template loaded by this Mustache instance.
|
342 |
+
*
|
343 |
+
* @throws Mustache_Exception_InvalidArgumentException if $helpers is not an array or Traversable
|
344 |
+
*
|
345 |
+
* @param array|Traversable $helpers
|
346 |
+
*/
|
347 |
+
public function setHelpers($helpers)
|
348 |
+
{
|
349 |
+
if (!is_array($helpers) && !$helpers instanceof Traversable) {
|
350 |
+
throw new Mustache_Exception_InvalidArgumentException('setHelpers expects an array of helpers');
|
351 |
+
}
|
352 |
+
|
353 |
+
$this->getHelpers()->clear();
|
354 |
+
|
355 |
+
foreach ($helpers as $name => $helper) {
|
356 |
+
$this->addHelper($name, $helper);
|
357 |
+
}
|
358 |
+
}
|
359 |
+
|
360 |
+
/**
|
361 |
+
* Get the current set of Mustache helpers.
|
362 |
+
*
|
363 |
+
* @see Mustache_Engine::setHelpers
|
364 |
+
*
|
365 |
+
* @return Mustache_HelperCollection
|
366 |
+
*/
|
367 |
+
public function getHelpers()
|
368 |
+
{
|
369 |
+
if (!isset($this->helpers)) {
|
370 |
+
$this->helpers = new Mustache_HelperCollection();
|
371 |
+
}
|
372 |
+
|
373 |
+
return $this->helpers;
|
374 |
+
}
|
375 |
+
|
376 |
+
/**
|
377 |
+
* Add a new Mustache helper.
|
378 |
+
*
|
379 |
+
* @see Mustache_Engine::setHelpers
|
380 |
+
*
|
381 |
+
* @param string $name
|
382 |
+
* @param mixed $helper
|
383 |
+
*/
|
384 |
+
public function addHelper($name, $helper)
|
385 |
+
{
|
386 |
+
$this->getHelpers()->add($name, $helper);
|
387 |
+
}
|
388 |
+
|
389 |
+
/**
|
390 |
+
* Get a Mustache helper by name.
|
391 |
+
*
|
392 |
+
* @see Mustache_Engine::setHelpers
|
393 |
+
*
|
394 |
+
* @param string $name
|
395 |
+
*
|
396 |
+
* @return mixed Helper
|
397 |
+
*/
|
398 |
+
public function getHelper($name)
|
399 |
+
{
|
400 |
+
return $this->getHelpers()->get($name);
|
401 |
+
}
|
402 |
+
|
403 |
+
/**
|
404 |
+
* Check whether this Mustache instance has a helper.
|
405 |
+
*
|
406 |
+
* @see Mustache_Engine::setHelpers
|
407 |
+
*
|
408 |
+
* @param string $name
|
409 |
+
*
|
410 |
+
* @return bool True if the helper is present
|
411 |
+
*/
|
412 |
+
public function hasHelper($name)
|
413 |
+
{
|
414 |
+
return $this->getHelpers()->has($name);
|
415 |
+
}
|
416 |
+
|
417 |
+
/**
|
418 |
+
* Remove a helper by name.
|
419 |
+
*
|
420 |
+
* @see Mustache_Engine::setHelpers
|
421 |
+
*
|
422 |
+
* @param string $name
|
423 |
+
*/
|
424 |
+
public function removeHelper($name)
|
425 |
+
{
|
426 |
+
$this->getHelpers()->remove($name);
|
427 |
+
}
|
428 |
+
|
429 |
+
/**
|
430 |
+
* Set the Mustache Logger instance.
|
431 |
+
*
|
432 |
+
* @throws Mustache_Exception_InvalidArgumentException If logger is not an instance of Mustache_Logger or Psr\Log\LoggerInterface.
|
433 |
+
*
|
434 |
+
* @param Mustache_Logger|Psr\Log\LoggerInterface $logger
|
435 |
+
*/
|
436 |
+
public function setLogger($logger = null)
|
437 |
+
{
|
438 |
+
if ($logger !== null && !($logger instanceof Mustache_Logger || is_a($logger, 'Psr\\Log\\LoggerInterface'))) {
|
439 |
+
throw new Mustache_Exception_InvalidArgumentException('Expected an instance of Mustache_Logger or Psr\\Log\\LoggerInterface.');
|
440 |
+
}
|
441 |
+
|
442 |
+
if ($this->getCache()->getLogger() === null) {
|
443 |
+
$this->getCache()->setLogger($logger);
|
444 |
+
}
|
445 |
+
|
446 |
+
$this->logger = $logger;
|
447 |
+
}
|
448 |
+
|
449 |
+
/**
|
450 |
+
* Get the current Mustache Logger instance.
|
451 |
+
*
|
452 |
+
* @return Mustache_Logger|Psr\Log\LoggerInterface
|
453 |
+
*/
|
454 |
+
public function getLogger()
|
455 |
+
{
|
456 |
+
return $this->logger;
|
457 |
+
}
|
458 |
+
|
459 |
+
/**
|
460 |
+
* Set the Mustache Tokenizer instance.
|
461 |
+
*
|
462 |
+
* @param Mustache_Tokenizer $tokenizer
|
463 |
+
*/
|
464 |
+
public function setTokenizer(Mustache_Tokenizer $tokenizer)
|
465 |
+
{
|
466 |
+
$this->tokenizer = $tokenizer;
|
467 |
+
}
|
468 |
+
|
469 |
+
/**
|
470 |
+
* Get the current Mustache Tokenizer instance.
|
471 |
+
*
|
472 |
+
* If no Tokenizer instance has been explicitly specified, this method will instantiate and return a new one.
|
473 |
+
*
|
474 |
+
* @return Mustache_Tokenizer
|
475 |
+
*/
|
476 |
+
public function getTokenizer()
|
477 |
+
{
|
478 |
+
if (!isset($this->tokenizer)) {
|
479 |
+
$this->tokenizer = new Mustache_Tokenizer();
|
480 |
+
}
|
481 |
+
|
482 |
+
return $this->tokenizer;
|
483 |
+
}
|
484 |
+
|
485 |
+
/**
|
486 |
+
* Set the Mustache Parser instance.
|
487 |
+
*
|
488 |
+
* @param Mustache_Parser $parser
|
489 |
+
*/
|
490 |
+
public function setParser(Mustache_Parser $parser)
|
491 |
+
{
|
492 |
+
$this->parser = $parser;
|
493 |
+
}
|
494 |
+
|
495 |
+
/**
|
496 |
+
* Get the current Mustache Parser instance.
|
497 |
+
*
|
498 |
+
* If no Parser instance has been explicitly specified, this method will instantiate and return a new one.
|
499 |
+
*
|
500 |
+
* @return Mustache_Parser
|
501 |
+
*/
|
502 |
+
public function getParser()
|
503 |
+
{
|
504 |
+
if (!isset($this->parser)) {
|
505 |
+
$this->parser = new Mustache_Parser();
|
506 |
+
}
|
507 |
+
|
508 |
+
return $this->parser;
|
509 |
+
}
|
510 |
+
|
511 |
+
/**
|
512 |
+
* Set the Mustache Compiler instance.
|
513 |
+
*
|
514 |
+
* @param Mustache_Compiler $compiler
|
515 |
+
*/
|
516 |
+
public function setCompiler(Mustache_Compiler $compiler)
|
517 |
+
{
|
518 |
+
$this->compiler = $compiler;
|
519 |
+
}
|
520 |
+
|
521 |
+
/**
|
522 |
+
* Get the current Mustache Compiler instance.
|
523 |
+
*
|
524 |
+
* If no Compiler instance has been explicitly specified, this method will instantiate and return a new one.
|
525 |
+
*
|
526 |
+
* @return Mustache_Compiler
|
527 |
+
*/
|
528 |
+
public function getCompiler()
|
529 |
+
{
|
530 |
+
if (!isset($this->compiler)) {
|
531 |
+
$this->compiler = new Mustache_Compiler();
|
532 |
+
}
|
533 |
+
|
534 |
+
return $this->compiler;
|
535 |
+
}
|
536 |
+
|
537 |
+
/**
|
538 |
+
* Set the Mustache Cache instance.
|
539 |
+
*
|
540 |
+
* @param Mustache_Cache $cache
|
541 |
+
*/
|
542 |
+
public function setCache(Mustache_Cache $cache)
|
543 |
+
{
|
544 |
+
if (isset($this->logger) && $cache->getLogger() === null) {
|
545 |
+
$cache->setLogger($this->getLogger());
|
546 |
+
}
|
547 |
+
|
548 |
+
$this->cache = $cache;
|
549 |
+
}
|
550 |
+
|
551 |
+
/**
|
552 |
+
* Get the current Mustache Cache instance.
|
553 |
+
*
|
554 |
+
* If no Cache instance has been explicitly specified, this method will instantiate and return a new one.
|
555 |
+
*
|
556 |
+
* @return Mustache_Cache
|
557 |
+
*/
|
558 |
+
public function getCache()
|
559 |
+
{
|
560 |
+
if (!isset($this->cache)) {
|
561 |
+
$this->setCache(new Mustache_Cache_NoopCache());
|
562 |
+
}
|
563 |
+
|
564 |
+
return $this->cache;
|
565 |
+
}
|
566 |
+
|
567 |
+
/**
|
568 |
+
* Get the current Lambda Cache instance.
|
569 |
+
*
|
570 |
+
* If 'cache_lambda_templates' is enabled, this is the default cache instance. Otherwise, it is a NoopCache.
|
571 |
+
*
|
572 |
+
* @see Mustache_Engine::getCache
|
573 |
+
*
|
574 |
+
* @return Mustache_Cache
|
575 |
+
*/
|
576 |
+
protected function getLambdaCache()
|
577 |
+
{
|
578 |
+
if ($this->cacheLambdaTemplates) {
|
579 |
+
return $this->getCache();
|
580 |
+
}
|
581 |
+
|
582 |
+
if (!isset($this->lambdaCache)) {
|
583 |
+
$this->lambdaCache = new Mustache_Cache_NoopCache();
|
584 |
+
}
|
585 |
+
|
586 |
+
return $this->lambdaCache;
|
587 |
+
}
|
588 |
+
|
589 |
+
/**
|
590 |
+
* Helper method to generate a Mustache template class.
|
591 |
+
*
|
592 |
+
* @param string $source
|
593 |
+
*
|
594 |
+
* @return string Mustache Template class name
|
595 |
+
*/
|
596 |
+
public function getTemplateClassName($source)
|
597 |
+
{
|
598 |
+
return $this->templateClassPrefix . md5(sprintf(
|
599 |
+
'version:%s,escape:%s,entity_flags:%i,charset:%s,strict_callables:%s,pragmas:%s,source:%s',
|
600 |
+
self::VERSION,
|
601 |
+
isset($this->escape) ? 'custom' : 'default',
|
602 |
+
$this->entityFlags,
|
603 |
+
$this->charset,
|
604 |
+
$this->strictCallables ? 'true' : 'false',
|
605 |
+
implode(' ', $this->getPragmas()),
|
606 |
+
$source
|
607 |
+
));
|
608 |
+
}
|
609 |
+
|
610 |
+
/**
|
611 |
+
* Load a Mustache Template by name.
|
612 |
+
*
|
613 |
+
* @param string $name
|
614 |
+
*
|
615 |
+
* @return Mustache_Template
|
616 |
+
*/
|
617 |
+
public function loadTemplate($name)
|
618 |
+
{
|
619 |
+
return $this->loadSource($this->getLoader()->load($name));
|
620 |
+
}
|
621 |
+
|
622 |
+
/**
|
623 |
+
* Load a Mustache partial Template by name.
|
624 |
+
*
|
625 |
+
* This is a helper method used internally by Template instances for loading partial templates. You can most likely
|
626 |
+
* ignore it completely.
|
627 |
+
*
|
628 |
+
* @param string $name
|
629 |
+
*
|
630 |
+
* @return Mustache_Template
|
631 |
+
*/
|
632 |
+
public function loadPartial($name)
|
633 |
+
{
|
634 |
+
try {
|
635 |
+
if (isset($this->partialsLoader)) {
|
636 |
+
$loader = $this->partialsLoader;
|
637 |
+
} elseif (isset($this->loader) && !$this->loader instanceof Mustache_Loader_StringLoader) {
|
638 |
+
$loader = $this->loader;
|
639 |
+
} else {
|
640 |
+
throw new Mustache_Exception_UnknownTemplateException($name);
|
641 |
+
}
|
642 |
+
|
643 |
+
return $this->loadSource($loader->load($name));
|
644 |
+
} catch (Mustache_Exception_UnknownTemplateException $e) {
|
645 |
+
// If the named partial cannot be found, log then return null.
|
646 |
+
$this->log(
|
647 |
+
Mustache_Logger::WARNING,
|
648 |
+
'Partial not found: "{name}"',
|
649 |
+
array('name' => $e->getTemplateName())
|
650 |
+
);
|
651 |
+
}
|
652 |
+
}
|
653 |
+
|
654 |
+
/**
|
655 |
+
* Load a Mustache lambda Template by source.
|
656 |
+
*
|
657 |
+
* This is a helper method used by Template instances to generate subtemplates for Lambda sections. You can most
|
658 |
+
* likely ignore it completely.
|
659 |
+
*
|
660 |
+
* @param string $source
|
661 |
+
* @param string $delims (default: null)
|
662 |
+
*
|
663 |
+
* @return Mustache_Template
|
664 |
+
*/
|
665 |
+
public function loadLambda($source, $delims = null)
|
666 |
+
{
|
667 |
+
if ($delims !== null) {
|
668 |
+
$source = $delims . "\n" . $source;
|
669 |
+
}
|
670 |
+
|
671 |
+
return $this->loadSource($source, $this->getLambdaCache());
|
672 |
+
}
|
673 |
+
|
674 |
+
/**
|
675 |
+
* Instantiate and return a Mustache Template instance by source.
|
676 |
+
*
|
677 |
+
* Optionally provide a Mustache_Cache instance. This is used internally by Mustache_Engine::loadLambda to respect
|
678 |
+
* the 'cache_lambda_templates' configuration option.
|
679 |
+
*
|
680 |
+
* @see Mustache_Engine::loadTemplate
|
681 |
+
* @see Mustache_Engine::loadPartial
|
682 |
+
* @see Mustache_Engine::loadLambda
|
683 |
+
*
|
684 |
+
* @param string $source
|
685 |
+
* @param Mustache_Cache $cache (default: null)
|
686 |
+
*
|
687 |
+
* @return Mustache_Template
|
688 |
+
*/
|
689 |
+
private function loadSource($source, Mustache_Cache $cache = null)
|
690 |
+
{
|
691 |
+
$className = $this->getTemplateClassName($source);
|
692 |
+
|
693 |
+
if (!isset($this->templates[$className])) {
|
694 |
+
if ($cache === null) {
|
695 |
+
$cache = $this->getCache();
|
696 |
+
}
|
697 |
+
|
698 |
+
if (!class_exists($className, false)) {
|
699 |
+
if (!$cache->load($className)) {
|
700 |
+
$compiled = $this->compile($source);
|
701 |
+
$cache->cache($className, $compiled);
|
702 |
+
}
|
703 |
+
}
|
704 |
+
|
705 |
+
$this->log(
|
706 |
+
Mustache_Logger::DEBUG,
|
707 |
+
'Instantiating template: "{className}"',
|
708 |
+
array('className' => $className)
|
709 |
+
);
|
710 |
+
|
711 |
+
$this->templates[$className] = new $className($this);
|
712 |
+
}
|
713 |
+
|
714 |
+
return $this->templates[$className];
|
715 |
+
}
|
716 |
+
|
717 |
+
/**
|
718 |
+
* Helper method to tokenize a Mustache template.
|
719 |
+
*
|
720 |
+
* @see Mustache_Tokenizer::scan
|
721 |
+
*
|
722 |
+
* @param string $source
|
723 |
+
*
|
724 |
+
* @return array Tokens
|
725 |
+
*/
|
726 |
+
private function tokenize($source)
|
727 |
+
{
|
728 |
+
return $this->getTokenizer()->scan($source);
|
729 |
+
}
|
730 |
+
|
731 |
+
/**
|
732 |
+
* Helper method to parse a Mustache template.
|
733 |
+
*
|
734 |
+
* @see Mustache_Parser::parse
|
735 |
+
*
|
736 |
+
* @param string $source
|
737 |
+
*
|
738 |
+
* @return array Token tree
|
739 |
+
*/
|
740 |
+
private function parse($source)
|
741 |
+
{
|
742 |
+
$parser = $this->getParser();
|
743 |
+
$parser->setPragmas($this->getPragmas());
|
744 |
+
|
745 |
+
return $parser->parse($this->tokenize($source));
|
746 |
+
}
|
747 |
+
|
748 |
+
/**
|
749 |
+
* Helper method to compile a Mustache template.
|
750 |
+
*
|
751 |
+
* @see Mustache_Compiler::compile
|
752 |
+
*
|
753 |
+
* @param string $source
|
754 |
+
*
|
755 |
+
* @return string generated Mustache template class code
|
756 |
+
*/
|
757 |
+
private function compile($source)
|
758 |
+
{
|
759 |
+
$tree = $this->parse($source);
|
760 |
+
$name = $this->getTemplateClassName($source);
|
761 |
+
|
762 |
+
$this->log(
|
763 |
+
Mustache_Logger::INFO,
|
764 |
+
'Compiling template to "{className}" class',
|
765 |
+
array('className' => $name)
|
766 |
+
);
|
767 |
+
|
768 |
+
$compiler = $this->getCompiler();
|
769 |
+
$compiler->setPragmas($this->getPragmas());
|
770 |
+
|
771 |
+
return $compiler->compile($source, $tree, $name, isset($this->escape), $this->charset, $this->strictCallables, $this->entityFlags);
|
772 |
+
}
|
773 |
+
|
774 |
+
/**
|
775 |
+
* Add a log record if logging is enabled.
|
776 |
+
*
|
777 |
+
* @param int $level The logging level
|
778 |
+
* @param string $message The log message
|
779 |
+
* @param array $context The log context
|
780 |
+
*/
|
781 |
+
private function log($level, $message, array $context = array())
|
782 |
+
{
|
783 |
+
if (isset($this->logger)) {
|
784 |
+
$this->logger->log($level, $message, $context);
|
785 |
+
}
|
786 |
+
}
|
787 |
+
}
|
lib/php/Mustache/Exception.php
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of Mustache.php.
|
5 |
+
*
|
6 |
+
* (c) 2010-2015 Justin Hileman
|
7 |
+
*
|
8 |
+
* For the full copyright and license information, please view the LICENSE
|
9 |
+
* file that was distributed with this source code.
|
10 |
+
*/
|
11 |
+
|
12 |
+
/**
|
13 |
+
* A Mustache Exception interface.
|
14 |
+
*/
|
15 |
+
interface Mustache_Exception
|
16 |
+
{
|
17 |
+
// This space intentionally left blank.
|
18 |
+
}
|
lib/php/Mustache/Exception/InvalidArgumentException.php
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of Mustache.php.
|
5 |
+
*
|
6 |
+
* (c) 2010-2015 Justin Hileman
|
7 |
+
*
|
8 |
+
* For the full copyright and license information, please view the LICENSE
|
9 |
+
* file that was distributed with this source code.
|
10 |
+
*/
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Invalid argument exception.
|
14 |
+
*/
|
15 |
+
class Mustache_Exception_InvalidArgumentException extends InvalidArgumentException implements Mustache_Exception
|
16 |
+
{
|
17 |
+
// This space intentionally left blank.
|
18 |
+
}
|
lib/php/Mustache/Exception/LogicException.php
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of Mustache.php.
|
5 |
+
*
|
6 |
+
* (c) 2010-2015 Justin Hileman
|
7 |
+
*
|
8 |
+
* For the full copyright and license information, please view the LICENSE
|
9 |
+
* file that was distributed with this source code.
|
10 |
+
*/
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Logic exception.
|
14 |
+
*/
|
15 |
+
class Mustache_Exception_LogicException extends LogicException implements Mustache_Exception
|
16 |
+
{
|
17 |
+
// This space intentionally left blank.
|
18 |
+
}
|
lib/php/Mustache/Exception/RuntimeException.php
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of Mustache.php.
|
5 |
+
*
|
6 |
+
* (c) 2010-2015 Justin Hileman
|
7 |
+
*
|
8 |
+
* For the full copyright and license information, please view the LICENSE
|
9 |
+
* file that was distributed with this source code.
|
10 |
+
*/
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Runtime exception.
|
14 |
+
*/
|
15 |
+
class Mustache_Exception_RuntimeException extends RuntimeException implements Mustache_Exception
|
16 |
+
{
|
17 |
+
// This space intentionally left blank.
|
18 |
+
}
|
lib/php/Mustache/Exception/SyntaxException.php
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of Mustache.php.
|
5 |
+
*
|
6 |
+
* (c) 2010-2015 Justin Hileman
|
7 |
+
*
|
8 |
+
* For the full copyright and license information, please view the LICENSE
|
9 |
+
* file that was distributed with this source code.
|
10 |
+
*/
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Mustache syntax exception.
|
14 |
+
*/
|
15 |
+
class Mustache_Exception_SyntaxException extends LogicException implements Mustache_Exception
|
16 |
+
{
|
17 |
+
protected $token;
|
18 |
+
|
19 |
+
/**
|
20 |
+
* @param string $msg
|
21 |
+
* @param array $token
|
22 |
+
*/
|
23 |
+
public function __construct($msg, array $token)
|
24 |
+
{
|
25 |
+
$this->token = $token;
|
26 |
+
parent::__construct($msg);
|
27 |
+
}
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @return array
|
31 |
+
*/
|
32 |
+
public function getToken()
|
33 |
+
{
|
34 |
+
return $this->token;
|
35 |
+
}
|
36 |
+
}
|
lib/php/Mustache/Exception/UnknownFilterException.php
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of Mustache.php.
|
5 |
+
*
|
6 |
+
* (c) 2010-2015 Justin Hileman
|
7 |
+
*
|
8 |
+
* For the full copyright and license information, please view the LICENSE
|
9 |
+
* file that was distributed with this source code.
|
10 |
+
*/
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Unknown filter exception.
|
14 |
+
*/
|
15 |
+
class Mustache_Exception_UnknownFilterException extends UnexpectedValueException implements Mustache_Exception
|
16 |
+
{
|
17 |
+
protected $filterName;
|
18 |
+
|
19 |
+
/**
|
20 |
+
* @param string $filterName
|
21 |
+
*/
|
22 |
+
public function __construct($filterName)
|
23 |
+
{
|
24 |
+
$this->filterName = $filterName;
|
25 |
+
parent::__construct(sprintf('Unknown filter: %s', $filterName));
|
26 |
+
}
|
27 |
+
|
28 |
+
public function getFilterName()
|
29 |
+
{
|
30 |
+
return $this->filterName;
|
31 |
+
}
|
32 |
+
}
|
lib/php/Mustache/Exception/UnknownHelperException.php
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of Mustache.php.
|
5 |
+
*
|
6 |
+
* (c) 2010-2015 Justin Hileman
|
7 |
+
*
|
8 |
+
* For the full copyright and license information, please view the LICENSE
|
9 |
+
* file that was distributed with this source code.
|
10 |
+
*/
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Unknown helper exception.
|
14 |
+
*/
|
15 |
+
class Mustache_Exception_UnknownHelperException extends InvalidArgumentException implements Mustache_Exception
|
16 |
+
{
|
17 |
+
protected $helperName;
|
18 |
+
|
19 |
+
/**
|
20 |
+
* @param string $helperName
|
21 |
+
*/
|
22 |
+
public function __construct($helperName)
|
23 |
+
{
|
24 |
+
$this->helperName = $helperName;
|
25 |
+
parent::__construct(sprintf('Unknown helper: %s', $helperName));
|
26 |
+
}
|
27 |
+
|
28 |
+
public function getHelperName()
|
29 |
+
{
|
30 |
+
return $this->helperName;
|
31 |
+
}
|
32 |
+
}
|
lib/php/Mustache/Exception/UnknownTemplateException.php
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of Mustache.php.
|
5 |
+
*
|
6 |
+
* (c) 2010-2015 Justin Hileman
|
7 |
+
*
|
8 |
+
* For the full copyright and license information, please view the LICENSE
|
9 |
+
* file that was distributed with this source code.
|
10 |
+
*/
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Unknown template exception.
|
14 |
+
*/
|
15 |
+
class Mustache_Exception_UnknownTemplateException extends InvalidArgumentException implements Mustache_Exception
|
16 |
+
{
|
17 |
+
protected $templateName;
|
18 |
+
|
19 |
+
/**
|
20 |
+
* @param string $templateName
|
21 |
+
*/
|
22 |
+
public function __construct($templateName)
|
23 |
+
{
|
24 |
+
$this->templateName = $templateName;
|
25 |
+
parent::__construct(sprintf('Unknown template: %s', $templateName));
|
26 |
+
}
|
27 |
+
|
28 |
+
public function getTemplateName()
|
29 |
+
{
|
30 |
+
return $this->templateName;
|
31 |
+
}
|
32 |
+
}
|
lib/php/Mustache/HelperCollection.php
ADDED
@@ -0,0 +1,172 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of Mustache.php.
|
5 |
+
*
|
6 |
+
* (c) 2010-2015 Justin Hileman
|
7 |
+
*
|
8 |
+
* For the full copyright and license information, please view the LICENSE
|
9 |
+
* file that was distributed with this source code.
|
10 |
+
*/
|
11 |
+
|
12 |
+
/**
|
13 |
+
* A collection of helpers for a Mustache instance.
|
14 |
+
*/
|
15 |
+
class Mustache_HelperCollection
|
16 |
+
{
|
17 |
+
private $helpers = array();
|
18 |
+
|
19 |
+
/**
|
20 |
+
* Helper Collection constructor.
|
21 |
+
*
|
22 |
+
* Optionally accepts an array (or Traversable) of `$name => $helper` pairs.
|
23 |
+
*
|
24 |
+
* @throws Mustache_Exception_InvalidArgumentException if the $helpers argument isn't an array or Traversable
|
25 |
+
*
|
26 |
+
* @param array|Traversable $helpers (default: null)
|
27 |
+
*/
|
28 |
+
public function __construct($helpers = null)
|
29 |
+
{
|
30 |
+
if ($helpers === null) {
|
31 |
+
return;
|
32 |
+
}
|
33 |
+
|
34 |
+
if (!is_array($helpers) && !$helpers instanceof Traversable) {
|
35 |
+
throw new Mustache_Exception_InvalidArgumentException('HelperCollection constructor expects an array of helpers');
|
36 |
+
}
|
37 |
+
|
38 |
+
foreach ($helpers as $name => $helper) {
|
39 |
+
$this->add($name, $helper);
|
40 |
+
}
|
41 |
+
}
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Magic mutator.
|
45 |
+
*
|
46 |
+
* @see Mustache_HelperCollection::add
|
47 |
+
*
|
48 |
+
* @param string $name
|
49 |
+
* @param mixed $helper
|
50 |
+
*/
|
51 |
+
public function __set($name, $helper)
|
52 |
+
{
|
53 |
+
$this->add($name, $helper);
|
54 |
+
}
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Add a helper to this collection.
|
58 |
+
*
|
59 |
+
* @param string $name
|
60 |
+
* @param mixed $helper
|
61 |
+
*/
|
62 |
+
public function add($name, $helper)
|
63 |
+
{
|
64 |
+
$this->helpers[$name] = $helper;
|
65 |
+
}
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Magic accessor.
|
69 |
+
*
|
70 |
+
* @see Mustache_HelperCollection::get
|
71 |
+
*
|
72 |
+
* @param string $name
|
73 |
+
*
|
74 |
+
* @return mixed Helper
|
75 |
+
*/
|
76 |
+
public function __get($name)
|
77 |
+
{
|
78 |
+
return $this->get($name);
|
79 |
+
}
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Get a helper by name.
|
83 |
+
*
|
84 |
+
* @throws Mustache_Exception_UnknownHelperException If helper does not exist.
|
85 |
+
*
|
86 |
+
* @param string $name
|
87 |
+
*
|
88 |
+
* @return mixed Helper
|
89 |
+
*/
|
90 |
+
public function get($name)
|
91 |
+
{
|
92 |
+
if (!$this->has($name)) {
|
93 |
+
throw new Mustache_Exception_UnknownHelperException($name);
|
94 |
+
}
|
95 |
+
|
96 |
+
return $this->helpers[$name];
|
97 |
+
}
|
98 |
+
|
99 |
+
/**
|
100 |
+
* Magic isset().
|
101 |
+
*
|
102 |
+
* @see Mustache_HelperCollection::has
|
103 |
+
*
|
104 |
+
* @param string $name
|
105 |
+
*
|
106 |
+
* @return bool True if helper is present
|
107 |
+
*/
|
108 |
+
public function __isset($name)
|
109 |
+
{
|
110 |
+
return $this->has($name);
|
111 |
+
}
|
112 |
+
|
113 |
+
/**
|
114 |
+
* Check whether a given helper is present in the collection.
|
115 |
+
*
|
116 |
+
* @param string $name
|
117 |
+
*
|
118 |
+
* @return bool True if helper is present
|
119 |
+
*/
|
120 |
+
public function has($name)
|
121 |
+
{
|
122 |
+
return array_key_exists($name, $this->helpers);
|
123 |
+
}
|
124 |
+
|
125 |
+
/**
|
126 |
+
* Magic unset().
|
127 |
+
*
|
128 |
+
* @see Mustache_HelperCollection::remove
|
129 |
+
*
|
130 |
+
* @param string $name
|
131 |
+
*/
|
132 |
+
public function __unset($name)
|
133 |
+
{
|
134 |
+
$this->remove($name);
|
135 |
+
}
|
136 |
+
|
137 |
+
/**
|
138 |
+
* Check whether a given helper is present in the collection.
|
139 |
+
*
|
140 |
+
* @throws Mustache_Exception_UnknownHelperException if the requested helper is not present.
|
141 |
+
*
|
142 |
+
* @param string $name
|
143 |
+
*/
|
144 |
+
public function remove($name)
|
145 |
+
{
|
146 |
+
if (!$this->has($name)) {
|
147 |
+
throw new Mustache_Exception_UnknownHelperException($name);
|
148 |
+
}
|
149 |
+
|
150 |
+
unset($this->helpers[$name]);
|
151 |
+
}
|
152 |
+
|
153 |
+
/**
|
154 |
+
* Clear the helper collection.
|
155 |
+
*
|
156 |
+
* Removes all helpers from this collection
|
157 |
+
*/
|
158 |
+
public function clear()
|
159 |
+
{
|
160 |
+
$this->helpers = array();
|
161 |
+
}
|
162 |
+
|
163 |
+
/**
|
164 |
+
* Check whether the helper collection is empty.
|
165 |
+
*
|
166 |
+
* @return bool True if the collection is empty
|
167 |
+
*/
|
168 |
+
public function isEmpty()
|
169 |
+
{
|
170 |
+
return empty($this->helpers);
|
171 |
+
}
|
172 |
+
}
|
lib/php/Mustache/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
The MIT License (MIT)
|
2 |
+
|
3 |
+
Copyright (c) 2010-2015 Justin Hileman
|
4 |
+
|
5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6 |
+
of this software and associated documentation files (the "Software"), to deal
|
7 |
+
in the Software without restriction, including without limitation the rights
|
8 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9 |
+
copies of the Software, and to permit persons to whom the Software is
|
10 |
+
furnished to do so, subject to the following conditions:
|
11 |
+
|
12 |
+
The above copyright notice and this permission notice shall be included in all
|
13 |
+
copies or substantial portions of the Software.
|
14 |
+
|
15 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16 |
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17 |
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
18 |
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
19 |
+
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
20 |
+
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
21 |
+
OR OTHER DEALINGS IN THE SOFTWARE.
|
lib/php/Mustache/LambdaHelper.php
ADDED
@@ -0,0 +1,76 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of Mustache.php.
|
5 |
+
*
|
6 |
+
* (c) 2010-2015 Justin Hileman
|
7 |
+
*
|
8 |
+
* For the full copyright and license information, please view the LICENSE
|
9 |
+
* file that was distributed with this source code.
|
10 |
+
*/
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Mustache Lambda Helper.
|
14 |
+
*
|
15 |
+
* Passed as the second argument to section lambdas (higher order sections),
|
16 |
+
* giving them access to a `render` method for rendering a string with the
|
17 |
+
* current context.
|
18 |
+
*/
|
19 |
+
class Mustache_LambdaHelper
|
20 |
+
{
|
21 |
+
private $mustache;
|
22 |
+
private $context;
|
23 |
+
private $delims;
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Mustache Lambda Helper constructor.
|
27 |
+
*
|
28 |
+
* @param Mustache_Engine $mustache Mustache engine instance.
|
29 |
+
* @param Mustache_Context $context Rendering context.
|
30 |
+
* @param string $delims Optional custom delimiters, in the format `{{= <% %> =}}`. (default: null)
|
31 |
+
*/
|
32 |
+
public function __construct(Mustache_Engine $mustache, Mustache_Context $context, $delims = null)
|
33 |
+
{
|
34 |
+
$this->mustache = $mustache;
|
35 |
+
$this->context = $context;
|
36 |
+
$this->delims = $delims;
|
37 |
+
}
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Render a string as a Mustache template with the current rendering context.
|
41 |
+
*
|
42 |
+
* @param string $string
|
43 |
+
*
|
44 |
+
* @return string Rendered template.
|
45 |
+
*/
|
46 |
+
public function render($string)
|
47 |
+
{
|
48 |
+
return $this->mustache
|
49 |
+
->loadLambda((string) $string, $this->delims)
|
50 |
+
->renderInternal($this->context);
|
51 |
+
}
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Render a string as a Mustache template with the current rendering context.
|
55 |
+
*
|
56 |
+
* @param string $string
|
57 |
+
*
|
58 |
+
* @return string Rendered template
|
59 |
+
*/
|
60 |
+
public function __invoke($string)
|
61 |
+
{
|
62 |
+
return $this->render($string);
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Get a Lambda Helper with custom delimiters.
|
67 |
+
*
|
68 |
+
* @param string $delims Custom delimiters, in the format `{{= <% %> =}}`.
|
69 |
+
*
|
70 |
+
* @return Mustache_LambdaHelper
|
71 |
+
*/
|
72 |
+
public function withDelimiters($delims)
|
73 |
+
{
|
74 |
+
return new self($this->mustache, $this->context, $delims);
|
75 |
+
}
|
76 |
+
}
|
lib/php/Mustache/Loader.php
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of Mustache.php.
|
5 |
+
*
|
6 |
+
* (c) 2010-2015 Justin Hileman
|
7 |
+
*
|
8 |
+
* For the full copyright and license information, please view the LICENSE
|
9 |
+
* file that was distributed with this source code.
|
10 |
+
*/
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Mustache Template Loader interface.
|
14 |
+
*/
|
15 |
+
interface Mustache_Loader
|
16 |
+
{
|
17 |
+
/**
|
18 |
+
* Load a Template by name.
|
19 |
+
*
|
20 |
+
* @throws Mustache_Exception_UnknownTemplateException If a template file is not found.
|
21 |
+
*
|
22 |
+
* @param string $name
|
23 |
+
*
|
24 |
+
* @return string Mustache Template source
|
25 |
+
*/
|
26 |
+
public function load($name);
|
27 |
+
}
|
lib/php/Mustache/Loader/ArrayLoader.php
ADDED
@@ -0,0 +1,79 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of Mustache.php.
|
5 |
+
*
|
6 |
+
* (c) 2010-2015 Justin Hileman
|
7 |
+
*
|
8 |
+
* For the full copyright and license information, please view the LICENSE
|
9 |
+
* file that was distributed with this source code.
|
10 |
+
*/
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Mustache Template array Loader implementation.
|
14 |
+
*
|
15 |
+
* An ArrayLoader instance loads Mustache Template source by name from an initial array:
|
16 |
+
*
|
17 |
+
* $loader = new ArrayLoader(
|
18 |
+
* 'foo' => '{{ bar }}',
|
19 |
+
* 'baz' => 'Hey {{ qux }}!'
|
20 |
+
* );
|
21 |
+
*
|
22 |
+
* $tpl = $loader->load('foo'); // '{{ bar }}'
|
23 |
+
*
|
24 |
+
* The ArrayLoader is used internally as a partials loader by Mustache_Engine instance when an array of partials
|
25 |
+
* is set. It can also be used as a quick-and-dirty Template loader.
|
26 |
+
*/
|
27 |
+
class Mustache_Loader_ArrayLoader implements Mustache_Loader, Mustache_Loader_MutableLoader
|
28 |
+
{
|
29 |
+
private $templates;
|
30 |
+
|
31 |
+
/**
|
32 |
+
* ArrayLoader constructor.
|
33 |
+
*
|
34 |
+
* @param array $templates Associative array of Template source (default: array())
|
35 |
+
*/
|
36 |
+
public function __construct(array $templates = array())
|
37 |
+
{
|
38 |
+
$this->templates = $templates;
|
39 |
+
}
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Load a Template.
|
43 |
+
*
|
44 |
+
* @throws Mustache_Exception_UnknownTemplateException If a template file is not found.
|
45 |
+
*
|
46 |
+
* @param string $name
|
47 |
+
*
|
48 |
+
* @return string Mustache Template source
|
49 |
+
*/
|
50 |
+
public function load($name)
|
51 |
+
{
|
52 |
+
if (!isset($this->templates[$name])) {
|
53 |
+
throw new Mustache_Exception_UnknownTemplateException($name);
|
54 |
+
}
|
55 |
+
|
56 |
+
return $this->templates[$name];
|
57 |
+
}
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Set an associative array of Template sources for this loader.
|
61 |
+
*
|
62 |
+
* @param array $templates
|
63 |
+
*/
|
64 |
+
public function setTemplates(array $templates)
|
65 |
+
{
|
66 |
+
$this->templates = $templates;
|
67 |
+
}
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Set a Template source by name.
|
71 |
+
*
|
72 |
+
* @param string $name
|
73 |
+
* @param string $template Mustache Template source
|
74 |
+
*/
|
75 |
+
public function setTemplate($name, $template)
|
76 |
+
{
|
77 |
+
$this->templates[$name] = $template;
|
78 |
+
}
|
79 |
+
}
|
lib/php/Mustache/Loader/CascadingLoader.php
ADDED
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of Mustache.php.
|
5 |
+
*
|
6 |
+
* (c) 2010-2015 Justin Hileman
|
7 |
+
*
|
8 |
+
* For the full copyright and license information, please view the LICENSE
|
9 |
+
* file that was distributed with this source code.
|
10 |
+
*/
|
11 |
+
|
12 |
+
/**
|
13 |
+
* A Mustache Template cascading loader implementation, which delegates to other
|
14 |
+
* Loader instances.
|
15 |
+
*/
|
16 |
+
class Mustache_Loader_CascadingLoader implements Mustache_Loader
|
17 |
+
{
|
18 |
+
private $loaders;
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Construct a CascadingLoader with an array of loaders.
|
22 |
+
*
|
23 |
+
* $loader = new Mustache_Loader_CascadingLoader(array(
|
24 |
+
* new Mustache_Loader_InlineLoader(__FILE__, __COMPILER_HALT_OFFSET__),
|
25 |
+
* new Mustache_Loader_FilesystemLoader(__DIR__.'/templates')
|
26 |
+
* ));
|
27 |
+
*
|
28 |
+
* @param Mustache_Loader[] $loaders
|
29 |
+
*/
|
30 |
+
public function __construct(array $loaders = array())
|
31 |
+
{
|
32 |
+
$this->loaders = array();
|
33 |
+
foreach ($loaders as $loader) {
|
34 |
+
$this->addLoader($loader);
|
35 |
+
}
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Add a Loader instance.
|
40 |
+
*
|
41 |
+
* @param Mustache_Loader $loader
|
42 |
+
*/
|
43 |
+
public function addLoader(Mustache_Loader $loader)
|
44 |
+
{
|
45 |
+
$this->loaders[] = $loader;
|
46 |
+
}
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Load a Template by name.
|
50 |
+
*
|
51 |
+
* @throws Mustache_Exception_UnknownTemplateException If a template file is not found.
|
52 |
+
*
|
53 |
+
* @param string $name
|
54 |
+
*
|
55 |
+
* @return string Mustache Template source
|
56 |
+
*/
|
57 |
+
public function load($name)
|
58 |
+
{
|
59 |
+
foreach ($this->loaders as $loader) {
|
60 |
+
try {
|
61 |
+
return $loader->load($name);
|
62 |
+
} catch (Mustache_Exception_UnknownTemplateException $e) {
|
63 |
+
// do nothing, check the next loader.
|
64 |
+
}
|
65 |
+
}
|
66 |
+
|
67 |
+
throw new Mustache_Exception_UnknownTemplateException($name);
|
68 |
+
}
|
69 |
+
}
|
lib/php/Mustache/Loader/FilesystemLoader.php
ADDED
@@ -0,0 +1,124 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of Mustache.php.
|
5 |
+
*
|
6 |
+
* (c) 2010-2015 Justin Hileman
|
7 |
+
*
|
8 |
+
* For the full copyright and license information, please view the LICENSE
|
9 |
+
* file that was distributed with this source code.
|
10 |
+
*/
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Mustache Template filesystem Loader implementation.
|
14 |
+
*
|
15 |
+
* A FilesystemLoader instance loads Mustache Template source from the filesystem by name:
|
16 |
+
*
|
17 |
+
* $loader = new Mustache_Loader_FilesystemLoader(dirname(__FILE__).'/views');
|
18 |
+
* $tpl = $loader->load('foo'); // equivalent to `file_get_contents(dirname(__FILE__).'/views/foo.mustache');
|
19 |
+
*
|
20 |
+
* This is probably the most useful Mustache Loader implementation. It can be used for partials and normal Templates:
|
21 |
+
*
|
22 |
+
* $m = new Mustache(array(
|
23 |
+
* 'loader' => new Mustache_Loader_FilesystemLoader(dirname(__FILE__).'/views'),
|
24 |
+
* 'partials_loader' => new Mustache_Loader_FilesystemLoader(dirname(__FILE__).'/views/partials'),
|
25 |
+
* ));
|
26 |
+
*/
|
27 |
+
class Mustache_Loader_FilesystemLoader implements Mustache_Loader
|
28 |
+
{
|
29 |
+
private $baseDir;
|
30 |
+
private $extension = '.mustache';
|
31 |
+
private $templates = array();
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Mustache filesystem Loader constructor.
|
35 |
+
*
|
36 |
+
* Passing an $options array allows overriding certain Loader options during instantiation:
|
37 |
+
*
|
38 |
+
* $options = array(
|
39 |
+
* // The filename extension used for Mustache templates. Defaults to '.mustache'
|
40 |
+
* 'extension' => '.ms',
|
41 |
+
* );
|
42 |
+
*
|
43 |
+
* @throws Mustache_Exception_RuntimeException if $baseDir does not exist.
|
44 |
+
*
|
45 |
+
* @param string $baseDir Base directory containing Mustache template files.
|
46 |
+
* @param array $options Array of Loader options (default: array())
|
47 |
+
*/
|
48 |
+
public function __construct($baseDir, array $options = array())
|
49 |
+
{
|
50 |
+
$this->baseDir = $baseDir;
|
51 |
+
|
52 |
+
if (strpos($this->baseDir, '://') === false) {
|
53 |
+
$this->baseDir = realpath($this->baseDir);
|
54 |
+
}
|
55 |
+
|
56 |
+
if (!is_dir($this->baseDir)) {
|
57 |
+
throw new Mustache_Exception_RuntimeException(sprintf('FilesystemLoader baseDir must be a directory: %s', $baseDir));
|
58 |
+
}
|
59 |
+
|
60 |
+
if (array_key_exists('extension', $options)) {
|
61 |
+
if (empty($options['extension'])) {
|
62 |
+
$this->extension = '';
|
63 |
+
} else {
|
64 |
+
$this->extension = '.' . ltrim($options['extension'], '.');
|
65 |
+
}
|
66 |
+
}
|
67 |
+
}
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Load a Template by name.
|
71 |
+
*
|
72 |
+
* $loader = new Mustache_Loader_FilesystemLoader(dirname(__FILE__).'/views');
|
73 |
+
* $loader->load('admin/dashboard'); // loads "./views/admin/dashboard.mustache";
|
74 |
+
*
|
75 |
+
* @param string $name
|
76 |
+
*
|
77 |
+
* @return string Mustache Template source
|
78 |
+
*/
|
79 |
+
public function load($name)
|
80 |
+
{
|
81 |
+
if (!isset($this->templates[$name])) {
|
82 |
+
$this->templates[$name] = $this->loadFile($name);
|
83 |
+
}
|
84 |
+
|
85 |
+
return $this->templates[$name];
|
86 |
+
}
|
87 |
+
|
88 |
+
/**
|
89 |
+
* Helper function for loading a Mustache file by name.
|
90 |
+
*
|
91 |
+
* @throws Mustache_Exception_UnknownTemplateException If a template file is not found.
|
92 |
+
*
|
93 |
+
* @param string $name
|
94 |
+
*
|
95 |
+
* @return string Mustache Template source
|
96 |
+
*/
|
97 |
+
protected function loadFile($name)
|
98 |
+
{
|
99 |
+
$fileName = $this->getFileName($name);
|
100 |
+
|
101 |
+
if (!file_exists($fileName)) {
|
102 |
+
throw new Mustache_Exception_UnknownTemplateException($name);
|
103 |
+
}
|
104 |
+
|
105 |
+
return file_get_contents($fileName);
|
106 |
+
}
|
107 |
+
|
108 |
+
/**
|
109 |
+
* Helper function for getting a Mustache template file name.
|
110 |
+
*
|
111 |
+
* @param string $name
|
112 |
+
*
|
113 |
+
* @return string Template file name
|
114 |
+
*/
|
115 |
+
protected function getFileName($name)
|
116 |
+
{
|
117 |
+
$fileName = $this->baseDir . '/' . $name;
|
118 |
+
if (substr($fileName, 0 - strlen($this->extension)) !== $this->extension) {
|
119 |
+
$fileName .= $this->extension;
|
120 |
+
}
|
121 |
+
|
122 |
+
return $fileName;
|
123 |
+
}
|
124 |
+
}
|
lib/php/Mustache/Loader/InlineLoader.php
ADDED
@@ -0,0 +1,123 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of Mustache.php.
|
5 |
+
*
|
6 |
+
* (c) 2010-2015 Justin Hileman
|
7 |
+
*
|
8 |
+
* For the full copyright and license information, please view the LICENSE
|
9 |
+
* file that was distributed with this source code.
|
10 |
+
*/
|
11 |
+
|
12 |
+
/**
|
13 |
+
* A Mustache Template loader for inline templates.
|
14 |
+
*
|
15 |
+
* With the InlineLoader, templates can be defined at the end of any PHP source
|
16 |
+
* file:
|
17 |
+
*
|
18 |
+
* $loader = new Mustache_Loader_InlineLoader(__FILE__, __COMPILER_HALT_OFFSET__);
|
19 |
+
* $hello = $loader->load('hello');
|
20 |
+
* $goodbye = $loader->load('goodbye');
|
21 |
+
*
|
22 |
+
* __halt_compiler();
|
23 |
+
*
|
24 |
+
* @@ hello
|
25 |
+
* Hello, {{ planet }}!
|
26 |
+
*
|
27 |
+
* @@ goodbye
|
28 |
+
* Goodbye, cruel {{ planet }}
|
29 |
+
*
|
30 |
+
* Templates are deliniated by lines containing only `@@ name`.
|
31 |
+
*
|
32 |
+
* The InlineLoader is well-suited to micro-frameworks such as Silex:
|
33 |
+
*
|
34 |
+
* $app->register(new MustacheServiceProvider, array(
|
35 |
+
* 'mustache.loader' => new Mustache_Loader_InlineLoader(__FILE__, __COMPILER_HALT_OFFSET__)
|
36 |
+
* ));
|
37 |
+
*
|
38 |
+
* $app->get('/{name}', function ($name) use ($app) {
|
39 |
+
* return $app['mustache']->render('hello', compact('name'));
|
40 |
+
* })
|
41 |
+
* ->value('name', 'world');
|
42 |
+
*
|
43 |
+
* // ...
|
44 |
+
*
|
45 |
+
* __halt_compiler();
|
46 |
+
*
|
47 |
+
* @@ hello
|
48 |
+
* Hello, {{ name }}!
|
49 |
+
*/
|
50 |
+
class Mustache_Loader_InlineLoader implements Mustache_Loader
|
51 |
+
{
|
52 |
+
protected $fileName;
|
53 |
+
protected $offset;
|
54 |
+
protected $templates;
|
55 |
+
|
56 |
+
/**
|
57 |
+
* The InlineLoader requires a filename and offset to process templates.
|
58 |
+
*
|
59 |
+
* The magic constants `__FILE__` and `__COMPILER_HALT_OFFSET__` are usually
|
60 |
+
* perfectly suited to the job:
|
61 |
+
*
|
62 |
+
* $loader = new Mustache_Loader_InlineLoader(__FILE__, __COMPILER_HALT_OFFSET__);
|
63 |
+
*
|
64 |
+
* Note that this only works if the loader is instantiated inside the same
|
65 |
+
* file as the inline templates. If the templates are located in another
|
66 |
+
* file, it would be necessary to manually specify the filename and offset.
|
67 |
+
*
|
68 |
+
* @param string $fileName The file to parse for inline templates
|
69 |
+
* @param int $offset A string offset for the start of the templates.
|
70 |
+
* This usually coincides with the `__halt_compiler`
|
71 |
+
* call, and the `__COMPILER_HALT_OFFSET__`.
|
72 |
+
*/
|
73 |
+
public function __construct($fileName, $offset)
|
74 |
+
{
|
75 |
+
if (!is_file($fileName)) {
|
76 |
+
throw new Mustache_Exception_InvalidArgumentException('InlineLoader expects a valid filename.');
|
77 |
+
}
|
78 |
+
|
79 |
+
if (!is_int($offset) || $offset < 0) {
|
80 |
+
throw new Mustache_Exception_InvalidArgumentException('InlineLoader expects a valid file offset.');
|
81 |
+
}
|
82 |
+
|
83 |
+
$this->fileName = $fileName;
|
84 |
+
$this->offset = $offset;
|
85 |
+
}
|
86 |
+
|
87 |
+
/**
|
88 |
+
* Load a Template by name.
|
89 |
+
*
|
90 |
+
* @throws Mustache_Exception_UnknownTemplateException If a template file is not found.
|
91 |
+
*
|
92 |
+
* @param string $name
|
93 |
+
*
|
94 |
+
* @return string Mustache Template source
|
95 |
+
*/
|
96 |
+
public function load($name)
|
97 |
+
{
|
98 |
+
$this->loadTemplates();
|
99 |
+
|
100 |
+
if (!array_key_exists($name, $this->templates)) {
|
101 |
+
throw new Mustache_Exception_UnknownTemplateException($name);
|
102 |
+
}
|
103 |
+
|
104 |
+
return $this->templates[$name];
|
105 |
+
}
|
106 |
+
|
107 |
+
/**
|
108 |
+
* Parse and load templates from the end of a source file.
|
109 |
+
*/
|
110 |
+
protected function loadTemplates()
|
111 |
+
{
|
112 |
+
if ($this->templates === null) {
|
113 |
+
$this->templates = array();
|
114 |
+
$data = file_get_contents($this->fileName, false, null, $this->offset);
|
115 |
+
foreach (preg_split("/^@@(?= [\w\d\.]+$)/m", $data, -1) as $chunk) {
|
116 |
+
if (trim($chunk)) {
|
117 |
+
list($name, $content) = explode("\n", $chunk, 2);
|
118 |
+
$this->templates[trim($name)] = trim($content);
|
119 |
+
}
|
120 |
+
}
|
121 |
+
}
|
122 |
+
}
|
123 |
+
}
|
lib/php/Mustache/Loader/MutableLoader.php
ADDED
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of Mustache.php.
|
5 |
+
*
|
6 |
+
* (c) 2010-2015 Justin Hileman
|
7 |
+
*
|
8 |
+
* For the full copyright and license information, please view the LICENSE
|
9 |
+
* file that was distributed with this source code.
|
10 |
+
*/
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Mustache Template mutable Loader interface.
|
14 |
+
*/
|
15 |
+
interface Mustache_Loader_MutableLoader
|
16 |
+
{
|
17 |
+
/**
|
18 |
+
* Set an associative array of Template sources for this loader.
|
19 |
+
*
|
20 |
+
* @param array $templates
|
21 |
+
*/
|
22 |
+
public function setTemplates(array $templates);
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Set a Template source by name.
|
26 |
+
*
|
27 |
+
* @param string $name
|
28 |
+
* @param string $template Mustache Template source
|
29 |
+
*/
|
30 |
+
public function setTemplate($name, $template);
|
31 |
+
}
|
lib/php/Mustache/Loader/StringLoader.php
ADDED
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of Mustache.php.
|
5 |
+
*
|
6 |
+
* (c) 2010-2015 Justin Hileman
|
7 |
+
*
|
8 |
+
* For the full copyright and license information, please view the LICENSE
|
9 |
+
* file that was distributed with this source code.
|
10 |
+
*/
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Mustache Template string Loader implementation.
|
14 |
+
*
|
15 |
+
* A StringLoader instance is essentially a noop. It simply passes the 'name' argument straight through:
|
16 |
+
*
|
17 |
+
* $loader = new StringLoader;
|
18 |
+
* $tpl = $loader->load('{{ foo }}'); // '{{ foo }}'
|
19 |
+
*
|
20 |
+
* This is the default Template Loader instance used by Mustache:
|
21 |
+
*
|
22 |
+
* $m = new Mustache;
|
23 |
+
* $tpl = $m->loadTemplate('{{ foo }}');
|
24 |
+
* echo $tpl->render(array('foo' => 'bar')); // "bar"
|
25 |
+
*/
|
26 |
+
class Mustache_Loader_StringLoader implements Mustache_Loader
|
27 |
+
{
|
28 |
+
/**
|
29 |
+
* Load a Template by source.
|
30 |
+
*
|
31 |
+
* @param string $name Mustache Template source
|
32 |
+
*
|
33 |
+
* @return string Mustache Template source
|
34 |
+
*/
|
35 |
+
public function load($name)
|
36 |
+
{
|
37 |
+
return $name;
|
38 |
+
}
|
39 |
+
}
|
lib/php/Mustache/Logger.php
ADDED
@@ -0,0 +1,126 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of Mustache.php.
|
5 |
+
*
|
6 |
+
* (c) 2010-2015 Justin Hileman
|
7 |
+
*
|
8 |
+
* For the full copyright and license information, please view the LICENSE
|
9 |
+
* file that was distributed with this source code.
|
10 |
+
*/
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Describes a Mustache logger instance.
|
14 |
+
*
|
15 |
+
* This is identical to the Psr\Log\LoggerInterface.
|
16 |
+
*
|
17 |
+
* The message MUST be a string or object implementing __toString().
|
18 |
+
*
|
19 |
+
* The message MAY contain placeholders in the form: {foo} where foo
|
20 |
+
* will be replaced by the context data in key "foo".
|
21 |
+
*
|
22 |
+
* The context array can contain arbitrary data, the only assumption that
|
23 |
+
* can be made by implementors is that if an Exception instance is given
|
24 |
+
* to produce a stack trace, it MUST be in a key named "exception".
|
25 |
+
*
|
26 |
+
* See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md
|
27 |
+
* for the full interface specification.
|
28 |
+
*/
|
29 |
+
interface Mustache_Logger
|
30 |
+
{
|
31 |
+
/**
|
32 |
+
* Psr\Log compatible log levels.
|
33 |
+
*/
|
34 |
+
const EMERGENCY = 'emergency';
|
35 |
+
const ALERT = 'alert';
|
36 |
+
const CRITICAL = 'critical';
|
37 |
+
const ERROR = 'error';
|
38 |
+
const WARNING = 'warning';
|
39 |
+
const NOTICE = 'notice';
|
40 |
+
const INFO = 'info';
|
41 |
+
const DEBUG = 'debug';
|
42 |
+
|
43 |
+
/**
|
44 |
+
* System is unusable.
|
45 |
+
*
|
46 |
+
* @param string $message
|
47 |
+
* @param array $context
|
48 |
+
*/
|
49 |
+
public function emergency($message, array $context = array());
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Action must be taken immediately.
|
53 |
+
*
|
54 |
+
* Example: Entire website down, database unavailable, etc. This should
|
55 |
+
* trigger the SMS alerts and wake you up.
|
56 |
+
*
|
57 |
+
* @param string $message
|
58 |
+
* @param array $context
|
59 |
+
*/
|
60 |
+
public function alert($message, array $context = array());
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Critical conditions.
|
64 |
+
*
|
65 |
+
* Example: Application component unavailable, unexpected exception.
|
66 |
+
*
|
67 |
+
* @param string $message
|
68 |
+
* @param array $context
|
69 |
+
*/
|
70 |
+
public function critical($message, array $context = array());
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Runtime errors that do not require immediate action but should typically
|
74 |
+
* be logged and monitored.
|
75 |
+
*
|
76 |
+
* @param string $message
|
77 |
+
* @param array $context
|
78 |
+
*/
|
79 |
+
public function error($message, array $context = array());
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Exceptional occurrences that are not errors.
|
83 |
+
*
|
84 |
+
* Example: Use of deprecated APIs, poor use of an API, undesirable things
|
85 |
+
* that are not necessarily wrong.
|
86 |
+
*
|
87 |
+
* @param string $message
|
88 |
+
* @param array $context
|
89 |
+
*/
|
90 |
+
public function warning($message, array $context = array());
|
91 |
+
|
92 |
+
/**
|
93 |
+
* Normal but significant events.
|
94 |
+
*
|
95 |
+
* @param string $message
|
96 |
+
* @param array $context
|
97 |
+
*/
|
98 |
+
public function notice($message, array $context = array());
|
99 |
+
|
100 |
+
/**
|
101 |
+
* Interesting events.
|
102 |
+
*
|
103 |
+
* Example: User logs in, SQL logs.
|
104 |
+
*
|
105 |
+
* @param string $message
|
106 |
+
* @param array $context
|
107 |
+
*/
|
108 |
+
public function info($message, array $context = array());
|
109 |
+
|
110 |
+
/**
|
111 |
+
* Detailed debug information.
|
112 |
+
*
|
113 |
+
* @param string $message
|
114 |
+
* @param array $context
|
115 |
+
*/
|
116 |
+
public function debug($message, array $context = array());
|
117 |
+
|
118 |
+
/**
|
119 |
+
* Logs with an arbitrary level.
|
120 |
+
*
|
121 |
+
* @param mixed $level
|
122 |
+
* @param string $message
|
123 |
+
* @param array $context
|
124 |
+
*/
|
125 |
+
public function log($level, $message, array $context = array());
|
126 |
+
}
|
lib/php/Mustache/Logger/AbstractLogger.php
ADDED
@@ -0,0 +1,121 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of Mustache.php.
|
5 |
+
*
|
6 |
+
* (c) 2010-2015 Justin Hileman
|
7 |
+
*
|
8 |
+
* For the full copyright and license information, please view the LICENSE
|
9 |
+
* file that was distributed with this source code.
|
10 |
+
*/
|
11 |
+
|
12 |
+
/**
|
13 |
+
* This is a simple Logger implementation that other Loggers can inherit from.
|
14 |
+
*
|
15 |
+
* This is identical to the Psr\Log\AbstractLogger.
|
16 |
+
*
|
17 |
+
* It simply delegates all log-level-specific methods to the `log` method to
|
18 |
+
* reduce boilerplate code that a simple Logger that does the same thing with
|
19 |
+
* messages regardless of the error level has to implement.
|
20 |
+
*/
|
21 |
+
abstract class Mustache_Logger_AbstractLogger implements Mustache_Logger
|
22 |
+
{
|
23 |
+
/**
|
24 |
+
* System is unusable.
|
25 |
+
*
|
26 |
+
* @param string $message
|
27 |
+
* @param array $context
|
28 |
+
*/
|
29 |
+
public function emergency($message, array $context = array())
|
30 |
+
{
|
31 |
+
$this->log(Mustache_Logger::EMERGENCY, $message, $context);
|
32 |
+
}
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Action must be taken immediately.
|
36 |
+
*
|
37 |
+
* Example: Entire website down, database unavailable, etc. This should
|
38 |
+
* trigger the SMS alerts and wake you up.
|
39 |
+
*
|
40 |
+
* @param string $message
|
41 |
+
* @param array $context
|
42 |
+
*/
|
43 |
+
public function alert($message, array $context = array())
|
44 |
+
{
|
45 |
+
$this->log(Mustache_Logger::ALERT, $message, $context);
|
46 |
+
}
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Critical conditions.
|
50 |
+
*
|
51 |
+
* Example: Application component unavailable, unexpected exception.
|
52 |
+
*
|
53 |
+
* @param string $message
|
54 |
+
* @param array $context
|
55 |
+
*/
|
56 |
+
public function critical($message, array $context = array())
|
57 |
+
{
|
58 |
+
$this->log(Mustache_Logger::CRITICAL, $message, $context);
|
59 |
+
}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Runtime errors that do not require immediate action but should typically
|
63 |
+
* be logged and monitored.
|
64 |
+
*
|
65 |
+
* @param string $message
|
66 |
+
* @param array $context
|
67 |
+
*/
|
68 |
+
public function error($message, array $context = array())
|
69 |
+
{
|
70 |
+
$this->log(Mustache_Logger::ERROR, $message, $context);
|
71 |
+
}
|
72 |
+
|
73 |
+
/**
|
74 |
+
* Exceptional occurrences that are not errors.
|
75 |
+
*
|
76 |
+
* Example: Use of deprecated APIs, poor use of an API, undesirable things
|
77 |
+
* that are not necessarily wrong.
|
78 |
+
*
|
79 |
+
* @param string $message
|
80 |
+
* @param array $context
|
81 |
+
*/
|
82 |
+
public function warning($message, array $context = array())
|
83 |
+
{
|
84 |
+
$this->log(Mustache_Logger::WARNING, $message, $context);
|
85 |
+
}
|
86 |
+
|
87 |
+
/**
|
88 |
+
* Normal but significant events.
|
89 |
+
*
|
90 |
+
* @param string $message
|
91 |
+
* @param array $context
|
92 |
+
*/
|
93 |
+
public function notice($message, array $context = array())
|
94 |
+
{
|
95 |
+
$this->log(Mustache_Logger::NOTICE, $message, $context);
|
96 |
+
}
|
97 |
+
|
98 |
+
/**
|
99 |
+
* Interesting events.
|
100 |
+
*
|
101 |
+
* Example: User logs in, SQL logs.
|
102 |
+
*
|
103 |
+
* @param string $message
|
104 |
+
* @param array $context
|
105 |
+
*/
|
106 |
+
public function info($message, array $context = array())
|
107 |
+
{
|
108 |
+
$this->log(Mustache_Logger::INFO, $message, $context);
|
109 |
+
}
|
110 |
+
|
111 |
+
/**
|
112 |
+
* Detailed debug information.
|
113 |
+
*
|
114 |
+
* @param string $message
|
115 |
+
* @param array $context
|
116 |
+
*/
|
117 |
+
public function debug($message, array $context = array())
|
118 |
+
{
|
119 |
+
$this->log(Mustache_Logger::DEBUG, $message, $context);
|
120 |
+
}
|
121 |
+
}
|
lib/php/Mustache/Logger/StreamLogger.php
ADDED
@@ -0,0 +1,194 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of Mustache.php.
|
5 |
+
*
|
6 |
+
* (c) 2010-2015 Justin Hileman
|
7 |
+
*
|
8 |
+
* For the full copyright and license information, please view the LICENSE
|
9 |
+
* file that was distributed with this source code.
|
10 |
+
*/
|
11 |
+
|
12 |
+
/**
|
13 |
+
* A Mustache Stream Logger.
|
14 |
+
*
|
15 |
+
* The Stream Logger wraps a file resource instance (such as a stream) or a
|
16 |
+
* stream URL. All log messages over the threshold level will be appended to
|
17 |
+
* this stream.
|
18 |
+
*
|
19 |
+
* Hint: Try `php://stderr` for your stream URL.
|
20 |
+
*/
|
21 |
+
class Mustache_Logger_StreamLogger extends Mustache_Logger_AbstractLogger
|
22 |
+
{
|
23 |
+
protected static $levels = array(
|
24 |
+
self::DEBUG => 100,
|
25 |
+
self::INFO => 200,
|
26 |
+
self::NOTICE => 250,
|
27 |
+
self::WARNING => 300,
|
28 |
+
self::ERROR => 400,
|
29 |
+
self::CRITICAL => 500,
|
30 |
+
self::ALERT => 550,
|
31 |
+
self::EMERGENCY => 600,
|
32 |
+
);
|
33 |
+
|
34 |
+
protected $level;
|
35 |
+
protected $stream = null;
|
36 |
+
protected $url = null;
|
37 |
+
|
38 |
+
/**
|
39 |
+
* @throws InvalidArgumentException if the logging level is unknown.
|
40 |
+
*
|
41 |
+
* @param resource|string $stream Resource instance or URL
|
42 |
+
* @param int $level The minimum logging level at which this handler will be triggered
|
43 |
+
*/
|
44 |
+
public function __construct($stream, $level = Mustache_Logger::ERROR)
|
45 |
+
{
|
46 |
+
$this->setLevel($level);
|
47 |
+
|
48 |
+
if (is_resource($stream)) {
|
49 |
+
$this->stream = $stream;
|
50 |
+
} else {
|
51 |
+
$this->url = $stream;
|
52 |
+
}
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Close stream resources.
|
57 |
+
*/
|
58 |
+
public function __destruct()
|
59 |
+
{
|
60 |
+
if (is_resource($this->stream)) {
|
61 |
+
fclose($this->stream);
|
62 |
+
}
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Set the minimum logging level.
|
67 |
+
*
|
68 |
+
* @throws Mustache_Exception_InvalidArgumentException if the logging level is unknown.
|
69 |
+
*
|
70 |
+
* @param int $level The minimum logging level which will be written
|
71 |
+
*/
|
72 |
+
public function setLevel($level)
|
73 |
+
{
|
74 |
+
if (!array_key_exists($level, self::$levels)) {
|
75 |
+
throw new Mustache_Exception_InvalidArgumentException(sprintf('Unexpected logging level: %s', $level));
|
76 |
+
}
|
77 |
+
|
78 |
+
$this->level = $level;
|
79 |
+
}
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Get the current minimum logging level.
|
83 |
+
*
|
84 |
+
* @return int
|
85 |
+
*/
|
86 |
+
public function getLevel()
|
87 |
+
{
|
88 |
+
return $this->level;
|
89 |
+
}
|
90 |
+
|
91 |
+
/**
|
92 |
+
* Logs with an arbitrary level.
|
93 |
+
*
|
94 |
+
* @throws Mustache_Exception_InvalidArgumentException if the logging level is unknown.
|
95 |
+
*
|
96 |
+
* @param mixed $level
|
97 |
+
* @param string $message
|
98 |
+
* @param array $context
|
99 |
+
*/
|
100 |
+
public function log($level, $message, array $context = array())
|
101 |
+
{
|
102 |
+
if (!array_key_exists($level, self::$levels)) {
|
103 |
+
throw new Mustache_Exception_InvalidArgumentException(sprintf('Unexpected logging level: %s', $level));
|
104 |
+
}
|
105 |
+
|
106 |
+
if (self::$levels[$level] >= self::$levels[$this->level]) {
|
107 |
+
$this->writeLog($level, $message, $context);
|
108 |
+
}
|
109 |
+
}
|
110 |
+
|
111 |
+
/**
|
112 |
+
* Write a record to the log.
|
113 |
+
*
|
114 |
+
* @throws Mustache_Exception_LogicException If neither a stream resource nor url is present.
|
115 |
+
* @throws Mustache_Exception_RuntimeException If the stream url cannot be opened.
|
116 |
+
*
|
117 |
+
* @param int $level The logging level
|
118 |
+
* @param string $message The log message
|
119 |
+
* @param array $context The log context
|
120 |
+
*/
|
121 |
+
protected function writeLog($level, $message, array $context = array())
|
122 |
+
{
|
123 |
+
if (!is_resource($this->stream)) {
|
124 |
+
if (!isset($this->url)) {
|
125 |
+
throw new Mustache_Exception_LogicException('Missing stream url, the stream can not be opened. This may be caused by a premature call to close().');
|
126 |
+
}
|
127 |
+
|
128 |
+
$this->stream = fopen($this->url, 'a');
|
129 |
+
if (!is_resource($this->stream)) {
|
130 |
+
// @codeCoverageIgnoreStart
|
131 |
+
throw new Mustache_Exception_RuntimeException(sprintf('The stream or file "%s" could not be opened.', $this->url));
|
132 |
+
// @codeCoverageIgnoreEnd
|
133 |
+
}
|
134 |
+
}
|
135 |
+
|
136 |
+
fwrite($this->stream, self::formatLine($level, $message, $context));
|
137 |
+
}
|
138 |
+
|
139 |
+
/**
|
140 |
+
* Gets the name of the logging level.
|
141 |
+
*
|
142 |
+
* @throws InvalidArgumentException if the logging level is unknown.
|
143 |
+
*
|
144 |
+
* @param int $level
|
145 |
+
*
|
146 |
+
* @return string
|
147 |
+
*/
|
148 |
+
protected static function getLevelName($level)
|
149 |
+
{
|
150 |
+
return strtoupper($level);
|
151 |
+
}
|
152 |
+
|
153 |
+
/**
|
154 |
+
* Format a log line for output.
|
155 |
+
*
|
156 |
+
* @param int $level The logging level
|
157 |
+
* @param string $message The log message
|
158 |
+
* @param array $context The log context
|
159 |
+
*
|
160 |
+
* @return string
|
161 |
+
*/
|
162 |
+
protected static function formatLine($level, $message, array $context = array())
|
163 |
+
{
|
164 |
+
return sprintf(
|
165 |
+
"%s: %s\n",
|
166 |
+
self::getLevelName($level),
|
167 |
+
self::interpolateMessage($message, $context)
|
168 |
+
);
|
169 |
+
}
|
170 |
+
|
171 |
+
/**
|
172 |
+
* Interpolate context values into the message placeholders.
|
173 |
+
*
|
174 |
+
* @param string $message
|
175 |
+
* @param array $context
|
176 |
+
*
|
177 |
+
* @return string
|
178 |
+
*/
|
179 |
+
protected static function interpolateMessage($message, array $context = array())
|
180 |
+
{
|
181 |
+
if (strpos($message, '{') === false) {
|
182 |
+
return $message;
|
183 |
+
}
|
184 |
+
|
185 |
+
// build a replacement array with braces around the context keys
|
186 |
+
$replace = array();
|
187 |
+
foreach ($context as $key => $val) {
|
188 |
+
$replace['{' . $key . '}'] = $val;
|
189 |
+
}
|
190 |
+
|
191 |
+
// interpolate replacement values into the the message and return
|
192 |
+
return strtr($message, $replace);
|
193 |
+
}
|
194 |
+
}
|
lib/php/Mustache/Parser.php
ADDED
@@ -0,0 +1,317 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of Mustache.php.
|
5 |
+
*
|
6 |
+
* (c) 2010-2015 Justin Hileman
|
7 |
+
*
|
8 |
+
* For the full copyright and license information, please view the LICENSE
|
9 |
+
* file that was distributed with this source code.
|
10 |
+
*/
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Mustache Parser class.
|
14 |
+
*
|
15 |
+
* This class is responsible for turning a set of Mustache tokens into a parse tree.
|
16 |
+
*/
|
17 |
+
class Mustache_Parser
|
18 |
+
{
|
19 |
+
private $lineNum;
|
20 |
+
private $lineTokens;
|
21 |
+
private $pragmas;
|
22 |
+
private $defaultPragmas = array();
|
23 |
+
|
24 |
+
private $pragmaFilters;
|
25 |
+
private $pragmaBlocks;
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Process an array of Mustache tokens and convert them into a parse tree.
|
29 |
+
*
|
30 |
+
* @param array $tokens Set of Mustache tokens
|
31 |
+
*
|
32 |
+
* @return array Mustache token parse tree
|
33 |
+
*/
|
34 |
+
public function parse(array $tokens = array())
|
35 |
+
{
|
36 |
+
$this->lineNum = -1;
|
37 |
+
$this->lineTokens = 0;
|
38 |
+
$this->pragmas = $this->defaultPragmas;
|
39 |
+
|
40 |
+
$this->pragmaFilters = isset($this->pragmas[Mustache_Engine::PRAGMA_FILTERS]);
|
41 |
+
$this->pragmaBlocks = isset($this->pragmas[Mustache_Engine::PRAGMA_BLOCKS]);
|
42 |
+
|
43 |
+
return $this->buildTree($tokens);
|
44 |
+
}
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Enable pragmas across all templates, regardless of the presence of pragma
|
48 |
+
* tags in the individual templates.
|
49 |
+
*
|
50 |
+
* @internal Users should set global pragmas in Mustache_Engine, not here :)
|
51 |
+
*
|
52 |
+
* @param string[] $pragmas
|
53 |
+
*/
|
54 |
+
public function setPragmas(array $pragmas)
|
55 |
+
{
|
56 |
+
$this->pragmas = array();
|
57 |
+
foreach ($pragmas as $pragma) {
|
58 |
+
$this->enablePragma($pragma);
|
59 |
+
}
|
60 |
+
$this->defaultPragmas = $this->pragmas;
|
61 |
+
}
|
62 |
+
|
63 |
+
/**
|
64 |
+
* Helper method for recursively building a parse tree.
|
65 |
+
*
|
66 |
+
* @throws Mustache_Exception_SyntaxException when nesting errors or mismatched section tags are encountered.
|
67 |
+
*
|
68 |
+
* @param array &$tokens Set of Mustache tokens
|
69 |
+
* @param array $parent Parent token (default: null)
|
70 |
+
*
|
71 |
+
* @return array Mustache Token parse tree
|
72 |
+
*/
|
73 |
+
private function buildTree(array &$tokens, array $parent = null)
|
74 |
+
{
|
75 |
+
$nodes = array();
|
76 |
+
|
77 |
+
while (!empty($tokens)) {
|
78 |
+
$token = array_shift($tokens);
|
79 |
+
|
80 |
+
if ($token[Mustache_Tokenizer::LINE] === $this->lineNum) {
|
81 |
+
$this->lineTokens++;
|
82 |
+
} else {
|
83 |
+
$this->lineNum = $token[Mustache_Tokenizer::LINE];
|
84 |
+
$this->lineTokens = 0;
|
85 |
+
}
|
86 |
+
|
87 |
+
if ($this->pragmaFilters && isset($token[Mustache_Tokenizer::NAME])) {
|
88 |
+
list($name, $filters) = $this->getNameAndFilters($token[Mustache_Tokenizer::NAME]);
|
89 |
+
if (!empty($filters)) {
|
90 |
+
$token[Mustache_Tokenizer::NAME] = $name;
|
91 |
+
$token[Mustache_Tokenizer::FILTERS] = $filters;
|
92 |
+
}
|
93 |
+
}
|
94 |
+
|
95 |
+
switch ($token[Mustache_Tokenizer::TYPE]) {
|
96 |
+
case Mustache_Tokenizer::T_DELIM_CHANGE:
|
97 |
+
$this->checkIfTokenIsAllowedInParent($parent, $token);
|
98 |
+
$this->clearStandaloneLines($nodes, $tokens);
|
99 |
+
break;
|
100 |
+
|
101 |
+
case Mustache_Tokenizer::T_SECTION:
|
102 |
+
case Mustache_Tokenizer::T_INVERTED:
|
103 |
+
$this->checkIfTokenIsAllowedInParent($parent, $token);
|
104 |
+
$this->clearStandaloneLines($nodes, $tokens);
|
105 |
+
$nodes[] = $this->buildTree($tokens, $token);
|
106 |
+
break;
|
107 |
+
|
108 |
+
case Mustache_Tokenizer::T_END_SECTION:
|
109 |
+
if (!isset($parent)) {
|
110 |
+
$msg = sprintf(
|
111 |
+
'Unexpected closing tag: /%s on line %d',
|
112 |
+
$token[Mustache_Tokenizer::NAME],
|
113 |
+
$token[Mustache_Tokenizer::LINE]
|
114 |
+
);
|
115 |
+
throw new Mustache_Exception_SyntaxException($msg, $token);
|
116 |
+
}
|
117 |
+
|
118 |
+
if ($token[Mustache_Tokenizer::NAME] !== $parent[Mustache_Tokenizer::NAME]) {
|
119 |
+
$msg = sprintf(
|
120 |
+
'Nesting error: %s (on line %d) vs. %s (on line %d)',
|
121 |
+
$parent[Mustache_Tokenizer::NAME],
|
122 |
+
$parent[Mustache_Tokenizer::LINE],
|
123 |
+
$token[Mustache_Tokenizer::NAME],
|
124 |
+
$token[Mustache_Tokenizer::LINE]
|
125 |
+
);
|
126 |
+
throw new Mustache_Exception_SyntaxException($msg, $token);
|
127 |
+
}
|
128 |
+
|
129 |
+
$this->clearStandaloneLines($nodes, $tokens);
|
130 |
+
$parent[Mustache_Tokenizer::END] = $token[Mustache_Tokenizer::INDEX];
|
131 |
+
$parent[Mustache_Tokenizer::NODES] = $nodes;
|
132 |
+
|
133 |
+
return $parent;
|
134 |
+
|
135 |
+
case Mustache_Tokenizer::T_PARTIAL:
|
136 |
+
$this->checkIfTokenIsAllowedInParent($parent, $token);
|
137 |
+
//store the whitespace prefix for laters!
|
138 |
+
if ($indent = $this->clearStandaloneLines($nodes, $tokens)) {
|
139 |
+
$token[Mustache_Tokenizer::INDENT] = $indent[Mustache_Tokenizer::VALUE];
|
140 |
+
}
|
141 |
+
$nodes[] = $token;
|
142 |
+
break;
|
143 |
+
|
144 |
+
case Mustache_Tokenizer::T_PARENT:
|
145 |
+
$this->checkIfTokenIsAllowedInParent($parent, $token);
|
146 |
+
$nodes[] = $this->buildTree($tokens, $token);
|
147 |
+
break;
|
148 |
+
|
149 |
+
case Mustache_Tokenizer::T_BLOCK_VAR:
|
150 |
+
if ($this->pragmaBlocks) {
|
151 |
+
// BLOCKS pragma is enabled, let's do this!
|
152 |
+
if ($parent[Mustache_Tokenizer::TYPE] === Mustache_Tokenizer::T_PARENT) {
|
153 |
+
$token[Mustache_Tokenizer::TYPE] = Mustache_Tokenizer::T_BLOCK_ARG;
|
154 |
+
}
|
155 |
+
$this->clearStandaloneLines($nodes, $tokens);
|
156 |
+
$nodes[] = $this->buildTree($tokens, $token);
|
157 |
+
} else {
|
158 |
+
// pretend this was just a normal "escaped" token...
|
159 |
+
$token[Mustache_Tokenizer::TYPE] = Mustache_Tokenizer::T_ESCAPED;
|
160 |
+
// TODO: figure out how to figure out if there was a space after this dollar:
|
161 |
+
$token[Mustache_Tokenizer::NAME] = '$' . $token[Mustache_Tokenizer::NAME];
|
162 |
+
$nodes[] = $token;
|
163 |
+
}
|
164 |
+
break;
|
165 |
+
|
166 |
+
case Mustache_Tokenizer::T_PRAGMA:
|
167 |
+
$this->enablePragma($token[Mustache_Tokenizer::NAME]);
|
168 |
+
// no break
|
169 |
+
|
170 |
+
case Mustache_Tokenizer::T_COMMENT:
|
171 |
+
$this->clearStandaloneLines($nodes, $tokens);
|
172 |
+
$nodes[] = $token;
|
173 |
+
break;
|
174 |
+
|
175 |
+
default:
|
176 |
+
$nodes[] = $token;
|
177 |
+
break;
|
178 |
+
}
|
179 |
+
}
|
180 |
+
|
181 |
+
if (isset($parent)) {
|
182 |
+
$msg = sprintf(
|
183 |
+
'Missing closing tag: %s opened on line %d',
|
184 |
+
$parent[Mustache_Tokenizer::NAME],
|
185 |
+
$parent[Mustache_Tokenizer::LINE]
|
186 |
+
);
|
187 |
+
throw new Mustache_Exception_SyntaxException($msg, $parent);
|
188 |
+
}
|
189 |
+
|
190 |
+
return $nodes;
|
191 |
+
}
|
192 |
+
|
193 |
+
/**
|
194 |
+
* Clear standalone line tokens.
|
195 |
+
*
|
196 |
+
* Returns a whitespace token for indenting partials, if applicable.
|
197 |
+
*
|
198 |
+
* @param array $nodes Parsed nodes.
|
199 |
+
* @param array $tokens Tokens to be parsed.
|
200 |
+
*
|
201 |
+
* @return array|null Resulting indent token, if any.
|
202 |
+
*/
|
203 |
+
private function clearStandaloneLines(array &$nodes, array &$tokens)
|
204 |
+
{
|
205 |
+
if ($this->lineTokens > 1) {
|
206 |
+
// this is the third or later node on this line, so it can't be standalone
|
207 |
+
return;
|
208 |
+
}
|
209 |
+
|
210 |
+
$prev = null;
|
211 |
+
if ($this->lineTokens === 1) {
|
212 |
+
// this is the second node on this line, so it can't be standalone
|
213 |
+
// unless the previous node is whitespace.
|
214 |
+
if ($prev = end($nodes)) {
|
215 |
+
if (!$this->tokenIsWhitespace($prev)) {
|
216 |
+
return;
|
217 |
+
}
|
218 |
+
}
|
219 |
+
}
|
220 |
+
|
221 |
+
if ($next = reset($tokens)) {
|
222 |
+
// If we're on a new line, bail.
|
223 |
+
if ($next[Mustache_Tokenizer::LINE] !== $this->lineNum) {
|
224 |
+
return;
|
225 |
+
}
|
226 |
+
|
227 |
+
// If the next token isn't whitespace, bail.
|
228 |
+
if (!$this->tokenIsWhitespace($next)) {
|
229 |
+
return;
|
230 |
+
}
|
231 |
+
|
232 |
+
if (count($tokens) !== 1) {
|
233 |
+
// Unless it's the last token in the template, the next token
|
234 |
+
// must end in newline for this to be standalone.
|
235 |
+
if (substr($next[Mustache_Tokenizer::VALUE], -1) !== "\n") {
|
236 |
+
return;
|
237 |
+
}
|
238 |
+
}
|
239 |
+
|
240 |
+
// Discard the whitespace suffix
|
241 |
+
array_shift($tokens);
|
242 |
+
}
|
243 |
+
|
244 |
+
if ($prev) {
|
245 |
+
// Return the whitespace prefix, if any
|
246 |
+
return array_pop($nodes);
|
247 |
+
}
|
248 |
+
}
|
249 |
+
|
250 |
+
/**
|
251 |
+
* Check whether token is a whitespace token.
|
252 |
+
*
|
253 |
+
* True if token type is T_TEXT and value is all whitespace characters.
|
254 |
+
*
|
255 |
+
* @param array $token
|
256 |
+
*
|
257 |
+
* @return bool True if token is a whitespace token
|
258 |
+
*/
|
259 |
+
private function tokenIsWhitespace(array $token)
|
260 |
+
{
|
261 |
+
if ($token[Mustache_Tokenizer::TYPE] === Mustache_Tokenizer::T_TEXT) {
|
262 |
+
return preg_match('/^\s*$/', $token[Mustache_Tokenizer::VALUE]);
|
263 |
+
}
|
264 |
+
|
265 |
+
return false;
|
266 |
+
}
|
267 |
+
|
268 |
+
/**
|
269 |
+
* Check whether a token is allowed inside a parent tag.
|
270 |
+
*
|
271 |
+
* @throws Mustache_Exception_SyntaxException if an invalid token is found inside a parent tag.
|
272 |
+
*
|
273 |
+
* @param array|null $parent
|
274 |
+
* @param array $token
|
275 |
+
*/
|
276 |
+
private function checkIfTokenIsAllowedInParent($parent, array $token)
|
277 |
+
{
|
278 |
+
if ($parent[Mustache_Tokenizer::TYPE] === Mustache_Tokenizer::T_PARENT) {
|
279 |
+
throw new Mustache_Exception_SyntaxException('Illegal content in < parent tag', $token);
|
280 |
+
}
|
281 |
+
}
|
282 |
+
|
283 |
+
/**
|
284 |
+
* Split a tag name into name and filters.
|
285 |
+
*
|
286 |
+
* @param string $name
|
287 |
+
*
|
288 |
+
* @return array [Tag name, Array of filters]
|
289 |
+
*/
|
290 |
+
private function getNameAndFilters($name)
|
291 |
+
{
|
292 |
+
$filters = array_map('trim', explode('|', $name));
|
293 |
+
$name = array_shift($filters);
|
294 |
+
|
295 |
+
return array($name, $filters);
|
296 |
+
}
|
297 |
+
|
298 |
+
/**
|
299 |
+
* Enable a pragma.
|
300 |
+
*
|
301 |
+
* @param string $name
|
302 |
+
*/
|
303 |
+
private function enablePragma($name)
|
304 |
+
{
|
305 |
+
$this->pragmas[$name] = true;
|
306 |
+
|
307 |
+
switch ($name) {
|
308 |
+
case Mustache_Engine::PRAGMA_BLOCKS:
|
309 |
+
$this->pragmaBlocks = true;
|
310 |
+
break;
|
311 |
+
|
312 |
+
case Mustache_Engine::PRAGMA_FILTERS:
|
313 |
+
$this->pragmaFilters = true;
|
314 |
+
break;
|
315 |
+
}
|
316 |
+
}
|
317 |
+
}
|
lib/php/Mustache/Template.php
ADDED
@@ -0,0 +1,180 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of Mustache.php.
|
5 |
+
*
|
6 |
+
* (c) 2010-2015 Justin Hileman
|
7 |
+
*
|
8 |
+
* For the full copyright and license information, please view the LICENSE
|
9 |
+
* file that was distributed with this source code.
|
10 |
+
*/
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Abstract Mustache Template class.
|
14 |
+
*
|
15 |
+
* @abstract
|
16 |
+
*/
|
17 |
+
abstract class Mustache_Template
|
18 |
+
{
|
19 |
+
/**
|
20 |
+
* @var Mustache_Engine
|
21 |
+
*/
|
22 |
+
protected $mustache;
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @var bool
|
26 |
+
*/
|
27 |
+
protected $strictCallables = false;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Mustache Template constructor.
|
31 |
+
*
|
32 |
+
* @param Mustache_Engine $mustache
|
33 |
+
*/
|
34 |
+
public function __construct(Mustache_Engine $mustache)
|
35 |
+
{
|
36 |
+
$this->mustache = $mustache;
|
37 |
+
}
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Mustache Template instances can be treated as a function and rendered by simply calling them.
|
41 |
+
*
|
42 |
+
* $m = new Mustache_Engine;
|
43 |
+
* $tpl = $m->loadTemplate('Hello, {{ name }}!');
|
44 |
+
* echo $tpl(array('name' => 'World')); // "Hello, World!"
|
45 |
+
*
|
46 |
+
* @see Mustache_Template::render
|
47 |
+
*
|
48 |
+
* @param mixed $context Array or object rendering context (default: array())
|
49 |
+
*
|
50 |
+
* @return string Rendered template
|
51 |
+
*/
|
52 |
+
public function __invoke($context = array())
|
53 |
+
{
|
54 |
+
return $this->render($context);
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Render this template given the rendering context.
|
59 |
+
*
|
60 |
+
* @param mixed $context Array or object rendering context (default: array())
|
61 |
+
*
|
62 |
+
* @return string Rendered template
|
63 |
+
*/
|
64 |
+
public function render($context = array())
|
65 |
+
{
|
66 |
+
return $this->renderInternal(
|
67 |
+
$this->prepareContextStack($context)
|
68 |
+
);
|
69 |
+
}
|
70 |
+
|
71 |
+
/**
|
72 |
+
* Internal rendering method implemented by Mustache Template concrete subclasses.
|
73 |
+
*
|
74 |
+
* This is where the magic happens :)
|
75 |
+
*
|
76 |
+
* NOTE: This method is not part of the Mustache.php public API.
|
77 |
+
*
|
78 |
+
* @param Mustache_Context $context
|
79 |
+
* @param string $indent (default: '')
|
80 |
+
*
|
81 |
+
* @return string Rendered template
|
82 |
+
*/
|
83 |
+
abstract public function renderInternal(Mustache_Context $context, $indent = '');
|
84 |
+
|
85 |
+
/**
|
86 |
+
* Tests whether a value should be iterated over (e.g. in a section context).
|
87 |
+
*
|
88 |
+
* In most languages there are two distinct array types: list and hash (or whatever you want to call them). Lists
|
89 |
+
* should be iterated, hashes should be treated as objects. Mustache follows this paradigm for Ruby, Javascript,
|
90 |
+
* Java, Python, etc.
|
91 |
+
*
|
92 |
+
* PHP, however, treats lists and hashes as one primitive type: array. So Mustache.php needs a way to distinguish
|
93 |
+
* between between a list of things (numeric, normalized array) and a set of variables to be used as section context
|
94 |
+
* (associative array). In other words, this will be iterated over:
|
95 |
+
*
|
96 |
+
* $items = array(
|
97 |
+
* array('name' => 'foo'),
|
98 |
+
* array('name' => 'bar'),
|
99 |
+
* array('name' => 'baz'),
|
100 |
+
* );
|
101 |
+
*
|
102 |
+
* ... but this will be used as a section context block:
|
103 |
+
*
|
104 |
+
* $items = array(
|
105 |
+
* 1 => array('name' => 'foo'),
|
106 |
+
* 'banana' => array('name' => 'bar'),
|
107 |
+
* 42 => array('name' => 'baz'),
|
108 |
+
* );
|
109 |
+
*
|
110 |
+
* @param mixed $value
|
111 |
+
*
|
112 |
+
* @return bool True if the value is 'iterable'
|
113 |
+
*/
|
114 |
+
protected function isIterable($value)
|
115 |
+
{
|
116 |
+
switch (gettype($value)) {
|
117 |
+
case 'object':
|
118 |
+
return $value instanceof Traversable;
|
119 |
+
|
120 |
+
case 'array':
|
121 |
+
$i = 0;
|
122 |
+
foreach ($value as $k => $v) {
|
123 |
+
if ($k !== $i++) {
|
124 |
+
return false;
|
125 |
+
}
|
126 |
+
}
|
127 |
+
|
128 |
+
return true;
|
129 |
+
|
130 |
+
default:
|
131 |
+
return false;
|
132 |
+
}
|
133 |
+
}
|
134 |
+
|
135 |
+
/**
|
136 |
+
* Helper method to prepare the Context stack.
|
137 |
+
*
|
138 |
+
* Adds the Mustache HelperCollection to the stack's top context frame if helpers are present.
|
139 |
+
*
|
140 |
+
* @param mixed $context Optional first context frame (default: null)
|
141 |
+
*
|
142 |
+
* @return Mustache_Context
|
143 |
+
*/
|
144 |
+
protected function prepareContextStack($context = null)
|
145 |
+
{
|
146 |
+
$stack = new Mustache_Context();
|
147 |
+
|
148 |
+
$helpers = $this->mustache->getHelpers();
|
149 |
+
if (!$helpers->isEmpty()) {
|
150 |
+
$stack->push($helpers);
|
151 |
+
}
|
152 |
+
|
153 |
+
if (!empty($context)) {
|
154 |
+
$stack->push($context);
|
155 |
+
}
|
156 |
+
|
157 |
+
return $stack;
|
158 |
+
}
|
159 |
+
|
160 |
+
/**
|
161 |
+
* Resolve a context value.
|
162 |
+
*
|
163 |
+
* Invoke the value if it is callable, otherwise return the value.
|
164 |
+
*
|
165 |
+
* @param mixed $value
|
166 |
+
* @param Mustache_Context $context
|
167 |
+
*
|
168 |
+
* @return string
|
169 |
+
*/
|
170 |
+
protected function resolveValue($value, Mustache_Context $context)
|
171 |
+
{
|
172 |
+
if (($this->strictCallables ? is_object($value) : !is_string($value)) && is_callable($value)) {
|
173 |
+
return $this->mustache
|
174 |
+
->loadLambda((string) call_user_func($value))
|
175 |
+
->renderInternal($context);
|
176 |
+
}
|
177 |
+
|
178 |
+
return $value;
|
179 |
+
}
|
180 |
+
}
|
lib/php/Mustache/Tokenizer.php
ADDED
@@ -0,0 +1,322 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of Mustache.php.
|
5 |
+
*
|
6 |
+
* (c) 2010-2015 Justin Hileman
|
7 |
+
*
|
8 |
+
* For the full copyright and license information, please view the LICENSE
|
9 |
+
* file that was distributed with this source code.
|
10 |
+
*/
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Mustache Tokenizer class.
|
14 |
+
*
|
15 |
+
* This class is responsible for turning raw template source into a set of Mustache tokens.
|
16 |
+
*/
|
17 |
+
class Mustache_Tokenizer
|
18 |
+
{
|
19 |
+
// Finite state machine states
|
20 |
+
const IN_TEXT = 0;
|
21 |
+
const IN_TAG_TYPE = 1;
|
22 |
+
const IN_TAG = 2;
|
23 |
+
|
24 |
+
// Token types
|
25 |
+
const T_SECTION = '#';
|
26 |
+
const T_INVERTED = '^';
|
27 |
+
const T_END_SECTION = '/';
|
28 |
+
const T_COMMENT = '!';
|
29 |
+
const T_PARTIAL = '>';
|
30 |
+
const T_PARENT = '<';
|
31 |
+
const T_DELIM_CHANGE = '=';
|
32 |
+
const T_ESCAPED = '_v';
|
33 |
+
const T_UNESCAPED = '{';
|
34 |
+
const T_UNESCAPED_2 = '&';
|
35 |
+
const T_TEXT = '_t';
|
36 |
+
const T_PRAGMA = '%';
|
37 |
+
const T_BLOCK_VAR = '$';
|
38 |
+
const T_BLOCK_ARG = '$arg';
|
39 |
+
|
40 |
+
// Valid token types
|
41 |
+
private static $tagTypes = array(
|
42 |
+
self::T_SECTION => true,
|
43 |
+
self::T_INVERTED => true,
|
44 |
+
self::T_END_SECTION => true,
|
45 |
+
self::T_COMMENT => true,
|
46 |
+
self::T_PARTIAL => true,
|
47 |
+
self::T_PARENT => true,
|
48 |
+
self::T_DELIM_CHANGE => true,
|
49 |
+
self::T_ESCAPED => true,
|
50 |
+
self::T_UNESCAPED => true,
|
51 |
+
self::T_UNESCAPED_2 => true,
|
52 |
+
self::T_PRAGMA => true,
|
53 |
+
self::T_BLOCK_VAR => true,
|
54 |
+
);
|
55 |
+
|
56 |
+
// Token properties
|
57 |
+
const TYPE = 'type';
|
58 |
+
const NAME = 'name';
|
59 |
+
const OTAG = 'otag';
|
60 |
+
const CTAG = 'ctag';
|
61 |
+
const LINE = 'line';
|
62 |
+
const INDEX = 'index';
|
63 |
+
const END = 'end';
|
64 |
+
const INDENT = 'indent';
|
65 |
+
const NODES = 'nodes';
|
66 |
+
const VALUE = 'value';
|
67 |
+
const FILTERS = 'filters';
|
68 |
+
|
69 |
+
private $state;
|
70 |
+
private $tagType;
|
71 |
+
private $buffer;
|
72 |
+
private $tokens;
|
73 |
+
private $seenTag;
|
74 |
+
private $line;
|
75 |
+
private $otag;
|
76 |
+
private $ctag;
|
77 |
+
private $otagLen;
|
78 |
+
private $ctagLen;
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Scan and tokenize template source.
|
82 |
+
*
|
83 |
+
* @throws Mustache_Exception_SyntaxException when mismatched section tags are encountered.
|
84 |
+
*
|
85 |
+
* @param string $text Mustache template source to tokenize
|
86 |
+
* @param string $delimiters Optionally, pass initial opening and closing delimiters (default: null)
|
87 |
+
*
|
88 |
+
* @return array Set of Mustache tokens
|
89 |
+
*/
|
90 |
+
public function scan($text, $delimiters = null)
|
91 |
+
{
|
92 |
+
// Setting mbstring.func_overload makes things *really* slow.
|
93 |
+
// Let's do everyone a favor and scan this string as ASCII instead.
|
94 |
+
$encoding = null;
|
95 |
+
if (function_exists('mb_internal_encoding') && ini_get('mbstring.func_overload') & 2) {
|
96 |
+
$encoding = mb_internal_encoding();
|
97 |
+
mb_internal_encoding('ASCII');
|
98 |
+
}
|
99 |
+
|
100 |
+
$this->reset();
|
101 |
+
|
102 |
+
if ($delimiters = trim($delimiters)) {
|
103 |
+
$this->setDelimiters($delimiters);
|
104 |
+
}
|
105 |
+
|
106 |
+
$len = strlen($text);
|
107 |
+
for ($i = 0; $i < $len; $i++) {
|
108 |
+
switch ($this->state) {
|
109 |
+
case self::IN_TEXT:
|
110 |
+
if ($this->tagChange($this->otag, $this->otagLen, $text, $i)) {
|
111 |
+
$i--;
|
112 |
+
$this->flushBuffer();
|
113 |
+
$this->state = self::IN_TAG_TYPE;
|
114 |
+
} else {
|
115 |
+
$char = $text[$i];
|
116 |
+
$this->buffer .= $char;
|
117 |
+
if ($char === "\n") {
|
118 |
+
$this->flushBuffer();
|
119 |
+
$this->line++;
|
120 |
+
}
|
121 |
+
}
|
122 |
+
break;
|
123 |
+
|
124 |
+
case self::IN_TAG_TYPE:
|
125 |
+
$i += $this->otagLen - 1;
|
126 |
+
$char = $text[$i + 1];
|
127 |
+
if (isset(self::$tagTypes[$char])) {
|
128 |
+
$tag = $char;
|
129 |
+
$this->tagType = $tag;
|
130 |
+
} else {
|
131 |
+
$tag = null;
|
132 |
+
$this->tagType = self::T_ESCAPED;
|
133 |
+
}
|
134 |
+
|
135 |
+
if ($this->tagType === self::T_DELIM_CHANGE) {
|
136 |
+
$i = $this->changeDelimiters($text, $i);
|
137 |
+
$this->state = self::IN_TEXT;
|
138 |
+
} elseif ($this->tagType === self::T_PRAGMA) {
|
139 |
+
$i = $this->addPragma($text, $i);
|
140 |
+
$this->state = self::IN_TEXT;
|
141 |
+
} else {
|
142 |
+
if ($tag !== null) {
|
143 |
+
$i++;
|
144 |
+
}
|
145 |
+
$this->state = self::IN_TAG;
|
146 |
+
}
|
147 |
+
$this->seenTag = $i;
|
148 |
+
break;
|
149 |
+
|
150 |
+
default:
|
151 |
+
if ($this->tagChange($this->ctag, $this->ctagLen, $text, $i)) {
|
152 |
+
$token = array(
|
153 |
+
self::TYPE => $this->tagType,
|
154 |
+
self::NAME => trim($this->buffer),
|
155 |
+
self::OTAG => $this->otag,
|
156 |
+
self::CTAG => $this->ctag,
|
157 |
+
self::LINE => $this->line,
|
158 |
+
self::INDEX => ($this->tagType === self::T_END_SECTION) ? $this->seenTag - $this->otagLen : $i + $this->ctagLen,
|
159 |
+
);
|
160 |
+
|
161 |
+
if ($this->tagType === self::T_UNESCAPED) {
|
162 |
+
// Clean up `{{{ tripleStache }}}` style tokens.
|
163 |
+
if ($this->ctag === '}}') {
|
164 |
+
if (($i + 2 < $len) && $text[$i + 2] === '}') {
|
165 |
+
$i++;
|
166 |
+
} else {
|
167 |
+
$msg = sprintf(
|
168 |
+
'Mismatched tag delimiters: %s on line %d',
|
169 |
+
$token[self::NAME],
|
170 |
+
$token[self::LINE]
|
171 |
+
);
|
172 |
+
|
173 |
+
throw new Mustache_Exception_SyntaxException($msg, $token);
|
174 |
+
}
|
175 |
+
} else {
|
176 |
+
$lastName = $token[self::NAME];
|
177 |
+
if (substr($lastName, -1) === '}') {
|
178 |
+
$token[self::NAME] = trim(substr($lastName, 0, -1));
|
179 |
+
} else {
|
180 |
+
$msg = sprintf(
|
181 |
+
'Mismatched tag delimiters: %s on line %d',
|
182 |
+
$token[self::NAME],
|
183 |
+
$token[self::LINE]
|
184 |
+
);
|
185 |
+
|
186 |
+
throw new Mustache_Exception_SyntaxException($msg, $token);
|
187 |
+
}
|
188 |
+
}
|
189 |
+
}
|
190 |
+
|
191 |
+
$this->buffer = '';
|
192 |
+
$i += $this->ctagLen - 1;
|
193 |
+
$this->state = self::IN_TEXT;
|
194 |
+
$this->tokens[] = $token;
|
195 |
+
} else {
|
196 |
+
$this->buffer .= $text[$i];
|
197 |
+
}
|
198 |
+
break;
|
199 |
+
}
|
200 |
+
}
|
201 |
+
|
202 |
+
$this->flushBuffer();
|
203 |
+
|
204 |
+
// Restore the user's encoding...
|
205 |
+
if ($encoding) {
|
206 |
+
mb_internal_encoding($encoding);
|
207 |
+
}
|
208 |
+
|
209 |
+
return $this->tokens;
|
210 |
+
}
|
211 |
+
|
212 |
+
/**
|
213 |
+
* Helper function to reset tokenizer internal state.
|
214 |
+
*/
|
215 |
+
private function reset()
|
216 |
+
{
|
217 |
+
$this->state = self::IN_TEXT;
|
218 |
+
$this->tagType = null;
|
219 |
+
$this->buffer = '';
|
220 |
+
$this->tokens = array();
|
221 |
+
$this->seenTag = false;
|
222 |
+
$this->line = 0;
|
223 |
+
$this->otag = '{{';
|
224 |
+
$this->ctag = '}}';
|
225 |
+
$this->otagLen = 2;
|
226 |
+
$this->ctagLen = 2;
|
227 |
+
}
|
228 |
+
|
229 |
+
/**
|
230 |
+
* Flush the current buffer to a token.
|
231 |
+
*/
|
232 |
+
private function flushBuffer()
|
233 |
+
{
|
234 |
+
if (strlen($this->buffer) > 0) {
|
235 |
+
$this->tokens[] = array(
|
236 |
+
self::TYPE => self::T_TEXT,
|
237 |
+
self::LINE => $this->line,
|
238 |
+
self::VALUE => $this->buffer,
|
239 |
+
);
|
240 |
+
$this->buffer = '';
|
241 |
+
}
|
242 |
+
}
|
243 |
+
|
244 |
+
/**
|
245 |
+
* Change the current Mustache delimiters. Set new `otag` and `ctag` values.
|
246 |
+
*
|
247 |
+
* @param string $text Mustache template source
|
248 |
+
* @param int $index Current tokenizer index
|
249 |
+
*
|
250 |
+
* @return int New index value
|
251 |
+
*/
|
252 |
+
private function changeDelimiters($text, $index)
|
253 |
+
{
|
254 |
+
$startIndex = strpos($text, '=', $index) + 1;
|
255 |
+
$close = '=' . $this->ctag;
|
256 |
+
$closeIndex = strpos($text, $close, $index);
|
257 |
+
|
258 |
+
$this->setDelimiters(trim(substr($text, $startIndex, $closeIndex - $startIndex)));
|
259 |
+
|
260 |
+
$this->tokens[] = array(
|
261 |
+
self::TYPE => self::T_DELIM_CHANGE,
|
262 |
+
self::LINE => $this->line,
|
263 |
+
);
|
264 |
+
|
265 |
+
return $closeIndex + strlen($close) - 1;
|
266 |
+
}
|
267 |
+
|
268 |
+
/**
|
269 |
+
* Set the current Mustache `otag` and `ctag` delimiters.
|
270 |
+
*
|
271 |
+
* @param string $delimiters
|
272 |
+
*/
|
273 |
+
private function setDelimiters($delimiters)
|
274 |
+
{
|
275 |
+
list($otag, $ctag) = explode(' ', $delimiters);
|
276 |
+
$this->otag = $otag;
|
277 |
+
$this->ctag = $ctag;
|
278 |
+
$this->otagLen = strlen($otag);
|
279 |
+
$this->ctagLen = strlen($ctag);
|
280 |
+
}
|
281 |
+
|
282 |
+
/**
|
283 |
+
* Add pragma token.
|
284 |
+
*
|
285 |
+
* Pragmas are hoisted to the front of the template, so all pragma tokens
|
286 |
+
* will appear at the front of the token list.
|
287 |
+
*
|
288 |
+
* @param string $text
|
289 |
+
* @param int $index
|
290 |
+
*
|
291 |
+
* @return int New index value
|
292 |
+
*/
|
293 |
+
private function addPragma($text, $index)
|
294 |
+
{
|
295 |
+
$end = strpos($text, $this->ctag, $index);
|
296 |
+
$pragma = trim(substr($text, $index + 2, $end - $index - 2));
|
297 |
+
|
298 |
+
// Pragmas are hoisted to the front of the template.
|
299 |
+
array_unshift($this->tokens, array(
|
300 |
+
self::TYPE => self::T_PRAGMA,
|
301 |
+
self::NAME => $pragma,
|
302 |
+
self::LINE => 0,
|
303 |
+
));
|
304 |
+
|
305 |
+
return $end + $this->ctagLen - 1;
|
306 |
+
}
|
307 |
+
|
308 |
+
/**
|
309 |
+
* Test whether it's time to change tags.
|
310 |
+
*
|
311 |
+
* @param string $tag Current tag name
|
312 |
+
* @param int $tagLen Current tag name length
|
313 |
+
* @param string $text Mustache template source
|
314 |
+
* @param int $index Current tokenizer index
|
315 |
+
*
|
316 |
+
* @return bool True if this is a closing section tag
|
317 |
+
*/
|
318 |
+
private function tagChange($tag, $tagLen, $text, $index)
|
319 |
+
{
|
320 |
+
return substr($text, $index, $tagLen) === $tag;
|
321 |
+
}
|
322 |
+
}
|
lib/php/Paapi/aalb_paapi_helper.php
ADDED
@@ -0,0 +1,131 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
Copyright 2016-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
5 |
+
|
6 |
+
Licensed under the GNU General Public License as published by the Free Software Foundation,
|
7 |
+
Version 2.0 (the "License"). You may not use this file except in compliance with the License.
|
8 |
+
A copy of the License is located in the "license" file accompanying this file.
|
9 |
+
|
10 |
+
This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
11 |
+
either express or implied. See the License for the specific language governing permissions
|
12 |
+
and limitations under the License.
|
13 |
+
*/
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Helper class for Paapi
|
17 |
+
*
|
18 |
+
* @since 1.0.0
|
19 |
+
* @package AmazonAssociatesLinkBuilder
|
20 |
+
* @subpackage AmazonAssociatesLinkBuilder/lib/php/Paapi
|
21 |
+
*/
|
22 |
+
class Aalb_Paapi_Helper {
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Returns signed URL for Paapi request
|
26 |
+
*
|
27 |
+
* @since 1.0.0
|
28 |
+
* @param array $params Paapi parameters.
|
29 |
+
* @param string $marketplace Marketplace to search the product.
|
30 |
+
* @return string Signed URL.
|
31 |
+
*/
|
32 |
+
function aws_signed_url($params,$marketplace) {
|
33 |
+
$access_key_id = openssl_decrypt(base64_decode(get_option(AALB_AWS_ACCESS_KEY)), AALB_ENCRYPTION_ALGORITHM, AALB_ENCRYPTION_KEY, 0, AALB_ENCRYPTION_IV);
|
34 |
+
$secret_key = openssl_decrypt(base64_decode(get_option(AALB_AWS_SECRET_KEY)), AALB_ENCRYPTION_ALGORITHM, AALB_ENCRYPTION_KEY, 0, AALB_ENCRYPTION_IV);
|
35 |
+
$host = $marketplace;
|
36 |
+
|
37 |
+
$method = 'GET';
|
38 |
+
$uri = PAAPI_URI;
|
39 |
+
|
40 |
+
$params["Service"] = PAAPI_SERVICE;
|
41 |
+
$params["AWSAccessKeyId"] = $access_key_id;
|
42 |
+
$params["Timestamp"] = gmdate('Y-m-d\TH:i:s\Z');
|
43 |
+
$params["Version"] = PAAPI_VERSION;
|
44 |
+
|
45 |
+
ksort($params);
|
46 |
+
|
47 |
+
$canonicalized_query = array();
|
48 |
+
foreach ($params as $param => $value) {
|
49 |
+
$param = str_replace("%7E", "~", rawurlencode($param));
|
50 |
+
$value = str_replace("%7E", "~", rawurlencode($value));
|
51 |
+
$canonicalized_query[] = $param . "=" . $value;
|
52 |
+
}
|
53 |
+
|
54 |
+
$canonicalized_query = implode("&", $canonicalized_query);
|
55 |
+
|
56 |
+
$string_to_sign = $method . "\n" . $host . "\n" . $uri . "\n" . $canonicalized_query;
|
57 |
+
$signature = base64_encode(hash_hmac("sha256", $string_to_sign, $secret_key, true));
|
58 |
+
$signature = str_replace("%7E", "~", rawurlencode($signature));
|
59 |
+
|
60 |
+
$signed_url = PAAPI_TRANSFER_PROTOCOL . $host . $uri . PAAPI_URL_QUERY_SEPARATOR . $canonicalized_query . "&Signature=" . $signature;
|
61 |
+
|
62 |
+
return $signed_url;
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Returns the item lookup URL for asins
|
67 |
+
*
|
68 |
+
* @param string $asin Asin value.
|
69 |
+
* @param string $marketplaces Marketplace to search the products.
|
70 |
+
* @param string $tracking_id Associate tag.
|
71 |
+
* @return string Signed URL for item lookup.
|
72 |
+
*/
|
73 |
+
function get_item_lookup_url($asin,$marketplace,$tracking_id) {
|
74 |
+
$params = array(
|
75 |
+
"Operation" => "ItemLookup",
|
76 |
+
"ItemId" => "$asin",
|
77 |
+
"IdType" => "ASIN",
|
78 |
+
"ResponseGroup" => "Images,ItemAttributes,OfferFull",
|
79 |
+
"Condition" => "New",
|
80 |
+
"AssociateTag" => "$tracking_id",
|
81 |
+
);
|
82 |
+
$url = $this->aws_signed_url ($params,$marketplace);
|
83 |
+
return $url;
|
84 |
+
}
|
85 |
+
|
86 |
+
/**
|
87 |
+
* Returns the item search URL for search keywords
|
88 |
+
*
|
89 |
+
* @param string $search_keywords Search keywords of the products.
|
90 |
+
* @param string $marketplaces Marketplace to search the products.
|
91 |
+
* @param string $tracking_id Associate tag.
|
92 |
+
* @return string Signed URL for item search.
|
93 |
+
*/
|
94 |
+
function get_item_search_url($search_keywords, $marketplace, $tracking_id) {
|
95 |
+
$params = array(
|
96 |
+
"Operation" => "ItemSearch",
|
97 |
+
"SearchIndex" => "All",
|
98 |
+
"Keywords" => "$search_keywords",
|
99 |
+
"ResponseGroup" => "Images,ItemAttributes,Offers",
|
100 |
+
"Condition" => "New",
|
101 |
+
"AssociateTag" => "$tracking_id",
|
102 |
+
);
|
103 |
+
$url = $this->aws_signed_url ($params, $marketplace);
|
104 |
+
return $url;
|
105 |
+
}
|
106 |
+
|
107 |
+
/**
|
108 |
+
* Paapi error messages to diaplay in case of request errors
|
109 |
+
*
|
110 |
+
* @param string $error code Error code of the request.
|
111 |
+
* @return string Paapi error message.
|
112 |
+
*/
|
113 |
+
function get_error_message($error) {
|
114 |
+
if($error == HTTP_BAD_REQUEST) {
|
115 |
+
return HTTP_BAD_REQUEST_MESSAGE;
|
116 |
+
}
|
117 |
+
if($error == HTTP_FORBIDDEN) {
|
118 |
+
return HTTP_FORBIDDEN_MESSAGE;
|
119 |
+
}
|
120 |
+
if($error == HTTP_INTERNAL_SERVER_ERROR) {
|
121 |
+
return HTTP_INTERNAL_SERVER_ERROR_MESSAGE;
|
122 |
+
}
|
123 |
+
if($error == HTTP_THROTTLE) {
|
124 |
+
return HTTP_THROTTLE_MESSAGE;
|
125 |
+
}
|
126 |
+
return $error;
|
127 |
+
}
|
128 |
+
|
129 |
+
}
|
130 |
+
|
131 |
+
?>
|
lib/php/aalb_internationalization_helper.php
ADDED
@@ -0,0 +1,84 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
Copyright 2016-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
5 |
+
|
6 |
+
Licensed under the GNU General Public License as published by the Free Software Foundation,
|
7 |
+
Version 2.0 (the "License"). You may not use this file except in compliance with the License.
|
8 |
+
A copy of the License is located in the "license" file accompanying this file.
|
9 |
+
|
10 |
+
This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
11 |
+
either express or implied. See the License for the specific language governing permissions
|
12 |
+
and limitations under the License.
|
13 |
+
*/
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Helper class for internationalizing the strings
|
17 |
+
*
|
18 |
+
* @since 1.0.0
|
19 |
+
* @package AmazonAssociatesLinkBuilder
|
20 |
+
* @subpackage AmazonAssociatesLinkBuilder/lib/php
|
21 |
+
*/
|
22 |
+
class Aalb_Internationalization_Helper {
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Array that defines the translations for various marketplaces
|
26 |
+
*/
|
27 |
+
protected $translation_array;
|
28 |
+
|
29 |
+
public function __construct() {
|
30 |
+
$this->translation_array = array(
|
31 |
+
CHECK_ON_AMAZON => array(
|
32 |
+
US => "Check on Amazon",
|
33 |
+
FR => "Consulter sur Amazon.fr",
|
34 |
+
IT => "Vedi su Amazon.it",
|
35 |
+
DE => "Hier auf Amazon.de",
|
36 |
+
ES => "Consultar en Amazon.es",
|
37 |
+
BR => "Check on Amazon",
|
38 |
+
CA => "Check on Amazon",
|
39 |
+
CN => "Check on Amazon",
|
40 |
+
IN => "Check on Amazon",
|
41 |
+
JP => "Check on Amazon",
|
42 |
+
MX => "Check on Amazon",
|
43 |
+
UK => "Check on Amazon",
|
44 |
+
),
|
45 |
+
OUT_OF_STOCK => array(
|
46 |
+
US => "Out of stock",
|
47 |
+
FR => "Rupture de stock",
|
48 |
+
IT => "Non disponibile",
|
49 |
+
DE => "Derzeit nicht verfügbar",
|
50 |
+
ES => "Producto no disponible",
|
51 |
+
BR => "Out of stock",
|
52 |
+
CA => "Out of stock",
|
53 |
+
CN => "Out of stock",
|
54 |
+
IN => "Out of stock",
|
55 |
+
JP => "Out of stock",
|
56 |
+
MX => "Out of stock",
|
57 |
+
UK => "Out of stock",
|
58 |
+
),
|
59 |
+
);
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Internationalize stings by marketplace
|
64 |
+
*
|
65 |
+
* @since 1.0.0
|
66 |
+
* @param String $key Identifier of string to be translated
|
67 |
+
* @return String $marketplace The target marketplace name
|
68 |
+
*/
|
69 |
+
public function internationalize_by_marketplace($key, $marketplace) {
|
70 |
+
$translated_string = $this->translation_array[$key][$marketplace];
|
71 |
+
|
72 |
+
if($translated_string == null) {
|
73 |
+
//use english if transation is not available
|
74 |
+
$translated_string = $this->translation_array[$key][AALB_DEFAULT_MARKETPLACE_NAME];
|
75 |
+
if($translated_string == null) {
|
76 |
+
//use key name if english is also not available
|
77 |
+
$translated_string = $key;
|
78 |
+
}
|
79 |
+
}
|
80 |
+
return $translated_string;
|
81 |
+
}
|
82 |
+
}
|
83 |
+
|
84 |
+
?>
|
lib/php/aalb_tracking_api_helper.php
ADDED
@@ -0,0 +1,120 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
Copyright 2016-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
5 |
+
|
6 |
+
Licensed under the GNU General Public License as published by the Free Software Foundation,
|
7 |
+
Version 2.0 (the "License"). You may not use this file except in compliance with the License.
|
8 |
+
A copy of the License is located in the "license" file accompanying this file.
|
9 |
+
|
10 |
+
This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
11 |
+
either express or implied. See the License for the specific language governing permissions
|
12 |
+
and limitations under the License.
|
13 |
+
*/
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Helper class for APIs used for impression and clicks tracking
|
17 |
+
*
|
18 |
+
* @since 1.0.0
|
19 |
+
* @package AmazonAssociatesLinkBuilder
|
20 |
+
* @subpackage AmazonAssociatesLinkBuilder/lib/php
|
21 |
+
*/
|
22 |
+
class Aalb_Tracking_Api_Helper {
|
23 |
+
|
24 |
+
protected $remote_loader;
|
25 |
+
protected $helper;
|
26 |
+
protected $version_info;
|
27 |
+
|
28 |
+
public function __construct() {
|
29 |
+
$this->remote_loader = new Aalb_Remote_Loader();
|
30 |
+
$this->helper = new Aalb_Helper();
|
31 |
+
|
32 |
+
//Initializes the version information once.
|
33 |
+
$plugin_version = $this->helper->get_plugin_version();
|
34 |
+
$wordpress_version = $this->helper->get_wordpress_version();
|
35 |
+
$this->version_info = array(
|
36 |
+
'wordpress' => $wordpress_version,
|
37 |
+
'plugin' => $plugin_version
|
38 |
+
);
|
39 |
+
}
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Builds the base url for each tracking api request. Adds common parameters
|
43 |
+
*
|
44 |
+
* @since 1.0.0
|
45 |
+
* @param string $method_path Relative path of the api method to be called.
|
46 |
+
* @return string The base url with common query parameters
|
47 |
+
*/
|
48 |
+
private function get_base_url($method_path) {
|
49 |
+
$access_key_id = openssl_decrypt(base64_decode(get_option(AALB_AWS_ACCESS_KEY)), AALB_ENCRYPTION_ALGORITHM, AALB_ENCRYPTION_KEY, 0, AALB_ENCRYPTION_IV);
|
50 |
+
return (AALB_TRACKING_API_ENDPOINT . $method_path . '?' . AALB_TRACKING_API_SOURCE_TOOL_QUERY_PARAM . '&' . AALB_TRACKING_API_ACCESS_KEY_QUERY_PARAM . $access_key_id);
|
51 |
+
}
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Returns the response of the link-id API.
|
55 |
+
* The GET request returns a unique link-id everytime a shortcode is added
|
56 |
+
*
|
57 |
+
* @since 1.0.0
|
58 |
+
* @param string $shortcode_name Name of the shortcode used
|
59 |
+
* @param string $shortcode_params Array of all shortcode parameter key-value pairs
|
60 |
+
* @return string Response of the get link-id API for the given link-id
|
61 |
+
*/
|
62 |
+
public function get_link_id($shortcode_name, $shortcode_params) {
|
63 |
+
$link_info = array(
|
64 |
+
'shortcode_name' => $shortcode_name,
|
65 |
+
'shortcode_params' => $shortcode_params,
|
66 |
+
'version' => $this->version_info
|
67 |
+
);
|
68 |
+
$request_body = wp_json_encode($link_info);
|
69 |
+
$base_url = $this->get_base_url('link-id');
|
70 |
+
$response = $this->remote_loader->post($base_url, $request_body);
|
71 |
+
return json_decode($response, true)["link-id"];
|
72 |
+
}
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Returns the response of the impressions API for a given link-id
|
76 |
+
*
|
77 |
+
* @since 1.0.0
|
78 |
+
* @param string $link_id Link ID for which impression parameters are required
|
79 |
+
* @param string $shortcode_name Name of the shortcode used
|
80 |
+
* @param string $shortcode_params Array of all shortcode parameter key-value pairs
|
81 |
+
* @return string Response of the get impression API for the given link-id
|
82 |
+
*/
|
83 |
+
public function get_impression_params($link_id, $shortcode_name, $shortcode_params) {
|
84 |
+
$link_info = array(
|
85 |
+
'shortcode_name' => $shortcode_name,
|
86 |
+
'shortcode_params' => $shortcode_params,
|
87 |
+
'version' => $this->version_info
|
88 |
+
);
|
89 |
+
$request_body = wp_json_encode($link_info);
|
90 |
+
$base_url = $this->get_base_url('impression');
|
91 |
+
$url = $base_url . '&link-id=' . $link_id;
|
92 |
+
return $this->remote_loader->post($url, $request_body);
|
93 |
+
}
|
94 |
+
|
95 |
+
/**
|
96 |
+
* Returns the click URL by parsing the recieved getImpressions API Response
|
97 |
+
*
|
98 |
+
* @since 1.0.0
|
99 |
+
* @param json string $impression_params JSON Response from the get impressions API for a link-id
|
100 |
+
* @return string $click_url Click URL for an impression ID
|
101 |
+
*/
|
102 |
+
public function get_click_url($impression_params) {
|
103 |
+
$body = json_decode($impression_params,true);
|
104 |
+
return $body["click-url"];
|
105 |
+
}
|
106 |
+
|
107 |
+
/**
|
108 |
+
* Echoes an invisible img with src=pixel-url to fire the pixels
|
109 |
+
*
|
110 |
+
* @since 1.0.0
|
111 |
+
* @param json string $impression_params JSON Response from the get impressions API for a link-id
|
112 |
+
*/
|
113 |
+
public function insert_pixel($impression_params) {
|
114 |
+
$body = json_decode($impression_params,true);
|
115 |
+
$pixel_url = $body["pixel-url"];
|
116 |
+
echo '<img src="' . $pixel_url . '" style="visibility:hidden"></img>';
|
117 |
+
}
|
118 |
+
}
|
119 |
+
|
120 |
+
?>
|
lib/php/aalb_validation_helper.php
ADDED
@@ -0,0 +1,97 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
Copyright 2016-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
5 |
+
|
6 |
+
Licensed under the GNU General Public License as published by the Free Software Foundation,
|
7 |
+
Version 2.0 (the "License"). You may not use this file except in compliance with the License.
|
8 |
+
A copy of the License is located in the "license" file accompanying this file.
|
9 |
+
|
10 |
+
This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
11 |
+
either express or implied. See the License for the specific language governing permissions
|
12 |
+
and limitations under the License.
|
13 |
+
*/
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Hepler class for validations used in the plugin.
|
17 |
+
*
|
18 |
+
* @since 1.0.0
|
19 |
+
* @package AmazonAssociatesLinkBuilder
|
20 |
+
* @subpackage AmazonAssociatesLinkBuilder/lib/php
|
21 |
+
*/
|
22 |
+
class Aalb_Validation_Helper{
|
23 |
+
|
24 |
+
protected $config_loader;
|
25 |
+
protected $helper;
|
26 |
+
|
27 |
+
public function __construct() {
|
28 |
+
$this->config_loader = new Aalb_Config_Loader();
|
29 |
+
$this->helper = new Aalb_Helper();
|
30 |
+
}
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Validate ASIN
|
34 |
+
*
|
35 |
+
* @since 1.0.0
|
36 |
+
* @param string $asins ASIN
|
37 |
+
* @return bool TRUE if the asin is valid, FALSE otherwise
|
38 |
+
*/
|
39 |
+
public function validate_asin($asin) {
|
40 |
+
return preg_match('/^([0-9][0-9]{8}[0-9X]|[A-Z][A-Z0-9]{9})$/', trim($asin));
|
41 |
+
}
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Validate Template Name
|
45 |
+
*
|
46 |
+
* @since 1.0.0
|
47 |
+
* @param string $template template name
|
48 |
+
* @return bool TRUE if the template name is valid, FALSE otherwise
|
49 |
+
*/
|
50 |
+
public function validate_template_name($template) {
|
51 |
+
$aalb_template_names = get_option(AALB_TEMPLATE_NAMES);
|
52 |
+
return in_array($template, $aalb_template_names);
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Validate Link ID
|
57 |
+
* The link id should be alphanumeric inlcude hyphens (-) to be valid
|
58 |
+
*
|
59 |
+
* @since 1.0.0
|
60 |
+
* @param string $link_id Link ID from shortcode
|
61 |
+
* @return bool TRUE if the link id is valid, FALSE otherwise
|
62 |
+
*/
|
63 |
+
public function validate_link_id($link_id) {
|
64 |
+
return ctype_alnum(str_replace(array('-'), '', $link_id));
|
65 |
+
}
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Validate Marketplace
|
69 |
+
*
|
70 |
+
* @since 1.0.0
|
71 |
+
* @param string $marketplace Marketplace Abbreviation from shortcode
|
72 |
+
* @return bool TRUE if the marketplace is valid, FALSE otherwise
|
73 |
+
*/
|
74 |
+
public function validate_marketplace($marketplace) {
|
75 |
+
$aalb_marketplace_names = $this->config_loader->fetch_marketplaces();
|
76 |
+
return in_array($marketplace, $aalb_marketplace_names);
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Validate Store ID
|
81 |
+
*
|
82 |
+
* @since 1.0.0
|
83 |
+
* @param string $store_id Associate Tag from Shortcode
|
84 |
+
* @return bool TRUE if the Associate Tag is valid, FALSE otherwise
|
85 |
+
*/
|
86 |
+
public function validate_store_id($store_id) {
|
87 |
+
$aalb_store_id_names = explode("\r\n", get_option(AALB_STORE_ID_NAMES));
|
88 |
+
//If the store id used is "not-specified".
|
89 |
+
if($store_id === AALB_DEFAULT_STORE_ID_NAME) {
|
90 |
+
$this->helper->show_error_in_preview("Associate Tag was not found. The sales will not be attributed to any store and you will not earn the associate fees for it. Please provide a valid Associate Tag if you wish to earn the referral fees. Assocaite Tags can be configured from the 'Settings' tab in the WordPress administration panel");
|
91 |
+
return true;
|
92 |
+
}
|
93 |
+
return in_array($store_id, $aalb_store_id_names);
|
94 |
+
}
|
95 |
+
|
96 |
+
}
|
97 |
+
?>
|
lib/php/aalb_xml_helper.php
ADDED
@@ -0,0 +1,246 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
Copyright 2016-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
5 |
+
|
6 |
+
Licensed under the GNU General Public License as published by the Free Software Foundation,
|
7 |
+
Version 2.0 (the "License"). You may not use this file except in compliance with the License.
|
8 |
+
A copy of the License is located in the "license" file accompanying this file.
|
9 |
+
|
10 |
+
This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
11 |
+
either express or implied. See the License for the specific language governing permissions
|
12 |
+
and limitations under the License.
|
13 |
+
*/
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Helper class for customizations to the xml response
|
17 |
+
*
|
18 |
+
* @since 1.0.0
|
19 |
+
* @package AmazonAssociatesLinkBuilder
|
20 |
+
* @subpackage AmazonAssociatesLinkBuilder/lib/php
|
21 |
+
*/
|
22 |
+
class Aalb_Xml_Helper {
|
23 |
+
|
24 |
+
protected $internationalization_helper;
|
25 |
+
|
26 |
+
public function __construct() {
|
27 |
+
$this->internationalization_helper = new Aalb_Internationalization_Helper();
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Add custom nodes to xml response
|
32 |
+
*
|
33 |
+
* @since 1.0.0
|
34 |
+
* @param SimpleXMLElement $items Well-formed XML string
|
35 |
+
* @return SimpleXMLElement $items XML String with custom nodes added
|
36 |
+
*/
|
37 |
+
public function add_custom_nodes($items, $marketplace) {
|
38 |
+
$common_marketplace_node_name = 'Marketplace' . $marketplace;
|
39 |
+
$items->ID = "[[UNIQUE_ID]]";
|
40 |
+
|
41 |
+
//add aalb nodes needed for each item
|
42 |
+
foreach ($items->Item as $item) {
|
43 |
+
$aalb_node = $item->addChild('aalb');
|
44 |
+
|
45 |
+
$aalb_node->ASIN = $item->ASIN;
|
46 |
+
$aalb_node->Title = $item->ItemAttributes->Title;
|
47 |
+
$aalb_node->DetailPageURL = $item->DetailPageURL;
|
48 |
+
$aalb_node->LargeImageURL = $item->LargeImage->URL;
|
49 |
+
$aalb_node->MediumImageURL = $item->MediumImage->URL;
|
50 |
+
$aalb_node->SmallImageURL = $item->SmallImage->URL;
|
51 |
+
|
52 |
+
//Marketplace
|
53 |
+
$marketplace_node_name = $common_marketplace_node_name;
|
54 |
+
$aalb_node = $this->add_xml_node($aalb_node, $marketplace_node_name , 'true');
|
55 |
+
|
56 |
+
//By Information
|
57 |
+
$aalb_node = $this->add_by_information_node($item, $aalb_node);
|
58 |
+
|
59 |
+
//Savings
|
60 |
+
$aalb_node = $this->add_savings_node($item, $aalb_node);
|
61 |
+
|
62 |
+
//MinimumPrice
|
63 |
+
$aalb_node = $this->add_min_price_node($item, $aalb_node);
|
64 |
+
|
65 |
+
//Prime
|
66 |
+
$aalb_node = $this->add_xml_node($aalb_node, 'Prime', $item->Offers->Offer->OfferListing->IsEligibleForPrime);
|
67 |
+
|
68 |
+
//Merchant Name
|
69 |
+
$aalb_node = $this->add_xml_node($aalb_node, 'Merchant', $item->Offers->Offer->Merchant->Name);
|
70 |
+
|
71 |
+
//Current and Strike Price
|
72 |
+
$aalb_node = $this->add_price_nodes($item, $aalb_node);
|
73 |
+
|
74 |
+
|
75 |
+
//Node to check "out of stock" items
|
76 |
+
$aalb_node = $this->add_out_of_stock_node($item, $aalb_node, $marketplace);
|
77 |
+
|
78 |
+
|
79 |
+
//If the Buying Price is empty or if is is Too Low to Display
|
80 |
+
if(empty($aalb_node->CurrentPrice) or strtolower($aalb_node->CurrentPrice) == 'too low to display') {
|
81 |
+
$aalb_node->CurrentPrice = $this->internationalization_helper->internationalize_by_marketplace(CHECK_ON_AMAZON, $marketplace);
|
82 |
+
}
|
83 |
+
}
|
84 |
+
|
85 |
+
//add common aalb nodes
|
86 |
+
$aalb_common_node = $items->addChild('aalb-common');
|
87 |
+
$aalb_common_node = $this->add_xml_node($aalb_common_node, $common_marketplace_node_name , 'true');
|
88 |
+
|
89 |
+
return $items;
|
90 |
+
}
|
91 |
+
|
92 |
+
/**
|
93 |
+
* Adds By Information Node
|
94 |
+
* And separated list of all artists, brands and authors
|
95 |
+
*
|
96 |
+
* @since 1.0.0
|
97 |
+
* @param SimpleXMLElement $item Well formed XML String: The Parent item node
|
98 |
+
* @return SimpleXMLElement $aalb_node Node to which values are to be added
|
99 |
+
*/
|
100 |
+
public function add_by_information_node($item, $aalb_node) {
|
101 |
+
$author_array = array();
|
102 |
+
$brand_array = array();
|
103 |
+
$artist_array = array();
|
104 |
+
$by_information = array();
|
105 |
+
foreach ($item->ItemAttributes->Author as $author) {
|
106 |
+
array_push($author_array, $author);
|
107 |
+
}
|
108 |
+
foreach ($item->ItemAttributes->Brand as $brand) {
|
109 |
+
array_push($brand_array, $brand);
|
110 |
+
}
|
111 |
+
foreach ($item->ItemAttributes->Artist as $artist) {
|
112 |
+
array_push($artist_array, $artist);
|
113 |
+
}
|
114 |
+
if(!empty($author_array)) {
|
115 |
+
array_push($by_information, implode(', ', $author_array));
|
116 |
+
}
|
117 |
+
if(!empty($brand_array)) {
|
118 |
+
array_push($by_information, implode(', ', $brand_array));
|
119 |
+
}
|
120 |
+
if(!empty($artist_array)) {
|
121 |
+
array_push($by_information, implode(', ', $artist_array));
|
122 |
+
}
|
123 |
+
$aalb_node->By = implode(' and ', $by_information);
|
124 |
+
return $aalb_node;
|
125 |
+
}
|
126 |
+
|
127 |
+
/**
|
128 |
+
* Adds Savings related nodes
|
129 |
+
* Adds Amount saved in both raw and formatted way and the percentage saved
|
130 |
+
*
|
131 |
+
* @since 1.0.0
|
132 |
+
* @param SimpleXMLElement $item Well formed XML String: The Parent item node
|
133 |
+
* @return SimpleXMLElement $aalb_node Node to which values are to be added
|
134 |
+
*/
|
135 |
+
public function add_savings_node($item, $aalb_node) {
|
136 |
+
$aalb_node = $this->add_xml_node($aalb_node, 'Saving', $item->Offers->Offer->OfferListing->AmountSaved->FormattedPrice);
|
137 |
+
$aalb_node = $this->add_xml_node($aalb_node, 'SavingValue', $item->Offers->Offer->OfferListing->AmountSaved->Amount);
|
138 |
+
$aalb_node = $this->add_xml_node($aalb_node, 'SavingPercent', $item->Offers->Offer->OfferListing->PercentageSaved);
|
139 |
+
return $aalb_node;
|
140 |
+
}
|
141 |
+
|
142 |
+
/**
|
143 |
+
* Adds Minimum Price related nodes
|
144 |
+
* Adds raw and formatted values of minimum price
|
145 |
+
*
|
146 |
+
* @since 1.0.0
|
147 |
+
* @param SimpleXMLElement $item Well formed XML String: The Parent item node
|
148 |
+
* @return SimpleXMLElement $aalb_node Node to which values are to be added
|
149 |
+
*/
|
150 |
+
public function add_min_price_node($item, $aalb_node) {
|
151 |
+
$aalb_node = $this->add_xml_node($aalb_node, 'MinimumPrice', $item->OfferSummary->LowestNewPrice->FormattedPrice);
|
152 |
+
$aalb_node = $this->add_xml_node($aalb_node, 'MinimumPriceValue', $item->OfferSummary->LowestNewPrice->Amount);
|
153 |
+
return $aalb_node;
|
154 |
+
}
|
155 |
+
|
156 |
+
/**
|
157 |
+
* Adds Current Price and Strike Price Nodes after applying logic
|
158 |
+
* Logic for Current Price and Strike Price
|
159 |
+
*
|
160 |
+
* @since 1.0.0
|
161 |
+
* @param SimpleXMLElement $item Well formed XML String: The Parent item node
|
162 |
+
* @return SimpleXMLElement $aalb_node Node to which values are to be added
|
163 |
+
*/
|
164 |
+
public function add_price_nodes($item, $aalb_node) {
|
165 |
+
$list_price = $item->ItemAttributes->ListPrice->FormattedPrice;
|
166 |
+
$price = $item->Offers->Offer->OfferListing->Price->FormattedPrice;
|
167 |
+
$sale_price = $item->Offers->Offer->OfferListing->SalePrice->FormattedPrice;
|
168 |
+
$list_price_amount = $item->ItemAttributes->ListPrice->Amount;
|
169 |
+
$price_amount = $item->Offers->Offer->OfferListing->Price->Amount;
|
170 |
+
$sale_price_amount = $item->Offers->Offer->OfferListing->SalePrice->Amount;
|
171 |
+
if(!empty($sale_price_amount)) {
|
172 |
+
//If Sale Price is returned
|
173 |
+
$aalb_node->CurrentPrice = $sale_price;
|
174 |
+
$aalb_node->CurrentPriceValue = $sale_price_amount;
|
175 |
+
$aalb_node->StrikePrice = $price;
|
176 |
+
$aalb_node->StrikePriceValue = $price_amount;
|
177 |
+
} else {
|
178 |
+
//If List Price is not returned or ListPrice<Price
|
179 |
+
if(empty($list_price_amount) or ((int)$list_price_amount < (int)$price_amount)) {
|
180 |
+
$aalb_node->CurrentPrice = $price;
|
181 |
+
$aalb_node->CurrentPriceValue = $price_amount;
|
182 |
+
} else {
|
183 |
+
$aalb_node->CurrentPrice = $price;
|
184 |
+
$aalb_node->CurrentPriceValue = $price_amount;
|
185 |
+
//Add StrikePrice node only if there is a difference with CurrentPrice amount
|
186 |
+
if((int)$list_price_amount > (int)$price_amount) {
|
187 |
+
$aalb_node->StrikePrice = $list_price;
|
188 |
+
$aalb_node->StrikePriceValue = $list_price_amount;
|
189 |
+
}
|
190 |
+
}
|
191 |
+
}
|
192 |
+
return $aalb_node;
|
193 |
+
}
|
194 |
+
|
195 |
+
/**
|
196 |
+
* Adds InStock node if the item is in stock; Updates Current Price otherwise
|
197 |
+
*
|
198 |
+
* @since 1.0.0
|
199 |
+
* @param SimpleXMLElement $item Well formed XML String: The Parent item node
|
200 |
+
* @return SimpleXMLElement $aalb_node Node to which values are to be added
|
201 |
+
*/
|
202 |
+
public function add_out_of_stock_node($item, $aalb_node, $marketplace) {
|
203 |
+
$total_new = $item->OfferSummary->TotalNew;
|
204 |
+
$availability = $item->Offers->Offer->OfferListing->Availability;
|
205 |
+
if(($total_new == '0' or $availability == "Out of Stock")) {
|
206 |
+
//If the item is out of stock, update Buying Price
|
207 |
+
$aalb_node->CurrentPrice = $this->internationalization_helper->internationalize_by_marketplace(OUT_OF_STOCK, $marketplace);;
|
208 |
+
} else {
|
209 |
+
//If the item is in stock; add a xml node to identify values in stock
|
210 |
+
$aalb_node->InStock = 'Yes True';
|
211 |
+
}
|
212 |
+
return $aalb_node;
|
213 |
+
}
|
214 |
+
|
215 |
+
/**
|
216 |
+
* Adds a child xml node to a given parent node if the value is not empty.
|
217 |
+
*
|
218 |
+
* @since 1.0.0
|
219 |
+
* @param SimpleXMLElement $parent_node PHP XML Object of parent node
|
220 |
+
* @param string $node_name Name of the new node to be added
|
221 |
+
* @param string $node_value Value of the new node to be added
|
222 |
+
* @return SimpleXMLElement $parent_node Parent node with added child node
|
223 |
+
*/
|
224 |
+
public function add_xml_node($parent_node, $node_name, $node_value) {
|
225 |
+
if(!empty($node_value)) {
|
226 |
+
$parent_node->$node_name = $node_value;
|
227 |
+
}
|
228 |
+
return $parent_node;
|
229 |
+
}
|
230 |
+
|
231 |
+
/**
|
232 |
+
* Adds Click URL Prefix to requierd hyperlinks
|
233 |
+
*
|
234 |
+
* @since 1.0.0
|
235 |
+
* @param SimpleXMLElement $items Well formed XML String
|
236 |
+
* @return SimpleXMLElement $items XML String with hyperlinks prefixed with click URL
|
237 |
+
*/
|
238 |
+
public function prefix_click_URL($items) {
|
239 |
+
foreach ($items->Item as $item) {
|
240 |
+
$item->DetailPageURL = '[[CLICK_URL_PREFIX]]' . $item->DetailPageURL;
|
241 |
+
}
|
242 |
+
return $items;
|
243 |
+
}
|
244 |
+
}
|
245 |
+
|
246 |
+
?>
|
readme.txt
ADDED
@@ -0,0 +1,110 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
=== Amazon Associates Link Builder ===
|
2 |
+
Contributors: @amazonlinkbuilder
|
3 |
+
Tags: Amazon, Affiliate, Associates, Amazon Associates, Amazon Associate, Product Advertising API, Amazon API, Amazon Link, Amazon Ad, Amazon Affiliate, eCommerce
|
4 |
+
Requires at least: 3.0.1
|
5 |
+
Tested up to: 4.4
|
6 |
+
Stable tag: 1.0
|
7 |
+
License: GPLv2
|
8 |
+
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
9 |
+
|
10 |
+
The official plugin from the Amazon Associates Program.
|
11 |
+
|
12 |
+
== Description ==
|
13 |
+
= About Amazon Associates Program =
|
14 |
+
The Amazon Associates Program is one of the original affiliate marketing programs. Available in geographies across the globe, the Amazon Associates Program has been partnering with content creators to help them monetize their passions since 1996. To learn more about the Amazon Associates Program, please click [here](https://affiliate-program.amazon.com/).
|
15 |
+
|
16 |
+
= About Amazon Associates Link Builder =
|
17 |
+
Link Builder is the official free Amazon Associates Program plugin for WordPress. The plugin enables you to search for products in the Amazon catalog, access real-time price and availability information, and easily create links in your posts to products on Amazon.com. You will be able to generate text links, create custom ad units, or take advantage of out-of-the-box widgets that we’ve designed and included with the plugin.
|
18 |
+
|
19 |
+
= Note =
|
20 |
+
* You must review and accept the Amazon Associates Link Builder Conditions of Use as applicable for your region - [US](https://s3.amazonaws.com/aalb-public-resources/documents/AssociatesLinkBuilder-ConditionsOfUse-US.pdf)| [CA](https://s3.amazonaws.com/aalb-public-resources/documents/AssociatesLinkBuilder-ConditionsOfUse-CA.pdf)| [EU](https://s3.amazonaws.com/aalb-public-resources/documents/AssociatesLinkBuilder-ConditionsOfUse-EU.pdf).
|
21 |
+
* The plugin is currently in beta form. We intend to regularly add new features and enhancements throughout the beta period and beyond, and welcome your feedback and input.
|
22 |
+
|
23 |
+
== Installation ==
|
24 |
+
|
25 |
+
= Pre-requisites =
|
26 |
+
__Become an Associate__ <br />
|
27 |
+
To become an Associate, create an Amazon Associates account using URL for your country:
|
28 |
+
Brazil https://associados.amazon.com.br/ <br />
|
29 |
+
Canada https://associates.amazon.ca/ <br />
|
30 |
+
China https://associates.amazon.cn/ <br />
|
31 |
+
France https://partenaires.amazon.fr/ <br />
|
32 |
+
Germany http://partnernet.amazon.de/ <br />
|
33 |
+
India https://affiliate-program.amazon.in/ <br />
|
34 |
+
Italy https://programma-affiliazione.amazon.it/ <br />
|
35 |
+
Japan https://affiliate.amazon.co.jp/ <br />
|
36 |
+
Mexico https://afiliados.amazon.com.mx/ <br />
|
37 |
+
Spain https://afiliados.amazon.es/ <br />
|
38 |
+
United Kingdom https://affiliate-program.amazon.co.uk/ <br />
|
39 |
+
United States http://affiliate-program.amazon.com/ <br />
|
40 |
+
<br />
|
41 |
+
Your Associate ID works only in the country in which you register. If you’d like to be an Associate in more than one country, please register separately for each country.
|
42 |
+
<br />
|
43 |
+
|
44 |
+
__Sign up for Product Advertising API__ <br />
|
45 |
+
Sign up for the Amazon Product Advertising API by following the instructions listed [here](http://docs.aws.amazon.com/AWSECommerceService/latest/DG/CHAP_GettingStarted.html). The Amazon Product Advertising API is a popular e-commerce service, powering Amazon-integrated experiences around the world, serving tens of thousands of applications and more than 1 billion API requests every day. It exposes a web-service, which allows Associates to programmatically search and look up items in the Amazon product catalog. The Link Builder plugin integrates the Product Advertising API, allowing you to access Amazon.com product catalog data without requiring additional software development.
|
46 |
+
|
47 |
+
= Installing =
|
48 |
+
To install the Amazon Associates Link Builder plugin:
|
49 |
+
1. Log in to your WordPress dashboard, navigate to the Plugins menu and click Add New.
|
50 |
+
2. In the search field type “Amazon Associates Link Builder” and click Search Plugins. You can install it by simply clicking “Install Now”.
|
51 |
+
|
52 |
+
= Updating =
|
53 |
+
Automatic updates should work like a charm. That said, it’s always good practice to back up your templates just in case.
|
54 |
+
|
55 |
+
= User Guide =
|
56 |
+
You can review the “About” section under the Associates Link Builder menu bar or [Link Builder User Guide](https://s3.amazonaws.com/aalb-public-resources/documents/AssociatesLinkBuilder-UserGuide.pdf) for more information on getting started and key features of the plugin.
|
57 |
+
|
58 |
+
= Configure plugin for first use =
|
59 |
+
Use the Associates Link Builder->Settings screen to configure the plugin.
|
60 |
+
1. Set Access Key ID and Secret Access Key in the Settings section. These credentials are used to invoke requests to the Amazon Product Advertising API for fetching information on an item.
|
61 |
+
2. Set default Associate ID. Associate ID is used to monitor traffic and sales from your links to Amazon. You can also define a list of valid Associate IDs (store ids or tracking ids). You should create a new tracking ID in your Amazon Associates account for using it as Associate ID in the plugin.
|
62 |
+
3. Set the default Amazon marketplace based on the Amazon Associates Program for which you are registered (for example, if you’ve signed up for the Amazon Associates Program in UK, then your default marketplace selection should be UK) and select an appropriate template for rendering your ads.
|
63 |
+
|
64 |
+
<br />
|
65 |
+
That's it! You’re all set to start adding Amazon affiliate links to your posts using the Amazon Associates Link Builder plugin!
|
66 |
+
|
67 |
+
= Support =
|
68 |
+
If you get stuck, or have any questions, you can ask for help in the [Amazon Associates Link Builder plugin forum](https://wordpress.org/support/plugin/amazon-link-builder).
|
69 |
+
|
70 |
+
== Screenshots ==
|
71 |
+
1. Amazon Associates Link Builder settings console
|
72 |
+
2. Search for products in Amazon catalog directly from the WordPress toolbar while creating a new post or a page
|
73 |
+
3. Select the products you would like to advertise
|
74 |
+
4. Associate a template and Associates Id to your links
|
75 |
+
5. Product Carousel Template: Stylishly designed and responsive ad unit that automatically adapts for different device types and screen resolutions that can be placed within or at the end of your content
|
76 |
+
6. Product Ad Template: A variation of the product carousel template for advertising one product at a time
|
77 |
+
7. Product Grid Template: Another variation of the product carousel template that can be used to display a grid of products alongside your content
|
78 |
+
8. Price Link Template: Dynamic hyperlink containing the current price offered for buying the item on Amazon
|
79 |
+
9. Create custom ad templates native to your site’ styling
|
80 |
+
|
81 |
+
== Frequently Asked Questions ==
|
82 |
+
|
83 |
+
= Where can I find more information on the Amazon Associates Program? =
|
84 |
+
You can find more information on the Amazon Associates Program at [Amazon Associates Help](https://affiliate-program.amazon.com/help/node).
|
85 |
+
|
86 |
+
= How does the plugin work? =
|
87 |
+
The plugin makes real-time calls to the Amazon Product Advertising API to search for, and look up information on, items in Amazon.com’s product catalog. Security credentials provided in the Settings console are used for signing API requests. The plugin also contains an in-build caching mechanism to cache the API results for optimizing the API usage and reducing the loading time of the link content.
|
88 |
+
|
89 |
+
= Can I track the performance of the ad units created using the plugin? =
|
90 |
+
Yes. You can track the performance of the ad unit by placement or section of your website by using tracking ids. You are recommended to use different tracking ids for different ad templates. This will allow you to track orders and earnings information for each type of ad using the reports section in Associates Central. You can create tracking ids [here](https://affiliate-program.amazon.com/home/account/tag/manage).
|
91 |
+
|
92 |
+
= What information is shared with Amazon? =
|
93 |
+
Information we learn from Amazon Associates Link Builder users helps us to evaluate performance of the plugin, troubleshoot technical issues, and generally improve the plugin. We only capture information on impressions, clicks, and sales for Amazon affiliate links in accordance with the [Amazon.com Privacy Notice](https://www.amazon.com/gp/help/customer/display.html?nodeId=468496).
|
94 |
+
|
95 |
+
= Where can I find support? =
|
96 |
+
You can review the “About” section under the Associates Link Builder menu bar or [Link Builder User Guide](https://s3.amazonaws.com/aalb-public-resources/documents/AssociatesLinkBuilder-UserGuide.pdf) for more information on getting started and key features of the plugin. If you get stuck, or have any questions, you can ask for help in the [Amazon Associates Link Builder Plugin Forum](https://wordpress.org/support/plugin/amazon-link-builder).
|
97 |
+
|
98 |
+
= How can I add links to different Amazon sites in my blog? =
|
99 |
+
You can search products using keywords in any supported country, but you have to join the Associates Program in those countries separately to be able to do this. For example – If you are a blogger in UK interested in linking to Amazon.com (US) site, then you will first need to join the Amazon Associates Program in US to be able to search for products on Amazon.com site.
|
100 |
+
|
101 |
+
== Changelog ==
|
102 |
+
|
103 |
+
= 1.0 =
|
104 |
+
12/12/2016 <br />
|
105 |
+
* Plugin released for beta testing
|
106 |
+
|
107 |
+
== Upgrade Notice ==
|
108 |
+
|
109 |
+
= 1.0 =
|
110 |
+
Install the Amazon Associates Link Builder plugin for WordPress!
|
shortcode/aalb_shortcode.php
ADDED
@@ -0,0 +1,240 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
Copyright 2016-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
5 |
+
|
6 |
+
Licensed under the GNU General Public License as published by the Free Software Foundation,
|
7 |
+
Version 2.0 (the "License"). You may not use this file except in compliance with the License.
|
8 |
+
A copy of the License is located in the "license" file accompanying this file.
|
9 |
+
|
10 |
+
This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
11 |
+
either express or implied. See the License for the specific language governing permissions
|
12 |
+
and limitations under the License.
|
13 |
+
*/
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Fired when a shortcode is there in the post page.
|
17 |
+
*
|
18 |
+
* Gets the product information by making a Paapi request and renders the HTML
|
19 |
+
*
|
20 |
+
* @since 1.0.0
|
21 |
+
* @package AmazonAssociatesLinkBuilder
|
22 |
+
* @subpackage AmazonAssociatesLinkBuilder/shortcode
|
23 |
+
*/
|
24 |
+
|
25 |
+
class Aalb_Shortcode {
|
26 |
+
|
27 |
+
protected $paapi_helper;
|
28 |
+
protected $template_engine;
|
29 |
+
protected $helper;
|
30 |
+
protected $config_loader;
|
31 |
+
protected $validation_helper;
|
32 |
+
protected $tracking_api_helper;
|
33 |
+
|
34 |
+
public function __construct() {
|
35 |
+
$this->template_engine = new Aalb_Template_Engine();
|
36 |
+
$this->paapi_helper = new Aalb_Paapi_Helper();
|
37 |
+
$this->helper = new Aalb_Helper();
|
38 |
+
$this->config_loader = new Aalb_Config_Loader();
|
39 |
+
$this->validation_helper = new Aalb_Validation_Helper();
|
40 |
+
$this->tracking_api_helper = new Aalb_Tracking_Api_Helper();
|
41 |
+
}
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Add basic styles
|
45 |
+
*
|
46 |
+
* @since 1.0.0
|
47 |
+
*/
|
48 |
+
public function enqueue_styles() {
|
49 |
+
wp_enqueue_style('aalb_basics_css', AALB_BASICS_CSS );
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Add CSS for the template
|
54 |
+
*
|
55 |
+
* @since 1.0.0
|
56 |
+
*/
|
57 |
+
public function enqueue_template_styles($template_name) {
|
58 |
+
wp_enqueue_style('aalb_template' . $template_name . '_css', AALB_TEMPLATE_URL . $template_name . '.css' );
|
59 |
+
}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* The function responsible for rendering the shortcode.
|
63 |
+
* Makes a GET request and calls the render_xml to render the response.
|
64 |
+
*
|
65 |
+
* @since 1.0.0
|
66 |
+
* @param array $atts Shortcode attribute and values.
|
67 |
+
* @return HTML Rendered html to display.
|
68 |
+
*/
|
69 |
+
public function render($atts) {
|
70 |
+
try {
|
71 |
+
$shortcode_attributes = $this->get_shortcode_attributes($atts);
|
72 |
+
|
73 |
+
$validated_link_id = $this->get_validated_link_id($shortcode_attributes['link_id']);
|
74 |
+
$validated_marketplace = $this->get_validated_marketplace($shortcode_attributes['marketplace']);
|
75 |
+
$validated_asins = $this->get_validated_asins($shortcode_attributes['asins']);
|
76 |
+
$validated_template = $this->get_validated_template($shortcode_attributes['template']);
|
77 |
+
$validated_store_id = $this->get_validated_store_id($shortcode_attributes['store']);
|
78 |
+
|
79 |
+
$marketplace = $this->get_marketplace_endpoint($validated_marketplace);
|
80 |
+
$url = $this->paapi_helper->get_item_lookup_url($validated_asins, $marketplace, $validated_store_id);
|
81 |
+
$asins = $this->format_asins($validated_asins);
|
82 |
+
$products_key = $this->helper->build_products_cache_key($asins, $marketplace, $validated_store_id);
|
83 |
+
$products_template_key = $this->helper->build_template_cache_key($asins, $marketplace, $validated_store_id, $validated_template );
|
84 |
+
|
85 |
+
$impression_params = $this->tracking_api_helper->get_impression_params($validated_link_id, AALB_SHORTCODE_AMAZON_LINK, $shortcode_attributes);
|
86 |
+
$click_url = $this->tracking_api_helper->get_click_url($impression_params);
|
87 |
+
$this->tracking_api_helper->insert_pixel($impression_params);
|
88 |
+
$this->enqueue_template_styles($validated_template);
|
89 |
+
|
90 |
+
return str_replace(array('[[CLICK_URL_PREFIX]]','[[UNIQUE_ID]]'), array($click_url, str_replace('.','-',$products_template_key)), $this->template_engine->render($products_template_key, $products_key, $validated_template, $url, $validated_marketplace));
|
91 |
+
} catch (Exception $e) {
|
92 |
+
error_log($this->paapi_helper->get_error_message($e->getMessage()));
|
93 |
+
}
|
94 |
+
|
95 |
+
}
|
96 |
+
|
97 |
+
/**
|
98 |
+
* Returns default shortcode attributes if not mentioned
|
99 |
+
*
|
100 |
+
* @since 1.0.0
|
101 |
+
* @param array $atts Shortcode attributes.
|
102 |
+
* @return array Default shortcode attributes if not mentioned.
|
103 |
+
*/
|
104 |
+
private function get_shortcode_attributes($atts) {
|
105 |
+
$shortcode_attributes=shortcode_atts(array(
|
106 |
+
'asins' => null,
|
107 |
+
'marketplace' => get_option(AALB_DEFAULT_MARKETPLACE),
|
108 |
+
'store' => get_option(AALB_DEFAULT_STORE_ID),
|
109 |
+
'template' => get_option(AALB_DEFAULT_TEMPLATE),
|
110 |
+
'link_id' => null
|
111 |
+
),$atts);
|
112 |
+
return $shortcode_attributes;
|
113 |
+
}
|
114 |
+
|
115 |
+
/**
|
116 |
+
* Format comma separated asins into hypen separated asins for building key.
|
117 |
+
* Checks for more spaces and trims it.
|
118 |
+
*
|
119 |
+
* @since 1.0.0
|
120 |
+
* @param string $asins Comma separated asins.
|
121 |
+
* @return string Hyphen separated asins.
|
122 |
+
*/
|
123 |
+
private function format_asins($asins) {
|
124 |
+
return preg_replace('/[ ,]+/', '-', trim($asins));
|
125 |
+
}
|
126 |
+
|
127 |
+
/**
|
128 |
+
* Get marketplace endpoint for marketplace abbreviation
|
129 |
+
*
|
130 |
+
* @since 1.0.0
|
131 |
+
* @param string $marketplace_abbr Marketplace Abbreviation from shortcode
|
132 |
+
* @return string $marketplace_endpoint Marketplace endpoint
|
133 |
+
*/
|
134 |
+
public function get_marketplace_endpoint($marketplace_abbr) {
|
135 |
+
$marketplace_endpoint = "";
|
136 |
+
$aalb_marketplace_names = $this->config_loader->fetch_marketplaces();
|
137 |
+
$marketplace_endpoint = array_search($marketplace_abbr, $aalb_marketplace_names);
|
138 |
+
return $marketplace_endpoint;
|
139 |
+
}
|
140 |
+
|
141 |
+
/**
|
142 |
+
* Get validated link-id
|
143 |
+
* Checks if the link id we got from the api is valid or not and returns
|
144 |
+
* validated link-id. In case of invalid marketplace, it returns empty string.
|
145 |
+
*
|
146 |
+
* @since 1.0.0
|
147 |
+
* @param string $marketplace Marketplace from shortcode
|
148 |
+
* @return string $validated_template Validated marketplace
|
149 |
+
*/
|
150 |
+
public function get_validated_link_id($link_id) {
|
151 |
+
$validated_link_id = $link_id;
|
152 |
+
if(!$this->validation_helper->validate_link_id($link_id)) {
|
153 |
+
//If the link id is not valid, return empty string
|
154 |
+
$validated_link_id = '';
|
155 |
+
}
|
156 |
+
return $validated_link_id;
|
157 |
+
}
|
158 |
+
|
159 |
+
/**
|
160 |
+
* Get validated marketplace.
|
161 |
+
* Checks if a marketplace abbreviation from shortcode is valid and returns
|
162 |
+
* validated marketplace. In case of invalid marketplace, it returns default marketplace.
|
163 |
+
*
|
164 |
+
* @since 1.0.0
|
165 |
+
* @param string $marketplace Marketplace from shortcode
|
166 |
+
* @return string $validated_template Validated marketplace
|
167 |
+
*/
|
168 |
+
public function get_validated_marketplace($marketplace) {
|
169 |
+
//Changing case of the marketplace to upper. Ensures case insensitivity
|
170 |
+
$validated_marketplace = strtoupper($marketplace);
|
171 |
+
if(!$this->validation_helper->validate_marketplace($marketplace)) {
|
172 |
+
//If the marketplace is not valid, return default marketplace
|
173 |
+
$validated_marketplace = get_option(AALB_DEFAULT_MARKETPLACE);
|
174 |
+
}
|
175 |
+
return $validated_marketplace;
|
176 |
+
}
|
177 |
+
|
178 |
+
/**
|
179 |
+
* Get validated asin list
|
180 |
+
* Drops invalid asin from the list
|
181 |
+
*
|
182 |
+
* @since 1.0.0
|
183 |
+
* @param string $asins List of asins from shortcode
|
184 |
+
* @return string List of validated asins
|
185 |
+
*/
|
186 |
+
public function get_validated_asins($asins) {
|
187 |
+
//Creates array of asins in the shortcode
|
188 |
+
$asins_array = explode(',', $asins);
|
189 |
+
foreach ($asins_array as $asin) {
|
190 |
+
if (!$this->validation_helper->validate_asin($asin)) {
|
191 |
+
//Drop Invalid ASIN out of list of asins
|
192 |
+
$asins_array = array_diff($asins_array, array($asin));
|
193 |
+
//Show error message regarding incorrect asin in preview mode only
|
194 |
+
$this->helper->show_error_in_preview("The ASIN: '" . $asin . "' is invalid.");
|
195 |
+
}
|
196 |
+
}
|
197 |
+
return implode(',',$asins_array);
|
198 |
+
}
|
199 |
+
|
200 |
+
/**
|
201 |
+
* Get validated template.
|
202 |
+
* Checks if a template is valid, returns default template otherwise
|
203 |
+
*
|
204 |
+
* @since 1.0.0
|
205 |
+
* @param string $template Template name from shortcode
|
206 |
+
* @return string $validated_template Validated template name
|
207 |
+
*/
|
208 |
+
public function get_validated_template($template) {
|
209 |
+
$validated_template = $template;
|
210 |
+
if (!$this->validation_helper->validate_template_name($template)) {
|
211 |
+
//Return Default template in case of invalid template name
|
212 |
+
$validated_template = get_option(AALB_DEFAULT_TEMPLATE);
|
213 |
+
//Show error message regarding incorrect asin in preview mode only
|
214 |
+
$this->helper->show_error_in_preview("The template: '" . $template . "' is invalid. Using default template '" . $validated_template . "'.");
|
215 |
+
}
|
216 |
+
return $validated_template;
|
217 |
+
}
|
218 |
+
|
219 |
+
/**
|
220 |
+
* Get validated store id.
|
221 |
+
* Checks if a store id is valid, returns default store id otherwise
|
222 |
+
*
|
223 |
+
* @since 1.0.0
|
224 |
+
* @param string $store_id Store ID from shortcode
|
225 |
+
* @return string $validated_store_id Validated Store ID
|
226 |
+
*/
|
227 |
+
public function get_validated_store_id($store_id) {
|
228 |
+
$validated_store_id = $store_id;
|
229 |
+
if (!$this->validation_helper->validate_store_id($store_id)) {
|
230 |
+
//Return Default store id in case of invalid store id
|
231 |
+
$validated_store_id = get_option(AALB_DEFAULT_STORE_ID,AALB_DEFAULT_STORE_ID_NAME);
|
232 |
+
//Show error message regarding incorrect asin in preview mode only
|
233 |
+
$this->helper->show_error_in_preview("The Associate tag '" . $store_id . "' is not present in the list of valid tags. Associate tag has been updated to '" . $validated_store_id . "'. Please check your Associate tag selection or contact the administrator to add a new tag.");
|
234 |
+
}
|
235 |
+
return $validated_store_id;
|
236 |
+
}
|
237 |
+
|
238 |
+
}
|
239 |
+
|
240 |
+
?>
|
shortcode/aalb_shortcode_loader.php
ADDED
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
Copyright 2016-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
5 |
+
|
6 |
+
Licensed under the GNU General Public License as published by the Free Software Foundation,
|
7 |
+
Version 2.0 (the "License"). You may not use this file except in compliance with the License.
|
8 |
+
A copy of the License is located in the "license" file accompanying this file.
|
9 |
+
|
10 |
+
This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
11 |
+
either express or implied. See the License for the specific language governing permissions
|
12 |
+
and limitations under the License.
|
13 |
+
*/
|
14 |
+
|
15 |
+
/**
|
16 |
+
*
|
17 |
+
* Registers the shortcode with the wordpress for rendering the product information.
|
18 |
+
* Makes only a single instance of Aalb_Shortcode for rendering all the shortcodes.
|
19 |
+
*
|
20 |
+
* @since 1.0.0
|
21 |
+
* @package AmazonAssociatesLinkBuilder
|
22 |
+
* @subpackage AmazonAssociatesLinkBuilder/shortcode
|
23 |
+
*/
|
24 |
+
class Aalb_Shortcode_Loader {
|
25 |
+
|
26 |
+
public $shortcode = null;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Create only a single instance of the Aalb Shortcode.
|
30 |
+
* No need to create an instance for rendering each shortcode.
|
31 |
+
*
|
32 |
+
* @since 1.0.0
|
33 |
+
* @return Aalb_Shortcode The instance of Aalb_Shortcode.
|
34 |
+
*/
|
35 |
+
public function get_shortcode() {
|
36 |
+
if(is_null($this->shortcode)) {
|
37 |
+
return new Aalb_Shortcode();
|
38 |
+
}
|
39 |
+
return $this->shortcode;
|
40 |
+
}
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Register shortcode with Wordpress
|
44 |
+
*
|
45 |
+
* @since 1.0.0
|
46 |
+
*/
|
47 |
+
public function add_shortcode() {
|
48 |
+
add_shortcode(AALB_SHORTCODE_AMAZON_LINK, array($this, 'shortcode_callback'));
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Disable shortcode
|
53 |
+
*
|
54 |
+
* @since 1.0.0
|
55 |
+
*/
|
56 |
+
public function remove_shortcode() {
|
57 |
+
remove_shortcode(AALB_SHORTCODE_AMAZON_LINK);
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Callback function for rendering shortcode
|
62 |
+
*
|
63 |
+
*
|
64 |
+
* @since 1.0.0
|
65 |
+
* @param array $atts Shortcode attributes and values.
|
66 |
+
* @return HTML HTML for displaying the templates.
|
67 |
+
*/
|
68 |
+
public function shortcode_callback($atts) {
|
69 |
+
return $this->get_shortcode()->render($atts);
|
70 |
+
}
|
71 |
+
|
72 |
+
}
|
73 |
+
|
74 |
+
?>
|
template/PriceLink.css
ADDED
File without changes
|
template/PriceLink.mustache
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{{#Items}}
|
2 |
+
{{#Item}}
|
3 |
+
{{#aalb}}
|
4 |
+
<a href="{{DetailPageURL}}" target="_blank" rel="nofollow">{{CurrentPrice}}!</a> <!--Individual attributes are provided as variable tags as {{[[attribute]]}}. Check documentation for list of supported variable tags.-->
|
5 |
+
{{/aalb}}
|
6 |
+
{{/Item}}
|
7 |
+
{{/Items}}
|
template/ProductAd.css
ADDED
@@ -0,0 +1,229 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.aalb-pa-ad-unit {
|
2 |
+
/*Enable this border property to have a border around the ad unit*/
|
3 |
+
/*border: 1px solid #d4d4c4;*/
|
4 |
+
background: #ffffff;
|
5 |
+
}
|
6 |
+
/* Actual styles start below */
|
7 |
+
.aalb-pa-ad-unit {
|
8 |
+
position: relative;
|
9 |
+
overflow: hidden;
|
10 |
+
padding: 22px 40px;
|
11 |
+
}
|
12 |
+
.aalb-pa-ad-unit * {
|
13 |
+
box-sizing: content-box;
|
14 |
+
box-shadow: none;
|
15 |
+
font-family: Arial, Helvetica, sans-serif;
|
16 |
+
margin: 0;
|
17 |
+
margin-bottom: 0;
|
18 |
+
margin-left: 0;
|
19 |
+
margin-right: 0;
|
20 |
+
margin-top: 0;
|
21 |
+
outline: 0;
|
22 |
+
padding: 0;
|
23 |
+
padding-bottom: 0;
|
24 |
+
padding-left: 0;
|
25 |
+
padding-right: 0;
|
26 |
+
padding-top: 0;
|
27 |
+
}
|
28 |
+
.aalb-pa-ad-unit.pull-left {
|
29 |
+
float: left;
|
30 |
+
}
|
31 |
+
.aalb-pa-ad-unit.pull-right {
|
32 |
+
float: right;
|
33 |
+
}
|
34 |
+
.aalb-pa-ad-unit.pull-left .aalb-pa-product, .aalb-pa-ad-unit.pull-right .aalb-pa-product {
|
35 |
+
width: 185px !important;
|
36 |
+
}
|
37 |
+
.aalb-pa-ad-unit a {
|
38 |
+
box-shadow: none !important;
|
39 |
+
}
|
40 |
+
.aalb-pa-ad-unit a:hover {
|
41 |
+
color: #c45500;
|
42 |
+
}
|
43 |
+
.aalb-pa-ad-unit .aalb-pa-ad-header {
|
44 |
+
padding-left: 3px;
|
45 |
+
padding-bottom: 9px;
|
46 |
+
font-size: 17px;
|
47 |
+
font-weight: normal;
|
48 |
+
color: #111111;
|
49 |
+
}
|
50 |
+
.aalb-pa-ad-unit .aalb-pa-product-list {
|
51 |
+
overflow: hidden;
|
52 |
+
}
|
53 |
+
.aalb-pa-ad-unit .aalb-pa-product {
|
54 |
+
min-width: 185px;
|
55 |
+
max-width: 385px;
|
56 |
+
height: auto !important;
|
57 |
+
padding-top: 22px;
|
58 |
+
padding-bottom: 22px;
|
59 |
+
margin-left: 10px;
|
60 |
+
margin-right: 10px;
|
61 |
+
float: left;
|
62 |
+
list-style: none;
|
63 |
+
text-align: center;
|
64 |
+
}
|
65 |
+
.aalb-pa-ad-unit .aalb-pa-product-image {
|
66 |
+
display: table;
|
67 |
+
width: 150px;
|
68 |
+
height: 150px;
|
69 |
+
margin: 0 auto;
|
70 |
+
text-align: center;
|
71 |
+
}
|
72 |
+
.aalb-pa-ad-unit .aalb-pa-product-image-wrapper {
|
73 |
+
display: table-cell;
|
74 |
+
vertical-align: middle;
|
75 |
+
}
|
76 |
+
.aalb-pa-ad-unit .aalb-pa-product-image a {
|
77 |
+
position: relative;
|
78 |
+
display: inline-block;
|
79 |
+
vertical-align: middle;
|
80 |
+
}
|
81 |
+
.aalb-pa-ad-unit .aalb-pa-product-image img {
|
82 |
+
max-width: 150px;
|
83 |
+
max-height: 150px;
|
84 |
+
vertical-align: bottom;
|
85 |
+
}
|
86 |
+
.aalb-pa-ad-unit .aalb-pa-percent-off {
|
87 |
+
display: block;
|
88 |
+
width: 32px;
|
89 |
+
height: 27px;
|
90 |
+
padding-top: 5px;
|
91 |
+
position: absolute;
|
92 |
+
top: -16px;
|
93 |
+
right: -16px;
|
94 |
+
color: #ffffff;
|
95 |
+
font-size: 12px;
|
96 |
+
text-align: center;
|
97 |
+
-webkit-border-radius: 50%;
|
98 |
+
-moz-border-radius: 50%;
|
99 |
+
-ms-border-radius: 50%;
|
100 |
+
border-radius: 50%;
|
101 |
+
background-color: #a50200;
|
102 |
+
background-image: -webkit-linear-gradient(top, #cb0400, #a50200);
|
103 |
+
background-image: linear-gradient(to bottom, #cb0400, #a50200);
|
104 |
+
}
|
105 |
+
.aalb-pa-ad-unit.hide-percent-off-badge .aalb-pa-percent-off {
|
106 |
+
display: none;
|
107 |
+
}
|
108 |
+
.aalb-pa-ad-unit .aalb-pa-product-details {
|
109 |
+
display: inline-block;
|
110 |
+
max-width: 100%;
|
111 |
+
margin-top: 11px;
|
112 |
+
text-align: left;
|
113 |
+
}
|
114 |
+
.aalb-pa-ad-unit .aalb-pa-product-title a {
|
115 |
+
display: block;
|
116 |
+
width: 100%;
|
117 |
+
overflow: hidden;
|
118 |
+
white-space: nowrap;
|
119 |
+
text-overflow: ellipsis;
|
120 |
+
font-size: 13px;
|
121 |
+
color: #111111;
|
122 |
+
text-decoration: none;
|
123 |
+
}
|
124 |
+
.aalb-pa-ad-unit.no-truncate .aalb-pa-product-title a {
|
125 |
+
text-overflow: initial;
|
126 |
+
white-space: initial;
|
127 |
+
}
|
128 |
+
.aalb-pa-ad-unit .aalb-pa-product-offer-price {
|
129 |
+
font-size: 13px;
|
130 |
+
color: #111111;
|
131 |
+
}
|
132 |
+
.aalb-pa-ad-unit .aalb-pa-product-offer-price-value {
|
133 |
+
color: #AB1700;
|
134 |
+
font-weight: bold;
|
135 |
+
}
|
136 |
+
.aalb-pa-ad-unit .aalb-pa-product-list-price {
|
137 |
+
font-size: 13px;
|
138 |
+
color: #565656;
|
139 |
+
}
|
140 |
+
.aalb-pa-ad-unit .aalb-pa-product-list-price-value {
|
141 |
+
text-decoration: line-through;
|
142 |
+
}
|
143 |
+
.aalb-pa-ad-unit .aalb-pa-product-prime-icon .icon-prime-all {
|
144 |
+
background: url('https://images-na.ssl-images-amazon.com/images/G/01/AUIClients/AmazonUIBaseCSS-sprite_1x-e1a6545ba46e2ced9fc835dbdec4fff037b5b6bf._V2_.png') no-repeat;
|
145 |
+
display: inline-block;
|
146 |
+
margin-top: -1px;
|
147 |
+
vertical-align: middle;
|
148 |
+
background-position: -205px -246px;
|
149 |
+
width: 47px;
|
150 |
+
height: 15px;
|
151 |
+
}
|
152 |
+
|
153 |
+
.aalb-pa-ad-unit .aalb-pa-product-prime-icon .icon-prime-es {
|
154 |
+
background: url('https://images-na.ssl-images-amazon.com/images/G/01/AUIClients/AmazonUIBaseCSS-sprite_1x-e1a6545ba46e2ced9fc835dbdec4fff037b5b6bf._V2_.png') no-repeat;
|
155 |
+
display: inline-block;
|
156 |
+
margin-top: -1px;
|
157 |
+
vertical-align: middle;
|
158 |
+
background-position: -205px -274px;
|
159 |
+
width: 62px;
|
160 |
+
height: 16px;
|
161 |
+
}
|
162 |
+
|
163 |
+
.aalb-pa-ad-unit .aalb-pa-product-offer-price,
|
164 |
+
.aalb-pa-ad-unit .aalb-pa-product-list-price,
|
165 |
+
.aalb-pa-ad-unit .aalb-pa-product-prime-icon {
|
166 |
+
display: inline-block;
|
167 |
+
margin-right: 2px;
|
168 |
+
}
|
169 |
+
.aalb-pa-ad-unit .aalb-pa-btn-prev,
|
170 |
+
.aalb-pa-ad-unit .aalb-pa-btn-next {
|
171 |
+
position: absolute;
|
172 |
+
top: 50%;
|
173 |
+
margin-top: -52px;
|
174 |
+
display: block;
|
175 |
+
visibility: hidden;
|
176 |
+
width: 43px;
|
177 |
+
height: 105px;
|
178 |
+
z-index: 2;
|
179 |
+
line-height: 105px;
|
180 |
+
background: #ffffff;
|
181 |
+
color: #D0D0D0;
|
182 |
+
font-size: 35px;
|
183 |
+
text-align: center;
|
184 |
+
text-decoration: none;
|
185 |
+
border: 1px solid #e9e9e9;
|
186 |
+
-webkit-box-shadow: 0 0 4px #e9e9e9;
|
187 |
+
box-shadow: 0 0 4px #e9e9e9;
|
188 |
+
}
|
189 |
+
.aalb-pa-ad-unit .aalb-pa-btn-prev:hover,
|
190 |
+
.aalb-pa-ad-unit .aalb-pa-btn-next:hover {
|
191 |
+
color: #999999;
|
192 |
+
}
|
193 |
+
.aalb-pa-ad-unit .aalb-pa-btn-prev:focus,
|
194 |
+
.aalb-pa-ad-unit .aalb-pa-btn-next:focus {
|
195 |
+
outline: none;
|
196 |
+
}
|
197 |
+
.aalb-pa-ad-unit .aalb-pa-btn-prev {
|
198 |
+
left: 0;
|
199 |
+
border-left: 0;
|
200 |
+
border-top-right-radius: 20px;
|
201 |
+
border-bottom-right-radius: 20px;
|
202 |
+
}
|
203 |
+
.aalb-pa-ad-unit .aalb-pa-btn-next {
|
204 |
+
right: 0;
|
205 |
+
border-right: 0;
|
206 |
+
border-top-left-radius: 20px;
|
207 |
+
border-bottom-left-radius: 20px;
|
208 |
+
}
|
209 |
+
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
|
210 |
+
.aalb-pa-ad-unit .aalb-pa-product-prime-icon .icon-prime-all {
|
211 |
+
background: url('https://images-na.ssl-images-amazon.com/images/G/01/AUIClients/AmazonUIBaseCSS-sprite_1x-e1a6545ba46e2ced9fc835dbdec4fff037b5b6bf._V2_.png') no-repeat;
|
212 |
+
display: inline-block;
|
213 |
+
margin-top: -1px;
|
214 |
+
vertical-align: middle;
|
215 |
+
background-position: -205px -246px;
|
216 |
+
width: 47px;
|
217 |
+
height: 15px;
|
218 |
+
}
|
219 |
+
|
220 |
+
.aalb-pa-ad-unit .aalb-pa-product-prime-icon .icon-prime-es {
|
221 |
+
background: url('https://images-na.ssl-images-amazon.com/images/G/01/AUIClients/AmazonUIBaseCSS-sprite_1x-e1a6545ba46e2ced9fc835dbdec4fff037b5b6bf._V2_.png') no-repeat;
|
222 |
+
display: inline-block;
|
223 |
+
margin-top: -1px;
|
224 |
+
vertical-align: middle;
|
225 |
+
background-position: -205px -274px;
|
226 |
+
width: 62px;
|
227 |
+
height: 16px;
|
228 |
+
}
|
229 |
+
}
|
template/ProductAd.mustache
ADDED
@@ -0,0 +1,141 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{{#Items}} <!--Section tag for iterating through the list of items-->
|
2 |
+
<!-- Single product Ad Template Layout. Position of the Ad can be configured by specifying pull-left or pull-right class below-->
|
3 |
+
<div class="aalb-pa-ad-unit pull-left" id="{{ID}}">
|
4 |
+
<div class="aalb-pa-wrapper">
|
5 |
+
<div class="aalb-pa-product-container">
|
6 |
+
<ul class="aalb-pa-product-list">
|
7 |
+
{{#Item}} <!-- Section tag for beginning of information on one item -->
|
8 |
+
{{#aalb}} <!-- Section tag for picking up information on attributes for the item -->
|
9 |
+
<li class="aalb-pa-product">
|
10 |
+
<div class="aalb-pa-product-image">
|
11 |
+
<div class="aalb-pa-product-image-wrapper">
|
12 |
+
<a href="{{DetailPageURL}}" title="{{Title}}" target="_blank" rel="nofollow"> <!--Individual attributes are provided as variable tags as {{[[attribute]]}}. Check documentation for list of supported variable tags.-->
|
13 |
+
<img src="{{MediumImageURL}}" srcset="{{LargeImageURL}}" alt="{{Title}}" />
|
14 |
+
{{#SavingPercent}} <!-- The section tag ensures that percentage savings is displayed only if it is available -->
|
15 |
+
<span class="aalb-pa-percent-off">
|
16 |
+
-{{SavingPercent}}%
|
17 |
+
</span>
|
18 |
+
{{/SavingPercent}}
|
19 |
+
</a>
|
20 |
+
</div>
|
21 |
+
</div>
|
22 |
+
<div class="aalb-pa-product-details">
|
23 |
+
<div class="aalb-pa-product-title">
|
24 |
+
<a href="{{DetailPageURL}}" title="{{Title}}" target="_blank" rel="nofollow">
|
25 |
+
{{Title}}
|
26 |
+
</a>
|
27 |
+
</div>
|
28 |
+
<div class="aalb-pa-product-offer-price">
|
29 |
+
<!-- The section tag for different marketplaces ensures localization of static text. -->
|
30 |
+
{{#MarketplaceUS}}Price{{/MarketplaceUS}}{{#MarketplaceFR}}Prix{{/MarketplaceFR}}{{#MarketplaceIT}}Prezzo{{/MarketplaceIT}}{{#MarketplaceDE}}Preis{{/MarketplaceDE}}{{#MarketplaceES}}Precio{{/MarketplaceES}}{{#MarketplaceBR}}Price{{/MarketplaceBR}}{{#MarketplaceCA}}Price{{/MarketplaceCA}}{{#MarketplaceCN}}Price{{/MarketplaceCN}}{{#MarketplaceIN}}Price{{/MarketplaceIN}}{{#MarketplaceJP}}Price{{/MarketplaceJP}}{{#MarketplaceMX}}Price{{/MarketplaceMX}}{{#MarketplaceUK}}Price{{/MarketplaceUK}}: <span class="aalb-pa-product-offer-price-value">{{CurrentPrice}}</span>
|
31 |
+
</div>
|
32 |
+
{{#StrikePrice}} <!-- The section tag ensures that strike price is displayed only if it is available -->
|
33 |
+
<div class="aalb-pa-product-list-price">
|
34 |
+
<!-- The section tag for different marketplaces ensures localization of static text. -->
|
35 |
+
{{#MarketplaceUS}}Was{{/MarketplaceUS}}{{#MarketplaceFR}}Ancien prix{{/MarketplaceFR}}{{#MarketplaceIT}}Da{{/MarketplaceIT}}{{#MarketplaceDE}}statt{{/MarketplaceDE}}{{#MarketplaceES}}Precio recomendado{{/MarketplaceES}}{{#MarketplaceBR}}Was{{/MarketplaceBR}}{{#MarketplaceCA}}Was{{/MarketplaceCA}}{{#MarketplaceCN}}Was{{/MarketplaceCN}}{{#MarketplaceIN}}Was{{/MarketplaceIN}}{{#MarketplaceJP}}Was{{/MarketplaceJP}}{{#MarketplaceMX}}Was{{/MarketplaceMX}}{{#MarketplaceUK}}Was{{/MarketplaceUK}}: <span class="aalb-pa-product-list-price-value">{{StrikePrice}}</span>
|
36 |
+
</div>
|
37 |
+
{{/StrikePrice}}
|
38 |
+
{{#Prime}} <!-- The section tag ensures that prime icon is displayed only if it is available -->
|
39 |
+
<div class="aalb-pa-product-prime-icon">
|
40 |
+
{{#MarketplaceES}} <!-- Display Prime Icon for ES if marketplace is ES -->
|
41 |
+
<i class="icon-prime-es"></i>
|
42 |
+
{{/MarketplaceES}}
|
43 |
+
{{^MarketplaceES}} <!-- Display Common Prime Icon for all other marketplaces -->
|
44 |
+
<i class="icon-prime-all"></i>
|
45 |
+
{{/MarketplaceES}}
|
46 |
+
</div>
|
47 |
+
{{/Prime}}
|
48 |
+
</div>
|
49 |
+
</li>
|
50 |
+
{{/aalb}}
|
51 |
+
{{/Item}}
|
52 |
+
</ul>
|
53 |
+
</div>
|
54 |
+
</div>
|
55 |
+
<a href="javascript:void(0);" class="aalb-pa-btn-prev">‹</a>
|
56 |
+
<a href="javascript:void(0);" class="aalb-pa-btn-next">›</a>
|
57 |
+
</div>
|
58 |
+
{{/Items}}
|
59 |
+
|
60 |
+
<script>
|
61 |
+
jQuery(document).ready(function() {
|
62 |
+
|
63 |
+
var CONSTANTS = {
|
64 |
+
productMinWidth : 185,
|
65 |
+
productMargin : 20
|
66 |
+
};
|
67 |
+
|
68 |
+
var $adUnits = jQuery('.aalb-pa-ad-unit');
|
69 |
+
$adUnits.each(function() {
|
70 |
+
var $adUnit = jQuery(this),
|
71 |
+
$wrapper = $adUnit.find('.aalb-pa-wrapper'),
|
72 |
+
$productContainer = $adUnit.find('.aalb-pa-product-container'),
|
73 |
+
$btnNext = $adUnit.find('.aalb-pa-btn-next'),
|
74 |
+
$btnPrev = $adUnit.find('.aalb-pa-btn-prev'),
|
75 |
+
$productList = $productContainer.find('.aalb-pa-product-list'),
|
76 |
+
$products = $productList.find('.aalb-pa-product'),
|
77 |
+
productCount = $products.length;
|
78 |
+
|
79 |
+
if (!productCount) {
|
80 |
+
return true;
|
81 |
+
}
|
82 |
+
|
83 |
+
var rows = $adUnit.find('input[name=rows]').length && parseInt($adUnit.find('input[name=rows]').val(), 10),
|
84 |
+
columns = $adUnit.find('input[name=columns]').length && parseInt($adUnit.find('input[name=columns]').val(), 10),
|
85 |
+
disableCarousel = $adUnit.find('input[name=disable-carousel]').length || rows || columns;
|
86 |
+
|
87 |
+
if (columns) {
|
88 |
+
var productContainerMinWidth = columns * (CONSTANTS.productMinWidth + CONSTANTS.productMargin) + 'px';
|
89 |
+
$adUnit.css('min-width', productContainerMinWidth);
|
90 |
+
$productContainer.css('min-width', productContainerMinWidth);
|
91 |
+
$products.filter(':nth-child(' + columns + 'n + 1)').css('clear', 'both');
|
92 |
+
}
|
93 |
+
|
94 |
+
if (rows && columns) {
|
95 |
+
var cutOffIndex = (rows * columns) - 1;
|
96 |
+
$products.filter(':gt(' + cutOffIndex + ')').remove();
|
97 |
+
}
|
98 |
+
|
99 |
+
function updateLayout() {
|
100 |
+
var wrapperWidth = $wrapper.width(),
|
101 |
+
possibleColumns = columns || parseInt(wrapperWidth / (CONSTANTS.productMinWidth + CONSTANTS.productMargin), 10),
|
102 |
+
actualColumns = columns || possibleColumns < productCount ? possibleColumns : productCount,
|
103 |
+
productWidth = parseInt(wrapperWidth / actualColumns, 10) - CONSTANTS.productMargin;
|
104 |
+
|
105 |
+
$products.css('width', productWidth + 'px');
|
106 |
+
|
107 |
+
if (!disableCarousel) {
|
108 |
+
if ((productCount * productWidth > wrapperWidth) && actualColumns !== 1) {
|
109 |
+
$btnNext.css('visibility', 'visible').removeClass('disabled').unbind('click');
|
110 |
+
$btnPrev.css('visibility', 'visible').removeClass('disabled').unbind('click');
|
111 |
+
$productContainer.jCarouselLite({
|
112 |
+
btnNext : '#' + $adUnit.attr('id') + ' .aalb-pa-btn-next',
|
113 |
+
btnPrev : '#' + $adUnit.attr('id') + ' .aalb-pa-btn-prev',
|
114 |
+
visible : actualColumns,
|
115 |
+
circular : false
|
116 |
+
});
|
117 |
+
} else {
|
118 |
+
$productContainer.css('width', 'auto');
|
119 |
+
$productList.css('width', 'auto');
|
120 |
+
$btnNext.css('visibility', 'hidden').unbind('click');
|
121 |
+
$btnPrev.css('visibility', 'hidden').unbind('click');
|
122 |
+
}
|
123 |
+
}
|
124 |
+
}
|
125 |
+
|
126 |
+
updateLayout();
|
127 |
+
jQuery(window).resize(updateLayout);
|
128 |
+
});
|
129 |
+
});
|
130 |
+
|
131 |
+
/*!
|
132 |
+
* jCarouselLite - v1.1 - 2014-09-28
|
133 |
+
* http://www.gmarwaha.com/jquery/jcarousellite/
|
134 |
+
* Copyright (c) 2014 Ganeshji Marwaha
|
135 |
+
* Licensed MIT (https://github.com/ganeshmax/jcarousellite/blob/master/LICENSE)
|
136 |
+
*/
|
137 |
+
|
138 |
+
!function(a){a.jCarouselLite={version:"1.1"},a.fn.jCarouselLite=function(b){return b=a.extend({},a.fn.jCarouselLite.options,b||{}),this.each(function(){function c(a){return n||(clearTimeout(A),z=a,b.beforeStart&&b.beforeStart.call(this,i()),b.circular?j(a):k(a),m({start:function(){n=!0},done:function(){b.afterEnd&&b.afterEnd.call(this,i()),b.auto&&h(),n=!1}}),b.circular||l()),!1}function d(){if(n=!1,o=b.vertical?"top":"left",p=b.vertical?"height":"width",q=B.find(">ul"),r=q.find(">li"),x=r.size(),w=x<b.visible?x:b.visible,b.circular){var c=r.slice(x-w).clone(),d=r.slice(0,w).clone();q.prepend(c).append(d),b.start+=w}s=a("li",q),y=s.size(),z=b.start}function e(){B.css("visibility","visible"),s.css({overflow:"hidden","float":b.vertical?"none":"left"}),q.css({margin:"0",padding:"0",position:"relative","list-style":"none","z-index":"1"}),B.css({overflow:"hidden",position:"relative","z-index":"2",left:"0px"}),!b.circular&&b.btnPrev&&0==b.start&&a(b.btnPrev).addClass("disabled")}function f(){t=b.vertical?s.outerHeight(!0):s.outerWidth(!0),u=t*y,v=t*w,s.css({width:s.width(),height:s.height()}),q.css(p,u+"px").css(o,-(z*t)),B.css(p,v+"px")}function g(){b.btnPrev&&a(b.btnPrev).click(function(){return c(z-b.scroll)}),b.btnNext&&a(b.btnNext).click(function(){return c(z+b.scroll)}),b.btnGo&&a.each(b.btnGo,function(d,e){a(e).click(function(){return c(b.circular?w+d:d)})}),b.mouseWheel&&B.mousewheel&&B.mousewheel(function(a,d){return c(d>0?z-b.scroll:z+b.scroll)}),b.auto&&h()}function h(){A=setTimeout(function(){c(z+b.scroll)},b.auto)}function i(){return s.slice(z).slice(0,w)}function j(a){var c;a<=b.start-w-1?(c=a+x+b.scroll,q.css(o,-(c*t)+"px"),z=c-b.scroll):a>=y-w+1&&(c=a-x-b.scroll,q.css(o,-(c*t)+"px"),z=c+b.scroll)}function k(a){0>a?z=0:a>y-w&&(z=y-w)}function l(){a(b.btnPrev+","+b.btnNext).removeClass("disabled"),a(z-b.scroll<0&&b.btnPrev||z+b.scroll>y-w&&b.btnNext||[]).addClass("disabled")}function m(c){n=!0,q.animate("left"==o?{left:-(z*t)}:{top:-(z*t)},a.extend({duration:b.speed,easing:b.easing},c))}var n,o,p,q,r,s,t,u,v,w,x,y,z,A,B=a(this);d(),e(),f(),g()})},a.fn.jCarouselLite.options={btnPrev:null,btnNext:null,btnGo:null,mouseWheel:!1,auto:null,speed:200,easing:null,vertical:!1,circular:!0,visible:3,start:0,scroll:1,beforeStart:null,afterEnd:null}}(jQuery);
|
139 |
+
|
140 |
+
|
141 |
+
</script>
|
template/ProductCarousel.css
ADDED
@@ -0,0 +1,230 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.aalb-pc-ad-unit {
|
2 |
+
/*Enable this border property to have a border around the ad unit*/
|
3 |
+
/*border: 1px solid #d4d4c4;*/
|
4 |
+
background: #ffffff;
|
5 |
+
}
|
6 |
+
/* Actual styles start below */
|
7 |
+
.aalb-pc-ad-unit {
|
8 |
+
position: relative;
|
9 |
+
overflow: hidden;
|
10 |
+
padding: 22px 40px;
|
11 |
+
}
|
12 |
+
.aalb-pc-ad-unit * {
|
13 |
+
box-sizing: content-box;
|
14 |
+
box-shadow: none;
|
15 |
+
font-family: Arial, Helvetica, sans-serif;
|
16 |
+
margin: 0;
|
17 |
+
margin-bottom: 0;
|
18 |
+
margin-left: 0;
|
19 |
+
margin-right: 0;
|
20 |
+
margin-top: 0;
|
21 |
+
outline: 0;
|
22 |
+
padding: 0;
|
23 |
+
padding-bottom: 0;
|
24 |
+
padding-left: 0;
|
25 |
+
padding-right: 0;
|
26 |
+
padding-top: 0;
|
27 |
+
}
|
28 |
+
.aalb-pc-ad-unit.pull-left {
|
29 |
+
float: left;
|
30 |
+
}
|
31 |
+
.aalb-pc-ad-unit.pull-right {
|
32 |
+
float: right;
|
33 |
+
}
|
34 |
+
.aalb-pc-ad-unit.pull-left .aalb-pc-product, .aalb-pc-ad-unit.pull-right .aalb-pc-product {
|
35 |
+
width: 185px !important;
|
36 |
+
}
|
37 |
+
.aalb-pc-ad-unit a {
|
38 |
+
box-shadow: none !important;
|
39 |
+
}
|
40 |
+
.aalb-pc-ad-unit a:hover {
|
41 |
+
color: #c45500;
|
42 |
+
}
|
43 |
+
.aalb-pc-ad-unit .aalb-pc-ad-header {
|
44 |
+
padding-left: 3px;
|
45 |
+
padding-bottom: 9px;
|
46 |
+
font-size: 17px;
|
47 |
+
font-weight: normal;
|
48 |
+
color: #111111;
|
49 |
+
}
|
50 |
+
.aalb-pc-ad-unit .aalb-pc-product-list {
|
51 |
+
/* Remove the border-top to remove the horizontal line after the Ad Header*/
|
52 |
+
border-top: 2px solid #f7f7f7;
|
53 |
+
overflow: hidden;
|
54 |
+
}
|
55 |
+
.aalb-pc-ad-unit .aalb-pc-product {
|
56 |
+
min-width: 185px;
|
57 |
+
max-width: 385px;
|
58 |
+
height: auto !important;
|
59 |
+
padding-top: 22px;
|
60 |
+
padding-bottom: 22px;
|
61 |
+
margin-left: 10px;
|
62 |
+
margin-right: 10px;
|
63 |
+
float: left;
|
64 |
+
list-style: none;
|
65 |
+
text-align: center;
|
66 |
+
}
|
67 |
+
.aalb-pc-ad-unit .aalb-pc-product-image {
|
68 |
+
display: table;
|
69 |
+
width: 150px;
|
70 |
+
height: 150px;
|
71 |
+
margin: 0 auto;
|
72 |
+
text-align: center;
|
73 |
+
}
|
74 |
+
.aalb-pc-ad-unit .aalb-pc-product-image-wrapper {
|
75 |
+
display: table-cell;
|
76 |
+
vertical-align: middle;
|
77 |
+
}
|
78 |
+
.aalb-pc-ad-unit .aalb-pc-product-image a {
|
79 |
+
position: relative;
|
80 |
+
display: inline-block;
|
81 |
+
vertical-align: middle;
|
82 |
+
}
|
83 |
+
.aalb-pc-ad-unit .aalb-pc-product-image img {
|
84 |
+
max-width: 150px;
|
85 |
+
max-height: 150px;
|
86 |
+
vertical-align: bottom;
|
87 |
+
}
|
88 |
+
.aalb-pc-ad-unit .aalb-pc-percent-off {
|
89 |
+
display: block;
|
90 |
+
width: 32px;
|
91 |
+
height: 27px;
|
92 |
+
padding-top: 5px;
|
93 |
+
position: absolute;
|
94 |
+
top: -16px;
|
95 |
+
right: -16px;
|
96 |
+
color: #ffffff;
|
97 |
+
font-size: 12px;
|
98 |
+
text-align: center;
|
99 |
+
-webkit-border-radius: 50%;
|
100 |
+
-moz-border-radius: 50%;
|
101 |
+
-ms-border-radius: 50%;
|
102 |
+
border-radius: 50%;
|
103 |
+
background-color: #a50200;
|
104 |
+
background-image: -webkit-linear-gradient(top, #cb0400, #a50200);
|
105 |
+
background-image: linear-gradient(to bottom, #cb0400, #a50200);
|
106 |
+
}
|
107 |
+
.aalb-pc-ad-unit.hide-percent-off-badge .aalb-pc-percent-off {
|
108 |
+
display: none;
|
109 |
+
}
|
110 |
+
.aalb-pc-ad-unit .aalb-pc-product-details {
|
111 |
+
display: inline-block;
|
112 |
+
max-width: 100%;
|
113 |
+
margin-top: 11px;
|
114 |
+
text-align: left;
|
115 |
+
}
|
116 |
+
.aalb-pc-ad-unit .aalb-pc-product-title a {
|
117 |
+
display: block;
|
118 |
+
width: 100%;
|
119 |
+
overflow: hidden;
|
120 |
+
white-space: nowrap;
|
121 |
+
text-overflow: ellipsis;
|
122 |
+
font-size: 13px;
|
123 |
+
color: #111111;
|
124 |
+
text-decoration: none;
|
125 |
+
}
|
126 |
+
.aalb-pc-ad-unit.no-truncate .aalb-pc-product-title a {
|
127 |
+
text-overflow: initial;
|
128 |
+
white-space: initial;
|
129 |
+
}
|
130 |
+
.aalb-pc-ad-unit .aalb-pc-product-offer-price {
|
131 |
+
font-size: 13px;
|
132 |
+
color: #111111;
|
133 |
+
}
|
134 |
+
.aalb-pc-ad-unit .aalb-pc-product-offer-price-value {
|
135 |
+
color: #AB1700;
|
136 |
+
font-weight: bold;
|
137 |
+
}
|
138 |
+
.aalb-pc-ad-unit .aalb-pc-product-list-price {
|
139 |
+
font-size: 13px;
|
140 |
+
color: #565656;
|
141 |
+
}
|
142 |
+
.aalb-pc-ad-unit .aalb-pc-product-list-price-value {
|
143 |
+
text-decoration: line-through;
|
144 |
+
}
|
145 |
+
.aalb-pc-ad-unit .aalb-pc-product-prime-icon .icon-prime-all {
|
146 |
+
background: url('https://images-na.ssl-images-amazon.com/images/G/01/AUIClients/AmazonUIBaseCSS-sprite_1x-e1a6545ba46e2ced9fc835dbdec4fff037b5b6bf._V2_.png') no-repeat;
|
147 |
+
display: inline-block;
|
148 |
+
margin-top: -1px;
|
149 |
+
vertical-align: middle;
|
150 |
+
background-position: -205px -246px;
|
151 |
+
width: 47px;
|
152 |
+
height: 15px;
|
153 |
+
}
|
154 |
+
|
155 |
+
.aalb-pc-ad-unit .aalb-pc-product-prime-icon .icon-prime-es {
|
156 |
+
background: url('https://images-na.ssl-images-amazon.com/images/G/01/AUIClients/AmazonUIBaseCSS-sprite_1x-e1a6545ba46e2ced9fc835dbdec4fff037b5b6bf._V2_.png') no-repeat;
|
157 |
+
display: inline-block;
|
158 |
+
margin-top: -1px;
|
159 |
+
vertical-align: middle;
|
160 |
+
background-position: -205px -274px;
|
161 |
+
width: 62px;
|
162 |
+
height: 16px;
|
163 |
+
}
|
164 |
+
.aalb-pc-ad-unit .aalb-pc-product-offer-price,
|
165 |
+
.aalb-pc-ad-unit .aalb-pc-product-list-price,
|
166 |
+
.aalb-pc-ad-unit .aalb-pc-product-prime-icon {
|
167 |
+
display: inline-block;
|
168 |
+
margin-right: 2px;
|
169 |
+
}
|
170 |
+
.aalb-pc-ad-unit .aalb-pc-btn-prev,
|
171 |
+
.aalb-pc-ad-unit .aalb-pc-btn-next {
|
172 |
+
position: absolute;
|
173 |
+
top: 50%;
|
174 |
+
margin-top: -52px;
|
175 |
+
display: block;
|
176 |
+
visibility: hidden;
|
177 |
+
width: 43px;
|
178 |
+
height: 105px;
|
179 |
+
z-index: 2;
|
180 |
+
line-height: 105px;
|
181 |
+
background: #ffffff;
|
182 |
+
color: #D0D0D0;
|
183 |
+
font-size: 35px;
|
184 |
+
text-align: center;
|
185 |
+
text-decoration: none;
|
186 |
+
border: 1px solid #e9e9e9;
|
187 |
+
-webkit-box-shadow: 0 0 4px #e9e9e9;
|
188 |
+
box-shadow: 0 0 4px #e9e9e9;
|
189 |
+
}
|
190 |
+
.aalb-pc-ad-unit .aalb-pc-btn-prev:hover,
|
191 |
+
.aalb-pc-ad-unit .aalb-pc-btn-next:hover {
|
192 |
+
color: #999999;
|
193 |
+
}
|
194 |
+
.aalb-pc-ad-unit .aalb-pc-btn-prev:focus,
|
195 |
+
.aalb-pc-ad-unit .aalb-pc-btn-next:focus {
|
196 |
+
outline: none;
|
197 |
+
}
|
198 |
+
.aalb-pc-ad-unit .aalb-pc-btn-prev {
|
199 |
+
left: 0;
|
200 |
+
border-left: 0;
|
201 |
+
border-top-right-radius: 20px;
|
202 |
+
border-bottom-right-radius: 20px;
|
203 |
+
}
|
204 |
+
.aalb-pc-ad-unit .aalb-pc-btn-next {
|
205 |
+
right: 0;
|
206 |
+
border-right: 0;
|
207 |
+
border-top-left-radius: 20px;
|
208 |
+
border-bottom-left-radius: 20px;
|
209 |
+
}
|
210 |
+
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
|
211 |
+
.aalb-pc-ad-unit .aalb-pc-product-prime-icon .icon-prime-all {
|
212 |
+
background: url('https://images-na.ssl-images-amazon.com/images/G/01/AUIClients/AmazonUIBaseCSS-sprite_1x-e1a6545ba46e2ced9fc835dbdec4fff037b5b6bf._V2_.png') no-repeat;
|
213 |
+
display: inline-block;
|
214 |
+
margin-top: -1px;
|
215 |
+
vertical-align: middle;
|
216 |
+
background-position: -205px -246px;
|
217 |
+
width: 47px;
|
218 |
+
height: 15px;
|
219 |
+
}
|
220 |
+
|
221 |
+
.aalb-pc-ad-unit .aalb-pc-product-prime-icon .icon-prime-es {
|
222 |
+
background: url('https://images-na.ssl-images-amazon.com/images/G/01/AUIClients/AmazonUIBaseCSS-sprite_1x-e1a6545ba46e2ced9fc835dbdec4fff037b5b6bf._V2_.png') no-repeat;
|
223 |
+
display: inline-block;
|
224 |
+
margin-top: -1px;
|
225 |
+
vertical-align: middle;
|
226 |
+
background-position: -205px -274px;
|
227 |
+
width: 62px;
|
228 |
+
height: 16px;
|
229 |
+
}
|
230 |
+
}
|
template/ProductCarousel.mustache
ADDED
@@ -0,0 +1,142 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!-- Ad Template with Carousel Layout-->
|
2 |
+
{{#Items}} <!--Section tag for iterating through the list of items-->
|
3 |
+
<div class="aalb-pc-ad-unit" id="{{ID}}">
|
4 |
+
<h2 class="aalb-pc-ad-header">{{#aalb-common}}{{#MarketplaceUS}}Products from Amazon.com{{/MarketplaceUS}}{{#MarketplaceFR}}Produits disponibles sur Amazon.fr {{/MarketplaceFR}}{{#MarketplaceIT}}Acquista su Amazon.it{{/MarketplaceIT}}{{#MarketplaceDE}}Produkte von Amazon.de{{/MarketplaceDE}}{{#MarketplaceES}}Producto disponible en Amazon.es{{/MarketplaceES}}{{#MarketplaceBR}}Products from Amazon.com.br{{/MarketplaceBR}}{{#MarketplaceCA}}Products from Amazon.ca{{/MarketplaceCA}}{{#MarketplaceCN}}Products from Amazon.cn{{/MarketplaceCN}}{{#MarketplaceIN}}Products from Amazon.in{{/MarketplaceIN}}{{#MarketplaceJP}}Products from Amazon.co.jp{{/MarketplaceJP}}{{#MarketplaceMX}}Products from Amazon.com.mx{{/MarketplaceMX}}{{#MarketplaceUK}}Products from Amazon.co.uk{{/MarketplaceUK}}{{/aalb-common}}</h2> <!-- Title of the ad localized according to the marketplace picked from the aalb-common tag-->
|
5 |
+
<div class="aalb-pc-wrapper">
|
6 |
+
<div class="aalb-pc-product-container">
|
7 |
+
<ul class="aalb-pc-product-list">
|
8 |
+
{{#Item}} <!-- Section tag for beginning of information on one item -->
|
9 |
+
{{#aalb}} <!-- Section tag for picking up information on attributes for the item -->
|
10 |
+
<li class="aalb-pc-product">
|
11 |
+
<div class="aalb-pc-product-image">
|
12 |
+
<div class="aalb-pc-product-image-wrapper">
|
13 |
+
<a href="{{DetailPageURL}}" title="{{Title}}" target="_blank" rel="nofollow"> <!--Individual attributes are provided as variable tags as {{[[attribute]]}}. Check documentation for list of supported variable tags.-->
|
14 |
+
<img src="{{MediumImageURL}}" srcset="{{LargeImageURL}}" alt="{{Title}}" />
|
15 |
+
{{#SavingPercent}} <!-- The section tag ensures that percentage savings is displayed only if it is available -->
|
16 |
+
<span class="aalb-pc-percent-off">
|
17 |
+
-{{SavingPercent}}%
|
18 |
+
</span>
|
19 |
+
{{/SavingPercent}}
|
20 |
+
</a>
|
21 |
+
</div>
|
22 |
+
</div>
|
23 |
+
<div class="aalb-pc-product-details">
|
24 |
+
<div class="aalb-pc-product-title">
|
25 |
+
<a href="{{DetailPageURL}}" title="{{Title}}" target="_blank" rel="nofollow">
|
26 |
+
{{Title}}
|
27 |
+
</a>
|
28 |
+
</div>
|
29 |
+
<div class="aalb-pc-product-offer-price">
|
30 |
+
<!-- The section tag for different marketplaces ensures localization of static text. -->
|
31 |
+
{{#MarketplaceUS}}Price{{/MarketplaceUS}}{{#MarketplaceFR}}Prix{{/MarketplaceFR}}{{#MarketplaceIT}}Prezzo{{/MarketplaceIT}}{{#MarketplaceDE}}Preis{{/MarketplaceDE}}{{#MarketplaceES}}Precio{{/MarketplaceES}}{{#MarketplaceBR}}Price{{/MarketplaceBR}}{{#MarketplaceCA}}Price{{/MarketplaceCA}}{{#MarketplaceCN}}Price{{/MarketplaceCN}}{{#MarketplaceIN}}Price{{/MarketplaceIN}}{{#MarketplaceJP}}Price{{/MarketplaceJP}}{{#MarketplaceMX}}Price{{/MarketplaceMX}}{{#MarketplaceUK}}Price{{/MarketplaceUK}}: <span class="aalb-pc-product-offer-price-value">{{CurrentPrice}}</span>
|
32 |
+
</div>
|
33 |
+
{{#StrikePrice}} <!-- The section tag ensures that strike price is displayed only if it is available -->
|
34 |
+
<div class="aalb-pc-product-list-price">
|
35 |
+
<!-- The section tag for different marketplaces ensures localization of static text. -->
|
36 |
+
{{#MarketplaceUS}}Was{{/MarketplaceUS}}{{#MarketplaceFR}}Ancien prix{{/MarketplaceFR}}{{#MarketplaceIT}}Da{{/MarketplaceIT}}{{#MarketplaceDE}}statt{{/MarketplaceDE}}{{#MarketplaceES}}Precio recomendado{{/MarketplaceES}}{{#MarketplaceBR}}Was{{/MarketplaceBR}}{{#MarketplaceCA}}Was{{/MarketplaceCA}}{{#MarketplaceCN}}Was{{/MarketplaceCN}}{{#MarketplaceIN}}Was{{/MarketplaceIN}}{{#MarketplaceJP}}Was{{/MarketplaceJP}}{{#MarketplaceMX}}Was{{/MarketplaceMX}}{{#MarketplaceUK}}Was{{/MarketplaceUK}}: <span class="aalb-pc-product-list-price-value">{{StrikePrice}}</span>
|
37 |
+
</div>
|
38 |
+
{{/StrikePrice}}
|
39 |
+
{{#Prime}} <!-- The section tag ensures that prime icon is displayed only if it is available -->
|
40 |
+
<div class="aalb-pc-product-prime-icon">
|
41 |
+
{{#MarketplaceES}} <!-- Display Prime Icon for ES if marketplace is ES -->
|
42 |
+
<i class="icon-prime-es"></i>
|
43 |
+
{{/MarketplaceES}}
|
44 |
+
{{^MarketplaceES}} <!-- Display Common Prime Icon for all other marketplaces -->
|
45 |
+
<i class="icon-prime-all"></i>
|
46 |
+
{{/MarketplaceES}}
|
47 |
+
</div>
|
48 |
+
{{/Prime}}
|
49 |
+
</div>
|
50 |
+
</li>
|
51 |
+
{{/aalb}}
|
52 |
+
{{/Item}}
|
53 |
+
</ul>
|
54 |
+
</div>
|
55 |
+
</div>
|
56 |
+
<a href="javascript:void(0);" class="aalb-pc-btn-prev">‹</a>
|
57 |
+
<a href="javascript:void(0);" class="aalb-pc-btn-next">›</a>
|
58 |
+
</div>
|
59 |
+
{{/Items}}
|
60 |
+
|
61 |
+
<script>
|
62 |
+
jQuery(document).ready(function() {
|
63 |
+
|
64 |
+
var CONSTANTS = {
|
65 |
+
productMinWidth : 185,
|
66 |
+
productMargin : 20
|
67 |
+
};
|
68 |
+
|
69 |
+
var $adUnits = jQuery('.aalb-pc-ad-unit');
|
70 |
+
$adUnits.each(function() {
|
71 |
+
var $adUnit = jQuery(this),
|
72 |
+
$wrapper = $adUnit.find('.aalb-pc-wrapper'),
|
73 |
+
$productContainer = $adUnit.find('.aalb-pc-product-container'),
|
74 |
+
$btnNext = $adUnit.find('.aalb-pc-btn-next'),
|
75 |
+
$btnPrev = $adUnit.find('.aalb-pc-btn-prev'),
|
76 |
+
$productList = $productContainer.find('.aalb-pc-product-list'),
|
77 |
+
$products = $productList.find('.aalb-pc-product'),
|
78 |
+
productCount = $products.length;
|
79 |
+
|
80 |
+
if (!productCount) {
|
81 |
+
return true;
|
82 |
+
}
|
83 |
+
|
84 |
+
var rows = $adUnit.find('input[name=rows]').length && parseInt($adUnit.find('input[name=rows]').val(), 10),
|
85 |
+
columns = $adUnit.find('input[name=columns]').length && parseInt($adUnit.find('input[name=columns]').val(), 10),
|
86 |
+
disableCarousel = $adUnit.find('input[name=disable-carousel]').length || rows || columns;
|
87 |
+
|
88 |
+
if (columns) {
|
89 |
+
var productContainerMinWidth = columns * (CONSTANTS.productMinWidth + CONSTANTS.productMargin) + 'px';
|
90 |
+
$adUnit.css('min-width', productContainerMinWidth);
|
91 |
+
$productContainer.css('min-width', productContainerMinWidth);
|
92 |
+
$products.filter(':nth-child(' + columns + 'n + 1)').css('clear', 'both');
|
93 |
+
}
|
94 |
+
|
95 |
+
if (rows && columns) {
|
96 |
+
var cutOffIndex = (rows * columns) - 1;
|
97 |
+
$products.filter(':gt(' + cutOffIndex + ')').remove();
|
98 |
+
}
|
99 |
+
|
100 |
+
function updateLayout() {
|
101 |
+
var wrapperWidth = $wrapper.width(),
|
102 |
+
possibleColumns = columns || parseInt(wrapperWidth / (CONSTANTS.productMinWidth + CONSTANTS.productMargin), 10),
|
103 |
+
actualColumns = columns || possibleColumns < productCount ? possibleColumns : productCount,
|
104 |
+
productWidth = parseInt(wrapperWidth / actualColumns, 10) - CONSTANTS.productMargin;
|
105 |
+
|
106 |
+
$products.css('width', productWidth + 'px');
|
107 |
+
|
108 |
+
if (!disableCarousel) {
|
109 |
+
if ((productCount * productWidth > wrapperWidth) && actualColumns !== 1) {
|
110 |
+
$btnNext.css('visibility', 'visible').removeClass('disabled').unbind('click');
|
111 |
+
$btnPrev.css('visibility', 'visible').removeClass('disabled').unbind('click');
|
112 |
+
$productContainer.jCarouselLite({
|
113 |
+
btnNext : '#' + $adUnit.attr('id') + ' .aalb-pc-btn-next',
|
114 |
+
btnPrev : '#' + $adUnit.attr('id') + ' .aalb-pc-btn-prev',
|
115 |
+
visible : actualColumns,
|
116 |
+
circular : false
|
117 |
+
});
|
118 |
+
} else {
|
119 |
+
$productContainer.css('width', 'auto');
|
120 |
+
$productList.css('width', 'auto');
|
121 |
+
$btnNext.css('visibility', 'hidden').unbind('click');
|
122 |
+
$btnPrev.css('visibility', 'hidden').unbind('click');
|
123 |
+
}
|
124 |
+
}
|
125 |
+
}
|
126 |
+
|
127 |
+
updateLayout();
|
128 |
+
jQuery(window).resize(updateLayout);
|
129 |
+
});
|
130 |
+
});
|
131 |
+
|
132 |
+
/*!
|
133 |
+
* jCarouselLite - v1.1 - 2014-09-28
|
134 |
+
* http://www.gmarwaha.com/jquery/jcarousellite/
|
135 |
+
* Copyright (c) 2014 Ganeshji Marwaha
|
136 |
+
* Licensed MIT (https://github.com/ganeshmax/jcarousellite/blob/master/LICENSE)
|
137 |
+
*/
|
138 |
+
|
139 |
+
!function(a){a.jCarouselLite={version:"1.1"},a.fn.jCarouselLite=function(b){return b=a.extend({},a.fn.jCarouselLite.options,b||{}),this.each(function(){function c(a){return n||(clearTimeout(A),z=a,b.beforeStart&&b.beforeStart.call(this,i()),b.circular?j(a):k(a),m({start:function(){n=!0},done:function(){b.afterEnd&&b.afterEnd.call(this,i()),b.auto&&h(),n=!1}}),b.circular||l()),!1}function d(){if(n=!1,o=b.vertical?"top":"left",p=b.vertical?"height":"width",q=B.find(">ul"),r=q.find(">li"),x=r.size(),w=x<b.visible?x:b.visible,b.circular){var c=r.slice(x-w).clone(),d=r.slice(0,w).clone();q.prepend(c).append(d),b.start+=w}s=a("li",q),y=s.size(),z=b.start}function e(){B.css("visibility","visible"),s.css({overflow:"hidden","float":b.vertical?"none":"left"}),q.css({margin:"0",padding:"0",position:"relative","list-style":"none","z-index":"1"}),B.css({overflow:"hidden",position:"relative","z-index":"2",left:"0px"}),!b.circular&&b.btnPrev&&0==b.start&&a(b.btnPrev).addClass("disabled")}function f(){t=b.vertical?s.outerHeight(!0):s.outerWidth(!0),u=t*y,v=t*w,s.css({width:s.width(),height:s.height()}),q.css(p,u+"px").css(o,-(z*t)),B.css(p,v+"px")}function g(){b.btnPrev&&a(b.btnPrev).click(function(){return c(z-b.scroll)}),b.btnNext&&a(b.btnNext).click(function(){return c(z+b.scroll)}),b.btnGo&&a.each(b.btnGo,function(d,e){a(e).click(function(){return c(b.circular?w+d:d)})}),b.mouseWheel&&B.mousewheel&&B.mousewheel(function(a,d){return c(d>0?z-b.scroll:z+b.scroll)}),b.auto&&h()}function h(){A=setTimeout(function(){c(z+b.scroll)},b.auto)}function i(){return s.slice(z).slice(0,w)}function j(a){var c;a<=b.start-w-1?(c=a+x+b.scroll,q.css(o,-(c*t)+"px"),z=c-b.scroll):a>=y-w+1&&(c=a-x-b.scroll,q.css(o,-(c*t)+"px"),z=c+b.scroll)}function k(a){0>a?z=0:a>y-w&&(z=y-w)}function l(){a(b.btnPrev+","+b.btnNext).removeClass("disabled"),a(z-b.scroll<0&&b.btnPrev||z+b.scroll>y-w&&b.btnNext||[]).addClass("disabled")}function m(c){n=!0,q.animate("left"==o?{left:-(z*t)}:{top:-(z*t)},a.extend({duration:b.speed,easing:b.easing},c))}var n,o,p,q,r,s,t,u,v,w,x,y,z,A,B=a(this);d(),e(),f(),g()})},a.fn.jCarouselLite.options={btnPrev:null,btnNext:null,btnGo:null,mouseWheel:!1,auto:null,speed:200,easing:null,vertical:!1,circular:!0,visible:3,start:0,scroll:1,beforeStart:null,afterEnd:null}}(jQuery);
|
140 |
+
|
141 |
+
|
142 |
+
</script>
|
template/ProductGrid.css
ADDED
@@ -0,0 +1,230 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.aalb-pg-ad-unit {
|
2 |
+
/*Enable this border property to have a border around the ad unit*/
|
3 |
+
/*border: 1px solid #d4d4c4;*/
|
4 |
+
background: #ffffff;
|
5 |
+
}
|
6 |
+
/* Actual styles start below */
|
7 |
+
.aalb-pg-ad-unit {
|
8 |
+
position: relative;
|
9 |
+
overflow: hidden;
|
10 |
+
padding: 22px 40px;
|
11 |
+
}
|
12 |
+
.aalb-pg-ad-unit * {
|
13 |
+
box-sizing: content-box;
|
14 |
+
box-shadow: none;
|
15 |
+
font-family: Arial, Helvetica, sans-serif;
|
16 |
+
margin: 0;
|
17 |
+
margin-bottom: 0;
|
18 |
+
margin-left: 0;
|
19 |
+
margin-right: 0;
|
20 |
+
margin-top: 0;
|
21 |
+
outline: 0;
|
22 |
+
padding: 0;
|
23 |
+
padding-bottom: 0;
|
24 |
+
padding-left: 0;
|
25 |
+
padding-right: 0;
|
26 |
+
padding-top: 0;
|
27 |
+
}
|
28 |
+
.aalb-pg-ad-unit.pull-left {
|
29 |
+
float: left;
|
30 |
+
}
|
31 |
+
.aalb-pg-ad-unit.pull-right {
|
32 |
+
float: right;
|
33 |
+
}
|
34 |
+
.aalb-pg-ad-unit.pull-left .aalb-pg-product, .aalb-pg-ad-unit.pull-right .aalb-pg-product {
|
35 |
+
width: 185px !important;
|
36 |
+
}
|
37 |
+
.aalb-pg-ad-unit a {
|
38 |
+
box-shadow: none !important;
|
39 |
+
}
|
40 |
+
.aalb-pg-ad-unit a:hover {
|
41 |
+
color: #c45500;
|
42 |
+
}
|
43 |
+
.aalb-pg-ad-unit .aalb-pg-ad-header {
|
44 |
+
padding-left: 3px;
|
45 |
+
padding-bottom: 9px;
|
46 |
+
font-size: 17px;
|
47 |
+
font-weight: normal;
|
48 |
+
color: #111111;
|
49 |
+
}
|
50 |
+
.aalb-pg-ad-unit .aalb-pg-product-list {
|
51 |
+
/* Remove the border-top to remove the horizontal line after the Ad Header*/
|
52 |
+
border-top: 2px solid #f7f7f7;
|
53 |
+
overflow: hidden;
|
54 |
+
}
|
55 |
+
.aalb-pg-ad-unit .aalb-pg-product {
|
56 |
+
min-width: 185px;
|
57 |
+
max-width: 385px;
|
58 |
+
height: auto !important;
|
59 |
+
padding-top: 22px;
|
60 |
+
padding-bottom: 22px;
|
61 |
+
margin-left: 10px;
|
62 |
+
margin-right: 10px;
|
63 |
+
float: left;
|
64 |
+
list-style: none;
|
65 |
+
text-align: center;
|
66 |
+
}
|
67 |
+
.aalb-pg-ad-unit .aalb-pg-product-image {
|
68 |
+
display: table;
|
69 |
+
width: 150px;
|
70 |
+
height: 150px;
|
71 |
+
margin: 0 auto;
|
72 |
+
text-align: center;
|
73 |
+
}
|
74 |
+
.aalb-pg-ad-unit .aalb-pg-product-image-wrapper {
|
75 |
+
display: table-cell;
|
76 |
+
vertical-align: middle;
|
77 |
+
}
|
78 |
+
.aalb-pg-ad-unit .aalb-pg-product-image a {
|
79 |
+
position: relative;
|
80 |
+
display: inline-block;
|
81 |
+
vertical-align: middle;
|
82 |
+
}
|
83 |
+
.aalb-pg-ad-unit .aalb-pg-product-image img {
|
84 |
+
max-width: 150px;
|
85 |
+
max-height: 150px;
|
86 |
+
vertical-align: bottom;
|
87 |
+
}
|
88 |
+
.aalb-pg-ad-unit .aalb-pg-percent-off {
|
89 |
+
display: block;
|
90 |
+
width: 32px;
|
91 |
+
height: 27px;
|
92 |
+
padding-top: 5px;
|
93 |
+
position: absolute;
|
94 |
+
top: -16px;
|
95 |
+
right: -16px;
|
96 |
+
color: #ffffff;
|
97 |
+
font-size: 12px;
|
98 |
+
text-align: center;
|
99 |
+
-webkit-border-radius: 50%;
|
100 |
+
-moz-border-radius: 50%;
|
101 |
+
-ms-border-radius: 50%;
|
102 |
+
border-radius: 50%;
|
103 |
+
background-color: #a50200;
|
104 |
+
background-image: -webkit-linear-gradient(top, #cb0400, #a50200);
|
105 |
+
background-image: linear-gradient(to bottom, #cb0400, #a50200);
|
106 |
+
}
|
107 |
+
.aalb-pg-ad-unit.hide-percent-off-badge .aalb-pg-percent-off {
|
108 |
+
display: none;
|
109 |
+
}
|
110 |
+
.aalb-pg-ad-unit .aalb-pg-product-details {
|
111 |
+
display: inline-block;
|
112 |
+
max-width: 100%;
|
113 |
+
margin-top: 11px;
|
114 |
+
text-align: left;
|
115 |
+
}
|
116 |
+
.aalb-pg-ad-unit .aalb-pg-product-title a {
|
117 |
+
display: block;
|
118 |
+
width: 100%;
|
119 |
+
overflow: hidden;
|
120 |
+
white-space: nowrap;
|
121 |
+
text-overflow: ellipsis;
|
122 |
+
font-size: 13px;
|
123 |
+
color: #111111;
|
124 |
+
text-decoration: none;
|
125 |
+
}
|
126 |
+
.aalb-pg-ad-unit.no-truncate .aalb-pg-product-title a {
|
127 |
+
text-overflow: initial;
|
128 |
+
white-space: initial;
|
129 |
+
}
|
130 |
+
.aalb-pg-ad-unit .aalb-pg-product-offer-price {
|
131 |
+
font-size: 13px;
|
132 |
+
color: #111111;
|
133 |
+
}
|
134 |
+
.aalb-pg-ad-unit .aalb-pg-product-offer-price-value {
|
135 |
+
color: #AB1700;
|
136 |
+
font-weight: bold;
|
137 |
+
}
|
138 |
+
.aalb-pg-ad-unit .aalb-pg-product-list-price {
|
139 |
+
font-size: 13px;
|
140 |
+
color: #565656;
|
141 |
+
}
|
142 |
+
.aalb-pg-ad-unit .aalb-pg-product-list-price-value {
|
143 |
+
text-decoration: line-through;
|
144 |
+
}
|
145 |
+
.aalb-pg-ad-unit .aalb-pg-product-prime-icon .icon-prime-all {
|
146 |
+
background: url('https://images-na.ssl-images-amazon.com/images/G/01/AUIClients/AmazonUIBaseCSS-sprite_1x-e1a6545ba46e2ced9fc835dbdec4fff037b5b6bf._V2_.png') no-repeat;
|
147 |
+
display: inline-block;
|
148 |
+
margin-top: -1px;
|
149 |
+
vertical-align: middle;
|
150 |
+
background-position: -205px -246px;
|
151 |
+
width: 47px;
|
152 |
+
height: 16px;
|
153 |
+
}
|
154 |
+
|
155 |
+
.aalb-pg-ad-unit .aalb-pg-product-prime-icon .icon-prime-es {
|
156 |
+
background: url('https://images-na.ssl-images-amazon.com/images/G/01/AUIClients/AmazonUIBaseCSS-sprite_1x-e1a6545ba46e2ced9fc835dbdec4fff037b5b6bf._V2_.png') no-repeat;
|
157 |
+
display: inline-block;
|
158 |
+
margin-top: -1px;
|
159 |
+
vertical-align: middle;
|
160 |
+
background-position: -205px -274px;
|
161 |
+
width: 62px;
|
162 |
+
height: 15px;
|
163 |
+
}
|
164 |
+
.aalb-pg-ad-unit .aalb-pg-product-offer-price,
|
165 |
+
.aalb-pg-ad-unit .aalb-pg-product-list-price,
|
166 |
+
.aalb-pg-ad-unit .aalb-pg-product-prime-icon {
|
167 |
+
display: inline-block;
|
168 |
+
margin-right: 2px;
|
169 |
+
}
|
170 |
+
.aalb-pg-ad-unit .aalb-pg-btn-prev,
|
171 |
+
.aalb-pg-ad-unit .aalb-pg-btn-next {
|
172 |
+
position: absolute;
|
173 |
+
top: 50%;
|
174 |
+
margin-top: -52px;
|
175 |
+
display: block;
|
176 |
+
visibility: hidden;
|
177 |
+
width: 43px;
|
178 |
+
height: 105px;
|
179 |
+
z-index: 2;
|
180 |
+
line-height: 105px;
|
181 |
+
background: #ffffff;
|
182 |
+
color: #D0D0D0;
|
183 |
+
font-size: 35px;
|
184 |
+
text-align: center;
|
185 |
+
text-decoration: none;
|
186 |
+
border: 1px solid #e9e9e9;
|
187 |
+
-webkit-box-shadow: 0 0 4px #e9e9e9;
|
188 |
+
box-shadow: 0 0 4px #e9e9e9;
|
189 |
+
}
|
190 |
+
.aalb-pg-ad-unit .aalb-pg-btn-prev:hover,
|
191 |
+
.aalb-pg-ad-unit .aalb-pg-btn-next:hover {
|
192 |
+
color: #999999;
|
193 |
+
}
|
194 |
+
.aalb-pg-ad-unit .aalb-pg-btn-prev:focus,
|
195 |
+
.aalb-pg-ad-unit .aalb-pg-btn-next:focus {
|
196 |
+
outline: none;
|
197 |
+
}
|
198 |
+
.aalb-pg-ad-unit .aalb-pg-btn-prev {
|
199 |
+
left: 0;
|
200 |
+
border-left: 0;
|
201 |
+
border-top-right-radius: 20px;
|
202 |
+
border-bottom-right-radius: 20px;
|
203 |
+
}
|
204 |
+
.aalb-pg-ad-unit .aalb-pg-btn-next {
|
205 |
+
right: 0;
|
206 |
+
border-right: 0;
|
207 |
+
border-top-left-radius: 20px;
|
208 |
+
border-bottom-left-radius: 20px;
|
209 |
+
}
|
210 |
+
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
|
211 |
+
.aalb-pg-ad-unit .aalb-pg-product-prime-icon .icon-prime-all {
|
212 |
+
background: url('https://images-na.ssl-images-amazon.com/images/G/01/AUIClients/AmazonUIBaseCSS-sprite_1x-e1a6545ba46e2ced9fc835dbdec4fff037b5b6bf._V2_.png') no-repeat;
|
213 |
+
display: inline-block;
|
214 |
+
margin-top: -1px;
|
215 |
+
vertical-align: middle;
|
216 |
+
background-position: -205px -246px;
|
217 |
+
width: 47px;
|
218 |
+
height: 15px;
|
219 |
+
}
|
220 |
+
|
221 |
+
.aalb-pg-ad-unit .aalb-pg-product-prime-icon .icon-prime-es {
|
222 |
+
background: url('https://images-na.ssl-images-amazon.com/images/G/01/AUIClients/AmazonUIBaseCSS-sprite_1x-e1a6545ba46e2ced9fc835dbdec4fff037b5b6bf._V2_.png') no-repeat;
|
223 |
+
display: inline-block;
|
224 |
+
margin-top: -1px;
|
225 |
+
vertical-align: middle;
|
226 |
+
background-position: -205px -274px;
|
227 |
+
width: 62px;
|
228 |
+
height: 16px;
|
229 |
+
}
|
230 |
+
}
|
template/ProductGrid.mustache
ADDED
@@ -0,0 +1,144 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!-- A 2x5 Grid Template Layout. It can be configured by the two input fields below -->
|
2 |
+
{{#Items}} <!--Section tag for iterating through the list of items-->
|
3 |
+
<div class="aalb-pg-ad-unit" id="{{ID}}">
|
4 |
+
<input type="hidden" name="columns" value="2" />
|
5 |
+
<input type="hidden" name="rows" value="5" />
|
6 |
+
<h2 class="aalb-pg-ad-header">{{#aalb-common}}{{#MarketplaceUS}}Products from Amazon.com{{/MarketplaceUS}}{{#MarketplaceFR}}Produits disponibles sur Amazon.fr {{/MarketplaceFR}}{{#MarketplaceIT}}Acquista su Amazon.it{{/MarketplaceIT}}{{#MarketplaceDE}}Produkte von Amazon.de{{/MarketplaceDE}}{{#MarketplaceES}}Producto disponible en Amazon.es{{/MarketplaceES}}{{#MarketplaceBR}}Products from Amazon.com.br{{/MarketplaceBR}}{{#MarketplaceCA}}Products from Amazon.ca{{/MarketplaceCA}}{{#MarketplaceCN}}Products from Amazon.cn{{/MarketplaceCN}}{{#MarketplaceIN}}Products from Amazon.in{{/MarketplaceIN}}{{#MarketplaceJP}}Products from Amazon.co.jp{{/MarketplaceJP}}{{#MarketplaceMX}}Products from Amazon.com.mx{{/MarketplaceMX}}{{#MarketplaceUK}}Products from Amazon.co.uk{{/MarketplaceUK}}{{/aalb-common}}</h2> <!-- Title of the ad localized according to the marketplace picked from the aalb-common tag -->
|
7 |
+
<div class="aalb-pg-wrapper">
|
8 |
+
<div class="aalb-pg-product-container">
|
9 |
+
<ul class="aalb-pg-product-list">
|
10 |
+
{{#Item}} <!-- Section tag for beginning of information on one item -->
|
11 |
+
{{#aalb}} <!-- Section tag for picking up information on attributes for the item -->
|
12 |
+
<li class="aalb-pg-product">
|
13 |
+
<div class="aalb-pg-product-image">
|
14 |
+
<div class="aalb-pg-product-image-wrapper">
|
15 |
+
<a href="{{DetailPageURL}}" title="{{Title}}" target="_blank" rel="nofollow"> <!--Individual attributes are provided as variable tags as {{[[attribute]]}}. Check documentation for list of supported variable tags.-->
|
16 |
+
<img src="{{MediumImageURL}}" srcset="{{LargeImageURL}}" alt="{{Title}}" />
|
17 |
+
{{#SavingPercent}} <!-- The section tag ensures that percentage savings is displayed only if it is available -->
|
18 |
+
<span class="aalb-pg-percent-off">
|
19 |
+
-{{SavingPercent}}%
|
20 |
+
</span>
|
21 |
+
{{/SavingPercent}}
|
22 |
+
</a>
|
23 |
+
</div>
|
24 |
+
</div>
|
25 |
+
<div class="aalb-pg-product-details">
|
26 |
+
<div class="aalb-pg-product-title">
|
27 |
+
<a href="{{DetailPageURL}}" title="{{Title}}" target="_blank" rel="nofollow">
|
28 |
+
{{Title}}
|
29 |
+
</a>
|
30 |
+
</div>
|
31 |
+
<div class="aalb-pg-product-offer-price">
|
32 |
+
<!-- The section tag for different marketplaces ensures localization of static text. -->
|
33 |
+
{{#MarketplaceUS}}Price{{/MarketplaceUS}}{{#MarketplaceFR}}Prix{{/MarketplaceFR}}{{#MarketplaceIT}}Prezzo{{/MarketplaceIT}}{{#MarketplaceDE}}Preis{{/MarketplaceDE}}{{#MarketplaceES}}Precio{{/MarketplaceES}}{{#MarketplaceBR}}Price{{/MarketplaceBR}}{{#MarketplaceCA}}Price{{/MarketplaceCA}}{{#MarketplaceCN}}Price{{/MarketplaceCN}}{{#MarketplaceIN}}Price{{/MarketplaceIN}}{{#MarketplaceJP}}Price{{/MarketplaceJP}}{{#MarketplaceMX}}Price{{/MarketplaceMX}}{{#MarketplaceUK}}Price{{/MarketplaceUK}}: <span class="aalb-pg-product-offer-price-value">{{CurrentPrice}}</span>
|
34 |
+
</div>
|
35 |
+
{{#StrikePrice}} <!-- The section tag ensures that strike price is displayed only if it is available -->
|
36 |
+
<div class="aalb-pg-product-list-price">
|
37 |
+
<!-- The section tag for different marketplaces ensures localization of static text. -->
|
38 |
+
{{#MarketplaceUS}}Was{{/MarketplaceUS}}{{#MarketplaceFR}}Ancien prix{{/MarketplaceFR}}{{#MarketplaceIT}}Da{{/MarketplaceIT}}{{#MarketplaceDE}}statt{{/MarketplaceDE}}{{#MarketplaceES}}Precio recomendado{{/MarketplaceES}}{{#MarketplaceBR}}Was{{/MarketplaceBR}}{{#MarketplaceCA}}Was{{/MarketplaceCA}}{{#MarketplaceCN}}Was{{/MarketplaceCN}}{{#MarketplaceIN}}Was{{/MarketplaceIN}}{{#MarketplaceJP}}Was{{/MarketplaceJP}}{{#MarketplaceMX}}Was{{/MarketplaceMX}}{{#MarketplaceUK}}Was{{/MarketplaceUK}}: <span class="aalb-pg-product-list-price-value">{{StrikePrice}}</span>
|
39 |
+
</div>
|
40 |
+
{{/StrikePrice}}
|
41 |
+
{{#Prime}} <!-- The section tag ensures that prime icon is displayed only if it is available -->
|
42 |
+
<div class="aalb-pg-product-prime-icon">
|
43 |
+
{{#MarketplaceES}} <!-- Display Prime Icon for ES if marketplace is ES -->
|
44 |
+
<i class="icon-prime-es"></i>
|
45 |
+
{{/MarketplaceES}}
|
46 |
+
{{^MarketplaceES}} <!-- Display Common Prime Icon for all other marketplaces -->
|
47 |
+
<i class="icon-prime-all"></i>
|
48 |
+
{{/MarketplaceES}}
|
49 |
+
</div>
|
50 |
+
{{/Prime}}
|
51 |
+
</div>
|
52 |
+
</li>
|
53 |
+
{{/aalb}}
|
54 |
+
{{/Item}}
|
55 |
+
</ul>
|
56 |
+
</div>
|
57 |
+
</div>
|
58 |
+
<a href="javascript:void(0);" class="aalb-pg-btn-prev">‹</a>
|
59 |
+
<a href="javascript:void(0);" class="aalb-pg-btn-next">›</a>
|
60 |
+
</div>
|
61 |
+
{{/Items}}
|
62 |
+
|
63 |
+
<script>
|
64 |
+
jQuery(document).ready(function() {
|
65 |
+
|
66 |
+
var CONSTANTS = {
|
67 |
+
productMinWidth : 185,
|
68 |
+
productMargin : 20
|
69 |
+
};
|
70 |
+
|
71 |
+
var $adUnits = jQuery('.aalb-pg-ad-unit');
|
72 |
+
$adUnits.each(function() {
|
73 |
+
var $adUnit = jQuery(this),
|
74 |
+
$wrapper = $adUnit.find('.aalb-pg-wrapper'),
|
75 |
+
$productContainer = $adUnit.find('.aalb-pg-product-container'),
|
76 |
+
$btnNext = $adUnit.find('.aalb-pg-btn-next'),
|
77 |
+
$btnPrev = $adUnit.find('.aalb-pg-btn-prev'),
|
78 |
+
$productList = $productContainer.find('.aalb-pg-product-list'),
|
79 |
+
$products = $productList.find('.aalb-pg-product'),
|
80 |
+
productCount = $products.length;
|
81 |
+
|
82 |
+
if (!productCount) {
|
83 |
+
return true;
|
84 |
+
}
|
85 |
+
|
86 |
+
var rows = $adUnit.find('input[name=rows]').length && parseInt($adUnit.find('input[name=rows]').val(), 10),
|
87 |
+
columns = $adUnit.find('input[name=columns]').length && parseInt($adUnit.find('input[name=columns]').val(), 10),
|
88 |
+
disableCarousel = $adUnit.find('input[name=disable-carousel]').length || rows || columns;
|
89 |
+
|
90 |
+
if (columns) {
|
91 |
+
var productContainerMinWidth = columns * (CONSTANTS.productMinWidth + CONSTANTS.productMargin) + 'px';
|
92 |
+
$adUnit.css('min-width', productContainerMinWidth);
|
93 |
+
$productContainer.css('min-width', productContainerMinWidth);
|
94 |
+
$products.filter(':nth-child(' + columns + 'n + 1)').css('clear', 'both');
|
95 |
+
}
|
96 |
+
|
97 |
+
if (rows && columns) {
|
98 |
+
var cutOffIndex = (rows * columns) - 1;
|
99 |
+
$products.filter(':gt(' + cutOffIndex + ')').remove();
|
100 |
+
}
|
101 |
+
|
102 |
+
function updateLayout() {
|
103 |
+
var wrapperWidth = $wrapper.width(),
|
104 |
+
possibleColumns = columns || parseInt(wrapperWidth / (CONSTANTS.productMinWidth + CONSTANTS.productMargin), 10),
|
105 |
+
actualColumns = columns || possibleColumns < productCount ? possibleColumns : productCount,
|
106 |
+
productWidth = parseInt(wrapperWidth / actualColumns, 10) - CONSTANTS.productMargin;
|
107 |
+
|
108 |
+
$products.css('width', productWidth + 'px');
|
109 |
+
|
110 |
+
if (!disableCarousel) {
|
111 |
+
if ((productCount * productWidth > wrapperWidth) && actualColumns !== 1) {
|
112 |
+
$btnNext.css('visibility', 'visible').removeClass('disabled').unbind('click');
|
113 |
+
$btnPrev.css('visibility', 'visible').removeClass('disabled').unbind('click');
|
114 |
+
$productContainer.jCarouselLite({
|
115 |
+
btnNext : '#' + $adUnit.attr('id') + ' .aalb-pg-btn-next',
|
116 |
+
btnPrev : '#' + $adUnit.attr('id') + ' .aalb-pg-btn-prev',
|
117 |
+
visible : actualColumns,
|
118 |
+
circular : false
|
119 |
+
});
|
120 |
+
} else {
|
121 |
+
$productContainer.css('width', 'auto');
|
122 |
+
$productList.css('width', 'auto');
|
123 |
+
$btnNext.css('visibility', 'hidden').unbind('click');
|
124 |
+
$btnPrev.css('visibility', 'hidden').unbind('click');
|
125 |
+
}
|
126 |
+
}
|
127 |
+
}
|
128 |
+
|
129 |
+
updateLayout();
|
130 |
+
jQuery(window).resize(updateLayout);
|
131 |
+
});
|
132 |
+
});
|
133 |
+
|
134 |
+
/*!
|
135 |
+
* jCarouselLite - v1.1 - 2014-09-28
|
136 |
+
* http://www.gmarwaha.com/jquery/jcarousellite/
|
137 |
+
* Copyright (c) 2014 Ganeshji Marwaha
|
138 |
+
* Licensed MIT (https://github.com/ganeshmax/jcarousellite/blob/master/LICENSE)
|
139 |
+
*/
|
140 |
+
|
141 |
+
!function(a){a.jCarouselLite={version:"1.1"},a.fn.jCarouselLite=function(b){return b=a.extend({},a.fn.jCarouselLite.options,b||{}),this.each(function(){function c(a){return n||(clearTimeout(A),z=a,b.beforeStart&&b.beforeStart.call(this,i()),b.circular?j(a):k(a),m({start:function(){n=!0},done:function(){b.afterEnd&&b.afterEnd.call(this,i()),b.auto&&h(),n=!1}}),b.circular||l()),!1}function d(){if(n=!1,o=b.vertical?"top":"left",p=b.vertical?"height":"width",q=B.find(">ul"),r=q.find(">li"),x=r.size(),w=x<b.visible?x:b.visible,b.circular){var c=r.slice(x-w).clone(),d=r.slice(0,w).clone();q.prepend(c).append(d),b.start+=w}s=a("li",q),y=s.size(),z=b.start}function e(){B.css("visibility","visible"),s.css({overflow:"hidden","float":b.vertical?"none":"left"}),q.css({margin:"0",padding:"0",position:"relative","list-style":"none","z-index":"1"}),B.css({overflow:"hidden",position:"relative","z-index":"2",left:"0px"}),!b.circular&&b.btnPrev&&0==b.start&&a(b.btnPrev).addClass("disabled")}function f(){t=b.vertical?s.outerHeight(!0):s.outerWidth(!0),u=t*y,v=t*w,s.css({width:s.width(),height:s.height()}),q.css(p,u+"px").css(o,-(z*t)),B.css(p,v+"px")}function g(){b.btnPrev&&a(b.btnPrev).click(function(){return c(z-b.scroll)}),b.btnNext&&a(b.btnNext).click(function(){return c(z+b.scroll)}),b.btnGo&&a.each(b.btnGo,function(d,e){a(e).click(function(){return c(b.circular?w+d:d)})}),b.mouseWheel&&B.mousewheel&&B.mousewheel(function(a,d){return c(d>0?z-b.scroll:z+b.scroll)}),b.auto&&h()}function h(){A=setTimeout(function(){c(z+b.scroll)},b.auto)}function i(){return s.slice(z).slice(0,w)}function j(a){var c;a<=b.start-w-1?(c=a+x+b.scroll,q.css(o,-(c*t)+"px"),z=c-b.scroll):a>=y-w+1&&(c=a-x-b.scroll,q.css(o,-(c*t)+"px"),z=c+b.scroll)}function k(a){0>a?z=0:a>y-w&&(z=y-w)}function l(){a(b.btnPrev+","+b.btnNext).removeClass("disabled"),a(z-b.scroll<0&&b.btnPrev||z+b.scroll>y-w&&b.btnNext||[]).addClass("disabled")}function m(c){n=!0,q.animate("left"==o?{left:-(z*t)}:{top:-(z*t)},a.extend({duration:b.speed,easing:b.easing},c))}var n,o,p,q,r,s,t,u,v,w,x,y,z,A,B=a(this);d(),e(),f(),g()})},a.fn.jCarouselLite.options={btnPrev:null,btnNext:null,btnGo:null,mouseWheel:!1,auto:null,speed:200,easing:null,vertical:!1,circular:!0,visible:3,start:0,scroll:1,beforeStart:null,afterEnd:null}}(jQuery);
|
142 |
+
|
143 |
+
|
144 |
+
</script>
|