commit 523ccac38e2a897e5566024efe8dbe53b04671fe Author: Bruno21 Date: Tue May 3 09:37:05 2022 +0200 Yuzu Theme from meowapps.com diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..aef8443 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "liveServer.settings.port": 5501 +} \ No newline at end of file diff --git a/404.php b/404.php new file mode 100644 index 0000000..6a176d5 --- /dev/null +++ b/404.php @@ -0,0 +1,60 @@ + + +
+
+ +
+ + +
+

+ + + +
+

+
    + 'count', + 'order' => 'DESC', + 'show_count' => 1, + 'title_li' => '', + 'number' => 10, + ) ); + ?> +
+
+ + ' . sprintf( esc_html__( 'Try looking in the monthly archives. %1$s', 'yuzu' ), convert_smilies( ':)' ) ) . '

'; + the_widget( 'WP_Widget_Archives', 'dropdown=1', "after_title=$yuzu_archive_content" ); + + the_widget( 'WP_Widget_Tag_Cloud' ); + ?> + +
+
+ +
+
+ + + 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. + + {description} + Copyright (C) {year} {fullname} + + 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. + + {signature of Ty Coon}, 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/archive.php b/archive.php new file mode 100644 index 0000000..5b40c15 --- /dev/null +++ b/archive.php @@ -0,0 +1,75 @@ + + +
+
+ +
+ +
+ +
+ '; + require get_template_directory() . '/components/article-cards/large-article-card.php'; + echo '
'; + $count++; + break; + case 1: + echo '
'; + require get_template_directory() . '/components/article-cards/medium-article-card.php'; + $count++; + break; + case 2: + require get_template_directory() . '/components/article-cards/medium-article-card.php'; + echo '
'; + $count++; + break; + case 3: + echo '
'; + require get_template_directory() . '/components/article-cards/small-article-card.php'; + $count++; + break; + case 4: + require get_template_directory() . '/components/article-cards/small-article-card.php'; + $count++; + break; + case 5: + require get_template_directory() . '/components/article-cards/small-article-card.php'; + echo '
'; + $count = 0; + break; + } + + + endwhile; + + the_posts_navigation(); + + else : + + _e('No posts found!', 'yuzu'); + + endif; + ?> +
+ + + + + Arrow Up Icon of a arrow pointing up \ No newline at end of file diff --git a/assets/icons/inline-camera.svg.php b/assets/icons/inline-camera.svg.php new file mode 100644 index 0000000..5142fc2 --- /dev/null +++ b/assets/icons/inline-camera.svg.php @@ -0,0 +1 @@ + Camera Icon of a photographic camera \ No newline at end of file diff --git a/assets/icons/inline-close.svg.php b/assets/icons/inline-close.svg.php new file mode 100644 index 0000000..fed4a06 --- /dev/null +++ b/assets/icons/inline-close.svg.php @@ -0,0 +1 @@ + Close Icon of a cross (x) \ No newline at end of file diff --git a/assets/icons/inline-hamburger.svg.php b/assets/icons/inline-hamburger.svg.php new file mode 100644 index 0000000..7b4ebac --- /dev/null +++ b/assets/icons/inline-hamburger.svg.php @@ -0,0 +1 @@ + Menu Icon of a menu made of three horizontal lines \ No newline at end of file diff --git a/assets/icons/inline-search.svg.php b/assets/icons/inline-search.svg.php new file mode 100644 index 0000000..3069301 --- /dev/null +++ b/assets/icons/inline-search.svg.php @@ -0,0 +1 @@ + Search Icon of a magnifying glass \ No newline at end of file diff --git a/assets/js/main.js b/assets/js/main.js new file mode 100644 index 0000000..f7036dc --- /dev/null +++ b/assets/js/main.js @@ -0,0 +1,93 @@ +jQuery(document).ready(function ($) { + + // Top Search Bar Opening/Closing + $('.open-top-bar-search').on('click', function() { + $(this).hide(); + $('.close-top-bar-search').show(); + $('.top-search-bar-container').addClass('opened'); + }); + + $('.close-top-bar-search').on('click', function () { + $(this).hide(); + $('.open-top-bar-search').show(); + $('.top-search-bar-container').removeClass('opened'); + }); + + + // Blog cards size equalizer + function equalizeArticleCardsHeights() { + if(php_vars.enable_posts_height_equalizer) { + $('.articles-list .row').each(function (index) { + if ($(this).css('display') == "inline") { + $('.article-card-container .article-meta').css('height', 'auto'); + } else { + var max_height = 0; + $(this).find('.article-card-container').each(function () { + var height = $(this).find('.article-meta').outerHeight(); + if (height > max_height) { + max_height = height; + } + }); + $(this).find('.article-card-container').find('.article-meta').css('height', max_height + 'px') + } + }); + } + } + + equalizeArticleCardsHeights(); + + // Rewrite Search Widget + $('.widget_search .search-field').attr('type', 'text'); + $('.widget_search .search-submit').remove(); + $('.widget_search .search-form').append(''); + + // Rewrite Meow Search Block + $('.mwt-search .mwt-search').attr('type', 'text'); + $('.mwt-search .search-submit').remove(); + $('.mwt-search form.search-form').append(''); + + // Mobile Navigation Init + $('.mobile-navigation').css('margin-top', - $('.mobile-navigation').outerHeight() + 'px') + // Mobile Navigation Toggle + $('.mobile-navigation-toggle').on('click', function() { + if($(this).hasClass('active')) { + $('.mobile-navigation').animate({ marginTop: - $('.mobile-navigation').outerHeight() + 'px'}, 200); + $(this).removeClass('active') + } else { + $('.mobile-navigation').animate({ marginTop: 0 }, 200); + $(this).addClass('active') + } + }) + + // On window resize + var resizeTimer + $(window).on('resize', function() { + clearTimeout(resizeTimer); + resizeTimer = setTimeout(function () { + $('.article-card-container .article-meta').css('height', 'auto'); + equalizeArticleCardsHeights(); + }, 250); + }) + + // On infinite scroll loading more posts + $(document.body).on('post-load', function () { + equalizeArticleCardsHeights(); + }); + + // Scroll back to top button + if ($('.scroll-back-to-top-btn').length > -1) { + $(window).on('scroll', function() { + var scrollTop = $(this).scrollTop(); + if(scrollTop > 100) { + $('.scroll-back-to-top-btn').addClass('visible'); + } + if(scrollTop <= 100) { + $('.scroll-back-to-top-btn').removeClass('visible'); + } + }); + + $('.scroll-back-to-top-btn').on('click', function() { + $("html, body").animate({ scrollTop: 0 }, 300); + }) + } +}); \ No newline at end of file diff --git a/assets/less/_article-cards.less b/assets/less/_article-cards.less new file mode 100644 index 0000000..7418f70 --- /dev/null +++ b/assets/less/_article-cards.less @@ -0,0 +1,193 @@ +// main: style.less + + +@media screen and (max-width: @tablet) { + .row { + display: inline; + } +} + +.article-card-container { + display: inline-block; + padding: 30px 15px; + box-sizing: border-box; + font-size: 16px; + + .article-card { + position: relative; + width: 100%; + background: @card_bg; + background: var(--card_bg); + box-shadow: @shadow; + box-shadow: var(--shadow); + color: var(--card_color); + transition: .2s; + + &:hover { + box-shadow: @deeper_shadow; + box-shadow: var(--deeper_shadow); + transition: .3s; + } + + .article-featured-image { + display: block; + background-size: cover; + background-position: center; + } + + .article-meta { + + .article-categories { + + .article-category { + display: inline-block; + text-transform: uppercase; + font-size: 14px; + color: @card_color; + color: var(--card_color); + opacity: .3; + } + } + + .article-title { + display: block; + font-size: 28px; + font-weight: 400; + margin-top: 0; + margin-bottom: 20px; + color: @card_color; + color: var(--card_color); + } + + .article-excerpt { + line-height: 160%; + opacity: .6; + } + + .read-more-btn { + display: inline-block; + color: @read_more_btn_color; + color: var(--read_more_btn_color); + background: @read_more_btn_bg; + background: var(--read_more_btn_bg); + padding: 15px 0; + width: 140px; + text-align: center; + line-height: 22px; + position: absolute; + bottom: 0; + left: 50%; + margin-left: -70px; + margin-bottom: -26px; + box-shadow: @shadow; + box-shadow: var(--shadow); + border-radius: 25px; + transition: .2s; + + &:hover { + box-shadow: @deeper_shadow; + box-shadow: var(--deeper_shadow); + transition: .3s; + } + } + } + } + + &.large { + width: 100%; + + .article-card { + display: flex; + width: 100%; + + .article-featured-image { + display: flex; + width: 60%; + padding-bottom: 40%; + } + + .article-meta { + position: relative; + display: flex; + flex: 1; + flex-direction: column; + justify-content: center; + padding: 30px; + box-sizing: border-box; + } + } + + @media screen and (max-width: @tablet) { + width: 50%; + + .article-card { + display: block; + + .article-featured-image { + width: 100%; + padding-bottom: 66.66%; + } + + .article-meta { + padding: 30px; + padding-bottom: 90px; + box-sizing: border-box; + } + } + } + + @media screen and (max-width: @big_phone) { + width: 100%; + } + } + + &.medium { + width: 50%; + vertical-align: top; + + .article-card { + + .article-featured-image { + width: 100%; + padding-bottom: 66.66%; + } + + .article-meta { + padding: 30px; + padding-bottom: 90px; + box-sizing: border-box; + } + } + + @media screen and (max-width: @big_phone) { + width: 100%; + } + } + + &.small { + width: 33.33%; + vertical-align: top; + + .article-card { + + .article-featured-image { + width: 100%; + padding-bottom: 66.66%; + } + + .article-meta { + padding: 30px; + padding-bottom: 90px; + box-sizing: border-box; + } + } + + @media screen and (max-width: @tablet) { + width: 50%; + } + + @media screen and (max-width: @big_phone) { + width: 100%; + } + } +} \ No newline at end of file diff --git a/assets/less/_blog.less b/assets/less/_blog.less new file mode 100644 index 0000000..64e505c --- /dev/null +++ b/assets/less/_blog.less @@ -0,0 +1,310 @@ +// main: style.less + +.articles-list { + font-size: 0; + width: 100%; + + .posts-navigation { + font-size: 16px; + margin-top: 60px; + + .nav-links { + + .nav-previous, .nav-next { + width: auto; + display: inline-block; + + a { + margin: 10px 4px; + display: inline-block; + border-radius: 30px; + //text-transform: uppercase; + font-size: 16px; + padding: 10px 20px; + background: @card_bg; + background: var(--card_bg); + color: @card_color; + color: var(--card_color); + box-shadow: @shadow; + box-shadow: var(--shadow); + transition: .2s; + + &:hover { + box-shadow: @deeper_shadow; + box-shadow: var(--deeper_shadow); + transition: .2s; + } + } + } + } + } +} + +.single-article, .single-page { + + .entry-content { + font-size: 18px; + line-height: 180%; + color: @body_color; + color: var(--body_color); + padding-bottom: 60px; + + p { + opacity: .8; + } + + blockquote { + + p { + padding-left: 20px; + border-left: 2px solid @body_color; + border-left: 2px solid var(--body_color); + } + } + + li { + opacity: .8; + } + } +} + +.single-article { + + .related-posts { + width: 100%; + display: flex; + + @media screen and (max-width: @big_phone) { + display: block; + } + + .previous-post, .next-post { + display: flex; + position: relative; + height: 300px; + flex: 1; + align-items: center; + color: white !important; + + @media screen and (max-width: @big_phone) { + height: 250px; + } + + .background { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-size: cover; + background-position: center; + } + + + .filter { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: #000; + opacity: .6; + } + + .content { + position: relative; + padding: 40px; + box-sizing: border-box; + + .label { + text-transform: uppercase; + font-weight: 400; + opacity: .6; + } + + h3 { + margin: 0; + font-weight: 400; + font-size: 38px; + + @media screen and (max-width: @big_phone) { + font-size: 32px; + } + } + } + } + } +} + +.comments-section { + background: @body_bg; + background: var(--body_bg); + color: @body_color; + color: var(--body_color); + padding-top: 60px; + + #disqus_thread { + width: 90%; + max-width: 960px; + margin: auto; + } + + .comment-reply-title { + text-align: center; + } + + .comment-form { + width: 90%; + max-width: 960px; + margin: auto; + text-align: center; + padding-bottom: 50px; + + @media screen and (max-width: @big_phone) { + padding-bottom: 25px; + } + + textarea { + display: block; + padding: 10px; + border-radius: 0; + background: @comment_form_bg; + background: var(--comment_form_bg); + color: @comment_form_color; + color: var(--comment_form_color); + border: 1px solid rgba(0,0,0,.4); + } + + .submit-button { + display: none; + } + + .comment-form-comment { + margin: 0; + } + + .user-infos { + display: flex; + + input { + flex: 1; + border: 1px solid rgba(0,0,0,.4); + border-top: none; + border-radius: 0; + padding: 10px; + background: @comment_form_bg; + background: var(--comment_form_bg); + color: @comment_form_color; + color: var(--comment_form_color); + + &:first-of-type { + border-right: none; + } + + &:last-of-type { + border-left: none; + } + } + } + + .form-submit { + width: 100%; + text-align: center; + + input { + display: inline-block; + background: @post_comment_btn_bg; + background: var(--post_comment_btn_bg); + border: 2px solid rgba(0,0,0,0); + color: @post_comment_btn_color; + color: var(--post_comment_btn_color); + box-shadow: @shadow; + box-shadow: var(--shadow); + font-size: 16px; + width: 100%; + max-width: 220px; + padding: 10px 20px; + border-radius: 25px; + cursor: pointer; + margin-top: 20px; + transition: .1s; + + &:hover { + box-shadow: @deeper_shadow; + box-shadow: var(--deeper_shadow); + transition: .1s; + } + } + } + } + + .comments-list-container { + padding: 60px 10px; + + @media screen and (max-width: @big_phone) { + padding: 30px 10px; + } + + ol.comment-list { + padding: 0; + margin: 0; + width: 100%; + max-width: 960px; + margin: auto; + list-style: none; + + li.comment { + display: block; + background: @comment_bg; + background: var(--comment_bg); + color: @comment_color; + color: var(--comment_color); + padding: 20px; + box-sizing: border-box; + box-shadow: 0 2px 4px rgba(0,0,0,.2); + margin: 30px 0; + + + &.bypostauthor { + border-left: 4px solid @comment_color; + border-left: 4px solid var(--comment_color); + } + + .comment-header { + display: flex; + align-items: center; + + .comment-author-profil-picture { + img { + border-radius: 50%; + } + } + + .comment-meta { + padding-left: 20px; + margin-top: -5px; + + .author-name { + font-size: 18px; + } + + .posted-on { + font-size: 13px; + } + } + } + } + + ol.children { + padding: 0; + margin: 0; + margin-left: 30px; + list-style: none; + + li.comment { + margin-top: 0; + } + } + } + } +} \ No newline at end of file diff --git a/assets/less/_custom-properties.less b/assets/less/_custom-properties.less new file mode 100644 index 0000000..d705595 --- /dev/null +++ b/assets/less/_custom-properties.less @@ -0,0 +1,71 @@ +// out: ../css/custom-properties.css + +body { + + // SHADOW + --shadow: 0px 2px 4px rgba(0,0,0,.1); + --deeper_shadow: 0px 2px 8px rgba(0,0,0,.15); + // FONTS + --lato: 'Lato', sans-serif; + --fjalla: 'Fjalla One', sans-serif; + + &.light-theme { + // COLORS + --top_bar_color: #2E3B4F; + --body_color: #2E3B4F; + --footer_color: #2E3B4F; + --card_color: #2E3B4F; + --link_color: #4B828E; + --link_hover_color: darken(#4B828E, 10%); + --tag_color: #4B828E; + --tag_hover_color: darken(#4B828E, 10%); + --search_widget_color: #2E3B4F; + --read_more_btn_color: #2E3B4F; + --comment_form_color: #2E3B4F; + --comment_color: #2E3B4F; + --post_comment_btn_color: #2E3B4F; + // BACKGROUNDS + --top_bar_bg: #FFF; + --body_bg: #FAFBFB; + --very_opaque_header_bg: linear-gradient(to top, rgba(250, 251, 251, 1), rgba(250, 251, 251, 0.9)); + --opaque_header_bg: linear-gradient(to top, rgba(250, 251, 251, 1), rgba(250, 251, 251, 0.6)); + --less_opaque_header_bg: linear-gradient(to top, rgba(250, 251, 251, 1), rgba(250, 251, 251, 0.4)); + --footer_bg: #FFF; + --card_bg: #FFF; + --search_widget_bg: #f5f4f4; + --read_more_btn_bg: #F5F5F5; + --comment_form_bg: #FFF; + --comment_bg: #FFF; + --post_comment_btn_bg: #FFF; + } + + &.dark-theme { + // COLORS + --top_bar_color: #F7F9FE; + --body_color: #F7F9FE; + --footer_color: #F7F9FE; + --card_color: #2E3B4F; + --link_color: #6db1c0; + --link_hover_color: darken(#6db1c0, 10%); + --tag_color: #6db1c0; + --tag_hover_color: darken(#6db1c0, 10%); + --search_widget_color: #F7F9FE; + --read_more_btn_color: #F7F9FE; + --comment_form_color: #2E3B4F; + --comment_color: #2E3B4F; + --post_comment_btn_color: #2E3B4F; + // BACKGROUNDS + --top_bar_bg: #232730; + --body_bg: #1d2027; + --very_opaque_header_bg: linear-gradient(to top, rgba(29, 32, 39, 1), rgba(29, 32, 39, 0.9)); + --opaque_header_bg: linear-gradient(to top, rgba(29, 32, 39, 1), rgba(29, 32, 39, 0.6)); + --less_opaque_header_bg: linear-gradient(to top, rgba(29, 32, 39, 1), rgba(29, 32, 39, 0.4)); + --footer_bg: #232730; + --card_bg: #FFF; + --search_widget_bg: #15181d; + --read_more_btn_bg: rgb(56, 67, 90); + --comment_form_bg: #FFF; + --comment_bg: #FFF; + --post_comment_btn_bg: #FFF; + } +} \ No newline at end of file diff --git a/assets/less/_footer.less b/assets/less/_footer.less new file mode 100644 index 0000000..3e4eef4 --- /dev/null +++ b/assets/less/_footer.less @@ -0,0 +1,149 @@ +// main: style.less + +.site-footer { + width: 100%; + padding: 60px 0; + background: @footer_bg; + background: var(--footer_bg); + color: @footer_color; + color: var(--footer_color); + box-shadow: @shadow; + box-shadow: var(--shadow); + + .widgets-area { + width: 90%; + max-width: 1260px; + margin: auto; + display: flex; + + @media screen and (max-width: @tablet) { + display: block; + width: 100%; + } + + .widgets-column { + flex: 1; + padding: 0px 20px; + box-sizing: border-box; + + .widget-title { + font-weight: 400; + font-size: 22px; + //font-family: var(--fjalla); + } + + ul { + margin: 0; + padding: 0; + + li { + list-style: none; + } + } + + .tagcloud { + + a { + font-size: 16px !important; + color: @tag_color; + color: var(--tag_color); + border: 1px solid @tag_color; + border: 1px solid var(--tag_color); + padding: 5px 8px; + line-height: 38px; + white-space: nowrap; + + &:hover { + color: @tag_hover_color; + color: var(--tag_hover_color); + border: 1px solid @tag_hover_color; + border: 1px solid var(--tag_hover_color); + } + } + } + + .widget_search { + + .search-form { + position: relative; + + .search-field { + width: 100%; + border-radius: 30px; + line-height: 20px; + padding: 10px 20px; + border: none; + outline: none; + color: @search_widget_color; + color: var(--search_widget_color); + background: @search_widget_bg; + background: var(--search_widget_bg); + transition: .1s; + + &:focus { + box-shadow: @shadow; + box-shadow: var(--shadow); + transition: .1s; + } + } + + svg { + position: absolute; + top: 7px; + right: 15px; + stroke: @search_widget_color; + stroke: var(--search_widget_color); + cursor: pointer; + } + + .hidden-submit { + display: none; + } + } + } + } + } + + .copyright-area { + text-align: center; + font-size: 14px; + opacity: .6; + } +} + +.scroll-back-to-top-btn { + position: fixed; + bottom: 20px; + right: 20px; + background: @card_bg; + background: var(--card_bg); + border-radius: 6px; + width: 50px; + height: 50px; + box-shadow: @shadow; + box-shadow: var(--shadow); + transition: .1s; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + visibility: hidden; + opacity: 0; + + svg { + stroke: @card_color; + stroke: var(--card_color); + } + + &:hover { + box-shadow: @deeper_shadow; + box-shadow: var(--deeper_shadow); + transition: .1s; + } + + &.visible { + visibility: visible; + opacity: 1; + transition: .3s; + } +} \ No newline at end of file diff --git a/assets/less/_general-elements.less b/assets/less/_general-elements.less new file mode 100644 index 0000000..b8c3175 --- /dev/null +++ b/assets/less/_general-elements.less @@ -0,0 +1,52 @@ +// main: style.less + +html, body { + margin: 0; + background: @body_bg; + background: var(--body_bg); +} + +.fullwidth-container, .super-large-container, .large-container, .medium-container { + &.top-and-bottom-margin { + margin: 60px auto; + } +} + +.fullwidth-container { + width: 100%; +} + +.super-large-container { + width: 95%; + max-width: 1260px; + margin: auto; +} + +.large-container { + width: 95%; + max-width: 960px; + margin: auto; +} + +.medium-container { + position: relative; + width: 95%; + max-width: 660px; + margin: auto; +} + +a { + color: @link_color; + color: var(--link_color); + text-decoration: none; + + &:visited, &:focus { + color: @link_color; + color: var(--link_color); + } + + &:hover { + color: @link_hover_color; + color: var(--link_hover_color); + } +} \ No newline at end of file diff --git a/assets/less/_gutenberg.less b/assets/less/_gutenberg.less new file mode 100644 index 0000000..713b28e --- /dev/null +++ b/assets/less/_gutenberg.less @@ -0,0 +1,26 @@ +// main: style.less + +.entry-content { + > *:not(.alignfull), > *:not(.alignwide) { + width: 90%; + max-width: 960px; + margin-left: auto !important; + margin-right: auto !important; + } + + .alignfull { + width: 100%; + max-width: 100%; + } + + .alignwide { + max-width: 1160px; + } +} + +.wp-block-cover { + p { + margin: 0; + opacity: 1 !important; + } +} \ No newline at end of file diff --git a/assets/less/_header.less b/assets/less/_header.less new file mode 100644 index 0000000..1910e31 --- /dev/null +++ b/assets/less/_header.less @@ -0,0 +1,139 @@ +// main: style.less + +.article-header { + text-align: center; + margin: 120px auto; + color: @body_color; + color: var(--body_color); + + @media screen and (max-width: @phone) { + margin: 70px auto; + } + + .article-categories { + margin-bottom: 10px; + + .article-category { + display: inline-block; + text-transform: uppercase; + font-size: 14px; + opacity: .3; + color: @body_color; + color: var(--body_color); + transition: .1s; + + &:hover { + opacity: .6; + transition: .1s; + } + } + } + + .article-title { + font-size: 48px; + line-height: 160%; + font-weight: 400; + margin-top: 0; + margin-bottom: 20px; + + @media screen and (max-width: @phone) { + font-size: 42px; + line-height: 140%; + } + } + + .article-meta { + opacity: 1; + color: @body_color; + color: var(--body_color); + + .author-picture { + display: inline-block; + width: 40px; + height: 40px; + border-radius: 50%; + background-size: cover; + background-position: center; + vertical-align: middle; + margin-right: 5px; + } + } +} + +.single-article { + .article-featured-image { + text-align: center; + margin-bottom: 60px; + + img { + max-width: 100%; + } + } +} + +.page-header { + text-align: center; + margin: 120px auto; + color: @body_color; + color: var(--body_color); + + @media screen and (max-width: @phone) { + margin: 70px auto; + } + + .label { + text-transform: uppercase; + font-size: 14px; + opacity: .3; + color: @body_color; + color: var(--body_color); + } + + .meow-breadcrumb .breadcrumb-items-container { + + .breadcrumb-item { + text-transform: uppercase; + font-size: 14px; + opacity: .3; + color: @body_color; + color: var(--body_color); + transition: .1s; + + &:hover { + opacity: .6; + transition: .1s; + } + + &.active { + opacity: 1; + } + } + + .divider { + opacity: .3; + margin: 0 5px; + } + } + + .page-title { + font-size: 48px; + line-height: 160%; + font-weight: 400; + margin-top: 0; + margin-bottom: 20px; + + @media screen and (max-width: @phone) { + font-size: 42px; + line-height: 140%; + } + } +} + +.page-featured-image { + text-align: center; + margin-bottom: 60px; + + img { + max-width: 100%; + } +} \ No newline at end of file diff --git a/assets/less/_meow-blocks.less b/assets/less/_meow-blocks.less new file mode 100644 index 0000000..c962c14 --- /dev/null +++ b/assets/less/_meow-blocks.less @@ -0,0 +1,253 @@ +// main: style.less + +.mwt-section-header { + width: 90% !important; + margin: auto; + + h3 { + position: relative; + width: auto !important; + display: inline-block; + font-weight: 400; + font-size: 28px; + color: @body_color; + color: var(--body_color); + + &::before { + content: ""; + position: absolute; + z-index: -9; + bottom: -5px; + width: 120%; + left: -10%; + height: 20px; + background: @body_color; + background: var(--body_color); + opacity: .05; + } + } +} + +.collections-list { + margin-left: -10px; + margin-right: -10px; +} + +.collection-card-container { + display: inline-block; + width: 25%; + padding: 10px; + box-sizing: border-box; + + @media screen and (max-width: @tablet) { + width: 33.33%; + } + + @media screen and (max-width: @big_phone) { + width: 100%; + } + + .collection-card { + position: relative; + display: block; + width: 100%; + padding-bottom: 66.66%; + border-radius: 8px; + overflow: hidden; + + .background { + position: absolute; + width: 100%; + padding-bottom: 66.66%; + background-size: cover; + background-position: center; + } + + .content { + position: absolute; + width: 100%; + bottom: 0; + padding: 10px 20px; + background: linear-gradient(to top, rgba(0,0,0,1), rgba(0,0,0,0)); + color: white; + box-sizing: border-box; + + h3 { + font-weight: 300; + font-size: 18px; + margin: 0; + line-height: 140%; + margin-bottom: 10px; + } + + .collection-meta { + font-size: 13px; + opacity: .5; + margin-top: -5px; + line-height: 1em; + + svg { + stroke: white; + vertical-align: middle; + margin-top: -3px; + margin-right: 5px; + height: 22px; + width: 22px; + } + } + } + } +} + +.folders-list { + margin-left: -10px; + margin-right: -10px; +} + +.folder-card-container { + display: inline-block; + width: 25%; + padding: 10px; + box-sizing: border-box; + vertical-align: top; + + @media screen and (max-width: @tablet) { + width: 33.33%; + } + + @media screen and (max-width: @big_phone) { + width: 100%; + } + + .folder-card { + width: 100%; + box-shadow: @shadow; + box-shadow: var(--shadow); + + &:hover { + box-shadow: @deeper_shadow; + box-shadow: var(--deeper_shadow); + transition: .1s; + } + + .card-header { + position: relative; + width: 100%; + padding-bottom: 66.66%; + + a { + position: absolute; + width: 100%; + height: 100%; + display: block; + background: #222; + background-size: cover; + background-position: center; + } + } + + .card-body { + background: @card_bg; + background: var(--card_bg); + padding: 10px 20px; + height: 110px; + display: flex; + flex-direction: column; + justify-content: center; + + h3 { + margin: 0; + font-size: 18px; + font-weight: 400; + line-height: 140%; + margin-bottom: 10px; + + a { + color: @card_color; + color: var(--card_color); + } + } + + .folder-meta { + font-size: 14px; + line-height: 1em; + opacity: .5; + margin-top: -5px; + color: @card_color; + color: var(--card_color); + } + } + } +} + +.mwt-keywords { + width: 90% !important; + margin: auto; + + .mwt-tags-cloud { + width: 100%; + overflow: hidden; + + a { + display: inline-block; + font-size: 16px !important; + color: @tag_color; + color: var(--tag_color); + border: 1px solid @tag_color; + border: 1px solid var(--tag_color); + padding: 0px 10px; + line-height: 38px; + white-space: nowrap; + margin: 3px; + + &:hover { + color: @tag_hover_color; + color: var(--tag_hover_color); + border: 1px solid @tag_hover_color; + border: 1px solid var(--tag_hover_color); + } + } + } +} + +.mwt-search { + position: relative; + width: 90% !important; + margin: auto; + + form.search-form { + width: 100%; + position: relative; + + .mwt-search { + width: 100% !important; + border-radius: 30px; + line-height: 20px; + padding: 10px 20px; + border: none; + outline: none; + background: @search_widget_bg; + background: var(--search_widget_bg); + transition: .1s; + + &:focus { + box-shadow: @shadow; + box-shadow: var(--shadow); + transition: .1s; + } + } + + svg { + position: absolute; + top: 7px; + right: 15px; + stroke: @footer_color; + stroke: var(--footer_color); + cursor: pointer; + } + + .hidden-submit { + display: none; + } + } +} \ No newline at end of file diff --git a/assets/less/_photography.less b/assets/less/_photography.less new file mode 100644 index 0000000..fc8388d --- /dev/null +++ b/assets/less/_photography.less @@ -0,0 +1,34 @@ +// main: style.less + +.opaque-featured-image-container { + width: 100%; + height: 400px; + position: absolute; + top: 0; + + .featured-image { + width: 100%; + height: 100%; + background-size: cover; + background-position: center; + } + + .filter { + width: 100%; + height: 400px; + position: absolute; + top: 0; + background: @opaque_header_bg; + background: var(--opaque_header_bg); + + &.less-opaque { + background: @less_opaque_header_bg; + background: var(--less_opaque_header_bg); + } + + &.very-opaque { + background: @very_opaque_header_bg; + background: var(--very_opaque_header_bg); + } + } +} \ No newline at end of file diff --git a/assets/less/_theme-info.less b/assets/less/_theme-info.less new file mode 100644 index 0000000..34a4d56 --- /dev/null +++ b/assets/less/_theme-info.less @@ -0,0 +1,23 @@ +// main: style.less + +/*! +Theme Name: Yuzu +Theme URI: https://meowapps.con/themes/yuzu/ +Author: MeowApps +Author URI: https://meowapps.con/ +Description: Fresh, small but not yellow, this theme has been designed for photographers, by photographers! +Version: 0.1.0 +License: GNU General Public License v2 or later +License URI: LICENSE +Text Domain: yuzu +Tags: custom-background, custom-logo, custom-menu, featured-images, threaded-comments, translation-ready + +This theme, like WordPress, is licensed under the GPL. +Use it to make something cool, have fun, and share what you've learned with others. + +Yuzu is based on Underscores https://underscores.me/, (C) 2012-2017 Automattic, Inc. +Underscores is distributed under the terms of the GNU GPL v2 or later. + +Normalizing styles have been helped along thanks to the fine work of +Nicolas Gallagher and Jonathan Neal https://necolas.github.io/normalize.css/ +*/ \ No newline at end of file diff --git a/assets/less/_top-bar.less b/assets/less/_top-bar.less new file mode 100644 index 0000000..f4fc8ef --- /dev/null +++ b/assets/less/_top-bar.less @@ -0,0 +1,389 @@ +// main: style.less + +.top-search-bar-container { + position: relative; + z-index: 99; + width: 100%; + height: 60px; + background: @top_bar_bg; + background: var(--top_bar_bg); + border-bottom: 1px solid rgba(0,0,0,.1); + margin-top: -60px; + transition: .2s; + + &.opened { + margin-top: 0px; + transition: .3s; + } + + .super-large-container { + position: relative; + height: 60px; + + form { + + input { + width: 100%; + line-height: 60px; + padding: 0; + border: none; + background: none; + outline: none; + font-size: 18px; + } + } + + .submit-top-bar-search { + position: absolute; + right: 0; + top: 50%; + height: 30px; + margin-top: -15px; + cursor: pointer; + opacity: .5; + transition: .1s; + + svg { + height: 30px; + width: 30px; + stroke: @top_bar_color; + stroke: var(--top_bar_color); + stroke-width: 2px; + cursor: pointer; + } + + &:hover { + opacity: 1; + transition: .1s; + } + } + } +} + +.site-header { + position: relative; + z-index: 99; + @header_height: 60px; + width: 100%; + background: @top_bar_bg; + background: var(--top_bar_bg); + height: @header_height; + box-shadow: @shadow; + box-shadow: var(--shadow); + + .top-bar-content { + display: flex; + + .site-branding { + flex: 1; + max-width: 300px; + + .site-logo { + height: 50px; + margin-top: 5px; + + a, img { + height: 100%; + width: auto; + } + } + + .site-title { + font-size: 18px; + line-height: @header_height; + margin: 0; + + a { + color: @top_bar_color; + color: var(--top_bar_color); + } + } + } + + .site-navigation { + flex: 1; + line-height: @header_height; + text-align: right; + + .menu-main-menu-container { + display: inline-block; + vertical-align: middle; + + @media screen and (max-width: 860px) { + display: none; + } + } + + ul { + margin: 0; + padding: 0; + + li { + position: relative; + display: inline-block; + list-style: none; + margin-left: 10px; + font-weight: 400; + + &.current-menu-item { + font-weight: 600; + + a { + opacity: 1; + } + } + + a { + color: @top_bar_color; + color: var(--top_bar_color); + opacity: .5; + } + + &:hover { + + a { + opacity: 1; + transition: .1s; + } + + ul { + visibility: visible; + opacity: 1; + transition: .1s; + + li a { + opacity: .5; + } + } + } + + ul { + visibility: hidden; + opacity: 0; + position: absolute; + z-index: 999; + background: @top_bar_bg; + background: var(--top_bar_bg); + padding: 20px; + box-shadow: @shadow; + box-shadow: var(--shadow); + right: 0; + margin-top: -1px; + margin-right: -20px; + transition: .1s; + text-align: left; + + li { + display: block; + margin: 0; + line-height: 30px; + white-space: nowrap; + + &.current-menu-item { + a { + opacity: 1; + } + } + + &:hover { + a { + opacity: 1; + } + } + + ul, &.current-menu-item > ul, &:hover > ul { + position: relative; + padding: 10px 20px; + border-left: 1px solid rgba(0,0,0,.4); + box-shadow: none; + + li { + display: block; + margin: 0; + line-height: 30px; + white-space: nowrap; + + a { + opacity: .5; + } + + &.current-menu-item { + a { + opacity: 1; + } + } + + &:hover { + a { + opacity: 1; + } + } + + ul, &.current-menu-item > ul, &:hover > ul { + position: relative; + padding: 10px 20px; + border-left: 1px solid rgba(0,0,0,.4); + + li { + display: block; + margin: 0; + line-height: 30px; + white-space: nowrap; + + a { + opacity: .5; + } + + &.current-menu-item { + a { + opacity: 1; + } + } + + &:hover { + a { + opacity: 1; + } + } + } + } + } + } + + } + + &::after { + content: ""; + position: absolute; + top: -2px; + left: 0; + width: 100%; + height: 5px; + background: @top_bar_bg; + background: var(--top_bar_bg); + } + } + } + } + + .open-top-bar-search, .close-top-bar-search { + display: inline-block; + margin-left: 20px; + vertical-align: middle; + line-height: @header_height; + cursor: pointer; + opacity: .5; + transition: .1s; + + &:hover { + opacity: 1; + transition: .1s; + } + + svg { + display: inline-block; + height: 16px; + width: 16px; + line-height: @header_height; + stroke: @top_bar_color; + stroke: var(--top_bar_color); + stroke-width: 2px; + } + + &.active { + opacity: 1; + + svg { + stroke-width: 3px; + } + } + } + } + } +} + +.mobile-navigation { + position: relative; + z-index: 9; + display: none; + width: 100%; + box-shadow: @shadow; + box-shadow: var(--shadow); + background: @top_bar_bg; + background: var(--top_bar_bg); + //background: var(--top_bar_bg); + text-align: center; + + @media screen and (max-width: 860px) { + display: block; + } + + .site-navigation { + display: inline-block; + padding: 30px 0; + margin: auto; + text-align: left; + + ul { + margin: 0; + padding: 0; + list-style: none; + + li { + line-height: 200%; + + a { + color: @top_bar_color; + color: var(--top_bar_color); + } + + ul { + padding-left: 30px; + border-left: 1px dashed #e6e6e6; + } + } + } + } + + .mobile-navigation-toggle { + position: absolute; + height: 40px; + width: 60px; + background: @top_bar_bg; + background: var(--top_bar_bg); + color: @top_bar_color; + color: var(--top_bar_color); + bottom: -40px; + left: 50%; + margin-left: -30px; + line-height: 40px; + box-shadow: @shadow; + box-shadow: var(--shadow); + text-align: center; + border-radius: 0 0 8px 8px; + cursor: pointer; + + .open-icon, .close-icon { + margin-top: 5px; + + svg { + stroke: @top_bar_color; + stroke: var(--top_bar_color); + } + } + + .close-icon { + display: none; + } + + &.active { + .close-icon { + display: block; + } + + .open-icon { + display: none; + } + } + } +} \ No newline at end of file diff --git a/assets/less/_variables.less b/assets/less/_variables.less new file mode 100644 index 0000000..eec1422 --- /dev/null +++ b/assets/less/_variables.less @@ -0,0 +1,39 @@ +// main: style.less + +// RESPONSIVENESS +@phone: 320px; // iPhone 6,7,8 +@big_phone: 376px; // iPhone X +@tablet: 768px; // iPad +@big_tablet: 1024px; // iPad Pro + + +// These variables will be used by browsers that can't support custom properties ( IE ) +@shadow: 0px 2px 4px rgba(0, 0, 0, 0.1); +@deeper_shadow: 0px 2px 8px rgba(0, 0, 0, 0.15); +@lato: 'Lato', sans-serif; +@top_bar_color: #2E3B4F; +@body_color: #2E3B4F; +@footer_color: #2E3B4F; +@card_color: #2E3B4F; +@link_color: #4B828E; +@link_hover_color: #39636d; +@tag_color: #4B828E; +@tag_hover_color: #39636d; +@search_widget_color: #2E3B4F; +@read_more_btn_color: #2E3B4F; +@comment_form_color: #2E3B4F; +@comment_color: #2E3B4F; +@post_comment_btn_color: #2E3B4F; +@top_bar_bg: #FFF; +@body_bg: #FAFBFB; +@very_opaque_header_bg: linear-gradient(to top, #fafbfb, rgba(250, 251, 251, 0.9)); +@opaque_header_bg: linear-gradient(to top, #fafbfb, rgba(250, 251, 251, 0.6)); +@less_opaque_header_bg: linear-gradient(to top, #fafbfb, rgba(250, 251, 251, 0.4)); +@footer_bg: #FFF; +@card_bg: #FFF; +@search_widget_bg: #f5f4f4; +@read_more_btn_bg: #F5F5F5; +@comment_form_bg: #FFF; +@comment_bg: #FFF; +@post_comment_btn_bg: #FFF; + diff --git a/assets/less/_wordpress.less b/assets/less/_wordpress.less new file mode 100644 index 0000000..d2632e1 --- /dev/null +++ b/assets/less/_wordpress.less @@ -0,0 +1,955 @@ +// main: style.less + +/*-------------------------------------------------------------- +>>> TABLE OF CONTENTS: +---------------------------------------------------------------- +# Normalize +# Typography +# Elements +# Forms +# Navigation + ## Links + ## Menus +# Accessibility +# Alignments +# Clearings +# Widgets +# Content + ## Posts and pages + ## Comments +# Infinite scroll +# Media + ## Captions + ## Galleries +--------------------------------------------------------------*/ +/*-------------------------------------------------------------- +# Normalize +--------------------------------------------------------------*/ +/* normalize.css v8.0.0 | MIT License | github.com/necolas/normalize.css */ + +/* Document + ========================================================================== */ + +/** + * 1. Correct the line height in all browsers. + * 2. Prevent adjustments of font size after orientation changes in iOS. + */ + +html { + line-height: 1.15; /* 1 */ + -webkit-text-size-adjust: 100%; /* 2 */ +} + +/* Sections + ========================================================================== */ + +/** + * Remove the margin in all browsers. + */ + +body { + margin: 0; +} + +/** + * Correct the font size and margin on `h1` elements within `section` and + * `article` contexts in Chrome, Firefox, and Safari. + */ + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +/* Grouping content + ========================================================================== */ + +/** + * 1. Add the correct box sizing in Firefox. + * 2. Show the overflow in Edge and IE. + */ + +hr { + box-sizing: content-box; /* 1 */ + height: 0; /* 1 */ + overflow: visible; /* 2 */ +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +pre { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/* Text-level semantics + ========================================================================== */ + +/** + * Remove the gray background on active links in IE 10. + */ + +a { + background-color: transparent; +} + +/** + * 1. Remove the bottom border in Chrome 57- + * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. + */ + +abbr[title] { + border-bottom: none; /* 1 */ + text-decoration: underline; /* 2 */ + text-decoration: underline dotted; /* 2 */ +} + +/** + * Add the correct font weight in Chrome, Edge, and Safari. + */ + +b, +strong { + font-weight: bolder; +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +code, +kbd, +samp { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/** + * Add the correct font size in all browsers. + */ + +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` elements from affecting the line height in + * all browsers. + */ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +/* Embedded content + ========================================================================== */ + +/** + * Remove the border on images inside links in IE 10. + */ + +img { + border-style: none; +} + +/* Forms + ========================================================================== */ + +/** + * 1. Change the font styles in all browsers. + * 2. Remove the margin in Firefox and Safari. + */ + +button, +input, +optgroup, +select, +textarea { + font-family: inherit; /* 1 */ + font-size: 100%; /* 1 */ + line-height: 1.15; /* 1 */ + margin: 0; /* 2 */ +} + +/** + * Show the overflow in IE. + * 1. Show the overflow in Edge. + */ + +button, +input { /* 1 */ + overflow: visible; +} + +/** + * Remove the inheritance of text transform in Edge, Firefox, and IE. + * 1. Remove the inheritance of text transform in Firefox. + */ + +button, +select { /* 1 */ + text-transform: none; +} + +/** + * Correct the inability to style clickable types in iOS and Safari. + */ + +button, +[type="button"], +[type="reset"], +[type="submit"] { + -webkit-appearance: button; +} + +/** + * Remove the inner border and padding in Firefox. + */ + +button::-moz-focus-inner, +[type="button"]::-moz-focus-inner, +[type="reset"]::-moz-focus-inner, +[type="submit"]::-moz-focus-inner { + border-style: none; + padding: 0; +} + +/** + * Restore the focus styles unset by the previous rule. + */ + +button:-moz-focusring, +[type="button"]:-moz-focusring, +[type="reset"]:-moz-focusring, +[type="submit"]:-moz-focusring { + outline: 1px dotted ButtonText; +} + +/** + * Correct the padding in Firefox. + */ + +fieldset { + padding: 0.35em 0.75em 0.625em; +} + +/** + * 1. Correct the text wrapping in Edge and IE. + * 2. Correct the color inheritance from `fieldset` elements in IE. + * 3. Remove the padding so developers are not caught out when they zero out + * `fieldset` elements in all browsers. + */ + +legend { + box-sizing: border-box; /* 1 */ + color: inherit; /* 2 */ + display: table; /* 1 */ + max-width: 100%; /* 1 */ + padding: 0; /* 3 */ + white-space: normal; /* 1 */ +} + +/** + * Add the correct vertical alignment in Chrome, Firefox, and Opera. + */ + +progress { + vertical-align: baseline; +} + +/** + * Remove the default vertical scrollbar in IE 10+. + */ + +textarea { + overflow: auto; +} + +/** + * 1. Add the correct box sizing in IE 10. + * 2. Remove the padding in IE 10. + */ + +[type="checkbox"], +[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ +} + +/** + * Correct the cursor style of increment and decrement buttons in Chrome. + */ + +[type="number"]::-webkit-inner-spin-button, +[type="number"]::-webkit-outer-spin-button { + height: auto; +} + +/** + * 1. Correct the odd appearance in Chrome and Safari. + * 2. Correct the outline style in Safari. + */ + +[type="search"] { + -webkit-appearance: textfield; /* 1 */ + outline-offset: -2px; /* 2 */ +} + +/** + * Remove the inner padding in Chrome and Safari on macOS. + */ + +[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * 1. Correct the inability to style clickable types in iOS and Safari. + * 2. Change font properties to `inherit` in Safari. + */ + +::-webkit-file-upload-button { + -webkit-appearance: button; /* 1 */ + font: inherit; /* 2 */ +} + +/* Interactive + ========================================================================== */ + +/* + * Add the correct display in Edge, IE 10+, and Firefox. + */ + +details { + display: block; +} + +/* + * Add the correct display in all browsers. + */ + +summary { + display: list-item; +} + +/* Misc + ========================================================================== */ + +/** + * Add the correct display in IE 10+. + */ + +template { + display: none; +} + +/** + * Add the correct display in IE 10. + */ + +[hidden] { + display: none; +} + +/*-------------------------------------------------------------- +# Typography +--------------------------------------------------------------*/ +body, +button, +input, +select, +optgroup, +textarea { + color: #404040; + font-family: sans-serif; + font-size: 16px; + font-size: 1rem; + line-height: 1.5; +} + +h1, h2, h3, h4, h5, h6 { + clear: both; +} + +p { + margin-bottom: 1.5em; +} + +dfn, cite, em, i { + font-style: italic; +} + +blockquote { + margin: 0 1.5em; +} + +address { + margin: 0 0 1.5em; +} + +pre { + background: #eee; + font-family: "Courier 10 Pitch", Courier, monospace; + font-size: 15px; + font-size: 0.9375rem; + line-height: 1.6; + margin-bottom: 1.6em; + max-width: 100%; + overflow: auto; + padding: 1.6em; +} + +code, kbd, tt, var { + font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; + font-size: 15px; + font-size: 0.9375rem; +} + +abbr, acronym { + border-bottom: 1px dotted #666; + cursor: help; +} + +mark, ins { + background: #fff9c0; + text-decoration: none; +} + +big { + font-size: 125%; +} + +/*-------------------------------------------------------------- +# Elements +--------------------------------------------------------------*/ +html { + box-sizing: border-box; +} + +*, +*:before, +*:after { + /* Inherit box-sizing to make it easier to change the property for components that leverage other behavior; see https://css-tricks.com/inheriting-box-sizing-probably-slightly-better-best-practice/ */ + box-sizing: inherit; +} + +body { + background: #fff; + /* Fallback for when there is no custom background color defined. */ +} + +hr { + background-color: #ccc; + border: 0; + height: 1px; + margin-bottom: 1.5em; +} + +ul, ol { + margin: 0 0 1.5em 3em; +} + +ul { + list-style: disc; +} + +ol { + list-style: decimal; +} + +li > ul, +li > ol { + margin-bottom: 0; + margin-left: 1.5em; +} + +dt { + font-weight: bold; +} + +dd { + margin: 0 1.5em 1.5em; +} + +img { + height: auto; + /* Make sure images are scaled correctly. */ + max-width: 100%; + /* Adhere to container width. */ +} + +figure { + margin: 1em 0; + /* Extra wide images within figure tags don't overflow the content area. */ +} + +table { + margin: 0 0 1.5em; + width: 100%; +} + +/*-------------------------------------------------------------- +# Forms +--------------------------------------------------------------*/ +button, +input[type="button"], +input[type="reset"], +input[type="submit"] { + border: 1px solid; + border-color: #ccc #ccc #bbb; + border-radius: 3px; + background: #e6e6e6; + color: rgba(0, 0, 0, 0.8); + font-size: 12px; + font-size: 0.75rem; + line-height: 1; + padding: .6em 1em .4em; +} + +button:hover, +input[type="button"]:hover, +input[type="reset"]:hover, +input[type="submit"]:hover { + border-color: #ccc #bbb #aaa; +} + +button:active, button:focus, +input[type="button"]:active, +input[type="button"]:focus, +input[type="reset"]:active, +input[type="reset"]:focus, +input[type="submit"]:active, +input[type="submit"]:focus { + border-color: #aaa #bbb #bbb; +} + +input[type="text"], +input[type="email"], +input[type="url"], +input[type="password"], +input[type="search"], +input[type="number"], +input[type="tel"], +input[type="range"], +input[type="date"], +input[type="month"], +input[type="week"], +input[type="time"], +input[type="datetime"], +input[type="datetime-local"], +input[type="color"], +textarea { + color: #666; + border: 1px solid #ccc; + border-radius: 3px; + padding: 3px; +} + +input[type="text"]:focus, +input[type="email"]:focus, +input[type="url"]:focus, +input[type="password"]:focus, +input[type="search"]:focus, +input[type="number"]:focus, +input[type="tel"]:focus, +input[type="range"]:focus, +input[type="date"]:focus, +input[type="month"]:focus, +input[type="week"]:focus, +input[type="time"]:focus, +input[type="datetime"]:focus, +input[type="datetime-local"]:focus, +input[type="color"]:focus, +textarea:focus { + color: #111; +} + +select { + border: 1px solid #ccc; +} + +textarea { + width: 100%; +} + +/*-------------------------------------------------------------- +# Navigation +--------------------------------------------------------------*/ +/*-------------------------------------------------------------- +## Links +--------------------------------------------------------------*/ +a { + color: royalblue; +} + +a:visited { + color: purple; +} + +a:hover, a:focus, a:active { + color: midnightblue; +} + +a:focus { + outline: thin dotted; +} + +a:hover, a:active { + outline: 0; +} + +/*-------------------------------------------------------------- +## Menus +--------------------------------------------------------------*/ +.main-navigation { + clear: both; + display: block; + float: left; + width: 100%; +} + +.main-navigation ul { + display: none; + list-style: none; + margin: 0; + padding-left: 0; +} + +.main-navigation ul ul { + box-shadow: 0 3px 3px rgba(0, 0, 0, 0.2); + float: left; + position: absolute; + top: 100%; + left: -999em; + z-index: 99999; +} + +.main-navigation ul ul ul { + left: -999em; + top: 0; +} + +.main-navigation ul ul li:hover > ul, +.main-navigation ul ul li.focus > ul { + left: 100%; +} + +.main-navigation ul ul a { + width: 200px; +} + +.main-navigation ul li:hover > ul, +.main-navigation ul li.focus > ul { + left: auto; +} + +.main-navigation li { + float: left; + position: relative; +} + +.main-navigation a { + display: block; + text-decoration: none; +} + +/* Small menu. */ +.menu-toggle, +.main-navigation.toggled ul { + display: block; +} + +@media screen and (min-width: 37.5em) { + .menu-toggle { + display: none; + } + .main-navigation ul { + display: block; + } +} + +.site-main .comment-navigation, .site-main +.posts-navigation, .site-main +.post-navigation { + margin: 0 0 1.5em; + overflow: hidden; +} + +.comment-navigation .nav-previous, +.posts-navigation .nav-previous, +.post-navigation .nav-previous { + float: left; + width: 50%; +} + +.comment-navigation .nav-next, +.posts-navigation .nav-next, +.post-navigation .nav-next { + float: right; + text-align: right; + width: 50%; +} + +/*-------------------------------------------------------------- +# Accessibility +--------------------------------------------------------------*/ +/* Text meant only for screen readers. */ +.screen-reader-text { + border: 0; + clip: rect(1px, 1px, 1px, 1px); + clip-path: inset(50%); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute !important; + width: 1px; + word-wrap: normal !important; /* Many screen reader and browser combinations announce broken words as they would appear visually. */ +} + +.screen-reader-text:focus { + background-color: #f1f1f1; + border-radius: 3px; + box-shadow: 0 0 2px 2px rgba(0, 0, 0, 0.6); + clip: auto !important; + clip-path: none; + color: #21759b; + display: block; + font-size: 14px; + font-size: 0.875rem; + font-weight: bold; + height: auto; + left: 5px; + line-height: normal; + padding: 15px 23px 14px; + text-decoration: none; + top: 5px; + width: auto; + z-index: 100000; + /* Above WP toolbar. */ +} + +/* Do not show the outline on the skip link target. */ +#content[tabindex="-1"]:focus { + outline: 0; +} + +/*-------------------------------------------------------------- +# Alignments +--------------------------------------------------------------*/ +.alignleft { + display: inline; + float: left; + margin-right: 1.5em; +} + +.alignright { + display: inline; + float: right; + margin-left: 1.5em; +} + +.aligncenter { + clear: both; + display: block; + margin-left: auto; + margin-right: auto; +} + +/*-------------------------------------------------------------- +# Clearings +--------------------------------------------------------------*/ +.clear:before, +.clear:after, +.entry-content:before, +.entry-content:after, +.comment-content:before, +.comment-content:after, +.site-header:before, +.site-header:after, +.site-content:before, +.site-content:after, +.site-footer:before, +.site-footer:after { + content: ""; + display: table; + table-layout: fixed; +} + +.clear:after, +.entry-content:after, +.comment-content:after, +.site-header:after, +.site-content:after, +.site-footer:after { + clear: both; +} + +/*-------------------------------------------------------------- +# Widgets +--------------------------------------------------------------*/ +.widget { + margin: 0 0 1.5em; + /* Make sure select elements fit in widgets. */ +} + +.widget select { + max-width: 100%; +} + +/*-------------------------------------------------------------- +# Content +--------------------------------------------------------------*/ +/*-------------------------------------------------------------- +## Posts and pages +--------------------------------------------------------------*/ +.sticky { + display: block; +} + +.updated:not(.published) { + display: none; +} + +.page-links { + clear: both; + margin: 0 0 1.5em; +} + +/*-------------------------------------------------------------- +## Comments +--------------------------------------------------------------*/ +.comment-content a { + word-wrap: break-word; +} + +.bypostauthor { + display: block; +} + +/*-------------------------------------------------------------- +# Infinite scroll +--------------------------------------------------------------*/ +/* Globally hidden elements when Infinite Scroll is supported and in use. */ +.infinite-scroll .posts-navigation, +.infinite-scroll.neverending .site-footer { + /* Theme Footer (when set to scrolling) */ + display: none; +} + +/* When Infinite Scroll has reached its end we need to re-display elements that were hidden (via .neverending) before. */ +.infinity-end.neverending .site-footer { + display: block; +} + +/*-------------------------------------------------------------- +# Media +--------------------------------------------------------------*/ +.page-content .wp-smiley, +.entry-content .wp-smiley, +.comment-content .wp-smiley { + border: none; + margin-bottom: 0; + margin-top: 0; + padding: 0; +} + +/* Make sure embeds and iframes fit their containers. */ +embed, +iframe, +object { + max-width: 100%; +} + +/* Make sure logo link wraps around logo image. */ +.custom-logo-link { + display: inline-block; +} + +/*-------------------------------------------------------------- +## Captions +--------------------------------------------------------------*/ +.wp-caption { + margin-bottom: 1.5em; + max-width: 100%; +} + +.wp-caption img[class*="wp-image-"] { + display: block; + margin-left: auto; + margin-right: auto; +} + +.wp-caption .wp-caption-text { + margin: 0.8075em 0; +} + +.wp-caption-text { + text-align: center; +} + +/*-------------------------------------------------------------- +## Galleries +--------------------------------------------------------------*/ +.gallery { + margin-bottom: 1.5em; +} + +.gallery-item { + display: inline-block; + text-align: center; + vertical-align: top; + width: 100%; +} + +.gallery-columns-2 .gallery-item { + max-width: 50%; +} + +.gallery-columns-3 .gallery-item { + max-width: 33.33%; +} + +.gallery-columns-4 .gallery-item { + max-width: 25%; +} + +.gallery-columns-5 .gallery-item { + max-width: 20%; +} + +.gallery-columns-6 .gallery-item { + max-width: 16.66%; +} + +.gallery-columns-7 .gallery-item { + max-width: 14.28%; +} + +.gallery-columns-8 .gallery-item { + max-width: 12.5%; +} + +.gallery-columns-9 .gallery-item { + max-width: 11.11%; +} + +.gallery-caption { + display: block; +} diff --git a/assets/less/editor-style.less b/assets/less/editor-style.less new file mode 100644 index 0000000..7a599bf --- /dev/null +++ b/assets/less/editor-style.less @@ -0,0 +1,13 @@ +// out: ../css/editor-style.css + +@import url('https://fonts.googleapis.com/css?family=Lato:400&display=swap'); + +.edit-post-visual-editor { + font-family: 'Lato', sans-serif !important; + + p { + font-size: 18px !important; + line-height: 180% !important; + opacity: .8; + } +} \ No newline at end of file diff --git a/assets/less/style.less b/assets/less/style.less new file mode 100644 index 0000000..bf96b23 --- /dev/null +++ b/assets/less/style.less @@ -0,0 +1,19 @@ +// out: ../../style.css + +// Importing Google Fonts +@import url('https://fonts.googleapis.com/css?family=Lato:300,400,700,900&display=swap'); + +// Importing LESS +@import '_theme-info'; +@import '_variables'; +@import '_wordpress'; +@import '_general-elements'; +@import '_gutenberg'; +@import '_blog'; +@import '_photography'; +@import '_meow-blocks'; +@import '_article-cards'; +@import '_footer'; + +@import '_top-bar'; +@import '_header'; \ No newline at end of file diff --git a/attachment.php b/attachment.php new file mode 100644 index 0000000..e1932b5 --- /dev/null +++ b/attachment.php @@ -0,0 +1,65 @@ + + +
+
+ +
+ ID); + $image_infos = get_post($post->ID); + $image_src = wp_get_attachment_image_src($post->ID, 'full')[0]; + $image_title = $post->post_title; + $image_description = $post->post_content; + + $image_tags = get_the_terms($post, 'attachment_keyword'); + $tag_cloud_markup = ""; + if(count($image_tags) > 1) { + $tag_cloud_markup = "
"; + foreach($image_tags as $tag) { + $tag_cloud_markup .= " + ".$tag->name." + "; + } + $tag_cloud_markup .= "
"; + } + ?> + + + +
+ +

+ +

+
+

+
+
+

+ +

+
+

+
+
+ +
+
+ +
+
+ + + diff --git a/author.php b/author.php new file mode 100644 index 0000000..6a7294f --- /dev/null +++ b/author.php @@ -0,0 +1,75 @@ + + +
+
+ +
+ +
+ +
+ '; + require get_template_directory() . '/components/article-cards/large-article-card.php'; + echo '
'; + $count++; + break; + case 1: + echo '
'; + require get_template_directory() . '/components/article-cards/medium-article-card.php'; + $count++; + break; + case 2: + require get_template_directory() . '/components/article-cards/medium-article-card.php'; + echo '
'; + $count++; + break; + case 3: + echo '
'; + require get_template_directory() . '/components/article-cards/small-article-card.php'; + $count++; + break; + case 4: + require get_template_directory() . '/components/article-cards/small-article-card.php'; + $count++; + break; + case 5: + require get_template_directory() . '/components/article-cards/small-article-card.php'; + echo '
'; + $count = 0; + break; + } + + + endwhile; + + the_posts_navigation(); + + else : + + _e('No posts found!', 'yuzu'); + + endif; + ?> +
+ + + + + + +
+
+ +
+ +
+ +
+ '; + require get_template_directory() . '/components/article-cards/large-article-card.php'; + echo '
'; + $count++; + break; + case 1: + echo '
'; + require get_template_directory() . '/components/article-cards/medium-article-card.php'; + $count++; + break; + case 2: + require get_template_directory() . '/components/article-cards/medium-article-card.php'; + echo '
'; + $count++; + break; + case 3: + echo '
'; + require get_template_directory() . '/components/article-cards/small-article-card.php'; + $count++; + break; + case 4: + require get_template_directory() . '/components/article-cards/small-article-card.php'; + $count++; + break; + case 5: + require get_template_directory() . '/components/article-cards/small-article-card.php'; + echo '
'; + $count = 0; + break; + } + + + endwhile; + + the_posts_navigation(); + + else : + + _e('No posts found!', 'yuzu'); + + endif; + ?> +
+ + + + +wp_version = $GLOBALS['wp_version']; + + // Announce that the class is ready, and pass the object (for advanced use). + do_action_ref_array( 'tgmpa_init', array( $this ) ); + + /* + * Load our text domain and allow for overloading the fall-back file. + * + * {@internal IMPORTANT! If this code changes, review the regex in the custom TGMPA + * generator on the website.}} + */ + add_action( 'init', array( $this, 'load_textdomain' ), 5 ); + add_filter( 'load_textdomain_mofile', array( $this, 'overload_textdomain_mofile' ), 10, 2 ); + + // When the rest of WP has loaded, kick-start the rest of the class. + add_action( 'init', array( $this, 'init' ) ); + } + + /** + * Magic method to (not) set protected properties from outside of this class. + * + * {@internal hackedihack... There is a serious bug in v2.3.2 - 2.3.6 where the `menu` property + * is being assigned rather than tested in a conditional, effectively rendering it useless. + * This 'hack' prevents this from happening.}} + * + * @see https://github.com/TGMPA/TGM-Plugin-Activation/blob/2.3.6/tgm-plugin-activation/class-tgm-plugin-activation.php#L1593 + * + * @since 2.5.2 + * + * @param string $name Name of an inaccessible property. + * @param mixed $value Value to assign to the property. + * @return void Silently fail to set the property when this is tried from outside of this class context. + * (Inside this class context, the __set() method if not used as there is direct access.) + */ + public function __set( $name, $value ) { + return; + } + + /** + * Magic method to get the value of a protected property outside of this class context. + * + * @since 2.5.2 + * + * @param string $name Name of an inaccessible property. + * @return mixed The property value. + */ + public function __get( $name ) { + return $this->{$name}; + } + + /** + * Initialise the interactions between this class and WordPress. + * + * Hooks in three new methods for the class: admin_menu, notices and styles. + * + * @since 2.0.0 + * + * @see TGM_Plugin_Activation::admin_menu() + * @see TGM_Plugin_Activation::notices() + * @see TGM_Plugin_Activation::styles() + */ + public function init() { + /** + * By default TGMPA only loads on the WP back-end and not in an Ajax call. Using this filter + * you can overrule that behaviour. + * + * @since 2.5.0 + * + * @param bool $load Whether or not TGMPA should load. + * Defaults to the return of `is_admin() && ! defined( 'DOING_AJAX' )`. + */ + if ( true !== apply_filters( 'tgmpa_load', ( is_admin() && ! defined( 'DOING_AJAX' ) ) ) ) { + return; + } + + // Load class strings. + $this->strings = array( + 'page_title' => __( 'Install Required Plugins', 'tgmpa' ), + 'menu_title' => __( 'Install Plugins', 'tgmpa' ), + /* translators: %s: plugin name. */ + 'installing' => __( 'Installing Plugin: %s', 'tgmpa' ), + /* translators: %s: plugin name. */ + 'updating' => __( 'Updating Plugin: %s', 'tgmpa' ), + 'oops' => __( 'Something went wrong with the plugin API.', 'tgmpa' ), + 'notice_can_install_required' => _n_noop( + /* translators: 1: plugin name(s). */ + 'This theme requires the following plugin: %1$s.', + 'This theme requires the following plugins: %1$s.', + 'tgmpa' + ), + 'notice_can_install_recommended' => _n_noop( + /* translators: 1: plugin name(s). */ + 'This theme recommends the following plugin: %1$s.', + 'This theme recommends the following plugins: %1$s.', + 'tgmpa' + ), + 'notice_ask_to_update' => _n_noop( + /* translators: 1: plugin name(s). */ + 'The following plugin needs to be updated to its latest version to ensure maximum compatibility with this theme: %1$s.', + 'The following plugins need to be updated to their latest version to ensure maximum compatibility with this theme: %1$s.', + 'tgmpa' + ), + 'notice_ask_to_update_maybe' => _n_noop( + /* translators: 1: plugin name(s). */ + 'There is an update available for: %1$s.', + 'There are updates available for the following plugins: %1$s.', + 'tgmpa' + ), + 'notice_can_activate_required' => _n_noop( + /* translators: 1: plugin name(s). */ + 'The following required plugin is currently inactive: %1$s.', + 'The following required plugins are currently inactive: %1$s.', + 'tgmpa' + ), + 'notice_can_activate_recommended' => _n_noop( + /* translators: 1: plugin name(s). */ + 'The following recommended plugin is currently inactive: %1$s.', + 'The following recommended plugins are currently inactive: %1$s.', + 'tgmpa' + ), + 'install_link' => _n_noop( + 'Begin installing plugin', + 'Begin installing plugins', + 'tgmpa' + ), + 'update_link' => _n_noop( + 'Begin updating plugin', + 'Begin updating plugins', + 'tgmpa' + ), + 'activate_link' => _n_noop( + 'Begin activating plugin', + 'Begin activating plugins', + 'tgmpa' + ), + 'return' => __( 'Return to Required Plugins Installer', 'tgmpa' ), + 'dashboard' => __( 'Return to the Dashboard', 'tgmpa' ), + 'plugin_activated' => __( 'Plugin activated successfully.', 'tgmpa' ), + 'activated_successfully' => __( 'The following plugin was activated successfully:', 'tgmpa' ), + /* translators: 1: plugin name. */ + 'plugin_already_active' => __( 'No action taken. Plugin %1$s was already active.', 'tgmpa' ), + /* translators: 1: plugin name. */ + 'plugin_needs_higher_version' => __( 'Plugin not activated. A higher version of %s is needed for this theme. Please update the plugin.', 'tgmpa' ), + /* translators: 1: dashboard link. */ + 'complete' => __( 'All plugins installed and activated successfully. %1$s', 'tgmpa' ), + 'dismiss' => __( 'Dismiss this notice', 'tgmpa' ), + 'notice_cannot_install_activate' => __( 'There are one or more required or recommended plugins to install, update or activate.', 'tgmpa' ), + 'contact_admin' => __( 'Please contact the administrator of this site for help.', 'tgmpa' ), + ); + + do_action( 'tgmpa_register' ); + + /* After this point, the plugins should be registered and the configuration set. */ + + // Proceed only if we have plugins to handle. + if ( empty( $this->plugins ) || ! is_array( $this->plugins ) ) { + return; + } + + // Set up the menu and notices if we still have outstanding actions. + if ( true !== $this->is_tgmpa_complete() ) { + // Sort the plugins. + array_multisort( $this->sort_order, SORT_ASC, $this->plugins ); + + add_action( 'admin_menu', array( $this, 'admin_menu' ) ); + add_action( 'admin_head', array( $this, 'dismiss' ) ); + + // Prevent the normal links from showing underneath a single install/update page. + add_filter( 'install_plugin_complete_actions', array( $this, 'actions' ) ); + add_filter( 'update_plugin_complete_actions', array( $this, 'actions' ) ); + + if ( $this->has_notices ) { + add_action( 'admin_notices', array( $this, 'notices' ) ); + add_action( 'admin_init', array( $this, 'admin_init' ), 1 ); + add_action( 'admin_enqueue_scripts', array( $this, 'thickbox' ) ); + } + } + + // If needed, filter plugin action links. + add_action( 'load-plugins.php', array( $this, 'add_plugin_action_link_filters' ), 1 ); + + // Make sure things get reset on switch theme. + add_action( 'switch_theme', array( $this, 'flush_plugins_cache' ) ); + + if ( $this->has_notices ) { + add_action( 'switch_theme', array( $this, 'update_dismiss' ) ); + } + + // Setup the force activation hook. + if ( true === $this->has_forced_activation ) { + add_action( 'admin_init', array( $this, 'force_activation' ) ); + } + + // Setup the force deactivation hook. + if ( true === $this->has_forced_deactivation ) { + add_action( 'switch_theme', array( $this, 'force_deactivation' ) ); + } + } + + /** + * Load translations. + * + * @since 2.6.0 + * + * (@internal Uses `load_theme_textdomain()` rather than `load_plugin_textdomain()` to + * get round the different ways of handling the path and deprecated notices being thrown + * and such. For plugins, the actual file name will be corrected by a filter.}} + * + * {@internal IMPORTANT! If this function changes, review the regex in the custom TGMPA + * generator on the website.}} + */ + public function load_textdomain() { + if ( is_textdomain_loaded( 'tgmpa' ) ) { + return; + } + + if ( false !== strpos( __FILE__, WP_PLUGIN_DIR ) || false !== strpos( __FILE__, WPMU_PLUGIN_DIR ) ) { + // Plugin, we'll need to adjust the file name. + add_action( 'load_textdomain_mofile', array( $this, 'correct_plugin_mofile' ), 10, 2 ); + load_theme_textdomain( 'tgmpa', dirname( __FILE__ ) . '/languages' ); + remove_action( 'load_textdomain_mofile', array( $this, 'correct_plugin_mofile' ), 10 ); + } else { + load_theme_textdomain( 'tgmpa', dirname( __FILE__ ) . '/languages' ); + } + } + + /** + * Correct the .mo file name for (must-use) plugins. + * + * Themese use `/path/{locale}.mo` while plugins use `/path/{text-domain}-{locale}.mo`. + * + * {@internal IMPORTANT! If this function changes, review the regex in the custom TGMPA + * generator on the website.}} + * + * @since 2.6.0 + * + * @param string $mofile Full path to the target mofile. + * @param string $domain The domain for which a language file is being loaded. + * @return string $mofile + */ + public function correct_plugin_mofile( $mofile, $domain ) { + // Exit early if not our domain (just in case). + if ( 'tgmpa' !== $domain ) { + return $mofile; + } + return preg_replace( '`/([a-z]{2}_[A-Z]{2}.mo)$`', '/tgmpa-$1', $mofile ); + } + + /** + * Potentially overload the fall-back translation file for the current language. + * + * WP, by default since WP 3.7, will load a local translation first and if none + * can be found, will try and find a translation in the /wp-content/languages/ directory. + * As this library is theme/plugin agnostic, translation files for TGMPA can exist both + * in the WP_LANG_DIR /plugins/ subdirectory as well as in the /themes/ subdirectory. + * + * This method makes sure both directories are checked. + * + * {@internal IMPORTANT! If this function changes, review the regex in the custom TGMPA + * generator on the website.}} + * + * @since 2.6.0 + * + * @param string $mofile Full path to the target mofile. + * @param string $domain The domain for which a language file is being loaded. + * @return string $mofile + */ + public function overload_textdomain_mofile( $mofile, $domain ) { + // Exit early if not our domain, not a WP_LANG_DIR load or if the file exists and is readable. + if ( 'tgmpa' !== $domain || false === strpos( $mofile, WP_LANG_DIR ) || @is_readable( $mofile ) ) { + return $mofile; + } + + // Current fallback file is not valid, let's try the alternative option. + if ( false !== strpos( $mofile, '/themes/' ) ) { + return str_replace( '/themes/', '/plugins/', $mofile ); + } elseif ( false !== strpos( $mofile, '/plugins/' ) ) { + return str_replace( '/plugins/', '/themes/', $mofile ); + } else { + return $mofile; + } + } + + /** + * Hook in plugin action link filters for the WP native plugins page. + * + * - Prevent activation of plugins which don't meet the minimum version requirements. + * - Prevent deactivation of force-activated plugins. + * - Add update notice if update available. + * + * @since 2.5.0 + */ + public function add_plugin_action_link_filters() { + foreach ( $this->plugins as $slug => $plugin ) { + if ( false === $this->can_plugin_activate( $slug ) ) { + add_filter( 'plugin_action_links_' . $plugin['file_path'], array( $this, 'filter_plugin_action_links_activate' ), 20 ); + } + + if ( true === $plugin['force_activation'] ) { + add_filter( 'plugin_action_links_' . $plugin['file_path'], array( $this, 'filter_plugin_action_links_deactivate' ), 20 ); + } + + if ( false !== $this->does_plugin_require_update( $slug ) ) { + add_filter( 'plugin_action_links_' . $plugin['file_path'], array( $this, 'filter_plugin_action_links_update' ), 20 ); + } + } + } + + /** + * Remove the 'Activate' link on the WP native plugins page if the plugin does not meet the + * minimum version requirements. + * + * @since 2.5.0 + * + * @param array $actions Action links. + * @return array + */ + public function filter_plugin_action_links_activate( $actions ) { + unset( $actions['activate'] ); + + return $actions; + } + + /** + * Remove the 'Deactivate' link on the WP native plugins page if the plugin has been set to force activate. + * + * @since 2.5.0 + * + * @param array $actions Action links. + * @return array + */ + public function filter_plugin_action_links_deactivate( $actions ) { + unset( $actions['deactivate'] ); + + return $actions; + } + + /** + * Add a 'Requires update' link on the WP native plugins page if the plugin does not meet the + * minimum version requirements. + * + * @since 2.5.0 + * + * @param array $actions Action links. + * @return array + */ + public function filter_plugin_action_links_update( $actions ) { + $actions['update'] = sprintf( + '%3$s', + esc_url( $this->get_tgmpa_status_url( 'update' ) ), + esc_attr__( 'This plugin needs to be updated to be compatible with your theme.', 'tgmpa' ), + esc_html__( 'Update Required', 'tgmpa' ) + ); + + return $actions; + } + + /** + * Handles calls to show plugin information via links in the notices. + * + * We get the links in the admin notices to point to the TGMPA page, rather + * than the typical plugin-install.php file, so we can prepare everything + * beforehand. + * + * WP does not make it easy to show the plugin information in the thickbox - + * here we have to require a file that includes a function that does the + * main work of displaying it, enqueue some styles, set up some globals and + * finally call that function before exiting. + * + * Down right easy once you know how... + * + * Returns early if not the TGMPA page. + * + * @since 2.1.0 + * + * @global string $tab Used as iframe div class names, helps with styling + * @global string $body_id Used as the iframe body ID, helps with styling + * + * @return null Returns early if not the TGMPA page. + */ + public function admin_init() { + if ( ! $this->is_tgmpa_page() ) { + return; + } + + if ( isset( $_REQUEST['tab'] ) && 'plugin-information' === $_REQUEST['tab'] ) { + // Needed for install_plugin_information(). + require_once ABSPATH . 'wp-admin/includes/plugin-install.php'; + + wp_enqueue_style( 'plugin-install' ); + + global $tab, $body_id; + $body_id = 'plugin-information'; + // @codingStandardsIgnoreStart + $tab = 'plugin-information'; + // @codingStandardsIgnoreEnd + + install_plugin_information(); + + exit; + } + } + + /** + * Enqueue thickbox scripts/styles for plugin info. + * + * Thickbox is not automatically included on all admin pages, so we must + * manually enqueue it for those pages. + * + * Thickbox is only loaded if the user has not dismissed the admin + * notice or if there are any plugins left to install and activate. + * + * @since 2.1.0 + */ + public function thickbox() { + if ( ! get_user_meta( get_current_user_id(), 'tgmpa_dismissed_notice_' . $this->id, true ) ) { + add_thickbox(); + } + } + + /** + * Adds submenu page if there are plugin actions to take. + * + * This method adds the submenu page letting users know that a required + * plugin needs to be installed. + * + * This page disappears once the plugin has been installed and activated. + * + * @since 1.0.0 + * + * @see TGM_Plugin_Activation::init() + * @see TGM_Plugin_Activation::install_plugins_page() + * + * @return null Return early if user lacks capability to install a plugin. + */ + public function admin_menu() { + // Make sure privileges are correct to see the page. + if ( ! current_user_can( 'install_plugins' ) ) { + return; + } + + $args = apply_filters( + 'tgmpa_admin_menu_args', + array( + 'parent_slug' => $this->parent_slug, // Parent Menu slug. + 'page_title' => $this->strings['page_title'], // Page title. + 'menu_title' => $this->strings['menu_title'], // Menu title. + 'capability' => $this->capability, // Capability. + 'menu_slug' => $this->menu, // Menu slug. + 'function' => array( $this, 'install_plugins_page' ), // Callback. + ) + ); + + $this->add_admin_menu( $args ); + } + + /** + * Add the menu item. + * + * {@internal IMPORTANT! If this function changes, review the regex in the custom TGMPA + * generator on the website.}} + * + * @since 2.5.0 + * + * @param array $args Menu item configuration. + */ + protected function add_admin_menu( array $args ) { + if ( has_filter( 'tgmpa_admin_menu_use_add_theme_page' ) ) { + _deprecated_function( 'The "tgmpa_admin_menu_use_add_theme_page" filter', '2.5.0', esc_html__( 'Set the parent_slug config variable instead.', 'tgmpa' ) ); + } + + if ( 'themes.php' === $this->parent_slug ) { + $this->page_hook = call_user_func( 'add_theme_page', $args['page_title'], $args['menu_title'], $args['capability'], $args['menu_slug'], $args['function'] ); + } else { + $this->page_hook = call_user_func( 'add_submenu_page', $args['parent_slug'], $args['page_title'], $args['menu_title'], $args['capability'], $args['menu_slug'], $args['function'] ); + } + } + + /** + * Echoes plugin installation form. + * + * This method is the callback for the admin_menu method function. + * This displays the admin page and form area where the user can select to install and activate the plugin. + * Aborts early if we're processing a plugin installation action. + * + * @since 1.0.0 + * + * @return null Aborts early if we're processing a plugin installation action. + */ + public function install_plugins_page() { + // Store new instance of plugin table in object. + $plugin_table = new TGMPA_List_Table; + + // Return early if processing a plugin installation action. + if ( ( ( 'tgmpa-bulk-install' === $plugin_table->current_action() || 'tgmpa-bulk-update' === $plugin_table->current_action() ) && $plugin_table->process_bulk_actions() ) || $this->do_plugin_install() ) { + return; + } + + // Force refresh of available plugin information so we'll know about manual updates/deletes. + wp_clean_plugins_cache( false ); + + ?> +
+

+ prepare_items(); ?> + + message ) && is_string( $this->message ) ) { + echo wp_kses_post( $this->message ); + } + ?> + views(); ?> + +
+ + + display(); ?> +
+
+ sanitize_key( urldecode( $_GET['plugin'] ) ); + + if ( ! isset( $this->plugins[ $slug ] ) ) { + return false; + } + + // Was an install or upgrade action link clicked? + if ( ( isset( $_GET['tgmpa-install'] ) && 'install-plugin' === $_GET['tgmpa-install'] ) || ( isset( $_GET['tgmpa-update'] ) && 'update-plugin' === $_GET['tgmpa-update'] ) ) { + + $install_type = 'install'; + if ( isset( $_GET['tgmpa-update'] ) && 'update-plugin' === $_GET['tgmpa-update'] ) { + $install_type = 'update'; + } + + check_admin_referer( 'tgmpa-' . $install_type, 'tgmpa-nonce' ); + + // Pass necessary information via URL if WP_Filesystem is needed. + $url = wp_nonce_url( + add_query_arg( + array( + 'plugin' => urlencode( $slug ), + 'tgmpa-' . $install_type => $install_type . '-plugin', + ), + $this->get_tgmpa_url() + ), + 'tgmpa-' . $install_type, + 'tgmpa-nonce' + ); + + $method = ''; // Leave blank so WP_Filesystem can populate it as necessary. + + if ( false === ( $creds = request_filesystem_credentials( esc_url_raw( $url ), $method, false, false, array() ) ) ) { + return true; + } + + if ( ! WP_Filesystem( $creds ) ) { + request_filesystem_credentials( esc_url_raw( $url ), $method, true, false, array() ); // Setup WP_Filesystem. + return true; + } + + /* If we arrive here, we have the filesystem. */ + + // Prep variables for Plugin_Installer_Skin class. + $extra = array(); + $extra['slug'] = $slug; // Needed for potentially renaming of directory name. + $source = $this->get_download_url( $slug ); + $api = ( 'repo' === $this->plugins[ $slug ]['source_type'] ) ? $this->get_plugins_api( $slug ) : null; + $api = ( false !== $api ) ? $api : null; + + $url = add_query_arg( + array( + 'action' => $install_type . '-plugin', + 'plugin' => urlencode( $slug ), + ), + 'update.php' + ); + + if ( ! class_exists( 'Plugin_Upgrader', false ) ) { + require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; + } + + $title = ( 'update' === $install_type ) ? $this->strings['updating'] : $this->strings['installing']; + $skin_args = array( + 'type' => ( 'bundled' !== $this->plugins[ $slug ]['source_type'] ) ? 'web' : 'upload', + 'title' => sprintf( $title, $this->plugins[ $slug ]['name'] ), + 'url' => esc_url_raw( $url ), + 'nonce' => $install_type . '-plugin_' . $slug, + 'plugin' => '', + 'api' => $api, + 'extra' => $extra, + ); + unset( $title ); + + if ( 'update' === $install_type ) { + $skin_args['plugin'] = $this->plugins[ $slug ]['file_path']; + $skin = new Plugin_Upgrader_Skin( $skin_args ); + } else { + $skin = new Plugin_Installer_Skin( $skin_args ); + } + + // Create a new instance of Plugin_Upgrader. + $upgrader = new Plugin_Upgrader( $skin ); + + // Perform the action and install the plugin from the $source urldecode(). + add_filter( 'upgrader_source_selection', array( $this, 'maybe_adjust_source_dir' ), 1, 3 ); + + if ( 'update' === $install_type ) { + // Inject our info into the update transient. + $to_inject = array( $slug => $this->plugins[ $slug ] ); + $to_inject[ $slug ]['source'] = $source; + $this->inject_update_info( $to_inject ); + + $upgrader->upgrade( $this->plugins[ $slug ]['file_path'] ); + } else { + $upgrader->install( $source ); + } + + remove_filter( 'upgrader_source_selection', array( $this, 'maybe_adjust_source_dir' ), 1 ); + + // Make sure we have the correct file path now the plugin is installed/updated. + $this->populate_file_path( $slug ); + + // Only activate plugins if the config option is set to true and the plugin isn't + // already active (upgrade). + if ( $this->is_automatic && ! $this->is_plugin_active( $slug ) ) { + $plugin_activate = $upgrader->plugin_info(); // Grab the plugin info from the Plugin_Upgrader method. + if ( false === $this->activate_single_plugin( $plugin_activate, $slug, true ) ) { + return true; // Finish execution of the function early as we encountered an error. + } + } + + $this->show_tgmpa_version(); + + // Display message based on if all plugins are now active or not. + if ( $this->is_tgmpa_complete() ) { + echo '

', sprintf( esc_html( $this->strings['complete'] ), '' . esc_html__( 'Return to the Dashboard', 'tgmpa' ) . '' ), '

'; + echo ''; + } else { + echo '

', esc_html( $this->strings['return'] ), '

'; + } + + return true; + } elseif ( isset( $this->plugins[ $slug ]['file_path'], $_GET['tgmpa-activate'] ) && 'activate-plugin' === $_GET['tgmpa-activate'] ) { + // Activate action link was clicked. + check_admin_referer( 'tgmpa-activate', 'tgmpa-nonce' ); + + if ( false === $this->activate_single_plugin( $this->plugins[ $slug ]['file_path'], $slug ) ) { + return true; // Finish execution of the function early as we encountered an error. + } + } + + return false; + } + + /** + * Inject information into the 'update_plugins' site transient as WP checks that before running an update. + * + * @since 2.5.0 + * + * @param array $plugins The plugin information for the plugins which are to be updated. + */ + public function inject_update_info( $plugins ) { + $repo_updates = get_site_transient( 'update_plugins' ); + + if ( ! is_object( $repo_updates ) ) { + $repo_updates = new stdClass; + } + + foreach ( $plugins as $slug => $plugin ) { + $file_path = $plugin['file_path']; + + if ( empty( $repo_updates->response[ $file_path ] ) ) { + $repo_updates->response[ $file_path ] = new stdClass; + } + + // We only really need to set package, but let's do all we can in case WP changes something. + $repo_updates->response[ $file_path ]->slug = $slug; + $repo_updates->response[ $file_path ]->plugin = $file_path; + $repo_updates->response[ $file_path ]->new_version = $plugin['version']; + $repo_updates->response[ $file_path ]->package = $plugin['source']; + if ( empty( $repo_updates->response[ $file_path ]->url ) && ! empty( $plugin['external_url'] ) ) { + $repo_updates->response[ $file_path ]->url = $plugin['external_url']; + } + } + + set_site_transient( 'update_plugins', $repo_updates ); + } + + /** + * Adjust the plugin directory name if necessary. + * + * The final destination directory of a plugin is based on the subdirectory name found in the + * (un)zipped source. In some cases - most notably GitHub repository plugin downloads -, this + * subdirectory name is not the same as the expected slug and the plugin will not be recognized + * as installed. This is fixed by adjusting the temporary unzipped source subdirectory name to + * the expected plugin slug. + * + * @since 2.5.0 + * + * @param string $source Path to upgrade/zip-file-name.tmp/subdirectory/. + * @param string $remote_source Path to upgrade/zip-file-name.tmp. + * @param \WP_Upgrader $upgrader Instance of the upgrader which installs the plugin. + * @return string $source + */ + public function maybe_adjust_source_dir( $source, $remote_source, $upgrader ) { + if ( ! $this->is_tgmpa_page() || ! is_object( $GLOBALS['wp_filesystem'] ) ) { + return $source; + } + + // Check for single file plugins. + $source_files = array_keys( $GLOBALS['wp_filesystem']->dirlist( $remote_source ) ); + if ( 1 === count( $source_files ) && false === $GLOBALS['wp_filesystem']->is_dir( $source ) ) { + return $source; + } + + // Multi-file plugin, let's see if the directory is correctly named. + $desired_slug = ''; + + // Figure out what the slug is supposed to be. + if ( false === $upgrader->bulk && ! empty( $upgrader->skin->options['extra']['slug'] ) ) { + $desired_slug = $upgrader->skin->options['extra']['slug']; + } else { + // Bulk installer contains less info, so fall back on the info registered here. + foreach ( $this->plugins as $slug => $plugin ) { + if ( ! empty( $upgrader->skin->plugin_names[ $upgrader->skin->i ] ) && $plugin['name'] === $upgrader->skin->plugin_names[ $upgrader->skin->i ] ) { + $desired_slug = $slug; + break; + } + } + unset( $slug, $plugin ); + } + + if ( ! empty( $desired_slug ) ) { + $subdir_name = untrailingslashit( str_replace( trailingslashit( $remote_source ), '', $source ) ); + + if ( ! empty( $subdir_name ) && $subdir_name !== $desired_slug ) { + $from_path = untrailingslashit( $source ); + $to_path = trailingslashit( $remote_source ) . $desired_slug; + + if ( true === $GLOBALS['wp_filesystem']->move( $from_path, $to_path ) ) { + return trailingslashit( $to_path ); + } else { + return new WP_Error( 'rename_failed', esc_html__( 'The remote plugin package does not contain a folder with the desired slug and renaming did not work.', 'tgmpa' ) . ' ' . esc_html__( 'Please contact the plugin provider and ask them to package their plugin according to the WordPress guidelines.', 'tgmpa' ), array( 'found' => $subdir_name, 'expected' => $desired_slug ) ); + } + } elseif ( empty( $subdir_name ) ) { + return new WP_Error( 'packaged_wrong', esc_html__( 'The remote plugin package consists of more than one file, but the files are not packaged in a folder.', 'tgmpa' ) . ' ' . esc_html__( 'Please contact the plugin provider and ask them to package their plugin according to the WordPress guidelines.', 'tgmpa' ), array( 'found' => $subdir_name, 'expected' => $desired_slug ) ); + } + } + + return $source; + } + + /** + * Activate a single plugin and send feedback about the result to the screen. + * + * @since 2.5.0 + * + * @param string $file_path Path within wp-plugins/ to main plugin file. + * @param string $slug Plugin slug. + * @param bool $automatic Whether this is an automatic activation after an install. Defaults to false. + * This determines the styling of the output messages. + * @return bool False if an error was encountered, true otherwise. + */ + protected function activate_single_plugin( $file_path, $slug, $automatic = false ) { + if ( $this->can_plugin_activate( $slug ) ) { + $activate = activate_plugin( $file_path ); + + if ( is_wp_error( $activate ) ) { + echo '

', wp_kses_post( $activate->get_error_message() ), '

', + '

', esc_html( $this->strings['return'] ), '

'; + + return false; // End it here if there is an error with activation. + } else { + if ( ! $automatic ) { + // Make sure message doesn't display again if bulk activation is performed + // immediately after a single activation. + if ( ! isset( $_POST['action'] ) ) { // WPCS: CSRF OK. + echo '

', esc_html( $this->strings['activated_successfully'] ), ' ', esc_html( $this->plugins[ $slug ]['name'] ), '.

'; + } + } else { + // Simpler message layout for use on the plugin install page. + echo '

', esc_html( $this->strings['plugin_activated'] ), '

'; + } + } + } elseif ( $this->is_plugin_active( $slug ) ) { + // No simpler message format provided as this message should never be encountered + // on the plugin install page. + echo '

', + sprintf( + esc_html( $this->strings['plugin_already_active'] ), + '' . esc_html( $this->plugins[ $slug ]['name'] ) . '' + ), + '

'; + } elseif ( $this->does_plugin_require_update( $slug ) ) { + if ( ! $automatic ) { + // Make sure message doesn't display again if bulk activation is performed + // immediately after a single activation. + if ( ! isset( $_POST['action'] ) ) { // WPCS: CSRF OK. + echo '

', + sprintf( + esc_html( $this->strings['plugin_needs_higher_version'] ), + '' . esc_html( $this->plugins[ $slug ]['name'] ) . '' + ), + '

'; + } + } else { + // Simpler message layout for use on the plugin install page. + echo '

', sprintf( esc_html( $this->strings['plugin_needs_higher_version'] ), esc_html( $this->plugins[ $slug ]['name'] ) ), '

'; + } + } + + return true; + } + + /** + * Echoes required plugin notice. + * + * Outputs a message telling users that a specific plugin is required for + * their theme. If appropriate, it includes a link to the form page where + * users can install and activate the plugin. + * + * Returns early if we're on the Install page. + * + * @since 1.0.0 + * + * @global object $current_screen + * + * @return null Returns early if we're on the Install page. + */ + public function notices() { + // Remove nag on the install page / Return early if the nag message has been dismissed or user < author. + if ( ( $this->is_tgmpa_page() || $this->is_core_update_page() ) || get_user_meta( get_current_user_id(), 'tgmpa_dismissed_notice_' . $this->id, true ) || ! current_user_can( apply_filters( 'tgmpa_show_admin_notice_capability', 'publish_posts' ) ) ) { + return; + } + + // Store for the plugin slugs by message type. + $message = array(); + + // Initialize counters used to determine plurality of action link texts. + $install_link_count = 0; + $update_link_count = 0; + $activate_link_count = 0; + $total_required_action_count = 0; + + foreach ( $this->plugins as $slug => $plugin ) { + if ( $this->is_plugin_active( $slug ) && false === $this->does_plugin_have_update( $slug ) ) { + continue; + } + + if ( ! $this->is_plugin_installed( $slug ) ) { + if ( current_user_can( 'install_plugins' ) ) { + $install_link_count++; + + if ( true === $plugin['required'] ) { + $message['notice_can_install_required'][] = $slug; + } else { + $message['notice_can_install_recommended'][] = $slug; + } + } + if ( true === $plugin['required'] ) { + $total_required_action_count++; + } + } else { + if ( ! $this->is_plugin_active( $slug ) && $this->can_plugin_activate( $slug ) ) { + if ( current_user_can( 'activate_plugins' ) ) { + $activate_link_count++; + + if ( true === $plugin['required'] ) { + $message['notice_can_activate_required'][] = $slug; + } else { + $message['notice_can_activate_recommended'][] = $slug; + } + } + if ( true === $plugin['required'] ) { + $total_required_action_count++; + } + } + + if ( $this->does_plugin_require_update( $slug ) || false !== $this->does_plugin_have_update( $slug ) ) { + + if ( current_user_can( 'update_plugins' ) ) { + $update_link_count++; + + if ( $this->does_plugin_require_update( $slug ) ) { + $message['notice_ask_to_update'][] = $slug; + } elseif ( false !== $this->does_plugin_have_update( $slug ) ) { + $message['notice_ask_to_update_maybe'][] = $slug; + } + } + if ( true === $plugin['required'] ) { + $total_required_action_count++; + } + } + } + } + unset( $slug, $plugin ); + + // If we have notices to display, we move forward. + if ( ! empty( $message ) || $total_required_action_count > 0 ) { + krsort( $message ); // Sort messages. + $rendered = ''; + + // As add_settings_error() wraps the final message in a

and as the final message can't be + // filtered, using

's in our html would render invalid html output. + $line_template = '%s' . "\n"; + + if ( ! current_user_can( 'activate_plugins' ) && ! current_user_can( 'install_plugins' ) && ! current_user_can( 'update_plugins' ) ) { + $rendered = esc_html( $this->strings['notice_cannot_install_activate'] ) . ' ' . esc_html( $this->strings['contact_admin'] ); + $rendered .= $this->create_user_action_links_for_notice( 0, 0, 0, $line_template ); + } else { + + // If dismissable is false and a message is set, output it now. + if ( ! $this->dismissable && ! empty( $this->dismiss_msg ) ) { + $rendered .= sprintf( $line_template, wp_kses_post( $this->dismiss_msg ) ); + } + + // Render the individual message lines for the notice. + foreach ( $message as $type => $plugin_group ) { + $linked_plugins = array(); + + // Get the external info link for a plugin if one is available. + foreach ( $plugin_group as $plugin_slug ) { + $linked_plugins[] = $this->get_info_link( $plugin_slug ); + } + unset( $plugin_slug ); + + $count = count( $plugin_group ); + $linked_plugins = array_map( array( 'TGMPA_Utils', 'wrap_in_em' ), $linked_plugins ); + $last_plugin = array_pop( $linked_plugins ); // Pop off last name to prep for readability. + $imploded = empty( $linked_plugins ) ? $last_plugin : ( implode( ', ', $linked_plugins ) . ' ' . esc_html_x( 'and', 'plugin A *and* plugin B', 'tgmpa' ) . ' ' . $last_plugin ); + + $rendered .= sprintf( + $line_template, + sprintf( + translate_nooped_plural( $this->strings[ $type ], $count, 'tgmpa' ), + $imploded, + $count + ) + ); + + } + unset( $type, $plugin_group, $linked_plugins, $count, $last_plugin, $imploded ); + + $rendered .= $this->create_user_action_links_for_notice( $install_link_count, $update_link_count, $activate_link_count, $line_template ); + } + + // Register the nag messages and prepare them to be processed. + add_settings_error( 'tgmpa', 'tgmpa', $rendered, $this->get_admin_notice_class() ); + } + + // Admin options pages already output settings_errors, so this is to avoid duplication. + if ( 'options-general' !== $GLOBALS['current_screen']->parent_base ) { + $this->display_settings_errors(); + } + } + + /** + * Generate the user action links for the admin notice. + * + * @since 2.6.0 + * + * @param int $install_count Number of plugins to install. + * @param int $update_count Number of plugins to update. + * @param int $activate_count Number of plugins to activate. + * @param int $line_template Template for the HTML tag to output a line. + * @return string Action links. + */ + protected function create_user_action_links_for_notice( $install_count, $update_count, $activate_count, $line_template ) { + // Setup action links. + $action_links = array( + 'install' => '', + 'update' => '', + 'activate' => '', + 'dismiss' => $this->dismissable ? '' . esc_html( $this->strings['dismiss'] ) . '' : '', + ); + + $link_template = '%1$s'; + + if ( current_user_can( 'install_plugins' ) ) { + if ( $install_count > 0 ) { + $action_links['install'] = sprintf( + $link_template, + translate_nooped_plural( $this->strings['install_link'], $install_count, 'tgmpa' ), + esc_url( $this->get_tgmpa_status_url( 'install' ) ) + ); + } + if ( $update_count > 0 ) { + $action_links['update'] = sprintf( + $link_template, + translate_nooped_plural( $this->strings['update_link'], $update_count, 'tgmpa' ), + esc_url( $this->get_tgmpa_status_url( 'update' ) ) + ); + } + } + + if ( current_user_can( 'activate_plugins' ) && $activate_count > 0 ) { + $action_links['activate'] = sprintf( + $link_template, + translate_nooped_plural( $this->strings['activate_link'], $activate_count, 'tgmpa' ), + esc_url( $this->get_tgmpa_status_url( 'activate' ) ) + ); + } + + $action_links = apply_filters( 'tgmpa_notice_action_links', $action_links ); + + $action_links = array_filter( (array) $action_links ); // Remove any empty array items. + + if ( ! empty( $action_links ) ) { + $action_links = sprintf( $line_template, implode( ' | ', $action_links ) ); + return apply_filters( 'tgmpa_notice_rendered_action_links', $action_links ); + } else { + return ''; + } + } + + /** + * Get admin notice class. + * + * Work around all the changes to the various admin notice classes between WP 4.4 and 3.7 + * (lowest supported version by TGMPA). + * + * @since 2.6.0 + * + * @return string + */ + protected function get_admin_notice_class() { + if ( ! empty( $this->strings['nag_type'] ) ) { + return sanitize_html_class( strtolower( $this->strings['nag_type'] ) ); + } else { + if ( version_compare( $this->wp_version, '4.2', '>=' ) ) { + return 'notice-warning'; + } elseif ( version_compare( $this->wp_version, '4.1', '>=' ) ) { + return 'notice'; + } else { + return 'updated'; + } + } + } + + /** + * Display settings errors and remove those which have been displayed to avoid duplicate messages showing + * + * @since 2.5.0 + */ + protected function display_settings_errors() { + global $wp_settings_errors; + + settings_errors( 'tgmpa' ); + + foreach ( (array) $wp_settings_errors as $key => $details ) { + if ( 'tgmpa' === $details['setting'] ) { + unset( $wp_settings_errors[ $key ] ); + break; + } + } + } + + /** + * Register dismissal of admin notices. + * + * Acts on the dismiss link in the admin nag messages. + * If clicked, the admin notice disappears and will no longer be visible to this user. + * + * @since 2.1.0 + */ + public function dismiss() { + if ( isset( $_GET['tgmpa-dismiss'] ) && check_admin_referer( 'tgmpa-dismiss-' . get_current_user_id() ) ) { + update_user_meta( get_current_user_id(), 'tgmpa_dismissed_notice_' . $this->id, 1 ); + } + } + + /** + * Add individual plugin to our collection of plugins. + * + * If the required keys are not set or the plugin has already + * been registered, the plugin is not added. + * + * @since 2.0.0 + * + * @param array|null $plugin Array of plugin arguments or null if invalid argument. + * @return null Return early if incorrect argument. + */ + public function register( $plugin ) { + if ( empty( $plugin['slug'] ) || empty( $plugin['name'] ) ) { + return; + } + + if ( empty( $plugin['slug'] ) || ! is_string( $plugin['slug'] ) || isset( $this->plugins[ $plugin['slug'] ] ) ) { + return; + } + + $defaults = array( + 'name' => '', // String + 'slug' => '', // String + 'source' => 'repo', // String + 'required' => false, // Boolean + 'version' => '', // String + 'force_activation' => false, // Boolean + 'force_deactivation' => false, // Boolean + 'external_url' => '', // String + 'is_callable' => '', // String|Array. + ); + + // Prepare the received data. + $plugin = wp_parse_args( $plugin, $defaults ); + + // Standardize the received slug. + $plugin['slug'] = $this->sanitize_key( $plugin['slug'] ); + + // Forgive users for using string versions of booleans or floats for version number. + $plugin['version'] = (string) $plugin['version']; + $plugin['source'] = empty( $plugin['source'] ) ? 'repo' : $plugin['source']; + $plugin['required'] = TGMPA_Utils::validate_bool( $plugin['required'] ); + $plugin['force_activation'] = TGMPA_Utils::validate_bool( $plugin['force_activation'] ); + $plugin['force_deactivation'] = TGMPA_Utils::validate_bool( $plugin['force_deactivation'] ); + + // Enrich the received data. + $plugin['file_path'] = $this->_get_plugin_basename_from_slug( $plugin['slug'] ); + $plugin['source_type'] = $this->get_plugin_source_type( $plugin['source'] ); + + // Set the class properties. + $this->plugins[ $plugin['slug'] ] = $plugin; + $this->sort_order[ $plugin['slug'] ] = $plugin['name']; + + // Should we add the force activation hook ? + if ( true === $plugin['force_activation'] ) { + $this->has_forced_activation = true; + } + + // Should we add the force deactivation hook ? + if ( true === $plugin['force_deactivation'] ) { + $this->has_forced_deactivation = true; + } + } + + /** + * Determine what type of source the plugin comes from. + * + * @since 2.5.0 + * + * @param string $source The source of the plugin as provided, either empty (= WP repo), a file path + * (= bundled) or an external URL. + * @return string 'repo', 'external', or 'bundled' + */ + protected function get_plugin_source_type( $source ) { + if ( 'repo' === $source || preg_match( self::WP_REPO_REGEX, $source ) ) { + return 'repo'; + } elseif ( preg_match( self::IS_URL_REGEX, $source ) ) { + return 'external'; + } else { + return 'bundled'; + } + } + + /** + * Sanitizes a string key. + * + * Near duplicate of WP Core `sanitize_key()`. The difference is that uppercase characters *are* + * allowed, so as not to break upgrade paths from non-standard bundled plugins using uppercase + * characters in the plugin directory path/slug. Silly them. + * + * @see https://developer.wordpress.org/reference/hooks/sanitize_key/ + * + * @since 2.5.0 + * + * @param string $key String key. + * @return string Sanitized key + */ + public function sanitize_key( $key ) { + $raw_key = $key; + $key = preg_replace( '`[^A-Za-z0-9_-]`', '', $key ); + + /** + * Filter a sanitized key string. + * + * @since 2.5.0 + * + * @param string $key Sanitized key. + * @param string $raw_key The key prior to sanitization. + */ + return apply_filters( 'tgmpa_sanitize_key', $key, $raw_key ); + } + + /** + * Amend default configuration settings. + * + * @since 2.0.0 + * + * @param array $config Array of config options to pass as class properties. + */ + public function config( $config ) { + $keys = array( + 'id', + 'default_path', + 'has_notices', + 'dismissable', + 'dismiss_msg', + 'menu', + 'parent_slug', + 'capability', + 'is_automatic', + 'message', + 'strings', + ); + + foreach ( $keys as $key ) { + if ( isset( $config[ $key ] ) ) { + if ( is_array( $config[ $key ] ) ) { + $this->$key = array_merge( $this->$key, $config[ $key ] ); + } else { + $this->$key = $config[ $key ]; + } + } + } + } + + /** + * Amend action link after plugin installation. + * + * @since 2.0.0 + * + * @param array $install_actions Existing array of actions. + * @return false|array Amended array of actions. + */ + public function actions( $install_actions ) { + // Remove action links on the TGMPA install page. + if ( $this->is_tgmpa_page() ) { + return false; + } + + return $install_actions; + } + + /** + * Flushes the plugins cache on theme switch to prevent stale entries + * from remaining in the plugin table. + * + * @since 2.4.0 + * + * @param bool $clear_update_cache Optional. Whether to clear the Plugin updates cache. + * Parameter added in v2.5.0. + */ + public function flush_plugins_cache( $clear_update_cache = true ) { + wp_clean_plugins_cache( $clear_update_cache ); + } + + /** + * Set file_path key for each installed plugin. + * + * @since 2.1.0 + * + * @param string $plugin_slug Optional. If set, only (re-)populates the file path for that specific plugin. + * Parameter added in v2.5.0. + */ + public function populate_file_path( $plugin_slug = '' ) { + if ( ! empty( $plugin_slug ) && is_string( $plugin_slug ) && isset( $this->plugins[ $plugin_slug ] ) ) { + $this->plugins[ $plugin_slug ]['file_path'] = $this->_get_plugin_basename_from_slug( $plugin_slug ); + } else { + // Add file_path key for all plugins. + foreach ( $this->plugins as $slug => $values ) { + $this->plugins[ $slug ]['file_path'] = $this->_get_plugin_basename_from_slug( $slug ); + } + } + } + + /** + * Helper function to extract the file path of the plugin file from the + * plugin slug, if the plugin is installed. + * + * @since 2.0.0 + * + * @param string $slug Plugin slug (typically folder name) as provided by the developer. + * @return string Either file path for plugin if installed, or just the plugin slug. + */ + protected function _get_plugin_basename_from_slug( $slug ) { + $keys = array_keys( $this->get_plugins() ); + + foreach ( $keys as $key ) { + if ( preg_match( '|^' . $slug . '/|', $key ) ) { + return $key; + } + } + + return $slug; + } + + /** + * Retrieve plugin data, given the plugin name. + * + * Loops through the registered plugins looking for $name. If it finds it, + * it returns the $data from that plugin. Otherwise, returns false. + * + * @since 2.1.0 + * + * @param string $name Name of the plugin, as it was registered. + * @param string $data Optional. Array key of plugin data to return. Default is slug. + * @return string|boolean Plugin slug if found, false otherwise. + */ + public function _get_plugin_data_from_name( $name, $data = 'slug' ) { + foreach ( $this->plugins as $values ) { + if ( $name === $values['name'] && isset( $values[ $data ] ) ) { + return $values[ $data ]; + } + } + + return false; + } + + /** + * Retrieve the download URL for a package. + * + * @since 2.5.0 + * + * @param string $slug Plugin slug. + * @return string Plugin download URL or path to local file or empty string if undetermined. + */ + public function get_download_url( $slug ) { + $dl_source = ''; + + switch ( $this->plugins[ $slug ]['source_type'] ) { + case 'repo': + return $this->get_wp_repo_download_url( $slug ); + case 'external': + return $this->plugins[ $slug ]['source']; + case 'bundled': + return $this->default_path . $this->plugins[ $slug ]['source']; + } + + return $dl_source; // Should never happen. + } + + /** + * Retrieve the download URL for a WP repo package. + * + * @since 2.5.0 + * + * @param string $slug Plugin slug. + * @return string Plugin download URL. + */ + protected function get_wp_repo_download_url( $slug ) { + $source = ''; + $api = $this->get_plugins_api( $slug ); + + if ( false !== $api && isset( $api->download_link ) ) { + $source = $api->download_link; + } + + return $source; + } + + /** + * Try to grab information from WordPress API. + * + * @since 2.5.0 + * + * @param string $slug Plugin slug. + * @return object Plugins_api response object on success, WP_Error on failure. + */ + protected function get_plugins_api( $slug ) { + static $api = array(); // Cache received responses. + + if ( ! isset( $api[ $slug ] ) ) { + if ( ! function_exists( 'plugins_api' ) ) { + require_once ABSPATH . 'wp-admin/includes/plugin-install.php'; + } + + $response = plugins_api( 'plugin_information', array( 'slug' => $slug, 'fields' => array( 'sections' => false ) ) ); + + $api[ $slug ] = false; + + if ( is_wp_error( $response ) ) { + wp_die( esc_html( $this->strings['oops'] ) ); + } else { + $api[ $slug ] = $response; + } + } + + return $api[ $slug ]; + } + + /** + * Retrieve a link to a plugin information page. + * + * @since 2.5.0 + * + * @param string $slug Plugin slug. + * @return string Fully formed html link to a plugin information page if available + * or the plugin name if not. + */ + public function get_info_link( $slug ) { + if ( ! empty( $this->plugins[ $slug ]['external_url'] ) && preg_match( self::IS_URL_REGEX, $this->plugins[ $slug ]['external_url'] ) ) { + $link = sprintf( + '%2$s', + esc_url( $this->plugins[ $slug ]['external_url'] ), + esc_html( $this->plugins[ $slug ]['name'] ) + ); + } elseif ( 'repo' === $this->plugins[ $slug ]['source_type'] ) { + $url = add_query_arg( + array( + 'tab' => 'plugin-information', + 'plugin' => urlencode( $slug ), + 'TB_iframe' => 'true', + 'width' => '640', + 'height' => '500', + ), + self_admin_url( 'plugin-install.php' ) + ); + + $link = sprintf( + '%2$s', + esc_url( $url ), + esc_html( $this->plugins[ $slug ]['name'] ) + ); + } else { + $link = esc_html( $this->plugins[ $slug ]['name'] ); // No hyperlink. + } + + return $link; + } + + /** + * Determine if we're on the TGMPA Install page. + * + * @since 2.1.0 + * + * @return boolean True when on the TGMPA page, false otherwise. + */ + protected function is_tgmpa_page() { + return isset( $_GET['page'] ) && $this->menu === $_GET['page']; + } + + /** + * Determine if we're on a WP Core installation/upgrade page. + * + * @since 2.6.0 + * + * @return boolean True when on a WP Core installation/upgrade page, false otherwise. + */ + protected function is_core_update_page() { + // Current screen is not always available, most notably on the customizer screen. + if ( ! function_exists( 'get_current_screen' ) ) { + return false; + } + + $screen = get_current_screen(); + + if ( 'update-core' === $screen->base ) { + // Core update screen. + return true; + } elseif ( 'plugins' === $screen->base && ! empty( $_POST['action'] ) ) { // WPCS: CSRF ok. + // Plugins bulk update screen. + return true; + } elseif ( 'update' === $screen->base && ! empty( $_POST['action'] ) ) { // WPCS: CSRF ok. + // Individual updates (ajax call). + return true; + } + + return false; + } + + /** + * Retrieve the URL to the TGMPA Install page. + * + * I.e. depending on the config settings passed something along the lines of: + * http://example.com/wp-admin/themes.php?page=tgmpa-install-plugins + * + * @since 2.5.0 + * + * @return string Properly encoded URL (not escaped). + */ + public function get_tgmpa_url() { + static $url; + + if ( ! isset( $url ) ) { + $parent = $this->parent_slug; + if ( false === strpos( $parent, '.php' ) ) { + $parent = 'admin.php'; + } + $url = add_query_arg( + array( + 'page' => urlencode( $this->menu ), + ), + self_admin_url( $parent ) + ); + } + + return $url; + } + + /** + * Retrieve the URL to the TGMPA Install page for a specific plugin status (view). + * + * I.e. depending on the config settings passed something along the lines of: + * http://example.com/wp-admin/themes.php?page=tgmpa-install-plugins&plugin_status=install + * + * @since 2.5.0 + * + * @param string $status Plugin status - either 'install', 'update' or 'activate'. + * @return string Properly encoded URL (not escaped). + */ + public function get_tgmpa_status_url( $status ) { + return add_query_arg( + array( + 'plugin_status' => urlencode( $status ), + ), + $this->get_tgmpa_url() + ); + } + + /** + * Determine whether there are open actions for plugins registered with TGMPA. + * + * @since 2.5.0 + * + * @return bool True if complete, i.e. no outstanding actions. False otherwise. + */ + public function is_tgmpa_complete() { + $complete = true; + foreach ( $this->plugins as $slug => $plugin ) { + if ( ! $this->is_plugin_active( $slug ) || false !== $this->does_plugin_have_update( $slug ) ) { + $complete = false; + break; + } + } + + return $complete; + } + + /** + * Check if a plugin is installed. Does not take must-use plugins into account. + * + * @since 2.5.0 + * + * @param string $slug Plugin slug. + * @return bool True if installed, false otherwise. + */ + public function is_plugin_installed( $slug ) { + $installed_plugins = $this->get_plugins(); // Retrieve a list of all installed plugins (WP cached). + + return ( ! empty( $installed_plugins[ $this->plugins[ $slug ]['file_path'] ] ) ); + } + + /** + * Check if a plugin is active. + * + * @since 2.5.0 + * + * @param string $slug Plugin slug. + * @return bool True if active, false otherwise. + */ + public function is_plugin_active( $slug ) { + return ( ( ! empty( $this->plugins[ $slug ]['is_callable'] ) && is_callable( $this->plugins[ $slug ]['is_callable'] ) ) || is_plugin_active( $this->plugins[ $slug ]['file_path'] ) ); + } + + /** + * Check if a plugin can be updated, i.e. if we have information on the minimum WP version required + * available, check whether the current install meets them. + * + * @since 2.5.0 + * + * @param string $slug Plugin slug. + * @return bool True if OK to update, false otherwise. + */ + public function can_plugin_update( $slug ) { + // We currently can't get reliable info on non-WP-repo plugins - issue #380. + if ( 'repo' !== $this->plugins[ $slug ]['source_type'] ) { + return true; + } + + $api = $this->get_plugins_api( $slug ); + + if ( false !== $api && isset( $api->requires ) ) { + return version_compare( $this->wp_version, $api->requires, '>=' ); + } + + // No usable info received from the plugins API, presume we can update. + return true; + } + + /** + * Check to see if the plugin is 'updatetable', i.e. installed, with an update available + * and no WP version requirements blocking it. + * + * @since 2.6.0 + * + * @param string $slug Plugin slug. + * @return bool True if OK to proceed with update, false otherwise. + */ + public function is_plugin_updatetable( $slug ) { + if ( ! $this->is_plugin_installed( $slug ) ) { + return false; + } else { + return ( false !== $this->does_plugin_have_update( $slug ) && $this->can_plugin_update( $slug ) ); + } + } + + /** + * Check if a plugin can be activated, i.e. is not currently active and meets the minimum + * plugin version requirements set in TGMPA (if any). + * + * @since 2.5.0 + * + * @param string $slug Plugin slug. + * @return bool True if OK to activate, false otherwise. + */ + public function can_plugin_activate( $slug ) { + return ( ! $this->is_plugin_active( $slug ) && ! $this->does_plugin_require_update( $slug ) ); + } + + /** + * Retrieve the version number of an installed plugin. + * + * @since 2.5.0 + * + * @param string $slug Plugin slug. + * @return string Version number as string or an empty string if the plugin is not installed + * or version unknown (plugins which don't comply with the plugin header standard). + */ + public function get_installed_version( $slug ) { + $installed_plugins = $this->get_plugins(); // Retrieve a list of all installed plugins (WP cached). + + if ( ! empty( $installed_plugins[ $this->plugins[ $slug ]['file_path'] ]['Version'] ) ) { + return $installed_plugins[ $this->plugins[ $slug ]['file_path'] ]['Version']; + } + + return ''; + } + + /** + * Check whether a plugin complies with the minimum version requirements. + * + * @since 2.5.0 + * + * @param string $slug Plugin slug. + * @return bool True when a plugin needs to be updated, otherwise false. + */ + public function does_plugin_require_update( $slug ) { + $installed_version = $this->get_installed_version( $slug ); + $minimum_version = $this->plugins[ $slug ]['version']; + + return version_compare( $minimum_version, $installed_version, '>' ); + } + + /** + * Check whether there is an update available for a plugin. + * + * @since 2.5.0 + * + * @param string $slug Plugin slug. + * @return false|string Version number string of the available update or false if no update available. + */ + public function does_plugin_have_update( $slug ) { + // Presume bundled and external plugins will point to a package which meets the minimum required version. + if ( 'repo' !== $this->plugins[ $slug ]['source_type'] ) { + if ( $this->does_plugin_require_update( $slug ) ) { + return $this->plugins[ $slug ]['version']; + } + + return false; + } + + $repo_updates = get_site_transient( 'update_plugins' ); + + if ( isset( $repo_updates->response[ $this->plugins[ $slug ]['file_path'] ]->new_version ) ) { + return $repo_updates->response[ $this->plugins[ $slug ]['file_path'] ]->new_version; + } + + return false; + } + + /** + * Retrieve potential upgrade notice for a plugin. + * + * @since 2.5.0 + * + * @param string $slug Plugin slug. + * @return string The upgrade notice or an empty string if no message was available or provided. + */ + public function get_upgrade_notice( $slug ) { + // We currently can't get reliable info on non-WP-repo plugins - issue #380. + if ( 'repo' !== $this->plugins[ $slug ]['source_type'] ) { + return ''; + } + + $repo_updates = get_site_transient( 'update_plugins' ); + + if ( ! empty( $repo_updates->response[ $this->plugins[ $slug ]['file_path'] ]->upgrade_notice ) ) { + return $repo_updates->response[ $this->plugins[ $slug ]['file_path'] ]->upgrade_notice; + } + + return ''; + } + + /** + * Wrapper around the core WP get_plugins function, making sure it's actually available. + * + * @since 2.5.0 + * + * @param string $plugin_folder Optional. Relative path to single plugin folder. + * @return array Array of installed plugins with plugin information. + */ + public function get_plugins( $plugin_folder = '' ) { + if ( ! function_exists( 'get_plugins' ) ) { + require_once ABSPATH . 'wp-admin/includes/plugin.php'; + } + + return get_plugins( $plugin_folder ); + } + + /** + * Delete dismissable nag option when theme is switched. + * + * This ensures that the user(s) is/are again reminded via nag of required + * and/or recommended plugins if they re-activate the theme. + * + * @since 2.1.1 + */ + public function update_dismiss() { + delete_metadata( 'user', null, 'tgmpa_dismissed_notice_' . $this->id, null, true ); + } + + /** + * Forces plugin activation if the parameter 'force_activation' is + * set to true. + * + * This allows theme authors to specify certain plugins that must be + * active at all times while using the current theme. + * + * Please take special care when using this parameter as it has the + * potential to be harmful if not used correctly. Setting this parameter + * to true will not allow the specified plugin to be deactivated unless + * the user switches themes. + * + * @since 2.2.0 + */ + public function force_activation() { + foreach ( $this->plugins as $slug => $plugin ) { + if ( true === $plugin['force_activation'] ) { + if ( ! $this->is_plugin_installed( $slug ) ) { + // Oops, plugin isn't there so iterate to next condition. + continue; + } elseif ( $this->can_plugin_activate( $slug ) ) { + // There we go, activate the plugin. + activate_plugin( $plugin['file_path'] ); + } + } + } + } + + /** + * Forces plugin deactivation if the parameter 'force_deactivation' + * is set to true and adds the plugin to the 'recently active' plugins list. + * + * This allows theme authors to specify certain plugins that must be + * deactivated upon switching from the current theme to another. + * + * Please take special care when using this parameter as it has the + * potential to be harmful if not used correctly. + * + * @since 2.2.0 + */ + public function force_deactivation() { + $deactivated = array(); + + foreach ( $this->plugins as $slug => $plugin ) { + /* + * Only proceed forward if the parameter is set to true and plugin is active + * as a 'normal' (not must-use) plugin. + */ + if ( true === $plugin['force_deactivation'] && is_plugin_active( $plugin['file_path'] ) ) { + deactivate_plugins( $plugin['file_path'] ); + $deactivated[ $plugin['file_path'] ] = time(); + } + } + + if ( ! empty( $deactivated ) ) { + update_option( 'recently_activated', $deactivated + (array) get_option( 'recently_activated' ) ); + } + } + + /** + * Echo the current TGMPA version number to the page. + * + * @since 2.5.0 + */ + public function show_tgmpa_version() { + echo '

', + esc_html( + sprintf( + /* translators: %s: version number */ + __( 'TGMPA v%s', 'tgmpa' ), + self::TGMPA_VERSION + ) + ), + '

'; + } + + /** + * Returns the singleton instance of the class. + * + * @since 2.4.0 + * + * @return \TGM_Plugin_Activation The TGM_Plugin_Activation object. + */ + public static function get_instance() { + if ( ! isset( self::$instance ) && ! ( self::$instance instanceof self ) ) { + self::$instance = new self(); + } + + return self::$instance; + } + } + + if ( ! function_exists( 'load_tgm_plugin_activation' ) ) { + /** + * Ensure only one instance of the class is ever invoked. + * + * @since 2.5.0 + */ + function load_tgm_plugin_activation() { + $GLOBALS['tgmpa'] = TGM_Plugin_Activation::get_instance(); + } + } + + if ( did_action( 'plugins_loaded' ) ) { + load_tgm_plugin_activation(); + } else { + add_action( 'plugins_loaded', 'load_tgm_plugin_activation' ); + } +} + +if ( ! function_exists( 'tgmpa' ) ) { + /** + * Helper function to register a collection of required plugins. + * + * @since 2.0.0 + * @api + * + * @param array $plugins An array of plugin arrays. + * @param array $config Optional. An array of configuration values. + */ + function tgmpa( $plugins, $config = array() ) { + $instance = call_user_func( array( get_class( $GLOBALS['tgmpa'] ), 'get_instance' ) ); + + foreach ( $plugins as $plugin ) { + call_user_func( array( $instance, 'register' ), $plugin ); + } + + if ( ! empty( $config ) && is_array( $config ) ) { + // Send out notices for deprecated arguments passed. + if ( isset( $config['notices'] ) ) { + _deprecated_argument( __FUNCTION__, '2.2.0', 'The `notices` config parameter was renamed to `has_notices` in TGMPA 2.2.0. Please adjust your configuration.' ); + if ( ! isset( $config['has_notices'] ) ) { + $config['has_notices'] = $config['notices']; + } + } + + if ( isset( $config['parent_menu_slug'] ) ) { + _deprecated_argument( __FUNCTION__, '2.4.0', 'The `parent_menu_slug` config parameter was removed in TGMPA 2.4.0. In TGMPA 2.5.0 an alternative was (re-)introduced. Please adjust your configuration. For more information visit the website: http://tgmpluginactivation.com/configuration/#h-configuration-options.' ); + } + if ( isset( $config['parent_url_slug'] ) ) { + _deprecated_argument( __FUNCTION__, '2.4.0', 'The `parent_url_slug` config parameter was removed in TGMPA 2.4.0. In TGMPA 2.5.0 an alternative was (re-)introduced. Please adjust your configuration. For more information visit the website: http://tgmpluginactivation.com/configuration/#h-configuration-options.' ); + } + + call_user_func( array( $instance, 'config' ), $config ); + } + } +} + +/** + * WP_List_Table isn't always available. If it isn't available, + * we load it here. + * + * @since 2.2.0 + */ +if ( ! class_exists( 'WP_List_Table' ) ) { + require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php'; +} + +if ( ! class_exists( 'TGMPA_List_Table' ) ) { + + /** + * List table class for handling plugins. + * + * Extends the WP_List_Table class to provide a future-compatible + * way of listing out all required/recommended plugins. + * + * Gives users an interface similar to the Plugin Administration + * area with similar (albeit stripped down) capabilities. + * + * This class also allows for the bulk install of plugins. + * + * @since 2.2.0 + * + * @package TGM-Plugin-Activation + * @author Thomas Griffin + * @author Gary Jones + */ + class TGMPA_List_Table extends WP_List_Table { + /** + * TGMPA instance. + * + * @since 2.5.0 + * + * @var object + */ + protected $tgmpa; + + /** + * The currently chosen view. + * + * @since 2.5.0 + * + * @var string One of: 'all', 'install', 'update', 'activate' + */ + public $view_context = 'all'; + + /** + * The plugin counts for the various views. + * + * @since 2.5.0 + * + * @var array + */ + protected $view_totals = array( + 'all' => 0, + 'install' => 0, + 'update' => 0, + 'activate' => 0, + ); + + /** + * References parent constructor and sets defaults for class. + * + * @since 2.2.0 + */ + public function __construct() { + $this->tgmpa = call_user_func( array( get_class( $GLOBALS['tgmpa'] ), 'get_instance' ) ); + + parent::__construct( + array( + 'singular' => 'plugin', + 'plural' => 'plugins', + 'ajax' => false, + ) + ); + + if ( isset( $_REQUEST['plugin_status'] ) && in_array( $_REQUEST['plugin_status'], array( 'install', 'update', 'activate' ), true ) ) { + $this->view_context = sanitize_key( $_REQUEST['plugin_status'] ); + } + + add_filter( 'tgmpa_table_data_items', array( $this, 'sort_table_items' ) ); + } + + /** + * Get a list of CSS classes for the tag. + * + * Overruled to prevent the 'plural' argument from being added. + * + * @since 2.5.0 + * + * @return array CSS classnames. + */ + public function get_table_classes() { + return array( 'widefat', 'fixed' ); + } + + /** + * Gathers and renames all of our plugin information to be used by WP_List_Table to create our table. + * + * @since 2.2.0 + * + * @return array $table_data Information for use in table. + */ + protected function _gather_plugin_data() { + // Load thickbox for plugin links. + $this->tgmpa->admin_init(); + $this->tgmpa->thickbox(); + + // Categorize the plugins which have open actions. + $plugins = $this->categorize_plugins_to_views(); + + // Set the counts for the view links. + $this->set_view_totals( $plugins ); + + // Prep variables for use and grab list of all installed plugins. + $table_data = array(); + $i = 0; + + // Redirect to the 'all' view if no plugins were found for the selected view context. + if ( empty( $plugins[ $this->view_context ] ) ) { + $this->view_context = 'all'; + } + + foreach ( $plugins[ $this->view_context ] as $slug => $plugin ) { + $table_data[ $i ]['sanitized_plugin'] = $plugin['name']; + $table_data[ $i ]['slug'] = $slug; + $table_data[ $i ]['plugin'] = '' . $this->tgmpa->get_info_link( $slug ) . ''; + $table_data[ $i ]['source'] = $this->get_plugin_source_type_text( $plugin['source_type'] ); + $table_data[ $i ]['type'] = $this->get_plugin_advise_type_text( $plugin['required'] ); + $table_data[ $i ]['status'] = $this->get_plugin_status_text( $slug ); + $table_data[ $i ]['installed_version'] = $this->tgmpa->get_installed_version( $slug ); + $table_data[ $i ]['minimum_version'] = $plugin['version']; + $table_data[ $i ]['available_version'] = $this->tgmpa->does_plugin_have_update( $slug ); + + // Prep the upgrade notice info. + $upgrade_notice = $this->tgmpa->get_upgrade_notice( $slug ); + if ( ! empty( $upgrade_notice ) ) { + $table_data[ $i ]['upgrade_notice'] = $upgrade_notice; + + add_action( "tgmpa_after_plugin_row_{$slug}", array( $this, 'wp_plugin_update_row' ), 10, 2 ); + } + + $table_data[ $i ] = apply_filters( 'tgmpa_table_data_item', $table_data[ $i ], $plugin ); + + $i++; + } + + return $table_data; + } + + /** + * Categorize the plugins which have open actions into views for the TGMPA page. + * + * @since 2.5.0 + */ + protected function categorize_plugins_to_views() { + $plugins = array( + 'all' => array(), // Meaning: all plugins which still have open actions. + 'install' => array(), + 'update' => array(), + 'activate' => array(), + ); + + foreach ( $this->tgmpa->plugins as $slug => $plugin ) { + if ( $this->tgmpa->is_plugin_active( $slug ) && false === $this->tgmpa->does_plugin_have_update( $slug ) ) { + // No need to display plugins if they are installed, up-to-date and active. + continue; + } else { + $plugins['all'][ $slug ] = $plugin; + + if ( ! $this->tgmpa->is_plugin_installed( $slug ) ) { + $plugins['install'][ $slug ] = $plugin; + } else { + if ( false !== $this->tgmpa->does_plugin_have_update( $slug ) ) { + $plugins['update'][ $slug ] = $plugin; + } + + if ( $this->tgmpa->can_plugin_activate( $slug ) ) { + $plugins['activate'][ $slug ] = $plugin; + } + } + } + } + + return $plugins; + } + + /** + * Set the counts for the view links. + * + * @since 2.5.0 + * + * @param array $plugins Plugins order by view. + */ + protected function set_view_totals( $plugins ) { + foreach ( $plugins as $type => $list ) { + $this->view_totals[ $type ] = count( $list ); + } + } + + /** + * Get the plugin required/recommended text string. + * + * @since 2.5.0 + * + * @param string $required Plugin required setting. + * @return string + */ + protected function get_plugin_advise_type_text( $required ) { + if ( true === $required ) { + return __( 'Required', 'tgmpa' ); + } + + return __( 'Recommended', 'tgmpa' ); + } + + /** + * Get the plugin source type text string. + * + * @since 2.5.0 + * + * @param string $type Plugin type. + * @return string + */ + protected function get_plugin_source_type_text( $type ) { + $string = ''; + + switch ( $type ) { + case 'repo': + $string = __( 'WordPress Repository', 'tgmpa' ); + break; + case 'external': + $string = __( 'External Source', 'tgmpa' ); + break; + case 'bundled': + $string = __( 'Pre-Packaged', 'tgmpa' ); + break; + } + + return $string; + } + + /** + * Determine the plugin status message. + * + * @since 2.5.0 + * + * @param string $slug Plugin slug. + * @return string + */ + protected function get_plugin_status_text( $slug ) { + if ( ! $this->tgmpa->is_plugin_installed( $slug ) ) { + return __( 'Not Installed', 'tgmpa' ); + } + + if ( ! $this->tgmpa->is_plugin_active( $slug ) ) { + $install_status = __( 'Installed But Not Activated', 'tgmpa' ); + } else { + $install_status = __( 'Active', 'tgmpa' ); + } + + $update_status = ''; + + if ( $this->tgmpa->does_plugin_require_update( $slug ) && false === $this->tgmpa->does_plugin_have_update( $slug ) ) { + $update_status = __( 'Required Update not Available', 'tgmpa' ); + + } elseif ( $this->tgmpa->does_plugin_require_update( $slug ) ) { + $update_status = __( 'Requires Update', 'tgmpa' ); + + } elseif ( false !== $this->tgmpa->does_plugin_have_update( $slug ) ) { + $update_status = __( 'Update recommended', 'tgmpa' ); + } + + if ( '' === $update_status ) { + return $install_status; + } + + return sprintf( + /* translators: 1: install status, 2: update status */ + _x( '%1$s, %2$s', 'Install/Update Status', 'tgmpa' ), + $install_status, + $update_status + ); + } + + /** + * Sort plugins by Required/Recommended type and by alphabetical plugin name within each type. + * + * @since 2.5.0 + * + * @param array $items Prepared table items. + * @return array Sorted table items. + */ + public function sort_table_items( $items ) { + $type = array(); + $name = array(); + + foreach ( $items as $i => $plugin ) { + $type[ $i ] = $plugin['type']; // Required / recommended. + $name[ $i ] = $plugin['sanitized_plugin']; + } + + array_multisort( $type, SORT_DESC, $name, SORT_ASC, $items ); + + return $items; + } + + /** + * Get an associative array ( id => link ) of the views available on this table. + * + * @since 2.5.0 + * + * @return array + */ + public function get_views() { + $status_links = array(); + + foreach ( $this->view_totals as $type => $count ) { + if ( $count < 1 ) { + continue; + } + + switch ( $type ) { + case 'all': + /* translators: 1: number of plugins. */ + $text = _nx( 'All (%s)', 'All (%s)', $count, 'plugins', 'tgmpa' ); + break; + case 'install': + /* translators: 1: number of plugins. */ + $text = _n( 'To Install (%s)', 'To Install (%s)', $count, 'tgmpa' ); + break; + case 'update': + /* translators: 1: number of plugins. */ + $text = _n( 'Update Available (%s)', 'Update Available (%s)', $count, 'tgmpa' ); + break; + case 'activate': + /* translators: 1: number of plugins. */ + $text = _n( 'To Activate (%s)', 'To Activate (%s)', $count, 'tgmpa' ); + break; + default: + $text = ''; + break; + } + + if ( ! empty( $text ) ) { + + $status_links[ $type ] = sprintf( + '%s', + esc_url( $this->tgmpa->get_tgmpa_status_url( $type ) ), + ( $type === $this->view_context ) ? ' class="current"' : '', + sprintf( $text, number_format_i18n( $count ) ) + ); + } + } + + return $status_links; + } + + /** + * Create default columns to display important plugin information + * like type, action and status. + * + * @since 2.2.0 + * + * @param array $item Array of item data. + * @param string $column_name The name of the column. + * @return string + */ + public function column_default( $item, $column_name ) { + return $item[ $column_name ]; + } + + /** + * Required for bulk installing. + * + * Adds a checkbox for each plugin. + * + * @since 2.2.0 + * + * @param array $item Array of item data. + * @return string The input checkbox with all necessary info. + */ + public function column_cb( $item ) { + return sprintf( + '', + esc_attr( $this->_args['singular'] ), + esc_attr( $item['slug'] ), + esc_attr( $item['sanitized_plugin'] ) + ); + } + + /** + * Create default title column along with the action links. + * + * @since 2.2.0 + * + * @param array $item Array of item data. + * @return string The plugin name and action links. + */ + public function column_plugin( $item ) { + return sprintf( + '%1$s %2$s', + $item['plugin'], + $this->row_actions( $this->get_row_actions( $item ), true ) + ); + } + + /** + * Create version information column. + * + * @since 2.5.0 + * + * @param array $item Array of item data. + * @return string HTML-formatted version information. + */ + public function column_version( $item ) { + $output = array(); + + if ( $this->tgmpa->is_plugin_installed( $item['slug'] ) ) { + $installed = ! empty( $item['installed_version'] ) ? $item['installed_version'] : _x( 'unknown', 'as in: "version nr unknown"', 'tgmpa' ); + + $color = ''; + if ( ! empty( $item['minimum_version'] ) && $this->tgmpa->does_plugin_require_update( $item['slug'] ) ) { + $color = ' color: #ff0000; font-weight: bold;'; + } + + $output[] = sprintf( + '

%2$s' . __( 'Installed version:', 'tgmpa' ) . '

', + $color, + $installed + ); + } + + if ( ! empty( $item['minimum_version'] ) ) { + $output[] = sprintf( + '

%1$s' . __( 'Minimum required version:', 'tgmpa' ) . '

', + $item['minimum_version'] + ); + } + + if ( ! empty( $item['available_version'] ) ) { + $color = ''; + if ( ! empty( $item['minimum_version'] ) && version_compare( $item['available_version'], $item['minimum_version'], '>=' ) ) { + $color = ' color: #71C671; font-weight: bold;'; + } + + $output[] = sprintf( + '

%2$s' . __( 'Available version:', 'tgmpa' ) . '

', + $color, + $item['available_version'] + ); + } + + if ( empty( $output ) ) { + return ' '; // Let's not break the table layout. + } else { + return implode( "\n", $output ); + } + } + + /** + * Sets default message within the plugins table if no plugins + * are left for interaction. + * + * Hides the menu item to prevent the user from clicking and + * getting a permissions error. + * + * @since 2.2.0 + */ + public function no_items() { + echo esc_html__( 'No plugins to install, update or activate.', 'tgmpa' ) . ' ' . esc_html__( 'Return to the Dashboard', 'tgmpa' ) . ''; + echo ''; + } + + /** + * Output all the column information within the table. + * + * @since 2.2.0 + * + * @return array $columns The column names. + */ + public function get_columns() { + $columns = array( + 'cb' => '', + 'plugin' => __( 'Plugin', 'tgmpa' ), + 'source' => __( 'Source', 'tgmpa' ), + 'type' => __( 'Type', 'tgmpa' ), + ); + + if ( 'all' === $this->view_context || 'update' === $this->view_context ) { + $columns['version'] = __( 'Version', 'tgmpa' ); + $columns['status'] = __( 'Status', 'tgmpa' ); + } + + return apply_filters( 'tgmpa_table_columns', $columns ); + } + + /** + * Get name of default primary column + * + * @since 2.5.0 / WP 4.3+ compatibility + * @access protected + * + * @return string + */ + protected function get_default_primary_column_name() { + return 'plugin'; + } + + /** + * Get the name of the primary column. + * + * @since 2.5.0 / WP 4.3+ compatibility + * @access protected + * + * @return string The name of the primary column. + */ + protected function get_primary_column_name() { + if ( method_exists( 'WP_List_Table', 'get_primary_column_name' ) ) { + return parent::get_primary_column_name(); + } else { + return $this->get_default_primary_column_name(); + } + } + + /** + * Get the actions which are relevant for a specific plugin row. + * + * @since 2.5.0 + * + * @param array $item Array of item data. + * @return array Array with relevant action links. + */ + protected function get_row_actions( $item ) { + $actions = array(); + $action_links = array(); + + // Display the 'Install' action link if the plugin is not yet available. + if ( ! $this->tgmpa->is_plugin_installed( $item['slug'] ) ) { + /* translators: %2$s: plugin name in screen reader markup */ + $actions['install'] = __( 'Install %2$s', 'tgmpa' ); + } else { + // Display the 'Update' action link if an update is available and WP complies with plugin minimum. + if ( false !== $this->tgmpa->does_plugin_have_update( $item['slug'] ) && $this->tgmpa->can_plugin_update( $item['slug'] ) ) { + /* translators: %2$s: plugin name in screen reader markup */ + $actions['update'] = __( 'Update %2$s', 'tgmpa' ); + } + + // Display the 'Activate' action link, but only if the plugin meets the minimum version. + if ( $this->tgmpa->can_plugin_activate( $item['slug'] ) ) { + /* translators: %2$s: plugin name in screen reader markup */ + $actions['activate'] = __( 'Activate %2$s', 'tgmpa' ); + } + } + + // Create the actual links. + foreach ( $actions as $action => $text ) { + $nonce_url = wp_nonce_url( + add_query_arg( + array( + 'plugin' => urlencode( $item['slug'] ), + 'tgmpa-' . $action => $action . '-plugin', + ), + $this->tgmpa->get_tgmpa_url() + ), + 'tgmpa-' . $action, + 'tgmpa-nonce' + ); + + $action_links[ $action ] = sprintf( + '' . esc_html( $text ) . '', // $text contains the second placeholder. + esc_url( $nonce_url ), + '' . esc_html( $item['sanitized_plugin'] ) . '' + ); + } + + $prefix = ( defined( 'WP_NETWORK_ADMIN' ) && WP_NETWORK_ADMIN ) ? 'network_admin_' : ''; + return apply_filters( "tgmpa_{$prefix}plugin_action_links", array_filter( $action_links ), $item['slug'], $item, $this->view_context ); + } + + /** + * Generates content for a single row of the table. + * + * @since 2.5.0 + * + * @param object $item The current item. + */ + public function single_row( $item ) { + parent::single_row( $item ); + + /** + * Fires after each specific row in the TGMPA Plugins list table. + * + * The dynamic portion of the hook name, `$item['slug']`, refers to the slug + * for the plugin. + * + * @since 2.5.0 + */ + do_action( "tgmpa_after_plugin_row_{$item['slug']}", $item['slug'], $item, $this->view_context ); + } + + /** + * Show the upgrade notice below a plugin row if there is one. + * + * @since 2.5.0 + * + * @see /wp-admin/includes/update.php + * + * @param string $slug Plugin slug. + * @param array $item The information available in this table row. + * @return null Return early if upgrade notice is empty. + */ + public function wp_plugin_update_row( $slug, $item ) { + if ( empty( $item['upgrade_notice'] ) ) { + return; + } + + echo ' + + + '; + } + + /** + * Extra controls to be displayed between bulk actions and pagination. + * + * @since 2.5.0 + * + * @param string $which 'top' or 'bottom' table navigation. + */ + public function extra_tablenav( $which ) { + if ( 'bottom' === $which ) { + $this->tgmpa->show_tgmpa_version(); + } + } + + /** + * Defines the bulk actions for handling registered plugins. + * + * @since 2.2.0 + * + * @return array $actions The bulk actions for the plugin install table. + */ + public function get_bulk_actions() { + + $actions = array(); + + if ( 'update' !== $this->view_context && 'activate' !== $this->view_context ) { + if ( current_user_can( 'install_plugins' ) ) { + $actions['tgmpa-bulk-install'] = __( 'Install', 'tgmpa' ); + } + } + + if ( 'install' !== $this->view_context ) { + if ( current_user_can( 'update_plugins' ) ) { + $actions['tgmpa-bulk-update'] = __( 'Update', 'tgmpa' ); + } + if ( current_user_can( 'activate_plugins' ) ) { + $actions['tgmpa-bulk-activate'] = __( 'Activate', 'tgmpa' ); + } + } + + return $actions; + } + + /** + * Processes bulk installation and activation actions. + * + * The bulk installation process looks for the $_POST information and passes that + * through if a user has to use WP_Filesystem to enter their credentials. + * + * @since 2.2.0 + */ + public function process_bulk_actions() { + // Bulk installation process. + if ( 'tgmpa-bulk-install' === $this->current_action() || 'tgmpa-bulk-update' === $this->current_action() ) { + + check_admin_referer( 'bulk-' . $this->_args['plural'] ); + + $install_type = 'install'; + if ( 'tgmpa-bulk-update' === $this->current_action() ) { + $install_type = 'update'; + } + + $plugins_to_install = array(); + + // Did user actually select any plugins to install/update ? + if ( empty( $_POST['plugin'] ) ) { + if ( 'install' === $install_type ) { + $message = __( 'No plugins were selected to be installed. No action taken.', 'tgmpa' ); + } else { + $message = __( 'No plugins were selected to be updated. No action taken.', 'tgmpa' ); + } + + echo '

', esc_html( $message ), '

'; + + return false; + } + + if ( is_array( $_POST['plugin'] ) ) { + $plugins_to_install = (array) $_POST['plugin']; + } elseif ( is_string( $_POST['plugin'] ) ) { + // Received via Filesystem page - un-flatten array (WP bug #19643). + $plugins_to_install = explode( ',', $_POST['plugin'] ); + } + + // Sanitize the received input. + $plugins_to_install = array_map( 'urldecode', $plugins_to_install ); + $plugins_to_install = array_map( array( $this->tgmpa, 'sanitize_key' ), $plugins_to_install ); + + // Validate the received input. + foreach ( $plugins_to_install as $key => $slug ) { + // Check if the plugin was registered with TGMPA and remove if not. + if ( ! isset( $this->tgmpa->plugins[ $slug ] ) ) { + unset( $plugins_to_install[ $key ] ); + continue; + } + + // For install: make sure this is a plugin we *can* install and not one already installed. + if ( 'install' === $install_type && true === $this->tgmpa->is_plugin_installed( $slug ) ) { + unset( $plugins_to_install[ $key ] ); + } + + // For updates: make sure this is a plugin we *can* update (update available and WP version ok). + if ( 'update' === $install_type && false === $this->tgmpa->is_plugin_updatetable( $slug ) ) { + unset( $plugins_to_install[ $key ] ); + } + } + + // No need to proceed further if we have no plugins to handle. + if ( empty( $plugins_to_install ) ) { + if ( 'install' === $install_type ) { + $message = __( 'No plugins are available to be installed at this time.', 'tgmpa' ); + } else { + $message = __( 'No plugins are available to be updated at this time.', 'tgmpa' ); + } + + echo '

', esc_html( $message ), '

'; + + return false; + } + + // Pass all necessary information if WP_Filesystem is needed. + $url = wp_nonce_url( + $this->tgmpa->get_tgmpa_url(), + 'bulk-' . $this->_args['plural'] + ); + + // Give validated data back to $_POST which is the only place the filesystem looks for extra fields. + $_POST['plugin'] = implode( ',', $plugins_to_install ); // Work around for WP bug #19643. + + $method = ''; // Leave blank so WP_Filesystem can populate it as necessary. + $fields = array_keys( $_POST ); // Extra fields to pass to WP_Filesystem. + + if ( false === ( $creds = request_filesystem_credentials( esc_url_raw( $url ), $method, false, false, $fields ) ) ) { + return true; // Stop the normal page form from displaying, credential request form will be shown. + } + + // Now we have some credentials, setup WP_Filesystem. + if ( ! WP_Filesystem( $creds ) ) { + // Our credentials were no good, ask the user for them again. + request_filesystem_credentials( esc_url_raw( $url ), $method, true, false, $fields ); + + return true; + } + + /* If we arrive here, we have the filesystem */ + + // Store all information in arrays since we are processing a bulk installation. + $names = array(); + $sources = array(); // Needed for installs. + $file_paths = array(); // Needed for upgrades. + $to_inject = array(); // Information to inject into the update_plugins transient. + + // Prepare the data for validated plugins for the install/upgrade. + foreach ( $plugins_to_install as $slug ) { + $name = $this->tgmpa->plugins[ $slug ]['name']; + $source = $this->tgmpa->get_download_url( $slug ); + + if ( ! empty( $name ) && ! empty( $source ) ) { + $names[] = $name; + + switch ( $install_type ) { + + case 'install': + $sources[] = $source; + break; + + case 'update': + $file_paths[] = $this->tgmpa->plugins[ $slug ]['file_path']; + $to_inject[ $slug ] = $this->tgmpa->plugins[ $slug ]; + $to_inject[ $slug ]['source'] = $source; + break; + } + } + } + unset( $slug, $name, $source ); + + // Create a new instance of TGMPA_Bulk_Installer. + $installer = new TGMPA_Bulk_Installer( + new TGMPA_Bulk_Installer_Skin( + array( + 'url' => esc_url_raw( $this->tgmpa->get_tgmpa_url() ), + 'nonce' => 'bulk-' . $this->_args['plural'], + 'names' => $names, + 'install_type' => $install_type, + ) + ) + ); + + // Wrap the install process with the appropriate HTML. + echo '
', + '

', esc_html( get_admin_page_title() ), '

+
'; + + // Process the bulk installation submissions. + add_filter( 'upgrader_source_selection', array( $this->tgmpa, 'maybe_adjust_source_dir' ), 1, 3 ); + + if ( 'tgmpa-bulk-update' === $this->current_action() ) { + // Inject our info into the update transient. + $this->tgmpa->inject_update_info( $to_inject ); + + $installer->bulk_upgrade( $file_paths ); + } else { + $installer->bulk_install( $sources ); + } + + remove_filter( 'upgrader_source_selection', array( $this->tgmpa, 'maybe_adjust_source_dir' ), 1 ); + + echo '
'; + + return true; + } + + // Bulk activation process. + if ( 'tgmpa-bulk-activate' === $this->current_action() ) { + check_admin_referer( 'bulk-' . $this->_args['plural'] ); + + // Did user actually select any plugins to activate ? + if ( empty( $_POST['plugin'] ) ) { + echo '

', esc_html__( 'No plugins were selected to be activated. No action taken.', 'tgmpa' ), '

'; + + return false; + } + + // Grab plugin data from $_POST. + $plugins = array(); + if ( isset( $_POST['plugin'] ) ) { + $plugins = array_map( 'urldecode', (array) $_POST['plugin'] ); + $plugins = array_map( array( $this->tgmpa, 'sanitize_key' ), $plugins ); + } + + $plugins_to_activate = array(); + $plugin_names = array(); + + // Grab the file paths for the selected & inactive plugins from the registration array. + foreach ( $plugins as $slug ) { + if ( $this->tgmpa->can_plugin_activate( $slug ) ) { + $plugins_to_activate[] = $this->tgmpa->plugins[ $slug ]['file_path']; + $plugin_names[] = $this->tgmpa->plugins[ $slug ]['name']; + } + } + unset( $slug ); + + // Return early if there are no plugins to activate. + if ( empty( $plugins_to_activate ) ) { + echo '

', esc_html__( 'No plugins are available to be activated at this time.', 'tgmpa' ), '

'; + + return false; + } + + // Now we are good to go - let's start activating plugins. + $activate = activate_plugins( $plugins_to_activate ); + + if ( is_wp_error( $activate ) ) { + echo '

', wp_kses_post( $activate->get_error_message() ), '

'; + } else { + $count = count( $plugin_names ); // Count so we can use _n function. + $plugin_names = array_map( array( 'TGMPA_Utils', 'wrap_in_strong' ), $plugin_names ); + $last_plugin = array_pop( $plugin_names ); // Pop off last name to prep for readability. + $imploded = empty( $plugin_names ) ? $last_plugin : ( implode( ', ', $plugin_names ) . ' ' . esc_html_x( 'and', 'plugin A *and* plugin B', 'tgmpa' ) . ' ' . $last_plugin ); + + printf( // WPCS: xss ok. + '

%1$s %2$s.

', + esc_html( _n( 'The following plugin was activated successfully:', 'The following plugins were activated successfully:', $count, 'tgmpa' ) ), + $imploded + ); + + // Update recently activated plugins option. + $recent = (array) get_option( 'recently_activated' ); + foreach ( $plugins_to_activate as $plugin => $time ) { + if ( isset( $recent[ $plugin ] ) ) { + unset( $recent[ $plugin ] ); + } + } + update_option( 'recently_activated', $recent ); + } + + unset( $_POST ); // Reset the $_POST variable in case user wants to perform one action after another. + + return true; + } + + return false; + } + + /** + * Prepares all of our information to be outputted into a usable table. + * + * @since 2.2.0 + */ + public function prepare_items() { + $columns = $this->get_columns(); // Get all necessary column information. + $hidden = array(); // No columns to hide, but we must set as an array. + $sortable = array(); // No reason to make sortable columns. + $primary = $this->get_primary_column_name(); // Column which has the row actions. + $this->_column_headers = array( $columns, $hidden, $sortable, $primary ); // Get all necessary column headers. + + // Process our bulk activations here. + if ( 'tgmpa-bulk-activate' === $this->current_action() ) { + $this->process_bulk_actions(); + } + + // Store all of our plugin data into $items array so WP_List_Table can use it. + $this->items = apply_filters( 'tgmpa_table_data_items', $this->_gather_plugin_data() ); + } + + /* *********** DEPRECATED METHODS *********** */ + + /** + * Retrieve plugin data, given the plugin name. + * + * @since 2.2.0 + * @deprecated 2.5.0 use {@see TGM_Plugin_Activation::_get_plugin_data_from_name()} instead. + * @see TGM_Plugin_Activation::_get_plugin_data_from_name() + * + * @param string $name Name of the plugin, as it was registered. + * @param string $data Optional. Array key of plugin data to return. Default is slug. + * @return string|boolean Plugin slug if found, false otherwise. + */ + protected function _get_plugin_data_from_name( $name, $data = 'slug' ) { + _deprecated_function( __FUNCTION__, 'TGMPA 2.5.0', 'TGM_Plugin_Activation::_get_plugin_data_from_name()' ); + + return $this->tgmpa->_get_plugin_data_from_name( $name, $data ); + } + } +} + + +if ( ! class_exists( 'TGM_Bulk_Installer' ) ) { + + /** + * Hack: Prevent TGMPA v2.4.1- bulk installer class from being loaded if 2.4.1- is loaded after 2.5+. + * + * @since 2.5.2 + * + * {@internal The TGMPA_Bulk_Installer class was originally called TGM_Bulk_Installer. + * For more information, see that class.}} + */ + class TGM_Bulk_Installer { + } +} +if ( ! class_exists( 'TGM_Bulk_Installer_Skin' ) ) { + + /** + * Hack: Prevent TGMPA v2.4.1- bulk installer skin class from being loaded if 2.4.1- is loaded after 2.5+. + * + * @since 2.5.2 + * + * {@internal The TGMPA_Bulk_Installer_Skin class was originally called TGM_Bulk_Installer_Skin. + * For more information, see that class.}} + */ + class TGM_Bulk_Installer_Skin { + } +} + +/** + * The WP_Upgrader file isn't always available. If it isn't available, + * we load it here. + * + * We check to make sure no action or activation keys are set so that WordPress + * does not try to re-include the class when processing upgrades or installs outside + * of the class. + * + * @since 2.2.0 + */ +add_action( 'admin_init', 'tgmpa_load_bulk_installer' ); +if ( ! function_exists( 'tgmpa_load_bulk_installer' ) ) { + /** + * Load bulk installer + */ + function tgmpa_load_bulk_installer() { + // Silently fail if 2.5+ is loaded *after* an older version. + if ( ! isset( $GLOBALS['tgmpa'] ) ) { + return; + } + + // Get TGMPA class instance. + $tgmpa_instance = call_user_func( array( get_class( $GLOBALS['tgmpa'] ), 'get_instance' ) ); + + if ( isset( $_GET['page'] ) && $tgmpa_instance->menu === $_GET['page'] ) { + if ( ! class_exists( 'Plugin_Upgrader', false ) ) { + require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; + } + + if ( ! class_exists( 'TGMPA_Bulk_Installer' ) ) { + + /** + * Installer class to handle bulk plugin installations. + * + * Extends WP_Upgrader and customizes to suit the installation of multiple + * plugins. + * + * @since 2.2.0 + * + * {@internal Since 2.5.0 the class is an extension of Plugin_Upgrader rather than WP_Upgrader.}} + * {@internal Since 2.5.2 the class has been renamed from TGM_Bulk_Installer to TGMPA_Bulk_Installer. + * This was done to prevent backward compatibility issues with v2.3.6.}} + * + * @package TGM-Plugin-Activation + * @author Thomas Griffin + * @author Gary Jones + */ + class TGMPA_Bulk_Installer extends Plugin_Upgrader { + /** + * Holds result of bulk plugin installation. + * + * @since 2.2.0 + * + * @var string + */ + public $result; + + /** + * Flag to check if bulk installation is occurring or not. + * + * @since 2.2.0 + * + * @var boolean + */ + public $bulk = false; + + /** + * TGMPA instance + * + * @since 2.5.0 + * + * @var object + */ + protected $tgmpa; + + /** + * Whether or not the destination directory needs to be cleared ( = on update). + * + * @since 2.5.0 + * + * @var bool + */ + protected $clear_destination = false; + + /** + * References parent constructor and sets defaults for class. + * + * @since 2.2.0 + * + * @param \Bulk_Upgrader_Skin|null $skin Installer skin. + */ + public function __construct( $skin = null ) { + // Get TGMPA class instance. + $this->tgmpa = call_user_func( array( get_class( $GLOBALS['tgmpa'] ), 'get_instance' ) ); + + parent::__construct( $skin ); + + if ( isset( $this->skin->options['install_type'] ) && 'update' === $this->skin->options['install_type'] ) { + $this->clear_destination = true; + } + + if ( $this->tgmpa->is_automatic ) { + $this->activate_strings(); + } + + add_action( 'upgrader_process_complete', array( $this->tgmpa, 'populate_file_path' ) ); + } + + /** + * Sets the correct activation strings for the installer skin to use. + * + * @since 2.2.0 + */ + public function activate_strings() { + $this->strings['activation_failed'] = __( 'Plugin activation failed.', 'tgmpa' ); + $this->strings['activation_success'] = __( 'Plugin activated successfully.', 'tgmpa' ); + } + + /** + * Performs the actual installation of each plugin. + * + * @since 2.2.0 + * + * @see WP_Upgrader::run() + * + * @param array $options The installation config options. + * @return null|array Return early if error, array of installation data on success. + */ + public function run( $options ) { + $result = parent::run( $options ); + + // Reset the strings in case we changed one during automatic activation. + if ( $this->tgmpa->is_automatic ) { + if ( 'update' === $this->skin->options['install_type'] ) { + $this->upgrade_strings(); + } else { + $this->install_strings(); + } + } + + return $result; + } + + /** + * Processes the bulk installation of plugins. + * + * @since 2.2.0 + * + * {@internal This is basically a near identical copy of the WP Core + * Plugin_Upgrader::bulk_upgrade() method, with minor adjustments to deal with + * new installs instead of upgrades. + * For ease of future synchronizations, the adjustments are clearly commented, but no other + * comments are added. Code style has been made to comply.}} + * + * @see Plugin_Upgrader::bulk_upgrade() + * @see https://core.trac.wordpress.org/browser/tags/4.2.1/src/wp-admin/includes/class-wp-upgrader.php#L838 + * (@internal Last synced: Dec 31st 2015 against https://core.trac.wordpress.org/browser/trunk?rev=36134}} + * + * @param array $plugins The plugin sources needed for installation. + * @param array $args Arbitrary passed extra arguments. + * @return array|false Install confirmation messages on success, false on failure. + */ + public function bulk_install( $plugins, $args = array() ) { + // [TGMPA + ] Hook auto-activation in. + add_filter( 'upgrader_post_install', array( $this, 'auto_activate' ), 10 ); + + $defaults = array( + 'clear_update_cache' => true, + ); + $parsed_args = wp_parse_args( $args, $defaults ); + + $this->init(); + $this->bulk = true; + + $this->install_strings(); // [TGMPA + ] adjusted. + + /* [TGMPA - ] $current = get_site_transient( 'update_plugins' ); */ + + /* [TGMPA - ] add_filter('upgrader_clear_destination', array($this, 'delete_old_plugin'), 10, 4); */ + + $this->skin->header(); + + // Connect to the Filesystem first. + $res = $this->fs_connect( array( WP_CONTENT_DIR, WP_PLUGIN_DIR ) ); + if ( ! $res ) { + $this->skin->footer(); + return false; + } + + $this->skin->bulk_header(); + + /* + * Only start maintenance mode if: + * - running Multisite and there are one or more plugins specified, OR + * - a plugin with an update available is currently active. + * @TODO: For multisite, maintenance mode should only kick in for individual sites if at all possible. + */ + $maintenance = ( is_multisite() && ! empty( $plugins ) ); + + /* + [TGMPA - ] + foreach ( $plugins as $plugin ) + $maintenance = $maintenance || ( is_plugin_active( $plugin ) && isset( $current->response[ $plugin] ) ); + */ + if ( $maintenance ) { + $this->maintenance_mode( true ); + } + + $results = array(); + + $this->update_count = count( $plugins ); + $this->update_current = 0; + foreach ( $plugins as $plugin ) { + $this->update_current++; + + /* + [TGMPA - ] + $this->skin->plugin_info = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin, false, true); + + if ( !isset( $current->response[ $plugin ] ) ) { + $this->skin->set_result('up_to_date'); + $this->skin->before(); + $this->skin->feedback('up_to_date'); + $this->skin->after(); + $results[$plugin] = true; + continue; + } + + // Get the URL to the zip file. + $r = $current->response[ $plugin ]; + + $this->skin->plugin_active = is_plugin_active($plugin); + */ + + $result = $this->run( + array( + 'package' => $plugin, // [TGMPA + ] adjusted. + 'destination' => WP_PLUGIN_DIR, + 'clear_destination' => false, // [TGMPA + ] adjusted. + 'clear_working' => true, + 'is_multi' => true, + 'hook_extra' => array( + 'plugin' => $plugin, + ), + ) + ); + + $results[ $plugin ] = $this->result; + + // Prevent credentials auth screen from displaying multiple times. + if ( false === $result ) { + break; + } + } //end foreach $plugins + + $this->maintenance_mode( false ); + + /** + * Fires when the bulk upgrader process is complete. + * + * @since WP 3.6.0 / TGMPA 2.5.0 + * + * @param Plugin_Upgrader $this Plugin_Upgrader instance. In other contexts, $this, might + * be a Theme_Upgrader or Core_Upgrade instance. + * @param array $data { + * Array of bulk item update data. + * + * @type string $action Type of action. Default 'update'. + * @type string $type Type of update process. Accepts 'plugin', 'theme', or 'core'. + * @type bool $bulk Whether the update process is a bulk update. Default true. + * @type array $packages Array of plugin, theme, or core packages to update. + * } + */ + do_action( 'upgrader_process_complete', $this, array( + 'action' => 'install', // [TGMPA + ] adjusted. + 'type' => 'plugin', + 'bulk' => true, + 'plugins' => $plugins, + ) ); + + $this->skin->bulk_footer(); + + $this->skin->footer(); + + // Cleanup our hooks, in case something else does a upgrade on this connection. + /* [TGMPA - ] remove_filter('upgrader_clear_destination', array($this, 'delete_old_plugin')); */ + + // [TGMPA + ] Remove our auto-activation hook. + remove_filter( 'upgrader_post_install', array( $this, 'auto_activate' ), 10 ); + + // Force refresh of plugin update information. + wp_clean_plugins_cache( $parsed_args['clear_update_cache'] ); + + return $results; + } + + /** + * Handle a bulk upgrade request. + * + * @since 2.5.0 + * + * @see Plugin_Upgrader::bulk_upgrade() + * + * @param array $plugins The local WP file_path's of the plugins which should be upgraded. + * @param array $args Arbitrary passed extra arguments. + * @return string|bool Install confirmation messages on success, false on failure. + */ + public function bulk_upgrade( $plugins, $args = array() ) { + + add_filter( 'upgrader_post_install', array( $this, 'auto_activate' ), 10 ); + + $result = parent::bulk_upgrade( $plugins, $args ); + + remove_filter( 'upgrader_post_install', array( $this, 'auto_activate' ), 10 ); + + return $result; + } + + /** + * Abuse a filter to auto-activate plugins after installation. + * + * Hooked into the 'upgrader_post_install' filter hook. + * + * @since 2.5.0 + * + * @param bool $bool The value we need to give back (true). + * @return bool + */ + public function auto_activate( $bool ) { + // Only process the activation of installed plugins if the automatic flag is set to true. + if ( $this->tgmpa->is_automatic ) { + // Flush plugins cache so the headers of the newly installed plugins will be read correctly. + wp_clean_plugins_cache(); + + // Get the installed plugin file. + $plugin_info = $this->plugin_info(); + + // Don't try to activate on upgrade of active plugin as WP will do this already. + if ( ! is_plugin_active( $plugin_info ) ) { + $activate = activate_plugin( $plugin_info ); + + // Adjust the success string based on the activation result. + $this->strings['process_success'] = $this->strings['process_success'] . "
\n"; + + if ( is_wp_error( $activate ) ) { + $this->skin->error( $activate ); + $this->strings['process_success'] .= $this->strings['activation_failed']; + } else { + $this->strings['process_success'] .= $this->strings['activation_success']; + } + } + } + + return $bool; + } + } + } + + if ( ! class_exists( 'TGMPA_Bulk_Installer_Skin' ) ) { + + /** + * Installer skin to set strings for the bulk plugin installations.. + * + * Extends Bulk_Upgrader_Skin and customizes to suit the installation of multiple + * plugins. + * + * @since 2.2.0 + * + * {@internal Since 2.5.2 the class has been renamed from TGM_Bulk_Installer_Skin to + * TGMPA_Bulk_Installer_Skin. + * This was done to prevent backward compatibility issues with v2.3.6.}} + * + * @see https://core.trac.wordpress.org/browser/trunk/src/wp-admin/includes/class-wp-upgrader-skins.php + * + * @package TGM-Plugin-Activation + * @author Thomas Griffin + * @author Gary Jones + */ + class TGMPA_Bulk_Installer_Skin extends Bulk_Upgrader_Skin { + /** + * Holds plugin info for each individual plugin installation. + * + * @since 2.2.0 + * + * @var array + */ + public $plugin_info = array(); + + /** + * Holds names of plugins that are undergoing bulk installations. + * + * @since 2.2.0 + * + * @var array + */ + public $plugin_names = array(); + + /** + * Integer to use for iteration through each plugin installation. + * + * @since 2.2.0 + * + * @var integer + */ + public $i = 0; + + /** + * TGMPA instance + * + * @since 2.5.0 + * + * @var object + */ + protected $tgmpa; + + /** + * Constructor. Parses default args with new ones and extracts them for use. + * + * @since 2.2.0 + * + * @param array $args Arguments to pass for use within the class. + */ + public function __construct( $args = array() ) { + // Get TGMPA class instance. + $this->tgmpa = call_user_func( array( get_class( $GLOBALS['tgmpa'] ), 'get_instance' ) ); + + // Parse default and new args. + $defaults = array( + 'url' => '', + 'nonce' => '', + 'names' => array(), + 'install_type' => 'install', + ); + $args = wp_parse_args( $args, $defaults ); + + // Set plugin names to $this->plugin_names property. + $this->plugin_names = $args['names']; + + // Extract the new args. + parent::__construct( $args ); + } + + /** + * Sets install skin strings for each individual plugin. + * + * Checks to see if the automatic activation flag is set and uses the + * the proper strings accordingly. + * + * @since 2.2.0 + */ + public function add_strings() { + if ( 'update' === $this->options['install_type'] ) { + parent::add_strings(); + /* translators: 1: plugin name, 2: action number 3: total number of actions. */ + $this->upgrader->strings['skin_before_update_header'] = __( 'Updating Plugin %1$s (%2$d/%3$d)', 'tgmpa' ); + } else { + /* translators: 1: plugin name, 2: error message. */ + $this->upgrader->strings['skin_update_failed_error'] = __( 'An error occurred while installing %1$s: %2$s.', 'tgmpa' ); + /* translators: 1: plugin name. */ + $this->upgrader->strings['skin_update_failed'] = __( 'The installation of %1$s failed.', 'tgmpa' ); + + if ( $this->tgmpa->is_automatic ) { + // Automatic activation strings. + $this->upgrader->strings['skin_upgrade_start'] = __( 'The installation and activation process is starting. This process may take a while on some hosts, so please be patient.', 'tgmpa' ); + /* translators: 1: plugin name. */ + $this->upgrader->strings['skin_update_successful'] = __( '%1$s installed and activated successfully.', 'tgmpa' ) . ' ' . esc_html__( 'Show Details', 'tgmpa' ) . '.'; + $this->upgrader->strings['skin_upgrade_end'] = __( 'All installations and activations have been completed.', 'tgmpa' ); + /* translators: 1: plugin name, 2: action number 3: total number of actions. */ + $this->upgrader->strings['skin_before_update_header'] = __( 'Installing and Activating Plugin %1$s (%2$d/%3$d)', 'tgmpa' ); + } else { + // Default installation strings. + $this->upgrader->strings['skin_upgrade_start'] = __( 'The installation process is starting. This process may take a while on some hosts, so please be patient.', 'tgmpa' ); + /* translators: 1: plugin name. */ + $this->upgrader->strings['skin_update_successful'] = esc_html__( '%1$s installed successfully.', 'tgmpa' ) . ' ' . esc_html__( 'Show Details', 'tgmpa' ) . '.'; + $this->upgrader->strings['skin_upgrade_end'] = __( 'All installations have been completed.', 'tgmpa' ); + /* translators: 1: plugin name, 2: action number 3: total number of actions. */ + $this->upgrader->strings['skin_before_update_header'] = __( 'Installing Plugin %1$s (%2$d/%3$d)', 'tgmpa' ); + } + } + } + + /** + * Outputs the header strings and necessary JS before each plugin installation. + * + * @since 2.2.0 + * + * @param string $title Unused in this implementation. + */ + public function before( $title = '' ) { + if ( empty( $title ) ) { + $title = esc_html( $this->plugin_names[ $this->i ] ); + } + parent::before( $title ); + } + + /** + * Outputs the footer strings and necessary JS after each plugin installation. + * + * Checks for any errors and outputs them if they exist, else output + * success strings. + * + * @since 2.2.0 + * + * @param string $title Unused in this implementation. + */ + public function after( $title = '' ) { + if ( empty( $title ) ) { + $title = esc_html( $this->plugin_names[ $this->i ] ); + } + parent::after( $title ); + + $this->i++; + } + + /** + * Outputs links after bulk plugin installation is complete. + * + * @since 2.2.0 + */ + public function bulk_footer() { + // Serve up the string to say installations (and possibly activations) are complete. + parent::bulk_footer(); + + // Flush plugins cache so we can make sure that the installed plugins list is always up to date. + wp_clean_plugins_cache(); + + $this->tgmpa->show_tgmpa_version(); + + // Display message based on if all plugins are now active or not. + $update_actions = array(); + + if ( $this->tgmpa->is_tgmpa_complete() ) { + // All plugins are active, so we display the complete string and hide the menu to protect users. + echo ''; + $update_actions['dashboard'] = sprintf( + esc_html( $this->tgmpa->strings['complete'] ), + '' . esc_html__( 'Return to the Dashboard', 'tgmpa' ) . '' + ); + } else { + $update_actions['tgmpa_page'] = '' . esc_html( $this->tgmpa->strings['return'] ) . ''; + } + + /** + * Filter the list of action links available following bulk plugin installs/updates. + * + * @since 2.5.0 + * + * @param array $update_actions Array of plugin action links. + * @param array $plugin_info Array of information for the last-handled plugin. + */ + $update_actions = apply_filters( 'tgmpa_update_bulk_plugins_complete_actions', $update_actions, $this->plugin_info ); + + if ( ! empty( $update_actions ) ) { + $this->feedback( implode( ' | ', (array) $update_actions ) ); + } + } + + /* *********** DEPRECATED METHODS *********** */ + + /** + * Flush header output buffer. + * + * @since 2.2.0 + * @deprecated 2.5.0 use {@see Bulk_Upgrader_Skin::flush_output()} instead + * @see Bulk_Upgrader_Skin::flush_output() + */ + public function before_flush_output() { + _deprecated_function( __FUNCTION__, 'TGMPA 2.5.0', 'Bulk_Upgrader_Skin::flush_output()' ); + $this->flush_output(); + } + + /** + * Flush footer output buffer and iterate $this->i to make sure the + * installation strings reference the correct plugin. + * + * @since 2.2.0 + * @deprecated 2.5.0 use {@see Bulk_Upgrader_Skin::flush_output()} instead + * @see Bulk_Upgrader_Skin::flush_output() + */ + public function after_flush_output() { + _deprecated_function( __FUNCTION__, 'TGMPA 2.5.0', 'Bulk_Upgrader_Skin::flush_output()' ); + $this->flush_output(); + $this->i++; + } + } + } + } + } +} + +if ( ! class_exists( 'TGMPA_Utils' ) ) { + + /** + * Generic utilities for TGMPA. + * + * All methods are static, poor-dev name-spacing class wrapper. + * + * Class was called TGM_Utils in 2.5.0 but renamed TGMPA_Utils in 2.5.1 as this was conflicting with Soliloquy. + * + * @since 2.5.0 + * + * @package TGM-Plugin-Activation + * @author Juliette Reinders Folmer + */ + class TGMPA_Utils { + /** + * Whether the PHP filter extension is enabled. + * + * @see http://php.net/book.filter + * + * @since 2.5.0 + * + * @static + * + * @var bool $has_filters True is the extension is enabled. + */ + public static $has_filters; + + /** + * Wrap an arbitrary string in tags. Meant to be used in combination with array_map(). + * + * @since 2.5.0 + * + * @static + * + * @param string $string Text to be wrapped. + * @return string + */ + public static function wrap_in_em( $string ) { + return '' . wp_kses_post( $string ) . ''; + } + + /** + * Wrap an arbitrary string in tags. Meant to be used in combination with array_map(). + * + * @since 2.5.0 + * + * @static + * + * @param string $string Text to be wrapped. + * @return string + */ + public static function wrap_in_strong( $string ) { + return '' . wp_kses_post( $string ) . ''; + } + + /** + * Helper function: Validate a value as boolean + * + * @since 2.5.0 + * + * @static + * + * @param mixed $value Arbitrary value. + * @return bool + */ + public static function validate_bool( $value ) { + if ( ! isset( self::$has_filters ) ) { + self::$has_filters = extension_loaded( 'filter' ); + } + + if ( self::$has_filters ) { + return filter_var( $value, FILTER_VALIDATE_BOOLEAN ); + } else { + return self::emulate_filter_bool( $value ); + } + } + + /** + * Helper function: Cast a value to bool + * + * @since 2.5.0 + * + * @static + * + * @param mixed $value Value to cast. + * @return bool + */ + protected static function emulate_filter_bool( $value ) { + // @codingStandardsIgnoreStart + static $true = array( + '1', + 'true', 'True', 'TRUE', + 'y', 'Y', + 'yes', 'Yes', 'YES', + 'on', 'On', 'ON', + ); + static $false = array( + '0', + 'false', 'False', 'FALSE', + 'n', 'N', + 'no', 'No', 'NO', + 'off', 'Off', 'OFF', + ); + // @codingStandardsIgnoreEnd + + if ( is_bool( $value ) ) { + return $value; + } elseif ( is_int( $value ) && ( 0 === $value || 1 === $value ) ) { + return (bool) $value; + } elseif ( ( is_float( $value ) && ! is_nan( $value ) ) && ( (float) 0 === $value || (float) 1 === $value ) ) { + return (bool) $value; + } elseif ( is_string( $value ) ) { + $value = trim( $value ); + if ( in_array( $value, $true, true ) ) { + return true; + } elseif ( in_array( $value, $false, true ) ) { + return false; + } else { + return false; + } + } + + return false; + } + } // End of class TGMPA_Utils +} // End of class_exists wrapper diff --git a/comments.php b/comments.php new file mode 100644 index 0000000..e01a1d5 --- /dev/null +++ b/comments.php @@ -0,0 +1,55 @@ + + +
+ + apply_filters( + 'comment_form_default_fields', array( + 'author' =>'', + 'email' => '', + 'url' => '
' + ) + ), + 'comment_field' => '

' . + '' . + '

', + 'comment_notes' => '', + 'comment_notes_after' => '
', + 'title_reply' => '' + ); + comment_form($args); + ?> + + + + + +
+
    + 'ol', + 'short_ping' => true, + 'callback' => 'yuzu_comment_template' + ) ); + ?> +
+
+ + + +
diff --git a/components/article-cards/large-article-card.php b/components/article-cards/large-article-card.php new file mode 100644 index 0000000..840d091 --- /dev/null +++ b/components/article-cards/large-article-card.php @@ -0,0 +1,28 @@ +
+
+ + + +
+
\ No newline at end of file diff --git a/components/article-cards/medium-article-card.php b/components/article-cards/medium-article-card.php new file mode 100644 index 0000000..cd60b7c --- /dev/null +++ b/components/article-cards/medium-article-card.php @@ -0,0 +1,28 @@ +
+
+ + + +
+
\ No newline at end of file diff --git a/components/article-cards/small-article-card.php b/components/article-cards/small-article-card.php new file mode 100644 index 0000000..00c1c61 --- /dev/null +++ b/components/article-cards/small-article-card.php @@ -0,0 +1,28 @@ +
+
+ + + +
+
\ No newline at end of file diff --git a/components/collection-card.php b/components/collection-card.php new file mode 100644 index 0000000..f2afc42 --- /dev/null +++ b/components/collection-card.php @@ -0,0 +1,17 @@ + \ No newline at end of file diff --git a/components/folder-card.php b/components/folder-card.php new file mode 100644 index 0000000..4a283d0 --- /dev/null +++ b/components/folder-card.php @@ -0,0 +1,19 @@ + + +
+
+
+ +
+
+

+
+ + +
+
+
+
\ No newline at end of file diff --git a/components/opaque-featured-image.php b/components/opaque-featured-image.php new file mode 100644 index 0000000..454befa --- /dev/null +++ b/components/opaque-featured-image.php @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/footer.php b/footer.php new file mode 100644 index 0000000..2be7df5 --- /dev/null +++ b/footer.php @@ -0,0 +1,46 @@ + + +
+
+ +
+ +
+ + +
+ +
+ + +
+ +
+ +
+ + +
+ + + +
+ +
+ + + + + + diff --git a/functions.php b/functions.php new file mode 100644 index 0000000..8b24df1 --- /dev/null +++ b/functions.php @@ -0,0 +1,367 @@ + tag in the document head, and expect WordPress to + * provide it for us. + */ + add_theme_support( 'title-tag' ); + + /* + * Gutenberg Align wide support. + */ + add_theme_support( 'align-wide' ); + + /* + * Enable support for Post Thumbnails on posts and pages. + * + * @link https://developer.wordpress.org/themes/functionality/featured-images-post-thumbnails/ + */ + add_theme_support( 'post-thumbnails' ); + + // This theme uses wp_nav_menu() in one location. + register_nav_menus( array( + 'menu-1' => esc_html__( 'Primary', 'yuzu' ), + ) ); + + /* + * Switch default core markup for search form, comment form, and comments + * to output valid HTML5. + */ + add_theme_support( 'html5', array( + 'search-form', + 'comment-form', + 'comment-list', + 'gallery', + 'caption', + ) ); + + // Set up the WordPress core custom background feature. + add_theme_support( 'custom-background', apply_filters( 'yuzu_custom_background_args', array( + 'default-color' => 'ffffff', + 'default-image' => '', + ) ) ); + + // Add theme support for selective refresh for widgets. + add_theme_support( 'customize-selective-refresh-widgets' ); + + /** + * Add support for core custom logo. + * + * @link https://codex.wordpress.org/Theme_Logo + */ + add_theme_support( 'custom-logo', array( + 'height' => 120, + 'flex-width' => true, + 'flex-height' => true, + ) ); + } +endif; +add_action( 'after_setup_theme', 'yuzu_setup' ); + +/** + * Set the content width in pixels, based on the theme's design and stylesheet. + * + * Priority 0 to make it available to lower priority callbacks. + * + * @global int $content_width + */ +function yuzu_content_width() { + // This variable is intended to be overruled from themes. + // Open WPCS issue: {@link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards/issues/1043}. + // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound + $GLOBALS['content_width'] = apply_filters( 'yuzu_content_width', 640 ); +} +add_action( 'after_setup_theme', 'yuzu_content_width', 0 ); + +/** + * Register widget area. + * + * @link https://developer.wordpress.org/themes/functionality/sidebars/#registering-a-sidebar + */ +function yuzu_widgets_init() { + register_sidebar( array( + 'name' => esc_html__( 'Footer · Left', 'yuzu' ), + 'id' => 'footer-left', + 'description' => esc_html__( 'Add widgets here.', 'yuzu' ), + 'before_widget' => '
', + 'after_widget' => '
', + 'before_title' => '

', + 'after_title' => '

', + ) ); + register_sidebar( array( + 'name' => esc_html__( 'Footer · Middle', 'yuzu' ), + 'id' => 'footer-middle', + 'description' => esc_html__( 'Add widgets here.', 'yuzu' ), + 'before_widget' => '
', + 'after_widget' => '
', + 'before_title' => '

', + 'after_title' => '

', + ) ); + register_sidebar( array( + 'name' => esc_html__( 'Footer · Right', 'yuzu' ), + 'id' => 'footer-right', + 'description' => esc_html__( 'Add widgets here.', 'yuzu' ), + 'before_widget' => '
', + 'after_widget' => '
', + 'before_title' => '

', + 'after_title' => '

', + ) ); +} +add_action( 'widgets_init', 'yuzu_widgets_init' ); + +/** + * Enqueue scripts and styles. + */ +function yuzu_scripts() { + $ver_num = mt_rand(); + + wp_enqueue_style( 'yuzu-custom-properties', get_template_directory_uri() . '/assets/css/custom-properties.css', array(), $ver_num ); + + wp_enqueue_style( 'yuzu-style', get_stylesheet_uri(), array(), $ver_num ); + + wp_enqueue_script( 'jquery' ); + + wp_enqueue_script( 'main-js', get_template_directory_uri() . '/assets/js/main.js', array('jquery'), $ver_num, true ); + + $dataToBePassed = array( + 'enable_posts_height_equalizer' => get_theme_mod('enable_posts_height_equalizer', true), + 'test' => 'test' + ); + wp_localize_script( 'main-js', 'php_vars', $dataToBePassed ); + + if ( is_singular() && comments_open() && get_option( 'thread_comments' ) ) { + wp_enqueue_script( 'comment-reply' ); + } +} +add_action( 'wp_enqueue_scripts', 'yuzu_scripts' ); + +/** + * Registers an editor stylesheet for the theme. + */ +function yuzu_add_editor_styles() { + add_editor_style( 'editor-style.css' ); +} +add_action( 'admin_init', 'yuzu_add_editor_styles' ); + +function legit_block_editor_styles() { + wp_enqueue_style( 'legit-editor-styles', get_theme_file_uri( '/assets/css/editor-style.css' ), false, '1.0', 'all' ); +} +add_action( 'enqueue_block_editor_assets', 'legit_block_editor_styles' ); + +/** + * Apply Color Scheme Class + */ +add_filter( 'body_class', 'apply_theme_color_scheme'); +function apply_theme_color_scheme( $classes ) { + $classes[] = get_theme_mod('color_scheme', 'light') . '-theme'; + return $classes; +} + +/** + * Reduce excerpt length + */ +add_filter( 'excerpt_length', function($length) { + return 25; +} ); + +/** + * Load Meow Blocks Output + */ +require get_template_directory() . '/inc/meow-blocks-output.php'; + + +/** + * Implement the Custom Header feature. + */ +require get_template_directory() . '/inc/custom-header.php'; + +/** + * Custom template tags for this theme. + */ +require get_template_directory() . '/inc/template-tags.php'; + +/** + * Functions which enhance the theme by hooking into WordPress. + */ +require get_template_directory() . '/inc/template-functions.php'; + +/** + * Customizer additions. + */ +require get_template_directory() . '/inc/custom-controls.php'; + +/** + * Customizer additions. + */ +require get_template_directory() . '/inc/customizer.php'; + +/** + * Apply Customizer Colors. + */ +require get_template_directory() . '/inc/apply-colors.php'; + +/** + * Load Jetpack compatibility file. + */ +if ( defined( 'JETPACK__VERSION' ) ) { + require get_template_directory() . '/inc/jetpack.php'; +} + +/** + * Custom comment template + */ +function yuzu_comment_template($comment, $args, $depth) { + $GLOBALS['comment'] = $comment; ?> +
  • id="li-comment-"> +
    +
    +
    + +
    +
    +
    +
    +
    +
    + +
    + comment_approved == '0') : ?> + +
    + + +
    + +
    +
  • +is_search ) { + $query->set( 'post_type', array( 'post', 'attachment', 'meow_collection' ) ); + $query->set( 'post_status', array( 'publish', 'inherit' ) ); + $query->set( 'posts_per_page', '-1'); + } + + return $query; +} +add_filter( 'pre_get_posts', 'attachment_search' ); + + +require_once( get_template_directory() . '/class-tgm-plugin-activation.php'); + +add_action( 'tgmpa_register', 'yuzu_register_required_plugins' ); + +/** + * Register the required plugins for this theme. + * + * + * + * This function is hooked into tgmpa_init, which is fired within the + * TGM_Plugin_Activation class constructor. + */ +function yuzu_register_required_plugins() { + /* + * Array of plugin arrays. Required keys are name and slug. + * If the source is NOT from the .org repo, then source is also required. + */ + $plugins = array( + // This is an example of how to include a plugin from the WordPress Plugin Repository. + array( + 'name' => 'Photography Core', + 'slug' => 'photography-core', + 'required' => false, + ), + array( + 'name' => 'WP/LR Sync', + 'slug' => 'wplr-sync', + 'required' => false, + ), + array( + 'name' => 'Meow Gallery', + 'slug' => 'meow-gallery', + 'is_callable' => array( 'Meow_Gallery_Core', 'installed' ), + 'required' => false, + ), + array( + 'name' => 'Meow Lightbox', + 'slug' => 'meow-lightbox', + 'is_callable' => array( 'Meow_Lightbox_Core', 'installed' ), + 'required' => false, + ) + ); + + /* + * Array of configuration settings. Amend each line as needed. + * + * TGMPA will start providing localized text strings soon. If you already have translations of our standard + * strings available, please help us make TGMPA even better by giving us access to these translations or by + * sending in a pull-request with .po file(s) with the translations. + * + * Only uncomment the strings in the config array if you want to customize the strings. + */ + $config = array( + 'id' => 'tgmpa', // Unique ID for hashing notices for multiple instances of TGMPA. + 'default_path' => '', // Default absolute path to bundled plugins. + 'menu' => 'tgmpa-install-plugins', // Menu slug. + 'parent_slug' => 'themes.php', // Parent menu slug. + 'capability' => 'edit_theme_options', // Capability needed to view plugin install page, should be a capability associated with the parent menu used. + 'has_notices' => true, // Show admin notices or not. + 'dismissable' => true, // If false, a user cannot dismiss the nag message. + 'dismiss_msg' => '', // If 'dismissable' is false, this message will be output at top of nag. + 'is_automatic' => false, // Automatically activate plugins after installation or not. + 'message' => '', // Message to output right before the plugins table. + ); + + tgmpa( $plugins, $config ); + +} + +/* + MEOW APPS LICENSE +*/ + +global $meowapps_theme_version; +$meowapps_theme_version = '0.1.0'; + +function prefix_theme_updater() { + require( get_template_directory() . '/updater/yuzu-updater.php' ); +} +add_action( 'after_setup_theme', 'prefix_theme_updater' ); diff --git a/header.php b/header.php new file mode 100644 index 0000000..07abb54 --- /dev/null +++ b/header.php @@ -0,0 +1,96 @@ + section and everything up until
    + * + * @link https://developer.wordpress.org/themes/basics/template-files/#template-partials + * + * @package Yuzu + */ + +?> + +> + + + + + + + + +> +
    + + +
    +
    + + + + + +
    +
    + + + +
    + +
    +
    +
    +
    +
    + +
    diff --git a/inc/apply-colors.php b/inc/apply-colors.php new file mode 100644 index 0000000..93bcffa --- /dev/null +++ b/inc/apply-colors.php @@ -0,0 +1,73 @@ + 1) + $opacity = 1.0; + $output = 'rgba('.implode(",",$rgb).','.$opacity.')'; + } else { + $output = 'rgb('.implode(",",$rgb).')'; + } + + //Return rgb(a) color string + return $output; +} + +function yuzu_customizer_head_styles() { + ?> + + + * @license http://www.gnu.org/licenses/gpl-2.0.html + * @link https://github.com/maddisondesigns + */ + class Skyrocket_Custom_Control extends WP_Customize_Control { + protected function get_skyrocket_resource_url() { + if( strpos( wp_normalize_path( __DIR__ ), wp_normalize_path( WP_PLUGIN_DIR ) ) === 0 ) { + // We're in a plugin directory and need to determine the url accordingly. + return plugin_dir_url( __DIR__ ); + } + + return trailingslashit( get_template_directory_uri() ); + } + } + + /** + * Image Check Box Custom Control + * + * @author Anthony Hortin + * @license http://www.gnu.org/licenses/gpl-2.0.html + * @link https://github.com/maddisondesigns + */ + class Skyrocket_Image_Checkbox_Custom_Control extends Skyrocket_Custom_Control { + /** + * The type of control being rendered + */ + public $type = 'image_checkbox'; + /** + * Enqueue our scripts and styles + */ + public function enqueue() { + wp_enqueue_style( 'skyrocket-custom-controls-css', $this->get_skyrocket_resource_url() . 'css/customizer.css', array(), '1.0', 'all' ); + } + /** + * Render the control in the customizer + */ + public function render_content() { + ?> +
    + label ) ) { ?> + label ); ?> + + description ) ) { ?> + description ); ?> + + value() ) ); ?> + link(); ?> /> + choices as $key => $value ) { ?> + + +
    + + * @license http://www.gnu.org/licenses/gpl-2.0.html + * @link https://github.com/maddisondesigns + */ + class Skyrocket_Text_Radio_Button_Custom_Control extends Skyrocket_Custom_Control { + /** + * The type of control being rendered + */ + public $type = 'text_radio_button'; + /** + * Enqueue our scripts and styles + */ + public function enqueue() { + wp_enqueue_style( 'skyrocket-custom-controls-css', $this->get_skyrocket_resource_url() . 'css/customizer.css', array(), '1.0', 'all' ); + } + /** + * Render the control in the customizer + */ + public function render_content() { + ?> +
    + label ) ) { ?> + label ); ?> + + description ) ) { ?> + description ); ?> + + +
    + choices as $key => $value ) { ?> + + +
    +
    + + * @license http://www.gnu.org/licenses/gpl-2.0.html + * @link https://github.com/maddisondesigns + */ + class Skyrocket_Image_Radio_Button_Custom_Control extends Skyrocket_Custom_Control { + /** + * The type of control being rendered + */ + public $type = 'image_radio_button'; + /** + * Enqueue our scripts and styles + */ + public function enqueue() { + wp_enqueue_style( 'skyrocket-custom-controls-css', $this->get_skyrocket_resource_url() . 'css/customizer.css', array(), '1.0', 'all' ); + } + /** + * Render the control in the customizer + */ + public function render_content() { + ?> +
    + label ) ) { ?> + label ); ?> + + description ) ) { ?> + description ); ?> + + + choices as $key => $value ) { ?> + + +
    + + * @license http://www.gnu.org/licenses/gpl-2.0.html + * @link https://github.com/maddisondesigns + */ + class Skyrocket_Single_Accordion_Custom_Control extends Skyrocket_Custom_Control { + /** + * The type of control being rendered + */ + public $type = 'single_accordion'; + /** + * Enqueue our scripts and styles + */ + public function enqueue() { + wp_enqueue_script( 'skyrocket-custom-controls-js', $this->get_skyrocket_resource_url() . 'js/customizer.js', array( 'jquery' ), '1.0', true ); + wp_enqueue_style( 'skyrocket-custom-controls-css', $this->get_skyrocket_resource_url() . 'css/customizer.css', array(), '1.0', 'all' ); + wp_enqueue_style( 'fontawesome', $this->get_skyrocket_resource_url() . 'css/font-awesome.min.css', array(), '4.6.3', 'all' ); + } + /** + * Render the control in the customizer + */ + public function render_content() { + $allowed_html = array( + 'a' => array( + 'href' => array(), + 'title' => array(), + 'class' => array(), + 'target' => array(), + ), + 'br' => array(), + 'em' => array(), + 'strong' => array(), + 'i' => array( + 'class' => array() + ), + ); + ?> +
    +
    label ); ?>
    +
    + description ) ) { + echo '
      '; + foreach ( $this->description as $key => $value ) { + echo '
    • ' . $key . wp_kses( $value, $allowed_html ) . '
    • '; + } + echo '
    '; + } + else { + echo wp_kses( $this->description, $allowed_html ); + } + ?> +
    +
    + + * @license http://www.gnu.org/licenses/gpl-2.0.html + * @link https://github.com/maddisondesigns + */ + class Skyrocket_Simple_Notice_Custom_Control extends Skyrocket_Custom_Control { + /** + * The type of control being rendered + */ + public $type = 'simple_notice'; + /** + * Render the control in the customizer + */ + public function render_content() { + $allowed_html = array( + 'a' => array( + 'href' => array(), + 'title' => array(), + 'class' => array(), + 'target' => array(), + ), + 'br' => array(), + 'em' => array(), + 'strong' => array(), + 'i' => array( + 'class' => array() + ), + 'span' => array( + 'class' => array(), + ), + 'code' => array(), + ); + ?> +
    + label ) ) { ?> + label ); ?> + + description ) ) { ?> + description, $allowed_html ); ?> + +
    + + * @license http://www.gnu.org/licenses/gpl-2.0.html + * @link https://github.com/maddisondesigns + */ + class Skyrocket_Slider_Custom_Control extends Skyrocket_Custom_Control { + /** + * The type of control being rendered + */ + public $type = 'slider_control'; + /** + * Enqueue our scripts and styles + */ + public function enqueue() { + wp_enqueue_script( 'skyrocket-custom-controls-js', $this->get_skyrocket_resource_url() . 'js/customizer.js', array( 'jquery', 'jquery-ui-core' ), '1.0', true ); + wp_enqueue_style( 'skyrocket-custom-controls-css', $this->get_skyrocket_resource_url() . 'css/customizer.css', array(), '1.0', 'all' ); + } + /** + * Render the control in the customizer + */ + public function render_content() { + ?> +
    + label ); ?>link(); ?> /> +
    +
    + + * @license http://www.gnu.org/licenses/gpl-2.0.html + * @link https://github.com/maddisondesigns + */ + class Skyrocket_Toggle_Switch_Custom_control extends Skyrocket_Custom_Control { + /** + * The type of control being rendered + */ + public $type = 'toggle_switch'; + /** + * Enqueue our scripts and styles + */ + public function enqueue(){ + wp_enqueue_style( 'skyrocket-custom-controls-css', $this->get_skyrocket_resource_url() . 'css/customizer.css', array(), '1.0', 'all' ); + } + /** + * Render the control in the customizer + */ + public function render_content(){ + ?> +
    +
    + link(); checked( $this->value() ); ?>> + +
    + label ); ?> + description ) ) { ?> + description ); ?> + +
    + + * @license http://www.gnu.org/licenses/gpl-2.0.html + * @link https://github.com/maddisondesigns + */ + class Skyrocket_Sortable_Repeater_Custom_Control extends Skyrocket_Custom_Control { + /** + * The type of control being rendered + */ + public $type = 'sortable_repeater'; + /** + * Button labels + */ + public $button_labels = array(); + /** + * Constructor + */ + public function __construct( $manager, $id, $args = array(), $options = array() ) { + parent::__construct( $manager, $id, $args ); + // Merge the passed button labels with our default labels + $this->button_labels = wp_parse_args( $this->button_labels, + array( + 'add' => __( 'Add', 'skyrocket' ), + ) + ); + } + /** + * Enqueue our scripts and styles + */ + public function enqueue() { + wp_enqueue_script( 'skyrocket-custom-controls-js', $this->get_skyrocket_resource_url() . 'js/customizer.js', array( 'jquery', 'jquery-ui-core' ), '1.0', true ); + wp_enqueue_style( 'skyrocket-custom-controls-css', $this->get_skyrocket_resource_url() . 'css/customizer.css', array(), '1.0', 'all' ); + } + /** + * Render the control in the customizer + */ + public function render_content() { + ?> +
    + label ) ) { ?> + label ); ?> + + description ) ) { ?> + description ); ?> + + link(); ?> /> +
    +
    + +
    +
    + +
    + + * @license http://www.gnu.org/licenses/gpl-2.0.html + * @link https://github.com/maddisondesigns + */ + class Skyrocket_Dropdown_Select2_Custom_Control extends Skyrocket_Custom_Control { + /** + * The type of control being rendered + */ + public $type = 'dropdown_select2'; + /** + * The type of Select2 Dropwdown to display. Can be either a single select dropdown or a multi-select dropdown. Either false for true. Default = false + */ + private $multiselect = false; + /** + * The Placeholder value to display. Select2 requires a Placeholder value to be set when using the clearall option. Default = 'Please select...' + */ + private $placeholder = 'Please select...'; + /** + * Constructor + */ + public function __construct( $manager, $id, $args = array(), $options = array() ) { + parent::__construct( $manager, $id, $args ); + // Check if this is a multi-select field + if ( isset( $this->input_attrs['multiselect'] ) && $this->input_attrs['multiselect'] ) { + $this->multiselect = true; + } + // Check if a placeholder string has been specified + if ( isset( $this->input_attrs['placeholder'] ) && $this->input_attrs['placeholder'] ) { + $this->placeholder = $this->input_attrs['placeholder']; + } + } + /** + * Enqueue our scripts and styles + */ + public function enqueue() { + wp_enqueue_script( 'skyrocket-select2-js', 'https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/js/select2.min.js', array( 'jquery' ), '4.0.6', true ); + wp_enqueue_script( 'skyrocket-custom-controls-js', $this->get_skyrocket_resource_url() . 'js/customizer.js', array( 'skyrocket-select2-js' ), '1.0', true ); + wp_enqueue_style( 'skyrocket-custom-controls-css', $this->get_skyrocket_resource_url() . 'css/customizer.css', array(), '1.1', 'all' ); + wp_enqueue_style( 'skyrocket-select2-css', 'https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/css/select2.min.css', array(), '4.0.6', 'all' ); + } + /** + * Render the control in the customizer + */ + public function render_content() { + $defaultValue = $this->value(); + if ( $this->multiselect ) { + $defaultValue = explode( ',', $this->value() ); + } + ?> + + + * @license http://www.gnu.org/licenses/gpl-2.0.html + * @link https://github.com/maddisondesigns + */ + class Skyrocket_Dropdown_Posts_Custom_Control extends Skyrocket_Custom_Control { + /** + * The type of control being rendered + */ + public $type = 'dropdown_posts'; + /** + * Posts + */ + private $posts = array(); + /** + * Constructor + */ + public function __construct( $manager, $id, $args = array(), $options = array() ) { + parent::__construct( $manager, $id, $args ); + // Get our Posts + $this->posts = get_posts( $this->input_attrs ); + } + /** + * Render the control in the customizer + */ + public function render_content() { + ?> + + + * @license http://www.gnu.org/licenses/gpl-2.0.html + * @link https://github.com/maddisondesigns + */ + class Skyrocket_TinyMCE_Custom_control extends Skyrocket_Custom_Control { + /** + * The type of control being rendered + */ + public $type = 'tinymce_editor'; + /** + * Enqueue our scripts and styles + */ + public function enqueue(){ + wp_enqueue_script( 'skyrocket-custom-controls-js', $this->get_skyrocket_resource_url() . 'js/customizer.js', array( 'jquery' ), '1.0', true ); + wp_enqueue_style( 'skyrocket-custom-controls-css', $this->get_skyrocket_resource_url() . 'css/customizer.css', array(), '1.0', 'all' ); + wp_enqueue_editor(); + } + /** + * Pass our TinyMCE toolbar string to JavaScript + */ + public function to_json() { + parent::to_json(); + $this->json['skyrockettinymcetoolbar1'] = isset( $this->input_attrs['toolbar1'] ) ? esc_attr( $this->input_attrs['toolbar1'] ) : 'bold italic bullist numlist alignleft aligncenter alignright link'; + $this->json['skyrockettinymcetoolbar2'] = isset( $this->input_attrs['toolbar2'] ) ? esc_attr( $this->input_attrs['toolbar2'] ) : ''; + $this->json['skyrocketmediabuttons'] = isset( $this->input_attrs['mediaButtons'] ) && ( $this->input_attrs['mediaButtons'] === true ) ? true : false; + } + /** + * Render the control in the customizer + */ + public function render_content(){ + ?> +
    + label ); ?> + description ) ) { ?> + description ); ?> + + +
    + + * @license http://www.gnu.org/licenses/gpl-2.0.html + * @link https://github.com/maddisondesigns + */ + class Skyrocket_Google_Font_Select_Custom_Control extends Skyrocket_Custom_Control { + /** + * The type of control being rendered + */ + public $type = 'google_fonts'; + /** + * The list of Google Fonts + */ + private $fontList = false; + /** + * The saved font values decoded from json + */ + private $fontValues = []; + /** + * The index of the saved font within the list of Google fonts + */ + private $fontListIndex = 0; + /** + * The number of fonts to display from the json file. Either positive integer or 'all'. Default = 'all' + */ + private $fontCount = 'all'; + /** + * The font list sort order. Either 'alpha' or 'popular'. Default = 'alpha' + */ + private $fontOrderBy = 'alpha'; + /** + * Get our list of fonts from the json file + */ + public function __construct( $manager, $id, $args = array(), $options = array() ) { + parent::__construct( $manager, $id, $args ); + // Get the font sort order + if ( isset( $this->input_attrs['orderby'] ) && strtolower( $this->input_attrs['orderby'] ) === 'popular' ) { + $this->fontOrderBy = 'popular'; + } + // Get the list of Google fonts + if ( isset( $this->input_attrs['font_count'] ) ) { + if ( 'all' != strtolower( $this->input_attrs['font_count'] ) ) { + $this->fontCount = ( abs( (int) $this->input_attrs['font_count'] ) > 0 ? abs( (int) $this->input_attrs['font_count'] ) : 'all' ); + } + } + $this->fontList = $this->skyrocket_getGoogleFonts( 'all' ); + // Decode the default json font value + $this->fontValues = json_decode( $this->value() ); + // Find the index of our default font within our list of Google fonts + $this->fontListIndex = $this->skyrocket_getFontIndex( $this->fontList, $this->fontValues->font ); + } + /** + * Enqueue our scripts and styles + */ + public function enqueue() { + wp_enqueue_script( 'skyrocket-select2-js', 'https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/js/select2.min.js', array( 'jquery' ), '4.0.6', true ); + wp_enqueue_script( 'skyrocket-custom-controls-js', $this->get_skyrocket_resource_url() . 'js/customizer.js', array( 'skyrocket-select2-js' ), '1.0', true ); + wp_enqueue_style( 'skyrocket-custom-controls-css', $this->get_skyrocket_resource_url() . 'css/customizer.css', array(), '1.1', 'all' ); + wp_enqueue_style( 'skyrocket-select2-css', 'https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/css/select2.min.css', array(), '4.0.6', 'all' ); + } + /** + * Export our List of Google Fonts to JavaScript + */ + public function to_json() { + parent::to_json(); + $this->json['skyrocketfontslist'] = $this->fontList; + } + /** + * Render the control in the customizer + */ + public function render_content() { + $fontCounter = 0; + $isFontInList = false; + $fontListStr = ''; + + if( !empty($this->fontList) ) { + ?> +
    + label ) ) { ?> + label ); ?> + + description ) ) { ?> + description ); ?> + + link(); ?> /> +
    + +
    +
    Select weight & style for regular text
    +
    + +
    +
    Select weight for italic text
    +
    + +
    +
    Select weight for bold text
    +
    + +
    + +
    + $value ) { + if( $value->family == $needle ) { + return $key; + } + } + return false; + } + + /** + * Return the list of Google Fonts from our json file. Unless otherwise specfied, list will be limited to 30 fonts. + */ + public function skyrocket_getGoogleFonts( $count = 30 ) { + // Google Fonts json generated from https://www.googleapis.com/webfonts/v1/webfonts?sort=popularity&key=YOUR-API-KEY + $fontFile = $this->get_skyrocket_resource_url() . 'inc/google-fonts-alphabetical.json'; + if ( $this->fontOrderBy === 'popular' ) { + $fontFile = $this->get_skyrocket_resource_url() . 'inc/google-fonts-popularity.json'; + } + + $request = wp_remote_get( $fontFile ); + if( is_wp_error( $request ) ) { + return ""; + } + + $body = wp_remote_retrieve_body( $request ); + $content = json_decode( $body ); + + if( $count == 'all' ) { + return $content->items; + } else { + return array_slice( $content->items, 0, $count ); + } + } + } + + /** + * Alpha Color Picker Custom Control + * + * @author Braad Martin + * @license http://www.gnu.org/licenses/gpl-3.0.html + * @link https://github.com/BraadMartin/components/tree/master/customizer/alpha-color-picker + */ + class Skyrocket_Customize_Alpha_Color_Control extends Skyrocket_Custom_Control { + /** + * The type of control being rendered + */ + public $type = 'alpha-color'; + /** + * Add support for palettes to be passed in. + * + * Supported palette values are true, false, or an array of RGBa and Hex colors. + */ + public $palette; + /** + * Add support for showing the opacity value on the slider handle. + */ + public $show_opacity; + /** + * Enqueue our scripts and styles + */ + public function enqueue() { + wp_enqueue_script( 'skyrocket-custom-controls-js', $this->get_skyrocket_resource_url() . 'js/customizer.js', array( 'jquery', 'wp-color-picker' ), '1.0', true ); + wp_enqueue_style( 'skyrocket-custom-controls-css', $this->get_skyrocket_resource_url() . 'css/customizer.css', array( 'wp-color-picker' ), '1.0', 'all' ); + } + /** + * Render the control in the customizer + */ + public function render_content() { + + // Process the palette + if ( is_array( $this->palette ) ) { + $palette = implode( '|', $this->palette ); + } else { + // Default to true. + $palette = ( false === $this->palette || 'false' === $this->palette ) ? 'false' : 'true'; + } + + // Support passing show_opacity as string or boolean. Default to true. + $show_opacity = ( false === $this->show_opacity || 'false' === $this->show_opacity ) ? 'false' : 'true'; + + ?> + + link(); ?> /> + $value) { + $input[$key] = esc_url_raw( $value ); + } + $input = implode( ',', $input ); + } + else { + $input = esc_url_raw( $input ); + } + return $input; + } + } + + /** + * Switch sanitization + * + * @param string Switch value + * @return integer Sanitized value + */ + if ( ! function_exists( 'skyrocket_switch_sanitization' ) ) { + function skyrocket_switch_sanitization( $input ) { + if ( true === $input ) { + return 1; + } else { + return 0; + } + } + } + + /** + * Radio Button and Select sanitization + * + * @param string Radio Button value + * @return integer Sanitized value + */ + if ( ! function_exists( 'skyrocket_radio_sanitization' ) ) { + function skyrocket_radio_sanitization( $input, $setting ) { + //get the list of possible radio box or select options + $choices = $setting->manager->get_control( $setting->id )->choices; + + if ( array_key_exists( $input, $choices ) ) { + return $input; + } else { + return $setting->default; + } + } + } + + /** + * Integer sanitization + * + * @param string Input value to check + * @return integer Returned integer value + */ + if ( ! function_exists( 'skyrocket_sanitize_integer' ) ) { + function skyrocket_sanitize_integer( $input ) { + return (int) $input; + } + } + + /** + * Text sanitization + * + * @param string Input to be sanitized (either a string containing a single string or multiple, separated by commas) + * @return string Sanitized input + */ + if ( ! function_exists( 'skyrocket_text_sanitization' ) ) { + function skyrocket_text_sanitization( $input ) { + if ( strpos( $input, ',' ) !== false) { + $input = explode( ',', $input ); + } + if( is_array( $input ) ) { + foreach ( $input as $key => $value ) { + $input[$key] = sanitize_text_field( $value ); + } + $input = implode( ',', $input ); + } + else { + $input = sanitize_text_field( $input ); + } + return $input; + } + } + + /** + * Array sanitization + * + * @param array Input to be sanitized + * @return array Sanitized input + */ + if ( ! function_exists( 'skyrocket_array_sanitization' ) ) { + function skyrocket_array_sanitization( $input ) { + if( is_array( $input ) ) { + foreach ( $input as $key => $value ) { + $input[$key] = sanitize_text_field( $value ); + } + } + else { + $input = ''; + } + return $input; + } + } + + /** + * Alpha Color (Hex & RGBa) sanitization + * + * @param string Input to be sanitized + * @return string Sanitized input + */ + if ( ! function_exists( 'skyrocket_hex_rgba_sanitization' ) ) { + function skyrocket_hex_rgba_sanitization( $input, $setting ) { + if ( empty( $input ) || is_array( $input ) ) { + return $setting->default; + } + + if ( false === strpos( $input, 'rgba' ) ) { + // If string doesn't start with 'rgba' then santize as hex color + $input = sanitize_hex_color( $input ); + } else { + // Sanitize as RGBa color + $input = str_replace( ' ', '', $input ); + sscanf( $input, 'rgba(%d,%d,%d,%f)', $red, $green, $blue, $alpha ); + $input = 'rgba(' . skyrocket_in_range( $red, 0, 255 ) . ',' . skyrocket_in_range( $green, 0, 255 ) . ',' . skyrocket_in_range( $blue, 0, 255 ) . ',' . skyrocket_in_range( $alpha, 0, 1 ) . ')'; + } + return $input; + } + } + + /** + * Only allow values between a certain minimum & maxmium range + * + * @param number Input to be sanitized + * @return number Sanitized input + */ + if ( ! function_exists( 'skyrocket_in_range' ) ) { + function skyrocket_in_range( $input, $min, $max ){ + if ( $input < $min ) { + $input = $min; + } + if ( $input > $max ) { + $input = $max; + } + return $input; + } + } + + /** + * Google Font sanitization + * + * @param string JSON string to be sanitized + * @return string Sanitized input + */ + if ( ! function_exists( 'skyrocket_google_font_sanitization' ) ) { + function skyrocket_google_font_sanitization( $input ) { + $val = json_decode( $input, true ); + if( is_array( $val ) ) { + foreach ( $val as $key => $value ) { + $val[$key] = sanitize_text_field( $value ); + } + $input = json_encode( $val ); + } + else { + $input = json_encode( sanitize_text_field( $val ) ); + } + return $input; + } + } + + /** + * Date Time sanitization + * + * @param string Date/Time string to be sanitized + * @return string Sanitized input + */ + if ( ! function_exists( 'skyrocket_date_time_sanitization' ) ) { + function skyrocket_date_time_sanitization( $input, $setting ) { + $datetimeformat = 'Y-m-d'; + if ( $setting->manager->get_control( $setting->id )->include_time ) { + $datetimeformat = 'Y-m-d H:i:s'; + } + $date = DateTime::createFromFormat( $datetimeformat, $input ); + if ( $date === false ) { + $date = DateTime::createFromFormat( $datetimeformat, $setting->default ); + } + return $date->format( $datetimeformat ); + } + } + + /** + * Slider sanitization + * + * @param string Slider value to be sanitized + * @return string Sanitized input + */ + if ( ! function_exists( 'skyrocket_range_sanitization' ) ) { + function skyrocket_range_sanitization( $input, $setting ) { + $attrs = $setting->manager->get_control( $setting->id )->input_attrs; + + $min = ( isset( $attrs['min'] ) ? $attrs['min'] : $input ); + $max = ( isset( $attrs['max'] ) ? $attrs['max'] : $input ); + $step = ( isset( $attrs['step'] ) ? $attrs['step'] : 1 ); + + $number = floor( $input / $attrs['step'] ) * $attrs['step']; + + return skyrocket_in_range( $number, $min, $max ); + } + } + +} \ No newline at end of file diff --git a/inc/custom-header.php b/inc/custom-header.php new file mode 100644 index 0000000..36c7e7a --- /dev/null +++ b/inc/custom-header.php @@ -0,0 +1,72 @@ + + * + * @link https://developer.wordpress.org/themes/functionality/custom-headers/ + * + * @package Yuzu + */ + +/** + * Set up the WordPress core custom header feature. + * + * @uses yuzu_header_style() + */ +function yuzu_custom_header_setup() { + add_theme_support( 'custom-header', apply_filters( 'yuzu_custom_header_args', array( + 'default-image' => '', + 'default-text-color' => '000000', + 'width' => 1000, + 'height' => 250, + 'flex-height' => true, + 'wp-head-callback' => 'yuzu_header_style', + ) ) ); +} +add_action( 'after_setup_theme', 'yuzu_custom_header_setup' ); + +if ( ! function_exists( 'yuzu_header_style' ) ) : + /** + * Styles the header image and text displayed on the blog. + * + * @see yuzu_custom_header_setup(). + */ + function yuzu_header_style() { + $header_text_color = get_header_textcolor(); + + /* + * If no custom options for text are set, let's bail. + * get_header_textcolor() options: Any hex value, 'blank' to hide text. Default: add_theme_support( 'custom-header' ). + */ + if ( get_theme_support( 'custom-header', 'default-text-color' ) === $header_text_color ) { + return; + } + + // If we get this far, we have custom styles. Let's do this. + ?> + + add_setting( + $args['setting'], array( + 'default' => $args['default'], + 'transport' => 'refresh' + ) + ); + $wp_customize->add_control( + new WP_Customize_Color_Control( + $wp_customize, + $args['setting'], + array( + 'label' => $args['label'], + 'description' => $args['description'], + 'section' => $args['section'], + 'settings' => $args['setting'], + 'active_callback' => $args['active_callback'] + ) + ) + ); + +} + +/* =============================================== */ +// # COLORS SECTION +/* =============================================== */ +$wp_customize->add_section( 'colors_section', array( + 'priority' => 10, + 'capability' => 'edit_theme_options', + 'theme_supports' => '', + 'title' => __( 'Colors', 'yuzu' ), + 'description' => '', + 'panel' => 'theme_settings', +) ); + + + /* =============================================== */ + // ## Scheme + /* =============================================== */ + $wp_customize->add_control( + new yuzu_Customizer_Accordion( + $wp_customize, + 'yuzu-color-sheme-accordion', + array( + 'section' => 'colors_section', + 'label' => __( 'Color Scheme', 'yuzu' ), + 'type' => 'accordion' + ) + ) + ); + + $wp_customize->add_setting( 'color_scheme', array( + 'default' => 'light', + 'transport' => 'refresh', + 'sanitize_callback' => 'sanitize_text_field', + ) ); + $wp_customize->add_control( + 'color_scheme', + array( + 'type' => 'radio', + 'label' => __('Color Scheme', 'yuzu'), + 'section' => 'colors_section', + 'choices' => array( + 'light' => __('Light Theme (default)', 'yuzu'), + 'dark' => __('Dark Theme', 'yuzu'), + 'custom' => __('Custom Theme', 'yuzu'), + ) + ) + ); + + function is_custom_scheme_callback( $control ) { + if ( $control->manager->get_setting('color_scheme')->value() == 'custom' ) { + return true; + } else { + return false; + } + } + + /* =============================================== */ + // ## Backgrounds + /* =============================================== */ + $wp_customize->add_control( + new yuzu_Customizer_Accordion( + $wp_customize, + 'yuzu-backgrounds-colors-accordion', + array( + 'section' => 'colors_section', + 'label' => __( 'Backgrounds', 'yuzu' ), + 'type' => 'accordion' + ) + ) + ); + + $wp_customize->add_setting( 'bg_not_editable_notice', + array( + 'default' => '', + 'transport' => 'postMessage', + 'sanitize_callback' => 'skyrocket_text_sanitization' + ) + ); + $wp_customize->add_control( new Skyrocket_Simple_Notice_Custom_control( $wp_customize, 'bg_not_editable_notice', + array( + 'label' => __( 'Unavailable', 'yuzu' ), + 'description' => __('Please select "Custom Scheme" in order to be able to edit colors individually.', 'yuzu' ), + 'section' => 'colors_section', + 'active_callback' => function(){ + if(get_theme_mod( 'color_scheme', 'light' ) != 'custom') + return true; + } + ) + ) ); + + $args = array( + 'setting' => 'top_bar_bg', + 'section' => 'colors_section', + 'label' => 'Top Bar Background', + 'description' => '', + 'default' => '#FFF', + 'active_callback' => 'is_custom_scheme_callback' + ); + create_color_control( $args, $wp_customize ); + + $args = array( + 'setting' => 'body_bg', + 'section' => 'colors_section', + 'label' => 'Body Background', + 'description' => '', + 'default' => '#FAFBFB', + 'active_callback' => 'is_custom_scheme_callback' + ); + create_color_control( $args, $wp_customize ); + + $args = array( + 'setting' => 'footer_bg', + 'section' => 'colors_section', + 'label' => 'Footer Background', + 'description' => '', + 'default' => '#F6F7FB', + 'active_callback' => 'is_custom_scheme_callback' + ); + create_color_control( $args, $wp_customize ); + + $args = array( + 'setting' => 'card_bg', + 'section' => 'colors_section', + 'label' => 'Cards Background', + 'description' => '', + 'default' => '#F6F7FB', + 'active_callback' => 'is_custom_scheme_callback' + ); + create_color_control( $args, $wp_customize ); + + $args = array( + 'setting' => 'search_widget_bg', + 'section' => 'colors_section', + 'label' => 'Search Field Background', + 'description' => '', + 'default' => '#f5f4f4', + 'active_callback' => 'is_custom_scheme_callback' + ); + create_color_control( $args, $wp_customize ); + + $args = array( + 'setting' => 'comment_bg', + 'section' => 'colors_section', + 'label' => 'Comment Background', + 'description' => '', + 'default' => '#F6F7FB', + 'active_callback' => 'is_custom_scheme_callback' + ); + create_color_control( $args, $wp_customize ); + + $args = array( + 'setting' => 'comment_form_bg', + 'section' => 'colors_section', + 'label' => 'Comment Form Background', + 'description' => '', + 'default' => '#F6F7FB', + 'active_callback' => 'is_custom_scheme_callback' + ); + create_color_control( $args, $wp_customize ); + + /* =============================================== */ + // ## Texts + /* =============================================== */ + $wp_customize->add_control( + new yuzu_Customizer_Accordion( + $wp_customize, + 'yuzu-text-colors-accordion', + array( + 'section' => 'colors_section', + 'label' => __( 'Font Colors', 'yuzu' ), + 'type' => 'accordion' + ) + ) + ); + + $wp_customize->add_setting( 'color_not_editable_notice', + array( + 'default' => '', + 'transport' => 'postMessage', + 'sanitize_callback' => 'skyrocket_text_sanitization' + ) + ); + $wp_customize->add_control( new Skyrocket_Simple_Notice_Custom_control( $wp_customize, 'color_not_editable_notice', + array( + 'label' => __( 'Unavailable', 'yuzu' ), + 'description' => __('Please select "Custom Scheme" in order to be able to edit colors individually.', 'yuzu' ), + 'section' => 'colors_section', + 'active_callback' => function(){ + if(get_theme_mod( 'color_scheme', 'light' ) != 'custom') + return true; + } + ) + ) ); + + $args = array( + 'setting' => 'link_color', + 'section' => 'colors_section', + 'label' => 'Link Color', + 'description' => '', + 'default' => '#4B828E', + 'active_callback' => 'is_custom_scheme_callback' + ); + create_color_control( $args, $wp_customize ); + + $args = array( + 'setting' => 'link_hover_color', + 'section' => 'colors_section', + 'label' => 'Hovered Link Color', + 'description' => '', + 'default' => '#39636D', + 'active_callback' => 'is_custom_scheme_callback' + ); + create_color_control( $args, $wp_customize ); + + $args = array( + 'setting' => 'top_bar_color', + 'section' => 'colors_section', + 'label' => 'Top Bar Color', + 'description' => '', + 'default' => '#2E3B4F', + 'active_callback' => 'is_custom_scheme_callback', + ); + create_color_control( $args, $wp_customize ); + + $args = array( + 'setting' => 'body_color', + 'section' => 'colors_section', + 'label' => 'Body Color', + 'description' => '', + 'default' => '#2E3B4F', + 'active_callback' => 'is_custom_scheme_callback' + ); + create_color_control( $args, $wp_customize ); + + $args = array( + 'setting' => 'footer_color', + 'section' => 'colors_section', + 'label' => 'Footer Color', + 'description' => '', + 'default' => '#2E3B4F', + 'active_callback' => 'is_custom_scheme_callback' + ); + create_color_control( $args, $wp_customize ); + + $args = array( + 'setting' => 'card_color', + 'section' => 'colors_section', + 'label' => 'Cards Color', + 'description' => '', + 'default' => '#2E3B4F', + 'active_callback' => 'is_custom_scheme_callback' + ); + create_color_control( $args, $wp_customize ); + + $args = array( + 'setting' => 'search_widget_color', + 'section' => 'colors_section', + 'label' => 'Search Field Color', + 'description' => '', + 'default' => '#2E3B4F', + 'active_callback' => 'is_custom_scheme_callback' + ); + create_color_control( $args, $wp_customize ); + + $args = array( + 'setting' => 'comment_color', + 'section' => 'colors_section', + 'label' => 'Comment Color', + 'description' => '', + 'default' => '#2E3B4F', + 'active_callback' => 'is_custom_scheme_callback' + ); + create_color_control( $args, $wp_customize ); + + $args = array( + 'setting' => 'comment_form_color', + 'section' => 'colors_section', + 'label' => 'Comment Form Color', + 'description' => '', + 'default' => '#2E3B4F', + 'active_callback' => 'is_custom_scheme_callback' + ); + create_color_control( $args, $wp_customize ); + + /* =============================================== */ + // ## Others + /* =============================================== */ + + $wp_customize->add_control( + new yuzu_Customizer_Accordion( + $wp_customize, + 'yuzu-other-colors-accordion', + array( + 'section' => 'colors_section', + 'label' => __( 'Others', 'yuzu' ), + 'type' => 'accordion' + ) + ) + ); + + $wp_customize->add_setting( 'other_not_editable_notice', + array( + 'default' => '', + 'transport' => 'postMessage', + 'sanitize_callback' => 'skyrocket_text_sanitization' + ) + ); + $wp_customize->add_control( new Skyrocket_Simple_Notice_Custom_control( $wp_customize, 'other_not_editable_notice', + array( + 'label' => __( 'Unavailable', 'yuzu' ), + 'description' => __('Please select "Custom Scheme" in order to be able to edit colors individually.', 'yuzu' ), + 'section' => 'colors_section', + 'active_callback' => function(){ + if(get_theme_mod( 'color_scheme', 'light' ) != 'custom') + return true; + } + ) + ) ); + + $args = array( + 'setting' => 'tag_color', + 'section' => 'colors_section', + 'label' => 'Tags Color', + 'description' => '', + 'default' => '#4B828E', + 'active_callback' => 'is_custom_scheme_callback' + ); + create_color_control( $args, $wp_customize ); + + $args = array( + 'setting' => 'tag_hover_color', + 'section' => 'colors_section', + 'label' => 'Hovered Tag Color', + 'description' => '', + 'default' => '#39636D', + 'active_callback' => 'is_custom_scheme_callback' + ); + create_color_control( $args, $wp_customize ); + + $args = array( + 'setting' => 'read_more_btn_bg', + 'section' => 'colors_section', + 'label' => 'Read More Button Background', + 'description' => '', + 'default' => '#F5F5F5', + 'active_callback' => 'is_custom_scheme_callback' + ); + create_color_control( $args, $wp_customize ); + + $args = array( + 'setting' => 'read_more_btn_color', + 'section' => 'colors_section', + 'label' => 'Read More Button Color', + 'description' => '', + 'default' => '#2E3B4F', + 'active_callback' => 'is_custom_scheme_callback' + ); + create_color_control( $args, $wp_customize ); + + $args = array( + 'setting' => 'post_comment_btn_bg', + 'section' => 'colors_section', + 'label' => 'Post Comment Button Background', + 'description' => '', + 'default' => '#F5F5F5', + 'active_callback' => 'is_custom_scheme_callback' + ); + create_color_control( $args, $wp_customize ); + + $args = array( + 'setting' => 'post_comment_btn_color', + 'section' => 'colors_section', + 'label' => 'Post Comment Button Color', + 'description' => '', + 'default' => '#2E3B4F', + 'active_callback' => 'is_custom_scheme_callback' + ); + create_color_control( $args, $wp_customize ); \ No newline at end of file diff --git a/inc/customizer-sections/general-section.php b/inc/customizer-sections/general-section.php new file mode 100644 index 0000000..b61f3e7 --- /dev/null +++ b/inc/customizer-sections/general-section.php @@ -0,0 +1,131 @@ +add_section( 'general_section', array( + 'priority' => 10, + 'capability' => 'edit_theme_options', + 'theme_supports' => '', + 'title' => __( 'General', 'yuzu' ), + 'description' => '', + 'panel' => 'theme_settings', +) ); + + /* =============================================== */ + // ## SOCIAL NETWORKS + /* =============================================== */ + $wp_customize->add_control( + new yuzu_Customizer_Accordion( + $wp_customize, + 'yuzu-social-networks-accordion', + array( + 'section' => 'general_section', + 'label' => __( 'Social Networks', 'yuzu' ), + 'type' => 'accordion' + ) + ) + ); + + $wp_customize->add_setting( + 'instagram_url', + array( + 'default' => '', + 'transport' => 'refresh', + 'sanitize_callback' => 'sanitize_text_field', + ) + ); + $wp_customize->add_control( + 'instagram_url', + array( + 'label' => __('Instagram URL', 'yuzu'), + 'description' => __('To hide it, leave it blank.', 'yuzu'), + 'section' => 'general_section', + 'type' => 'text' + ) + ); + + $wp_customize->add_setting( + 'facebook_url', + array( + 'default' => '', + 'transport' => 'refresh', + 'sanitize_callback' => 'sanitize_text_field', + ) + ); + $wp_customize->add_control( + 'facebook_url', + array( + 'label' => __('Facebook URL', 'yuzu'), + 'description' => __('To hide it, leave it blank.', 'yuzu'), + 'section' => 'general_section', + 'type' => 'text' + ) + ); + + $wp_customize->add_setting( + 'twitter_url', + array( + 'default' => '', + 'transport' => 'refresh', + 'sanitize_callback' => 'sanitize_text_field', + ) + ); + $wp_customize->add_control( + 'twitter_url', + array( + 'label' => __('Twitter URL', 'yuzu'), + 'description' => __('To hide it, leave it blank.', 'yuzu'), + 'section' => 'general_section', + 'type' => 'text' + ) + ); + + $wp_customize->add_setting( + 'flickr_url', + array( + 'default' => '', + 'transport' => 'refresh', + 'sanitize_callback' => 'sanitize_text_field', + ) + ); + $wp_customize->add_control( + 'flickr_url', + array( + 'label' => __('Flickr URL', 'yuzu'), + 'description' => __('To hide it, leave it blank.', 'yuzu'), + 'section' => 'general_section', + 'type' => 'text' + ) + ); + + /* =============================================== */ + // ## COPYRIGHT + /* =============================================== */ + $wp_customize->add_control( + new yuzu_Customizer_Accordion( + $wp_customize, + 'yuzu-copyright-infos-accordion', + array( + 'section' => 'general_section', + 'label' => __( 'Copyright', 'yuzu' ), + 'type' => 'accordion' + ) + ) + ); + + $wp_customize->add_setting( + 'copyright_text', + array( + 'default' => '© Yuzu Theme 2018', + 'transport' => 'refresh', + 'sanitize_callback' => 'wp_kses_post', + ) + ); + $wp_customize->add_control( + 'copyright_text', + array( + 'label' => __('Copyright Text', 'yuzu'), + 'section' => 'general_section', + 'type' => 'text' + ) + ); \ No newline at end of file diff --git a/inc/customizer-sections/layout-section.php b/inc/customizer-sections/layout-section.php new file mode 100644 index 0000000..53a129e --- /dev/null +++ b/inc/customizer-sections/layout-section.php @@ -0,0 +1,127 @@ +add_section( 'layout_section', array( + 'priority' => 10, + 'capability' => 'edit_theme_options', + 'theme_supports' => '', + 'title' => __( 'Layout', 'yuzu' ), + 'description' => '', + 'panel' => 'theme_settings', +) ); + + /* =============================================== */ + // ## Top Bar + /* =============================================== */ + $wp_customize->add_control( + new yuzu_Customizer_Accordion( + $wp_customize, + 'yuzu-top-bar-layout-setting-accordion', + array( + 'section' => 'layout_section', + 'label' => __( 'Top Bar', 'yuzu' ), + 'type' => 'accordion' + ) + ) + ); + + $wp_customize->add_setting( 'enable_search_in_top_bar', array( + 'default' => true, + 'transport' => 'refresh', + ) ); + + $wp_customize->add_control( + 'enable_search_in_top_bar', + array( + 'type' => 'checkbox', + 'label' => __('Enable search in the top bar.', 'yuzu'), + 'section' => 'layout_section', + ) + ); + + /* =============================================== */ + // ## Blog + /* =============================================== */ + $wp_customize->add_control( + new yuzu_Customizer_Accordion( + $wp_customize, + 'yuzu-blog-layout-setting-accordion', + array( + 'section' => 'layout_section', + 'label' => __( 'Blog', 'yuzu' ), + 'type' => 'accordion' + ) + ) + ); + + $wp_customize->add_setting( 'enable_posts_height_equalizer', array( + 'default' => true, + 'transport' => 'refresh', + ) ); + + $wp_customize->add_control( + 'enable_posts_height_equalizer', + array( + 'type' => 'checkbox', + 'label' => __('Equalize articles cards height.', 'yuzu'), + 'section' => 'layout_section', + ) + ); + + $wp_customize->add_setting( 'display_posts_navigation', array( + 'default' => true, + 'transport' => 'refresh', + ) ); + + $wp_customize->add_control( + 'display_posts_navigation', + array( + 'type' => 'checkbox', + 'label' => __('Display previous/next articles at the bottom of articles.', 'yuzu'), + 'section' => 'layout_section', + ) + ); + + $wp_customize->add_setting( 'display_posts_meta', array( + 'default' => true, + 'transport' => 'refresh', + ) ); + + $wp_customize->add_control( + 'display_posts_meta', + array( + 'type' => 'checkbox', + 'label' => __('Display article metadata.', 'yuzu'), + 'section' => 'layout_section', + ) + ); + + /* =============================================== */ + // ## Other + /* =============================================== */ + $wp_customize->add_control( + new yuzu_Customizer_Accordion( + $wp_customize, + 'yuzu-other-layout-setting-accordion', + array( + 'section' => 'layout_section', + 'label' => __( 'Others', 'yuzu' ), + 'type' => 'accordion' + ) + ) + ); + + $wp_customize->add_setting( 'enable_scroll_back_to_top_btn', array( + 'default' => true, + 'transport' => 'refresh', + ) ); + + $wp_customize->add_control( + 'enable_scroll_back_to_top_btn', + array( + 'type' => 'checkbox', + 'label' => __('Display a button to scroll back to top of the page.', 'yuzu'), + 'section' => 'layout_section', + ) + ); \ No newline at end of file diff --git a/inc/customizer-sections/style-section.php b/inc/customizer-sections/style-section.php new file mode 100644 index 0000000..e7ad747 --- /dev/null +++ b/inc/customizer-sections/style-section.php @@ -0,0 +1,46 @@ +add_section( 'style_section', array( + 'priority' => 10, + 'capability' => 'edit_theme_options', + 'theme_supports' => '', + 'title' => __( 'Style', 'yuzu' ), + 'description' => '', + 'panel' => 'theme_settings', +) ); + + /* =============================================== */ + // ## Headers + /* =============================================== */ + $wp_customize->add_control( + new yuzu_Customizer_Accordion( + $wp_customize, + 'yuzu-headers-style-sheme-accordion', + array( + 'section' => 'style_section', + 'label' => __( 'Headers', 'yuzu' ), + 'type' => 'accordion' + ) + ) + ); + + $wp_customize->add_setting( 'header_background_opacity', array( + 'default' => 'normal-opaque', + 'transport' => 'refresh', + 'sanitize_callback' => 'sanitize_text_field', + ) ); + $wp_customize->add_control( + 'header_background_opacity', + array( + 'type' => 'radio', + 'label' => __('Header Background Opacity', 'yuzu'), + 'section' => 'style_section', + 'choices' => array( + 'less-opaque' => __('Less opaque', 'yuzu'), + 'normal-opaque' => __('Normal', 'yuzu'), + 'very-opaque' => __('Very opaque', 'yuzu'), + ) + ) + ); \ No newline at end of file diff --git a/inc/customizer.php b/inc/customizer.php new file mode 100644 index 0000000..72c27da --- /dev/null +++ b/inc/customizer.php @@ -0,0 +1,65 @@ +type ) { + default: + case 'heading': + echo '' . esc_html( $this->label ) . ''; + break; + } + } + } + class yuzu_Customizer_Accordion extends WP_Customize_Control { + public $settings = 'blogname'; + public $description = ''; + + public function render_content() { + switch ( $this->type ) { + default: + case 'accordion': + echo ' +
    +

    '. esc_html( $this->label ) .'

    +
    '; + break; + } + } + } +endif; + +/** + * Add postMessage support for site title and description for the Theme Customizer. + * + * @param WP_Customize_Manager $wp_customize Theme Customizer object. + */ +function yuzu_customize_register( $wp_customize ) { + $wp_customize->get_setting( 'blogname' )->transport = 'postMessage'; + $wp_customize->get_setting( 'blogdescription' )->transport = 'postMessage'; + $wp_customize->get_setting( 'header_textcolor' )->transport = 'postMessage'; + + $wp_customize->remove_section('colors'); + $wp_customize->remove_section('header_image'); + $wp_customize->remove_section('background_image'); + + $wp_customize->remove_control('blogdescription'); + $wp_customize->remove_control('display_header_text'); + + $wp_customize->add_panel( 'theme_settings', array( + 'priority' => 10, + 'capability' => 'edit_theme_options', + 'theme_supports' => '', + 'title' => __( 'Yuzu Theme Settings', 'yuzu' ), + 'description' => __( 'All the settings for yuzu Theme', 'yuzu' ), + ) ); + + require get_template_directory() . '/inc/customizer-sections/general-section.php'; + require get_template_directory() . '/inc/customizer-sections/layout-section.php'; + require get_template_directory() . '/inc/customizer-sections/style-section.php'; + require get_template_directory() . '/inc/customizer-sections/colors-section.php'; +} +add_action( 'customize_register', 'yuzu_customize_register' ); + diff --git a/inc/jetpack.php b/inc/jetpack.php new file mode 100644 index 0000000..4aadf8a --- /dev/null +++ b/inc/jetpack.php @@ -0,0 +1,80 @@ + 'articles-list', + 'posts_per_page' => 6, + 'render' => 'yuzu_infinite_scroll_render', + 'footer' => 'page', + ) ); + + // Add theme support for Responsive Videos. + add_theme_support( 'jetpack-responsive-videos' ); + + // Add theme support for Content Options. + add_theme_support( 'jetpack-content-options', array( + 'featured-images' => array( + 'archive' => true, + 'post' => true, + 'page' => true, + ), + ) ); +} +add_action( 'after_setup_theme', 'yuzu_jetpack_setup' ); + +/** + * Custom render function for Infinite Scroll. + */ +function yuzu_infinite_scroll_render() { + $count = 0; + while ( have_posts() ) { + the_post(); + switch($count) { + case 0: + echo '
    '; + require get_template_directory() . '/components/article-cards/large-article-card.php'; + echo '
    '; + $count++; + break; + case 1: + echo '
    '; + require get_template_directory() . '/components/article-cards/medium-article-card.php'; + $count++; + break; + case 2: + require get_template_directory() . '/components/article-cards/medium-article-card.php'; + echo '
    '; + $count++; + break; + case 3: + echo '
    '; + require get_template_directory() . '/components/article-cards/small-article-card.php'; + $count++; + break; + case 4: + require get_template_directory() . '/components/article-cards/small-article-card.php'; + $count++; + break; + case 5: + require get_template_directory() . '/components/article-cards/small-article-card.php'; + echo '
    '; + $count = 0; + break; + } + } +} diff --git a/inc/meow-blocks-output.php b/inc/meow-blocks-output.php new file mode 100644 index 0000000..d7f3508 --- /dev/null +++ b/inc/meow-blocks-output.php @@ -0,0 +1,32 @@ +"; + foreach( $collections as $collection ) { + ob_start(); + require(locate_template('components/collection-card.php')); + $output .= ob_get_clean(); + } + $output .= "
    "; + return $output; +} +add_filter( 'mwt_collections_output', 'yuzu_mwt_collections_output', 10, 2 ); + + +function yuzu_mwt_folders_output( $html, $folders ) { + $output = "
    "; + foreach( $folders as $folder ) { + ob_start(); + require(locate_template('components/folder-card.php')); + $output .= ob_get_clean(); + } + $output .= "
    "; + return $output; +} +add_filter( 'mwt_folders_output', 'yuzu_mwt_folders_output', 10, 2 ); \ No newline at end of file diff --git a/inc/template-functions.php b/inc/template-functions.php new file mode 100644 index 0000000..6a90360 --- /dev/null +++ b/inc/template-functions.php @@ -0,0 +1,37 @@ +', esc_url( get_bloginfo( 'pingback_url' ) ) ); + } +} +add_action( 'wp_head', 'yuzu_pingback_header' ); diff --git a/inc/template-tags.php b/inc/template-tags.php new file mode 100644 index 0000000..95b2256 --- /dev/null +++ b/inc/template-tags.php @@ -0,0 +1,148 @@ +%2$s'; + if ( get_the_time( 'U' ) !== get_the_modified_time( 'U' ) ) { + $time_string = ''; + } + + $time_string = sprintf( $time_string, + esc_attr( get_the_date( DATE_W3C ) ), + esc_html( get_the_date() ), + esc_attr( get_the_modified_date( DATE_W3C ) ), + esc_html( get_the_modified_date() ) + ); + + $posted_on = sprintf( + /* translators: %s: post date. */ + esc_html_x( 'Posted on %s', 'post date', 'yuzu' ), + '' . $time_string . '' + ); + + echo '' . $posted_on . ''; // WPCS: XSS OK. + + } +endif; + +if ( ! function_exists( 'yuzu_posted_by' ) ) : + /** + * Prints HTML with meta information for the current author. + */ + function yuzu_posted_by() { + $byline = sprintf( + /* translators: %s: post author. */ + esc_html_x( 'by %s', 'post author', 'yuzu' ), + '' . esc_html( get_the_author() ) . '' + ); + + echo ''; // WPCS: XSS OK. + + } +endif; + +if ( ! function_exists( 'yuzu_entry_footer' ) ) : + /** + * Prints HTML with meta information for the categories, tags and comments. + */ + function yuzu_entry_footer() { + // Hide category and tag text for pages. + if ( 'post' === get_post_type() ) { + /* translators: used between list items, there is a space after the comma */ + $categories_list = get_the_category_list( esc_html__( ', ', 'yuzu' ) ); + if ( $categories_list ) { + /* translators: 1: list of categories. */ + printf( '' . esc_html__( 'Posted in %1$s', 'yuzu' ) . '', $categories_list ); // WPCS: XSS OK. + } + + /* translators: used between list items, there is a space after the comma */ + $tags_list = get_the_tag_list( '', esc_html_x( ', ', 'list item separator', 'yuzu' ) ); + if ( $tags_list ) { + /* translators: 1: list of tags. */ + printf( '' . esc_html__( 'Tagged %1$s', 'yuzu' ) . '', $tags_list ); // WPCS: XSS OK. + } + } + + if ( ! is_single() && ! post_password_required() && ( comments_open() || get_comments_number() ) ) { + echo ''; + comments_popup_link( + sprintf( + wp_kses( + /* translators: %s: post title */ + __( 'Leave a Comment on %s', 'yuzu' ), + array( + 'span' => array( + 'class' => array(), + ), + ) + ), + get_the_title() + ) + ); + echo ''; + } + + edit_post_link( + sprintf( + wp_kses( + /* translators: %s: Name of current post. Only visible to screen readers */ + __( 'Edit %s', 'yuzu' ), + array( + 'span' => array( + 'class' => array(), + ), + ) + ), + get_the_title() + ), + '', + '' + ); + } +endif; + +if ( ! function_exists( 'yuzu_post_thumbnail' ) ) : + /** + * Displays an optional post thumbnail. + * + * Wraps the post thumbnail in an anchor element on index views, or a div + * element when on single views. + */ + function yuzu_post_thumbnail() { + if ( post_password_required() || is_attachment() || ! has_post_thumbnail() ) { + return; + } + + if ( is_singular() ) : + ?> + +
    + +
    + + + + + + + +
    +
    + +
    + '; + require get_template_directory() . '/components/article-cards/large-article-card.php'; + echo '
    '; + $count++; + break; + case 1: + echo '
    '; + require get_template_directory() . '/components/article-cards/medium-article-card.php'; + $count++; + break; + case 2: + require get_template_directory() . '/components/article-cards/medium-article-card.php'; + echo '
    '; + $count++; + break; + case 3: + echo '
    '; + require get_template_directory() . '/components/article-cards/small-article-card.php'; + $count++; + break; + case 4: + require get_template_directory() . '/components/article-cards/small-article-card.php'; + $count++; + break; + case 5: + require get_template_directory() . '/components/article-cards/small-article-card.php'; + echo '
    '; + $count = 0; + break; + } + + + endwhile; + + the_posts_navigation(); + + else : + + _e('No posts found!', 'yuzu'); + + endif; + ?> +
    + + +
    + + 1);\n" +"X-Poedit-KeywordsList: __;_e\n" +"X-Poedit-SearchPath-0: .\n" + +#: archive.php:11 +msgid "Archive" +msgstr "Archive" + +#: archive.php:65 author.php:65 category.php:73 index.php:56 tag.php:73 +msgid "No posts found!" +msgstr "Aucun article trouvé!" + +#: attachment.php:31 taxonomy-attachment_keyword.php:37 +msgid "Keyword" +msgstr "Mot-clé" + +#: attachment.php:45 +msgid "Description" +msgstr "Description" + +#: attachment.php:52 +msgid "Keywords" +msgstr "Mots-clés" + +#: author.php:11 +msgid "Articles written by" +msgstr "Articles écrits par" + +#: category.php:19 +msgid "Category" +msgstr "Catégorie" + +#: class-tgm-plugin-activation.php:334 +msgid "Install Required Plugins" +msgstr "Installer les extensions requises" + +#: class-tgm-plugin-activation.php:335 +msgid "Install Plugins" +msgstr "Installer les extensions" + +#: class-tgm-plugin-activation.php:337 +#, php-format +msgid "Installing Plugin: %s" +msgstr "Installation de l'extension: %s" + +#: class-tgm-plugin-activation.php:339 +#, php-format +msgid "Updating Plugin: %s" +msgstr "Mise-à-jour de l'extension: %s" + +#: class-tgm-plugin-activation.php:340 +msgid "Something went wrong with the plugin API." +msgstr "Il y a eu une erreur avec l'API de l'extension." + +#: class-tgm-plugin-activation.php:392 +msgid "Return to Required Plugins Installer" +msgstr "Retourner à l'installateur des extensions requises" + +#: class-tgm-plugin-activation.php:393 +msgid "Return to the Dashboard" +msgstr "Retourner au tableau de bord" + +#: class-tgm-plugin-activation.php:394 class-tgm-plugin-activation.php:3252 +msgid "Plugin activated successfully." +msgstr "Extension activée avec succès." + +#: class-tgm-plugin-activation.php:395 +msgid "The following plugin was activated successfully:" +msgstr "Les extensions suivantes ont correctement été activées:" + +#: class-tgm-plugin-activation.php:397 +#, php-format +msgid "No action taken. Plugin %1$s was already active." +msgstr "Aucun action réalisée. L'extension %1s était déjà active." + +#: class-tgm-plugin-activation.php:399 +#, php-format +msgid "" +"Plugin not activated. A higher version of %s is needed for this theme. " +"Please update the plugin." +msgstr "" +"Extension non activée. Une version supérieure de %s est nécéssaire pour ce " +"thème. Veuillez mettre-à-jour l'extension." + +#: class-tgm-plugin-activation.php:401 +#, php-format +msgid "All plugins installed and activated successfully. %1$s" +msgstr "" +"Toutes les extensions ont été installées et activées correctement. %1$s" + +#: class-tgm-plugin-activation.php:402 +msgid "Dismiss this notice" +msgstr "Fermer cette notification" + +#: class-tgm-plugin-activation.php:403 +msgid "" +"There are one or more required or recommended plugins to install, update or " +"activate." +msgstr "" +"Il y a au moins une extension requise ou recommandée à installer, veuillez " +"mettre à jour ou activer." + +#: class-tgm-plugin-activation.php:404 +msgid "Please contact the administrator of this site for help." +msgstr "Veuillez contacter l'administrateur du site pour de l'aide." + +#: class-tgm-plugin-activation.php:2075 +#, php-format +msgid "TGMPA v%s" +msgstr "TGMP v%s" + +#: class-tgm-plugin-activation.php:2366 +msgid "Required" +msgstr "Requis" + +#: class-tgm-plugin-activation.php:2369 +msgid "Recommended" +msgstr "Recommandé" + +#: class-tgm-plugin-activation.php:2385 +msgid "WordPress Repository" +msgstr "Annuaire WordPress" + +#: class-tgm-plugin-activation.php:2388 +msgid "External Source" +msgstr "Source externe" + +#: class-tgm-plugin-activation.php:2391 +msgid "Pre-Packaged" +msgstr "Pré-assemblé" + +#: class-tgm-plugin-activation.php:2408 +msgid "Not Installed" +msgstr "Non installé" + +#: class-tgm-plugin-activation.php:2412 +msgid "Installed But Not Activated" +msgstr "Installé mais non activé" + +#: class-tgm-plugin-activation.php:2414 +msgid "Active" +msgstr "Actif" + +#: class-tgm-plugin-activation.php:2420 +msgid "Required Update not Available" +msgstr "Mise-à-jour requise non disponible" + +#: class-tgm-plugin-activation.php:2423 +msgid "Requires Update" +msgstr "Requiert une mise-à-jour" + +#: class-tgm-plugin-activation.php:2426 +msgid "Update recommended" +msgstr "Mise-à-jour recommandée" + +#: class-tgm-plugin-activation.php:2583 +msgid "Installed version:" +msgstr "Version installée:" + +#: class-tgm-plugin-activation.php:2591 +msgid "Minimum required version:" +msgstr "Version minimale requise:" + +#: class-tgm-plugin-activation.php:2603 +msgid "Available version:" +msgstr "Version disponible:" + +#: class-tgm-plugin-activation.php:2640 +msgid "Plugin" +msgstr "Extension" + +#: class-tgm-plugin-activation.php:2641 +msgid "Source" +msgstr "Source" + +#: class-tgm-plugin-activation.php:2642 +msgid "Type" +msgstr "Type" + +#: class-tgm-plugin-activation.php:2646 +msgid "Version" +msgstr "Version" + +#: class-tgm-plugin-activation.php:2647 +msgid "Status" +msgstr "Statut" + +#: class-tgm-plugin-activation.php:2696 +#, php-format +msgid "Install %2$s" +msgstr "Installer %2$s" + +#: class-tgm-plugin-activation.php:2701 +#, php-format +msgid "Update %2$s" +msgstr "Mettre-à-jour %2$s" + +#: class-tgm-plugin-activation.php:2707 +#, php-format +msgid "Activate %2$s" +msgstr "Activer %2$s" + +#: class-tgm-plugin-activation.php:2810 +msgid "Install" +msgstr "Installer" + +#: class-tgm-plugin-activation.php:2816 +msgid "Update" +msgstr "Mettre-à-jour" + +#: class-tgm-plugin-activation.php:2819 +msgid "Activate" +msgstr "Activer" + +#: class-tgm-plugin-activation.php:2850 +msgid "No plugins were selected to be installed. No action taken." +msgstr "" +"Aucune extension n’a été sélectionnée pour être installée. Aucune action n’a " +"été effectuée." + +#: class-tgm-plugin-activation.php:2852 +msgid "No plugins were selected to be updated. No action taken." +msgstr "" +"Aucune extension n’a été sélectionnée pour être mise à jour. Aucune action " +"n’a été effectuée." + +#: class-tgm-plugin-activation.php:2893 +msgid "No plugins are available to be installed at this time." +msgstr "Aucune extension à installer pour le moment." + +#: class-tgm-plugin-activation.php:2895 +msgid "No plugins are available to be updated at this time." +msgstr "Aucune extension à mettre à jour pour le moment." + +#: class-tgm-plugin-activation.php:3251 +msgid "Plugin activation failed." +msgstr "L’activation de l’extension a échoué." + +#: class-tgm-plugin-activation.php:3591 +#, php-format +msgid "Updating Plugin %1$s (%2$d/%3$d)" +msgstr "Mise à jour de l’extension %1$s (%2$d/%3$d)" + +#: class-tgm-plugin-activation.php:3594 +#, php-format +msgid "An error occurred while installing %1$s: %2$s." +msgstr "" +"Une erreur est survenue lors de l’installation de %1$s: %2$s." + +#: class-tgm-plugin-activation.php:3596 +#, php-format +msgid "The installation of %1$s failed." +msgstr "L’installation de %1$s a échoué." + +#: class-tgm-plugin-activation.php:3600 +msgid "" +"The installation and activation process is starting. This process may take a " +"while on some hosts, so please be patient." +msgstr "" +"Le processus d’installation et d’activation a démarré. Cette opération peut " +"prendre du temps selon votre hébergeur, merci de bien vouloir patienter." + +#: class-tgm-plugin-activation.php:3602 +#, php-format +msgid "%1$s installed and activated successfully." +msgstr "%1$s installé et activé avec succès." + +#: class-tgm-plugin-activation.php:3603 +msgid "All installations and activations have been completed." +msgstr "Toutes les installations et activations sont terminées." + +#: class-tgm-plugin-activation.php:3605 +#, php-format +msgid "Installing and Activating Plugin %1$s (%2$d/%3$d)" +msgstr "Mise à jour et activation de l’extension %1$s (%2$d/%3$d)" + +#: class-tgm-plugin-activation.php:3608 +msgid "" +"The installation process is starting. This process may take a while on some " +"hosts, so please be patient." +msgstr "" +"Le processus d’installation a démarré. Cette opération peut prendre du temps " +"selon votre hébergeur, merci de bien vouloir patienter." + +#: class-tgm-plugin-activation.php:3611 +msgid "All installations have been completed." +msgstr "Toutes les installations sont terminées." + +#: class-tgm-plugin-activation.php:3613 +#, php-format +msgid "Installing Plugin %1$s (%2$d/%3$d)" +msgstr "Installation de l’extension %1$s (%2$d/%3$d)" + +#: comments.php:24 +msgid "Write an answer ..." +msgstr "Écrire une réponse ..." + +#: comments.php:27 +msgid "Post" +msgstr "Poster" + +#: components/article-cards/large-article-card.php:24 +#: components/article-cards/medium-article-card.php:24 +#: components/article-cards/small-article-card.php:24 +msgid "Read More" +msgstr "Lire la suite" + +#: functions.php:260 +msgid "Your comment is awaiting moderation." +msgstr "Votre commentaire est en attente de modération." + +#: header.php:31 +msgid "What are you looking for ... ?" +msgstr "Que cherchez-vous ... ?" + +#: inc/custom-controls.php:358 +msgid "Add" +msgstr "Ajouter" + +#: inc/customizer-sections/colors-section.php:33 +msgid "Colors" +msgstr "Couleurs" + +#: inc/customizer-sections/colors-section.php:48 +#: inc/customizer-sections/colors-section.php:63 +msgid "Color Scheme" +msgstr "Schéma de couleur" + +#: inc/customizer-sections/colors-section.php:66 +msgid "Light Theme (default)" +msgstr "Thème clair ( par défaut )" + +#: inc/customizer-sections/colors-section.php:67 +msgid "Dark Theme" +msgstr "Thème sombre" + +#: inc/customizer-sections/colors-section.php:68 +msgid "Custom Theme" +msgstr "Thème personnalisé" + +#: inc/customizer-sections/colors-section.php:90 +msgid "Backgrounds" +msgstr "Fonds" + +#: inc/customizer-sections/colors-section.php:105 +#: inc/customizer-sections/colors-section.php:209 +#: inc/customizer-sections/colors-section.php:334 +msgid "Unavailable" +msgstr "Indisponible" + +#: inc/customizer-sections/colors-section.php:106 +#: inc/customizer-sections/colors-section.php:210 +#: inc/customizer-sections/colors-section.php:335 +msgid "" +"Please select \"Custom Scheme\" in order to be able to edit colors " +"individually." +msgstr "" +"Veuillez choisir \"Thème personnalisé\" pour pouvoir modifier les couleurs " +"individuellements." + +#: inc/customizer-sections/colors-section.php:194 +msgid "Font Colors" +msgstr "Couleur des textes" + +#: inc/customizer-sections/colors-section.php:319 +#: inc/customizer-sections/layout-section.php:109 +msgid "Others" +msgstr "Autre" + +#: inc/customizer-sections/general-section.php:9 +msgid "General" +msgstr "Général" + +#: inc/customizer-sections/general-section.php:23 +msgid "Social Networks" +msgstr "Réseaux sociaux" + +#: inc/customizer-sections/general-section.php:40 +msgid "Instagram URL" +msgstr "URL Instagram" + +#: inc/customizer-sections/general-section.php:41 +#: inc/customizer-sections/general-section.php:59 +#: inc/customizer-sections/general-section.php:77 +#: inc/customizer-sections/general-section.php:95 +msgid "To hide it, leave it blank." +msgstr "Pour ne pas le montrer, laisser vide." + +#: inc/customizer-sections/general-section.php:58 +msgid "Facebook URL" +msgstr "URL Facebook" + +#: inc/customizer-sections/general-section.php:76 +msgid "Twitter URL" +msgstr "URL Twitter" + +#: inc/customizer-sections/general-section.php:94 +msgid "Flickr URL" +msgstr "URL Flickr" + +#: inc/customizer-sections/general-section.php:110 +msgid "Copyright" +msgstr "Copyright" + +#: inc/customizer-sections/general-section.php:127 +msgid "Copyright Text" +msgstr "Texte du copyright" + +#: inc/customizer-sections/layout-section.php:9 +msgid "Layout" +msgstr "Mise-en-page" + +#: inc/customizer-sections/layout-section.php:23 +msgid "Top Bar" +msgstr "Barre supérieure" + +#: inc/customizer-sections/layout-section.php:38 +msgid "Enable search in the top bar." +msgstr "Activer la recherche dans la barre supérieure." + +#: inc/customizer-sections/layout-section.php:52 +msgid "Blog" +msgstr "Blog" + +#: inc/customizer-sections/layout-section.php:67 +msgid "Equalize articles cards height." +msgstr "Égaliser la hauteur des conteneurs des articles." + +#: inc/customizer-sections/layout-section.php:81 +msgid "Display previous/next articles at the bottom of articles." +msgstr "Afficher les articles suivants/précédents en bas des articles." + +#: inc/customizer-sections/layout-section.php:95 +msgid "Display article metadata." +msgstr "Afficher les métadonnées de l'article." + +#: inc/customizer-sections/layout-section.php:124 +msgid "Display a button to scroll back to top of the page." +msgstr "Afficher un bouton pour remonter en haut de la page." + +#: inc/customizer.php:44 +msgid "Initials" +msgstr "Initiales" + +#: inc/customizer.php:72 +msgid "Yuzu Theme Settings" +msgstr "Réglages du thème yuzu" + +#: inc/customizer.php:73 +msgid "All the settings for yuzu Theme" +msgstr "Tous les réglages du thème Yuzu" + +#: inc/template-tags.php:82 +#, php-format +msgid "Leave a Comment on %s" +msgstr "Laisse un commentaire on %s" + +#: inc/template-tags.php:99 +#, php-format +msgid "Edit %s" +msgstr "Modifier %s" + +#: search.php:12 +msgid "Search Results For" +msgstr "Résultat de la recherche pour" + +#: search.php:38 +msgid "Articles" +msgstr "Articles" + +#: search.php:62 +msgid "Collections" +msgstr "Collections" + +#: search.php:79 +msgid "Images" +msgstr "Images" + +#: single-meow_collection.php:22 +msgid "Home" +msgstr "Acceuil" + +#: single.php:74 +msgid "Previous Post" +msgstr "Article précédent" + +#: single.php:89 +msgid "Next Post" +msgstr "Article suivant" + +#: tag.php:19 +msgid "Tag" +msgstr "Tag" + +#: taxonomy-meow_folder.php:22 +msgid "" +"Sorry, but it seems you haven't installed the Photography Core plugin ? " +"Please install it to use photography related features on this theme." +msgstr "" +"Désolé, mais il semblerait que vous n'ayez pas installé l'extension " +"Photography Core? Veuillez l'installer pour pouvoir utiliser des " +"fonctionalités liées à la photographie sur ce thème." + +#~ msgid "Schemes" +#~ msgstr "Schémas" diff --git a/languages/ja.mo b/languages/ja.mo new file mode 100644 index 0000000..0f3f1a8 Binary files /dev/null and b/languages/ja.mo differ diff --git a/languages/ja.po b/languages/ja.po new file mode 100644 index 0000000..c0da4be --- /dev/null +++ b/languages/ja.po @@ -0,0 +1,501 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"POT-Creation-Date: 2019-06-14 14:43+0900\n" +"PO-Revision-Date: 2019-06-14 14:58+0900\n" +"Last-Translator: \n" +"Language-Team: \n" +"Language: ja_JP\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 2.2.3\n" +"X-Poedit-Basepath: ..\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Poedit-KeywordsList: __;_e\n" +"X-Poedit-SearchPath-0: .\n" + +#: archive.php:11 +msgid "Archive" +msgstr "アーカイブ" + +#: archive.php:65 author.php:65 category.php:73 index.php:56 tag.php:73 +msgid "No posts found!" +msgstr "投稿ではありません!" + +#: attachment.php:31 taxonomy-attachment_keyword.php:37 +msgid "Keyword" +msgstr "キーワード" + +#: attachment.php:45 +msgid "Description" +msgstr "説明" + +#: attachment.php:52 +msgid "Keywords" +msgstr "キーワード" + +#: author.php:11 +msgid "Articles written by" +msgstr "によって書かれた" + +#: category.php:19 +msgid "Category" +msgstr "カテゴリー" + +#: class-tgm-plugin-activation.php:334 +msgid "Install Required Plugins" +msgstr "必須プラグインのインストール" + +#: class-tgm-plugin-activation.php:335 +msgid "Install Plugins" +msgstr "プラグインのインストール" + +#: class-tgm-plugin-activation.php:337 +#, php-format +msgid "Installing Plugin: %s" +msgstr "プラグインのインストール中: %s" + +#: class-tgm-plugin-activation.php:339 +#, php-format +msgid "Updating Plugin: %s" +msgstr "プラグインを更新中: %s" + +#: class-tgm-plugin-activation.php:340 +msgid "Something went wrong with the plugin API." +msgstr "プラグイン API で問題が発生しました。" + +#: class-tgm-plugin-activation.php:392 +msgid "Return to Required Plugins Installer" +msgstr "必須プラグインのインストール画面に戻る" + +#: class-tgm-plugin-activation.php:393 +msgid "Return to the Dashboard" +msgstr "ダッシュボードに戻る" + +#: class-tgm-plugin-activation.php:394 class-tgm-plugin-activation.php:3252 +msgid "Plugin activated successfully." +msgstr "プラグインを有効化しました。" + +#: class-tgm-plugin-activation.php:395 +msgid "The following plugin was activated successfully:" +msgstr "次のプラグインを有効化しました:" + +#: class-tgm-plugin-activation.php:397 +#, php-format +msgid "No action taken. Plugin %1$s was already active." +msgstr "操作を実行しませんでした。プラグイン %1$s はすでに有効化されています。" + +#: class-tgm-plugin-activation.php:399 +#, php-format +msgid "" +"Plugin not activated. A higher version of %s is needed for this theme. " +"Please update the plugin." +msgstr "" +"プラグインを有効化できませんでした。このテーマはプラグイン %s の現在のバー" +"ジョンをサポートしていません。プラグインを更新してください。" + +#: class-tgm-plugin-activation.php:401 +#, php-format +msgid "All plugins installed and activated successfully. %1$s" +msgstr "すべてのプラグインを正常にインストールし、有効化しました。 %1$s" + +#: class-tgm-plugin-activation.php:402 +msgid "Dismiss this notice" +msgstr "通知を無視" + +#: class-tgm-plugin-activation.php:403 +msgid "" +"There are one or more required or recommended plugins to install, update or " +"activate." +msgstr "" +"インストール、更新、有効化可能な必須、または推奨のプラグインがあります。" + +#: class-tgm-plugin-activation.php:404 +msgid "Please contact the administrator of this site for help." +msgstr "ヘルプが必要な場合はこのサイトの管理者にお問い合わせください。" + +#: class-tgm-plugin-activation.php:2075 +#, php-format +msgid "TGMPA v%s" +msgstr "TGMPA v%s" + +#: class-tgm-plugin-activation.php:2366 +msgid "Required" +msgstr "必須" + +#: class-tgm-plugin-activation.php:2369 +msgid "Recommended" +msgstr "推奨" + +#: class-tgm-plugin-activation.php:2385 +msgid "WordPress Repository" +msgstr "WordPress 公式ディレクトリ" + +#: class-tgm-plugin-activation.php:2388 +msgid "External Source" +msgstr "外部ソース" + +#: class-tgm-plugin-activation.php:2391 +msgid "Pre-Packaged" +msgstr "プリパッケージ" + +#: class-tgm-plugin-activation.php:2408 +msgid "Not Installed" +msgstr "未インストール" + +#: class-tgm-plugin-activation.php:2412 +msgid "Installed But Not Activated" +msgstr "停止中" + +#: class-tgm-plugin-activation.php:2414 +msgid "Active" +msgstr "有効" + +#: class-tgm-plugin-activation.php:2420 +msgid "Required Update not Available" +msgstr "必要な更新が利用不可" + +#: class-tgm-plugin-activation.php:2423 +msgid "Requires Update" +msgstr "更新が必要" + +#: class-tgm-plugin-activation.php:2426 +msgid "Update recommended" +msgstr "更新を推奨" + +#: class-tgm-plugin-activation.php:2583 +msgid "Installed version:" +msgstr "インストール済みバージョン:" + +#: class-tgm-plugin-activation.php:2591 +msgid "Minimum required version:" +msgstr "最低要求バージョン:" + +#: class-tgm-plugin-activation.php:2603 +msgid "Available version:" +msgstr "利用可能なバージョン:" + +#: class-tgm-plugin-activation.php:2640 +msgid "Plugin" +msgstr "プラグイン" + +#: class-tgm-plugin-activation.php:2641 +msgid "Source" +msgstr "取得元" + +#: class-tgm-plugin-activation.php:2642 +msgid "Type" +msgstr "タイプ" + +#: class-tgm-plugin-activation.php:2646 +msgid "Version" +msgstr "バージョン" + +#: class-tgm-plugin-activation.php:2647 +msgid "Status" +msgstr "状態" + +#: class-tgm-plugin-activation.php:2696 +#, php-format +msgid "Install %2$s" +msgstr "%2$s インストール" + +#: class-tgm-plugin-activation.php:2701 +#, php-format +msgid "Update %2$s" +msgstr "%2$s 更新" + +#: class-tgm-plugin-activation.php:2707 +#, php-format +msgid "Activate %2$s" +msgstr "%2$s 有効化" + +#: class-tgm-plugin-activation.php:2810 +msgid "Install" +msgstr "インストール" + +#: class-tgm-plugin-activation.php:2816 +msgid "Update" +msgstr "更新" + +#: class-tgm-plugin-activation.php:2819 +msgid "Activate" +msgstr "有効化" + +#: class-tgm-plugin-activation.php:2850 +msgid "No plugins were selected to be installed. No action taken." +msgstr "インストールするプラグインが選択されていません。処理を中断しました。" + +#: class-tgm-plugin-activation.php:2852 +msgid "No plugins were selected to be updated. No action taken." +msgstr "更新するプラグインが選択されていません。処理を中断しました。" + +#: class-tgm-plugin-activation.php:2893 +msgid "No plugins are available to be installed at this time." +msgstr "現在インストール可能なプラグインはありません。" + +#: class-tgm-plugin-activation.php:2895 +msgid "No plugins are available to be updated at this time." +msgstr "現在更新可能なプラグインはありません。" + +#: class-tgm-plugin-activation.php:3251 +msgid "Plugin activation failed." +msgstr "プラグインの有効化に失敗しました。" + +#: class-tgm-plugin-activation.php:3591 +#, php-format +msgid "Updating Plugin %1$s (%2$d/%3$d)" +msgstr "プラグインを更新中 %1$s (%2$d/%3$d)" + +#: class-tgm-plugin-activation.php:3594 +#, php-format +msgid "An error occurred while installing %1$s: %2$s." +msgstr "%2$s%1$s のインストール中にエラーが発生しました。" + +#: class-tgm-plugin-activation.php:3596 +#, php-format +msgid "The installation of %1$s failed." +msgstr "%1$s のインストールに失敗しました。" + +#: class-tgm-plugin-activation.php:3600 +msgid "" +"The installation and activation process is starting. This process may take a " +"while on some hosts, so please be patient." +msgstr "" +"インストールと有効化を開始しました。環境によっては時間がかかる場合がありま" +"す。しばらくお待ちください。" + +#: class-tgm-plugin-activation.php:3602 +#, php-format +msgid "%1$s installed and activated successfully." +msgstr "%1$s を正常にインストールし、有効化しました。" + +#: class-tgm-plugin-activation.php:3603 +msgid "All installations and activations have been completed." +msgstr "すべてのインストールと有効化が完了しました。" + +#: class-tgm-plugin-activation.php:3605 +#, php-format +msgid "Installing and Activating Plugin %1$s (%2$d/%3$d)" +msgstr "プラグインをインストール、有効化中 %1$s (%2$d/%3$d)" + +#: class-tgm-plugin-activation.php:3608 +msgid "" +"The installation process is starting. This process may take a while on some " +"hosts, so please be patient." +msgstr "" +"更新プロセスを開始しました。環境によっては時間がかかる場合があります。しばら" +"くお待ちください。" + +#: class-tgm-plugin-activation.php:3611 +msgid "All installations have been completed." +msgstr "すべてのインストールが完了しました。" + +#: class-tgm-plugin-activation.php:3613 +#, php-format +msgid "Installing Plugin %1$s (%2$d/%3$d)" +msgstr "プラグインをインストール中 %1$s (%2$d/%3$d)" + +#: comments.php:24 +msgid "Write an answer ..." +msgstr "コメントを残す ..." + +#: comments.php:27 +msgid "Post" +msgstr "投稿" + +#: components/article-cards/large-article-card.php:24 +#: components/article-cards/medium-article-card.php:24 +#: components/article-cards/small-article-card.php:24 +msgid "Read More" +msgstr "続きを読む" + +#: functions.php:260 +msgid "Your comment is awaiting moderation." +msgstr "あなたのコメントは現在承認待ちです。" + +#: header.php:31 +msgid "What are you looking for ... ?" +msgstr "何を探していますか...?" + +#: inc/custom-controls.php:358 +msgid "Add" +msgstr "付け足す" + +#: inc/customizer-sections/colors-section.php:33 +msgid "Colors" +msgstr "色" + +#: inc/customizer-sections/colors-section.php:48 +#: inc/customizer-sections/colors-section.php:63 +msgid "Color Scheme" +msgstr "配色" + +#: inc/customizer-sections/colors-section.php:66 +msgid "Light Theme (default)" +msgstr "明るい" + +#: inc/customizer-sections/colors-section.php:67 +msgid "Dark Theme" +msgstr "暗闇" + +#: inc/customizer-sections/colors-section.php:68 +msgid "Custom Theme" +msgstr "風習" + +#: inc/customizer-sections/colors-section.php:90 +msgid "Backgrounds" +msgstr "背景" + +#: inc/customizer-sections/colors-section.php:105 +#: inc/customizer-sections/colors-section.php:209 +#: inc/customizer-sections/colors-section.php:334 +msgid "Unavailable" +msgstr "無効" + +#: inc/customizer-sections/colors-section.php:106 +#: inc/customizer-sections/colors-section.php:210 +#: inc/customizer-sections/colors-section.php:335 +msgid "" +"Please select \"Custom Scheme\" in order to be able to edit colors " +"individually." +msgstr "風習を選べて下さい。" + +#: inc/customizer-sections/colors-section.php:194 +msgid "Font Colors" +msgstr "テキスト色" + +#: inc/customizer-sections/colors-section.php:319 +#: inc/customizer-sections/layout-section.php:109 +msgid "Others" +msgstr "その他" + +#: inc/customizer-sections/general-section.php:9 +msgid "General" +msgstr "一般" + +#: inc/customizer-sections/general-section.php:23 +msgid "Social Networks" +msgstr "SNS" + +#: inc/customizer-sections/general-section.php:40 +msgid "Instagram URL" +msgstr "インスタグラムのURL" + +#: inc/customizer-sections/general-section.php:41 +#: inc/customizer-sections/general-section.php:59 +#: inc/customizer-sections/general-section.php:77 +#: inc/customizer-sections/general-section.php:95 +msgid "To hide it, leave it blank." +msgstr "虚しいだったら見せません。" + +#: inc/customizer-sections/general-section.php:58 +msgid "Facebook URL" +msgstr "FacebookのURL" + +#: inc/customizer-sections/general-section.php:76 +msgid "Twitter URL" +msgstr "ツイッターのURL" + +#: inc/customizer-sections/general-section.php:94 +msgid "Flickr URL" +msgstr "FlickrのURL" + +#: inc/customizer-sections/general-section.php:110 +msgid "Copyright" +msgstr "著作権" + +#: inc/customizer-sections/general-section.php:127 +msgid "Copyright Text" +msgstr "著作権" + +#: inc/customizer-sections/layout-section.php:9 +msgid "Layout" +msgstr "設計" + +#: inc/customizer-sections/layout-section.php:23 +msgid "Top Bar" +msgstr "上部分" + +#: inc/customizer-sections/layout-section.php:38 +msgid "Enable search in the top bar." +msgstr "上部分の検索フィールドを見せます。" + +#: inc/customizer-sections/layout-section.php:52 +msgid "Blog" +msgstr "ブロッグ" + +#: inc/customizer-sections/layout-section.php:67 +msgid "Equalize articles cards height." +msgstr "投稿の高さを平等にする." + +#: inc/customizer-sections/layout-section.php:81 +msgid "Display previous/next articles at the bottom of articles." +msgstr "過去の投稿/次の投稿を見せます。" + +#: inc/customizer-sections/layout-section.php:95 +msgid "Display article metadata." +msgstr "投稿のメタを見せます。" + +#: inc/customizer-sections/layout-section.php:124 +msgid "Display a button to scroll back to top of the page." +msgstr "ページの上部までスクロールしてくれるボタンを見せる。" + +#: inc/customizer.php:55 +msgid "Yuzu Theme Settings" +msgstr "Yuzuテーマの設定" + +#: inc/customizer.php:56 +msgid "All the settings for yuzu Theme" +msgstr "Yuzuテーマの設定" + +#: inc/template-tags.php:82 +#, php-format +msgid "Leave a Comment on %s" +msgstr "%sにコメントを残す" + +#: inc/template-tags.php:99 +#, php-format +msgid "Edit %s" +msgstr "編集 %s" + +#: search.php:12 +msgid "Search Results For" +msgstr "検索結果" + +#: search.php:38 +msgid "Articles" +msgstr "投稿" + +#: search.php:62 +msgid "Collections" +msgstr "コレクション" + +#: search.php:79 +msgid "Images" +msgstr "写真" + +#: single-meow_collection.php:22 +msgid "Home" +msgstr "トップ" + +#: single.php:74 +msgid "Previous Post" +msgstr "過去の投稿" + +#: single.php:89 +msgid "Next Post" +msgstr "次の投稿" + +#: tag.php:19 +msgid "Tag" +msgstr "タグ" + +#: taxonomy-meow_folder.php:22 +msgid "" +"Sorry, but it seems you haven't installed the Photography Core plugin ? " +"Please install it to use photography related features on this theme." +msgstr "" +"ごめんなさいですけど「Photography Core」と言うプラグイン見つからないようで" +"す。インストール下さい。" diff --git a/languages/readme.txt b/languages/readme.txt new file mode 100644 index 0000000..4b1570f --- /dev/null +++ b/languages/readme.txt @@ -0,0 +1,7 @@ +Place your theme language files in this directory. + +Please visit the following links to learn more about translating WordPress themes: + +https://make.wordpress.org/polyglots/teams/ +https://developer.wordpress.org/themes/functionality/localization/ +https://developer.wordpress.org/reference/functions/load_theme_textdomain/ diff --git a/languages/yuzu.pot b/languages/yuzu.pot new file mode 100644 index 0000000..59216a2 --- /dev/null +++ b/languages/yuzu.pot @@ -0,0 +1,186 @@ +# Copyright (C) 2017 Automattic +# This file is distributed under the GNU General Public License v2 or later. +msgid "" +msgstr "" +"Project-Id-Version: _s 1.0.0\n" +"Report-Msgid-Bugs-To: https://wordpress.org/tags/_s\n" +"POT-Creation-Date: 2016-12-23 16:00+0100\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"PO-Revision-Date: 2017-MO-DA HO:MI+ZONE\n" +"Last-Translator:\n" +"Language-Team: LANGUAGE \n" +"X-Generator: grunt-wp-i18n 0.5.4\n" + +#: 404.php:17 +msgid "Oops! That page can’t be found." +msgstr "" + +#: 404.php:21 +msgid "" +"It looks like nothing was found at this location. Maybe try one of the " +"links below or a search?" +msgstr "" + +#: 404.php:30 +msgid "Most Used Categories" +msgstr "" + +#: 404.php:47 +#. translators: %1$s: smiley +msgid "Try looking in the monthly archives. %1$s" +msgstr "" + +#: comments.php:34 +#. translators: 1: title. +msgid "One thought on “%1$s”" +msgstr "" + +#: comments.php:67 +msgid "Comments are closed." +msgstr "" + +#: footer.php:18 +msgid "https://wordpress.org/" +msgstr "" + +#: footer.php:20 +#. translators: %s: CMS name, i.e. WordPress. +msgid "Proudly powered by %s" +msgstr "" + +#: footer.php:25 +#. translators: 1: Theme name, 2: Theme author. +msgid "Theme: %1$s by %2$s." +msgstr "" + +#: functions.php:47 +msgid "Primary" +msgstr "" + +#: functions.php:105 +msgid "Sidebar" +msgstr "" + +#: functions.php:107 +msgid "Add widgets here." +msgstr "" + +#: header.php:24 +msgid "Skip to content" +msgstr "" + +#: header.php:45 +msgid "Primary Menu" +msgstr "" + +#: inc/template-tags.php:52 +#. translators: used between list items, there is a space after the comma +msgid ", " +msgstr "" + +#: inc/template-tags.php:55 +#. translators: 1: list of categories. +msgid "Posted in %1$s" +msgstr "" + +#: inc/template-tags.php:62 +#. translators: 1: list of tags. +msgid "Tagged %1$s" +msgstr "" + +#: inc/template-tags.php:72 +#. translators: %s: post title +msgid "Leave a Comment on %s" +msgstr "" + +#: inc/template-tags.php:89 template-parts/content-page.php:35 +#. translators: %s: Name of current post. Only visible to screen readers +msgid "Edit %s" +msgstr "" + +#: search.php:21 +#. translators: %s: search query. +msgid "Search Results for: %s" +msgstr "" + +#: template-parts/content-none.php:14 +msgid "Nothing Found" +msgstr "" + +#: template-parts/content-none.php:25 +#. translators: 1: link to WP admin new post page. +msgid "Ready to publish your first post? Get started here." +msgstr "" + +#: template-parts/content-none.php:38 +msgid "" +"Sorry, but nothing matched your search terms. Please try again with some " +"different keywords." +msgstr "" + +#: template-parts/content-none.php:44 +msgid "" +"It seems we can’t find what you’re looking for. Perhaps " +"searching can help." +msgstr "" + +#: template-parts/content-page.php:22 template-parts/content.php:45 +msgid "Pages:" +msgstr "" + +#: template-parts/content.php:34 +#. translators: %s: Name of current post. Only visible to screen readers +msgid "Continue reading \"%s\"" +msgstr "" + +#. Theme Name of the plugin/theme +msgid "_s" +msgstr "" + +#. Theme URI of the plugin/theme +msgid "https://underscores.me/" +msgstr "" + +#. Description of the plugin/theme +msgid "" +"Hi. I'm a starter theme called _s, or underscores, if " +"you like. I'm a theme meant for hacking so don't use me as a Parent " +"Theme. Instead try turning me into the next, most awesome, WordPress " +"theme out there. That's what I'm here for." +msgstr "" + +#. Author of the plugin/theme +msgid "Automattic" +msgstr "" + +#. Author URI of the plugin/theme +msgid "https://automattic.com/" +msgstr "" + +#: comments.php:40 +#. translators: 1: comment count number, 2: title. +msgctxt "comments title" +msgid "%1$s thought on “%2$s”" +msgid_plural "%1$s thoughts on “%2$s”" +msgstr[0] "" +msgstr[1] "" + +#: inc/template-tags.php:29 +#. translators: %s: post date. +msgctxt "post date" +msgid "Posted on %s" +msgstr "" + +#: inc/template-tags.php:35 +#. translators: %s: post author. +msgctxt "post author" +msgid "by %s" +msgstr "" + +#: inc/template-tags.php:59 +#. translators: used between list items, there is a space after the comma +msgctxt "list item separator" +msgid ", " +msgstr "" diff --git a/page-templates/template-no-header-page.php b/page-templates/template-no-header-page.php new file mode 100644 index 0000000..3a4b7e7 --- /dev/null +++ b/page-templates/template-no-header-page.php @@ -0,0 +1,44 @@ + + + +
    +
    + + +
    + + +
    + +
    + + +
    + +
    + +
    + +
    +
    + + + +
    +
    + + +
    + + + + + + + +
    + +
    + + +
    + +
    + +
    + +
    +
    + + + + + + + + + + A custom set of code standard rules to check for WordPress themes. + + + + + + + + + + + + + + + + + + . + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/rtl.css b/rtl.css new file mode 100644 index 0000000..25a1a82 --- /dev/null +++ b/rtl.css @@ -0,0 +1,17 @@ +/* +Theme Name: Yuzu + +Adding support for languages written in a Right To Left (RTL) direction is easy - +it's just a matter of overwriting all the horizontal positioning attributes +of your CSS stylesheet in a separate stylesheet file named rtl.css. + +https://codex.wordpress.org/Right-to-Left_Language_Support + +*/ + +/* +body { + direction: rtl; + unicode-bidi: embed; +} +*/ diff --git a/screenshot.png b/screenshot.png new file mode 100644 index 0000000..98c347e Binary files /dev/null and b/screenshot.png differ diff --git a/search.php b/search.php new file mode 100644 index 0000000..d111bbb --- /dev/null +++ b/search.php @@ -0,0 +1,100 @@ + + +
    +
    + +
    + +
    + +
    + +
    +

    +
    +
    +
    + +
    + +
    +

    +
    +
    +
    + get_collection($post->ID); + require get_template_directory() . '/components/collection-card.php'; + } + endwhile; + ?> +
    + +
    +

    +
    +
    +
    + ID; + } + endwhile; + $ids = implode(',',$ids_array); + echo do_shortcode('[gallery mgl-layout="default" ids="'.$ids.'"]'); + ?> +
    + +
    + +
    +
    + + + +
    +
    + +
    + + + + +
    + +
    + + +
    + +
    + +
    + +
    +
    + + + +
    +
    + +
    > + +
    +
    + + + +
    +

    + + + +
    + + +
    + +
    + + +
    + +
    + + + + + + +
    + +
    + +
    + +
    +
    + +>> TABLE OF CONTENTS: +---------------------------------------------------------------- +# Normalize +# Typography +# Elements +# Forms +# Navigation + ## Links + ## Menus +# Accessibility +# Alignments +# Clearings +# Widgets +# Content + ## Posts and pages + ## Comments +# Infinite scroll +# Media + ## Captions + ## Galleries +--------------------------------------------------------------*/ +/*-------------------------------------------------------------- +# Normalize +--------------------------------------------------------------*/ +/* normalize.css v8.0.0 | MIT License | github.com/necolas/normalize.css */ +/* Document + ========================================================================== */ +/** + * 1. Correct the line height in all browsers. + * 2. Prevent adjustments of font size after orientation changes in iOS. + */ +html { + line-height: 1.15; + /* 1 */ + -webkit-text-size-adjust: 100%; + /* 2 */ +} +/* Sections + ========================================================================== */ +/** + * Remove the margin in all browsers. + */ +body { + margin: 0; +} +/** + * Correct the font size and margin on `h1` elements within `section` and + * `article` contexts in Chrome, Firefox, and Safari. + */ +h1 { + font-size: 2em; + margin: 0.67em 0; +} +/* Grouping content + ========================================================================== */ +/** + * 1. Add the correct box sizing in Firefox. + * 2. Show the overflow in Edge and IE. + */ +hr { + box-sizing: content-box; + /* 1 */ + height: 0; + /* 1 */ + overflow: visible; + /* 2 */ +} +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ +pre { + font-family: monospace, monospace; + /* 1 */ + font-size: 1em; + /* 2 */ +} +/* Text-level semantics + ========================================================================== */ +/** + * Remove the gray background on active links in IE 10. + */ +a { + background-color: transparent; +} +/** + * 1. Remove the bottom border in Chrome 57- + * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. + */ +abbr[title] { + border-bottom: none; + /* 1 */ + text-decoration: underline; + /* 2 */ + text-decoration: underline dotted; + /* 2 */ +} +/** + * Add the correct font weight in Chrome, Edge, and Safari. + */ +b, +strong { + font-weight: bolder; +} +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ +code, +kbd, +samp { + font-family: monospace, monospace; + /* 1 */ + font-size: 1em; + /* 2 */ +} +/** + * Add the correct font size in all browsers. + */ +small { + font-size: 80%; +} +/** + * Prevent `sub` and `sup` elements from affecting the line height in + * all browsers. + */ +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} +sub { + bottom: -0.25em; +} +sup { + top: -0.5em; +} +/* Embedded content + ========================================================================== */ +/** + * Remove the border on images inside links in IE 10. + */ +img { + border-style: none; +} +/* Forms + ========================================================================== */ +/** + * 1. Change the font styles in all browsers. + * 2. Remove the margin in Firefox and Safari. + */ +button, +input, +optgroup, +select, +textarea { + font-family: inherit; + /* 1 */ + font-size: 100%; + /* 1 */ + line-height: 1.15; + /* 1 */ + margin: 0; + /* 2 */ +} +/** + * Show the overflow in IE. + * 1. Show the overflow in Edge. + */ +button, +input { + /* 1 */ + overflow: visible; +} +/** + * Remove the inheritance of text transform in Edge, Firefox, and IE. + * 1. Remove the inheritance of text transform in Firefox. + */ +button, +select { + /* 1 */ + text-transform: none; +} +/** + * Correct the inability to style clickable types in iOS and Safari. + */ +button, +[type="button"], +[type="reset"], +[type="submit"] { + -webkit-appearance: button; +} +/** + * Remove the inner border and padding in Firefox. + */ +button::-moz-focus-inner, +[type="button"]::-moz-focus-inner, +[type="reset"]::-moz-focus-inner, +[type="submit"]::-moz-focus-inner { + border-style: none; + padding: 0; +} +/** + * Restore the focus styles unset by the previous rule. + */ +button:-moz-focusring, +[type="button"]:-moz-focusring, +[type="reset"]:-moz-focusring, +[type="submit"]:-moz-focusring { + outline: 1px dotted ButtonText; +} +/** + * Correct the padding in Firefox. + */ +fieldset { + padding: 0.35em 0.75em 0.625em; +} +/** + * 1. Correct the text wrapping in Edge and IE. + * 2. Correct the color inheritance from `fieldset` elements in IE. + * 3. Remove the padding so developers are not caught out when they zero out + * `fieldset` elements in all browsers. + */ +legend { + box-sizing: border-box; + /* 1 */ + color: inherit; + /* 2 */ + display: table; + /* 1 */ + max-width: 100%; + /* 1 */ + padding: 0; + /* 3 */ + white-space: normal; + /* 1 */ +} +/** + * Add the correct vertical alignment in Chrome, Firefox, and Opera. + */ +progress { + vertical-align: baseline; +} +/** + * Remove the default vertical scrollbar in IE 10+. + */ +textarea { + overflow: auto; +} +/** + * 1. Add the correct box sizing in IE 10. + * 2. Remove the padding in IE 10. + */ +[type="checkbox"], +[type="radio"] { + box-sizing: border-box; + /* 1 */ + padding: 0; + /* 2 */ +} +/** + * Correct the cursor style of increment and decrement buttons in Chrome. + */ +[type="number"]::-webkit-inner-spin-button, +[type="number"]::-webkit-outer-spin-button { + height: auto; +} +/** + * 1. Correct the odd appearance in Chrome and Safari. + * 2. Correct the outline style in Safari. + */ +[type="search"] { + -webkit-appearance: textfield; + /* 1 */ + outline-offset: -2px; + /* 2 */ +} +/** + * Remove the inner padding in Chrome and Safari on macOS. + */ +[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} +/** + * 1. Correct the inability to style clickable types in iOS and Safari. + * 2. Change font properties to `inherit` in Safari. + */ +::-webkit-file-upload-button { + -webkit-appearance: button; + /* 1 */ + font: inherit; + /* 2 */ +} +/* Interactive + ========================================================================== */ +/* + * Add the correct display in Edge, IE 10+, and Firefox. + */ +details { + display: block; +} +/* + * Add the correct display in all browsers. + */ +summary { + display: list-item; +} +/* Misc + ========================================================================== */ +/** + * Add the correct display in IE 10+. + */ +template { + display: none; +} +/** + * Add the correct display in IE 10. + */ +[hidden] { + display: none; +} +/*-------------------------------------------------------------- +# Typography +--------------------------------------------------------------*/ +body, +button, +input, +select, +optgroup, +textarea { + color: #404040; + font-family: sans-serif; + font-size: 16px; + font-size: 1rem; + line-height: 1.5; +} +h1, +h2, +h3, +h4, +h5, +h6 { + clear: both; +} +p { + margin-bottom: 1.5em; +} +dfn, +cite, +em, +i { + font-style: italic; +} +blockquote { + margin: 0 1.5em; +} +address { + margin: 0 0 1.5em; +} +pre { + background: #eee; + font-family: "Courier 10 Pitch", Courier, monospace; + font-size: 15px; + font-size: 0.9375rem; + line-height: 1.6; + margin-bottom: 1.6em; + max-width: 100%; + overflow: auto; + padding: 1.6em; +} +code, +kbd, +tt, +var { + font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; + font-size: 15px; + font-size: 0.9375rem; +} +abbr, +acronym { + border-bottom: 1px dotted #666; + cursor: help; +} +mark, +ins { + background: #fff9c0; + text-decoration: none; +} +big { + font-size: 125%; +} +/*-------------------------------------------------------------- +# Elements +--------------------------------------------------------------*/ +html { + box-sizing: border-box; +} +*, +*:before, +*:after { + /* Inherit box-sizing to make it easier to change the property for components that leverage other behavior; see https://css-tricks.com/inheriting-box-sizing-probably-slightly-better-best-practice/ */ + box-sizing: inherit; +} +body { + background: #fff; + /* Fallback for when there is no custom background color defined. */ +} +hr { + background-color: #ccc; + border: 0; + height: 1px; + margin-bottom: 1.5em; +} +ul, +ol { + margin: 0 0 1.5em 3em; +} +ul { + list-style: disc; +} +ol { + list-style: decimal; +} +li > ul, +li > ol { + margin-bottom: 0; + margin-left: 1.5em; +} +dt { + font-weight: bold; +} +dd { + margin: 0 1.5em 1.5em; +} +img { + height: auto; + /* Make sure images are scaled correctly. */ + max-width: 100%; + /* Adhere to container width. */ +} +figure { + margin: 1em 0; + /* Extra wide images within figure tags don't overflow the content area. */ +} +table { + margin: 0 0 1.5em; + width: 100%; +} +/*-------------------------------------------------------------- +# Forms +--------------------------------------------------------------*/ +button, +input[type="button"], +input[type="reset"], +input[type="submit"] { + border: 1px solid; + border-color: #ccc #ccc #bbb; + border-radius: 3px; + background: #e6e6e6; + color: rgba(0, 0, 0, 0.8); + font-size: 12px; + font-size: 0.75rem; + line-height: 1; + padding: .6em 1em .4em; +} +button:hover, +input[type="button"]:hover, +input[type="reset"]:hover, +input[type="submit"]:hover { + border-color: #ccc #bbb #aaa; +} +button:active, +button:focus, +input[type="button"]:active, +input[type="button"]:focus, +input[type="reset"]:active, +input[type="reset"]:focus, +input[type="submit"]:active, +input[type="submit"]:focus { + border-color: #aaa #bbb #bbb; +} +input[type="text"], +input[type="email"], +input[type="url"], +input[type="password"], +input[type="search"], +input[type="number"], +input[type="tel"], +input[type="range"], +input[type="date"], +input[type="month"], +input[type="week"], +input[type="time"], +input[type="datetime"], +input[type="datetime-local"], +input[type="color"], +textarea { + color: #666; + border: 1px solid #ccc; + border-radius: 3px; + padding: 3px; +} +input[type="text"]:focus, +input[type="email"]:focus, +input[type="url"]:focus, +input[type="password"]:focus, +input[type="search"]:focus, +input[type="number"]:focus, +input[type="tel"]:focus, +input[type="range"]:focus, +input[type="date"]:focus, +input[type="month"]:focus, +input[type="week"]:focus, +input[type="time"]:focus, +input[type="datetime"]:focus, +input[type="datetime-local"]:focus, +input[type="color"]:focus, +textarea:focus { + color: #111; +} +select { + border: 1px solid #ccc; +} +textarea { + width: 100%; +} +/*-------------------------------------------------------------- +# Navigation +--------------------------------------------------------------*/ +/*-------------------------------------------------------------- +## Links +--------------------------------------------------------------*/ +a { + color: royalblue; +} +a:visited { + color: purple; +} +a:hover, +a:focus, +a:active { + color: midnightblue; +} +a:focus { + outline: thin dotted; +} +a:hover, +a:active { + outline: 0; +} +/*-------------------------------------------------------------- +## Menus +--------------------------------------------------------------*/ +.main-navigation { + clear: both; + display: block; + float: left; + width: 100%; +} +.main-navigation ul { + display: none; + list-style: none; + margin: 0; + padding-left: 0; +} +.main-navigation ul ul { + box-shadow: 0 3px 3px rgba(0, 0, 0, 0.2); + float: left; + position: absolute; + top: 100%; + left: -999em; + z-index: 99999; +} +.main-navigation ul ul ul { + left: -999em; + top: 0; +} +.main-navigation ul ul li:hover > ul, +.main-navigation ul ul li.focus > ul { + left: 100%; +} +.main-navigation ul ul a { + width: 200px; +} +.main-navigation ul li:hover > ul, +.main-navigation ul li.focus > ul { + left: auto; +} +.main-navigation li { + float: left; + position: relative; +} +.main-navigation a { + display: block; + text-decoration: none; +} +/* Small menu. */ +.menu-toggle, +.main-navigation.toggled ul { + display: block; +} +@media screen and (min-width: 37.5em) { + .menu-toggle { + display: none; + } + .main-navigation ul { + display: block; + } +} +.site-main .comment-navigation, +.site-main .posts-navigation, +.site-main .post-navigation { + margin: 0 0 1.5em; + overflow: hidden; +} +.comment-navigation .nav-previous, +.posts-navigation .nav-previous, +.post-navigation .nav-previous { + float: left; + width: 50%; +} +.comment-navigation .nav-next, +.posts-navigation .nav-next, +.post-navigation .nav-next { + float: right; + text-align: right; + width: 50%; +} +/*-------------------------------------------------------------- +# Accessibility +--------------------------------------------------------------*/ +/* Text meant only for screen readers. */ +.screen-reader-text { + border: 0; + clip: rect(1px, 1px, 1px, 1px); + clip-path: inset(50%); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute !important; + width: 1px; + word-wrap: normal !important; + /* Many screen reader and browser combinations announce broken words as they would appear visually. */ +} +.screen-reader-text:focus { + background-color: #f1f1f1; + border-radius: 3px; + box-shadow: 0 0 2px 2px rgba(0, 0, 0, 0.6); + clip: auto !important; + clip-path: none; + color: #21759b; + display: block; + font-size: 14px; + font-size: 0.875rem; + font-weight: bold; + height: auto; + left: 5px; + line-height: normal; + padding: 15px 23px 14px; + text-decoration: none; + top: 5px; + width: auto; + z-index: 100000; + /* Above WP toolbar. */ +} +/* Do not show the outline on the skip link target. */ +#content[tabindex="-1"]:focus { + outline: 0; +} +/*-------------------------------------------------------------- +# Alignments +--------------------------------------------------------------*/ +.alignleft { + display: inline; + float: left; + margin-right: 1.5em; +} +.alignright { + display: inline; + float: right; + margin-left: 1.5em; +} +.aligncenter { + clear: both; + display: block; + margin-left: auto; + margin-right: auto; +} +/*-------------------------------------------------------------- +# Clearings +--------------------------------------------------------------*/ +.clear:before, +.clear:after, +.entry-content:before, +.entry-content:after, +.comment-content:before, +.comment-content:after, +.site-header:before, +.site-header:after, +.site-content:before, +.site-content:after, +.site-footer:before, +.site-footer:after { + content: ""; + display: table; + table-layout: fixed; +} +.clear:after, +.entry-content:after, +.comment-content:after, +.site-header:after, +.site-content:after, +.site-footer:after { + clear: both; +} +/*-------------------------------------------------------------- +# Widgets +--------------------------------------------------------------*/ +.widget { + margin: 0 0 1.5em; + /* Make sure select elements fit in widgets. */ +} +.widget select { + max-width: 100%; +} +/*-------------------------------------------------------------- +# Content +--------------------------------------------------------------*/ +/*-------------------------------------------------------------- +## Posts and pages +--------------------------------------------------------------*/ +.sticky { + display: block; +} +.updated:not(.published) { + display: none; +} +.page-links { + clear: both; + margin: 0 0 1.5em; +} +/*-------------------------------------------------------------- +## Comments +--------------------------------------------------------------*/ +.comment-content a { + word-wrap: break-word; +} +.bypostauthor { + display: block; +} +/*-------------------------------------------------------------- +# Infinite scroll +--------------------------------------------------------------*/ +/* Globally hidden elements when Infinite Scroll is supported and in use. */ +.infinite-scroll .posts-navigation, +.infinite-scroll.neverending .site-footer { + /* Theme Footer (when set to scrolling) */ + display: none; +} +/* When Infinite Scroll has reached its end we need to re-display elements that were hidden (via .neverending) before. */ +.infinity-end.neverending .site-footer { + display: block; +} +/*-------------------------------------------------------------- +# Media +--------------------------------------------------------------*/ +.page-content .wp-smiley, +.entry-content .wp-smiley, +.comment-content .wp-smiley { + border: none; + margin-bottom: 0; + margin-top: 0; + padding: 0; +} +/* Make sure embeds and iframes fit their containers. */ +embed, +iframe, +object { + max-width: 100%; +} +/* Make sure logo link wraps around logo image. */ +.custom-logo-link { + display: inline-block; +} +/*-------------------------------------------------------------- +## Captions +--------------------------------------------------------------*/ +.wp-caption { + margin-bottom: 1.5em; + max-width: 100%; +} +.wp-caption img[class*="wp-image-"] { + display: block; + margin-left: auto; + margin-right: auto; +} +.wp-caption .wp-caption-text { + margin: 0.8075em 0; +} +.wp-caption-text { + text-align: center; +} +/*-------------------------------------------------------------- +## Galleries +--------------------------------------------------------------*/ +.gallery { + margin-bottom: 1.5em; +} +.gallery-item { + display: inline-block; + text-align: center; + vertical-align: top; + width: 100%; +} +.gallery-columns-2 .gallery-item { + max-width: 50%; +} +.gallery-columns-3 .gallery-item { + max-width: 33.33%; +} +.gallery-columns-4 .gallery-item { + max-width: 25%; +} +.gallery-columns-5 .gallery-item { + max-width: 20%; +} +.gallery-columns-6 .gallery-item { + max-width: 16.66%; +} +.gallery-columns-7 .gallery-item { + max-width: 14.28%; +} +.gallery-columns-8 .gallery-item { + max-width: 12.5%; +} +.gallery-columns-9 .gallery-item { + max-width: 11.11%; +} +.gallery-caption { + display: block; +} +html, +body { + margin: 0; + background: #FAFBFB; + background: var(--body_bg); +} +.fullwidth-container.top-and-bottom-margin, +.super-large-container.top-and-bottom-margin, +.large-container.top-and-bottom-margin, +.medium-container.top-and-bottom-margin { + margin: 60px auto; +} +.fullwidth-container { + width: 100%; +} +.super-large-container { + width: 95%; + max-width: 1260px; + margin: auto; +} +.large-container { + width: 95%; + max-width: 960px; + margin: auto; +} +.medium-container { + position: relative; + width: 95%; + max-width: 660px; + margin: auto; +} +a { + color: #4B828E; + color: var(--link_color); + text-decoration: none; +} +a:visited, +a:focus { + color: #4B828E; + color: var(--link_color); +} +a:hover { + color: #39636d; + color: var(--link_hover_color); +} +.entry-content > *:not(.alignfull), +.entry-content > *:not(.alignwide) { + width: 90%; + max-width: 960px; + margin-left: auto !important; + margin-right: auto !important; +} +.entry-content .alignfull { + width: 100%; + max-width: 100%; +} +.entry-content .alignwide { + max-width: 1160px; +} +.wp-block-cover p { + margin: 0; + opacity: 1 !important; +} +.articles-list { + font-size: 0; + width: 100%; +} +.articles-list .posts-navigation { + font-size: 16px; + margin-top: 60px; +} +.articles-list .posts-navigation .nav-links .nav-previous, +.articles-list .posts-navigation .nav-links .nav-next { + width: auto; + display: inline-block; +} +.articles-list .posts-navigation .nav-links .nav-previous a, +.articles-list .posts-navigation .nav-links .nav-next a { + margin: 10px 4px; + display: inline-block; + border-radius: 30px; + font-size: 16px; + padding: 10px 20px; + background: #FFF; + background: var(--card_bg); + color: #2E3B4F; + color: var(--card_color); + box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.1); + box-shadow: var(--shadow); + transition: .2s; +} +.articles-list .posts-navigation .nav-links .nav-previous a:hover, +.articles-list .posts-navigation .nav-links .nav-next a:hover { + box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.15); + box-shadow: var(--deeper_shadow); + transition: .2s; +} +.single-article .entry-content, +.single-page .entry-content { + font-size: 18px; + line-height: 180%; + color: #2E3B4F; + color: var(--body_color); + padding-bottom: 60px; +} +.single-article .entry-content p, +.single-page .entry-content p { + opacity: .8; +} +.single-article .entry-content blockquote p, +.single-page .entry-content blockquote p { + padding-left: 20px; + border-left: 2px solid #2E3B4F; + border-left: 2px solid var(--body_color); +} +.single-article .entry-content li, +.single-page .entry-content li { + opacity: .8; +} +.single-article .related-posts { + width: 100%; + display: flex; +} +@media screen and (max-width: 376px) { + .single-article .related-posts { + display: block; + } +} +.single-article .related-posts .previous-post, +.single-article .related-posts .next-post { + display: flex; + position: relative; + height: 300px; + flex: 1; + align-items: center; + color: white !important; +} +@media screen and (max-width: 376px) { + .single-article .related-posts .previous-post, + .single-article .related-posts .next-post { + height: 250px; + } +} +.single-article .related-posts .previous-post .background, +.single-article .related-posts .next-post .background { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-size: cover; + background-position: center; +} +.single-article .related-posts .previous-post .filter, +.single-article .related-posts .next-post .filter { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: #000; + opacity: .6; +} +.single-article .related-posts .previous-post .content, +.single-article .related-posts .next-post .content { + position: relative; + padding: 40px; + box-sizing: border-box; +} +.single-article .related-posts .previous-post .content .label, +.single-article .related-posts .next-post .content .label { + text-transform: uppercase; + font-weight: 400; + opacity: .6; +} +.single-article .related-posts .previous-post .content h3, +.single-article .related-posts .next-post .content h3 { + margin: 0; + font-weight: 400; + font-size: 38px; +} +@media screen and (max-width: 376px) { + .single-article .related-posts .previous-post .content h3, + .single-article .related-posts .next-post .content h3 { + font-size: 32px; + } +} +.comments-section { + background: #FAFBFB; + background: var(--body_bg); + color: #2E3B4F; + color: var(--body_color); + padding-top: 60px; +} +.comments-section #disqus_thread { + width: 90%; + max-width: 960px; + margin: auto; +} +.comments-section .comment-reply-title { + text-align: center; +} +.comments-section .comment-form { + width: 90%; + max-width: 960px; + margin: auto; + text-align: center; + padding-bottom: 50px; +} +@media screen and (max-width: 376px) { + .comments-section .comment-form { + padding-bottom: 25px; + } +} +.comments-section .comment-form textarea { + display: block; + padding: 10px; + border-radius: 0; + background: #FFF; + background: var(--comment_form_bg); + color: #2E3B4F; + color: var(--comment_form_color); + border: 1px solid rgba(0, 0, 0, 0.4); +} +.comments-section .comment-form .submit-button { + display: none; +} +.comments-section .comment-form .comment-form-comment { + margin: 0; +} +.comments-section .comment-form .user-infos { + display: flex; +} +.comments-section .comment-form .user-infos input { + flex: 1; + border: 1px solid rgba(0, 0, 0, 0.4); + border-top: none; + border-radius: 0; + padding: 10px; + background: #FFF; + background: var(--comment_form_bg); + color: #2E3B4F; + color: var(--comment_form_color); +} +.comments-section .comment-form .user-infos input:first-of-type { + border-right: none; +} +.comments-section .comment-form .user-infos input:last-of-type { + border-left: none; +} +.comments-section .comment-form .form-submit { + width: 100%; + text-align: center; +} +.comments-section .comment-form .form-submit input { + display: inline-block; + background: #FFF; + background: var(--post_comment_btn_bg); + border: 2px solid rgba(0, 0, 0, 0); + color: #2E3B4F; + color: var(--post_comment_btn_color); + box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.1); + box-shadow: var(--shadow); + font-size: 16px; + width: 100%; + max-width: 220px; + padding: 10px 20px; + border-radius: 25px; + cursor: pointer; + margin-top: 20px; + transition: .1s; +} +.comments-section .comment-form .form-submit input:hover { + box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.15); + box-shadow: var(--deeper_shadow); + transition: .1s; +} +.comments-section .comments-list-container { + padding: 60px 10px; +} +@media screen and (max-width: 376px) { + .comments-section .comments-list-container { + padding: 30px 10px; + } +} +.comments-section .comments-list-container ol.comment-list { + padding: 0; + margin: 0; + width: 100%; + max-width: 960px; + margin: auto; + list-style: none; +} +.comments-section .comments-list-container ol.comment-list li.comment { + display: block; + background: #FFF; + background: var(--comment_bg); + color: #2E3B4F; + color: var(--comment_color); + padding: 20px; + box-sizing: border-box; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); + margin: 30px 0; +} +.comments-section .comments-list-container ol.comment-list li.comment.bypostauthor { + border-left: 4px solid #2E3B4F; + border-left: 4px solid var(--comment_color); +} +.comments-section .comments-list-container ol.comment-list li.comment .comment-header { + display: flex; + align-items: center; +} +.comments-section .comments-list-container ol.comment-list li.comment .comment-header .comment-author-profil-picture img { + border-radius: 50%; +} +.comments-section .comments-list-container ol.comment-list li.comment .comment-header .comment-meta { + padding-left: 20px; + margin-top: -5px; +} +.comments-section .comments-list-container ol.comment-list li.comment .comment-header .comment-meta .author-name { + font-size: 18px; +} +.comments-section .comments-list-container ol.comment-list li.comment .comment-header .comment-meta .posted-on { + font-size: 13px; +} +.comments-section .comments-list-container ol.comment-list ol.children { + padding: 0; + margin: 0; + margin-left: 30px; + list-style: none; +} +.comments-section .comments-list-container ol.comment-list ol.children li.comment { + margin-top: 0; +} +.opaque-featured-image-container { + width: 100%; + height: 400px; + position: absolute; + top: 0; +} +.opaque-featured-image-container .featured-image { + width: 100%; + height: 100%; + background-size: cover; + background-position: center; +} +.opaque-featured-image-container .filter { + width: 100%; + height: 400px; + position: absolute; + top: 0; + background: linear-gradient(to top, #fafbfb, rgba(250, 251, 251, 0.6)); + background: var(--opaque_header_bg); +} +.opaque-featured-image-container .filter.less-opaque { + background: linear-gradient(to top, #fafbfb, rgba(250, 251, 251, 0.4)); + background: var(--less_opaque_header_bg); +} +.opaque-featured-image-container .filter.very-opaque { + background: linear-gradient(to top, #fafbfb, rgba(250, 251, 251, 0.9)); + background: var(--very_opaque_header_bg); +} +.mwt-section-header { + width: 90% !important; + margin: auto; +} +.mwt-section-header h3 { + position: relative; + width: auto !important; + display: inline-block; + font-weight: 400; + font-size: 28px; + color: #2E3B4F; + color: var(--body_color); +} +.mwt-section-header h3::before { + content: ""; + position: absolute; + z-index: -9; + bottom: -5px; + width: 120%; + left: -10%; + height: 20px; + background: #2E3B4F; + background: var(--body_color); + opacity: .05; +} +.collections-list { + margin-left: -10px; + margin-right: -10px; +} +.collection-card-container { + display: inline-block; + width: 25%; + padding: 10px; + box-sizing: border-box; +} +@media screen and (max-width: 768px) { + .collection-card-container { + width: 33.33%; + } +} +@media screen and (max-width: 376px) { + .collection-card-container { + width: 100%; + } +} +.collection-card-container .collection-card { + position: relative; + display: block; + width: 100%; + padding-bottom: 66.66%; + border-radius: 8px; + overflow: hidden; +} +.collection-card-container .collection-card .background { + position: absolute; + width: 100%; + padding-bottom: 66.66%; + background-size: cover; + background-position: center; +} +.collection-card-container .collection-card .content { + position: absolute; + width: 100%; + bottom: 0; + padding: 10px 20px; + background: linear-gradient(to top, #000000, rgba(0, 0, 0, 0)); + color: white; + box-sizing: border-box; +} +.collection-card-container .collection-card .content h3 { + font-weight: 300; + font-size: 18px; + margin: 0; + line-height: 140%; + margin-bottom: 10px; +} +.collection-card-container .collection-card .content .collection-meta { + font-size: 13px; + opacity: .5; + margin-top: -5px; + line-height: 1em; +} +.collection-card-container .collection-card .content .collection-meta svg { + stroke: white; + vertical-align: middle; + margin-top: -3px; + margin-right: 5px; + height: 22px; + width: 22px; +} +.folders-list { + margin-left: -10px; + margin-right: -10px; +} +.folder-card-container { + display: inline-block; + width: 25%; + padding: 10px; + box-sizing: border-box; + vertical-align: top; +} +@media screen and (max-width: 768px) { + .folder-card-container { + width: 33.33%; + } +} +@media screen and (max-width: 376px) { + .folder-card-container { + width: 100%; + } +} +.folder-card-container .folder-card { + width: 100%; + box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.1); + box-shadow: var(--shadow); +} +.folder-card-container .folder-card:hover { + box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.15); + box-shadow: var(--deeper_shadow); + transition: .1s; +} +.folder-card-container .folder-card .card-header { + position: relative; + width: 100%; + padding-bottom: 66.66%; +} +.folder-card-container .folder-card .card-header a { + position: absolute; + width: 100%; + height: 100%; + display: block; + background: #222; + background-size: cover; + background-position: center; +} +.folder-card-container .folder-card .card-body { + background: #FFF; + background: var(--card_bg); + padding: 10px 20px; + height: 110px; + display: flex; + flex-direction: column; + justify-content: center; +} +.folder-card-container .folder-card .card-body h3 { + margin: 0; + font-size: 18px; + font-weight: 400; + line-height: 140%; + margin-bottom: 10px; +} +.folder-card-container .folder-card .card-body h3 a { + color: #2E3B4F; + color: var(--card_color); +} +.folder-card-container .folder-card .card-body .folder-meta { + font-size: 14px; + line-height: 1em; + opacity: .5; + margin-top: -5px; + color: #2E3B4F; + color: var(--card_color); +} +.mwt-keywords { + width: 90% !important; + margin: auto; +} +.mwt-keywords .mwt-tags-cloud { + width: 100%; + overflow: hidden; +} +.mwt-keywords .mwt-tags-cloud a { + display: inline-block; + font-size: 16px !important; + color: #4B828E; + color: var(--tag_color); + border: 1px solid #4B828E; + border: 1px solid var(--tag_color); + padding: 0px 10px; + line-height: 38px; + white-space: nowrap; + margin: 3px; +} +.mwt-keywords .mwt-tags-cloud a:hover { + color: #39636d; + color: var(--tag_hover_color); + border: 1px solid #39636d; + border: 1px solid var(--tag_hover_color); +} +.mwt-search { + position: relative; + width: 90% !important; + margin: auto; +} +.mwt-search form.search-form { + width: 100%; + position: relative; +} +.mwt-search form.search-form .mwt-search { + width: 100% !important; + border-radius: 30px; + line-height: 20px; + padding: 10px 20px; + border: none; + outline: none; + background: #f5f4f4; + background: var(--search_widget_bg); + transition: .1s; +} +.mwt-search form.search-form .mwt-search:focus { + box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.1); + box-shadow: var(--shadow); + transition: .1s; +} +.mwt-search form.search-form svg { + position: absolute; + top: 7px; + right: 15px; + stroke: #2E3B4F; + stroke: var(--footer_color); + cursor: pointer; +} +.mwt-search form.search-form .hidden-submit { + display: none; +} +@media screen and (max-width: 768px) { + .row { + display: inline; + } +} +.article-card-container { + display: inline-block; + padding: 30px 15px; + box-sizing: border-box; + font-size: 16px; +} +.article-card-container .article-card { + position: relative; + width: 100%; + background: #FFF; + background: var(--card_bg); + box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.1); + box-shadow: var(--shadow); + color: var(--card_color); + transition: .2s; +} +.article-card-container .article-card:hover { + box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.15); + box-shadow: var(--deeper_shadow); + transition: .3s; +} +.article-card-container .article-card .article-featured-image { + display: block; + background-size: cover; + background-position: center; +} +.article-card-container .article-card .article-meta .article-categories .article-category { + display: inline-block; + text-transform: uppercase; + font-size: 14px; + color: #2E3B4F; + color: var(--card_color); + opacity: .3; +} +.article-card-container .article-card .article-meta .article-title { + display: block; + font-size: 28px; + font-weight: 400; + margin-top: 0; + margin-bottom: 20px; + color: #2E3B4F; + color: var(--card_color); +} +.article-card-container .article-card .article-meta .article-excerpt { + line-height: 160%; + opacity: .6; +} +.article-card-container .article-card .article-meta .read-more-btn { + display: inline-block; + color: #2E3B4F; + color: var(--read_more_btn_color); + background: #F5F5F5; + background: var(--read_more_btn_bg); + padding: 15px 0; + width: 140px; + text-align: center; + line-height: 22px; + position: absolute; + bottom: 0; + left: 50%; + margin-left: -70px; + margin-bottom: -26px; + box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.1); + box-shadow: var(--shadow); + border-radius: 25px; + transition: .2s; +} +.article-card-container .article-card .article-meta .read-more-btn:hover { + box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.15); + box-shadow: var(--deeper_shadow); + transition: .3s; +} +.article-card-container.large { + width: 100%; +} +.article-card-container.large .article-card { + display: flex; + width: 100%; +} +.article-card-container.large .article-card .article-featured-image { + display: flex; + width: 60%; + padding-bottom: 40%; +} +.article-card-container.large .article-card .article-meta { + position: relative; + display: flex; + flex: 1; + flex-direction: column; + justify-content: center; + padding: 30px; + box-sizing: border-box; +} +@media screen and (max-width: 768px) { + .article-card-container.large { + width: 50%; + } + .article-card-container.large .article-card { + display: block; + } + .article-card-container.large .article-card .article-featured-image { + width: 100%; + padding-bottom: 66.66%; + } + .article-card-container.large .article-card .article-meta { + padding: 30px; + padding-bottom: 90px; + box-sizing: border-box; + } +} +@media screen and (max-width: 376px) { + .article-card-container.large { + width: 100%; + } +} +.article-card-container.medium { + width: 50%; + vertical-align: top; +} +.article-card-container.medium .article-card .article-featured-image { + width: 100%; + padding-bottom: 66.66%; +} +.article-card-container.medium .article-card .article-meta { + padding: 30px; + padding-bottom: 90px; + box-sizing: border-box; +} +@media screen and (max-width: 376px) { + .article-card-container.medium { + width: 100%; + } +} +.article-card-container.small { + width: 33.33%; + vertical-align: top; +} +.article-card-container.small .article-card .article-featured-image { + width: 100%; + padding-bottom: 66.66%; +} +.article-card-container.small .article-card .article-meta { + padding: 30px; + padding-bottom: 90px; + box-sizing: border-box; +} +@media screen and (max-width: 768px) { + .article-card-container.small { + width: 50%; + } +} +@media screen and (max-width: 376px) { + .article-card-container.small { + width: 100%; + } +} +.site-footer { + width: 100%; + padding: 60px 0; + background: #FFF; + background: var(--footer_bg); + color: #2E3B4F; + color: var(--footer_color); + box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.1); + box-shadow: var(--shadow); +} +.site-footer .widgets-area { + width: 90%; + max-width: 1260px; + margin: auto; + display: flex; +} +@media screen and (max-width: 768px) { + .site-footer .widgets-area { + display: block; + width: 100%; + } +} +.site-footer .widgets-area .widgets-column { + flex: 1; + padding: 0px 20px; + box-sizing: border-box; +} +.site-footer .widgets-area .widgets-column .widget-title { + font-weight: 400; + font-size: 22px; +} +.site-footer .widgets-area .widgets-column ul { + margin: 0; + padding: 0; +} +.site-footer .widgets-area .widgets-column ul li { + list-style: none; +} +.site-footer .widgets-area .widgets-column .tagcloud a { + font-size: 16px !important; + color: #4B828E; + color: var(--tag_color); + border: 1px solid #4B828E; + border: 1px solid var(--tag_color); + padding: 5px 8px; + line-height: 38px; + white-space: nowrap; +} +.site-footer .widgets-area .widgets-column .tagcloud a:hover { + color: #39636d; + color: var(--tag_hover_color); + border: 1px solid #39636d; + border: 1px solid var(--tag_hover_color); +} +.site-footer .widgets-area .widgets-column .widget_search .search-form { + position: relative; +} +.site-footer .widgets-area .widgets-column .widget_search .search-form .search-field { + width: 100%; + border-radius: 30px; + line-height: 20px; + padding: 10px 20px; + border: none; + outline: none; + color: #2E3B4F; + color: var(--search_widget_color); + background: #f5f4f4; + background: var(--search_widget_bg); + transition: .1s; +} +.site-footer .widgets-area .widgets-column .widget_search .search-form .search-field:focus { + box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.1); + box-shadow: var(--shadow); + transition: .1s; +} +.site-footer .widgets-area .widgets-column .widget_search .search-form svg { + position: absolute; + top: 7px; + right: 15px; + stroke: #2E3B4F; + stroke: var(--search_widget_color); + cursor: pointer; +} +.site-footer .widgets-area .widgets-column .widget_search .search-form .hidden-submit { + display: none; +} +.site-footer .copyright-area { + text-align: center; + font-size: 14px; + opacity: .6; +} +.scroll-back-to-top-btn { + position: fixed; + bottom: 20px; + right: 20px; + background: #FFF; + background: var(--card_bg); + border-radius: 6px; + width: 50px; + height: 50px; + box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.1); + box-shadow: var(--shadow); + transition: .1s; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + visibility: hidden; + opacity: 0; +} +.scroll-back-to-top-btn svg { + stroke: #2E3B4F; + stroke: var(--card_color); +} +.scroll-back-to-top-btn:hover { + box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.15); + box-shadow: var(--deeper_shadow); + transition: .1s; +} +.scroll-back-to-top-btn.visible { + visibility: visible; + opacity: 1; + transition: .3s; +} +.top-search-bar-container { + position: relative; + z-index: 99; + width: 100%; + height: 60px; + background: #FFF; + background: var(--top_bar_bg); + border-bottom: 1px solid rgba(0, 0, 0, 0.1); + margin-top: -60px; + transition: .2s; +} +.top-search-bar-container.opened { + margin-top: 0px; + transition: .3s; +} +.top-search-bar-container .super-large-container { + position: relative; + height: 60px; +} +.top-search-bar-container .super-large-container form input { + width: 100%; + line-height: 60px; + padding: 0; + border: none; + background: none; + outline: none; + font-size: 18px; +} +.top-search-bar-container .super-large-container .submit-top-bar-search { + position: absolute; + right: 0; + top: 50%; + height: 30px; + margin-top: -15px; + cursor: pointer; + opacity: .5; + transition: .1s; +} +.top-search-bar-container .super-large-container .submit-top-bar-search svg { + height: 30px; + width: 30px; + stroke: #2E3B4F; + stroke: var(--top_bar_color); + stroke-width: 2px; + cursor: pointer; +} +.top-search-bar-container .super-large-container .submit-top-bar-search:hover { + opacity: 1; + transition: .1s; +} +.site-header { + position: relative; + z-index: 99; + width: 100%; + background: #FFF; + background: var(--top_bar_bg); + height: 60px; + box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.1); + box-shadow: var(--shadow); +} +.site-header .top-bar-content { + display: flex; +} +.site-header .top-bar-content .site-branding { + flex: 1; + max-width: 300px; +} +.site-header .top-bar-content .site-branding .site-logo { + height: 50px; + margin-top: 5px; +} +.site-header .top-bar-content .site-branding .site-logo a, +.site-header .top-bar-content .site-branding .site-logo img { + height: 100%; + width: auto; +} +.site-header .top-bar-content .site-branding .site-title { + font-size: 18px; + line-height: 60px; + margin: 0; +} +.site-header .top-bar-content .site-branding .site-title a { + color: #2E3B4F; + color: var(--top_bar_color); +} +.site-header .top-bar-content .site-navigation { + flex: 1; + line-height: 60px; + text-align: right; +} +.site-header .top-bar-content .site-navigation .menu-main-menu-container { + display: inline-block; + vertical-align: middle; +} +@media screen and (max-width: 860px) { + .site-header .top-bar-content .site-navigation .menu-main-menu-container { + display: none; + } +} +.site-header .top-bar-content .site-navigation ul { + margin: 0; + padding: 0; +} +.site-header .top-bar-content .site-navigation ul li { + position: relative; + display: inline-block; + list-style: none; + margin-left: 10px; + font-weight: 400; +} +.site-header .top-bar-content .site-navigation ul li.current-menu-item { + font-weight: 600; +} +.site-header .top-bar-content .site-navigation ul li.current-menu-item a { + opacity: 1; +} +.site-header .top-bar-content .site-navigation ul li a { + color: #2E3B4F; + color: var(--top_bar_color); + opacity: .5; +} +.site-header .top-bar-content .site-navigation ul li:hover a { + opacity: 1; + transition: .1s; +} +.site-header .top-bar-content .site-navigation ul li:hover ul { + visibility: visible; + opacity: 1; + transition: .1s; +} +.site-header .top-bar-content .site-navigation ul li:hover ul li a { + opacity: .5; +} +.site-header .top-bar-content .site-navigation ul li ul { + visibility: hidden; + opacity: 0; + position: absolute; + z-index: 999; + background: #FFF; + background: var(--top_bar_bg); + padding: 20px; + box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.1); + box-shadow: var(--shadow); + right: 0; + margin-top: -1px; + margin-right: -20px; + transition: .1s; + text-align: left; +} +.site-header .top-bar-content .site-navigation ul li ul li { + display: block; + margin: 0; + line-height: 30px; + white-space: nowrap; +} +.site-header .top-bar-content .site-navigation ul li ul li.current-menu-item a { + opacity: 1; +} +.site-header .top-bar-content .site-navigation ul li ul li:hover a { + opacity: 1; +} +.site-header .top-bar-content .site-navigation ul li ul li ul, +.site-header .top-bar-content .site-navigation ul li ul li.current-menu-item > ul, +.site-header .top-bar-content .site-navigation ul li ul li:hover > ul { + position: relative; + padding: 10px 20px; + border-left: 1px solid rgba(0, 0, 0, 0.4); + box-shadow: none; +} +.site-header .top-bar-content .site-navigation ul li ul li ul li, +.site-header .top-bar-content .site-navigation ul li ul li.current-menu-item > ul li, +.site-header .top-bar-content .site-navigation ul li ul li:hover > ul li { + display: block; + margin: 0; + line-height: 30px; + white-space: nowrap; +} +.site-header .top-bar-content .site-navigation ul li ul li ul li a, +.site-header .top-bar-content .site-navigation ul li ul li.current-menu-item > ul li a, +.site-header .top-bar-content .site-navigation ul li ul li:hover > ul li a { + opacity: .5; +} +.site-header .top-bar-content .site-navigation ul li ul li ul li.current-menu-item a, +.site-header .top-bar-content .site-navigation ul li ul li.current-menu-item > ul li.current-menu-item a, +.site-header .top-bar-content .site-navigation ul li ul li:hover > ul li.current-menu-item a { + opacity: 1; +} +.site-header .top-bar-content .site-navigation ul li ul li ul li:hover a, +.site-header .top-bar-content .site-navigation ul li ul li.current-menu-item > ul li:hover a, +.site-header .top-bar-content .site-navigation ul li ul li:hover > ul li:hover a { + opacity: 1; +} +.site-header .top-bar-content .site-navigation ul li ul li ul li ul, +.site-header .top-bar-content .site-navigation ul li ul li.current-menu-item > ul li ul, +.site-header .top-bar-content .site-navigation ul li ul li:hover > ul li ul, +.site-header .top-bar-content .site-navigation ul li ul li ul li.current-menu-item > ul, +.site-header .top-bar-content .site-navigation ul li ul li.current-menu-item > ul li.current-menu-item > ul, +.site-header .top-bar-content .site-navigation ul li ul li:hover > ul li.current-menu-item > ul, +.site-header .top-bar-content .site-navigation ul li ul li ul li:hover > ul, +.site-header .top-bar-content .site-navigation ul li ul li.current-menu-item > ul li:hover > ul, +.site-header .top-bar-content .site-navigation ul li ul li:hover > ul li:hover > ul { + position: relative; + padding: 10px 20px; + border-left: 1px solid rgba(0, 0, 0, 0.4); +} +.site-header .top-bar-content .site-navigation ul li ul li ul li ul li, +.site-header .top-bar-content .site-navigation ul li ul li.current-menu-item > ul li ul li, +.site-header .top-bar-content .site-navigation ul li ul li:hover > ul li ul li, +.site-header .top-bar-content .site-navigation ul li ul li ul li.current-menu-item > ul li, +.site-header .top-bar-content .site-navigation ul li ul li.current-menu-item > ul li.current-menu-item > ul li, +.site-header .top-bar-content .site-navigation ul li ul li:hover > ul li.current-menu-item > ul li, +.site-header .top-bar-content .site-navigation ul li ul li ul li:hover > ul li, +.site-header .top-bar-content .site-navigation ul li ul li.current-menu-item > ul li:hover > ul li, +.site-header .top-bar-content .site-navigation ul li ul li:hover > ul li:hover > ul li { + display: block; + margin: 0; + line-height: 30px; + white-space: nowrap; +} +.site-header .top-bar-content .site-navigation ul li ul li ul li ul li a, +.site-header .top-bar-content .site-navigation ul li ul li.current-menu-item > ul li ul li a, +.site-header .top-bar-content .site-navigation ul li ul li:hover > ul li ul li a, +.site-header .top-bar-content .site-navigation ul li ul li ul li.current-menu-item > ul li a, +.site-header .top-bar-content .site-navigation ul li ul li.current-menu-item > ul li.current-menu-item > ul li a, +.site-header .top-bar-content .site-navigation ul li ul li:hover > ul li.current-menu-item > ul li a, +.site-header .top-bar-content .site-navigation ul li ul li ul li:hover > ul li a, +.site-header .top-bar-content .site-navigation ul li ul li.current-menu-item > ul li:hover > ul li a, +.site-header .top-bar-content .site-navigation ul li ul li:hover > ul li:hover > ul li a { + opacity: .5; +} +.site-header .top-bar-content .site-navigation ul li ul li ul li ul li.current-menu-item a, +.site-header .top-bar-content .site-navigation ul li ul li.current-menu-item > ul li ul li.current-menu-item a, +.site-header .top-bar-content .site-navigation ul li ul li:hover > ul li ul li.current-menu-item a, +.site-header .top-bar-content .site-navigation ul li ul li ul li.current-menu-item > ul li.current-menu-item a, +.site-header .top-bar-content .site-navigation ul li ul li.current-menu-item > ul li.current-menu-item > ul li.current-menu-item a, +.site-header .top-bar-content .site-navigation ul li ul li:hover > ul li.current-menu-item > ul li.current-menu-item a, +.site-header .top-bar-content .site-navigation ul li ul li ul li:hover > ul li.current-menu-item a, +.site-header .top-bar-content .site-navigation ul li ul li.current-menu-item > ul li:hover > ul li.current-menu-item a, +.site-header .top-bar-content .site-navigation ul li ul li:hover > ul li:hover > ul li.current-menu-item a { + opacity: 1; +} +.site-header .top-bar-content .site-navigation ul li ul li ul li ul li:hover a, +.site-header .top-bar-content .site-navigation ul li ul li.current-menu-item > ul li ul li:hover a, +.site-header .top-bar-content .site-navigation ul li ul li:hover > ul li ul li:hover a, +.site-header .top-bar-content .site-navigation ul li ul li ul li.current-menu-item > ul li:hover a, +.site-header .top-bar-content .site-navigation ul li ul li.current-menu-item > ul li.current-menu-item > ul li:hover a, +.site-header .top-bar-content .site-navigation ul li ul li:hover > ul li.current-menu-item > ul li:hover a, +.site-header .top-bar-content .site-navigation ul li ul li ul li:hover > ul li:hover a, +.site-header .top-bar-content .site-navigation ul li ul li.current-menu-item > ul li:hover > ul li:hover a, +.site-header .top-bar-content .site-navigation ul li ul li:hover > ul li:hover > ul li:hover a { + opacity: 1; +} +.site-header .top-bar-content .site-navigation ul li ul::after { + content: ""; + position: absolute; + top: -2px; + left: 0; + width: 100%; + height: 5px; + background: #FFF; + background: var(--top_bar_bg); +} +.site-header .top-bar-content .site-navigation .open-top-bar-search, +.site-header .top-bar-content .site-navigation .close-top-bar-search { + display: inline-block; + margin-left: 20px; + vertical-align: middle; + line-height: 60px; + cursor: pointer; + opacity: .5; + transition: .1s; +} +.site-header .top-bar-content .site-navigation .open-top-bar-search:hover, +.site-header .top-bar-content .site-navigation .close-top-bar-search:hover { + opacity: 1; + transition: .1s; +} +.site-header .top-bar-content .site-navigation .open-top-bar-search svg, +.site-header .top-bar-content .site-navigation .close-top-bar-search svg { + display: inline-block; + height: 16px; + width: 16px; + line-height: 60px; + stroke: #2E3B4F; + stroke: var(--top_bar_color); + stroke-width: 2px; +} +.site-header .top-bar-content .site-navigation .open-top-bar-search.active, +.site-header .top-bar-content .site-navigation .close-top-bar-search.active { + opacity: 1; +} +.site-header .top-bar-content .site-navigation .open-top-bar-search.active svg, +.site-header .top-bar-content .site-navigation .close-top-bar-search.active svg { + stroke-width: 3px; +} +.mobile-navigation { + position: relative; + z-index: 9; + display: none; + width: 100%; + box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.1); + box-shadow: var(--shadow); + background: #FFF; + background: var(--top_bar_bg); + text-align: center; +} +@media screen and (max-width: 860px) { + .mobile-navigation { + display: block; + } +} +.mobile-navigation .site-navigation { + display: inline-block; + padding: 30px 0; + margin: auto; + text-align: left; +} +.mobile-navigation .site-navigation ul { + margin: 0; + padding: 0; + list-style: none; +} +.mobile-navigation .site-navigation ul li { + line-height: 200%; +} +.mobile-navigation .site-navigation ul li a { + color: #2E3B4F; + color: var(--top_bar_color); +} +.mobile-navigation .site-navigation ul li ul { + padding-left: 30px; + border-left: 1px dashed #e6e6e6; +} +.mobile-navigation .mobile-navigation-toggle { + position: absolute; + height: 40px; + width: 60px; + background: #FFF; + background: var(--top_bar_bg); + color: #2E3B4F; + color: var(--top_bar_color); + bottom: -40px; + left: 50%; + margin-left: -30px; + line-height: 40px; + box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.1); + box-shadow: var(--shadow); + text-align: center; + border-radius: 0 0 8px 8px; + cursor: pointer; +} +.mobile-navigation .mobile-navigation-toggle .open-icon, +.mobile-navigation .mobile-navigation-toggle .close-icon { + margin-top: 5px; +} +.mobile-navigation .mobile-navigation-toggle .open-icon svg, +.mobile-navigation .mobile-navigation-toggle .close-icon svg { + stroke: #2E3B4F; + stroke: var(--top_bar_color); +} +.mobile-navigation .mobile-navigation-toggle .close-icon { + display: none; +} +.mobile-navigation .mobile-navigation-toggle.active .close-icon { + display: block; +} +.mobile-navigation .mobile-navigation-toggle.active .open-icon { + display: none; +} +.article-header { + text-align: center; + margin: 120px auto; + color: #2E3B4F; + color: var(--body_color); +} +@media screen and (max-width: 320px) { + .article-header { + margin: 70px auto; + } +} +.article-header .article-categories { + margin-bottom: 10px; +} +.article-header .article-categories .article-category { + display: inline-block; + text-transform: uppercase; + font-size: 14px; + opacity: .3; + color: #2E3B4F; + color: var(--body_color); + transition: .1s; +} +.article-header .article-categories .article-category:hover { + opacity: .6; + transition: .1s; +} +.article-header .article-title { + font-size: 48px; + line-height: 160%; + font-weight: 400; + margin-top: 0; + margin-bottom: 20px; +} +@media screen and (max-width: 320px) { + .article-header .article-title { + font-size: 42px; + line-height: 140%; + } +} +.article-header .article-meta { + opacity: 1; + color: #2E3B4F; + color: var(--body_color); +} +.article-header .article-meta .author-picture { + display: inline-block; + width: 40px; + height: 40px; + border-radius: 50%; + background-size: cover; + background-position: center; + vertical-align: middle; + margin-right: 5px; +} +.single-article .article-featured-image { + text-align: center; + margin-bottom: 60px; +} +.single-article .article-featured-image img { + max-width: 100%; +} +.page-header { + text-align: center; + margin: 120px auto; + color: #2E3B4F; + color: var(--body_color); +} +@media screen and (max-width: 320px) { + .page-header { + margin: 70px auto; + } +} +.page-header .label { + text-transform: uppercase; + font-size: 14px; + opacity: .3; + color: #2E3B4F; + color: var(--body_color); +} +.page-header .meow-breadcrumb .breadcrumb-items-container .breadcrumb-item { + text-transform: uppercase; + font-size: 14px; + opacity: .3; + color: #2E3B4F; + color: var(--body_color); + transition: .1s; +} +.page-header .meow-breadcrumb .breadcrumb-items-container .breadcrumb-item:hover { + opacity: .6; + transition: .1s; +} +.page-header .meow-breadcrumb .breadcrumb-items-container .breadcrumb-item.active { + opacity: 1; +} +.page-header .meow-breadcrumb .breadcrumb-items-container .divider { + opacity: .3; + margin: 0 5px; +} +.page-header .page-title { + font-size: 48px; + line-height: 160%; + font-weight: 400; + margin-top: 0; + margin-bottom: 20px; +} +@media screen and (max-width: 320px) { + .page-header .page-title { + font-size: 42px; + line-height: 140%; + } +} +.page-featured-image { + text-align: center; + margin-bottom: 60px; +} +.page-featured-image img { + max-width: 100%; +} diff --git a/tag.php b/tag.php new file mode 100644 index 0000000..a93a1ea --- /dev/null +++ b/tag.php @@ -0,0 +1,83 @@ + + +
    +
    + +
    + +
    + +
    + '; + require get_template_directory() . '/components/article-cards/large-article-card.php'; + echo '
    '; + $count++; + break; + case 1: + echo '
    '; + require get_template_directory() . '/components/article-cards/medium-article-card.php'; + $count++; + break; + case 2: + require get_template_directory() . '/components/article-cards/medium-article-card.php'; + echo '
    '; + $count++; + break; + case 3: + echo '
    '; + require get_template_directory() . '/components/article-cards/small-article-card.php'; + $count++; + break; + case 4: + require get_template_directory() . '/components/article-cards/small-article-card.php'; + $count++; + break; + case 5: + require get_template_directory() . '/components/article-cards/small-article-card.php'; + echo '
    '; + $count = 0; + break; + } + + + endwhile; + + the_posts_navigation(); + + else : + + _e('No posts found!', 'yuzu'); + + endif; + ?> +
    + + +
    + +term_id; +$current_term = get_term($term_id); +?> + + 'attachment', + 'post_mime_type' =>'image', + 'post_status' => 'inherit', + 'posts_per_page' => -1, + 'tax_query' => array( + array( + 'taxonomy' => 'attachment_keyword', + 'field' => 'slug', + 'terms' => $current_term->slug, + ), + ), +); +$query_images = new WP_Query( $query_images_args ); + +while ( $query_images->have_posts() ) : $query_images->the_post(); + $ids_array[] = $post->ID; +endwhile; +$ids = implode(',', $ids_array); + +?> + +
    +
    + +
    + + +
    + +
    +
    + +
    +
    + +term_id; +$current_term = get_term($term_id); +?> + +
    +
    + + get_folder_thumbnail( $term_id ); + if($featured_image_id) { + $featured_image = wp_get_attachment_image_src($featured_image_id, 'kantan-hero-image')[0]; + require get_template_directory() . '/components/opaque-featured-image.php'; + } + ?> + +
    + + + + get_collections($term_id); + if( count( $collections ) != 0 ) { + ?> +
    +
    +
    +

    Collections

    +
    +
    + +
    +
    + get_folders($term_id); + if( count( $folders ) != 0 ) { + ?> +
    +
    +
    +

    Folders

    +
    +
    + +
    +
    + +
    + + + +
    +
    + + 'http://easydigitaldownloads.com', + 'theme_slug' => get_template(), + 'item_name' => '', + 'license' => '', + 'version' => '', + 'author' => '', + 'download_id' => '', + 'renew_url' => '', + 'beta' => false, + ) ); + + /** + * Fires after the theme $config is setup. + * + * @since x.x.x + * + * @param array $config Array of EDD SL theme data. + */ + do_action( 'post_edd_sl_theme_updater_setup', $config ); + + // Set config arguments + $this->remote_api_url = $config['remote_api_url']; + $this->item_name = $config['item_name']; + $this->theme_slug = sanitize_key( $config['theme_slug'] ); + $this->version = $config['version']; + $this->author = $config['author']; + $this->download_id = $config['download_id']; + $this->renew_url = $config['renew_url']; + $this->beta = $config['beta']; + + // Populate version fallback + if ( '' == $config['version'] ) { + $theme = wp_get_theme( $this->theme_slug ); + $this->version = $theme->get( 'Version' ); + } + + // Strings passed in from the updater config + $this->strings = $strings; + + add_action( 'init', array( $this, 'updater' ) ); + add_action( 'admin_init', array( $this, 'register_option' ) ); + add_action( 'admin_init', array( $this, 'license_action' ) ); + add_action( 'admin_menu', array( $this, 'license_menu' ) ); + add_action( 'update_option_' . $this->theme_slug . '_license_key', array( $this, 'activate_license' ), 10, 2 ); + add_filter( 'http_request_args', array( $this, 'disable_wporg_request' ), 5, 2 ); + + } + + /** + * Creates the updater class. + * + * since 1.0.0 + */ + function updater() { + if ( ! current_user_can( 'manage_options' ) ) { + return; + } + + /* If there is no valid license key status, don't allow updates. */ + if ( get_option( $this->theme_slug . '_license_key_status', false) != 'valid' ) { + return; + } + + if ( !class_exists( 'EDD_Theme_Updater' ) ) { + // Load our custom theme updater + include( dirname( __FILE__ ) . '/theme-updater-class.php' ); + } + + new EDD_Theme_Updater( + array( + 'remote_api_url' => $this->remote_api_url, + 'version' => $this->version, + 'license' => trim( get_option( $this->theme_slug . '_license_key' ) ), + 'item_name' => $this->item_name, + 'author' => $this->author, + 'beta' => $this->beta + ), + $this->strings + ); + } + + /** + * Adds a menu item for the theme license under the appearance menu. + * + * since 1.0.0 + */ + function license_menu() { + + $strings = $this->strings; + + add_theme_page( + $strings['theme-license'], + $strings['theme-license'], + 'manage_options', + $this->theme_slug . '-license', + array( $this, 'license_page' ) + ); + } + + /** + * Outputs the markup used on the theme license page. + * + * since 1.0.0 + */ + function license_page() { + + $strings = $this->strings; + + $license = trim( get_option( $this->theme_slug . '_license_key' ) ); + $status = get_option( $this->theme_slug . '_license_key_status', false ); + + // Checks license status to display under license key + if ( ! $license ) { + $message = $strings['enter-key']; + } else { + // delete_transient( $this->theme_slug . '_license_message' ); + if ( ! get_transient( $this->theme_slug . '_license_message', false ) ) { + set_transient( $this->theme_slug . '_license_message', $this->check_license(), ( 60 * 60 * 24 ) ); + } + $message = get_transient( $this->theme_slug . '_license_message' ); + } + ?> +
    +

    +
    + + theme_slug . '-license' ); ?> + +
    +
    ', + esc_html__( 'Upgrade message from the plugin author:', 'tgmpa' ), + ' ', wp_kses_data( $item['upgrade_notice'] ), ' +
    +
    + + + + + + + + + + + + + + + +
    + + + +

    + +

    +
    + + + theme_slug . '_nonce', $this->theme_slug . '_nonce' ); + if ( 'valid' == $status ) { ?> + + + + +
    + + + theme_slug . '-license', + $this->theme_slug . '_license_key', + array( $this, 'sanitize_license' ) + ); + } + + /** + * Sanitizes the license key. + * + * since 1.0.0 + * + * @param string $new License key that was submitted. + * @return string $new Sanitized license key. + */ + function sanitize_license( $new ) { + + $old = get_option( $this->theme_slug . '_license_key' ); + + if ( $old && $old != $new ) { + // New license has been entered, so must reactivate + delete_option( $this->theme_slug . '_license_key_status' ); + delete_transient( $this->theme_slug . '_license_message' ); + } + + return $new; + } + + /** + * Makes a call to the API. + * + * @since 1.0.0 + * + * @param array $api_params to be used for wp_remote_get. + * @return array $response decoded JSON response. + */ + function get_api_response( $api_params ) { + + // Call the custom API. + $verify_ssl = (bool) apply_filters( 'edd_sl_api_request_verify_ssl', true ); + $response = wp_remote_post( $this->remote_api_url, array( 'timeout' => 15, 'sslverify' => $verify_ssl, 'body' => $api_params ) ); + + return $response; + } + + /** + * Activates the license key. + * + * @since 1.0.0 + */ + function activate_license() { + + $license = trim( get_option( $this->theme_slug . '_license_key' ) ); + + // Data to send in our API request. + $api_params = array( + 'edd_action' => 'activate_license', + 'license' => $license, + 'item_name' => urlencode( $this->item_name ), + 'url' => home_url() + ); + + $response = $this->get_api_response( $api_params ); + + // make sure the response came back okay + if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) { + + if ( is_wp_error( $response ) ) { + $message = $response->get_error_message(); + } else { + $message = __( 'An error occurred, please try again.' ); + } + + $base_url = admin_url( 'themes.php?page=' . $this->theme_slug . '-license' ); + $redirect = add_query_arg( array( 'sl_theme_activation' => 'false', 'message' => urlencode( $message ) ), $base_url ); + + wp_redirect( $redirect ); + exit(); + + } else { + + $license_data = json_decode( wp_remote_retrieve_body( $response ) ); + + if ( false === $license_data->success ) { + + switch( $license_data->error ) { + + case 'expired' : + + $message = sprintf( + __( 'Your license key expired on %s.' ), + date_i18n( get_option( 'date_format' ), strtotime( $license_data->expires, current_time( 'timestamp' ) ) ) + ); + break; + + case 'disabled': + case 'revoked' : + + $message = __( 'Your license key has been disabled.' ); + break; + + case 'missing' : + + $message = __( 'Invalid license.' ); + break; + + case 'invalid' : + case 'site_inactive' : + + $message = __( 'Your license is not active for this URL.' ); + break; + + case 'item_name_mismatch' : + + $message = sprintf( __( 'This appears to be an invalid license key for %s.' ), $this->item_name ); + break; + + case 'no_activations_left': + + $message = __( 'Your license key has reached its activation limit.' ); + break; + + default : + + $message = __( 'An error occurred, please try again.' ); + break; + } + + if ( ! empty( $message ) ) { + $base_url = admin_url( 'themes.php?page=' . $this->theme_slug . '-license' ); + $redirect = add_query_arg( array( 'sl_theme_activation' => 'false', 'message' => urlencode( $message ) ), $base_url ); + + wp_redirect( $redirect ); + exit(); + } + + } + + } + + // $response->license will be either "active" or "inactive" + if ( $license_data && isset( $license_data->license ) ) { + update_option( $this->theme_slug . '_license_key_status', $license_data->license ); + delete_transient( $this->theme_slug . '_license_message' ); + } + + wp_redirect( admin_url( 'themes.php?page=' . $this->theme_slug . '-license' ) ); + exit(); + + } + + /** + * Deactivates the license key. + * + * @since 1.0.0 + */ + function deactivate_license() { + + // Retrieve the license from the database. + $license = trim( get_option( $this->theme_slug . '_license_key' ) ); + + // Data to send in our API request. + $api_params = array( + 'edd_action' => 'deactivate_license', + 'license' => $license, + 'item_name' => urlencode( $this->item_name ), + 'url' => home_url() + ); + + $response = $this->get_api_response( $api_params ); + + // make sure the response came back okay + if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) { + + if ( is_wp_error( $response ) ) { + $message = $response->get_error_message(); + } else { + $message = __( 'An error occurred, please try again.' ); + } + + $base_url = admin_url( 'themes.php?page=' . $this->theme_slug . '-license' ); + $redirect = add_query_arg( array( 'sl_theme_activation' => 'false', 'message' => urlencode( $message ) ), $base_url ); + + wp_redirect( $redirect ); + exit(); + + } else { + + $license_data = json_decode( wp_remote_retrieve_body( $response ) ); + + // $license_data->license will be either "deactivated" or "failed" + if ( $license_data && ( $license_data->license == 'deactivated' ) ) { + delete_option( $this->theme_slug . '_license_key_status' ); + delete_transient( $this->theme_slug . '_license_message' ); + } + + } + + if ( ! empty( $message ) ) { + $base_url = admin_url( 'themes.php?page=' . $this->theme_slug . '-license' ); + $redirect = add_query_arg( array( 'sl_theme_activation' => 'false', 'message' => urlencode( $message ) ), $base_url ); + + wp_redirect( $redirect ); + exit(); + } + + wp_redirect( admin_url( 'themes.php?page=' . $this->theme_slug . '-license' ) ); + exit(); + + } + + /** + * Constructs a renewal link + * + * @since 1.0.0 + */ + function get_renewal_link() { + + // If a renewal link was passed in the config, use that + if ( '' != $this->renew_url ) { + return $this->renew_url; + } + + // If download_id was passed in the config, a renewal link can be constructed + $license_key = trim( get_option( $this->theme_slug . '_license_key', false ) ); + if ( '' != $this->download_id && $license_key ) { + $url = esc_url( $this->remote_api_url ); + $url .= '/checkout/?edd_license_key=' . $license_key . '&download_id=' . $this->download_id; + return $url; + } + + // Otherwise return the remote_api_url + return $this->remote_api_url; + + } + + + + /** + * Checks if a license action was submitted. + * + * @since 1.0.0 + */ + function license_action() { + + if ( isset( $_POST[ $this->theme_slug . '_license_activate' ] ) ) { + if ( check_admin_referer( $this->theme_slug . '_nonce', $this->theme_slug . '_nonce' ) ) { + $this->activate_license(); + } + } + + if ( isset( $_POST[$this->theme_slug . '_license_deactivate'] ) ) { + if ( check_admin_referer( $this->theme_slug . '_nonce', $this->theme_slug . '_nonce' ) ) { + $this->deactivate_license(); + } + } + + } + + /** + * Checks if license is valid and gets expire date. + * + * @since 1.0.0 + * + * @return string $message License status message. + */ + function check_license() { + + $license = trim( get_option( $this->theme_slug . '_license_key' ) ); + $strings = $this->strings; + + $api_params = array( + 'edd_action' => 'check_license', + 'license' => $license, + 'item_name' => urlencode( $this->item_name ), + 'url' => home_url() + ); + + $response = $this->get_api_response( $api_params ); + + // make sure the response came back okay + if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) { + + if ( is_wp_error( $response ) ) { + $message = $response->get_error_message(); + } else { + $message = $strings['license-status-unknown']; + } + + $base_url = admin_url( 'themes.php?page=' . $this->theme_slug . '-license' ); + $redirect = add_query_arg( array( 'sl_theme_activation' => 'false', 'message' => urlencode( $message ) ), $base_url ); + + wp_redirect( $redirect ); + exit(); + + } else { + + $license_data = json_decode( wp_remote_retrieve_body( $response ) ); + + // If response doesn't include license data, return + if ( !isset( $license_data->license ) ) { + $message = $strings['license-status-unknown']; + return $message; + } + + // We need to update the license status at the same time the message is updated + if ( $license_data && isset( $license_data->license ) ) { + update_option( $this->theme_slug . '_license_key_status', $license_data->license ); + } + + // Get expire date + $expires = false; + if ( isset( $license_data->expires ) && 'lifetime' != $license_data->expires ) { + $expires = date_i18n( get_option( 'date_format' ), strtotime( $license_data->expires, current_time( 'timestamp' ) ) ); + $renew_link = '' . $strings['renew'] . ''; + } elseif ( isset( $license_data->expires ) && 'lifetime' == $license_data->expires ) { + $expires = 'lifetime'; + } + + // Get site counts + $site_count = $license_data->site_count; + $license_limit = $license_data->license_limit; + + // If unlimited + if ( 0 == $license_limit ) { + $license_limit = $strings['unlimited']; + } + + if ( $license_data->license == 'valid' ) { + $message = $strings['license-key-is-active'] . ' '; + if ( isset( $expires ) && 'lifetime' != $expires ) { + $message .= sprintf( $strings['expires%s'], $expires ) . ' '; + } + if ( isset( $expires ) && 'lifetime' == $expires ) { + $message .= $strings['expires-never']; + } + if ( $site_count && $license_limit ) { + $message .= sprintf( $strings['%1$s/%2$-sites'], $site_count, $license_limit ); + } + } else if ( $license_data->license == 'expired' ) { + if ( $expires ) { + $message = sprintf( $strings['license-key-expired-%s'], $expires ); + } else { + $message = $strings['license-key-expired']; + } + if ( $renew_link ) { + $message .= ' ' . $renew_link; + } + } else if ( $license_data->license == 'invalid' ) { + $message = $strings['license-keys-do-not-match']; + } else if ( $license_data->license == 'inactive' ) { + $message = $strings['license-is-inactive']; + } else if ( $license_data->license == 'disabled' ) { + $message = $strings['license-key-is-disabled']; + } else if ( $license_data->license == 'site_inactive' ) { + // Site is inactive + $message = $strings['site-is-inactive']; + } else { + $message = $strings['license-status-unknown']; + } + + } + + return $message; + } + + /** + * Disable requests to wp.org repository for this theme. + * + * @since 1.0.0 + */ + function disable_wporg_request( $r, $url ) { + + // If it's not a theme update request, bail. + if ( 0 !== strpos( $url, 'https://api.wordpress.org/themes/update-check/1.1/' ) ) { + return $r; + } + + // Decode the JSON response + $themes = json_decode( $r['body']['themes'] ); + + // Remove the active parent and child themes from the check + $parent = get_option( 'template' ); + $child = get_option( 'stylesheet' ); + unset( $themes->themes->$parent ); + unset( $themes->themes->$child ); + + // Encode the updated JSON response + $r['body']['themes'] = json_encode( $themes ); + + return $r; + } + +} + +/** + * This is a means of catching errors from the activation method above and displyaing it to the customer + */ +function edd_sample_theme_admin_notices() { + if ( isset( $_GET['sl_theme_activation'] ) && ! empty( $_GET['message'] ) ) { + + switch( $_GET['sl_theme_activation'] ) { + + case 'false': + $message = urldecode( $_GET['message'] ); + ?> +
    +

    +
    + 'http://easydigitaldownloads.com', + 'request_data' => array(), + 'theme_slug' => get_template(), // use get_stylesheet() for child theme updates + 'item_name' => '', + 'license' => '', + 'version' => '', + 'author' => '', + 'beta' => false, + ); + + $args = wp_parse_args( $args, $defaults ); + + $this->license = $args['license']; + $this->item_name = $args['item_name']; + $this->version = $args['version']; + $this->theme_slug = sanitize_key( $args['theme_slug'] ); + $this->author = $args['author']; + $this->beta = $args['beta']; + $this->remote_api_url = $args['remote_api_url']; + $this->response_key = $this->theme_slug . '-' . $this->beta . '-update-response'; + $this->strings = $strings; + + add_filter( 'site_transient_update_themes', array( $this, 'theme_update_transient' ) ); + add_filter( 'delete_site_transient_update_themes', array( $this, 'delete_theme_update_transient' ) ); + add_action( 'load-update-core.php', array( $this, 'delete_theme_update_transient' ) ); + add_action( 'load-themes.php', array( $this, 'delete_theme_update_transient' ) ); + add_action( 'load-themes.php', array( $this, 'load_themes_screen' ) ); + } + + /** + * Show the update notification when neecessary + * + * @return void + */ + function load_themes_screen() { + add_thickbox(); + add_action( 'admin_notices', array( $this, 'update_nag' ) ); + } + + /** + * Display the update notifications + * + * @return void + */ + function update_nag() { + + $strings = $this->strings; + $theme = wp_get_theme( $this->theme_slug ); + $api_response = get_transient( $this->response_key ); + + if ( false === $api_response ) { + return; + } + + $update_url = wp_nonce_url( 'update.php?action=upgrade-theme&theme=' . urlencode( $this->theme_slug ), 'upgrade-theme_' . $this->theme_slug ); + $update_onclick = ' onclick="if ( confirm(\'' . esc_js( $strings['update-notice'] ) . '\') ) {return true;}return false;"'; + + if ( version_compare( $this->version, $api_response->new_version, '<' ) ) { + + echo '
    '; + printf( + $strings['update-available'], + $theme->get( 'Name' ), + $api_response->new_version, + '#TB_inline?width=640&inlineId=' . $this->theme_slug . '_changelog', + $theme->get( 'Name' ), + $update_url, + $update_onclick + ); + echo '
    '; + echo ''; + } + } + + /** + * Update the theme update transient with the response from the version check + * + * @param array $value The default update values. + * @return array|boolean If an update is available, returns the update parameters, if no update is needed returns false, if + * the request fails returns false. + */ + function theme_update_transient( $value ) { + $update_data = $this->check_for_update(); + if ( $update_data ) { + + // Make sure the theme property is set. See issue 1463 on Github in the Software Licensing Repo. + $update_data['theme'] = $this->theme_slug; + + $value->response[ $this->theme_slug ] = $update_data; + } + return $value; + } + + /** + * Remove the update data for the theme + * + * @return void + */ + function delete_theme_update_transient() { + delete_transient( $this->response_key ); + } + + /** + * Call the EDD SL API (using the URL in the construct) to get the latest version information + * + * @return array|boolean If an update is available, returns the update parameters, if no update is needed returns false, if + * the request fails returns false. + */ + function check_for_update() { + + $update_data = get_transient( $this->response_key ); + + if ( false === $update_data ) { + $failed = false; + + $api_params = array( + 'edd_action' => 'get_version', + 'license' => $this->license, + 'name' => $this->item_name, + 'slug' => $this->theme_slug, + 'version' => $this->version, + 'author' => $this->author, + 'beta' => $this->beta + ); + + $response = wp_remote_post( $this->remote_api_url, array( 'timeout' => 15, 'body' => $api_params ) ); + + // Make sure the response was successful + if ( is_wp_error( $response ) || 200 != wp_remote_retrieve_response_code( $response ) ) { + $failed = true; + } + + $update_data = json_decode( wp_remote_retrieve_body( $response ) ); + + if ( ! is_object( $update_data ) ) { + $failed = true; + } + + // If the response failed, try again in 30 minutes + if ( $failed ) { + $data = new stdClass; + $data->new_version = $this->version; + set_transient( $this->response_key, $data, strtotime( '+30 minutes', time() ) ); + return false; + } + + // If the status is 'ok', return the update arguments + if ( ! $failed ) { + $update_data->sections = maybe_unserialize( $update_data->sections ); + set_transient( $this->response_key, $update_data, strtotime( '+12 hours', time() ) ); + } + } + + if ( version_compare( $this->version, $update_data->new_version, '>=' ) ) { + return false; + } + + return (array) $update_data; + } + +} diff --git a/updater/yuzu-updater.php b/updater/yuzu-updater.php new file mode 100644 index 0000000..22b4f19 --- /dev/null +++ b/updater/yuzu-updater.php @@ -0,0 +1,49 @@ + 'https://store.meowapps.com', // Site where EDD is hosted + 'item_name' => 'Yuzu Theme', // Name of theme + 'theme_slug' => 'yuzu-theme', // Theme slug + 'version' => $meowapps_theme_version, // The current version of this theme + 'author' => 'Meow Apps', // The author of this theme + 'download_id' => '', // Optional, used for generating a license renewal link + 'renew_url' => '', // Optional, allows for a custom license renewal link + 'beta' => false, // Optional, set to true to opt into beta versions + ), + + // Strings + $strings = array( + 'theme-license' => __( 'Theme License', 'edd-theme-updater' ), + 'enter-key' => __( 'Enter your theme license key.', 'edd-theme-updater' ), + 'license-key' => __( 'License Key', 'edd-theme-updater' ), + 'license-action' => __( 'License Action', 'edd-theme-updater' ), + 'deactivate-license' => __( 'Deactivate License', 'edd-theme-updater' ), + 'activate-license' => __( 'Activate License', 'edd-theme-updater' ), + 'status-unknown' => __( 'License status is unknown.', 'edd-theme-updater' ), + 'renew' => __( 'Renew?', 'edd-theme-updater' ), + 'unlimited' => __( 'unlimited', 'edd-theme-updater' ), + 'license-key-is-active' => __( 'License key is active.', 'edd-theme-updater' ), + 'expires%s' => __( 'Expires %s.', 'edd-theme-updater' ), + 'expires-never' => __( 'Lifetime License.', 'edd-theme-updater' ), + '%1$s/%2$-sites' => __( 'You have %1$s / %2$s sites activated.', 'edd-theme-updater' ), + 'license-key-expired-%s' => __( 'License key expired %s.', 'edd-theme-updater' ), + 'license-key-expired' => __( 'License key has expired.', 'edd-theme-updater' ), + 'license-keys-do-not-match' => __( 'License keys do not match.', 'edd-theme-updater' ), + 'license-is-inactive' => __( 'License is inactive.', 'edd-theme-updater' ), + 'license-key-is-disabled' => __( 'License key is disabled.', 'edd-theme-updater' ), + 'site-is-inactive' => __( 'Site is inactive.', 'edd-theme-updater' ), + 'license-status-unknown' => __( 'License status is unknown.', 'edd-theme-updater' ), + 'update-notice' => __( "Updating this theme will lose any customizations you have made. 'Cancel' to stop, 'OK' to update.", 'edd-theme-updater' ), + 'update-available' => __('%1$s %2$s is available. Check out what\'s new or update now.', 'edd-theme-updater' ), + ) + +);