diff --git a/src/wp-content/plugins/simple-lightbox/COPYING b/src/wp-content/plugins/simple-lightbox/COPYING new file mode 100644 index 00000000..d159169d --- /dev/null +++ b/src/wp-content/plugins/simple-lightbox/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/src/wp-content/plugins/simple-lightbox/css/admin.css b/src/wp-content/plugins/simple-lightbox/css/admin.css new file mode 100644 index 00000000..ef9d29f1 --- /dev/null +++ b/src/wp-content/plugins/simple-lightbox/css/admin.css @@ -0,0 +1,28 @@ +.subhead { + margin-bottom: .2em; +} + +#slb_settings { + display: block; + padding: 2em 0 0; +} + +.slb_option_item .block { + display: inline-block; +} + +.slb_option_item label.title { + width: 200px; + padding: 10px; +} + +.slb_option_item .input { + font-size: 11px; + line-height: 20px; + margin-bottom: 9px; + padding: 8px 10px; +} + +.slb_option_item .input select { + min-width: 12em; +} diff --git a/src/wp-content/plugins/simple-lightbox/css/lb_black.css b/src/wp-content/plugins/simple-lightbox/css/lb_black.css new file mode 100644 index 00000000..4815049f --- /dev/null +++ b/src/wp-content/plugins/simple-lightbox/css/lb_black.css @@ -0,0 +1,138 @@ +.slb_dataCaption { font-weight: bold;} +.slb_dataNumber { display: block; clear: left; } +#slb_nav { display: block; clear: left; padding:0 0 10px 0;} +.slb_navPrev { margin:0 8px 0 0; } +.slb_navNext { margin:0 8px 0 0; } +.slb_slbClose { + display:block; + margin:0; + padding:0 0 10px 0; + text-decoration:none; + float:right; + width:66px; + height:28px; + background:url("../images/closelabel_black.gif") no-repeat; + text-indent:-9999px; + overflow:hidden; +} + +#slb_lightbox { + position: absolute; + top: 20px; + left: 0; + width: 100%; + z-index: 3100; + text-align: center; + line-height: 0; + color:#fff; +} + +#slb_lightbox a, #slb_lightbox a:hover { + border-bottom:none; + color:#fff; + text-decoration:underline; +} + +#slb_lightbox a img { border: none; } + +#slb_container { + position: relative; + background-color: #000; + width: 250px; + height: 250px; + margin: 0 auto; +} + +#imageContainer { + padding: 10px; +} + +#loading { + position: absolute; + top: 40%; + left: 0%; + height: 25%; + width: 100%; + text-align: center; + line-height: 0; +} +#slb_slbLoading { + display:block; + margin:0 auto; + padding:0; + width:32px; + height:32px; + background:url("../images/loading_black.gif") center center no-repeat; + text-indent:-9999px; +} + +#nav_hover { + position: absolute; + top: 0; + left: 0; + height: 100%; + width: 100%; + z-index: 10; + left: 0; +} + +#nav_hover a { outline: none; } + +#nav_hover .slb_nav { + width: 47%; + height: 98%; + background: transparent url("../images/blank.gif") no-repeat; /* Trick IE into showing hover */ + display: block; + text-indent: -9999px; +} + +#nav_hover .slb_navPrev { left: 0; float: left;} +#nav_hover .slb_navNext { right: 0; float: right;} +#nav_hover .slb_navPrev:hover, #nav_hover .slb_navPrev:visited:hover { background: url("../images/prevlabel_black.gif") left 15% no-repeat; } +#nav_hover .slb_navNext:hover, #nav_hover .slb_navNext:visited:hover { background: url("../images/nextlabel_black.gif") right 15% no-repeat; } + +#slb_details { + font: 10px Verdana, Helvetica, sans-serif; + background-color: #000; + margin: 0 auto; + line-height: 1.4em; +} + +#imageData { + padding:0 10px; +} +#imageDetails { width: 70%; float: left; text-align: left; } + +#slb_overlay { + position: absolute; + top: 0; + left: 0; + z-index: 3090; + width: 100%; + height: 500px; + background-color: #151410; + filter:alpha(opacity=60); + -moz-opacity: 0.6; + opacity: 0.6; +} + + +.clearfix:after { + content: "."; + display: block; + height: 0; + clear: both; + visibility: hidden; +} + +* html>body .clearfix { + display: inline-block; + width: 100%; +} + +* html .clearfix { + /* Hides from IE-mac \*/ + height: 1%; + /* End hide from IE-mac */ +} + \ No newline at end of file diff --git a/src/wp-content/plugins/simple-lightbox/css/lightbox.css b/src/wp-content/plugins/simple-lightbox/css/lightbox.css new file mode 100644 index 00000000..9f553bef --- /dev/null +++ b/src/wp-content/plugins/simple-lightbox/css/lightbox.css @@ -0,0 +1,138 @@ +.slb_dataCaption { font-weight: bold;} +.slb_dataNumber { display: block; clear: left; } +#slb_nav { display: block; clear: left; padding:0 0 10px 0;} +.slb_navPrev { margin:0 8px 0 0; } +.slb_navNext { margin:0 8px 0 0; } +.slb_slbClose { + display:block; + margin:0; + padding:0 0 10px 0; + text-decoration:none; + float:right; + width:66px; + height:28px; + background:url("../images/closelabel.gif") no-repeat; + text-indent:-9999px; + overflow:hidden; +} + +#slb_lightbox { + position: absolute; + top: 20px; + left: 0; + width: 100%; + z-index: 3100; + text-align: center; + line-height: 0; + color:#151410; +} + +#slb_lightbox a, #slb_lightbox a:hover { + border-bottom:none; + color:#151410; + text-decoration:underline; +} + +#slb_lightbox a img { border: none; } + +#slb_container { + position: relative; + background-color: #fff; + width: 250px; + height: 250px; + margin: 0 auto; +} + +#imageContainer { + padding: 10px; +} + +#loading { + position: absolute; + top: 40%; + left: 0%; + height: 25%; + width: 100%; + text-align: center; + line-height: 0; +} +#slb_slbLoading { + display:block; + margin:0 auto; + padding:0; + width:32px; + height:32px; + background:url("../images/loading.gif") center center no-repeat; + text-indent:-9999px; +} + +#nav_hover { + position: absolute; + top: 0; + left: 0; + height: 100%; + width: 100%; + z-index: 10; + left: 0; +} + +#nav_hover a { outline: none; } + +#nav_hover .slb_nav { + width: 47%; + height: 98%; + background: transparent url("../images/blank.gif") no-repeat; /* Trick IE into showing hover */ + display: block; + text-indent: -9999px; +} + +#nav_hover .slb_navPrev { left: 0; float: left;} +#nav_hover .slb_navNext { right: 0; float: right;} +#nav_hover .slb_navPrev:hover, #nav_hover .slb_navPrev:visited:hover { background: url("../images/prevlabel.gif") left 15% no-repeat; } +#nav_hover .slb_navNext:hover, #nav_hover .slb_navNext:visited:hover { background: url("../images/nextlabel.gif") right 15% no-repeat; } + +#slb_details { + font: 10px Verdana, Helvetica, sans-serif; + background-color: #fff; + margin: 0 auto; + line-height: 1.4em; +} + +#imageData { + padding:0 10px; +} +#imageDetails { width: 70%; float: left; text-align: left; } + +#slb_overlay { + position: absolute; + top: 0; + left: 0; + z-index: 3090; + width: 100%; + height: 500px; + background-color: #151410; + filter:alpha(opacity=60); + -moz-opacity: 0.6; + opacity: 0.6; +} + + +.clearfix:after { + content: "."; + display: block; + height: 0; + clear: both; + visibility: hidden; +} + +* html>body .clearfix { + display: inline-block; + width: 100%; +} + +* html .clearfix { + /* Hides from IE-mac \*/ + height: 1%; + /* End hide from IE-mac */ +} + \ No newline at end of file diff --git a/src/wp-content/plugins/simple-lightbox/images/Thumbs.db b/src/wp-content/plugins/simple-lightbox/images/Thumbs.db new file mode 100644 index 00000000..00e9db86 Binary files /dev/null and b/src/wp-content/plugins/simple-lightbox/images/Thumbs.db differ diff --git a/src/wp-content/plugins/simple-lightbox/images/blank.gif b/src/wp-content/plugins/simple-lightbox/images/blank.gif new file mode 100644 index 00000000..1d11fa9a Binary files /dev/null and b/src/wp-content/plugins/simple-lightbox/images/blank.gif differ diff --git a/src/wp-content/plugins/simple-lightbox/images/closelabel.gif b/src/wp-content/plugins/simple-lightbox/images/closelabel.gif new file mode 100644 index 00000000..af0cab2d Binary files /dev/null and b/src/wp-content/plugins/simple-lightbox/images/closelabel.gif differ diff --git a/src/wp-content/plugins/simple-lightbox/images/closelabel_black.gif b/src/wp-content/plugins/simple-lightbox/images/closelabel_black.gif new file mode 100644 index 00000000..e42ac03c Binary files /dev/null and b/src/wp-content/plugins/simple-lightbox/images/closelabel_black.gif differ diff --git a/src/wp-content/plugins/simple-lightbox/images/loading.gif b/src/wp-content/plugins/simple-lightbox/images/loading.gif new file mode 100644 index 00000000..6371884f Binary files /dev/null and b/src/wp-content/plugins/simple-lightbox/images/loading.gif differ diff --git a/src/wp-content/plugins/simple-lightbox/images/loading_black.gif b/src/wp-content/plugins/simple-lightbox/images/loading_black.gif new file mode 100644 index 00000000..7b8b8367 Binary files /dev/null and b/src/wp-content/plugins/simple-lightbox/images/loading_black.gif differ diff --git a/src/wp-content/plugins/simple-lightbox/images/nextlabel.gif b/src/wp-content/plugins/simple-lightbox/images/nextlabel.gif new file mode 100644 index 00000000..7c66121f Binary files /dev/null and b/src/wp-content/plugins/simple-lightbox/images/nextlabel.gif differ diff --git a/src/wp-content/plugins/simple-lightbox/images/nextlabel_black.gif b/src/wp-content/plugins/simple-lightbox/images/nextlabel_black.gif new file mode 100644 index 00000000..6a523771 Binary files /dev/null and b/src/wp-content/plugins/simple-lightbox/images/nextlabel_black.gif differ diff --git a/src/wp-content/plugins/simple-lightbox/images/prevlabel.gif b/src/wp-content/plugins/simple-lightbox/images/prevlabel.gif new file mode 100644 index 00000000..06418767 Binary files /dev/null and b/src/wp-content/plugins/simple-lightbox/images/prevlabel.gif differ diff --git a/src/wp-content/plugins/simple-lightbox/images/prevlabel_black.gif b/src/wp-content/plugins/simple-lightbox/images/prevlabel_black.gif new file mode 100644 index 00000000..55286e3c Binary files /dev/null and b/src/wp-content/plugins/simple-lightbox/images/prevlabel_black.gif differ diff --git a/src/wp-content/plugins/simple-lightbox/includes/class.base.php b/src/wp-content/plugins/simple-lightbox/includes/class.base.php new file mode 100644 index 00000000..9cf98997 --- /dev/null +++ b/src/wp-content/plugins/simple-lightbox/includes/class.base.php @@ -0,0 +1,135 @@ +__construct(); + } + + /** + * Constructor + */ + function __construct() { + $this->util =& new SLB_Utilities($this); + } + + /*-** Init **-*/ + + /** + * Default initialization method + * To be overriden by child classes + */ + function init() { + $func = 'register_hooks'; + if ( isset($this) && method_exists($this, $func) ) { + call_user_method($func, $this); + } + } + + function register_hooks() { + //Activation + $func_activate = 'activate'; + if ( method_exists($this, $func_activate) ) + register_activation_hook($this->util->get_plugin_base_file(), $this->m($func_activate)); + //Deactivation + $func_deactivate = 'deactivate'; + if ( method_exists($this, $func_deactivate) ) + register_deactivation_hook($this->util->get_plugin_base_file(), $this->m($func_deactivate)); + } + + /*-** Reflection **-*/ + + /** + * Retrieve base object + * @return object|bool Base object (FALSE if object does not exist) + */ + function &get_base() { + return ( isset($GLOBALS[$this->base]) ) ? $GLOBALS[$this->base] : false; + } + + /*-** Method/Function calling **-*/ + + /** + * Returns callback to instance method + * @param string $method Method name + * @return array Callback array + */ + function &m($method) { + return $this->util->m($this, $method); + } + + /*-** Prefix **-*/ + + /** + * Retrieve class prefix (with separator if set) + * @param bool|string $sep Separator to append to class prefix (Default: no separator) + * @return string Class prefix + */ + function get_prefix($sep = null) { + $args = func_get_args(); + return call_user_func_array($this->util->m($this->util, 'get_prefix'), $args); + } + + /** + * Check if a string is prefixed + * @param string $text Text to check for prefix + * @param string $sep (optional) Separator used + */ + function has_prefix($text, $sep = null) { + $args = func_get_args(); + return call_user_func_array($this->util->m($this->util, 'has_prefix'), $args); + } + + /** + * Prepend plugin prefix to some text + * @param string $text Text to add to prefix + * @param string $sep (optional) Text used to separate prefix and text + * @param bool $once (optional) Whether to add prefix to text that already contains a prefix or not + * @return string Text with prefix prepended + */ + function add_prefix($text, $sep = null, $once = true) { + $args = func_get_args(); + return call_user_func_array($this->util->m($this->util, 'add_prefix'), $args); + } + + /** + * Remove prefix from specified string + * @param string $text String to remove prefix from + * @param string $sep (optional) Separator used with prefix + */ + function remove_prefix($text, $sep = null) { + $args = func_get_args(); + return call_user_func_array($this->util->m($this->util, 'remove_prefix'), $args); + } +} + +?> \ No newline at end of file diff --git a/src/wp-content/plugins/simple-lightbox/includes/class.fields.php b/src/wp-content/plugins/simple-lightbox/includes/class.fields.php new file mode 100644 index 00000000..593db227 --- /dev/null +++ b/src/wp-content/plugins/simple-lightbox/includes/class.fields.php @@ -0,0 +1,2240 @@ + Key (string): Format name + * > Val (array): Options + * @var array + */ + var $id_formats_default = array( + 'attr_id' => array( + 'wrap' => array('open' => '_', 'segment_open' => '_'), + 'prefix' => array('get_container', 'get_id', 'add_prefix'), + 'recursive' => true + ), + 'attr_name' => array( + 'wrap' => array('open' => '[', 'close' => ']', 'segment_open' => '[', 'segment_close' => ']'), + 'recursive' => true, + 'prefix' => array('get_container', 'get_id', 'add_prefix') + ) + ); + + /** + * Reference to parent object that current instance inherits from + * @var object + */ + var $parent = null; + + /** + * Title + * @var string + */ + var $title = ''; + + /** + * @var string Short description + */ + var $description = ''; + + /** + * @var array Object Properties + */ + var $properties = array(); + + /** + * Initialization properties + * @var array + */ + var $properties_init = null; + + /** + * Structure: Property names stored as keys in group + * Root + * -> Group Name + * -> Property Name => Null + * Reason: Faster searching over large arrays + * @var array Groupings of Properties + */ + var $property_groups = array(); + + /** + * Keys to filter out of properties array before setting properties + * @var array + */ + var $property_filter = array('group'); + + /** + * Data for object + * May also contain data for nested objects + * @var mixed + */ + var $data = null; + + /** + * @var array Script resources to include for object + */ + var $scripts = array(); + + /** + * @var array CSS style resources to include for object + */ + var $styles = array(); + + /** + * Hooks (Filters/Actions) for object + * @var array + */ + var $hooks = array(); + + /** + * Mapping of child properties to parent members + * Allows more flexibility when creating new instances of child objects using property arrays + * Associative array structure: + * > Key: Child property to map FROM + * > Val: Parent property to map TO + * @var array + */ + var $map = null; + + /** + * Legacy Constructor + */ + function SLB_Field_Base($id = '', $parent = null) { + $args = func_get_args(); + call_user_func_array(array(&$this, '__construct'), $args); + } + + /** + * Constructor + */ + function __construct($id = '', $parent = null) { + parent::__construct(); + //Normalize Properties + $args = func_get_args(); + if ( func_num_args() > 1 && empty($parent) ) { + unset($args[1]); + $args = array_values($args); + } + $properties = $this->make_properties($this->util->func_get_options($args), array('id' => $id, 'parent' => $parent)); + //Remove empty variables + if ( empty($properties['parent']) ) + unset($properties['parent']); + //Save init properties + $this->properties_init = $properties; + //Set Properties + $this->set_properties($properties); + } + + /* Getters/Setters */ + + /** + * Checks if the specified path exists in the object + * @param array $path Path to check for + * @return bool TRUE if path exists in object, FALSE otherwise + */ + function path_isset($path = '') { + //Stop execution if no path is supplied + if ( empty($path) ) + return false; + $args = func_get_args(); + $path = $this->util->build_path($args); + $item =& $this; + //Iterate over path and check if each level exists before moving on to the next + for ($x = 0; $x < count($path); $x++) { + if ( $this->util->property_exists($item, $path[$x]) ) { + //Set $item as reference to next level in path for next iteration + $item =& $this->util->get_property($item, $path[$x]); + //$item =& $item[ $path[$x] ]; + } else { + return false; + } + } + return true; + } + + /** + * Retrieves a value from object using a specified path + * Checks to make sure path exists in object before retrieving value + * @param array $path Path to retrieve value from. Each item in array is a deeper dimension + * @return mixed Value at specified path + */ + function &get_path_value($path = '') { + $ret = ''; + $path = $this->util->build_path(func_get_args()); + if ( $this->path_isset($path) ) { + $ret =& $this; + for ($x = 0; $x < count($path); $x++) { + if ( 0 == $x ) + $ret =& $ret->{ $path[$x] }; + else + $ret =& $ret[ $path[$x] ]; + } + } + return $ret; + } + + /** + * Search for specified member value in field type ancestors + * @param string $member Name of object member to search (e.g. properties, layout, etc.) + * @param string $name Value to retrieve from member + * @return mixed Member value if found (Default: empty string) + */ + function get_parent_value($member, $name = '', $default = '') { + $parent =& $this->get_parent(); + return $this->get_object_value($parent, $member, $name, $default, 'parent'); + } + + /** + * Retrieves specified member value + * Handles inherited values + * Merging corresponding parents if value is an array (e.g. for property groups) + * @param string|array $member Member to search. May also contain a path to the desired member + * @param string $name Value to retrieve from member + * @param mixed $default Default value if no value found (Default: empty string) + * @param string $dir Direction to move through hierarchy to find value + * Possible Values: + * parent (default) - Search through field parents + * current - Do not search through connected objects + * container - Search through field containers + * caller - Search through field callers + * @return mixed Specified member value + * @todo Return reference + */ + function &get_member_value($member, $name = '', $default = '', $dir = 'parent') { + //Check if path to member is supplied + $path = array(); + if ( is_array($member) && isset($member['tag']) ) { + if ( isset($member['attributes']['ref_base']) ) { + if ( 'root' != $member['attributes']['ref_base'] ) + $path[] = $member['attributes']['ref_base']; + } else { + $path[] = 'properties'; + } + + $path[] = $member['tag']; + } else { + $path = $member; + } + + $path = $this->util->build_path($path, $name); + //Set defaults and prepare data + $val = $default; + $inherit = false; + $inherit_tag = '{inherit}'; + + /* Determine whether the value must be retrieved from a parent/container object + * Conditions: + * > Path does not exist in current field + * > Path exists and is not an object, but at least one of the following is true: + * > Value at path is an array (e.g. properties, elements, etc. array) + * > Parent/container values should be merged with retrieved array + * > Value at path is a string that inherits from another field + * > Value from other field will be retrieved and will replace inheritance placeholder in retrieved value + */ + + $deeper = false; + + if ( !$this->path_isset($path) ) + $deeper = true; + else { + $val = $this->get_path_value($path); + if ( !is_object($val) && ( is_array($val) || ($inherit = strpos($val, $inherit_tag)) !== false ) ) + $deeper = true; + else + $deeper = false; + } + if ( $deeper && 'current' != $dir ) { + //Get Parent value (recursive) + $ex_val = ( 'parent' != $dir ) ? $this->get_container_value($member, $name, $default) : $this->get_parent_value($member, $name, $default); + //Handle inheritance + if ( is_array($val) ) { + //Combine Arrays + if ( is_array($ex_val) ) + $val = array_merge($ex_val, $val); + } elseif ( $inherit !== false ) { + //Replace placeholder with inherited string + $val = str_replace($inherit_tag, $ex_val, $val); + } else { + //Default: Set parent value as value + $val = $ex_val; + } + } + + return $val; + } + + /** + * Search for specified member value in an object + * @param object $object Reference to object to retrieve value from + * @param string $member Name of object member to search (e.g. properties, layout, etc.) + * @param string $name (optional) Value to retrieve from member + * @param mixed $default (optional) Default value to use if no value found (Default: empty string) + * @param string $dir Direction to move through hierarchy to find value @see SLB_Field_Type::get_member_value() for possible values + * @return mixed Member value if found (Default: $default) + */ + function get_object_value(&$object, $member, $name = '', $default = '', $dir = 'parent') { + $ret = $default; + if ( is_object($object) && method_exists($object, 'get_member_value') ) + $ret = $object->get_member_value($member, $name, $default, $dir); + return $ret; + } + + /** + * Set item ID + * @param string $id Unique item ID + */ + function set_id($id) { + if ( empty($id) || !is_string($id) ) + return false; + $this->id = trim($id); + } + + /** + * Retrieves field ID + * @param array|string $options (optional) Options or ID of format to use + * @return string item ID + */ + function get_id($options = array()) { + $item_id = trim($this->id); + + $formats = $this->get_id_formats(); + + //Setup options + $options_default = array( + 'format' => null, + 'wrap' => array('open' => '', 'close' => '', 'segment_open' => '', 'segment_close' => ''), + 'segments_pre' => null, + 'prefix' => '', + 'recursive' => false + ); + + //Load options based on format + if ( !is_array($options) ) + $options = array('format' => $options); + if ( is_string($options['format']) && isset($formats[$options['format']]) ) + $options_default = wp_parse_args($formats[$options['format']], $options_default); + else + unset($options['format']); + $options = wp_parse_args($options, $options_default); + extract($options); + + //Validate options + $wrap = wp_parse_args($wrap, $options_default['wrap']); + + if ( !is_array($segments_pre) ) + $segments_pre = array($segments_pre); + $segments_pre = array_reverse($segments_pre); + + //Format ID based on options + + $item_id = array($item_id); + + //Add parent objects to ID + if ( !!$recursive ) { + //Create array of ID components + $c = $this->get_caller(); + while ( !!$c ) { + //Add ID of current caller to array + if ( method_exists($c, 'get_id') && ( $itemp = $c->get_id() ) && !empty($itemp) ) + $item_id = $itemp; + //Get parent object + $c = ( method_exists($c, 'get_caller') ) ? $c->get_caller() : null; + $itemp = ''; + } + unset($c); + } + + //Additional segments (Pre) + foreach ( $segments_pre as $seg ) { + if ( is_null($seg) ) + continue; + if ( is_object($seg) ) + $seg = (array)$seg; + if ( is_array($seg) ) + $item_id = array_merge($item_id, array_reverse($seg)); + elseif ( '' != strval($seg) ) + $item_id[] = strval($seg); + } + + //Prefix + if ( is_array($prefix) ) { + //Array is sequence of instance methods to call on object + //Last array member can be an array of parameters to pass to methods + $count = count($prefix); + $args = ( $count > 1 && is_array($prefix[$count - 1]) ) ? array_pop($prefix) : array(); + $p = $this; + $val = ''; + //Iterate through methods + foreach ( $prefix as $m ) { + //Build callback + $m = $this->util->m($p, $m); + //Call callback + if ( is_callable($m) ) + $val = call_user_func_array($m, $args); + //Process returned value + if ( is_object($val) ) + $p = $val; //Use returned object in next round + else + array_unshift($args, $val); //Pass returned value as parameter to next method on using current object + } + $prefix = $val; + unset($p, $val); + } + if ( is_numeric($prefix) ) + $prefix = strval($prefix); + if ( empty($prefix) || !is_string($prefix) ) + $prefix = ''; + + //Convert array to string + $item_id = $prefix . $wrap['open'] . implode($wrap['segment_close'] . $wrap['segment_open'], array_reverse($item_id)) . $wrap['close']; + return $item_id; + } + + /** + * Retrieve ID formatting options for class + * Format options arrays are merged together and saved to $id_formats + * @uses $id_formats + * @uses $id_formats_default + * @return array ID Formatting options + */ + function &get_id_formats() { + if ( is_null($this->id_formats) ) { + $this->id_formats = wp_parse_args($this->id_formats, $this->id_formats_default); + } + return $this->id_formats; + } + + /** + * Retrieve value from data member + * @param string $context Context to format data for + * @param bool $top (optional) Whether to traverse through the field hierarchy to get data for field (Default: TRUE) + * @return mixed Value at specified path + */ + function get_data($context = '', $top = true) { + $opt_d = array('context' => '', 'top' => true); + $args = func_get_args(); + $a = false; + if ( count($args) == 1 && is_array($args[0]) && !empty($args[0]) ) { + $a = true; + $args = wp_parse_args($args[0], $opt_d); + extract($args); + } + + if ( is_string($top) ) { + if ( 'false' == $top ) + $top = false; + elseif ( 'true' == $top ) + $top = true; + elseif ( is_numeric($top) ) + $top = intval($top); + } + $top = !!$top; + $obj =& $this; + $obj_path = array(&$this); + $path = array(); + if ( $top ) { + //Iterate through hiearchy to get top-most object + while ( !empty($obj) ) { + $new = null; + //Try to get caller first + if ( method_exists($obj, 'get_caller') ) { + $checked = true; + $new =& $obj->get_caller(); + } + //Try to get container if no caller found + if ( empty($new) && method_exists($obj, 'get_container') ) { + $checked = true; + $new =& $obj->get_container(); + //Load data + if ( method_exists($new, 'load_data') ) { + $new->load_data(); + } + } + + $obj =& $new; + unset($new); + //Stop iteration + if ( !empty($obj) ) { + //Add object to path if it is valid + $obj_path[] =& $obj; + } + } + unset($obj); + } + + //Check each object (starting with top-most) for matching data for current field + + //Reverse array + $obj_path = array_reverse($obj_path); + //Build path for data location + foreach ( $obj_path as $obj ) { + if ( method_exists($obj, 'get_id') ) + $path[] = $obj->get_id(); + } + //Iterate through objects + while ( !empty($obj_path) ) { + //Get next object + $obj =& array_shift($obj_path); + //Shorten path + array_shift($path); + //Check for value in object and stop iteration if matching data found + $val = $this->get_object_value($obj, 'data', $path, null, 'current'); + if ( !is_null($val) ) { + break; + } + } + return $this->format($val, $context); + } + + /** + * Sets value in data member + * Sets value to data member itself by default + * @param mixed $value Value to set + * @param string|array $name Name of value to set (Can also be path to value) + */ + function set_data($value, $name = '') { + $ref =& $this->get_path_value('data', $name); + $ref = $value; + } + + /** + * Sets parent object of current instance + * Parent objects must be the same object type as current instance + * @uses SLB to get field type definition + * @uses SLB_Fields::has() to check if field type exists + * @uses SLB_Fields::get() to retrieve field type object reference + * @param string|object $parent Parent ID or reference + */ + function set_parent($parent = null) { + //Stop processing if parent empty + if ( empty($parent) && !is_string($this->parent) ) + return false; + //Parent passed as object reference wrapped in array + if ( is_array($parent) && is_object($parent[0]) ) + $parent =& $parent[0]; + + //No parent set but parent ID (previously) set in object + if ( empty($parent) && is_string($this->parent) ) + $parent = $this->parent; + + //Retrieve reference object if ID was supplied + if ( is_string($parent) ) { + $parent = trim($parent); + //Get parent object reference + /** + * @var SLB + */ + $b =& $this->get_base(); + if ( $b && $b->fields->has($parent) ) { + $parent =& $b->fields->get($parent); + } + } + + //Set parent value on object + if ( is_string($parent) || is_object($parent) ) + $this->parent =& $parent; + } + + /** + * Retrieve field type parent + * @return SLB_Field_Type Reference to parent field + */ + function &get_parent() { + return $this->parent; + } + + /** + * Set object title + * @param string $title Title for object + * @param string $plural Plural form of title + */ + function set_title($title = '') { + $this->title = strip_tags(trim($title)); + } + + /** + * Retrieve object title + */ + function get_title() { + return $this->get_member_value('title', '','', 'current'); + } + + /** + * Set object description + * @param string $description Description for object + */ + function set_description($description = '') { + $this->description = strip_tags(trim($description)); + } + + /** + * Retrieve object description + * @return string Object description + */ + function get_description() { + $dir = 'current'; + return $this->get_member_value('description', '','', $dir); + return $desc; + } + + /** + * Sets multiple properties on field type at once + * @param array $properties Properties. Each element is an array containing the arguments to set a new property + * @return boolean TRUE if successful, FALSE otherwise + */ + function set_properties($properties) { + if ( !is_array($properties) ) + return false; + + //Set Member properties + foreach ( $properties as $prop => $val ) { + if ( ( $m = 'set_' . $prop ) && method_exists($this, $m) ) { + $this->{$m}($val); + //Remove member property from array + unset($properties[$prop]); + } + } + + //Filter properties + $properties = $this->filter_properties($properties); + + //Set additional instance properties + foreach ( $properties as $name => $val) { + $this->set_property($name, $val); + } + } + + /** + * Remap properties based on $map + * @uses $map For determine how child properties should map to parent properties + * @uses SLB_Utlities::array_remap() to perform array remapping + * @param array $properties Associative array of properties + * @return array Remapped properties + */ + function remap_properties($properties) { + //Return remapped properties + return $this->util->array_remap($properties, $this->map); + } + + /** + * Build properties array + * Accepts a variable number of additional arrays of default properties + * that will be merged in order from last to first + * (e.g. first array overwrites duplicate members in last) + * @uses SLB_Field_Base::remap() to remap properties members if necessary + * @param array $props Instance properties + * @param array $defaults Default properties + * @return array Normalized properties + */ + function make_properties($props, $defaults = array()) { + $args = func_get_args(); + $args = array_reverse($args); + $props = array(); + foreach ( $args as $arg ) { + $props = wp_parse_args($arg, $props); + } + return $this->remap_properties($props); + } + + /** + * Filter property members + * @uses $property_filter to remove define members to remove from $properties + * @param array $props Properties + * @return array Filtered properties + */ + function filter_properties($props = array()) { + return $this->util->array_filter_keys($props, $this->property_filter); + } + + /** + * Add/Set a property on the field definition + * @param string $name Name of property + * @param mixed $value Default value for property + * @param string|array $group Group(s) property belongs to + * @return boolean TRUE if property is successfully added to field type, FALSE otherwise + */ + function set_property($name, $value = '', $group = null) { + //Do not add if property name is not a string + if ( !is_string($name) ) + return false; + //Create property array + $prop_arr = array(); + $prop_arr['value'] = $value; + //Add to properties array + $this->properties[$name] = $value; + //Add property to specified groups + if ( !empty($group) ) { + $this->set_group_property($group, $name); + } + return true; + } + + /** + * Retreives property from field type + * @param string $name Name of property to retrieve + * @return mixed Specified Property if exists (Default: Empty string) + */ + function get_property($name) { + $val = $this->get_member_value('properties', $name); + return $val; + } + + /** + * Removes a property from item + * @param string $name Property ID + */ + function remove_property($name) { + //Remove property + if ( isset($this->properties[$name]) ) + unset($this->properties[$name]); + //Remove from group + foreach ( array_keys($this->property_groups) as $g ) { + if ( isset($this->property_groups[$g][$name]) ) { + unset($this->property_groups[$g][$name]); + break; + } + } + } + + /** + * Adds Specified Property to a Group + * @param string|array $group Group(s) to add property to + * @param string $property Property to add to group + */ + function set_group_property($group, $property) { + if ( is_string($group) && isset($this->property_groups[$group][$property]) ) + return; + if ( !is_array($group) ) { + $group = array($group); + } + + foreach ($group as $g) { + $g = trim($g); + //Initialize group if it doesn't already exist + if ( !isset($this->property_groups[$g]) ) + $this->property_groups[$g] = array(); + + //Add property to group + $this->property_groups[$g][$property] = null; + } + } + + /** + * Retrieve property group + * @param string $group Group to retrieve + * @return array Array of properties in specified group + */ + function get_group($group) { + return $this->get_member_value('property_groups', $group, array()); + } + + /** + * Save field data + * Child classes will define their own + * functionality for this method + * @return bool TRUE if save was successful (FALSE otherwise) + */ + function save() { + return true; + } + + /*-** Hooks **-*/ + + /** + * Retrieve hooks added to object + * @return array Hooks + */ + function get_hooks() { + return $this->get_member_value('hooks', '', array()); + } + + /** + * Add hook for object + * @see add_filter() for parameter defaults + * @param $tag + * @param $function_to_add + * @param $priority + * @param $accepted_args + */ + function add_hook($tag, $function_to_add, $priority = 10, $accepted_args = 1) { + //Create new array for tag (if not already set) + if ( !isset($this->hooks[$tag]) ) + $this->hooks[$tag] = array(); + //Build Unique ID + if ( is_string($function_to_add) ) + $id = $function_to_add; + elseif ( is_array($function_to_add) && !empty($function_to_add) ) + $id = strval($function_to_add[count($function_to_add) - 1]); + else + $id = 'function_' . ( count($this->hooks[$tag]) + 1 ); + //Add hook + $this->hooks[$tag][$id] = func_get_args(); + } + + /** + * Convenience method for adding an action for object + * @see add_filter() for parameter defaults + * @param $tag + * @param $function_to_add + * @param $priority + * @param $accepted_args + */ + function add_action($tag, $function_to_add, $priority = 10, $accepted_args = 1) { + $this->add_hook($tag, $function_to_add, $priority, $accepted_args); + } + + /** + * Convenience method for adding a filter for object + * @see add_filter() for parameter defaults + * @param $tag + * @param $function_to_add + * @param $priority + * @param $accepted_args + */ + function add_filter($tag, $function_to_add, $priority = 10, $accepted_args = 1) { + $this->add_hook($tag, $function_to_add, $priority, $accepted_args); + } + + /*-** Dependencies **-*/ + + /** + * Adds dependency to object + * @param string $type Type of dependency to add (script, style) + * @param array|string $context When dependency will be added (@see SLB_Utilities::get_action() for possible contexts) + * @see wp_enqueue_script for the following of the parameters + * @param $handle + * @param $src + * @param $deps + * @param $ver + * @param $ex + */ + function add_dependency($type, $context, $handle, $src = false, $deps = array(), $ver = false, $ex = false) { + $args = func_get_args(); + //Remove type/context from arguments + $args = array_slice($args, 2); + + //Set context + if ( !is_array($context) ) { + //Wrap single contexts in an array + if ( is_string($context) ) + $context = array($context); + else + $context = array(); + } + //Add file to instance property + if ( isset($this->{$type}) && is_array($this->{$type}) ) + $this->{$type}[$handle] = array('context' => $context, 'params' => $args); + } + + /** + * Add script to object to be added in specified contexts + * @param array|string $context Array of contexts to add script to page + * @see wp_enqueue_script for the following of the parameters + * @param $handle + * @param $src + * @param $deps + * @param $ver + * @param $in_footer + */ + function add_script( $context, $handle, $src = false, $deps = array(), $ver = false, $in_footer = false ) { + $args = func_get_args(); + //Add file type to front of arguments array + array_unshift($args, 'scripts'); + call_user_func_array($this->m('add_dependency'), $args); + } + + /** + * Retrieve script dependencies for object + * @return array Script dependencies + */ + function get_scripts() { + return $this->get_member_value('scripts', '', array()); + } + + /** + * Add style to object to be added in specified contexts + * @param array|string $context Array of contexts to add style to page + * @see wp_enqueue_style for the following of the parameters + * @param $handle + * @param $src + * @param $deps + * @param $ver + * @param $in_footer + */ + function add_style( $handle, $src = false, $deps = array(), $ver = false, $media = false ) { + $args = func_get_args(); + array_unshift($args, 'styles'); + call_user_func_array($this->m('add_dependency'), $args); + } + + /** + * Retrieve Style dependencies for object + * @return array Style dependencies + */ + function get_styles() { + return $this->get_member_value('styles', '', array()); + } + + /* Helpers */ + + /** + * Format value based on specified context + * @param mixed $value Value to format + * @param string $context Current context + * @return mixed Formatted value + */ + function format($value, $context = '') { + $handler = 'format_' . trim(strval($context)); + //Only process if context is valid and has a handler + if ( !empty($context) && method_exists($this, $handler) ) { + //Pass value to handler + $value = $this->{$handler}($value, $context); + } + //Return formatted value + return $value; + } + + /** + * Format value for output in form field + * @param mixed $value Value to format + * @return mixed Formatted value + */ + function format_form($value) { + if ( is_string($value) ) + $value = htmlentities($value); + return $value; + } +} + +/** + * Field Types + * Stores properties for a specific field + * @package Simple Lightbox + * @subpackage Fields + * @author SM + */ +class SLB_Field_Type extends SLB_Field_Base { + /* Properties */ + + /** + * @var array Array of Field types that make up current Field type + */ + var $elements = array(); + + /** + * @var array Field type layouts + */ + var $layout = array(); + + /** + * @var SLB_Field_Type Parent field type (reference) + */ + var $parent = null; + + /** + * Object that field is in + * @var SLB_Field|SLB_Field_Type|SLB_Field_Collection + */ + var $container = null; + + /** + * Object that called field + * Used to determine field hierarchy/nesting + * @var SLB_Field|SLB_Field_Type|SLB_Field_Collection + */ + var $caller = null; + + /** + * Legacy Constructor + */ + function SLB_Field_Type($id = '', $parent = null) { + $args = func_get_args(); + call_user_func_array(array(&$this, '__construct'), $args); + } + + function __construct($id = '', $parent = null) { + parent::__construct($id, $parent); + } + + /* Getters/Setters */ + + /** + * Search for specified member value in field's container object (if exists) + * @param string $member Name of object member to search (e.g. properties, layout, etc.) + * @param string $name Value to retrieve from member + * @return mixed Member value if found (Default: empty string) + */ + function get_container_value($member, $name = '', $default = '') { + $container =& $this->get_container(); + return $this->get_object_value($container, $member, $name, $default, 'container'); + } + + /** + * Search for specified member value in field's container object (if exists) + * @param string $member Name of object member to search (e.g. properties, layout, etc.) + * @param string $name Value to retrieve from member + * @return mixed Member value if found (Default: empty string) + */ + function get_caller_value($member, $name = '', $default = '') { + $caller =& $this->get_caller(); + return $this->get_object_value($caller, $member, $name, $default, 'caller'); + } + + /** + * Sets reference to container object of current field + * Reference is cleared if no valid object is passed to method + * @param object $container + */ + function set_container(&$container) { + if ( !empty($container) && is_object($container) ) { + //Set as param as container for current field + $this->container =& $container; + } else { + //Clear container member if argument is invalid + $this->clear_container(); + } + } + + /** + * Clears reference to container object of current field + */ + function clear_container() { + $this->container = null; + } + + /** + * Retrieves reference to container object of current field + * @return object Reference to container object + */ + function &get_container() { + $ret = null; + if ( $this->has_container() ) + $ret =& $this->container; + return $ret; + } + + /** + * Checks if field has a container reference + * @return bool TRUE if field is contained, FALSE otherwise + */ + function has_container() { + return !empty($this->container); + } + + /** + * Sets reference to calling object of current field + * Any existing reference is cleared if no valid object is passed to method + * @param object $caller Calling object + */ + function set_caller(&$caller) { + if ( !empty($caller) && is_object($caller) ) + $this->caller =& $caller; + else + $this->clear_caller(); + } + + /** + * Clears reference to calling object of current field + */ + function clear_caller() { + unset($this->caller); + } + + /** + * Retrieves reference to caller object of current field + * @return object Reference to caller object + */ + function &get_caller() { + $ret = null; + if ( $this->has_caller() ) + $ret =& $this->caller; + return $ret; + } + + /** + * Checks if field has a caller reference + * @return bool TRUE if field is called by another field, FALSE otherwise + */ + function has_caller() { + return !empty($this->caller); + } + + + + /** + * Sets an element for the field type + * @param string $name Name of element + * @param SLB_Field_Type $type Reference of field type to use for element + * @param array $properties Properties for element (passed as keyed associative array) + * @param string $id_prop Name of property to set $name to (e.g. ID, etc.) + */ + function set_element($name, $type, $properties = array(), $id_prop = 'id') { + $name = trim(strval($name)); + if ( empty($name) ) + return false; + //Create new field for element + $el = new SLB_Field($name, $type); + //Set container to current field instance + $el->set_container($this); + //Add properties to element + $el->set_properties($properties); + //Save element to current instance + $this->elements[$name] =& $el; + } + + /** + * Add a layout to the field + * @param string $name Name of layout + * @param string $value Layout text + */ + function set_layout($name, $value = '') { + if ( !is_string($name) ) + return false; + $name = trim($name); + $this->layout[$name] = $value; + return true; + } + + /** + * Retrieve specified layout + * @param string $name Layout name + * @param bool $parse_nested (optional) Whether nested layouts should be expanded in retreived layout or not (Default: TRUE) + * @return string Specified layout text + */ + function get_layout($name = 'form', $parse_nested = true) { + //Retrieve specified layout (use $name value if no layout by that name exists) + $layout = $this->get_member_value('layout', $name, $name); + + //Find all nested layouts in current layout + if ( !empty($layout) && !!$parse_nested ) { + $ph = $this->get_placeholder_defaults(); + + while ($ph->match = $this->parse_layout($layout, $ph->pattern_layout)) { + //Iterate through the different types of layout placeholders + foreach ($ph->match as $tag => $instances) { + //Iterate through instances of a specific type of layout placeholder + foreach ($instances as $instance) { + //Get nested layout + $nested_layout = $this->get_member_value($instance); + + //Replace layout placeholder with retrieved item data + if ( !empty($nested_layout) ) + $layout = str_replace($ph->start . $instance['match'] . $ph->end, $nested_layout, $layout); + } + } + } + } + + return $layout; + } + + /** + * Checks if specified layout exists + * Finds layout if it exists in current object or any of its parents + * @param string $layout Name of layout to check for + * @return bool TRUE if layout exists, FALSE otherwise + */ + function has_layout($layout) { + $ret = false; + if ( is_string($layout) && ($layout = trim($layout)) && !empty($layout) ) { + $layout = $this->get_member_value('layout', $layout, false); + if ( $layout !== false ) + $ret = true; + } + + return $ret; + } + + /** + * Checks if layout content is valid + * Layouts need to have placeholders to be valid + * @param string $layout_content Layout content (markup) + * @return bool TRUE if layout is valid, FALSE otherwise + */ + function is_valid_layout($layout_content) { + $ph = $this->get_placeholder_defaults(); + return preg_match($ph->pattern_general, $layout_content); + } + + /** + * Parse field layout with a regular expression + * @param string $layout Layout data + * @param string $search Regular expression pattern to search layout for + * @return array Associative array containing all of the regular expression matches in the layout data + * Array Structure: + * root => placeholder tags + * => Tag instances (array) + * 'tag' => (string) tag name + * 'match' => (string) placeholder match + * 'attributes' => (array) attributes + */ + function parse_layout($layout, $search) { + $ph_xml = ''; + $parse_match = ''; + $ph_root_tag = 'ph_root_element'; + $ph_start_xml = '<'; + $ph_end_xml = ' />'; + $ph_wrap_start = '<' . $ph_root_tag . '>'; + $ph_wrap_end = ''; + $parse_result = false; + + //Find all nested layouts in layout + $match_value = preg_match_all($search, $layout, $parse_match, PREG_PATTERN_ORDER); + + if ($match_value !== false && $match_value > 0) { + $parse_result = array(); + //Get all matched elements + $parse_match = $parse_match[1]; + + //Build XML string from placeholders + foreach ($parse_match as $ph) { + $ph_xml .= $ph_start_xml . $ph . $ph_end_xml . ' '; + } + $ph_xml = $ph_wrap_start . $ph_xml . $ph_wrap_end; + //Parse XML data + $ph_prs = xml_parser_create(); + xml_parser_set_option($ph_prs, XML_OPTION_SKIP_WHITE, 1); + xml_parser_set_option($ph_prs, XML_OPTION_CASE_FOLDING, 0); + $ret = xml_parse_into_struct($ph_prs, $ph_xml, $parse_result['values'], $parse_result['index']); + xml_parser_free($ph_prs); + + //Build structured array with all parsed data + + unset($parse_result['index'][$ph_root_tag]); + + //Build structured array + $result = array(); + foreach ($parse_result['index'] as $tag => $instances) { + $result[$tag] = array(); + //Instances + foreach ($instances as $instance) { + //Skip instance if it doesn't exist in parse results + if (!isset($parse_result['values'][$instance])) + continue; + + //Stop processing instance if a previously-saved instance with the same options already exists + foreach ($result[$tag] as $tag_match) { + if ($tag_match['match'] == $parse_match[$instance - 1]) + continue 2; + } + + //Init instance data array + $inst_data = array(); + + //Add Tag to array + $inst_data['tag'] = $parse_result['values'][$instance]['tag']; + + //Add instance data to array + $inst_data['attributes'] = (isset($parse_result['values'][$instance]['attributes'])) ? $inst_data['attributes'] = $parse_result['values'][$instance]['attributes'] : ''; + + //Add match to array + $inst_data['match'] = $parse_match[$instance - 1]; + + //Add to result array + $result[$tag][] = $inst_data; + } + } + $parse_result = $result; + } + + return $parse_result; + } + + /** + * Retrieves default properties to use when evaluating layout placeholders + * @return object Object with properties for evaluating layout placeholders + */ + function get_placeholder_defaults() { + $ph = new stdClass(); + $ph->start = '{'; + $ph->end = '}'; + $ph->reserved = array('ref' => 'ref_base'); + $ph->pattern_general = '/' . $ph->start . '([a-zA-Z0-9_].*?)' . $ph->end . '/i'; + $ph->pattern_layout = '/' . $ph->start . '([a-zA-Z0-9].*?\s+' . $ph->reserved['ref'] . '="layout.*?".*?)' . $ph->end . '/i'; + return $ph; + } + + /** + * Build item output + * @param string $layout (optional) Layout to build + * @param string $data Data to pass to layout + * @return string Generated output + */ + function build($layout = 'form', $data = null) { + $out = array( + $this->build_pre($layout, $data), + $this->build_layout($layout,$data), + $this->build_post($layout, $data) + ); + return implode('', $out); + } + + /** + * Content to add before layout output + * @return string + */ + function build_pre($layout = 'form', $data = null) { + return ''; + } + + /** + * Content to add after layout output + * @return string + */ + function build_post($layout = 'form', $data = null) { + return ''; + } + + /** + * Builds HTML for a field based on its properties + * @param string $layout (optional) Name of layout to build + * @param array $data Additional data for current item + */ + function build_layout($layout = 'form', $data = null) { + $out_default = ''; + //Get base layout + $out = $this->get_layout($layout); + //Only parse valid layouts + if ( $this->is_valid_layout($out) ) { + //Parse Layout + $ph = $this->get_placeholder_defaults(); + + //Search layout for placeholders + while ( $ph->match = $this->parse_layout($out, $ph->pattern_general) ) { + //Iterate through placeholders (tag, id, etc.) + foreach ( $ph->match as $tag => $instances ) { + //Iterate through instances of current placeholder + foreach ( $instances as $instance ) { + //Process value based on placeholder name + $target_property = apply_filters($this->add_prefix('process_placeholder_' . $tag), '', $this, $instance, $layout, $data); + //Process value using default processors (if necessary) + if ( '' == $target_property ) { + $target_property = apply_filters($this->add_prefix('process_placeholder'), $target_property, $this, $instance, $layout, $data); + } + + //Clear value if value not a string + if ( !is_scalar($target_property) ) { + $target_property = ''; + } + //Replace layout placeholder with retrieved item data + $out = str_replace($ph->start . $instance['match'] . $ph->end, $target_property, $out); + } + } + } + } else { + $out = $out_default; + } + /* Return generated value */ + return implode('', array($this->build_pre(), $out, $this->build_post())); + } +} + +class SLB_Field extends SLB_Field_Type {} + +/** + * Managed collection of fields + * @package Simple Lightbox + * @subpackage Fields + * @author SM + */ +class SLB_Field_Collection extends SLB_Field_Base { + + /** + * Indexed array of items in collection + * @var array + */ + var $items = array(); + + /** + * Associative array of groups in content type + * Key: Group name + * Value: object of group properties + * > title + * > description string Group description + * > items array Items in group + * @var array + */ + var $groups = array(); + + /** + * Item type + * @var string + */ + var $item_type = 'SLB_Field'; + + /* Constructors */ + + /** + * Legacy constructor + * @uses __construct() to init instance + * @param string $id Content type ID + */ + function SLB_Field_Collection($id, $title = '', $properties = null) { + $args = func_get_args(); + call_user_func_array(array(&$this, '__construct'), $args); + } + + /** + * Class constructor + * @param string $id Content type ID + * @param array $properties (optional) Properties to set for content type (Default: none) + */ + function __construct($id, $properties = null) { + //Parent constructor + parent::__construct($id, $properties); + + //Init + $this->init(); + + //Setup object based on properties + if ( is_array($properties) && !empty($properties) ) { + //Groups + if ( isset($properties['groups']) ) + $this->add_groups($properties['groups']); + //Items + if ( isset($properties['items']) ) + $this->add_items($properties['items']); + } + } + + /*-** Getters/Setters **-*/ + + /* Data */ + + /** + * Retrieve external data for items in collection + * Retrieved data is saved to the collection's $data property + * Uses class properties to determine how data is retrieved + * Examples: + * > DB + * > XML + * > JSON + * @return void + */ + function load_data() {} + + /** + * Set data for an item + * @param string|object $item Reference or ID of Field to set data for + * @param mixed $value Data to set + */ + function set_data($item, $value = '', $save = true) { + //Set data for entire collection + if ( 1 == func_num_args() && is_array($item) ) + $this->data = wp_parse_args($item, $this->data); + //Get $item's ID + elseif ( is_object($item) && method_exists($item, 'get_id') ) + $item = $item->get_id(); + //Set data + if ( is_string($item) && !empty($item) && isset($this->items[$item]) ) + $this->data[$item] = $value; + if ( $save ) + $this->save(); + } + + /* Item */ + + /** + * Adds item to collection + * @param string $id Unique name for item + * @param object|string $parent Field type that this item is based on + * @param array $properties (optional) Item properties + * @param string $group (optional) Group ID to add item to + * @return object Reference to new item + */ + function &add($id, $parent = null, $properties = array(), $group = null) { + $args = func_get_args(); + $properties = $this->make_properties($this->util->func_get_options($args), $properties, array('group' => $group)); + $it = ( is_object($id) ) ? 'O:' . $id->get_id() . '(' . get_class($id) . ')' : $id; + //Check if previously created item is being added + if ( is_object($id) && strtolower(get_class($id)) == strtolower($this->item_type) ) { + $item =& $id; + } else { + //Create item + if ( !class_exists($this->item_type) ) + return false; + $type = $this->item_type; + /** + * @var SLB_Field + */ + $item =& new $type($id, $properties); + } + if ( strlen($item->get_id()) == 0 ) { + return false; + } + + $item->set_container($this); + + //Add item to collection + $this->items[$item->get_id()] =& $item; + + //Add item to group + if ( empty($group) ) { + //Check properties array for group + if ( isset($properties['group']) ) { + $group = $properties['group']; + //Remove group property from array + unset($properties['group']); + } + } + $this->add_to_group($group, $item->id); + return $item; + } + + /** + * Removes item from collection + * @param string|object $item Object or item ID to remove + */ + function remove($item) { + if ( $this->has($item) ) { + $item = $this->get($item); + $item = $item->get_id(); + //Remove from items array + unset($this->items[$item]); + //Remove item from groups + $this->remove_from_group($item); + } + } + + /** + * Checks if item exists in the collection + * @param string $item Item ID + * @return bool TRUE if item exists, FALSE otherwise + */ + function has($item) { + return ( !is_string($item) || empty($item) || is_null($this->get_member_value('items', $item, null)) ) ? false : true; + } + + /** + * Retrieve specified item in collection + * @param string|object $item Item object or ID to retrieve + * @return object Specified item + */ + function &get($item) { + if ( $this->has($item) ) { + if ( !is_object($item) || !is_a($item, $this->item_type) ) { + if ( is_string($item) ) { + $item = trim($item); + $item =& $this->items[$item]; + } + else { + $item = false; + } + } + } + + if ( empty($item) ) { + //Return empty item if no item exists + $item =& new $this->item_type; + } + return $item; + } + + /** + * Retrieve item data + * @param $item + * @param $context + * @param $top + */ + function get_data($item = null, $context = '', $top = true) { + $this->load_data(); + $ret = null; + if ( $this->has($item) ) { + $item =& $this->get($item); + $ret = $item->get_data($context, $top); + } elseif ( is_null($item) ) { + $ret = parent::get_data($context, $top); + } + return $ret; + } + + /* Items (Collection) */ + + /** + * Add multiple items to collection + * @param array $items Items to add to collection + * Array Structure: + * > Key (string): Item ID + * > Val (array): Item properties + * @return void + */ + function add_items($items = array()) { + //Validate + if ( !is_array($items) || empty($items) ) + return false; + //Iterate + foreach ( $items as $id => $props ) { + $this->add($id, $props); + } + } + + /** + * Retrieve reference to items in collection + * @return array Collection items (reference) + */ + function &get_items($group = null) { + if ( $this->group_exists($group) ) { + return $this->get_group_items($group); + } + return $this->items; + } + + /** + * Default bulk item building method + * Children classes should implement their own functionality + * If no group specified, all items in collection are built + * @param string|object $group (optional) Group to build items for (ID or instance object) + * @return void + */ + function build_items($group = null) { + $items =& $this->get_items($group); + $out = array(); + foreach ( $items as $item ) { + $out[] = $item->build(); + } + return implode('', $out); + } + + /* Group */ + + /** + * Add groups to collection + * @param array $groups Associative array of group properties + * Array structure: + * > Key (string): group ID + * > Val (string): Group Title + */ + function add_groups($groups = array()) { + //Validate + if ( !is_array($groups) || empty($groups) ) + return false; + //Iterate + foreach ( $groups as $id => $props ) { + $this->add_group($id, $props); + } + } + + /** + * Adds group to content type + * Groups are used to display related items in the UI + * @param string $id Unique name for group + * @param string $title Group title + * @param string $description Short description of group's purpose + * @param array $items (optional) ID's of existing items to add to group + * @return object Group object + */ + function &add_group($id, $title = '', $description = '', $items = array()) { + //Create new group and set properties + $id = trim($id); + $this->groups[$id] =& $this->create_group($title, $description); + //Add items to group (if supplied) + if ( !empty($items) && is_array($items) ) + $this->add_to_group($id, $items); + return $this->groups[$id]; + } + + /** + * Remove specified group from content type + * @param string $id Group ID to remove + */ + function remove_group($id) { + $id = trim($id); + if ( $this->group_exists($id) ) { + unset($this->groups[$id]); + } + } + + /** + * Standardized method to create a new item group + * @param string $title Group title (used in meta boxes, etc.) + * @param string $description Short description of group's purpose + * @return object Group object + */ + function &create_group($title = '', $description = '') { + //Create new group object + $group = new stdClass(); + /* Set group properties */ + + //Set Title + $title = ( is_scalar($title) ) ? trim($title) : ''; + $group->title = $title; + //Set Description + $description = ( is_scalar($description) ) ? trim($description) : ''; + $group->description = $description; + //Create array to hold items + $group->items = array(); + return $group; + } + + /** + * Checks if group exists in collection + * @param string $id Group name + * @return bool TRUE if group exists, FALSE otherwise + */ + function group_exists($group) { + $ret = false; + if ( is_object($group) ) + $ret = true; + elseif ( is_string($group) && ($group = trim($group)) && strlen($group) > 0 ) { + $group = trim($group); + //Check if group exists + $ret = !is_null($this->get_member_value('groups', $group, null)); + } + return $ret; + } + + /** + * Adds item to a group in the collection + * Group is created if it does not already exist + * @param string|array $group ID of group (or group parameters if new group) to add item to + * @param string|array $items Name or array of item(s) to add to group + */ + function add_to_group($group, $items) { + //Validate parameters + $group_id = ''; + if ( !empty($group) ) { + if ( !is_array($group) ) { + $group = array($group, $group); + } + + $group[0] = $group_id = trim(sanitize_title_with_dashes($group[0])); + } + if ( empty($group_id) || empty($items) ) + return false; + //Create group if it doesn't exist + if ( !$this->group_exists($group_id) ) { + call_user_func_array($this->m('add_group'), $group); + } + if ( ! is_array($items) ) + $items = array($items); + foreach ( $items as $item ) { + if ( ! $this->has($item) ) + continue; + $iref =& $this->get($item); + //Remove item from any other group it's in (items can only be in one group) + foreach ( array_keys($this->groups) as $group_name ) { + if ( isset($this->groups[$group_name]->items[$iref->id]) ) + unset($this->groups[$group_name]->items[$iref->id]); + } + //Add reference to item in group + $this->groups[$group_id]->items[$iref->id] =& $iref; + unset($iref); + } + } + + /** + * Remove item from a group + * If no group is specified, then item is removed from all groups + * @param string|object $item Object or ID of item to remove from group + * @param string $group (optional) Group ID to remove item from + */ + function remove_from_group($item, $group = '') { + //Get ID of item to remove or stop execution if item invalid + $item = $this->get($item); + $item = $item->get_id(); + if ( !$item ) + return false; + + //Remove item from group + if ( !empty($group) ) { + //Remove item from single group + if ( ($group =& $this->get_group($group)) && isset($group->items[$item]) ) { + unset($group->items[$item]); + } + } else { + //Remove item from all groups + foreach ( array_keys($this->groups) as $group ) { + if ( ($group =& $this->get_group($group)) && isset($group->items[$item]) ) { + unset($group->items[$item]); + } + } + } + } + + /** + * Retrieve specified group + * @param string $group ID of group to retrieve + * @return object Reference to specified group + */ + function &get_group($group) { + if ( is_object($group) ) + return $group; + if ( is_string($group) ) + $group = trim($group); + //Create group if it doesn't already exist + if ( ! $this->group_exists($group) ) + $this->add_group($group); + return $this->get_member_value('groups', $group); + } + + /** + * Retrieve a group's items + * @uses SLB_Field_Collection::get_group() to retrieve group object + * @param object|string $group Group object or group ID + * @return array Group's items + */ + function &get_group_items($group) { + $group =& $this->get_group($group); + return $group->items; + } + + /** + * Retrieve all groups in content type + * @return array Reference to group objects + */ + function &get_groups() { + return $this->get_member_value('groups'); + } + + /** + * Output items in a group + * @param string $group ID of Group to output + * @return string Group output + * @todo Refactor to be general builder + */ + function build_group($group) { + $out = array(); + $classnames = (object) array( + 'multi' => 'multi_field', + 'single' => 'single_field', + 'elements' => 'has_elements' + ); + + //Stop execution if group does not exist + if ( $this->group_exists($group) && $group =& $this->get_group($group) ) { + $group_items = ( count($group->items) > 1 ) ? $classnames->multi : $classnames->single . ( ( ( $fs = array_keys($group->items) ) && ( $f =& $group->items[$fs[0]] ) && ( $els = $f->get_member_value('elements', '', null) ) && !empty($els) ) ? '_' . $classnames->elements : '' ); + $classname = array($this->add_prefix('attributes_wrap'), $group_items); + $out[] = '
'; //Wrap all items in group + + //Build layout for each item in group + foreach ( array_keys($group->items) as $item_id ) { + $item =& $group->items[$item_id]; + $item->set_caller($this); + //Start item output + $id = $this->add_prefix('field_' . $item->get_id()); + $out[] = '
'; + //Build item layout + $out[] = $item->build_layout(); + //end item output + $out[] = '
'; + $item->clear_caller(); + } + $out[] = '
'; //Close items container + //Add description if exists + if ( !empty($group->description) ) + $out[] = '

' . $group->description . '

'; + } + + //Return group output + return implode($out); + } + + /* Collection */ + + /** + * Build entire collection of items + */ + function build() { + //Get Groups + $groups = array_keys($this->get_groups()); + //Build groups + foreach ( $groups as $group ) { + $this->build_group($group); + } + } +} + +/** + * Collection of default system-wide fields + * @package Simple Lightbox + * @subpackage Fields + * @author SM + * + */ +class SLB_Fields extends SLB_Field_Collection { + + var $item_type = 'SLB_Field_Type'; + + /** + * Placeholder handlers + * @var array + */ + var $placholders = null; + + /* Constructor */ + + function SLB_Fields() { + $this->__construct(); + } + + function __construct() { + parent::__construct('fields'); + } + + function register_hooks() { + parent::register_hooks(); + + //Init fields + add_action('init', $this->m('register_types')); + //Init placeholders + add_action('init', $this->m('register_placeholders')); + } + + /* Field Types */ + + /** + * Initialize fields and content types + */ + function register_types() { + /* Field Types */ + + //Base + $base =& new SLB_Field_Type('base'); + $base->set_description('Default Element'); + $base->set_property('tag', 'span'); + $base->set_property('class', '', 'attr'); + $base->set_layout('form_attr', '{tag} name="{field_name}" id="{field_id}" {properties ref_base="root" group="attr"}'); + $base->set_layout('form', '<{form_attr ref_base="layout"} />'); + $base->set_layout('label', ''); + $base->set_layout('display', '{data context="display"}'); + $this->add($base); + + //Base closed + $base_closed =& new SLB_Field_Type('base_closed'); + $base_closed->set_parent('base'); + $base_closed->set_description('Default Element (Closed Tag)'); + $base_closed->set_layout('form_start', '<{tag} id="{field_id}" name="{field_name}" {properties ref_base="root" group="attr"}>'); + $base_closed->set_layout('form_end', ''); + $base_closed->set_layout('form', '{form_start ref_base="layout"}{data}{form_end ref_base="layout"}'); + $this->add($base_closed); + + //Input + $input =& new SLB_Field_Type('input', 'base'); + $input->set_description('Default Input Element'); + $input->set_property('tag', 'input'); + $input->set_property('type', 'text', 'attr'); + $input->set_property('value', '{data}', 'attr'); + $this->add($input); + + //Text input + $text =& new SLB_Field_Type('text', 'input'); + $text->set_description('Text Box'); + $text->set_property('size', 15, 'attr'); + $text->set_property('label'); + $text->set_layout('form', '{label ref_base="layout"} {inherit}'); + $this->add($text); + + //Checkbox + $cb =& new SLB_Field_Type('checkbox', 'input'); + $cb->set_property('type', 'checkbox'); + $cb->set_property('value', null); + $cb->set_layout('form_attr', '{inherit} {checked}'); + $cb->set_layout('form', '{label ref_base="layout"} <{form_attr ref_base="layout"} />'); + $this->add($cb); + + //Textarea + $ta =& new SLB_Field_Type('textarea', 'base_closed'); + $ta->set_property('tag', 'textarea'); + $ta->set_property('cols', 40, 'attr'); + $ta->set_property('rows', 3, 'attr'); + $this->add($ta); + + //Rich Text + $rt =& new SLB_Field_Type('richtext', 'textarea'); + $rt->set_property('class', 'theEditor {inherit}'); + $rt->set_layout('form', '
{inherit}
'); + $rt->add_action('admin_print_footer_scripts', 'wp_tiny_mce', 25); + $this->add($rt); + + //Hidden + $hidden =& new SLB_Field_Type('hidden'); + $hidden->set_parent('input'); + $hidden->set_description('Hidden Field'); + $hidden->set_property('type', 'hidden'); + $this->add($hidden); + + //Select + $select =& new SLB_Field_Type('select', 'base_closed'); + $select->set_description('Select tag'); + $select->set_property('tag', 'select'); + $select->set_property('tag_option', 'option'); + $select->set_property('options', array()); + $select->set_layout('form', '{label ref_base="layout"} {form_start ref_base="layout"}{option_loop ref_base="layout"}{form_end ref_base="layout"}'); + $select->set_layout('option_loop', '{loop data="properties.options" layout="option" layout_data="option_data"}'); + $select->set_layout('option', '<{tag_option} value="{data_ext id="option_value"}">{data_ext id="option_text"}'); + $select->set_layout('option_data', '<{tag_option} value="{data_ext id="option_value"}" selected="selected">{data_ext id="option_text"}'); + $this->add($select); + + //Span + $span =& new SLB_Field_Type('span', 'base_closed'); + $span->set_description('Inline wrapper'); + $span->set_property('tag', 'span'); + $span->set_property('value', 'Hello there!'); + $this->add($span); + + //Enable plugins to modify (add, remove, etc.) field types + do_action_ref_array($this->add_prefix('register_fields'), array(&$this)); + + //Signal completion of field registration + do_action_ref_array($this->add_prefix('fields_registered'), array(&$this)); + } + + /* Placeholder handlers */ + + function register_placeholders() { + //Default placeholder handlers + $this->register_placeholder('all', $this->m('process_placeholder_default'), 11); + $this->register_placeholder('field_id', $this->m('process_placeholder_id')); + $this->register_placeholder('field_name', $this->m('process_placeholder_name')); + $this->register_placeholder('data', $this->m('process_placeholder_data')); + $this->register_placeholder('data_ext',$this->m('process_placeholder_data_ext')); + $this->register_placeholder('loop', $this->m('process_placeholder_loop')); + $this->register_placeholder('label', $this->m('process_placeholder_label')); + $this->register_placeholder('checked', $this->m('process_placeholder_checked')); + + //Allow other code to register placeholders + do_action_ref_array($this->add_prefix('register_field_placeholders'), array(&$this)); + + //Signal completion of field placeholder registration + do_action_ref_array($this->add_prefix('field_placeholders_registered'), array(&$this)); + } + + /** + * Register a function to handle a placeholder + * Multiple handlers may be registered for a single placeholder + * Adds filter hook to WP for handling specified placeholder + * Placeholders are in layouts and are replaced with data at runtime + * @uses add_filter() + * @param string $placeholder Name of placeholder to add handler for (Using 'all' will set the function as a handler for all placeholders + * @param callback $callback Function to set as a handler + * @param int $priority (optional) Priority of handler + * @return void + */ + function register_placeholder($placeholder, $callback, $priority = 10) { + if ( 'all' == $placeholder ) + $placeholder = ''; + else + $placeholder = '_' . $placeholder; + $hook = $this->add_prefix('process_placeholder' . $placeholder); + add_filter($hook, $callback, $priority, 5); + } + + /** + * Default placeholder processing + * To be executed when current placeholder has not been handled by another handler + * @param string $output Value to be used in place of placeholder + * @param SLB_Field $item Field containing placeholder + * @param array $placeholder Current placeholder + * @see SLB_Field::parse_layout for structure of $placeholder array + * @param string $layout Layout to build + * @param array $data Extended data for item + * @return string Value to use in place of current placeholder + */ + function process_placeholder_default($output, $item, $placeholder, $layout, $data) { + //Validate parameters before processing + if ( empty($output) && is_a($item, 'SLB_Field_Type') && is_array($placeholder) ) { + //Build path to replacement data + $output = $item->get_member_value($placeholder); + + //Check if value is group (properties, etc.) + //All groups must have additional attributes (beyond reserved attributes) that define how items in group are used + if (is_array($output) + && !empty($placeholder['attributes']) + && is_array($placeholder['attributes']) + && ($ph = $item->get_placeholder_defaults()) + && $attribs = array_diff(array_keys($placeholder['attributes']), array_values($ph->reserved)) + ) { + /* Targeted property is an array, but the placeholder contains additional options on how property is to be used */ + + //Find items matching criteria in $output + //Check for group criteria + if ( 'properties' == $placeholder['tag'] && ($prop_group = $item->get_group($placeholder['attributes']['group'])) && !empty($prop_group) ) { + /* Process group */ + $group_out = array(); + //Iterate through properties in group and build string + foreach ( array_keys($prop_group) as $prop_key ) { + $prop_val = $item->get_property($prop_key); + if ( !is_null($prop_val) ) + $group_out[] = $prop_key . '="' . $prop_val . '"'; + } + $output = implode(' ', $group_out); + } + } elseif ( is_object($output) && is_a($output, $item->base_class) ) { + /* Targeted property is actually a nested item */ + //Set caller to current item + $output->set_caller($item); + //Build layout for nested element + $output = $output->build_layout($layout); + } + } + + return $output; + } + + /** + * Build Field ID attribute + * @see SLB_Field_Type::process_placeholder_default for parameter descriptions + * @return string Placeholder output + */ + function process_placeholder_id($output, $item, $placeholder, $layout, $data) { + //Get attributes + $args = wp_parse_args($placeholder['attributes'], array('format' => 'attr_id')); + return $item->get_id($args); + } + + /** + * Build Field name attribute + * Name is formatted as an associative array for processing by PHP after submission + * @see SLB_Field_Type::process_placeholder_default for parameter descriptions + * @return string Placeholder output + */ + function process_placeholder_name($output, $item, $placeholder, $layout, $data) { + //Get attributes + $args = wp_parse_args($placeholder['attributes'], array('format' => 'attr_name')); + return $item->get_id($args); + } + + /** + * Build item label + * @see SLB_Fields::process_placeholder_default for parameter descriptions + * @return string Field label + */ + function process_placeholder_label($output, $item, $placeholder, $layout, $data) { + //Check if item has label property (e.g. sub-elements) + $out = $item->get_property('label'); + //If property not set, use item title + if ( empty($out) ) + $out = $item->get_title(); + return $out; + } + + /** + * Retrieve data for item + * @see SLB_Field_Type::process_placeholder_default for parameter descriptions + * @return string Placeholder output + */ + function process_placeholder_data($output, $item, $placeholder, $layout) { + $attr_default = array ( + 'context' => '', + ); + $opts = wp_parse_args($placeholder['attributes'], $attr_default); + //Save context to separate variable + $context = $opts['context']; + unset($opts['context']); + //Get data + $out = $item->get_data($opts); + if ( !is_null($out) ) { + //Get specific member in value (e.g. value from a specific item element) + if ( isset($opts['element']) && is_array($out) && ( $el = $opts['element'] ) && isset($out[$el]) ) + $out = $out[$el]; + } + + //Format data based on context + $out = $item->format($out, $context); + //Return data + return $out; + } + + /** + * Set checked attribute on item + * Evaluates item's data to see if item should be checked or not + * @see SLB_Fields::process_placeholder_default for parameter descriptions + * @return string Appropriate checkbox attribute + */ + function process_placeholder_checked($output, $item, $placeholder, $layout, $data) { + $out = ''; + $c = $item->get_container(); + $d = ( isset($c->data[$item->get_id()]) ) ? $c->data[$item->get_id()] : null; + $item->set_property('d', true); + if ( $item->get_data() ) + $out = 'checked="checked"'; + $item->set_property('d', false); + return $out; + } + + /** + * Loops over data to build item output + * Options: + * data - Dot-delimited path in item that contains data to loop through + * layout - Name of layout to use for each data item in loop + * layout_data - Name of layout to use for data item that matches previously-saved item data + * @see SLB_Field_Type::process_placeholder_default for parameter descriptions + * @return string Placeholder output + */ + function process_placeholder_loop($output, $item, $placeholder, $layout, $data) { + //Setup loop options + $attr_defaults = array ( + 'layout' => '', + 'layout_data' => null, + 'data' => '' + ); + $attr = wp_parse_args($placeholder['attributes'], $attr_defaults); + if ( is_null($attr['layout_data']) ) + $attr['layout_data'] =& $attr['layout']; + //Get data for loop + $path = explode('.', $attr['data']); + $loop_data = $item->get_member_value($path); + + //Check if data is callback + if ( is_callable($loop_data) ) + $loop_data = call_user_func($loop_data); + + //Get item data + $data = $item->get_data(); + + //Iterate over data and build output + $out = array(); + if ( is_array($loop_data) && !empty($loop_data) ) { + foreach ( $loop_data as $value => $label ) { + //Load appropriate layout based on item value + $layout = ( ($data === 0 && $value === $data) xor $data == $value ) ? $attr['layout_data'] : $attr['layout']; + //Stop processing if no valid layout is returned + if ( empty($layout) ) + continue; + //Prep extended item data + $data_ext = array('option_value' => $value, 'option_text' => $label); + $out[] = $item->build_layout($layout, $data_ext); + } + } + + //Return output + return implode($out); + } + + /** + * Returns specified value from extended data array for item + * @see SLB_Field_Type::process_placeholder_default for parameter descriptions + * @return string Placeholder output + */ + function process_placeholder_data_ext($output, $item, $placeholder, $layout, $data) { + if ( isset($placeholder['attributes']['id']) && ($key = $placeholder['attributes']['id']) && isset($data[$key]) ) { + $output = strval($data[$key]); + } + + return $output; + } +} \ No newline at end of file diff --git a/src/wp-content/plugins/simple-lightbox/includes/class.options.php b/src/wp-content/plugins/simple-lightbox/includes/class.options.php new file mode 100644 index 00000000..0a6d39cf --- /dev/null +++ b/src/wp-content/plugins/simple-lightbox/includes/class.options.php @@ -0,0 +1,394 @@ + 'data', + 'attr' => 'properties' + ); + + /* Init */ + + function SLB_Option($id, $title = '', $default = '') { + $args = func_get_args(); + call_user_func_array(array(&$this, '__construct'), $args); + } + + /** + * @see SLB_Field::__construct() + * @uses parent::__construct() to initialize instance + * @param $id + * @param $title + * @param $default + */ + function __construct($id, $title = '', $default = '') { + //Normalize properties + $args = func_get_args(); + $props = SLB_Utilities::func_get_options($args); + $props = wp_parse_args($props, array ('id' => $id, 'title' => $title, 'default' => $default)); + //Send to parent constructor + parent::__construct($props); + } + + /* Getters/Setters */ + + /** + * Retrieve default value for option + * @return mixed Default option value + */ + function get_default($context = '') { + return $this->get_data($context, false); + } + + /** + * Sets parent based on default value + */ + function set_parent($parent = null) { + $p =& $this->get_parent(); + if ( empty($parent) && empty($p) ) { + $parent = 'text'; + $d = $this->get_default(); + if ( is_bool($d) ) + $parent = 'checkbox'; + $parent = 'option_' . $parent; + } elseif ( !empty($p) && !is_object($p) ) { + $parent =& $p; + } + parent::set_parent($parent); + } + + /* Formatting */ + + /** + * Format data as string for browser output + * @see SLB_Field_Base::format() + * @param mixed $value Data to format + * @param string $context (optional) Current context + * @return string Formatted value + */ + function format_display($value, $context = '') { + if ( !is_string($value) ) { + if ( is_bool($value) ) + $value = ( $value ) ? 'Enabled' : 'Disabled'; + elseif ( is_null($value) ) + $value = ''; + else + $value = strval($value); + } + return htmlentities($value); + } +} + +/** + * Options collection + * @package Simple Lightbox + * @subpackage Options + * @author SM + * @uses SLB_Field_Collection + */ +class SLB_Options extends SLB_Field_Collection { + + /* Properties */ + + var $item_type = 'SLB_Option'; + + /* Init */ + + function SLB_Options($id, $props = array()) { + $args = func_get_args(); + call_user_func_array(array(&$this, '__construct'), $args); + } + + function __construct($id, $props = array()) { + parent::__construct($id, $props); + } + + function register_hooks() { + parent::register_hooks(); + //Register fields + add_action($this->add_prefix('register_fields'), $this->m('register_fields')); + //Set option parents + add_action($this->add_prefix('fields_registered'), $this->m('set_parents')); + } + + /** + * Migrate options from old versions to current version + */ + function migrate() { + //Legacy options + $oid = 'enabled_single'; + $d = null; + $this->load_data(); + if ( ($o = get_option($oid, $d)) && $o !== $d ) { + $this->set_data('enabled_post', $o, false); + $this->set_data('enabled_page', $o, false); + } + //Migrate separate options to unified option + $items =& $this->get_items(); + foreach ( $items as $id => $opt ) { + $oid = $this->add_prefix($id); + $o = get_option($oid, $d); + if ( $o !== $d ) { + //Migrate value to data array + $this->set_data($id, $o, false); + //Delete legacy option + delete_option($oid); + } + } + //Remove any remaining legacy items + if ( is_array($this->properties_init) && isset($this->properties_init['legacy']) && is_array($this->properties_init['legacy']) ) { + foreach( $this->properties_init['legacy'] as $opt ) + delete_option($this->add_prefix($opt)); + } + //Save changes + $this->save(); + } + + /* Option setup */ + + /** + * Register option-specific fields + * @param SLB_Fields $fields Reference to global fields object + * @return void + */ + function register_fields(&$fields) { + //Layouts + $layout_label = ''; + $label_ref = '{label ref_base="layout"}'; + $field_pre = '
'; + $field_post = '
'; + $opt_pre = '
'; + $opt_post = '
'; + $layout_form = '<{form_attr ref_base="layout"} /> (Default: {data context="display" top="0"})'; + + //Text input + $otxt =& new SLB_Field_Type('option_text', 'text'); + $otxt->set_property('class', '{inherit} code'); + $otxt->set_property('size', null); + $otxt->set_property('value', '{data context="form"}'); + $otxt->set_layout('label', $layout_label); + $otxt->set_layout('form', $opt_pre . $label_ref . $field_pre . $layout_form . $field_post . $opt_post); + $fields->add($otxt); + + //Checkbox + $ocb =& new SLB_Field_Type('option_checkbox', 'checkbox'); + $ocb->set_layout('label', $layout_label); + $ocb->set_layout('form', $opt_pre . $label_ref . $field_pre . $layout_form . $field_post . $opt_post); + $fields->add($ocb); + + //Theme + $othm =& new SLB_Field_Type('option_theme', 'select'); + $othm->set_layout('label', $layout_label); + $othm->set_layout('form_start', $field_pre . '{inherit}'); + $othm->set_layout('form_end', '{inherit}' . $field_post); + $othm->set_layout('form', $opt_pre . '{inherit}' . $opt_post); + $fields->add($othm); + } + + /** + * Set parent field types for options + * Parent only set for Admin pages + * @uses SLB_Option::set_parent() to set parent field for each option item + * @uses is_admin() to determine if current request is admin page + * @param object $fields Collection of default field types + * @return void + */ + function set_parents(&$fields) { + if ( !is_admin() ) + return false; + $items =& $this->get_items(); + foreach ( array_keys($items) as $opt ) { + $items[$opt]->set_parent(); + } + foreach ( $this->items as $opt ) { + $p = $opt->parent; + if ( is_object($p) ) + $p = 'o:' . $p->id; + } + } + + /* Processing */ + + function validate($values) { + if ( is_array($values) ) { + //Get option group being validated + /* + $group = ''; + $filter = 'sanitize_option_'; + $option = str_replace($filter, '', current_filter()); + if ( $this->get_id() == $this->remove_prefix($option) ) { + $group = ''; + } else { + $group = substr($option, strlen($this->add_prefix($this->get_id())) + 1); + } + */ + //Format data based on option type (bool, string, etc.) + foreach ( $values as $id => $val ) { + //Get default + $d = $this->get_default($id); + if ( is_bool($d) && !empty($val) ) + $values[$id] = true; + } + //Merge in additional options that are not in post data + //Missing options (e.g. disabled checkboxes) & defaults + $items =& $this->get_items(); + foreach ( $items as $id => $opt ) { + //Add options that were not included in form submission + if ( !array_key_exists($id, $values) ) { + if ( is_bool($opt->get_default()) ) + $values[$id] = false; + else + $values[$id] = $opt->get_default(); + } + } + } + + //Return value + return $values; + } + + /* Data */ + + /** + * Retrieve options from database + * @return array Options data + */ + function fetch_data($sanitize = true) { + $data = get_option($this->get_key(), null); + if ( $sanitize && is_array($data) ) { + //Sanitize loaded data based on default values + foreach ( $data as $id => $val ) { + if ( $this->has($id) ) { + $opt = $this->get($id); + if ( is_bool($opt->get_default()) ) + $data[$id] = !!$val; + } else { + unset($data[$id]); + } + } + } + return $data; + } + + /** + * Retrieves option data for collection + * @see SLB_Field_Collection::load_data() + */ + function load_data() { + static $fetched = false; + if ( !$fetched ) { + $fetched = true; + //Retrieve data + $this->data = $this->fetch_data(); + } + } + + /** + * Resets option values to their default values + * @param bool $hard Reset all options if TRUE (default), Reset only unset options if FALSE + */ + function reset($hard = true) { + $this->load_data(); + //Reset data + if ( $hard ) { + $this->data = null; + } + //Save + $this->save(); + } + + /** + * Save options data to database + */ + function save() { + $opts =& $this->get_items(); + $data = array(); + foreach ( $opts as $id => $opt ) { + $data[$id] = $opt->get_data(); + } + $this->data = $data; + update_option($this->get_key(), $data); + } + + /* Collection */ + + /** + * Build key for saving/retrieving data to options table + * @return string Key + */ + function get_key() { + return $this->add_prefix($this->get_id()); + } + + /** + * Add option to collection + * @uses SLB_Field_Collection::add() to add item + * @param string $id Unique item ID + * @param string $title Item title + * @param mixed $default Default value + * @param string $group (optional) Group ID to add item to + * @return SLB_Option Option instance reference + */ + function &add($id, $title = '', $default = '', $group = null) { + //Build properties array + $properties = $this->make_properties($title, array('title' => $title, 'group' => $group, 'default' => $default)); + + //Create item + /** + * @var SLB_Option + */ + $item =& parent::add($id, $properties); + + return $item; + } + + /** + * Retrieve option value + * @uses get_data() to retrieve option data + * @param string $option Option ID to retrieve value for + * @param string $context (optional) Context for formatting data + * @return mixed Option value + */ + function get_value($option, $context = '') { + return $this->get_data($option, $context); + } + + /** + * Retrieve option's default value + * @uses get_data() to retrieve option data + * @param string $option Option ID to retrieve value for + * @param string $context (optional) Context for formatting data + * @return mixed Option's default value + */ + function get_default($option, $context = '') { + return $this->get_data($option, $context, false); + } + + /* Output */ + + function build_group($group) { + if ( !$this->group_exists($group) ) + return false; + $group =& $this->get_group($group); + //Stop processing if group contains no items + if ( !count($this->get_items($group)) ) + return false; + + //Group header + echo '

' . $group->title . '

'; + //Build items + echo $this->build_items($group); + } +} \ No newline at end of file diff --git a/src/wp-content/plugins/simple-lightbox/includes/class.utilities.php b/src/wp-content/plugins/simple-lightbox/includes/class.utilities.php new file mode 100644 index 00000000..1f4def56 --- /dev/null +++ b/src/wp-content/plugins/simple-lightbox/includes/class.utilities.php @@ -0,0 +1,1032 @@ + 'Plugin Name', + 'PluginURI' => 'Plugin URI', + 'Version' => 'Version', + 'Description' => 'Description', + 'Author' => 'Author', + 'AuthorURI' => 'Author URI', + 'TextDomain' => 'Text Domain', + 'DomainPath' => 'Domain Path', + 'Network' => 'Network', + ); + + /* Constructors */ + + function SLB_Utilities(&$obj) { + $this->__construct(&$obj); + } + + function __construct(&$obj) { + if ( is_object($obj) ) + $this->parent =& $obj; + } + + /** + * Returns callback array to instance method + * @param object $obj Instance object + * @param string $method Name of method + * @return array Callback array + */ + function &m(&$obj, $method = '') { + if ( $obj == null && isset($this) ) + $obj =& $this; + $arr = array(&$obj, $method); + return $arr; + } + + /* Helper Functions */ + + /*-** Prefix **-*/ + + /** + * Get valid separator + * @param string $sep (optional) Separator supplied + * @return string Separator + */ + function get_sep($sep = false) { + if ( is_null($sep) ) + $sep = ''; + if ( !is_string($sep) ) + $default = '_'; + return ( is_string($sep) ) ? $sep : $default; + } + + /** + * Retrieve class prefix (with separator if set) + * @param bool|string $sep Separator to append to class prefix (Default: no separator) + * @return string Class prefix + */ + function get_prefix($sep = null) { + $sep = $this->get_sep($sep); + $prefix = ( !empty($this->parent->prefix) ) ? $this->parent->prefix . $sep : ''; + return $prefix; + } + + /** + * Check if a string is prefixed + * @param string $text Text to check for prefix + * @param string $sep (optional) Separator used + */ + function has_prefix($text, $sep = null) { + return ( !empty($text) && strpos($text, $this->get_prefix($sep)) === 0 ); + } + + /** + * Prepend plugin prefix to some text + * @param string $text Text to add to prefix + * @param string $sep (optional) Text used to separate prefix and text + * @param bool $once (optional) Whether to add prefix to text that already contains a prefix or not + * @return string Text with prefix prepended + */ + function add_prefix($text, $sep = '_', $once = true) { + if ( $this->has_prefix($text, $sep) ) + return $text; + return $this->get_prefix($sep) . $text; + } + + /** + * Remove prefix from specified string + * @param string $text String to remove prefix from + * @param string $sep (optional) Separator used with prefix + */ + function remove_prefix($text, $sep = '_') { + if ( $this->has_prefix($text,$sep) ) + $text = substr($text, strlen($this->get_prefix($sep))); + return $text; + } + + /** + * Returns Database prefix for Cornerstone-related DB Tables + * @return string Database prefix + */ + function get_db_prefix() { + global $wpdb; + return $wpdb->prefix . $this->get_prefix('_'); + } + + /*-** WP **-*/ + + /** + * Checks if $post is a valid Post object + * If $post is not valid, assigns global post object to $post (if available) + * @return bool TRUE if $post is valid object by end of function processing + * @param object $post Post object to evaluate + */ + function check_post(&$post) { + if (empty($post)) { + if (isset($GLOBALS['post'])) { + $post = $GLOBALS['post']; + $GLOBALS['post'] =& $post; + } + else + return false; + } + if (is_array($post)) + $post = (object) $post; + elseif (is_numeric($post)) + $post = get_post($post); + if (!is_object($post)) + return false; + return true; + } + + /* Hooks */ + + function do_action($tag, $arg = '') { + do_action($this->add_prefix($tag), $arg); + } + + function apply_filters($tag, $value) { + apply_filters($this->add_prefix($tag), $value); + } + + function add_action($tag, $function_to_add, $priority = 10, $accepted_args = 1) { + return add_action($this->add_prefix($tag), $function_to_add, $priority, $accepted_args); + } + + function add_filter($tag, $function_to_add, $priority = 10, $accepted_args = 1) { + return add_filter($this->add_prefix(tag), $function_to_add, $priority, $accepted_args); + } + + /* Meta */ + + /** + * Retrieves post metadata for internal methods + * Metadata set internally is wrapped in an array so it is unwrapped before returned the retrieved value + * @see get_post_meta() + * @param int $post_id Post ID + * @param string $key Name of metadata to retrieve + * @param boolean $single Whether or not to retrieve single value or not + * @return mixed Retrieved post metadata + */ + function post_meta_get($post_id, $key, $single = false) { + $meta_value = get_post_meta($post_id, $this->post_meta_get_key($key), $single); + if (is_array($meta_value) && count($meta_value) == 1) + $meta_value = $meta_value[0]; + return $meta_value; + } + + /** + * Wraps metadata in array for storage in database + * @param mixed $meta_value Value to be set as metadata + * @return array Wrapped metadata value + */ + function post_meta_prepare_value($meta_value) { + return array($meta_value); + } + + /** + * Adds Metadata for a post to database + * For internal methods + * @see add_post_meta + * @param $post_id + * @param $meta_key + * @param $meta_value + * @param $unique + * @return boolean Result of operation + */ + function post_meta_add($post_id, $meta_key, $meta_value, $unique = false) { + $meta_value = $this->post_meta_value_prepare($meta_value); + return add_post_meta($post_id, $meta_key, $meta_value, $unique); + } + + /** + * Updates post metadata for internal data/methods + * @see update_post_meta() + * @param $post_id + * @param $meta_key + * @param $meta_value + * @param $prev_value + * @return boolean Result of operation + */ + function post_meta_update($post_id, $meta_key, $meta_value, $prev_value = '') { + $meta_value = $this->post_meta_prepare_value($meta_value); + return update_post_meta($post_id, $meta_key, $meta_value, $prev_value); + } + + /** + * Builds postmeta key for custom data set by plugin + * @param string $key Base key name + * @return string Formatted postmeta key + */ + function post_meta_get_key($key) { + $sep = '_'; + if ( strpos($key, $sep . $this->prefix) !== 0 ) { + $key_base = func_get_args(); + if ( !empty($key_base) ) { + $key = array_merge((array)$this->prefix, $key_base); + return $sep . implode($sep, $key); + } + } + + return $key; + } + + /** + * Creates a meta key for storing post meta data + * Prefixes standard prefixed text with underscore to hide meta data on post edit forms + * @param string $text Text to use as base of meta key + * @return string Formatted meta key + */ + function make_meta_key($text = '') { + return '_' . $this->add_prefix($text); + } + + /*-** Request **-*/ + + /** + * Checks if the currently executing file matches specified file name + * @param string $filename Filename to check for + * @return bool TRUE if current page matches specified filename, FALSE otherwise + */ + function is_file( $filename ) { + return ( $filename == basename( $_SERVER['SCRIPT_NAME'] ) ); + } + + /** + * Checks whether the current page is a management page + * @return bool TRUE if current page is a management page, FALSE otherwise + */ + function is_admin_management_page() { + return ( is_admin() + && ( $this->is_file('edit.php') + || ( $this->is_file('admin.php') + && isset($_GET['page']) + && strpos($_GET['page'], 'cnr') === 0 ) + ) + ); + } + + /** + * Joins and normalizes the slashes in the paths passed to method + * All forward/back slashes are converted to forward slashes + * Multiple path segments can be passed as additional argments + * @param string $path Path to normalize + * @param bool $trailing_slash (optional) Whether or not normalized path should have a trailing slash or not (Default: FALSE) + * If multiple path segments are passed, $trailing_slash will be the LAST parameter (default value used if omitted) + */ + function normalize_path($path, $trailing_slash = false) { + $sl_f = '/'; + $sl_b = '\\'; + $parts = func_get_args(); + if ( func_num_args() > 1 ) { + if ( is_bool(($tr = $parts[count($parts) - 1])) ) { + $trailing_slash = $tr; + //Remove from args array + array_pop($parts); + } else { + $trailing_slash = false; + } + $first = true; + //Trim trailing slashes from path parts + foreach ( $parts as $key => $part ) { + $part = trim($part); + //Special Trim + $parts[$key] = trim($part, $sl_f . $sl_b); + //Verify path still contains value + if ( empty($parts[$key]) ) { + unset($parts[$key]); + continue; + } + //Only continue processing the first valid path segment + if ( $first ) + $first = !$first; + else + continue; + //Add back leading slash if necessary + if ( $part[0] == $sl_f || $part[0] == $sl_b ) + $parts[$key] = $sl_f . $parts[$key]; + + } + } + //Join path parts together + $parts = implode($sl_b, $parts); + $parts = str_replace($sl_b, $sl_f, $parts); + //Add trailing slash (if necessary) + if ( $trailing_slash ) + $parts .= $sl_f; + return $parts; + } + + /** + * Returns URL of file (assumes that it is in plugin directory) + * @param string $file name of file get URL + * @return string File URL + */ + function get_file_url($file) { + if ( is_string($file) && '' != trim($file) ) { + $file = str_replace(' ', '%20', $this->normalize_path($this->get_url_base(), $file)); + } + return $file; + } + + /** + * Returns path to plugin file + * @param string $file file name + * @return string File path + */ + function get_file_path($file) { + if ( is_string($file) && '' != trim($file) ) { + $file = $this->normalize_path($this->get_path_base(), $file); + } + return $file; + } + + /** + * Retrieves file extension + * @param string $file file name/path + * @return string File's extension + */ + function get_file_extension($file) { + $ret = ''; + $sep = '.'; + if ( ( $rpos = strrpos($file, $sep) ) !== false ) + $ret = substr($file, $rpos + 1); + return $ret; + } + + /** + * Checks if file has specified extension + * @uses get_file_extension() + * @param string $file File name/path + * @param string $extension File ending to check $file for + * @return bool TRUE if file has extension + */ + function has_file_extension($file, $extension) { + return ( $this->get_file_extension($file) == $extension ) ? true : false; + } + + /** + * Retrieve base URL for plugin-specific files + * @uses get_plugin_base() + * @uses normalize_path() + * @return string Base URL + */ + function get_url_base() { + static $url_base = ''; + if ( '' == $url_base ) { + $url_base = $this->normalize_path(plugins_url(), $this->get_plugin_base()); + } + return $url_base; + } + + /** + * Retrieve plugin's base path + * @uses WP_PLUGIN_DIR + * @uses get_plugin_base() + * @uses normalize_path() + * @return string Base path + */ + function get_path_base() { + static $path_base = ''; + if ( '' == $path_base ) { + $path_base = $this->normalize_path(WP_PLUGIN_DIR, $this->get_plugin_base()); + } + return $path_base; + } + + /** + * Retrieve plugin's base directory + * @uses WP_PLUGIN_DIR + * @uses normalize_path() + * @return string Base directory + */ + function get_plugin_base() { + static $plugin_dir = ''; + if ( '' == $plugin_dir ) { + $plugin_dir = str_replace($this->normalize_path(WP_PLUGIN_DIR), '', $this->normalize_path(dirname(dirname(__FILE__)))); + } + return $plugin_dir; + } + + /** + * Retrieve plugin's base file path + * @uses get_path_base() + * @uses get_file_path() + * @return string Base file path + */ + function get_plugin_base_file() { + static $file = ''; + global $cnr; + if ( empty($file) ) { + $dir = @ opendir($this->get_path_base()); + if ( $dir ) { + while ( ($ftemp = readdir($dir)) !== false ) { + //Only process PHP files + $ftemp = $this->get_file_path($ftemp); + if ( !$this->has_file_extension($ftemp, 'php') || !is_readable($ftemp) ) + continue; + //Check for data + $data = get_file_data($ftemp, $this->plugin_headers); + if ( !empty($data['Name']) ) { + //Set base file + $file = $ftemp; + break; + } + } + } + @closedir($dir); + } + //Return + return $file; + } + + /** + * Retrieve plugin's internal name + * Internal name is used by WP core + * @uses get_plugin_base_file() + * @uses plugin_basename() + * @return string Internal plugin name + */ + function get_plugin_base_name() { + $file = $this->get_plugin_base_file(); + return plugin_basename($file); + } + + /** + * Retrieve plugin info + * Parses info comment in main plugin file + * @uses get_plugin_base_file() + */ + function get_plugin_info($field = '') { + static $data = array(); + $ret = ''; + //Get plugin data + if ( empty($data) ) { + $file = $this->get_plugin_base_file(); + $data = get_file_data($file, $this->plugin_headers); + } + //Return specified field + if ( !empty($field) ) { + if ( isset($data[$field]) ) + $ret = $data[$field]; + } else { + $ret = $data; + } + return $ret; + } + + /** + * Retrieve plugin version + * @uses get_plugin_info() + * @param bool $strip_desc Strip any additional version text + * @return string Plugin version + */ + function get_plugin_version($strip_desc = true) { + static $v = ''; + //Retrieve version + if ( empty($v) ) { + $field = 'Version'; + $v = $this->get_plugin_info($field); + } + //Format + $ret = $v; + if ( $strip_desc ) { + $ret = explode(' ', $ret, 2); + $ret = $ret[0]; + } + //Return + return $ret; + } + + /** + * Retrieve current action based on URL query variables + * @param mixed $default (optional) Default action if no action exists + * @return string Current action + */ + function get_action($default = null) { + $action = ''; + + //Check if action is set in URL + if ( isset($_GET['action']) ) + $action = $_GET['action']; + //Otherwise, Determine action based on plugin plugin admin page suffix + elseif ( isset($_GET['page']) && ($pos = strrpos($_GET['page'], '-')) && $pos !== false && ( $pos != count($_GET['page']) - 1 ) ) + $action = trim(substr($_GET['page'], $pos + 1), '-_'); + + //Determine action for core admin pages + if ( ! isset($_GET['page']) || empty($action) ) { + $actions = array( + 'add' => array('page-new', 'post-new'), + 'edit-item' => array('page', 'post'), + 'edit' => array('edit', 'edit-pages') + ); + $page = basename($_SERVER['SCRIPT_NAME'], '.php'); + + foreach ( $actions as $act => $pages ) { + if ( in_array($page, $pages) ) { + $action = $act; + break; + } + } + } + if ( empty($action) ) + $action = $default; + return $action; + } + + /*-** General **-*/ + + /** + * Checks if last parameter sent to a function is an array of options and returns it + * Calling function should use `func_get_args()` and pass the value to this method + * @param array $args Parameters passed to calling function + * @return array Options array (Default: empty array) + */ + function func_get_options($args) { + $r = array(); + if ( is_array($args) && !empty($args) ) { + $last = count($args) - 1; + if ( is_array($args[$last]) ) + $r = $args[$last]; + } + return $r; + } + + /** + * Checks if a property exists in a class or object + * (Compatibility method for PHP 4 + * @param mixed $class Class or object to check + * @param string $property Name of property to look for in $class + */ + function property_exists($class, $property) { + if ( !is_object($class) && !is_array($class) ) + return false; + if ( function_exists('property_exists') && is_object($class) ) { + return property_exists($class, $property); + } else { + return array_key_exists($property, $class); + } + } + + /** + * Retrieve specified property from object or array + * @param object|array $obj Object or array to get property from + * @param string $property Property name to retrieve + * @return mixed Property value + */ + function &get_property(&$obj, $property) { + $property = trim($property); + //Object + if ( is_object($obj) ) + return $obj->{$property}; + //Array + if ( is_array($obj) ) + return $obj[$property]; + //Class + if ( is_string($obj) && class_exists($obj) ) { + $cvars = get_class_vars($obj); + if ( isset($cvars[$property]) ) + return $cvars[$property]; + } + } + + /** + * Remap array members based on a + * mapping of source/destination keys + * @param array $properties Associative array of properties + * @param array $map Source/Destination mapping + * > Key: Source member + * > Val: Destination member + * @param bool $overwrite If TRUE, source value will be set in destination regardless of whether member already exists or not + * @return array Remapped properties + */ + function array_remap($arr, $map = array(), $overwrite = false) { + if ( !empty($map) && is_array($map) ) { + //Iterate through mappings + foreach ( $map as $from => $to ) { + if ( !array_key_exists($from, $arr) ) + continue; + $move = $overwrite; + //Only remap if parent property doesn't already exist in array + if ( !array_key_exists($to, $arr) ) + $move = true; + if ( $move ) { + //Move member value to new key + $arr[$to] = $arr[$from]; + //Remove source member + unset($arr[$from]); + } + } + } + //Return remapped properties + return $arr; + } + + function array_filter_keys($arr, $keys) { + if ( is_array($arr) && !empty($arr) && is_array($keys) && !empty($keys) ) { + foreach ( $keys as $rem ) { + if ( array_key_exists($rem, $arr) ) + unset($arr[$rem]); + } + } + + return $arr; + } + + /** + * Insert an item into an array at the specified position + * @param mixed $item Item to insert into array + * @param int $pos Index position to insert item into array + * @return array Modified array + */ + function array_insert($array, $item, $pos = null) { + array_splice($array, $pos, 0, $item); + return $array; + } + + /** + * Merges 1 or more arrays together + * Methodology + * - Set first parameter as base array + * - All other parameters will be merged into base array + * - Iterate through other parameters (arrays) + * - Skip all non-array parameters + * - Iterate though key/value pairs of current array + * - Merge item in base array with current item based on key name + * - If the current item's value AND the corresponding item in the base array are BOTH arrays, recursively merge the the arrays + * - If the current item's value OR the corresponding item in the base array is NOT an array, current item overwrites base item + * @param array Variable number of arrays + * @param array $arr1 Default array + * @return array Merged array + */ + function array_merge_recursive_distinct($arr1) { + //Get all arrays passed to function + $args = func_get_args(); + if ( empty($args) ) + return false; + //Return empty array if first parameter is not an array + if ( !is_array($args[0]) ) + return array(); + //Set first array as base array + $merged = $args[0]; + //Iterate through arrays to merge + $arg_length = count($args); + for ( $x = 1; $x < $arg_length; $x++ ) { + //Skip if argument is not an array (only merge arrays) + if ( !is_array($args[$x]) ) + continue; + //Iterate through argument items + foreach ( $args[$x] as $key => $val ) { + //Generate key for numeric indexes + if ( is_int($key) ) { + //Add new item to merged array + $merged[] = null; + //Get key of new item + $key = array_pop(array_keys($merged)); + } + if ( !isset($merged[$key]) || !is_array($merged[$key]) || !is_array($val) ) { + $merged[$key] = $val; + } elseif ( is_array($merged[$key]) && is_array($val) ) { + $merged[$key] = $this->array_merge_recursive_distinct($merged[$key], $val); + } + } + } + return $merged; + } + + /** + * Replaces string value in one array with the value of the matching element in a another array + * + * @param string $search Text to search for in array + * @param array $arr_replace Array to use for replacing values + * @param array $arr_subject Array to search for specified value + * @return array Searched array with replacements made + */ + function array_replace_recursive($search, $arr_replace, $arr_subject) { + foreach ($arr_subject as $key => $val) { + //Skip element if key does not exist in the replacement array + if (!isset($arr_replace[$key])) + continue; + //If element values for both arrays are strings, replace text + if (is_string($val) && strpos($val, $search) !== false && is_string($arr_replace[$key])) + $arr_subject[$key] = str_replace($search, $arr_replace[$key], $val); + //If value in both arrays are arrays, recursively replace text + if (is_array($val) && is_array($arr_replace[$key])) + $arr_subject[$key] = $this->array_replace_recursive($search, $arr_replace[$key], $val); + } + + return $arr_subject; + } + + /** + * Checks if item at specified path in array is set + * @param array $arr Array to check for item + * @param array $path Array of segments that form path to array (each array item is a deeper dimension in the array) + * @return boolean TRUE if item is set in array, FALSE otherwise + */ + function array_item_isset(&$arr, &$path) { + $f_path = $this->get_array_path($path); + return eval('return isset($arr' . $f_path . ');'); + } + + /** + * Returns value of item at specified path in array + * @param array $arr Array to get item from + * @param array $path Array of segments that form path to array (each array item is a deeper dimension in the array) + * @return mixed Value of item in array (Default: empty string) + */ + function &get_array_item(&$arr, &$path) { + $item = ''; + if ($this->array_item_isset($arr, $path)) { + eval('$item =& $arr' . $this->get_array_path($path) . ';'); + } + return $item; + } + + /** + * Build formatted string based on array values + * Array values in formatted string will be ordered by index order + * @param array $attribute Values to build string with + * @param string $format (optional) Format name (Default: Multidimensional array representation > ['value1']['value2']['value3'], etc.) + * @return string Formatted string based on array values + */ + function get_array_path($attribute = '', $format = null) { + //Formatted value + $fmtd = ''; + if (!empty($attribute)) { + //Make sure attribute is array + if (!is_array($attribute)) { + $attribute = array($attribute); + } + //Format attribute + $format = strtolower($format); + switch ($format) { + case 'id': + $fmtd = array_shift($attribute) . '[' . implode('][', $attribute) . ']'; + break; + case 'metadata': + case 'attribute': + //Join segments + $delim = '_'; + $fmtd = implode($delim, $attribute); + //Replace white space and repeating delimiters + $fmtd = str_replace(' ', $delim, $fmtd); + while (strpos($fmtd, $delim.$delim) !== false) + $fmtd = str_replace($delim.$delim, $delim, $fmtd); + //Prefix formatted value with delimeter for metadata keys + if ('metadata' == $format) + $fmtd = $delim . $fmtd; + break; + case 'path': + case 'post': + default: + $fmtd = '["' . implode('"]["', $attribute) . '"]'; + } + } + return $fmtd; + } + + /** + * Builds array of path elements based on arguments + * Each item in path array represents a deeper level in structure path is for (object, array, filesystem, etc.) + * @param array|string Value to add to the path + * @return array 1-dimensional array of path elements + */ + function build_path() { + $path = array(); + $args = func_get_args(); + + //Iterate through parameters and build path + foreach ( $args as $arg ) { + if ( empty($arg) ) + continue; + + if (is_array($arg)) { + //Recurse through array items to pull out any more arrays + foreach ($arg as $key => $val) { + $path = array_merge($path, $this->build_path($val)); + } + //$path = array_merge($path, array_values($arg)); + } elseif ( is_scalar($arg) ) { + $path[] = $arg; + } + } + + return $path; + } + + /** + * Builds attribute string for HTML element + * @param array $attr Attributes + * @return string Formatted attribute string + */ + function build_attribute_string($attr) { + $ret = ''; + if ( is_object($attr) ) + $attr = (array) $attr; + if ( is_array($attr) ) { + array_map('esc_attr', $attr); + $attr_str = array(); + foreach ( $attr as $key => $val ) { + $attr_str[] = $key . '="' . $val . '"'; + } + $ret = implode(' ', $attr_str); + } + return $ret; + } + + /** + * Generate external stylesheet element + * @param $url Stylesheet URL + * @return string Stylesheet element + */ + function build_stylesheet_element($url = '') { + $attributes = array('href' => $url, 'type' => 'text/css', 'rel' => 'stylesheet'); + return $this->build_html_element(array('tag' => 'link', 'wrap' => false, 'attributes' => $attributes)); + } + + /** + * Generate external script element + * @param $url Script URL + * @return string Script element + */ + function build_ext_script_element($url = '') { + $attributes = array('src' => $url, 'type' => 'text/javascript'); + return $this->build_html_element(array('tag' => 'script', 'attributes' => $attributes)); + } + + /** + * Generate HTML element based on values + * @param $args Element arguments + * @return string Generated HTML element + */ + function build_html_element($args) { + $defaults = array( + 'tag' => 'span', + 'wrap' => true, + 'content' => '', + 'attributes' => array() + ); + $el_start = '<'; + $el_end = '>'; + $el_close = '/'; + extract(wp_parse_args($args, $defaults), EXTR_SKIP); + $content = trim($content); + + if ( !$wrap && strlen($content) > 0 ) + $wrap = true; + + $attributes = $this->build_attribute_string($attributes); + if ( strlen($attributes) > 0 ) + $attributes = ' ' . $attributes; + + $ret = $el_start . $tag . $attributes; + + if ( $wrap ) + $ret .= $el_end . $content . $el_start . $el_close . $tag; + else + $ret .= ' ' . $el_close; + + $ret .= $el_end; + return $ret; + } + + /*-** Admin **-*/ + + /** + * Add submenu page in the admin menu + * Adds ability to set the position of the page in the menu + * @see add_submenu_page (Wraps functionality) + * + * @param $parent + * @param $page_title + * @param $menu_title + * @param $access_level + * @param $file + * @param $function + * @param int $pos Index position of menu page + * + * @global array $submenu Admin page submenus + */ + function add_submenu_page($parent, $page_title, $menu_title, $capability, $file, $function = '', $pos = false) { + //Add submenu page as usual + $args = func_get_args(); + $hookname = call_user_func_array('add_submenu_page', $args); + if ( is_int($pos) ) { + global $submenu; + //Get last submenu added + $parent = $this->get_submenu_parent_file($parent); + if ( isset($submenu[$parent]) ) { + $subs =& $submenu[$parent]; + + //Make sure menu isn't already in the desired position + if ( $pos <= ( count($subs) - 1 ) ) { + //Get submenu that was just added + $sub = array_pop($subs); + //Insert into desired position + if ( 0 == $pos ) { + array_unshift($subs, $sub); + } else { + $top = array_slice($subs, 0, $pos); + $bottom = array_slice($subs, $pos); + array_push($top, $sub); + $subs = array_merge($top, $bottom); + } + } + } + } + + return $hookname; + } + + /** + * Remove admin submenu + * @param string $parent Submenu parent file + * @param string $file Submenu file name + * @return int|null Index of removed submenu (NULL if submenu not found) + * + * @global array $submenu + * @global array $_registered_pages + */ + function remove_submenu_page($parent, $file) { + global $submenu, $_registered_pages; + $ret = null; + + $parent = $this->get_submenu_parent_file($parent); + $file = plugin_basename($file); + $file_index = 2; + + //Find submenu + if ( isset($submenu[$parent]) ) { + $subs =& $submenu[$parent]; + for ($x = 0; $x < count($subs); $x++) { + if ( $subs[$x][$file_index] == $file ) { + //Remove matching submenu + $hookname = get_plugin_page_hookname($file, $parent); + remove_all_actions($hookname); + unset($_registered_pages[$hookname]); + unset($subs[$x]); + $subs = array_values($subs); + //Set index and stop processing + $ret = $x; + break; + } + } + } + + return $ret; + } + + /** + * Replace a submenu page + * Adds a submenu page in the place of an existing submenu page that has the same $file value + * + * @param $parent + * @param $page_title + * @param $menu_title + * @param $access_level + * @param $file + * @param $function + * @return string Hookname + * + * @global array $submenu + */ + function replace_submenu_page($parent, $page_title, $menu_title, $access_level, $file, $function = '') { + global $submenu; + //Remove matching submenu (if exists) + $pos = $this->remove_submenu_page($parent, $file); + //Insert submenu page + $hookname = $this->add_submenu_page($parent, $page_title, $menu_title, $access_level, $file, $function, $pos); + return $hookname; + } + + /** + * Retrieves parent file for submenu + * @param string $parent Parent file + * @return string Formatted parent file name + * + * @global array $_wp_real_parent_file; + */ + function get_submenu_parent_file($parent) { + global $_wp_real_parent_file; + $parent = plugin_basename($parent); + if ( isset($_wp_real_parent_file[$parent]) ) + $parent = $_wp_real_parent_file[$parent]; + return $parent; + } +} \ No newline at end of file diff --git a/src/wp-content/plugins/simple-lightbox/js/dev/lightbox.js b/src/wp-content/plugins/simple-lightbox/js/dev/lightbox.js new file mode 100644 index 00000000..6613044c --- /dev/null +++ b/src/wp-content/plugins/simple-lightbox/js/dev/lightbox.js @@ -0,0 +1,867 @@ +// ----------------------------------------------------------------------------------- +// +// Simple Lightbox +// by Archetyped - http://archetyped.com/tools/simple-lightbox/ +// Updated: 2011-01-27 +// +// Originally based on Lightbox Slideshow v1.1 +// by Justin Barkhuff - http://www.justinbarkhuff.com/lab/lightbox_slideshow/ +// 2007/08/15 +// +// Largely based on Lightbox v2.02 +// by Lokesh Dhakar - http://huddletogether.com/projects/lightbox2/ +// 2006/03/31 +// +// Licensed under the Creative Commons Attribution 2.5 License - http://creativecommons.org/licenses/by/2.5/ +// +// The code inserts HTML at the bottom of the page for displaying content in a non-modal dialog +// +// ----------------------------------------------------------------------------------- + +/** + * Lightbox object + */ +//var SLB = null; +(function($) { +SLB = { + activeImage : null, + badObjects : ['select','object','embed'], + container : null, + enableSlideshow : null, + groupName : null, + imageArray : [], + options : null, + overlayDuration : null, + overlayOpacity : null, + playSlides : null, + refTags : ['a'], + relAttribute : null, + resizeDuration : null, + slideShowTimer : null, + startImage : null, + prefix : 'slb', + checkedUrls : {}, + + + /** + * Initialize lightbox instance + * @param object options Instance options + */ + initialize: function(options) { + this.options = $.extend(true, { + animate : true, // resizing animations + validateLinks : false, //Validate links before adding them to lightbox + captionEnabled: true, //Display caption + captionSrc : true, //Use image source URI if title not set + autoPlay : true, // should slideshow start automatically + borderSize : 10, // if you adjust the padding in the CSS, you will need to update this variable + containerID : document, // lightbox container object + enableSlideshow : true, // enable slideshow feature + googleAnalytics : false, // track individual image views using Google Analytics + imageDataLocation : 'south', // location of image caption information + initImage : '', // ID of image link to automatically launch when upon script initialization + loop : true, // whether to continuously loop slideshow images + overlayDuration : .2, // time to fade in shadow overlay + overlayOpacity : .8, // transparency of shadow overlay + relAttribute : 'lightbox', // specifies the rel attribute value that triggers lightbox + resizeSpeed : 400, // controls the speed of the image resizing (milliseconds) + showGroupName : false, // show group name of images in image details + slideTime : 4, // time to display images during slideshow + altsrc : 'src', + strings : { // allows for localization + closeLink : 'close', + loadingMsg : 'loading', + nextLink : 'next »', + prevLink : '« prev', + startSlideshow : 'start slideshow', + stopSlideshow : 'stop slideshow', + numDisplayPrefix : 'Image', + numDisplaySeparator : 'of' + }, + placeholders : { + slbContent: '', + slbLoading: 'loading', + slbClose: 'close', + navPrev: '« prev', + navNext: '» next', + navSlideControl: 'Stop', + dataCaption: '', + dataNumber: '' + }, + layout : null + }, options); + + //Stop if no layout is defined + if (!this.options.layout || this.options.layout.toString().length == 0) + this.end(); + + //Validate options + if ( this.options.animate ) { + this.overlayDuration = Math.max(this.options.overlayDuration,0); + this.resizeDuration = this.options.resizeSpeed; + } else { + this.overlayDuration = 0; + this.resizeDuration = 0; + } + this.enableSlideshow = this.options.enableSlideshow; + this.overlayOpacity = Math.max(Math.min(this.options.overlayOpacity,1),0); + this.playSlides = this.options.autoPlay; + this.container = $(this.options.containerID); + this.relAttribute = this.options.relAttribute; + this.updateImageList(); + var t = this; + var objBody = $(this.container).get(0) != document ? this.container : $('body'); + + var objOverlay = $('
', { + 'id': this.getID('overlay'), + 'css': {'display': 'none'} + }).appendTo(objBody) + .click(function() {t.end()}); + + var objLightbox = $('
', { + 'id': this.getID('lightbox'), + 'css': {'display': 'none'} + }).appendTo(objBody) + .click(function() {t.end()}); + + //Build layout from template + var layout = this.getLayout(); + + //Append to container + $(layout).appendTo(objLightbox); + + //Set UI + this.setUI(); + + //Add events + this.setEvents(); + + if (this.options.initImage != '') { + this.start($(this.options.initImage)); + } + }, + + /** + * Build layout from template + * @uses options.layout + * @return string Layout markup (HTML) + */ + getLayout: function() { + var l = this.options.layout; + + //Expand placeholders + var ph, phs, phr; + for (ph in this.options.placeholders) { + phs = '{' + ph + '}'; + //Continue to next placeholder if current one is not in layout + if (l.indexOf(phs) == -1) + continue; + phr = new RegExp(phs, "g"); + l = l.replace(phr, this.options.placeholders[ph]); + } + + //Return final layout + return l; + + }, + + /** + * Set localized values for UI elements + */ + setUI: function() { + var s = this.options.strings; + this.get('slbClose').html(s.closeLink); + this.get('navNext').html(s.nextLink); + this.get('navPrev').html(s.prevLink); + this.get('navSlideControl').html(((this.playSlides) ? s.stopSlideshow : s.startSlideshow)); + }, + + /** + * Add events to various UI elements + */ + setEvents: function() { + var t = this, delay = 500; + this.get('container,details').click(function(ev) { + ev.stopPropagation(); + }); + + var clickP = function() { + t.get('navPrev').unbind('click').click(false); + setTimeout(function() {t.get('navPrev').click(clickP)}, delay); + t.showPrev(); + return false; + }; + this.get('navPrev').click(function(){ + return clickP(); + }); + + var clickN = function() { + t.get('navNext').unbind('click').click(false); + setTimeout(function() {t.get('navNext').click(clickN)}, delay); + t.showNext(); + return false; + }; + this.get('navNext').click(function() { + return clickN(); + }); + + this.get('navSlideControl').click(function() { + t.toggleSlideShow(); + return false; + }); + this.get('slbClose').click(function() { + t.end(); + return false; + }); + }, + + /** + * Finds all compatible image links on page + */ + updateImageList: function() { + var el, els, rel, t = this; + sel = [], selBase = '[href][rel*="' + this.relAttribute + '"]'; + + //Define event handler + var handler = function() { + //Check if element is valid for lightbox + t.start(this); + return false; + }; + + //Build selector + for (var i = 0; i < this.refTags.length; i++) { + sel.push(this.refTags[i] + selBase); + } + sel = sel.join(','); + + //Add event handler to links + $(sel, $(this.container)).live('click', handler); + }, + + /** + * Build caption for displayed caption + * @param {Object} imageLink + */ + getCaption: function(imageLink) { + imageLink = $(imageLink); + var caption = ''; + if (this.options.captionEnabled) { + caption = imageLink.attr('title') || ''; + if (caption == '') { + var inner = $(imageLink).find('img').first(); + if ($(inner).length) + caption = $(inner).attr('title') || $(inner).attr('alt'); + if (!caption) { + if (imageLink.text().length) + caption = imageLink.text(); + else + if (this.options.captionSrc) + caption = imageLink.attr('href'); + } + if (!caption) + caption = ''; + } + } + return caption; + }, + + /** + * Display overlay and lightbox. If image is part of a set, add siblings to imageArray. + * @param node imageLink Link element containing image URL + */ + start: function(imageLink) { + imageLink = $(imageLink); + this.hideBadObjects(); + + this.imageArray = []; + this.groupName = this.getGroup(imageLink); + + var rel = $(imageLink).attr('rel') || ''; + var imageTitle = ''; + var t = this; + var groupTemp = {}; + this.fileExists(this.getSourceFile(imageLink), + function() { //File exists + // Stretch overlay to fill page and fade in + t.get('overlay') + .height($(document).height()) + .fadeTo(t.overlayDuration, t.overlayOpacity); + + // Add image to array closure + var addLink = function(el, idx) { + groupTemp[idx] = el; + return groupTemp.length; + }; + + //Build final image array & launch lightbox + var proceed = function() { + t.startImage = 0; + //Sort links by document order + var order = [], el; + for (var x in groupTemp) { + order.push(x); + } + order.sort(function(a, b) { return (a - b); }); + for (x = 0; x < order.length; x++) { + el = groupTemp[order[x]]; + //Check if link being evaluated is the same as the clicked link + if ($(el).get(0) == $(imageLink).get(0)) { + t.startImage = x; + } + t.imageArray.push({'link':t.getSourceFile($(el)), 'title':t.getCaption(el)}); + } + // Calculate top offset for the lightbox and display + var lightboxTop = $(document).scrollTop() + ($(window).height() / 15); + + t.get('lightbox').css('top', lightboxTop + 'px').show(); + t.changeImage(t.startImage); + } + + // If image is NOT part of a group.. + if (null == t.groupName) { + // Add single image to imageArray + addLink(imageLink, 0); + t.startImage = 0; + proceed(); + } else { + // If image is part of a group + var els = $(t.container).find($(imageLink).get(0).tagName.toLowerCase()); + // Loop through links on page & find other images in group + var grpLinks = []; + var i, el; + for (i = 0; i < els.length; i++) { + el = $(els[i]); + if (t.getSourceFile(el) && (t.getGroup(el) == t.groupName)) { + //Add links in same group to temp array + grpLinks.push(el); + } + } + + //Loop through group links, validate, and add to imageArray + var processed = 0; + for (i = 0; i < grpLinks.length; i++) { + el = grpLinks[i]; + t.fileExists(t.getSourceFile($(el)), + function(args) { //File exists + var el = args.els[args.idx]; + var il = addLink(el, args.idx); + processed++; + if (processed == args.els.length) + proceed(); + }, + function(args) { //File does not exist + processed++; + if (args.idx == args.els.length) + proceed(); + }, + {'idx': i, 'els': grpLinks}); + } + } + }, + function() { //File does not exist + t.end(); + }); + }, + + /** + * Retrieve source URI in link + * @param {Object} el + * @return string Source file URI + */ + getSourceFile: function(el) { + var src = $(el).attr('href'); + var rel = $(el).attr('rel') || ''; + var reSrc = new RegExp('\\b' + this.options.altsrc + '\\[(.+?)\\](?:\\b|$)'); + if ( reSrc.test(rel) ) { + src = reSrc.exec(rel)[1]; + } + return src; + }, + + /** + * Extract group name from + * @param obj el Element to extract group name from + * @return string Group name + */ + getGroup: function(el) { + //Get full attribute value + var g = null; + var rel = $(el).attr('rel') || ''; + if (rel != '') { + var gTmp = ''; + var gSt = '['; + var gEnd = ']'; + var search = this.relAttribute; + var searching = true; + var idx; + var prefix = ' '; + while (searching) { + idx = rel.indexOf(search); + //Stop processing if value is not found + if (idx == -1) + return g; + //Prefix with space to find whole word + if (prefix != search.charAt(0) && idx > 0) { + search = prefix + search; + } + else { + searching = false; + } + } + gTmp = $.trim(rel.substring(idx).replace(search, '')); + //Check if group defined + if (gTmp.length && gSt == gTmp.charAt(0) && gTmp.indexOf(gEnd) != -1) { + //Extract group name + g = gTmp.substring(1, gTmp.indexOf(gEnd)); + } + } + return g; + }, + + /** + * Preload requested image prior to displaying it in lightbox + * @param int imageNum Index of image in imageArray property + * @uses imageArray to retrieve index at specified image + * @uses resizeImageContainer() to resize lightbox after image has loaded + */ + changeImage: function(imageNum) { + this.activeImage = imageNum; + + this.disableKeyboardNav(); + this.pauseSlideShow(); + + // hide elements during transition + this.get('slbLoading').show(); + this.get('slbContent').hide(); + this.get('details').hide(); + var imgPreloader = new Image(); + var t = this; + // once image is preloaded, resize image container + $(imgPreloader).bind('load', function() { + t.get('slbContent').attr('src', imgPreloader.src); + t.resizeImageContainer(imgPreloader.width, imgPreloader.height); + //Restart slideshow if active + if ( t.isSlideShowActive() ) + t.startSlideShow(); + }); + + //Load image + imgPreloader.src = this.imageArray[this.activeImage].link; + }, + + /** + * Resizes lightbox to fit image + * @param int imgWidth Image width in pixels + * @param int imgHeight Image height in pixels + */ + resizeImageContainer: function(imgWidth, imgHeight) { + // get current height and width + var el = this.get('container'); + var borderSize = this.options.borderSize * 2; + + this.get('container').animate({width: imgWidth + borderSize, height: imgHeight + borderSize}, this.resizeDuration) + + this.showImage(); + }, + + /** + * Display image and begin preloading neighbors. + */ + showImage: function() { + this.get('slbLoading').hide(); + var t = this; + this.get('slbContent').fadeIn(500, function() { t.updateDetails(); }); + this.preloadNeighborImages(); + }, + + /** + * Display caption, image number, and bottom nav + */ + updateDetails: function() { + if (this.options.captionEnabled) { + this.get('dataCaption').text(this.imageArray[this.activeImage].title); + this.get('dataCaption').show(); + } else { + this.get('dataCaption').hide(); + } + + // if image is part of set display 'Image x of y' + if (this.hasImages()) { + var num_display = this.options.strings.numDisplayPrefix + ' ' + (this.activeImage + 1) + ' ' + this.options.strings.numDisplaySeparator + ' ' + this.imageArray.length; + if (this.options.showGroupName && this.groupName != '') { + num_display += ' ' + this.options.strings.numDisplaySeparator + ' ' + this.groupName; + } + this.get('dataNumber') + .text(num_display) + .show(); + } + + this.get('details').width(this.get('slbContent').width() + (this.options.borderSize * 2)); + this.updateNav(); + var t = this; + this.get('details').animate({height: 'show', opacity: 'show'}, 650); + }, + + /** + * Display appropriate previous and next hover navigation. + */ + updateNav: function() { + if (this.hasImages()) { + this.get('navPrev').show(); + this.get('navNext').show(); + if (this.enableSlideshow) { + this.get('navSlideControl').show(); + if (this.playSlides) { + this.startSlideShow(); + } else { + this.stopSlideShow(); + } + } else { + this.get('navSlideControl').hide(); + } + } else { + // Hide navigation controls when only one image exists + this.get('dataNumber').hide(); + this.get('navPrev').hide(); + this.get('navNext').hide(); + this.get('navSlideControl').hide(); + } + this.enableKeyboardNav(); + }, + + /** + * Checks if slideshow is currently activated + * @return bool TRUE if slideshow is active, FALSE otherwise + * @uses playSlides to check slideshow activation status + */ + isSlideShowActive: function() { + return this.playSlides; + }, + + /** + * Start the slideshow + */ + startSlideShow: function() { + this.playSlides = true; + var t = this; + clearInterval(this.slideShowTimer); + this.slideShowTimer = setInterval(function() { t.showNext(); t.pauseSlideShow(); }, this.options.slideTime * 1000); + this.get('navSlideControl').text(this.options.strings.stopSlideshow); + }, + + /** + * Stop the slideshow + */ + stopSlideShow: function() { + this.playSlides = false; + if (this.slideShowTimer) { + clearInterval(this.slideShowTimer); + } + this.get('navSlideControl').text(this.options.strings.startSlideshow); + }, + + /** + * Toggles the slideshow status + */ + toggleSlideShow: function() { + if (this.playSlides) { + this.stopSlideShow(); + }else{ + this.startSlideShow(); + } + }, + + /** + * Pauses the slideshow + * Stops the slideshow but does not change the slideshow's activation status + */ + pauseSlideShow: function() { + if (this.slideShowTimer) { + clearInterval(this.slideShowTimer); + } + }, + + /** + * Check if there is at least one image to display in the lightbox + * @return bool TRUE if at least one image is found + * @uses imageArray to check for images + */ + hasImage: function() { + return ( this.imageArray.length > 0 ); + }, + + /** + * Check if there are multiple images to display in the lightbox + * @return bool TRUE if there are multiple images + * @uses imageArray to determine the number of images + */ + hasImages: function() { + return ( this.imageArray.length > 1 ); + }, + + /** + * Check if the current image is the first image in the list + * @return bool TRUE if image is first + * @uses activeImage to check index of current image + */ + isFirstImage: function() { + return ( this.activeImage == 0 ); + }, + + /** + * Check if the current image is the last image in the list + * @return bool TRUE if image is last + * @uses activeImage to check index of current image + * @uses imageArray to compare current image to total number of images + */ + isLastImage: function() { + return ( this.activeImage == this.imageArray.length - 1 ); + }, + + /** + * Show the next image in the list + */ + showNext : function() { + if (this.hasImages()) { + if ( !this.options.loop && this.isLastImage() ) { + return this.end(); + } + if ( this.isLastImage() ) { + this.showFirst(); + } else { + this.changeImage(this.activeImage + 1); + } + } + }, + + /** + * Show the previous image in the list + */ + showPrev : function() { + if (this.hasImages()) { + if ( !this.options.loop && this.isFirstImage() ) + return this.end(); + if (this.activeImage == 0) { + this.showLast(); + } else { + this.changeImage(this.activeImage - 1); + } + } + }, + + /** + * Show the first image in the list + */ + showFirst : function() { + if (this.hasImages()) { + this.changeImage(0); + } + }, + + /** + * Show the last image in the list + */ + showLast : function() { + if (this.hasImages()) { + this.changeImage(this.imageArray.length - 1); + } + }, + + /** + * Enable image navigation via the keyboard + */ + enableKeyboardNav: function() { + var t = this; + $(document).keydown(function(e) { + t.keyboardAction(e); + }); + }, + + /** + * Disable image navigation via the keyboard + */ + disableKeyboardNav: function() { + $(document).unbind('keydown'); + }, + + /** + * Handler for keyboard events + * @param event e Keyboard event data + */ + keyboardAction: function(e) { + if (e == null) { // ie + keycode = event.keyCode; + } else { // mozilla + keycode = e.which; + } + + key = String.fromCharCode(keycode).toLowerCase(); + + if (keycode == 27 || key == 'x' || key == 'o' || key == 'c') { // close lightbox + this.end(); + } else if (key == 'p' || key == '%') { // display previous image + this.showPrev(); + } else if (key == 'n' || key =='\'') { // display next image + this.showNext(); + } else if (key == 'f') { // display first image + this.showFirst(); + } else if (key == 'l') { // display last image + this.showLast(); + } else if (key == 's') { // toggle slideshow + if (this.hasImage() && this.options.enableSlideshow) { + this.toggleSlideShow(); + } + } + }, + + /** + * Preloads images before/after current image + */ + preloadNeighborImages: function() { + var nextImageID = this.imageArray.length - 1 == this.activeImage ? 0 : this.activeImage + 1; + nextImage = new Image(); + nextImage.src = this.imageArray[nextImageID].link; + + var prevImageID = this.activeImage == 0 ? this.imageArray.length - 1 : this.activeImage - 1; + prevImage = new Image(); + prevImage.src = this.imageArray[prevImageID].link; + }, + + /** + * Close the lightbox + */ + end: function() { + this.disableKeyboardNav(); + this.pauseSlideShow(); + this.get('lightbox').hide(); + this.get('overlay').fadeOut(this.overlayDuration); + this.showBadObjects(); + }, + + /** + * Displays objects that may conflict with the lightbox + * @param bool show (optional) Whether or not to show objects (Default: TRUE) + */ + showBadObjects: function (show) { + show = ( typeof(show) == 'undefined' ) ? true : !!show; + var vis = (show) ? 'visible' : 'hidden'; + $(this.badObjects.join(',')).css('visibility', vis); + }, + + /** + * Hides objects that may conflict with the lightbox + * @uses showBadObjects() to hide objects + */ + hideBadObjects: function () { + this.showBadObjects(false); + }, + + /** + * Add prefix to text + * @param string txt Text to add prefix to + * @return string Prefixed text + */ + addPrefix: function(txt) { + return this.prefix + '_' + txt; + }, + + /** + * Generate formatted ID for lightbox-specific elements + * @param string id Base ID of element + * @return string Formatted ID + */ + getID: function(id) { + return this.addPrefix(id); + }, + + /** + * Generate formatted selector for lightbox-specific elements + * Compares specified ID to placeholders first, then named elements + * Multiple selectors can be included and separated by commas (',') + * @param string id Base ID of element + * @uses options.placeholders to compare id to placeholder names + * @return string Formatted selector + */ + getSel: function(id) { + //Process multiple selectors + var delim = ',', prefix = '#', sel; + if (id.toString().indexOf(delim) != -1) { + //Split + var sels = id.toString().split(delim); + //Build selector + for (var x = 0; x < sels.length; x++) { + sels[x] = this.getSel($.trim(sels[x])); + } + //Join + sel = sels.join(delim); + } else { + //Single selector + if (id in this.options.placeholders) { + var ph = $(this.options.placeholders[id]); + if (!ph.attr('id')) { + //Class selector + prefix = '.'; + } + } + sel = prefix + this.getID(id); + } + + return sel; + }, + + /** + * Retrieve lightbox-specific element + * @param string id Base ID of element + * @uses getSel() to generate formatted selector for element + * @return object jQuery object of selected element(s) + */ + get: function(id) { + return $(this.getSel(id)); + }, + + /** + * Checks if file exists using AJAX request + * @param string url File URL + * @param callback success Callback to run if file exists + * @param callback failure Callback to run if file does not exist + * @param obj args Arguments for callback + */ + fileExists: function(url, success, failure, args) { + if (!this.options.validateLinks) + return success(args); + var statusFail = 400; + var stateCheck = 4; + var t = this; + var proceed = function(res) { + if (res.status < statusFail) { + if ($.isFunction(success)) + success(args); + } else { + if ($.isFunction(failure)) + failure(args); + } + }; + + //Check if URL already processed + if (url in this.checkedUrls) { + proceed(this.checkedUrls[url]); + } else { + var req = new XMLHttpRequest(); + req.open('HEAD', url, true); + req.onreadystatechange = function() { + if (stateCheck == this.readyState) { + t.addUrl(url, this); + proceed(this); + } + }; + req.send(); + } + }, + + addUrl: function(url, res) { + if (!(url in this.checkedUrls)) + this.checkedUrls[url] = res; + } +} +})(jQuery); \ No newline at end of file diff --git a/src/wp-content/plugins/simple-lightbox/js/lib.js b/src/wp-content/plugins/simple-lightbox/js/lib.js new file mode 100644 index 00000000..b6b036f1 --- /dev/null +++ b/src/wp-content/plugins/simple-lightbox/js/lib.js @@ -0,0 +1,21 @@ +(function(d){SLB={activeImage:null,badObjects:["select","object","embed"],container:null,enableSlideshow:null,groupName:null,imageArray:[],options:null,overlayDuration:null,overlayOpacity:null,playSlides:null,refTags:["a"],relAttribute:null,resizeDuration:null,slideShowTimer:null,startImage:null,prefix:"slb",checkedUrls:{},initialize:function(a){this.options=d.extend(true,{animate:true,validateLinks:false,captionEnabled:true,captionSrc:true,autoPlay:true,borderSize:10,containerID:document,enableSlideshow:true, +googleAnalytics:false,imageDataLocation:"south",initImage:"",loop:true,overlayDuration:0.2,overlayOpacity:0.8,relAttribute:"lightbox",resizeSpeed:400,showGroupName:false,slideTime:4,altsrc:"src",strings:{closeLink:"close",loadingMsg:"loading",nextLink:"next »",prevLink:"« prev",startSlideshow:"start slideshow",stopSlideshow:"stop slideshow",numDisplayPrefix:"Image",numDisplaySeparator:"of"},placeholders:{slbContent:'',slbLoading:'loading', +slbClose:'close',navPrev:'« prev',navNext:'» next',navSlideControl:'Stop',dataCaption:'',dataNumber:''},layout:null},a);if(!this.options.layout||this.options.layout.toString().length==0)this.end();if(this.options.animate){this.overlayDuration=Math.max(this.options.overlayDuration, +0);this.resizeDuration=this.options.resizeSpeed}else this.resizeDuration=this.overlayDuration=0;this.enableSlideshow=this.options.enableSlideshow;this.overlayOpacity=Math.max(Math.min(this.options.overlayOpacity,1),0);this.playSlides=this.options.autoPlay;this.container=d(this.options.containerID);this.relAttribute=this.options.relAttribute;this.updateImageList();var b=this;a=d(this.container).get(0)!=document?this.container:d("body");d("
",{id:this.getID("overlay"),css:{display:"none"}}).appendTo(a).click(function(){b.end()}); +a=d("
",{id:this.getID("lightbox"),css:{display:"none"}}).appendTo(a).click(function(){b.end()});var c=this.getLayout();d(c).appendTo(a);this.setUI();this.setEvents();this.options.initImage!=""&&this.start(d(this.options.initImage))},getLayout:function(){var a=this.options.layout,b,c;for(b in this.options.placeholders){c="{"+b+"}";if(a.indexOf(c)!=-1){c=new RegExp(c,"g");a=a.replace(c,this.options.placeholders[b])}}return a},setUI:function(){var a=this.options.strings;this.get("slbClose").html(a.closeLink); +this.get("navNext").html(a.nextLink);this.get("navPrev").html(a.prevLink);this.get("navSlideControl").html(this.playSlides?a.stopSlideshow:a.startSlideshow)},setEvents:function(){var a=this;this.get("container,details").click(function(g){g.stopPropagation()});var b=function(){a.get("navPrev").unbind("click").click(false);setTimeout(function(){a.get("navPrev").click(b)},500);a.showPrev();return false};this.get("navPrev").click(function(){return b()});var c=function(){a.get("navNext").unbind("click").click(false); +setTimeout(function(){a.get("navNext").click(c)},500);a.showNext();return false};this.get("navNext").click(function(){return c()});this.get("navSlideControl").click(function(){a.toggleSlideShow();return false});this.get("slbClose").click(function(){a.end();return false})},updateImageList:function(){var a=this;sel=[];selBase='[href][rel*="'+this.relAttribute+'"]';for(var b=0;b0)c=" "+c;else g=false}c=d.trim(a.substring(h).replace(c,""));if(c.length&&"["==c.charAt(0)&&c.indexOf("]")!=-1)b=c.substring(1,c.indexOf("]"))}return b},changeImage:function(a){this.activeImage=a;this.disableKeyboardNav();this.pauseSlideShow();this.get("slbLoading").show();this.get("slbContent").hide();this.get("details").hide();var b=new Image,c=this;d(b).bind("load", +function(){c.get("slbContent").attr("src",b.src);c.resizeImageContainer(b.width,b.height);c.isSlideShowActive()&&c.startSlideShow()});b.src=this.imageArray[this.activeImage].link},resizeImageContainer:function(a,b){this.get("container");var c=this.options.borderSize*2;this.get("container").animate({width:a+c,height:b+c},this.resizeDuration);this.showImage()},showImage:function(){this.get("slbLoading").hide();var a=this;this.get("slbContent").fadeIn(500,function(){a.updateDetails()});this.preloadNeighborImages()}, +updateDetails:function(){if(this.options.captionEnabled){this.get("dataCaption").text(this.imageArray[this.activeImage].title);this.get("dataCaption").show()}else this.get("dataCaption").hide();if(this.hasImages()){var a=this.options.strings.numDisplayPrefix+" "+(this.activeImage+1)+" "+this.options.strings.numDisplaySeparator+" "+this.imageArray.length;if(this.options.showGroupName&&this.groupName!="")a+=" "+this.options.strings.numDisplaySeparator+" "+this.groupName;this.get("dataNumber").text(a).show()}this.get("details").width(this.get("slbContent").width()+ +this.options.borderSize*2);this.updateNav();this.get("details").animate({height:"show",opacity:"show"},650)},updateNav:function(){if(this.hasImages()){this.get("navPrev").show();this.get("navNext").show();if(this.enableSlideshow){this.get("navSlideControl").show();this.playSlides?this.startSlideShow():this.stopSlideShow()}else this.get("navSlideControl").hide()}else{this.get("dataNumber").hide();this.get("navPrev").hide();this.get("navNext").hide();this.get("navSlideControl").hide()}this.enableKeyboardNav()}, +isSlideShowActive:function(){return this.playSlides},startSlideShow:function(){this.playSlides=true;var a=this;clearInterval(this.slideShowTimer);this.slideShowTimer=setInterval(function(){a.showNext();a.pauseSlideShow()},this.options.slideTime*1E3);this.get("navSlideControl").text(this.options.strings.stopSlideshow)},stopSlideShow:function(){this.playSlides=false;this.slideShowTimer&&clearInterval(this.slideShowTimer);this.get("navSlideControl").text(this.options.strings.startSlideshow)},toggleSlideShow:function(){this.playSlides? +this.stopSlideShow():this.startSlideShow()},pauseSlideShow:function(){this.slideShowTimer&&clearInterval(this.slideShowTimer)},hasImage:function(){return this.imageArray.length>0},hasImages:function(){return this.imageArray.length>1},isFirstImage:function(){return this.activeImage==0},isLastImage:function(){return this.activeImage==this.imageArray.length-1},showNext:function(){if(this.hasImages()){if(!this.options.loop&&this.isLastImage())return this.end();this.isLastImage()?this.showFirst():this.changeImage(this.activeImage+ +1)}},showPrev:function(){if(this.hasImages()){if(!this.options.loop&&this.isFirstImage())return this.end();this.activeImage==0?this.showLast():this.changeImage(this.activeImage-1)}},showFirst:function(){this.hasImages()&&this.changeImage(0)},showLast:function(){this.hasImages()&&this.changeImage(this.imageArray.length-1)},enableKeyboardNav:function(){var a=this;d(document).keydown(function(b){a.keyboardAction(b)})},disableKeyboardNav:function(){d(document).unbind("keydown")},keyboardAction:function(a){keycode= +a==null?event.keyCode:a.which;key=String.fromCharCode(keycode).toLowerCase();if(keycode==27||key=="x"||key=="o"||key=="c")this.end();else if(key=="p"||key=="%")this.showPrev();else if(key=="n"||key=="'")this.showNext();else if(key=="f")this.showFirst();else if(key=="l")this.showLast();else key=="s"&&this.hasImage()&&this.options.enableSlideshow&&this.toggleSlideShow()},preloadNeighborImages:function(){var a=this.imageArray.length-1==this.activeImage?0:this.activeImage+1;nextImage=new Image;nextImage.src= +this.imageArray[a].link;a=this.activeImage==0?this.imageArray.length-1:this.activeImage-1;prevImage=new Image;prevImage.src=this.imageArray[a].link},end:function(){this.disableKeyboardNav();this.pauseSlideShow();this.get("lightbox").hide();this.get("overlay").fadeOut(this.overlayDuration);this.showBadObjects()},showBadObjects:function(a){d(this.badObjects.join(",")).css("visibility",(typeof a=="undefined"?true:!!a)?"visible":"hidden")},hideBadObjects:function(){this.showBadObjects(false)},addPrefix:function(a){return this.prefix+ +"_"+a},getID:function(a){return this.addPrefix(a)},getSel:function(a){var b="#";if(a.toString().indexOf(",")!=-1){a=a.toString().split(",");for(b=0;bis_enabled(); +} + +function slb_register_theme($name, $title, $stylesheet_url, $layout) { + global $slb; + $slb->register_theme($name, $title, $stylesheet_url, $layout); +} + +?> diff --git a/src/wp-content/plugins/simple-lightbox/model.php b/src/wp-content/plugins/simple-lightbox/model.php new file mode 100644 index 00000000..9454d707 --- /dev/null +++ b/src/wp-content/plugins/simple-lightbox/model.php @@ -0,0 +1,633 @@ + array ( + 'activation' => 'Activation', + 'grouping' => 'Grouping', + 'ui' => 'UI', + 'labels' => 'Labels' + ), + 'items' => array ( + 'enabled' => array('title' => 'Enable Lightbox Functionality', 'default' => true, 'group' => 'activation'), + 'enabled_home' => array('title' => 'Enable on Home page', 'default' => true, 'group' => 'activation'), + 'enabled_post' => array('title' => 'Enable on Posts', 'default' => true, 'group' => 'activation'), + 'enabled_page' => array('title' => 'Enable on Pages', 'default' => true, 'group' => 'activation'), + 'enabled_archive' => array('title' => 'Enable on Archive Pages (tags, categories, etc.)', 'default' => true, 'group' => 'activation'), + 'activate_links' => array('title' => 'Activate all image links in item content', 'default' => true, 'group' => 'activation'), + 'activate_attachments' => array('title' => 'Activate all image attachment links', 'default' => true, 'group' => 'activation'), + 'validate_links' => array('title' => 'Validate links', 'default' => false, 'group' => 'activation'), + 'group_links' => array('title' => 'Group automatically activated links (for displaying as a slideshow)', 'default' => true, 'group' => 'grouping'), + 'group_post' => array('title' => 'Group image links by Post (e.g. on pages with multiple posts)', 'default' => true, 'group' => 'grouping'), + 'theme' => array('title' => 'Theme', 'default' => 'default', 'group' => 'ui', 'parent' => 'option_theme'), + 'animate' => array('title' => 'Animate lightbox resizing', 'default' => true, 'group' => 'ui'), + 'autostart' => array('title' => 'Automatically Start Slideshow', 'default' => true, 'group' => 'ui'), + 'duration' => array('title' => 'Slide Duration (Seconds)', 'default' => '6', 'attr' => array('size' => 3, 'maxlength' => 3), 'group' => 'ui'), + 'loop' => array('title' => 'Loop through images', 'default' => true, 'group' => 'ui'), + 'overlay_opacity' => array('title' => 'Overlay Opacity (0 - 1)', 'default' => '0.8', 'attr' => array('size' => 3, 'maxlength' => 3), 'group' => 'ui'), + 'enabled_caption' => array('title' => 'Enable caption', 'default' => true, 'group' => 'ui'), + 'caption_src' => array('title' => 'Use image URI as caption when link title not set', 'default' => true, 'group' => 'ui'), + 'txt_closeLink' => array('title' => 'Close link (for accessibility only, image used for button)', 'default' => 'close', 'group' => 'labels'), + 'txt_loadingMsg' => array('title' => 'Loading indicator', 'default' => 'loading', 'group' => 'labels'), + 'txt_nextLink' => array('title' => 'Next Image link', 'default' => 'next »', 'group' => 'labels'), + 'txt_prevLink' => array('title' => 'Previous Image link', 'default' => '« prev', 'group' => 'labels'), + 'txt_startSlideshow' => array('title' => 'Start Slideshow link', 'default' => 'start slideshow', 'group' => 'labels'), + 'txt_stopSlideshow' => array('title' => 'Stop Slideshow link', 'default' => 'stop slideshow', 'group' => 'labels'), + 'txt_numDisplayPrefix' => array('title' => 'Image number prefix (e.g. Image x of y)', 'default' => 'Image', 'group' => 'labels'), + 'txt_numDisplaySeparator' => array('title' => 'Image number separator (e.g. Image x of y)', 'default' => 'of', 'group' => 'labels') + ), + 'legacy' => array ( + 'header_activation', + 'header_enabled', + 'header_strings', + 'header_ui', + 'enabled_single' + ) + ); + + /* Instance members */ + + /** + * Options instance + * @var SLB_Options + */ + var $options = null; + + /** + * Fields + * @var SLB_Fields + */ + var $fields = null; + + /*-** Init **-*/ + + function SLB_Lightbox() { + $this->__construct(); + } + + function __construct() { + parent::__construct(); + $this->init(); + + //Setup options + $opt_theme =& $this->options_config['items']['theme']; + $opt_theme['default'] = $this->theme_default = $this->add_prefix($this->theme_default); + $opt_theme['options'] = $this->m('get_theme_options'); + + //Init objects + $this->fields =& new SLB_Fields(); + $this->options =& new SLB_Options('options', $this->options_config); + } + + function register_hooks() { + parent::register_hooks(); + + /* Admin */ + + //Init lightbox admin + add_action('admin_init', $this->m('admin_settings')); + //Enqueue header files (CSS/JS) + add_action('admin_enqueue_scripts', $this->m('admin_enqueue_files')); + //Reset Settings + add_action('admin_action_' . $this->add_prefix('reset'), $this->m('admin_reset')); + add_action('admin_notices', $this->m('admin_notices')); + //Plugin listing + add_filter('plugin_action_links_' . $this->util->get_plugin_base_name(), $this->m('admin_plugin_action_links'), 10, 4); + + /* Client-side */ + + //Init lightbox + add_action('wp_enqueue_scripts', $this->m('enqueue_files')); + add_action('wp_head', $this->m('client_init')); + add_filter('the_content', $this->m('activate_post_links'), 99); + + /* Themes */ + $this->util->add_action('init_themes', $this->m('init_default_themes')); + } + + function activate() { + //Set default options (if not yet set) + $this->options->reset(false); + $this->options->migrate(); + } + + /*-** Helpers **-*/ + + /** + * Checks whether lightbox is currently enabled/disabled + * @return bool TRUE if lightbox is currently enabled, FALSE otherwise + */ + function is_enabled($check_request = true) { + $ret = ( $this->options->get_value('enabled') ) ? true : false; + if ( $ret && $check_request ) { + $opt = ''; + //Determine option to check + if ( is_home() ) + $opt = 'home'; + elseif ( is_singular() ) { + $opt = ( is_page() ) ? 'page' : 'post'; + } + elseif ( is_archive() || is_search() ) + $opt = 'archive'; + //Check option + if ( !empty($opt) && ( $opt = 'enabled_' . $opt ) && $this->options->has($opt) ) { + $ret = ( $this->options->get_value($opt) ) ? true : false; + } + } + return $ret; + } + + /*-** Theme **-*/ + + /** + * Retrieve themes + * @uses do_action() Calls 'slb_init_themes' hook to allow plugins to register themes + * @uses $themes to return registered themes + * @return array Retrieved themes + */ + function get_themes() { + static $fetched = false; + if ( !$fetched ) { + $this->themes = array(); + $this->util->do_action('init_themes'); + $fetched = true; + } + return $this->themes; + } + + /** + * Retrieve theme + * @param string $name Name of theme to retrieve + * @uses theme_exists() to check for existence of theme + * @return array Theme data + */ + function get_theme($name = '') { + $name = strval($name); + //Default: Get current theme if no theme specified + if ( empty($name) ) { + $name = $this->options->get_value('theme'); + } + if ( !$this->theme_exists($name) ) + $name = $this->theme_default; + return $this->themes[$name]; + } + + /** + * Retrieve specific of theme data + * @uses get_theme() to retrieve theme data + * @param string $name Theme name + * @param string $field Theme field to retrieve + * @return mixed Field data + */ + function get_theme_data($name = '', $field) { + $theme = $this->get_theme($name); + return ( isset($theme[$field]) ) ? $theme[$field] : ''; + } + + /** + * Retrieve theme stylesheet URL + * @param string $name Theme name + * @uses get_theme_data() to retrieve theme data + * @return string Stylesheet URL + */ + function get_theme_style($name = '') { + return $this->get_theme_data($name, 'stylesheet_url'); + } + + /** + * Retrieve theme layout + * @uses get_theme_data() to retrieve theme data + * @param string $name Theme name + * @param bool $filter (optional) Filter layout based on user preferences + * @return string Theme layout HTML + */ + function get_theme_layout($name = '', $filter = true) { + $l = $this->get_theme_data($name, 'layout'); + //Filter + if ( !$this->options->get_value('enabled_caption') ) + $l = str_replace($this->get_theme_placeholder('dataCaption'), '', $l); + return $l; + } + + /** + * Check whether a theme exists + * @param string $name Theme to look for + * @uses get_themes() to intialize themes if not already performed + * @return bool TRUE if theme exists, FALSE otherwise + */ + function theme_exists($name) { + $this->get_themes(); + return ( isset($this->themes[trim(strval($name))]) ); + } + + /** + * Register lightbox theme + * @param string $name Unique theme name + * @param string $title Display name for theme + * @param string $stylesheet_url URL to stylesheet + * @param string $layout Layout HTML + * @uses $themes to store the registered theme + */ + function register_theme($name, $title, $stylesheet_url, $layout) { + if ( !is_array($this->themes) ) { + $this->themes = array(); + } + + //Validate parameters + $name = trim(strval($name)); + $title = trim(strval($title)); + $stylesheet_url = trim(strval($stylesheet_url)); + $layout = $this->format_theme_layout($layout); + + $defaults = array( + 'name' => '', + 'title' => '', + 'stylesheet_url' => '', + 'layout' => '' + ); + + //Add theme to array + $this->themes[$name] = wp_parse_args(compact(array_keys($defaults), $defaults)); + } + + /** + * Build theme placeholder + * @param string $name Placeholder name + * @return string Placeholder + */ + function get_theme_placeholder($name) { + return '{' . $name . '}'; + } + + /** + * Formats layout for usage in JS + * @param string $layout Layout to format + * @return string Formatted layout + */ + function format_theme_layout($layout = '') { + //Remove line breaks + $layout = str_replace(array("\r\n", "\n", "\r", "\t"), '', $layout); + + //Escape quotes + $layout = str_replace("'", "\'", $layout); + + //Return + return "'" . $layout . "'"; + } + + /** + * Add default themes + * @uses register_theme() to register the theme(s) + */ + function init_default_themes() { + $name = $this->theme_default; + $title = 'Default'; + $stylesheet_url = $this->util->get_file_url('css/lightbox.css'); + $layout = file_get_contents($this->util->normalize_path($this->util->get_path_base(), 'templates', 'default', 'layout.html')); + $this->register_theme($name, $title, $stylesheet_url, $layout); + //Testing: Additional themes + $this->register_theme('black', 'Black', $this->util->get_file_url('css/lb_black.css'), $layout); + } + + /*-** Frontend **-*/ + + /** + * Scans post content for image links and activates them + * + * Lightbox will not be activated for feeds + * @param $content + */ + function activate_post_links($content) { + //Check option + if ( ! is_feed() && $this->is_enabled() && $this->options->get_value('activate_links') ) { + $links = array(); + //Get all links on page + $rgx = "/\]+href=.*?\>/i"; + preg_match_all($rgx, $content, $links); + $links = $links[0]; + $domain = str_replace(array('http://', 'https://'), '', get_bloginfo('url')); + //Process links + if ( count($links) > 0 ) { + global $post; + $types = (object) array('img' => 'image', 'att' => 'attachment'); + $img_types = array('jpg', 'jpeg', 'gif', 'png'); + $rgx = "/\b(\w+.*?)=([\"'])(.*?)\\2(?:\s|$)/i"; + //Iterate through links & add lightbox if necessary + foreach ( $links as $link ) { + //Check if rel attribute exists + $link_new = $link; + //Parse link + $link_attr = substr($link_new, 2, strlen($link_new) - 3); + $attr_matches = $attr = array(); + preg_match_all($rgx, $link_attr, $attr_matches); + foreach ( $attr_matches[1] as $key => $val ) { + if ( isset($attr_matches[3][$key]) ) + $attr[trim($val)] = trim($attr_matches[3][$key]); + } + //Destroy parsing vars + unset($link_attr, $attr_matches); + + //Set default attributes + $attr = array_merge(array('rel' => '', 'href' => ''), $attr); + $h =& $attr['href']; + $r =& $attr['rel']; + + + //Stop processing link if lightbox attribute has already been set + $lb = 'lightbox'; + if ( empty($h) || '#' == $h || ( !empty($r) && ( strpos($r, $lb) !== false || strpos($r, $this->add_prefix('off')) !== false ) ) ) + continue; + //Determine link type + $type = false; + if ( in_array($this->util->get_file_extension($h), $img_types) ) + $type = $types->img; + elseif ( strpos($h, $domain) !== false && is_local_attachment($h) && ( $pid = url_to_postid($h) ) && wp_attachment_is_image($pid) ) + $type = $types->att; + if ( !$type ) { + continue; + } + + if ( $type == $types->att && !$this->options->get_value('activate_attachments') ) + continue; + + //Process link + if ( empty($r) ) + $r = array(); + else + $r = array($r); + + //Check if links should be grouped + if ( $this->options->get_value('group_links') ) { + $group = ( $this->options->get_value('group_post') ) ? $this->add_prefix($post->ID) : $this->get_prefix(); + $lb .= '[' . $group . ']'; + } + $r[] = $lb; + + //Type specific processing + switch ($type) { + case $types->att: + //Get attachment URL + $src = wp_get_attachment_url($pid); + if ( !empty($src) ) + $r[] = $this->add_prefix('src[' . $src . ']'); + break; + } + + //Convert rel attribute to string + $r = implode(' ', $r); + + $link_new = 'util->build_attribute_string($attr) . '>'; + //Insert modified link + $content = str_replace($link, $link_new, $content); + unset($h, $r); + } + } + } + return $content; + } + + /** + * Enqueue files in template head + */ + function enqueue_files() { + if ( ! $this->is_enabled() ) + return; + wp_enqueue_script($this->add_prefix('lib'), $this->util->get_file_url('js/lib.js'), array('jquery'), $this->util->get_plugin_version()); + wp_enqueue_style($this->add_prefix('style'), $this->get_theme_style(), array(), $this->util->get_plugin_version()); + } + + /** + * Sets options/settings to initialize lightbox functionality on page load + * @return void + */ + function client_init() { + if ( ! $this->is_enabled() ) + return; + + $options = array(); + $out = array(); + $out['script_start'] = ''; + $js_code = array(); + //Get options + $options = array( + 'validateLinks' => $this->options->get_value('validate_links'), + 'autoPlay' => $this->options->get_value('autostart'), + 'slideTime' => $this->options->get_value('duration'), + 'loop' => $this->options->get_value('loop'), + 'overlayOpacity' => $this->options->get_value('overlay_opacity'), + 'animate' => $this->options->get_value('animate'), + 'captionEnabled' => $this->options->get_value('enabled_caption'), + 'captionSrc' => $this->options->get_value('caption_src'), + 'layout' => $this->get_theme_layout(), + 'altsrc' => $this->add_prefix('src') + ); + $lb_obj = array(); + foreach ($options as $option => $val) { + if ( is_bool($val) ) + $val = ( $val ) ? 'true' : 'false'; + elseif ( is_string($val) && "'" != $val[0] ) + $val = "'" . $val . "'"; + $lb_obj[] = "'{$option}':{$val}"; + } + //Load UI Strings + if ( ($strings = $this->build_strings()) && !empty($strings) ) + $lb_obj[] = $strings; + $js_code[] = 'SLB.initialize({' . implode(',', $lb_obj) . '});'; + echo $out['script_start'] . implode('', $js_code) . $out['script_end']; + } + + /** + * Build JS object of UI strings when initializing lightbox + * @return string JS object of UI strings + */ + function build_strings() { + $ret = ''; + $prefix = 'txt_'; + $opt_strings = array_filter(array_keys($this->options->get_items()), create_function('$opt', 'return ( strpos($opt, "' . $prefix . '") === 0 );')); + if ( $opt_strings ) { + $strings = array(); + foreach ( $opt_strings as $key ) { + $name = substr($key, strlen($prefix)); + $strings[] = "'" . $name . "':'" . $this->options->get_value($key) . "'"; + } + $ret = "'strings':{" . implode(',', $strings) . "}"; + } + return $ret; + } + + /*-** Admin **-*/ + + /** + * Adds custom links below plugin on plugin listing page + * @param $actions + * @param $plugin_file + * @param $plugin_data + * @param $context + */ + function admin_plugin_action_links($actions, $plugin_file, $plugin_data, $context) { + //Add link to settings (only if active) + if ( is_plugin_active($this->util->get_plugin_base_name()) ) { + $settings = __('Settings'); + $reset = __('Reset'); + $reset_confirm = "'" . __('Are you sure you want to reset your settings?') . "'"; + $action = $this->add_prefix('reset'); + $reset_link = wp_nonce_url(add_query_arg('action', $action, remove_query_arg(array($this->add_prefix('action'), 'action'), $_SERVER['REQUEST_URI'])), $action); + array_unshift($actions, '' . $settings . ''); + array_splice($actions, 1, 0, '' . $reset . ''); + } + return $actions; + } + + /** + * Reset plugin settings + * Redirects to referring page upon completion + */ + function admin_reset() { + //Validate user + if ( ! current_user_can('activate_plugins') || ! check_admin_referer($this->add_prefix('reset')) ) + wp_die(__('You do not have sufficient permissions to manage plugins for this blog.')); + $action = 'reset'; + if ( isset($_REQUEST['action']) && $this->add_prefix($action) == $_REQUEST['action'] ) { + //Reset settings + $this->options->reset(true); + $uri = remove_query_arg(array('_wpnonce', 'action'), add_query_arg(array($this->add_prefix('action') => $action), $_SERVER['REQUEST_URI'])); + //Redirect user + wp_redirect($uri); + exit; + } + } + + /** + * Displays notices for admin operations + */ + function admin_notices() { + if ( is_admin() && isset($_REQUEST[$this->add_prefix('action')]) ) { + $action = $_REQUEST[$this->add_prefix('action')]; + $msg = null; + if ( $action ) { + switch ( $action ) { + case 'reset': + $msg = "Simple Lightbox's settings have been reset"; + break; + } + if ( ! is_null($msg) ) { + ?> +

+ Media Admin menu + * @todo Move appropriate code to options class + */ + function admin_settings() { + $page = $this->options_admin_page; + $form = $this->options_admin_form; + $curr = basename($_SERVER['SCRIPT_NAME']); + if ( $curr != $page && $curr != $form ) { + return; + } + + $page = 'media'; + $section = $this->get_prefix(); + //Section + add_settings_section($section, '' . __('Lightbox Settings') . '', $this->m('admin_section'), $page); + //Register settings container + register_setting($page, $this->add_prefix('options'), $this->options->m('validate')); + } + + /** + * Enqueues header files for admin pages + * @todo Separate and move options CSS to options class + */ + function admin_enqueue_files() { + //Enqueue custom CSS for options page + if ( is_admin() && basename($_SERVER['SCRIPT_NAME']) == $this->options_admin_page ) { + wp_enqueue_style($this->add_prefix('admin'), $this->util->get_file_url('css/admin.css'), array(), $this->util->get_plugin_version()); + } + } + + /** + * Get ID of settings section on admin page + * @return string ID of settings section + * @todo Eval for moving to options class + */ + function admin_get_settings_section() { + return $this->add_prefix('settings'); + } + + /** + * Placeholder function for lightbox admin settings + * Required because setting init function requires a callback + * @todo Evaluate for moving to options class + */ + function admin_section() { + $this->options->build(); + } + + /* Custom fields */ + + function get_theme_options() { + //Get themes + $themes = $this->get_themes(); + + //Pop out default theme + $theme_default = $themes[$this->theme_default]; + unset($themes[$this->theme_default]); + + //Sort themes by title + uasort($themes, create_function('$a,$b', 'return strcmp($a[\'title\'], $b[\'title\']);')); + + //Insert default theme at top of array + $themes = array($this->theme_default => $theme_default) + $themes; + + //Build options + foreach ( $themes as $name => $props ) { + $themes[$name] = $props['title']; + } + return $themes; + } +} + +?> diff --git a/src/wp-content/plugins/simple-lightbox/readme.txt b/src/wp-content/plugins/simple-lightbox/readme.txt new file mode 100644 index 00000000..4a2d355b --- /dev/null +++ b/src/wp-content/plugins/simple-lightbox/readme.txt @@ -0,0 +1,150 @@ +=== Plugin Name === +Contributors: Archetyped +Donate link: http://archetyped.com/tools/simple-lightbox/#donate +Tags: lightbox, gallery, photography, images, theme, template, style +Requires at least: 3.1.2 +Tested up to: 3.2 +Stable tag: trunk + +A simple, themeable, and customizable Lightbox for Wordpress + +== Description == +Simple Lightbox is a very simple and customizable lightbox that is easy to add to your Wordpress website. It also [supports themes](http://archetyped.com/lab/slb-registering-themes/), so it can be fully integrated with your site's theme. + +### BETA NOTES +The current release is a beta version. Please test and [provide feedback on the beta release page](http://archetyped.com/lab/slb-1-5-5-beta/). +Main changes + +#### Beta 5 +* Update: Additional WordPress 3.2 support (Gallery) +* Fix: Improved options migration from old versions (Hutchison Migration) + +#### Beta 4 +* Add: Support for WordPress 3.2 +* Add: Support for links added after page load (e.g. via AJAX, etc.) +* Add: Admin option to enable/disable attachment links +* Optimize: Improved compatibility for older versions of PHP + +#### Beta 3 +* Add: Support for image attachment links +* Optimize: Improved compatibility for older versions of PHP +* Optimize: Internal optimizations + +#### Beta 2 +* Fix: Debug code removed (Fatal Seb) +* Update: Improved URL handling +* Update: Cache-management for enqueued files + +#### Beta 1 +* Update: Options management overhaul +* Fix: XHTML Validation (Hajo Validation) + +#### Customization +Options for customizing the lightbox behavior are located in the **Settings > Media** admin menu in the **Lightbox Settings** section (or just click the **Settings** link below the plugin's name when viewing the list of installed plugins) + +* **New: Link Validation** (Optional) +* **New: Keyboard Navigation** +* **New: Show/Hide Lightbox Caption** +* Theme Support +* Customizable UI Text +* Enable/Disable Lightbox Functionality (Default: Enabled) +* Enable Lightbox depending on Page Type (Home, Pages, Archive, etc.) +* Automatically activate lightbox for links to images on page (no need to add `rel="lightbox"` attribute to link) +* Group automatically-activated links (play as a slideshow) +* Group image links by Post (separate slideshow for each Post on page) +* Enable/Disable Lightbox resizing animation +* Automatically Start Slideshow (Default: Enabled) +* Slide Duration (Seconds) (Default: 6) +* Loop through images (Default: Enabled) +* Overlay Opacity (0 - 1) (Default: 0.8) + +#### Usage +* The necessary Javascript and CSS files will be automatically added to the page as long as `wp_head()` is called in the theme +* That's it! + +== Installation == + +1. Verify that your theme uses the `wp_head()` template tag (this is where the necessary files will be added to your theme output) +1. Let plugin automatically add lightbox functionality for links to images or manually add `rel="lightbox"` to any image links that you want to be displayed in a lightbox + +== Upgrade Notice == + +No upgrade notices + +== Frequently Asked Questions == + +Post your questions and comments on [Simple Lightbox's beta release page](http://archetyped.com/lab/slb-1-5-5-beta/) + +== Screenshots == + +1. Lightbox Customization Options +2. Customized UI Text + +== Changelog == += 1.5.4 = +* Add: Optional Link validation +* Add: Keyboard Navigation +* Add: Option to enable/disable image caption +* Add: `rel` attribute supported again +* Add: Use `slb_off` in link's `rel` attribute to disable automatic activation for link +* Fix: HTTPS compatibility (Jürgen Protocol) +* Fix: Enabling SLB on Pages issue +* Fix: Zmanu is_single +* Fix: Image order is sometimes incorrect +* Optimize: Filter double clicks +* Optimize: Separate options to enable/disable SLB on Posts and Pages +* Optimize: Better grouping support + += 1.5.3 = +* Fix: Caption may not display under certain circumstances (Caption Erin) +* Fix: Images not grouped when "separate by post" option is activated (Logical Ross) +* Update: Lightbox will not be activated for links that already have `rel` attribute set + += 1.5.2 = +* Fix: Slideshow loops out of control (Mirage of Wallentin) +* Fix: Lightbox fails when group by posts disabled (Lange Find) +* Add: Option to use the image's URI as caption when link title not set (Under UI options) + += 1.5.1 = +* Add: WP Gallery support +* Fix: Navigation hidden when only one image +* Fix: Use user-defined UI text + += 1.5 = +* Add: Theme support +* Optimize: Javascript cleanup and file size reductions +* Optimize: CSS cleanup + += 1.4 = +* Update: Integrated with jQuery +* Optimize: Javascript filesize 9x smaller +* Add: Close lightbox by clicking to left/right outside of image (an oft-requested feature) + += 1.3.2 = +* Add: Option to enable/disable lightbox resizing animation (thanks Maria!) + += 1.3.1 = +* Update: Utilities code (internal) + += 1.3 = +* Add: Customizable UI label text (close, next, and prev button images can be replaced in `images` directory) +* Add: Group image links by Post (separate slideshow for each post) +* Add: Reset settings link on plugin listings page +* Optimize: Organized settings page + += 1.2.1 = +* Fixed: Image title given higher precedence than Image alt (more compatible w/WP workflow) + += 1.2 = +* Added: Option to group automatically activated links +* Optimized: Lightbox caption retrieval + += 1.1 = +* Added: Enable/disable lightbox functionality by page type (Home, Pages/Posts, Archive, etc.) +* Added: Automatically activate lightbox functionality for image links +* Added: Link to settings menu on plugin listing page +* Optimized: Options menu field building +* Optimized: Loading of default values for plugin options +* Optimized: General code optimizations += 1.0 = +* Initial release diff --git a/src/wp-content/plugins/simple-lightbox/screenshot-1.gif b/src/wp-content/plugins/simple-lightbox/screenshot-1.gif new file mode 100644 index 00000000..979af6e4 Binary files /dev/null and b/src/wp-content/plugins/simple-lightbox/screenshot-1.gif differ diff --git a/src/wp-content/plugins/simple-lightbox/screenshot-2.gif b/src/wp-content/plugins/simple-lightbox/screenshot-2.gif new file mode 100644 index 00000000..36cddfcc Binary files /dev/null and b/src/wp-content/plugins/simple-lightbox/screenshot-2.gif differ diff --git a/src/wp-content/plugins/simple-lightbox/templates/default/layout.html b/src/wp-content/plugins/simple-lightbox/templates/default/layout.html new file mode 100644 index 00000000..efc6f047 --- /dev/null +++ b/src/wp-content/plugins/simple-lightbox/templates/default/layout.html @@ -0,0 +1,28 @@ +
+
+ {slbContent} + +
+ {slbLoading} +
+
+
+
+
+
+ {dataCaption} + {dataNumber} + + {navPrev} + {navNext} + {navSlideControl} + +
+
+ {slbClose} +
+
+
\ No newline at end of file