From 16bf7c905f45468c017e9bdfbee434193f8b1b60 Mon Sep 17 00:00:00 2001 From: agata <automa@insicuri.net> Date: Fri, 12 Jul 2019 16:19:10 +0200 Subject: [PATCH] added https://it.wordpress.org/plugins/multisite-enhancements --- .../plugins/multisite-enhancements/LICENSE | 339 ++++++++++++++ .../css/wordpress-multisite-enhancements.css | 11 + .../wordpress-multisite-enhancements.min.css | 1 + .../inc/assets/js/filtering-plugins.js | 22 + .../inc/assets/js/filtering-plugins.min.js | 1 + .../inc/assets/js/filtering-themes.js | 23 + .../inc/assets/js/filtering-themes.min.js | 1 + .../inc/autoload/class-add-admin-favicon.php | 279 ++++++++++++ .../inc/autoload/class-add-blog-id.php | 110 +++++ .../inc/autoload/class-add-css.php | 62 +++ .../inc/autoload/class-add-plugin-list.php | 377 ++++++++++++++++ .../autoload/class-add-site-status-labels.php | 116 +++++ .../inc/autoload/class-add-ssl-identifier.php | 112 +++++ .../inc/autoload/class-add-theme-list.php | 417 ++++++++++++++++++ .../inc/autoload/class-admin-bar-tweaks.php | 141 ++++++ .../inc/autoload/class-change-footer-text.php | 141 ++++++ .../inc/autoload/class-core.php | 155 +++++++ .../inc/autoload/class-filtering-plugins.php | 51 +++ .../inc/autoload/class-filtering-themes.php | 51 +++ .../class-multisite-add-new-plugin.php | 58 +++ .../inc/autoload/core.php | 45 ++ .../multisite-enhancements.php | 161 +++++++ .../plugins/multisite-enhancements/readme.txt | 213 +++++++++ 23 files changed, 2887 insertions(+) create mode 100644 wp-content/plugins/multisite-enhancements/LICENSE create mode 100644 wp-content/plugins/multisite-enhancements/inc/assets/css/wordpress-multisite-enhancements.css create mode 100644 wp-content/plugins/multisite-enhancements/inc/assets/css/wordpress-multisite-enhancements.min.css create mode 100644 wp-content/plugins/multisite-enhancements/inc/assets/js/filtering-plugins.js create mode 100644 wp-content/plugins/multisite-enhancements/inc/assets/js/filtering-plugins.min.js create mode 100644 wp-content/plugins/multisite-enhancements/inc/assets/js/filtering-themes.js create mode 100644 wp-content/plugins/multisite-enhancements/inc/assets/js/filtering-themes.min.js create mode 100755 wp-content/plugins/multisite-enhancements/inc/autoload/class-add-admin-favicon.php create mode 100755 wp-content/plugins/multisite-enhancements/inc/autoload/class-add-blog-id.php create mode 100644 wp-content/plugins/multisite-enhancements/inc/autoload/class-add-css.php create mode 100755 wp-content/plugins/multisite-enhancements/inc/autoload/class-add-plugin-list.php create mode 100644 wp-content/plugins/multisite-enhancements/inc/autoload/class-add-site-status-labels.php create mode 100644 wp-content/plugins/multisite-enhancements/inc/autoload/class-add-ssl-identifier.php create mode 100755 wp-content/plugins/multisite-enhancements/inc/autoload/class-add-theme-list.php create mode 100755 wp-content/plugins/multisite-enhancements/inc/autoload/class-admin-bar-tweaks.php create mode 100755 wp-content/plugins/multisite-enhancements/inc/autoload/class-change-footer-text.php create mode 100755 wp-content/plugins/multisite-enhancements/inc/autoload/class-core.php create mode 100644 wp-content/plugins/multisite-enhancements/inc/autoload/class-filtering-plugins.php create mode 100644 wp-content/plugins/multisite-enhancements/inc/autoload/class-filtering-themes.php create mode 100755 wp-content/plugins/multisite-enhancements/inc/autoload/class-multisite-add-new-plugin.php create mode 100755 wp-content/plugins/multisite-enhancements/inc/autoload/core.php create mode 100644 wp-content/plugins/multisite-enhancements/multisite-enhancements.php create mode 100644 wp-content/plugins/multisite-enhancements/readme.txt diff --git a/wp-content/plugins/multisite-enhancements/LICENSE b/wp-content/plugins/multisite-enhancements/LICENSE new file mode 100644 index 000000000..d159169d1 --- /dev/null +++ b/wp-content/plugins/multisite-enhancements/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + 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/wp-content/plugins/multisite-enhancements/inc/assets/css/wordpress-multisite-enhancements.css b/wp-content/plugins/multisite-enhancements/inc/assets/css/wordpress-multisite-enhancements.css new file mode 100644 index 000000000..ed92c52cc --- /dev/null +++ b/wp-content/plugins/multisite-enhancements/inc/assets/css/wordpress-multisite-enhancements.css @@ -0,0 +1,11 @@ +td.column-active_blogs { + width: 200px; +} + +td.column-active_blogs a { + cursor: pointer; +} + +.siteslist { + display: none; +} \ No newline at end of file diff --git a/wp-content/plugins/multisite-enhancements/inc/assets/css/wordpress-multisite-enhancements.min.css b/wp-content/plugins/multisite-enhancements/inc/assets/css/wordpress-multisite-enhancements.min.css new file mode 100644 index 000000000..a5ee5035b --- /dev/null +++ b/wp-content/plugins/multisite-enhancements/inc/assets/css/wordpress-multisite-enhancements.min.css @@ -0,0 +1 @@ +td.column-active_blogs{width:200px}td.column-active_blogs a{cursor:pointer;}.siteslist{display:none} \ No newline at end of file diff --git a/wp-content/plugins/multisite-enhancements/inc/assets/js/filtering-plugins.js b/wp-content/plugins/multisite-enhancements/inc/assets/js/filtering-plugins.js new file mode 100644 index 000000000..d4db27611 --- /dev/null +++ b/wp-content/plugins/multisite-enhancements/inc/assets/js/filtering-plugins.js @@ -0,0 +1,22 @@ +// via https://github.com/charliepark/faq-patrol +// extend :contains to be case-insensitive; via http://stackoverflow.com/questions/187537/ +jQuery( document ).ready( function( $ ) { + 'use strict'; + + $.expr[ ':' ].contains = function( a, i, m ) { + return ( + a.textContent || a.innerText || '' + ).toUpperCase().indexOf( m[ 3 ].toUpperCase() ) >= 0; + }; + + $( '#plugin-search-input' ).keyup( function() { + var val = $( this ).val(); + var selector = '#the-list'; + if ( val.length < 2 ) { + $( selector ).find( '> tr' ).show(); + } else { + $( selector ).find( '> tr' ).hide(); + $( selector ).find( '.plugin-title strong:contains(' + val + ')' ).parent().parent().show(); + } + } ).focus(); +} ); diff --git a/wp-content/plugins/multisite-enhancements/inc/assets/js/filtering-plugins.min.js b/wp-content/plugins/multisite-enhancements/inc/assets/js/filtering-plugins.min.js new file mode 100644 index 000000000..8a63a1766 --- /dev/null +++ b/wp-content/plugins/multisite-enhancements/inc/assets/js/filtering-plugins.min.js @@ -0,0 +1 @@ +jQuery(document).ready(function(a){"use strict";a.expr[":"].contains=function(a,b,c){return(a.textContent||a.innerText||"").toUpperCase().indexOf(c[3].toUpperCase())>=0},a("#plugin-search-input").keyup(function(){var b=a(this).val(),c="#the-list";b.length<2?a(c).find("> tr").show():(a(c).find("> tr").hide(),a(c).find(".plugin-title strong:contains("+b+")").parent().parent().show())}).focus()}); \ No newline at end of file diff --git a/wp-content/plugins/multisite-enhancements/inc/assets/js/filtering-themes.js b/wp-content/plugins/multisite-enhancements/inc/assets/js/filtering-themes.js new file mode 100644 index 000000000..57584c8af --- /dev/null +++ b/wp-content/plugins/multisite-enhancements/inc/assets/js/filtering-themes.js @@ -0,0 +1,23 @@ +// via https://github.com/charliepark/faq-patrol +// extend :contains to be case-insensitive; via http://stackoverflow.com/questions/187537/ +// @version 2016-10-05s +jQuery( document ).ready( function( $ ) { + 'use strict'; + + $.expr[ ':' ].contains = function( a, i, m ) { + return ( + a.textContent || a.innerText || '' + ).toUpperCase().indexOf( m[ 3 ].toUpperCase() ) >= 0; + }; + + $( '#theme-search-input' ).keyup( function() { + var val = $( this ).val(); + var selector = '#the-list'; + if ( val.length < 2 ) { + $( selector ).find( '> tr' ).show(); + } else { + $( selector ).find( '> tr' ).hide(); + $( selector ).find( '.theme-title strong:contains(' + val + ')' ).parent().parent().show(); + } + } ).focus(); +} ); diff --git a/wp-content/plugins/multisite-enhancements/inc/assets/js/filtering-themes.min.js b/wp-content/plugins/multisite-enhancements/inc/assets/js/filtering-themes.min.js new file mode 100644 index 000000000..ec0b14c05 --- /dev/null +++ b/wp-content/plugins/multisite-enhancements/inc/assets/js/filtering-themes.min.js @@ -0,0 +1 @@ +jQuery(document).ready(function(a){"use strict";a.expr[":"].contains=function(a,b,c){return(a.textContent||a.innerText||"").toUpperCase().indexOf(c[3].toUpperCase())>=0},a("#theme-search-input").keyup(function(){var b=a(this).val(),c="#the-list";b.length<2?a(c).find("> tr").show():(a(c).find("> tr").hide(),a(c).find(".theme-title strong:contains("+b+")").parent().parent().show())}).focus()}); \ No newline at end of file diff --git a/wp-content/plugins/multisite-enhancements/inc/autoload/class-add-admin-favicon.php b/wp-content/plugins/multisite-enhancements/inc/autoload/class-add-admin-favicon.php new file mode 100755 index 000000000..f10f9432d --- /dev/null +++ b/wp-content/plugins/multisite-enhancements/inc/autoload/class-add-admin-favicon.php @@ -0,0 +1,279 @@ +<?php +/** + * Add Favicon from theme folder to the admin area to easier identify the blog. + * + * Remove also the "W" logo and his sublinks in admin bar + * Add Favicon to each blog on the Admin Bar Item "My Sites" + * + * Use the follow filter hooks for different changes + * Use the filter hook to add hooks, there will add the markup + * - Hook: multisite_enhancements_favicon + * - Default is: admin_head + * Use the filter hook to change style + * - Hook: multisite_enhancements_add_favicon + * Use the filter hook to change style + * - Hook: multisite_enhancements_add_admin_bar_favicon + * Use the filter hook to change the default to remove the "W" logo and his sublinks + * - Hook: multisite_enhancements_remove_wp_admin_bar + * - Default is: TRUE + * + * @since 2015-07-23 + * @version 2016-10-05 + * @package WordPress + */ + +add_action( 'init', array( 'Multisite_Add_Admin_Favicon', 'init' ) ); + +/** + * Add Favicon from theme folder to the admin area to easier identify the blog. + * + * Class Multisite_Add_Admin_Favicon + */ +class Multisite_Add_Admin_Favicon { + + /** + * Value to get sites in the Network. + * + * @since 2015-02-26 + * @var int + */ + private $sites_limit = 9999; + + /** + * Define Hooks for add the favicon markup. + * + * @since 0.0.2 + * @var array + */ + static protected $favicon_hooks = array( + 'admin_head', + 'wp_head', + ); + + /** + * Filter to remove "W" logo incl. sublinks from admin bar. + * + * @since 0.0.2 + * @var Boolean + */ + static protected $remove_wp_admin_bar = TRUE; + + /** + * Initialize the class. + */ + public static function init() { + + $class = __CLASS__; + if ( empty( $GLOBALS[ $class ] ) ) { + $GLOBALS[ $class ] = new $class; + } + } + + /** + * Init function to register all used hooks. + * + * Use the filter hook to add hooks, there will add the markup + * Hook: multisite_enhancements_favicon + * + * @since 0.0.2 + */ + public function __construct() { + + /** + * Filter hook to change the value for get sites inside the network. + * + * @type integer + */ + $this->sites_limit = (int) apply_filters( 'multisite_enhancements_sites_limit', $this->sites_limit ); + + /** + * Hooks for add favicon markup. + * + * @type array + */ + $hooks = (array) apply_filters( 'multisite_enhancements_favicon', self::$favicon_hooks ); + + foreach ( $hooks as $hook ) { + add_action( esc_attr( $hook ), array( $this, 'set_favicon' ) ); + + // Add favicon from theme folder to each blog. + add_action( esc_attr( $hook ), array( $this, 'set_admin_bar_blog_icon' ) ); + } + + // Remove admin bar item with "W" logo. + add_action( 'admin_bar_menu', array( $this, 'change_admin_bar_menu' ), 25 ); + } + + /** + * Create markup, if favicon is exist in active theme folder. + * + * Use the filter hook to change style + * Hook: multisite_enhancements_add_favicon + * + * @since 0.0.2 + */ + public function set_favicon() { + + $stylesheet_dir_uri = get_stylesheet_directory_uri(); + $stylesheet_dir = get_stylesheet_directory(); + $output = ''; + + if ( file_exists( $stylesheet_dir . $this->get_favicon_path() ) ) { + $output .= '<link rel="shortcut icon" type="image/x-icon" href="' + . esc_url( $stylesheet_dir_uri . $this->get_favicon_path() ) . '" />'; + $output .= '<style>'; + $output .= '#wpadminbar #wp-admin-bar-site-name>.ab-item:before { content: none !important;}'; + $output .= 'li#wp-admin-bar-site-name a { background: url( "' + . $stylesheet_dir_uri . $this->get_favicon_path() + . '" ) left center/20px no-repeat !important; padding-left: 21px !important; background-size: 20px !important; } li#wp-admin-bar-site-name { margin-left: 5px !important; } li#wp-admin-bar-site-name {} #wp-admin-bar-site-name div a { background: none !important; }' . "\n"; + $output .= '</style>'; + } + + /** + * Use the filter hook to change style. + * + * @type string + */ + echo apply_filters( 'multisite_enhancements_add_favicon', $output ); + } + + /** + * Add Favicon from each blog to Multisite Menu of "My Sites". + * + * Use the filter hook to change style + * Hook: multisite_enhancements_add_admin_bar_favicon + * + * @since 0.0.2 + */ + public function set_admin_bar_blog_icon() { + + // Only usable if the user is logged in and use the admin bar. + if ( ! is_user_logged_in() || ! is_admin_bar_showing() ) { + return; + } + + $user_id = get_current_user_id(); + $user_blogs = get_blogs_of_user( $user_id ); + + $output = ''; + foreach ( (array) $user_blogs as $blog ) { + + $custom_icon = FALSE; + + // Validate, that we use nly int value. + $blog_id = (int) $blog->userblog_id; + $stylesheet = get_blog_option( $blog_id, 'stylesheet' ); + + // Get stylesheet directory uri. + $theme_root_uri = get_theme_root_uri( $stylesheet ); + $stylesheet_dir_uri = "$theme_root_uri/$stylesheet"; + + // Get stylesheet directory. + $theme_root = get_theme_root( $stylesheet ); + $stylesheet_dir = "$theme_root/$stylesheet"; + + // Create favicon directory and directory url locations. + $favicon_dir_uri = $this->get_favicon_path( $blog_id, $stylesheet_dir_uri, 'url' ); + $favicon_dir = $this->get_favicon_path( $blog_id, $stylesheet_dir, 'dir' ); + + // Check if the user has manually added a site icon in WP (since WP 4.3). + $site_icon_id = (int) get_blog_option( $blog_id, 'site_icon' ); + if ( 0 !== $site_icon_id ) { + switch_to_blog( $blog_id ); + $url_data = wp_get_attachment_image_src( $site_icon_id, array( 32, 32 ) ); + $custom_icon = esc_url( $url_data[0] ); + restore_current_blog(); + } elseif ( file_exists( $favicon_dir ) ) { + $custom_icon = $favicon_dir_uri; + } + + if ( FALSE !== $custom_icon ) { + $output .= '#wpadminbar .quicklinks li#wp-admin-bar-blog-' . $blog_id + . ' .blavatar { font-size: 0 !important; }'; + $output .= '#wp-admin-bar-blog-' . $blog_id + . ' div.blavatar { background: url( "' . $custom_icon + . '" ) left bottom/16px no-repeat !important; background-size: 16px !important; margin: 0 2px 0 -2px; }' . "\n"; + } + } + + if ( '' !== $output ) { + /** + * Use the filter hook to change style. + * + * @type string + */ + echo apply_filters( + 'multisite_enhancements_add_admin_bar_favicon', + "\n" . '<style>' . $output . '</style>' . "\n" + ); + } + } + + /** + * Maybe removes the "W" logo incl. sublinks from the admin menu. + * + * Use the filter hook to change the default to remove the "W" logo and his sublinks + * Hook: multisite_enhancements_remove_wp_admin_bar + * + * @since 0.0.2 + * @param WP_Admin_Bar $admin_bar WP_Admin_Bar instance, passed by reference. + */ + public function change_admin_bar_menu( $admin_bar ) { + + /** + * Use the filter hook to remove or not remove the first part in the admin bar. + * + * @type bool + */ + if ( apply_filters( + 'multisite_enhancements_remove_wp_admin_bar', + self::$remove_wp_admin_bar + ) + ) { + $admin_bar->remove_node( 'wp-logo' ); + } + } + + /** + * Get the path to the favicon file from the root of a theme. + * + * @since 1.0.5 + * + * @param int $blog_id Id of the blog in the network. + * @param string $path Path to Favicon. + * @param string $path_type Type 'url' or 'dir'. + * + * @return string File path to favicon file. + * @internal param ID $integer of blog in network + * @internal param Path $string to Favicon + * @internal param Path $string type 'url' or 'dir' + */ + protected function get_favicon_path( $blog_id = 0, $path = '', $path_type = 'url' ) { + + if ( 0 === $blog_id ) { + $blog_id = get_current_blog_id(); + } + + /** + * Filter the file path to the favicon file. + * + * Default is '/favicon.ico' which assumes there's a .ico file in the theme root. + * This filter allows that path, file name, and file extension to be changed. + * + * @since 1.0.5 + * + * @param string $path Path to favicon file. + * + * Optional parameters: + * + * When using a different directory than the stylesheet use the $blog_id and $path_type + * integer $blog_id + * + * string $path_type = 'url' -> use URL for the location as a URL + * string $path_type = 'dir' -> use URL for the location in the server, used to check if the file exists + */ + + return apply_filters( 'multisite_enhancements_favicon_path', $path . '/favicon.ico', $blog_id, $path_type ); + } + +} // end class diff --git a/wp-content/plugins/multisite-enhancements/inc/autoload/class-add-blog-id.php b/wp-content/plugins/multisite-enhancements/inc/autoload/class-add-blog-id.php new file mode 100755 index 000000000..74368fa6b --- /dev/null +++ b/wp-content/plugins/multisite-enhancements/inc/autoload/class-add-blog-id.php @@ -0,0 +1,110 @@ +<?php +/** + * View Blog and User ID in WordPress Multisite. + * + * @see http://wpengineer.com/2188/view-blog-id-in-wordpress-multisite/ + * @since 2013-07-19 + * @version 2016-01-15 + * @package WordPress + */ + +add_action( 'init', array( 'Multisite_Add_Blog_Id', 'init' ) ); + +/** + * View Blog and User ID in WordPress Multisite. + * Class Multisite_Add_Blog_Id + */ +class Multisite_Add_Blog_Id { + + /** + * Init the class. + */ + public static function init() { + + $class = __CLASS__; + if ( empty( $GLOBALS[ $class ] ) ) { + $GLOBALS[ $class ] = new $class; + } + } + + /** + * Init function to register all used hooks. + * + * @since 0.0.1 + */ + public function __construct() { + + if ( ! is_network_admin() ) { + return; + } + + // Add blog id. + add_filter( 'wpmu_blogs_columns', array( $this, 'get_id' ) ); + add_action( 'manage_sites_custom_column', array( $this, 'get_blog_id' ), 10, 2 ); + + // Add user id. + add_filter( 'manage_users-network_columns', array( $this, 'get_id' ) ); + add_filter( 'manage_users_custom_column', array( $this, 'get_user_id' ), 10, 3 ); + + add_action( 'admin_print_styles-sites.php', array( $this, 'add_style' ) ); + add_action( 'admin_print_styles-users.php', array( $this, 'add_style' ) ); + } + + /** + * Echo the site id of each site. + * + * @param string $column_name The name of the column. + * @param integer $blog_id The Id of the blog. + * + * @return mixed + */ + public function get_blog_id( $column_name, $blog_id ) { + + if ( 'object_id' === $column_name ) { + echo (int) $blog_id; + } + + return $column_name; + } + + /** + * Echo the ID of each user. + * + * @param string $value Custom column output. + * @param string $column_name The current column name. + * @param int $user_id ID of the currently-listed user. + * + * @return int|string + */ + public function get_user_id( $value, $column_name, $user_id ) { + + if ( 'object_id' === $column_name ) { + return (int) $user_id; + } + + return $value; + } + + /** + * Add in a column header. + * + * @param array $columns An array of displayed site columns. + * + * @return mixed + */ + public function get_id( $columns ) { + + $columns[ 'object_id' ] = __( 'ID' ); + + return $columns; + } + + /** + * Add custom style. + */ + public function add_style() { + + echo '<style>#object_id { width:7%; }</style>'; + } + +} // end class diff --git a/wp-content/plugins/multisite-enhancements/inc/autoload/class-add-css.php b/wp-content/plugins/multisite-enhancements/inc/autoload/class-add-css.php new file mode 100644 index 000000000..1625a9dbc --- /dev/null +++ b/wp-content/plugins/multisite-enhancements/inc/autoload/class-add-css.php @@ -0,0 +1,62 @@ +<?php +/** + * On the network plugin and theme pages, add css to present the active column + * If this class is loaded, modify the presentation of the column in order to + * allow showing or hiding the list of sites that uses a theme or plugin + * + * Kudos to #n-goncalves for this solution. + * @see https://github.com/bueltge/wordpress-multisite-enhancements/pull/44 + * + * @since 2018-02-15 + * @version 2018-02-15 + * @package WordPress + */ + +add_action( 'init', array( 'Enqueue_Column_Style', 'init' ) ); + +/** + * On the network plugin and theme pages, add css to present the active column + * If this class is loaded, modify the presentation of the column in order to + * allow showing or hiding the list of sites that uses a theme or plugin + * + * Class Enqueue_Column_Style + */ +class Enqueue_Column_Style { + + /** + * Init function to register all used hooks. + * + */ + public function __construct() { + + add_action( 'admin_head-themes.php', array( $this, 'enqueue_style' ) ); + add_action( 'admin_head-plugins.php', array( $this, 'enqueue_style' ) ); + } + + /** + * Initialize the class. + */ + public static function init() { + + $class = __CLASS__; + if ( empty( $GLOBALS[ $class ] ) ) { + $GLOBALS[ $class ] = new $class; + } + } + + /** + * Enqueue column style. + * + */ + public function enqueue_style() { + + $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min'; + + wp_register_style( + 'admin_column_css', + plugins_url( '/inc/assets/css/wordpress-multisite-enhancements' . $suffix . '.css', MULTISITE_ENHANCEMENT_BASE ), + false ); + wp_enqueue_style( 'admin_column_css' ); + } // end enqueue_style() + +} // end class diff --git a/wp-content/plugins/multisite-enhancements/inc/autoload/class-add-plugin-list.php b/wp-content/plugins/multisite-enhancements/inc/autoload/class-add-plugin-list.php new file mode 100755 index 000000000..7202a1ec8 --- /dev/null +++ b/wp-content/plugins/multisite-enhancements/inc/autoload/class-add-plugin-list.php @@ -0,0 +1,377 @@ +<?php +/** + * On the network plugins page, show which blogs have this plugin active. + * + * @since 2013-07-19 + * @version 2018-04-13 + * @package WordPress + */ + +add_action( 'init', array( 'Multisite_Add_Plugin_List', 'init' ) ); + +/** + * Class Multisite_Add_Plugin_List + */ +class Multisite_Add_Plugin_List { + + /** + * On this plugin status will not show the not or activated status in the table of plugins. + * + * @since 01/03/2014 + * @var array + */ + static protected $excluded_plugin_status = array( 'dropins', 'mustuse' ); + /** + * String for the transient string, there save the blog plugins. + * + * @since 2015-02-21 + * @var string + */ + static protected $site_transient_blogs_plugins = 'blogs_plugins'; + /** + * Define the allowed html tags for wp_kses. + * + * @var array + */ + static protected $wp_kses_allowed_html = array( + 'br' => array(), + 'nobr' => array( + 'class' => array(), + ), + 'span' => array( + 'class' => array(), + ), + 'ul' => array( + 'id' => array(), + 'class' => array(), + ), + 'li' => array( + 'title' => array(), + ), + 'a' => array( + 'href' => array(), + 'onclick' => array(), + 'title' => array(), + ), + 'p' => array(), + ); + /** + * Value to get sites in the Network. + * + * @since 2015-02-26 + * @var int + */ + private $sites_limit = 9999; + /** + * Member variable to store data about active plugins for each blog. + * + * @since 2015-02-21 + * @var array + */ + private $blogs_plugins; + + /** + * Init function to register all used hooks. + * + * @since 0.0.1 + */ + public function __construct() { + + add_action( 'load-plugins.php', array( $this, 'development_helper' ) ); + + // Fires after a plugin has been activated; but not on silently activated, like update. + add_action( 'activated_plugin', array( $this, 'clear_plugins_site_transient' ), 10, 2 ); + // Fires before a plugin is deactivate; but not on silently activated, like update. + add_action( 'deactivated_plugin', array( $this, 'clear_plugins_site_transient' ), 10, 2 ); + + if ( ! is_network_admin() ) { + return; + } + + /** + * Filter to change the value for get sites inside the network. + * + * @type integer + */ + $this->sites_limit = (int) apply_filters( 'multisite_enhancements_sites_limit', $this->sites_limit ); + + add_filter( 'manage_plugins-network_columns', array( $this, 'add_plugins_column' ), 10, 1 ); + add_action( 'manage_plugins_custom_column', array( $this, 'manage_plugins_custom_column' ), 10, 3 ); + } + + /** + * Initialize the class. + */ + public static function init() { + + $class = __CLASS__; + if ( empty( $GLOBALS[ $class ] ) ) { + $GLOBALS[ $class ] = new $class; + } + } + + /** + * Print Network Admin Notices to inform, that the transient are deleted. + * + * @since 2016-10-23 + */ + public function notice_about_clear_cache() { + + $class = 'notice notice-info'; + $message = esc_attr__( 'Multisite Enhancements: Plugin usage information is not cached while WP_DEBUG is true.', + 'multisite-enhancements' ); + printf( '<div class="%1$s"><p>%2$s</p></div>', $class, $message ); + } + + /** + * Add in a column header. + * + * @since 0.0.1 + * + * @param array $columns An array of displayed site columns. + * + * @return array + */ + public function add_plugins_column( $columns ) { + + // If not set, then no changes on output. + if ( ! array_key_exists( 'plugin_status', $_GET ) ) { + $_GET['plugin_status'] = ''; + } + + // Not useful on different selections. + if ( ! in_array( esc_attr( $_GET['plugin_status'] ), self::$excluded_plugin_status, false ) ) { + // Translators: Active in is the head of the table column on plugin list. + $columns['active_blogs'] = '<nobr>' . _x( 'Usage', 'column name', 'multisite-enhancements' ) . '</nobr>'; + } + + return $columns; + } + + /** + * Get data for each row on each plugin. + * Echo the string. + * + * @since 0.0.1 + * + * @param String $column_name Name of the column. + * @param String $plugin_file Path to the plugin file. + * @param array $plugin_data An array of plugin data. + * + * @return void + */ + public function manage_plugins_custom_column( $column_name, $plugin_file, $plugin_data ) { + + if ( 'active_blogs' !== $column_name ) { + return null; + } + + // Is this plugin network activated. + if ( ! function_exists( 'is_plugin_active_for_network' ) ) { + require_once ABSPATH . '/wp-admin/includes/plugin.php'; + } + + $active_on_network = is_plugin_active_for_network( $plugin_file ); + + $output = ''; + + if ( $active_on_network ) { + // We don't need to check any further for network active plugins. + // Translators: The plugin is network wide active, the string is for each plugin possible. + $output .= __( '<nobr>Network Activated</nobr>', 'multisite-enhancements' ); + + // List Blogs, there is activated. + } else { + // Is this plugin active on any blogs in this network. + $active_on_blogs = $this->is_plugin_active_on_blogs( $plugin_file ); + + if ( ! $active_on_blogs ) { + // Translators: The plugin is not activated, the string is for each plugin possible. + $output .= __( '<nobr>Not Activated</nobr>', 'multisite-enhancements' ); + } else { + $active_count = sizeOf( $active_on_blogs ); + $output .= '<p>'; + + $is_list_hidden = false; + // Hide the list of sites if the class isn"t loaded or there's less or equal to 4 sites + if ( class_exists( 'Enqueue_Column_Style', false ) && $active_count > 4 ) { + $output .= sprintf( + _n( 'Active on %2$s %1$d site %3$s', 'Active on %2$s %1$d sites %3$s', $active_count, 'multisite-enhancements' ), + $active_count, + "<a onclick=\"jQuery('ul[id*=\'siteslist_{$plugin_file}\']').slideToggle('swing');\">", + '</a>' + ); + } else { + $output .= sprintf( + _n( 'Active on %s site', 'Active on %s sites', $active_count, 'multisite-enhancements' ), + $active_count + ); + $is_list_hidden = true; + } + $output .= '</p>'; + $output .= '<ul id="siteslist_' . $plugin_file; + $output .= ( $is_list_hidden ) ? '">' : '" class="siteslist">'; + + + foreach ( $active_on_blogs as $key => $value ) { + + // Check the site for archived. + $class = $hint = ''; + if ( $this->is_archived( $key ) ) { + $class = ' class="site-archived"'; + $hint = esc_attr__( ', Archived site', 'multisite-enhancements' ); + } + + $output .= '<li' . $class . ' title="Blog ID: ' . $key . $hint . '">'; + $output .= '<nobr><a href="' . get_admin_url( $key ) . 'plugins.php">' + . $value['name'] . '</a>' . $hint . '</nobr></li>'; + } + + $output .= '</ul>'; + } + } + + if ( ! isset($plugin_data['Network']) ) { + $plugin_data['Network'] = false; + } + + // Add indicator that the plugin is "Network Only". + if ( $plugin_data['Network'] ) { + $output .= '<br /><nobr class="submitbox"><span class="submitdelete">' + . esc_attr__( 'Network Only', 'multisite-enhancements' ) + . '</span></nobr>'; + } + + echo wp_kses( $output, self::$wp_kses_allowed_html ); + } + + /** + * Is plugin active in blogs. + * + * @since 0.0.1 + * + * @param string $plugin_file An name of the plugin file. + * + * @internal param $String + * + * @return array $active_in_plugins Which Blog ID and Name of Blog for each item in Array. + */ + public function is_plugin_active_on_blogs( $plugin_file ) { + + $blogs_plugins = $this->get_blogs_plugins(); + + $active_in_plugins = array(); + + foreach ( $blogs_plugins as $blog_id => $data ) { + if ( in_array( $plugin_file, $data['active_plugins'], true ) ) { + $active_in_plugins[ $blog_id ] = array( + 'name' => $data['blogname'], + 'path' => $data['blogpath'], + ); + } + } + + return $active_in_plugins; + } + + /** + * Gets an array of blog data including active plugins for each blog. + * + * @since 21/02/2015 + * + * @return array + */ + public function get_blogs_plugins() { + + // See if the data is present in the variable first. + if ( $this->blogs_plugins ) { + return $this->blogs_plugins; + + // If not, see if we can load data from the transient. + } elseif ( false === ( $this->blogs_plugins = get_site_transient( self::$site_transient_blogs_plugins ) ) ) { + + // Cannot load data from transient, so load from DB and set transient. + $this->blogs_plugins = array(); + + $blogs = (array) Multisite_Core::get_blog_list( 0, $this->sites_limit ); + + /** + * Data to each site of the network, blogs. + * + * @var array $blog + */ + foreach ( $blogs as $blog ) { + + // Convert object to array. + $blog = (array) $blog; + + $this->blogs_plugins[ $blog['blog_id'] ] = $blog; + $this->blogs_plugins[ $blog['blog_id'] ]['blogpath'] = get_blog_details( + $blog['blog_id'] + )->path; + $this->blogs_plugins[ $blog['blog_id'] ]['blogname'] = get_blog_details( + $blog['blog_id'] + )->blogname; + $this->blogs_plugins[ $blog['blog_id'] ]['active_plugins'] = array(); + $plugins = (array) get_blog_option( + $blog['blog_id'], 'active_plugins' + ); + if ( $plugins ) { + foreach ( $plugins as $plugin_file ) { + $this->blogs_plugins[ $blog['blog_id'] ]['active_plugins'][] = $plugin_file; + } + } + } + + if ( ! $this->development_helper() ) { + set_site_transient( self::$site_transient_blogs_plugins, $this->blogs_plugins ); + } + } + + // Data should be here, if loaded from transient or DB. + return $this->blogs_plugins; + } + + /** + * Run helpers if the debug constant is true to help on development, debugging. + * + * @since 2016-10-23 + * @return bool + */ + public function development_helper() { + + if ( ! defined( 'WP_DEBUG' ) || ! WP_DEBUG ) { + return false; + } + + add_action( 'network_admin_notices', array( $this, 'notice_about_clear_cache' ) ); + $this->clear_plugins_site_transient(); + + return true; + } + + /** + * Clears the $blogs_plugins site transient when any plugins are activated/deactivated. + * + * @since 2015-02-25 + */ + public function clear_plugins_site_transient() { + + delete_site_transient( self::$site_transient_blogs_plugins ); + } + + /** + * Check, if the status of the site archived. + * + * @param integer $site_id ID of the site. + * + * @return bool + */ + public function is_archived( $site_id ) { + + $site_id = (int) $site_id; + + return (bool) get_blog_details( $site_id )->archived; + } + +} // end class diff --git a/wp-content/plugins/multisite-enhancements/inc/autoload/class-add-site-status-labels.php b/wp-content/plugins/multisite-enhancements/inc/autoload/class-add-site-status-labels.php new file mode 100644 index 000000000..46ca1e407 --- /dev/null +++ b/wp-content/plugins/multisite-enhancements/inc/autoload/class-add-site-status-labels.php @@ -0,0 +1,116 @@ +<?php +/** + * Add status labels to blogs. + * + * @since 2015-07-14 + * @version 2016-10-28 + * @package WordPress + */ + +add_action( 'init', array( 'Multisite_Add_Site_Status_labels', 'init' ) ); + +/** + * Add status labels to sites. + * + * Class Multisite_Add_Site_Status_labels + */ +class Multisite_Add_Site_Status_labels { + + /** + * Initialize the class. + */ + public static function init() { + + $class = __CLASS__; + if ( empty( $GLOBALS[ $class ] ) ) { + $GLOBALS[ $class ] = new $class; + } + } + + /** + * Init function to register all used hooks. + * + * @since 2015-07-14 + */ + public function __construct() { + + if ( ! current_user_can( 'manage_network' ) ) { + return; + } + + add_action( 'admin_bar_menu', array( $this, 'add_status_label' ) ); + } + + /** + * Check string, if is a external url. + * + * @param string $haystack The string to search in. + * @param string $needle The search string. + * + * @return bool + */ + public function check_external_url( $haystack, $needle ) { + + // Remove last string for exactly check. + $needle = rtrim( $needle, '/' ); + + return $needle + && FALSE === strpos( + $haystack, + str_replace( array( 'http://', 'https://', '//' ), '', $needle ) + ); + } + + /** + * Check, if the status of the site public. + * + * @param integer $site_id ID of the site. + * + * @return bool + */ + public function is_site_live( $site_id ) { + + $site_id = (int) $site_id; + return (bool) get_blog_option( $site_id, 'blog_public' ); + } + + /** + * Add status label from each blog to Multisite Menu of "My Sites". + * + * Use the filter hook 'multisite_enhancements_status_label' to change style, dashicon, markup. + * + * @param \WP_Admin_Bar $admin_bar All necessary admin bar items. + * + * @return mixed + */ + public function add_status_label( \WP_Admin_Bar $admin_bar ) { + + foreach ( $admin_bar->user->blogs as $key => $blog ) { + + $url_hint = ''; + $live_hint = ''; + + if ( $this->check_external_url( $blog->siteurl, $admin_bar->user->domain ) ) { + $title = esc_attr__( 'external domain', 'multisite-enhancements' ); + $class = 'ab-icon dashicons-before dashicons-external'; + $url_hint = '<span title="' . $title . '" class="' . $class . '"></span>'; + } + + if ( ! $this->is_site_live( $blog->userblog_id ) ) { + $title = esc_attr__( 'noindex', 'multisite-enhancements' ); + $class = 'ab-icon dashicons-before dashicons-dismiss'; + $live_hint = '<span title="' . $title . '" class="' . $class . '"></span>'; + } + + // Add span markup. + $blogname = $url_hint . $live_hint . $blog->blogname; + + // Filter hook for custom style of the admin bar site string. + $blogname = apply_filters( 'multisite_enhancements_status_label', $blogname, $blog ); + + $admin_bar->user->blogs[ $key ]->blogname = $blogname; + } + + return $admin_bar; + } +} // end class diff --git a/wp-content/plugins/multisite-enhancements/inc/autoload/class-add-ssl-identifier.php b/wp-content/plugins/multisite-enhancements/inc/autoload/class-add-ssl-identifier.php new file mode 100644 index 000000000..f516a3ed5 --- /dev/null +++ b/wp-content/plugins/multisite-enhancements/inc/autoload/class-add-ssl-identifier.php @@ -0,0 +1,112 @@ +<?php # -*- coding: utf-8 -*- +/** + * Add a icon to identify the ssl protocol on each site. + * + * @since 2017-07-13 + * @version 2017-11-26 + * @package WordPress + */ + +namespace Bueltge\Multisite_Add_Ssh_Identifier; + +add_action( 'admin_init', __NAMESPACE__ . '\\bootstrap' ); +/** + * Create the instance of this class. + */ +function bootstrap() { + + $multisite_add_ssh_identifier = new Multisite_Add_Ssh_Identifier(); + $multisite_add_ssh_identifier->init(); +} + +/** + * Class Multisite_Add_Ssh_Identifier + */ +class Multisite_Add_Ssh_Identifier { + + /** + * Set column name to identifier the column. + * + * @var string + */ + private $column = 'site_ssl'; + + /** + * Use the WP hooks to include the functions in wp. + */ + public function init() { + + add_filter( 'wpmu_blogs_columns', array( $this, 'add_column' ) ); + add_action( 'manage_sites_custom_column', array( $this, 'get_protocol' ), 10, 2 ); + + add_action( 'admin_print_styles-sites.php', array( $this, 'add_style' ) ); + } + + /** + * Constructor. + * + * Multisite_Add_Ssh_Identifier constructor. + */ + public function __construct() {} + + /** + * Determines if SSL is used. + * + * @param integer $blog_id + * + * @return bool + */ + private function is_ssl( $blog_id ) { + + return ( strstr( get_home_url( $blog_id ), 'https' ) ) ? true : false; + } + + /** + * Add new column for the ssh identifier. + * + * @param array $columns + * + * @return array + */ + public function add_column( array $columns ) { + + $first_column = array_slice( $columns, 0, 1 ); + $after_first_columns = array_slice( $columns, 1 ); + $ssh_column = array( $this->column => esc_html__( 'https', 'multisite-enhancements' ) ); + + // Union of the arrays. + $columns = $first_column + $ssh_column + $after_first_columns; + + return $columns; + } + + /** + * Print icon, markup to identifier the protocol for each site. + * + * @param string $column_name + * @param integer $blog_id + * + * @return string + */ + public function get_protocol( $column_name, $blog_id ) { + + if ( $this->column === $column_name ) { + + $status = 'unlock'; + if ( $this->is_ssl( $blog_id ) ) { + $status = 'lock'; + } + + echo '<span class="dashicons dashicons-' . $status . '"></span>'; // WPCS: XSS ok. + } + return $column_name; + } + + /** + * Print custom style for the https column. + */ + public function add_style() { + + echo '<style>#' . esc_attr( $this->column ) . ' { width:5%; } .column-' . esc_attr( $this->column ) . ' { text-align: center; }</style>'; + } +} diff --git a/wp-content/plugins/multisite-enhancements/inc/autoload/class-add-theme-list.php b/wp-content/plugins/multisite-enhancements/inc/autoload/class-add-theme-list.php new file mode 100755 index 000000000..f394db7d9 --- /dev/null +++ b/wp-content/plugins/multisite-enhancements/inc/autoload/class-add-theme-list.php @@ -0,0 +1,417 @@ +<?php +/** + * On the network theme page, show which blog have the theme active. + * + * @since 2013-07-22 + * @version 2018-05-16 + * @package WordPress + */ + +add_action( 'init', array( 'Multisite_Add_Theme_List', 'init' ) ); + +/** + * On the network theme page, show which blog have the theme active. + * + * Class Multisite_Add_Theme_List + */ +class Multisite_Add_Theme_List { + + /** + * String for the transient string, there save the blog themes. + * + * @since 2015-02-21 + * @var string + */ + static protected $site_transient_blogs_themes = 'blogs_themes'; + /** + * Define the allowed html tags for wp_kses. + * + * @var array + */ + static protected $wp_kses_allowed_html = array( + 'br' => array(), + 'nobr' => array( + 'class' => array(), + ), + 'span' => array( + 'class' => array(), + ), + 'ul' => array( + 'id' => array(), + 'class' => array(), + ), + 'li' => array( + 'title' => array(), + ), + 'a' => array( + 'href' => array(), + 'onclick' => array(), + 'title' => array(), + ), + 'p' => array(), + ); + /** + * Value to get sites in the Network. + * + * @since 2015-02-26 + * @var int + */ + private $sites_limit = 9999; + /** + * Member variable to store data about active theme for each blog. + * + * @since 21/02/2015 + * @var array + */ + private $blogs_themes; + + /** + * Init function to register all used hooks. + * + * @since 0.0.2 + */ + public function __construct() { + + // Delete transient on themes page. + add_action( 'load-themes.php', array( $this, 'development_helper' ) ); + + // Fires after the theme is switched. + add_action( 'switch_theme', array( $this, 'clear_themes_site_transient' ), 10, 1 ); + + if ( ! is_network_admin() ) { + return; + } + + /** + * Filter to change the value for get sites inside the network. + * + * @since 2015-02-26 + * @type integer + */ + $this->sites_limit = (int) apply_filters( 'multisite_enhancements_sites_limit', $this->sites_limit ); + + add_filter( 'manage_themes-network_columns', array( $this, 'add_themes_column' ), 10, 1 ); + add_action( 'manage_themes_custom_column', array( $this, 'manage_themes_custom_column' ), 10, 3 ); + + add_action( 'update_site_option_allowedthemes', array( $this, 'clear_themes_site_transient' ), 10, 1 ); + } + + /** + * Initialize the class. + */ + public static function init() { + + $class = __CLASS__; + if ( empty( $GLOBALS[ $class ] ) ) { + $GLOBALS[ $class ] = new $class; + } + } + + /** + * Print Network Admin Notices to inform, that the transient are deleted. + * + * @since 2016-10-23 + */ + public function notice_about_clear_cache() { + + $class = 'notice notice-info'; + $message = esc_attr__( + 'Multisite Enhancements: Theme usage information is not cached while WP_DEBUG is true.', + 'multisite-enhancements' + ); + printf( '<div class="%1$s"><p>%2$s</p></div>', $class, $message ); + } + + /** + * Add in a column header. + * + * @since 0.0.2 + * + * @param array $columns An array of displayed site columns. + * + * @return array + */ + public function add_themes_column( $columns ) { + + $columns['active_blogs'] = '<nobr>' . _x( 'Usage', 'column name', 'multisite-enhancements' ) . '</nobr>'; + + return $columns; + } + + /** + * Get data for each row on each theme. + * Print the string about the usage. + * + * @since 0.0.2 + * + * @param String $column_name Name of the column. + * @param String $theme_key Path to the theme file. + * @param array|\WP_Theme $theme_data An array of theme data. + */ + public function manage_themes_custom_column( $column_name, $theme_key, \WP_Theme $theme_data ) { + + if ( 'active_blogs' !== $column_name ) { + return null; + } + + $output = ''; + + $active_on_blogs = $this->is_theme_active_on_blogs( $theme_key ); + + // Check, if is a child theme and return parent. + $child_context = ''; + $is_child = $this->is_child( $theme_data ); + if ( $is_child ) { + $parent_name = $theme_data->parent()->Name; + $child_context .= '<br>' . sprintf( + // Translators: The placeholder will be replaced by the name of the parent theme. + esc_attr__( 'This is a child theme of %s.', 'multisite-enhancements' ), + '<strong>' . esc_attr( $parent_name ) . '</strong>' + ); + } + + // Check if used as a parent theme for a child. + $parent_context = ''; + $used_as_parent = $this->is_parent( $theme_key ); + if ( count( $used_as_parent ) ) { + $parent_context .= '<br>' . esc_attr__( + 'This is used as a parent theme by:', + 'multisite-enhancements' + ) . ' '; + $parent_context .= implode( ', ', $used_as_parent ); + } + + if ( ! $active_on_blogs ) { + // Translators: The theme is not activated, the string is for each plugin possible. + $output .= __( '<nobr>Not Activated</nobr>', 'multisite-enhancements' ); + $output .= $child_context; + $output .= $parent_context; + } else { + $active_count = count( $active_on_blogs ); + $output .= '<p>'; + + $is_list_hidden = false; + // Hide the list of sites if the class isn"t loaded or there's less or equal to 4 sites. + if ( class_exists( 'Enqueue_Column_Style', false ) && $active_count > 4 ) { + $output .= sprintf( + _n( + 'Active on %2$s %1$d site %3$s', + 'Active on %2$s %1$d sites %3$s', + $active_count, + 'multisite-enhancements' + ), + $active_count, + "<a onclick=\"jQuery('ul[id*=\'siteslist_{$theme_key}\']').slideToggle('swing');\">", + '</a>' + ); + } else { + $output .= sprintf( + // Translators: The placeholder will be replaced by the count of sites there use that theme. + _n( 'Active on %s site', 'Active on %s sites', $active_count, 'multisite-enhancements' ), + $active_count + ); + $is_list_hidden = true; + } + $output .= '</p>'; + $output .= '<ul id="siteslist_' . $theme_key; + $output .= ( $is_list_hidden ) ? '">' : '" class="siteslist">'; + + foreach ( $active_on_blogs as $key => $value ) { + + // Check the site for archived. + $class = $hint = ''; + if ( $this->is_archived( $key ) ) { + $class = ' class="site-archived"'; + $hint = esc_attr__( ', Archived site', 'multisite-enhancements' ); + } + + $output .= '<li' . $class . ' title="Blog ID: ' . $key . $hint . '">'; + $output .= '<nobr><a href="' . get_admin_url( $key ) . 'themes.php">' + . $value['name'] . '</a>' . $hint . '</nobr>'; + $output .= '</li>'; + } + + $output .= '</ul>'; + $output .= $child_context; + $output .= $parent_context; + } + + echo wp_kses( $output, self::$wp_kses_allowed_html ); + } + + /** + * Is theme active in blogs. + * + * Return array with values to each theme + * + * @since 0.0.2 + * + * @param String $theme_key The key of each theme. + * + * @return array + */ + public function is_theme_active_on_blogs( $theme_key ) { + + $blogs_themes = $this->get_blogs_themes(); + + $active_in_themes = array(); + + foreach ( $blogs_themes as $blog_id => $data ) { + + if ( $data['stylesheet'] === $theme_key ) { + $active_in_themes[ $blog_id ] = array( + 'name' => $data['blogname'], + 'path' => $data['blogpath'], + ); + } + } + + return $active_in_themes; + } + + /** + * Gets an array of blog data including active theme for each blog. + * + * @since 21/02/2015 + * + * @return array + */ + public function get_blogs_themes() { + + // See if the data is present in the variable first. + if ( $this->blogs_themes ) { + return $this->blogs_themes; + + // If not, see if we can load data from the transient. + } elseif ( false === ( $this->blogs_themes = get_site_transient( self::$site_transient_blogs_themes ) ) ) { + + // Cannot load data from transient, so load from DB and set transient. + $this->blogs_themes = array(); + + $blogs = (array) Multisite_Core::get_blog_list( 0, $this->sites_limit ); + + /** + * Data to each site of the network, blogs. + * + * @var array $blog + */ + foreach ( $blogs as $blog ) { + + // Convert object to array. + $blog = (array) $blog; + + $this->blogs_themes[ $blog['blog_id'] ] = $blog; + $this->blogs_themes[ $blog['blog_id'] ]['blogpath'] = get_blog_details( + $blog['blog_id'] + )->path; + $this->blogs_themes[ $blog['blog_id'] ]['blogname'] = get_blog_details( + $blog['blog_id'] + )->blogname; + $this->blogs_themes[ $blog['blog_id'] ]['template'] = get_blog_option( + $blog['blog_id'], 'template' + ); + $this->blogs_themes[ $blog['blog_id'] ]['stylesheet'] = get_blog_option( + $blog['blog_id'], 'stylesheet' + ); + } + + if ( ! $this->development_helper() ) { + set_site_transient( self::$site_transient_blogs_themes, $this->blogs_themes ); + } + } + + // Data should be here, if loaded from transient or DB. + return $this->blogs_themes; + } + + /** + * Run helpers if the debug constant is true to help on development, debugging. + * + * @since 2016-10-23 + * @return bool + */ + public function development_helper() { + + if ( ! defined( 'WP_DEBUG' ) || ! WP_DEBUG ) { + return false; + } + + add_action( 'network_admin_notices', array( $this, 'notice_about_clear_cache' ) ); + $this->clear_themes_site_transient(); + + return true; + } + + /** + * Clears the $blogs_themes site transient when any themes are activated/deactivated. + * + * @since 2015-02-21 + */ + public function clear_themes_site_transient() { + + delete_site_transient( self::$site_transient_blogs_themes ); + } + + /** + * Check, the current theme have a parent value and is a child theme. + * + * @param array|\WP_Theme $theme_data An array of theme data. + * + * @return bool + */ + public function is_child( \WP_Theme $theme_data ) { + + return (bool) $theme_data->parent(); + } + + /** + * Gets an array of themes which have the selected one as parent. + * + * @since 21/02/2015 + * @version 2017-02-22 + * + * @param string $theme_key The key of each theme. + * + * @return array + */ + public function is_parent( $theme_key ) { + + $blogs_themes = $this->get_blogs_themes(); + $parent_of = array(); + + /** + * Provide the data to the Theme of each site. + * + * @var array $data + */ + foreach ( $blogs_themes as $blog_id => $data ) { + + $template = false; + if ( array_key_exists( 'template', $data ) ) { + $template = $data['template']; + } + + if ( $template === $theme_key && $template !== $data['stylesheet'] ) { + $theme = wp_get_theme( $data['stylesheet'] ); + $parent_of[] = $theme->get( 'Name' ); + } + } + + return array_unique( $parent_of ); + } + + /** + * Check, if the status of the site archived. + * + * @param integer $site_id ID of the site. + * + * @return bool + */ + public function is_archived( $site_id ) { + + $site_id = (int) $site_id; + + return (bool) get_blog_details( $site_id )->archived; + } + +} // end class diff --git a/wp-content/plugins/multisite-enhancements/inc/autoload/class-admin-bar-tweaks.php b/wp-content/plugins/multisite-enhancements/inc/autoload/class-admin-bar-tweaks.php new file mode 100755 index 000000000..ab92e5742 --- /dev/null +++ b/wp-content/plugins/multisite-enhancements/inc/autoload/class-admin-bar-tweaks.php @@ -0,0 +1,141 @@ +<?php +/** + * Adds several useful items to the multisite 'Network Admin' admin bar. + * + * @since 2013-07-19 + * @version 2016-10-28 + * @package WordPress + */ + +add_action( 'init', array( 'Multisite_Admin_Bar_Tweaks', 'init' ) ); + +/** + * Class Multisite_Admin_Bar_Tweaks + */ +class Multisite_Admin_Bar_Tweaks { + + /** + * Initialize this class. + */ + public static function init() { + + $class = __CLASS__; + if ( empty( $GLOBALS[ $class ] ) ) { + $GLOBALS[ $class ] = new $class; + } + } + + /** + * Init function to register all used hooks. + * + * @since 0.0.1 + */ + public function __construct() { + + add_action( 'wp_before_admin_bar_render', array( $this, 'enhance_network_admin_bar' ) ); + add_action( 'wp_before_admin_bar_render', array( $this, 'enhance_network_blog_admin_bar' ) ); + } + + /** + * Enhance network item. + * + * @since 0.0.1 + */ + public function enhance_network_admin_bar() { + + global $wp_admin_bar; + + // Show only when the user has at least one site, or they're a super admin. + if ( ! isset( $wp_admin_bar->user->blogs ) || count( $wp_admin_bar->user->blogs ) < 1 ) { + return; + } + + // Since WP version 3.7 is the plugin link in core. + // Return, if is active. + /** + * Toolbar API class. + * + * @var WP_Admin_Bar $wp_admin_bar + */ + $wp_admin_bar_nodes = (array) $wp_admin_bar->get_nodes(); + + if ( array_key_exists( 'network-admin-p', $wp_admin_bar_nodes ) ) { + return; + } + + // Add a link to the Network > Plugins page. + $wp_admin_bar->add_node( + array( + 'parent' => 'network-admin', + 'id' => 'network-admin-plugins', + 'title' => __( 'Plugins' ), + 'href' => network_admin_url( 'plugins.php' ), + ) + ); + } + + /** + * Enhance each blog menu in network admin bar. + * + * Add new 'Manage Comment' Item with count of comments, there wait for moderate + * + * @since 0.0.1 + */ + public function enhance_network_blog_admin_bar() { + + /** + * The Toolbar API class. + * + * @var WP_Admin_Bar $wp_admin_bar + */ + global $wp_admin_bar; + + if ( ! isset( $wp_admin_bar->user->blogs ) ) { + return; + } + + foreach ( (array) $wp_admin_bar->user->blogs as $blog ) { + + switch_to_blog( $blog->userblog_id ); + + $menu_id = 'blog-' . $blog->userblog_id; + + if ( current_user_can( 'edit_posts' ) ) { + + $wp_admin_bar->remove_node( $menu_id . '-c' ); + + $awaiting_mod = wp_count_comments(); + $awaiting_mod = $awaiting_mod->moderated; + + $title = __( 'Manage Comments' ) + . '<span class="ab-label awaiting-mod pending-count count-' + . (int) $awaiting_mod . '" style="margin-left:.2em">' . number_format_i18n( $awaiting_mod ) . '</span>'; + + $awaiting_title = esc_attr( + sprintf( + _n( + '%s comment awaiting moderation', + '%s comments awaiting moderation', + $awaiting_mod + ), number_format_i18n( $awaiting_mod ) + ) + ); + + $wp_admin_bar->add_menu( + array( + 'parent' => $menu_id, + 'id' => $menu_id . '-comments', + 'title' => $title, + 'href' => admin_url( 'edit-comments.php' ), + 'meta' => array( 'title' => $awaiting_title ), + ) + ); + + } + + restore_current_blog(); + + } + } + +} // end class diff --git a/wp-content/plugins/multisite-enhancements/inc/autoload/class-change-footer-text.php b/wp-content/plugins/multisite-enhancements/inc/autoload/class-change-footer-text.php new file mode 100755 index 000000000..371eb4633 --- /dev/null +++ b/wp-content/plugins/multisite-enhancements/inc/autoload/class-change-footer-text.php @@ -0,0 +1,141 @@ +<?php +/** + * Change/Enhance the admin footer text with RAM, SQL Queries and RAM version in Footer. + * + * Only for Admins + * + * Use the follow filter hooks for different changes + * Use the filter hook to change capability to view the new text on admin footer + * - Hook: multisite_enhancements_admin_footer_text_capability + * - default is: manage_options + * Reset of text from wp default + * - Hook: multisite_enhancements_reset_admin_footer_text + * - default is: TRUE + * Change content if admin footer text + * - Hook: multisite_enhancements_admin_footer_text + * - default is: Blog-Name, RAM, SQL, RAM Version + * + * @since 2013-07-23 + * @version 2016-10-28 + * @package WordPress + */ + +add_action( 'init', array( 'Multisite_Change_Footer_Text', 'init' ) ); + +/** + * Class Multisite_Change_Footer_Text + */ +class Multisite_Change_Footer_Text { + + /** + * Define the capability to view the new admin footer text. + * + * @since 0.0.2 + * @var String + */ + static protected $capability = 'manage_options'; + + /** + * Filter to reset admin footer message. + * + * @since 0.0.2 + * @var Boolean + */ + static protected $reset_footer_text = TRUE; + + /** + * Initialize the class. + */ + public static function init() { + + $class = __CLASS__; + if ( empty( $GLOBALS[ $class ] ) ) { + $GLOBALS[ $class ] = new $class; + } + } + + /** + * Init function to register all used hooks. + * + * Use the filter hook to change capability to view the new text on admin footer + * Hook: multisite_enhancements_admin_footer_text_capability + * + * @since 0.0.2 + */ + public function __construct() { + + /** + * Use this filter to change capability to view the new text on admin footer. + * + * @type string + */ + $capability = apply_filters( + 'multisite_enhancements_admin_footer_text_capability', + self::$capability + ); + + // Get default content for non admins. + if ( current_user_can( $capability ) ) { + add_action( 'admin_footer_text', array( $this, 'get_footer_text' ) ); + } + } + + /** + * Change admin footer text. + * + * Use the two different filters for change + * Reset of text from wp default - Hook: multisite_enhancements_reset_admin_footer_text + * Change content - Hook: multisite_enhancements_admin_footer_text + * + * @since 0.0.2 + * + * @param String $footer_text The string for the footer to inform the users. + * + * @return String + */ + public function get_footer_text( $footer_text ) { + + /** + * Filter to reset admin footer message. + * + * @type string + */ + if ( apply_filters( + 'multisite_enhancements_reset_admin_footer_text', + self::$reset_footer_text + ) + ) { + $footer_text = ''; + } + + // Set string of admin area. + $blogname = get_bloginfo( 'name' ); + if ( is_network_admin() ) { + $blogname = ' ' . esc_html( $GLOBALS[ 'current_site' ]->site_name ); + } + + $footer_text .= wp_html_excerpt( $blogname, 40, __( '…', 'multisite-enhancements' ) ); + $footer_text .= ' • <abbr title="' + . esc_html__( 'Random-access memory', 'multisite-enhancements' ) + . '">' . esc_html__( 'RAM', 'multisite-enhancements' ) . '</abbr> ' + . number_format_i18n( + memory_get_peak_usage( true ) / 1024 / 1024, + 1 + ) + . esc_html__( '/', 'multisite-enhancements' ) . WP_MEMORY_LIMIT; + $footer_text .= ' • <abbr title="' . esc_html__( 'Structured Query Language', + 'multisite-enhancements' ) . '">' . esc_html__( 'SQL', + 'multisite-enhancements' ) . '</abbr> ' . $GLOBALS[ 'wpdb' ]->num_queries; + $footer_text .= ' • <abbr title="' . esc_html__( 'Version of PHP (Hypertext Preprocessor)', + 'multisite-enhancements' ) . '">' . esc_html__( 'PHPv', + 'multisite-enhancements' ) . '</abbr> ' . phpversion(); + + /** + * Filter for change content form other source. + * + * @type string + */ + return apply_filters( 'multisite_enhancements_admin_footer_text', $footer_text ); + } + +} // end class diff --git a/wp-content/plugins/multisite-enhancements/inc/autoload/class-core.php b/wp-content/plugins/multisite-enhancements/inc/autoload/class-core.php new file mode 100755 index 000000000..5893d30ec --- /dev/null +++ b/wp-content/plugins/multisite-enhancements/inc/autoload/class-core.php @@ -0,0 +1,155 @@ +<?php +/** + * Core methods, there will be used. + * + * @since 2013-07-24 + * @version 2016-10-28 + * @package WordPress + */ + +add_action( 'init', array( 'Multisite_Core', 'init' ) ); + +/** + * Class Multisite_Core + */ +class Multisite_Core { + + /** + * Init the class. + */ + public static function init() { + + $class = __CLASS__; + if ( empty( $GLOBALS[ $class ] ) ) { + $GLOBALS[ $class ] = new $class; + } + } + + /** + * Returns an array of arrays containing information about each public blog hosted on this WPMU install. + * + * Only blogs marked as public and flagged as safe (mature flag off) are returned. + * + * @param Integer $start The first blog to return in the array. + * @param Integer $num The number of blogs to return in the array (thus the size of the array). + * Setting this to string 'all' returns all blogs from $start. + * @param Boolean $details Get also Postcount for each blog, default is False for a better performance. + * @param Integer $expires Time until expiration in seconds, default 86400s (1day). + * + * @return array Returns an array of arrays each representing a blog. + * Details are represented in the following format: + * blog_id (integer) ID of blog detailed. + * domain (string) Domain used to access this blog. + * path (string) Path used to access this blog. + * postcount (integer) The number of posts in this blog. + */ + public static function get_blog_list( $start = 0, $num = 10, $details = FALSE, $expires = 86400 ) { + + // Since WP version 4.6.0 is a new function inside the core to get this value. + if ( function_exists( 'get_sites' ) ) { + return get_sites( + array( + 'number' => $num, + ) + ); + } + + // For WordPress smaller version 4.6.0, available since WordPress 3.7. + if ( function_exists( 'wp_get_sites' ) ) { + return wp_get_sites( + array( + 'limit' => $num, + ) + ); + } + + // Get blog list from cache. + $blogs = get_site_transient( 'multisite_blog_list' ); + + // For debugging purpose. + if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) { + $blogs = FALSE; + } + + if ( FALSE === $blogs ) { + + global $wpdb; + + // Add limit for select. + $limit = "LIMIT $start, $num"; + if ( 'all' === $num ) { + $limit = ''; + } + + /** @noinspection SqlDialectInspection */ + /** @noinspection SqlNoDataSourceInspection */ + $blogs = $wpdb->get_results( + $wpdb->prepare( + " + SELECT blog_id, domain, path + FROM $wpdb->blogs + WHERE site_id = %d + AND public = '1' + AND archived = '0' + AND mature = '0' + AND spam = '0' + AND deleted = '0' + ORDER BY registered ASC + $limit + ", $wpdb->siteid + ), + ARRAY_A + ); + + // Set the Transient cache. + set_site_transient( 'multisite_blog_list', $blogs, $expires ); + } + + // Only if usable, set via var. + if (TRUE === $details ) { + + /** + * Get data to each site in the network. + * + * @var array $blog_list + */ + $blog_list = get_site_transient( 'multisite_blog_list_details' ); + + // For debugging purpose. + if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) { + $blog_list = FALSE; + } + + if ( FALSE === $blog_list ) { + + global $wpdb; + /** + * The data details of each site of the network. + * + * @var array $blog_details + */ + foreach ( (array) $blogs as $blog_details ) { + $blog_list[ $blog_details[ 'blog_id' ] ] = $blog_details; + $blog_list[ $blog_details[ 'blog_id' ] ][ 'postcount' ] = $wpdb->get_var( + "SELECT COUNT(ID) + FROM " . $wpdb->get_blog_prefix( $blog_details[ 'blog_id' ] ) . "posts + WHERE post_status='publish' + AND post_type='post'" + ); + } + + // Set the Transient cache. + set_site_transient( 'multisite_blog_list_details', $blog_list, $expires ); + } + unset( $blogs ); + $blogs = $blog_list; + } + + if ( FALSE === is_array( $blogs ) ) { + return array(); + } + + return $blogs; + } + +} // end class diff --git a/wp-content/plugins/multisite-enhancements/inc/autoload/class-filtering-plugins.php b/wp-content/plugins/multisite-enhancements/inc/autoload/class-filtering-plugins.php new file mode 100644 index 000000000..91db91fb3 --- /dev/null +++ b/wp-content/plugins/multisite-enhancements/inc/autoload/class-filtering-plugins.php @@ -0,0 +1,51 @@ +<?php +/** + * Add simple javascript to filter the plugin list on network and single plugin page of WordPress back end. + * + * @since 2015-11-29 + * @package WordPress + */ + +add_action( 'admin_init', array( 'Filtering_Plugins', 'init' ) ); + +/** + * Class Filtering_Plugins + */ +class Filtering_Plugins { + + /** + * Init the class. + */ + public static function init() { + + $class = __CLASS__; + if ( empty( $GLOBALS[ $class ] ) ) { + $GLOBALS[ $class ] = new $class; + } + } + + /** + * Filtering_Plugins constructor. + */ + public function __construct() { + + add_action( 'admin_print_scripts-plugins.php', array( $this, 'enqueue_script' ) ); + } + + /** + * Enqueue scripts. + */ + public function enqueue_script() { + + $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min'; + + wp_register_script( + 'me_filtering_plugins', + plugins_url( '/inc/assets/js/filtering-plugins' . $suffix . '.js', MULTISITE_ENHANCEMENT_BASE ), + array( 'jquery' ), + '2015-11-29', + TRUE + ); + wp_enqueue_script( 'me_filtering_plugins' ); + } +} diff --git a/wp-content/plugins/multisite-enhancements/inc/autoload/class-filtering-themes.php b/wp-content/plugins/multisite-enhancements/inc/autoload/class-filtering-themes.php new file mode 100644 index 000000000..57daf730b --- /dev/null +++ b/wp-content/plugins/multisite-enhancements/inc/autoload/class-filtering-themes.php @@ -0,0 +1,51 @@ +<?php +/** + * Add simple javascript to filter the theme list on network and single site theme page of WordPress back end. + * + * @since 2016-10-05 + * @package WordPress + */ + +add_action( 'admin_init', array( 'Filtering_Themes', 'init' ) ); + +/** + * Class Filtering_Themes + */ +class Filtering_Themes { + + /** + * Init the class. + */ + public static function init() { + + $class = __CLASS__; + if ( empty( $GLOBALS[ $class ] ) ) { + $GLOBALS[ $class ] = new $class; + } + } + + /** + * Filtering_Plugins constructor. + */ + public function __construct() { + + add_action( 'admin_print_scripts-themes.php', array( $this, 'enqueue_script' ) ); + } + + /** + * Enqueue scripts. + */ + public function enqueue_script() { + + $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min'; + + wp_register_script( + 'me_filtering_plugins', + plugins_url( '/inc/assets/js/filtering-themes' . $suffix . '.js', MULTISITE_ENHANCEMENT_BASE ), + array( 'jquery' ), + '2016-10-05', + TRUE + ); + wp_enqueue_script( 'me_filtering_plugins' ); + } +} diff --git a/wp-content/plugins/multisite-enhancements/inc/autoload/class-multisite-add-new-plugin.php b/wp-content/plugins/multisite-enhancements/inc/autoload/class-multisite-add-new-plugin.php new file mode 100755 index 000000000..29d9213de --- /dev/null +++ b/wp-content/plugins/multisite-enhancements/inc/autoload/class-multisite-add-new-plugin.php @@ -0,0 +1,58 @@ +<?php +/** + * Enables an 'Add New' link under the Plugins menu for Network admins. + * + * @since 2013-07-19 + * @version 2016-01-15 + * @package WordPress + */ + +add_action( 'init', array( 'Multisite_Add_New_Plugin', 'init' ) ); + +/** + * Class Multisite_Add_New_Plugin + */ +class Multisite_Add_New_Plugin { + + /** + * Init the class. + */ + public static function init() { + + $class = __CLASS__; + if ( empty( $GLOBALS[ $class ] ) ) { + $GLOBALS[ $class ] = new $class; + } + } + + /** + * Init function to register all used hooks. + * + * @since 0.0.1 + */ + public function __construct() { + + // Only on each blog, not network admin. + if ( is_network_admin() ) { + return; + } + + add_action( 'admin_menu', array( $this, 'add_plugins_page' ) ); + } + + /** + * Add menu item. + * + * @since 0.0.1 + */ + public function add_plugins_page() { + + add_plugins_page( + __( 'Add New' ), + __( 'Add New' ), + 'manage_network', + 'plugin-install.php' + ); + } + +} // end class diff --git a/wp-content/plugins/multisite-enhancements/inc/autoload/core.php b/wp-content/plugins/multisite-enhancements/inc/autoload/core.php new file mode 100755 index 000000000..3e67445e3 --- /dev/null +++ b/wp-content/plugins/multisite-enhancements/inc/autoload/core.php @@ -0,0 +1,45 @@ +<?php +/** + * Core functions, there was missed in WP Core for use with Multisite. + * + * Hint: Since WordPress version 3.7.0 use the function 'wp_get_sites()', + * Hint again: Since WordPress version 4.6.0 is the function 'get_sites()' the right alternative, + * a alternative inside the core of WP + * + * @since 2013-07-24 + * @version 2016-10-05 + * @package WordPress + */ + +if ( ! function_exists( 'get_blog_list' ) ) { + + /** + * Returns an array of arrays containing information about each public blog hosted on this WPMU install. + * + * Only sites marked as public and flagged as safe (mature flag off) are returned. + * + * @param Integer $start The first blog to return in the array. + * @param Integer $num The number of sites to return in the array (thus the size of the array). + * Setting this to string 'all' returns all sites from $start. + * @param Integer $expires Time until expiration in seconds, default 86400s (1day). + * + * @return array|bool + * Details are represented in the following format: + * blog_id (integer) ID of blog detailed. + * domain (string) Domain used to access this blog. + * path (string) Path used to access this blog. + * postcount (integer) The number of posts in this blog. + */ + function get_blog_list( $start = 0, $num = 10, $expires = 86400 ) { + if ( ! is_multisite() ) { + return false; + } + + if ( ! class_exists( 'Multisite_Core' ) ) { + require_once __DIR__ . '/class-core.php'; + new Multisite_Core(); + } + + return Multisite_Core::get_blog_list( $start, $num, $expires ); + } +} // end if fct exist diff --git a/wp-content/plugins/multisite-enhancements/multisite-enhancements.php b/wp-content/plugins/multisite-enhancements/multisite-enhancements.php new file mode 100644 index 000000000..391fd7f81 --- /dev/null +++ b/wp-content/plugins/multisite-enhancements/multisite-enhancements.php @@ -0,0 +1,161 @@ +<?php # -*- coding: utf-8 -*- +/** + * Plugin Name: Multisite Enhancements + * Description: Enhance Multisite for Network Admins with different topics + * Plugin URI: https://github.com/bueltge/WordPress-Multisite-Enhancements + * Version: 1.5.1 + * Author: Frank Bültge + * Author URI: https://bueltge.de + * License: GPLv2+ + * License URI: ./assets/LICENSE + * Text Domain: multisite-enhancements + * Domain Path: /languages + * Network: true + */ + +! defined( 'ABSPATH' ) && exit; + +add_filter( 'plugins_loaded', array( 'Multisite_Enhancements', 'get_object' ) ); + +/** + * Class Multisite_Enhancements. + * Plugin wrapper to list as plugin in WordPress environment and load all necessary files. + * Use the filter hook 'multisite_enhancements_autoload' to unset classes, there is not necessary for you. + */ +class Multisite_Enhancements { + + /** + * Define folder, there have inside the autoload files. + * + * @since 0.0.1 + * @var String + */ + static protected $file_base = ''; + + /** + * The class object. + * + * @since 0.0.1 + * @var String + */ + static protected $class_object; + + /** + * Load the object and get the current state. + * + * @since 0.0.1 + * @return String $class_object + */ + public static function get_object() { + + if ( NULL === self::$class_object ) { + self::$class_object = new self; + } + + return self::$class_object; + } + + /** + * Init function to register all used hooks. + * + * @since 0.0.1 + */ + public function __construct() { + + // This check prevents using this plugin not in a multisite. + if ( function_exists( 'is_multisite' ) && ! is_multisite() ) { + add_filter( 'admin_notices', array( $this, 'error_msg_no_multisite' ) ); + + return; + } + + $this->load_translation(); + + // Since 2015-08-18 only PHP 5.3, use now __DIR__ as equivalent to dirname(__FILE__). + self::$file_base = __DIR__ . '/inc'; + self::load(); + } + + /** + * Load translation file. + * + * @since 2016-10-23 + */ + public function load_translation() { + + load_plugin_textdomain( + 'multisite-enhancements', + FALSE, + basename( __DIR__ ) . '/languages/' + ); + } + + /** + * Display an Admin Notice if multisite is not active. + * + * @since 0.0.1 + */ + public function error_msg_no_multisite() { + + deactivate_plugins( plugin_basename( __FILE__ ) ); + ?> + <div class="error"> + <p> + <?php esc_html_e( + 'The plugin only works in a multisite installation. See how to install a multisite network:', + 'multisite-enhancements' + ); ?> + <a href="http://codex.wordpress.org/Create_A_Network" title="<?php esc_html_e( + 'WordPress Codex: Create a network', 'multisite-enhancements' + ); ?>"> + <?php esc_html_e( 'WordPress Codex: Create a network', 'multisite-enhancements' ); ?> + </a> + </p> + </div> + + <div class="updated notice"> + <p> + <?php echo wp_kses( + __( 'Plugin <strong>deactivated</strong>.', 'multisite-enhancements' ), + array( + 'strong' => array(), + ) + ); ?> + </p> + </div> + <?php + } + + /** + * Load all files in folder inc. + * Use the filter hook 'multisite_enhancements_autoload' to unset classes, there is not necessary for you. + * + * @since 0.0.1 + */ + public static function load() { + + $file_base = self::$file_base; + define( 'MULTISITE_ENHANCEMENT_BASE', $file_base ); + + $autoload_paths = glob( "$file_base/autoload/*.php" ); + + foreach ( $autoload_paths as $classnames => $path ) { + $path_split = explode( DIRECTORY_SEPARATOR, $path ); + $class = end( $path_split ); + $autoload_files[$class] = $path; + } + + $autoload_files = (array) apply_filters( 'multisite_enhancements_autoload', $autoload_files ); + + // Load files. + foreach ( $autoload_files as $path ) { + /** + * Path of each file, that we load. + * + * @var string $path + */ + require_once $path; + } + } + +} // end class diff --git a/wp-content/plugins/multisite-enhancements/readme.txt b/wp-content/plugins/multisite-enhancements/readme.txt new file mode 100644 index 000000000..07c2f421b --- /dev/null +++ b/wp-content/plugins/multisite-enhancements/readme.txt @@ -0,0 +1,213 @@ +=== Multisite Enhancements === +Contributors: Bueltge, inpsyde +Tags: multisite, administration, admin bar, network, +Requires at least: 4.6 +Tested up to: 5.1 +Requires PHP: 5.6 +Stable tag: 1.5.1 +License: GPLv2 or later +License URI: http://www.gnu.org/licenses/gpl-2.0.html + +Enhance Multisite for Network Admins with different topics + +== Description == +When you work quite a bit with WordPress Multisites, sometimes you need more information or menu items. This plugin enhances the network area for super admins with useful functions. + +* Adds Blog and User ID in network view [more](http://wpengineer.com/2188/view-blog-id-in-wordpress-multisite/) +* Enables an 'Add New' link under the Plugins menu for Network admins +* Adds several useful items to the multisite 'Network Admin' admin bar +* On the network plugins page, shows which site has this plugin active +* On the network theme page, shows which blog has the theme active and is a Child theme +* Change Admin footer text for Administrators to view currently used RAM, SQL, RAM version fast +* Adds Favicon from theme folder to the admin area to easily identify the blog, use the `favicon.ico` file in the theme folder of the active theme in each blog +* Adds Favicon to each blog on the Admin Bar Item 'My Sites'. If you a like a custom path for each favicon, please see the [documentation](https://github.com/bueltge/WordPress-Multisite-Enhancements/wiki/Filter-Hook-for-Favicon-File-Path) for this feature. +* Removes also the 'W' logo and his sub-links in admin bar +* Adds the status to each site in the admin bar to identify fastly if the site has a `noindex` status and to see the external url. +* Handy ssl identifier to each site in network site view page. +* Add functions to be used in your install + * The function `get_blog_list()` is currently deprecated in the WP Core, but currently usable. The plugin checks this and gets an alternative in [`inc/autoload/core.php`](./inc/autoload/core.php) + * If you will develop with the alternative to this function from my source, then use the method `get_blog_list()` in class `Multisite_Core`. My source also use caching with the Transient API. More about the function in [`inc/autoload/class-core.php`](./inc/autoload/class-core.php). + * If you use WordPress version 3.7 and higher, then check the function `wp_get_sites()`, the new alternative function inside the core to get all sides inside the network. The function accepts a array with arguments, see the [description](http://wpseek.com/wp_get_sites/). + * But if you use WordPress 4.6 and higher then that new alternative ;) - `get_sites()` - is the current function to get all sites in the network. The helper method of this plugin `Multisite_Core::get_blog_list()` or the function `get_blog_list()` have all checks included. + +* Filter theme list to find your target fast. Works on single theme page and also network theme page. + += Crafted by Inpsyde = +The team at [Inpsyde](http://inpsyde.com/) is engineering the web and WordPress since 2006. + += Donation? = +You want to donate - we prefer a [positive review](https://wordpress.org/support/view/plugin-reviews/multisite-enhancements?rate=5#postform), nothing more. + +== Installation == + += Requirements = +* WordPress Multisite 3.0+ +* PHP 5.6*, newer PHP versions will work faster. (It should work also under PHP 5.3, but untested.) + += Installation = +* Use the installer via back-end of your install or ... + +1. Unpack the download-package +2. Upload the files to the `/wp-content/plugins/` directory +3. Activate the plugin through the 'Network/Plugins' menu in WordPress and hit 'Network Activate' +4. No options, no settings, it works + +== Screenshots == +1. Add Blog-ID on Sites +2. Add User-ID on Users +3. Add New link to install new plugin on each blog +4. Manage Comments with Counter on Admin Bar +5. On which blog is the plugin active +6. On which blog is the theme active +7. New Admin footer text +8. Favicon on Admin bar +9. Filter Themes + +== Other Notes == + +**Crafted by [Inpsyde](https://inpsyde.com) · The team is engineering the Web since 2006.** + += Hints, knowledge = +See also for helpful hints on the [wiki page](https://github.com/bueltge/wordpress-multisite-enhancements/wiki). +Especially the follow topics are interest: + +* [Filter Hook for Favicon File Path - Define your custom Favicon path](https://github.com/bueltge/WordPress-Multisite-Enhancements/wiki/Filter-Hook-for-Favicon-File-Path) +* [Large Network Problem](https://github.com/bueltge/wordpress-multisite-enhancements/wiki/Large-Network-Problem) + += Bugs, technical hints or contribute = +Please give me feedback, contribute and file technical bugs on this +[GitHub Repo](https://github.com/bueltge/WordPress-Multisite-Enhancements/issues), use Issues. + += License = +Good news, this plugin is free for everyone! Since it's released under the GPL, +you can use it free of charge on your personal or commercial blog. But if you enjoy this plugin, +you can thank me and leave a +[small donation](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=6069955 "Paypal Donate link") +for the time I've spent writing and supporting this plugin. +And I really don't want to know how many hours of my life this plugin has already eaten ;) + += Contact & Feedback = +The plugin is designed and developed by me [Frank Bültge](http://bueltge.de), [G+ Page](https://plus.google.com/+FrankBültge/about?rel=author) + +Please let me know if you like the plugin or you hate it or whatever ... +Please fork it, add an issue for ideas and bugs on the [Github Repository](https://github.com/bueltge/WordPress-Multisite-Enhancements). + += Disclaimer = +I'm German and my English might be gruesome here and there. +So please be patient with me and let me know of typos or grammatical parts. Thanks + +== Changelog == += 1.5.0 (2019-02-25) = +* Remove feature 'Networkmenu is now scrollable'. + += 1.5.0 (2019-02-24) = +* Networkmenu is now scrollable. +* More clearance for the message about inactive cache. +* Small php fixes. + += 1.4.3 (2018-05-17) = +* Fix undefined index Network on plugin list, #46 +* Fix small php notes. +* Fix the possibility to translate the footer message about RAM, SQL queries. +* Add fix to leave message for the parent theme in a single line. +* Add Ui change to list more as 4 themes in Theme usage overview. Probs @n-goncalves #44 + += 1.4.2 (2017-02-22) = +* Change syntax for usage of plugins, themes; probs @cfoellmann +* Count the usage in sites for plugins, themes; probs @cfoellmann +* Change of the autoloader, the removal of a function is now more solid. See [the wiki page](https://github.com/bueltge/wordpress-multisite-enhancements/wiki/Remove-features); probs @cfoellmann +* Added option to display or hide the list of sites if too big #44; probs @n-goncalves + += 1.4.1 (2017-08-10) = +* Added a change for initialization of the class to run also on php 5.3 installs. + += 1.4.0 (2017-07-23) = +* Adds handy ssl identifier to each site in network site view page. + += 1.3.8 (2017-02-23) = +* Fixed duplicated view on parent theme usage. +* Adds status text to a site, if is a archived site on plugin/theme list. + += 1.3.7 (2016-10-24) = +* Fix the usage of plugins for each site in the network on the plugin network view. +* Add helpers to remove transient caching for development, debugging, if `WP_DEBUG` is true. +* Fix markup error of missing closing tag in footer text. +* Fix markup error on comment admin bar menu item in each site item of the item 'My Sites'. +* Add possibility to translate the plugin. + += 1.3.6 (2016-10-07) = +* Switch to new core function `get_sites` +* Remove Plugin Search, now inside the core, since WP 3.6.0 +* Add Theme filter search to single and network theme page to find fast and simple the result. + += 1.3.5 (2016-05-30) = +* Performance: Change the function to get all sites of a user to set favicon. [#25](https://github.com/bueltge/wordpress-multisite-enhancements/issues/25) + += 1.3.4 (2016-05-19) = +* Fix value type for nodes from admin bar. +* Enhance the Multisite requirements check. + += 1.3.3 (2016-01-15) = +* Fix Blog Id enhancement, change filter type. +* Change different code topics for better performance and stability. + += 1.3.2 (2015-12-17) = +* Prevent PHP Warning. Props noelboss + += 1.3.1 (2015-12-03) = +* Enhance the external domain check for more exactly check, that's also work on root domain of multisite. Props Matt [Thread](https://wordpress.org/support/topic/main-blog-being-tagged-as-external-domain) + += 1.3.0 (2015-11-28) = +* Add new functionality to filter plugin list live. +* Improve status label filter `multisite_enhancements_status_label`, now with the parameters `$blogname` and `$blog`. + += 1.2.1 (2015-09-24) = +* Bugfix: Correction for the site icon topic. The functions "has_site_icon" and "get_site_icon_url" aren't compatible with multisites. Icon only displayed when on that blog, in network or other blog the WP logo showed. +* Enhancement: Check for active usage of admin bar before add favicon to Admin Bar. + += 1.2.0 (2015-09-03) = +* Add support for Favicon feature `wp_site_icon` since WP 4.3, probs [JoryHogeveen](https://github.com/JoryHogeveen) +* Add status label to each site in the admin bar, probs JoryHogeveen +* Codex changes +* Add hook `multisite_enhancements_autoload` to unset files, there not necessary on autoload, see also the [Wiki](https://github.com/bueltge/wordpress-multisite-enhancements/wiki) for more information + += 1.1.0 (2015-02-26) = +* Some modifications to plugin and theme admin columns for better performance and usage on Multisites with more as 100 blogs, plugins, themes [Issue #16](https://github.com/bueltge/wordpress-multisite-enhancements/pull/16) +* Code inspections +* Enhance the value to get sites inside the network form WordPress default 100 to 9999 +* Add hook `multisite_enhancements_sites_limit` to change this value, see [wiki page](https://github.com/bueltge/wordpress-multisite-enhancements/wiki/Large-Network-Problem) + += 1.0.7 (09/23/2014) = +* Code maintenance +* Add parameters for custom favicon, see [documentation](https://github.com/bueltge/WordPress-Multisite-Enhancements/wiki/Filter-Hook-for-Favicon-File-Path) + += 1.0.6 (09/13/2014) = +* Add check for child theme, that you fast see, if is a child and what is the parent inside the network view of themes + += 1.0.5 (05/15/2014) = +* Fix list of active plugin in plugin network view +* Add hook for custom favicon path, see [documentation](https://github.com/bueltge/WordPress-Multisite-Enhancements/wiki/Filter-Hook-for-Favicon-File-Path) + += 1.0.4 (04/27/2014) = +* Add break, if no plugin is active, fixed [Error in "Active In" column](http://wordpress.org/support/topic/error-in-active-in-column) + += 1.0.3 (03/09/2014) = +* Remove Super Admin check, that works the enhancements also on other roles. +* Add indicator for "Network Only" Plugins. +* Add Favicon Indicator also in Admin Bar on Front end side. + += 1.0.2 (02/03/2014) = + * Add Favicon in Admin Bar also in Front end + * Enhance style for favicon size + * Grammar fix in tags, readme + * Small changes for columns and 3.8 design + += 1.0.1 (01/03/2014) = + * Add CSS rule for new WP 3.8 back end design (mp6 plugin) + * Add more whitespace on the comment count in admin bar + * Enhance the filter to list active plugins [#1](https://github.com/bueltge/WordPress-Multisite-Enhancements/issues/1) + += 1.0.0 (10/31/2013) = + * First release on wordpress.org after different installs with different users + +For more information about changes see the commits on the [working repository](https://github.com/bueltge/WordPress-Multisite-Enhancements/commits/master). -- GitLab