Showing preview only (2,194K chars total). Download the full file or copy to clipboard to get everything.
Repository: AesopInteractive/lasso
Branch: master
Commit: f9ede4873bc4
Files: 127
Total size: 2.1 MB
Directory structure:
gitextract_5b5hx62o/
├── .gitattributes
├── .gitignore
├── .travis.yml
├── CONTRIBUTING.md
├── Gruntfile.js
├── LICENSE.txt
├── README.md
├── README.txt
├── admin/
│ ├── assets/
│ │ ├── css/
│ │ │ └── lasso-editor-settings.css
│ │ ├── js/
│ │ │ └── lasso-editor-settings.js
│ │ └── less/
│ │ ├── style.less
│ │ └── welcome.less
│ └── includes/
│ ├── EDD_SL_Plugin_Updater.php
│ ├── class-tgm-plugin-activation.php
│ ├── load_admin.php
│ └── menus/
│ ├── license.php
│ ├── settings.php
│ └── welcome.php
├── bootstrap.php
├── composer.json
├── includes/
│ ├── lasso_autoloader.php
│ ├── process/
│ │ ├── delete.php
│ │ ├── gallery.php
│ │ ├── map.php
│ │ ├── meta.php
│ │ ├── new_object.php
│ │ ├── revision.php
│ │ ├── save.php
│ │ ├── title_update.php
│ │ ├── tour.php
│ │ ├── update_object.php
│ │ └── upload_image.php
│ ├── sanatize.php
│ └── save_gallery.php
├── internal-api/
│ ├── api_action.php
│ ├── auth.php
│ ├── docs.md
│ ├── end_points.php
│ ├── find_data.php
│ └── route.php
├── languages/
│ ├── lasso-de_DE.mo
│ ├── lasso-de_DE.po
│ ├── lasso-es_ES.mo
│ ├── lasso-es_ES.po
│ ├── lasso-ko_KR.mo
│ ├── lasso-ko_KR.po
│ └── lasso.pot
├── lasso.php
├── package.json
├── public/
│ ├── assets/
│ │ ├── css/
│ │ │ ├── editus-table-edit-public.css
│ │ │ ├── lasso.css
│ │ │ └── style.css
│ │ ├── js/
│ │ │ ├── editus-table-edit-public.js
│ │ │ ├── lasso.js
│ │ │ ├── source/
│ │ │ │ ├── all-posts.js
│ │ │ │ ├── enter-editor.js
│ │ │ │ ├── modal-sizing.js
│ │ │ │ ├── post-settings.js
│ │ │ │ ├── process-gallery-opts.js
│ │ │ │ ├── process-gallery.js
│ │ │ │ ├── process-image-upload.js
│ │ │ │ ├── process-map.js
│ │ │ │ ├── process-new-post.js
│ │ │ │ ├── process-save-component.js
│ │ │ │ ├── process-save-meta.js
│ │ │ │ ├── process-save-title.js
│ │ │ │ ├── process-save.js
│ │ │ │ ├── process-wpimg.js
│ │ │ │ ├── revisions.js
│ │ │ │ ├── settings-live-editing.js
│ │ │ │ ├── settings-panel.js
│ │ │ │ ├── toolbar.js
│ │ │ │ ├── tour.js
│ │ │ │ ├── util--color-picker.js
│ │ │ │ ├── util--content-editable.js
│ │ │ │ ├── util--geo-complete.js
│ │ │ │ ├── util--imagesloaded.js
│ │ │ │ ├── util--rangy-classapplier.js
│ │ │ │ ├── util--rangy-core.js
│ │ │ │ ├── util--scrollbar.js
│ │ │ │ ├── util--slider.js
│ │ │ │ ├── util--sweet-alert.js
│ │ │ │ ├── util--tagit.js
│ │ │ │ ├── util--touch-punch.js
│ │ │ │ ├── util--undo.js
│ │ │ │ └── util--wp-api.js
│ │ │ └── tour.js
│ │ └── less/
│ │ ├── source/
│ │ │ ├── all-posts.less
│ │ │ ├── animations.less
│ │ │ ├── component-controls.less
│ │ │ ├── component-settings--gallery.less
│ │ │ ├── component-settings--map.less
│ │ │ ├── component-settings.less
│ │ │ ├── editor-controls.less
│ │ │ ├── editor.less
│ │ │ ├── featimg-controls.less
│ │ │ ├── fonts.css
│ │ │ ├── fonts.less
│ │ │ ├── form-controls.less
│ │ │ ├── mixins.css
│ │ │ ├── mixins.less
│ │ │ ├── mobile.less
│ │ │ ├── post-settings.less
│ │ │ ├── revisions.less
│ │ │ ├── scrollbar.less
│ │ │ ├── sidebar.less
│ │ │ ├── sweet-alert.less
│ │ │ ├── toolbar.less
│ │ │ ├── tour.less
│ │ │ ├── util--tags.less
│ │ │ ├── util--tooltips.less
│ │ │ ├── variables.css
│ │ │ ├── variables.less
│ │ │ └── wpimg-controls.less
│ │ └── style.less
│ └── includes/
│ ├── assets.php
│ ├── components.php
│ ├── editor-modules--gallery.php
│ ├── editor-modules.php
│ ├── helpers.php
│ ├── lasso.php
│ ├── option-engine.php
│ ├── register_meta_field.php
│ ├── tour.php
│ ├── underscore-templates.php
│ └── wrap-shortcodes.php
└── uninstall.php
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitattributes
================================================
.gitattributes export-ignore
.gitignore export-ignore
.travis.yml export-ignore
composer.json export-ignore
CONTRIBUTING.md export-ignore
Gruntfile.js export-ignore
package.json export-ignore
README.md export-ignore
tests/ export-ignore
================================================
FILE: .gitignore
================================================
.DS_Store
node_modules
.sass-cache
================================================
FILE: .travis.yml
================================================
language: php
sudo: false
php:
- 5.4
- 5.5
- 5.6
- hhvm
- nightly
# Specify versions of WordPress to test against
env:
- WP_VERSION=latest WP_MULTISITE=0
- WP_VERSION=latest WP_MULTISITE=1
- WP_VERSION=4.1 WP_MULTISITE=0
- WP_VERSION=4.0 WP_MULTISITE=0
- WP_VERSION=3.9.2 WP_MULTISITE=0
matrix:
include:
- php: 5.3
env: WP_VERSION=latest WP_MULTISITE=1
exclude:
- php: hhvm
env: WP_VERSION=3.9.2 WP_MULTISITE=0
- php: hhvm
env: WP_VERSION=4.0 WP_MULTISITE=0
notifications:
slack: aesop:GGeOu8QQeUGTkLvO1zTblBZv
================================================
FILE: CONTRIBUTING.md
================================================
This repository is for reporting Editus bugs only. This is not a support forum. If you need any help with Editus please email help@lasso.is with the same email that you purchased Editus with so that our system will identify you.
When submitting a pull request, test Editus with [Aesop Story Theme](https://github.com/AesopInteractive/aesop-story-theme), and make any pull requests against our latest release branch.
================================================
FILE: Gruntfile.js
================================================
'use strict';
module.exports = function(grunt) {
require('load-grunt-tasks')(grunt);
grunt.initConfig({
// watch our project for changes
watch: {
concat: {
files: ['public/assets/js/source/*'],
tasks:['concat:dist', 'uglify' ]
},
less: {
files: ['public/assets/less/**/*','admin/assets/less/**/*'],
tasks: ['less:coreLess','less:settingsLess']
},
livereload: {
options: { livereload: true },
files: ['public/assets/**/*','admin/assets/**/*', '**/*.html', '**/*.php', 'public/assets/img/**/*.{png,jpg,jpeg,gif,webp,svg}']
},
},
less: {
coreLess: {
options: {
paths: ['public/assets/less/*'],
cleancss:true
},
files: {
'public/assets/css/lasso.css': 'public/assets/less/style.less'
}
},
settingsLess: {
options: {
paths: ['admin/assets/less/*'],
cleancss:true
},
files: {
'admin/assets/css/lasso-editor-settings.css': 'admin/assets/less/style.less'
}
}
},
concat: {
dist: {
src: [
'public/assets/js/source/util--undo.js',
'public/assets/js/source/util--rangy-core.js',
'public/assets/js/source/util--rangy-classapplier.js',
'public/assets/js/source/util--content-editable.js',
'public/assets/js/source/util--scrollbar.js',
'public/assets/js/source/util--sweet-alert.js',
'public/assets/js/source/util--geo-complete.js',
'public/assets/js/source/util--imagesloaded.js',
'public/assets/js/source/util--slider.js',
'public/assets/js/source/util--touch-punch.js',
'public/assets/js/source/util--tagit.js',
'public/assets/js/source/enter-editor.js',
'public/assets/js/source/post-settings.js',
'public/assets/js/source/settings-panel.js',
'public/assets/js/source/settings-live-editing.js',
'public/assets/js/source/toolbar.js',
'public/assets/js/source/process-save.js',
'public/assets/js/source/process-gallery.js',
'public/assets/js/source/process-gallery-opts.js',
'public/assets/js/source/process-map.js',
'public/assets/js/source/process-image-upload.js',
'public/assets/js/source/process-save-component.js',
'public/assets/js/source/process-new-post.js',
'public/assets/js/source/process-save-title.js',
'public/assets/js/source/process-wpimg.js',
'public/assets/js/source/process-save-meta.js',
'public/assets/js/source/modal-sizing.js',
'public/assets/js/source/all-posts.js',
'public/assets/js/source/tour.js',
'public/assets/js/source/revisions.js'
],
dest: 'public/assets/js/lasso.js'
}
},
uglify: {
scripts: {
options: {
sourceMap: 'public/assets/js/lasso.js.map',
sourceMappingURL: 'lasso.js.map'
},
files: {
'public/assets/js/lasso.min.js': [
'public/assets/js/lasso.js'
]
}
}
},
makepot: {
target: {
options: {
domainPath: '/languages/', // Where to save the POT file.
exclude: ['build/.*'],
mainFile: 'lasso.php', // Main project file.
potFilename: 'lasso.pot', // Name of the POT file.
potHeaders: {
poedit: true, // Includes common Poedit headers.
'x-poedit-keywordslist': true // Include a list of all possible gettext functions.
},
type: 'wp-plugin', // Type of project (wp-plugin or wp-theme).
updateTimestamp: true, // Whether the POT-Creation-Date should be updated without other changes.
processPot: function( pot, options ) {
pot.headers['report-msgid-bugs-to'] = 'http://edituswp.com';
pot.headers['language'] = 'en_US';
return pot;
}
}
}
}
});
// register task
grunt.registerTask('default', ['watch']);
};
================================================
FILE: LICENSE.txt
================================================
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.
================================================
FILE: README.md
================================================
<table width="100%">
<tr>
<td align="left" width="70%">
<strong><a href="https://edituswp.com">Editus</a></strong><br />
Content creation and editing made simple
</td>
<td align="right" width="20%">
<a href="https://scrutinizer-ci.com/g/AesopInteractive/lasso/?branch=master">
<img src="https://scrutinizer-ci.com/g/AesopInteractive/lasso/badges/quality-score.png?b=master" alt="Build status">
</a>
</td>
</tr>
</table>
Editus is a commercial plugin available from https://edituswp.com. The plugin is hosted here on a public GitHub repository in order to better faciliate community contributions from developers and users alike. If you have a suggestion, a bug report, or a patch for an issue, feel free to submit it [here](https://github.com/AesopInteractive/lasso/issues). When submitting a pull request, test Editus with [Aesop Story Theme](https://github.com/AesopInteractive/aesop-story-theme), and make any pull requests against our latest release branch.
We do ask, however, that if you are using the plugin on a live site that you please purchase a valid license from the website. We cannot provide support to anyone who does not hold a valid license key.
Developer documentation can be found [here](https://github.com/AesopInteractive/lasso-documentation).
Pull requests for our documentation are [welcome](https://github.com/AesopInteractive/lasso-documentation/pulls).
## Requirements
Editus requires PHP 5.4 or above.
================================================
FILE: README.txt
================================================
=== Editus ===
Contributors: nphaskins, hyunster, michaelbeil
Plugin URI: https://edituswp.com
Requires at least: 3.5
Tested up to: 5.9
Stable tag: 1.5.1
Front-end editing and creation suite.
== Description ==
Front-end editing and creation suite.
== Changelog ==
= 1.5.1
* Support for Gutenberg list blocks
= 1.5.0
* Allowing the component pop up when using a keyboard without a mouse
= 1.4.9
* Improved compatibility with standard WP blocks
= 1.4.5
* NEW: Optional Paragraph component
* Further changes for the popup menu option
* Timeline Component Fix
= 1.4.3
* NEW: Text popup menu option
* A fix for custom post types
= 1.4.1
* A bug fix for simple image component
* NEW: Setting to change the placeholder text for new posts
= 1.4.0
* NEW: Custom Taxonomy Support Option
= 1.3.10
* Partial support for Gutenberg Cover Block
* Fixed the issue where the component controls were disappearing after saving
= 1.3.8
* Support for Gutenberg Image Block
* Fixed the issue that custom post types could not save custom fields
= 1.3.6
* The table component component right click menu now supports deleting the table
* Minor bug fixes
= 1.3.5
* Fix for simple image components
* New option to auto-prefix links with http://
= 1.3.4
* More non-Aesop image component options
= 1.3.3
* More non-Aesop image component options
* Support for More Tag
* Bug fixes
= 1.3.0
* NEW option to edit excerpts
* NEW new options for non-Aesop image components
= 1.2.9
* Bug fix for custom fields
= 1.2.8
* New optional table component
= 1.2.6
* UI customization fixes
= 1.2.5
* Fix for gallery create/update
* Allow component icon color customization
* Further Gutenberg compatibility work
= 1.2.4
* Fix for post settings
* Further Gutenberg compatibility work
= 1.2.3
* Fix for Aesop Image component
= 1.2.2
* PHP error fix
= 1.2.1
* Some JS fixes
= 1.2.0
* Support for multi-page posts
= 1.1.11
* Fix for multiple users trying to edit the same post at the same time
* Changed the behavior when the user deletes all text while using the editor.
= 1.1.10
* Styles fixes for mobile
= 1.1.9
* Now you can use Ctrl+SPACE to remove formatting from selected text.
= 1.1.8
* A bug fix in the component editor
= 1.1.7
* Support for WP Column and Spacer blocks.
= 1.1.6
* Fix for the map component.
= 1.1.5
* Fix for searching and auto save.
= 1.1.4
* Added a filter for the table html codes
= 1.1.3
* Fix for the "Click" UI setting
* Fix for custom fields
= 1.1.2
* Fix for multi-sites
= 1.1.1
* Added Icons for OL and UL for the toolbar
* German translation update
= 1.1.0
* NEW: OL and UL buttons to create lists.
= 1.0.9.2
* Fix for post locking
* Further AJAX changes
= 1.0.8
* Added the delete post button to mobile
= 1.0.7
* Fix for meta information saving
= 1.0.6
* Fix for Status saving and component insertion
= 1.0.5
* Fix for Aesop Gallery component
= 1.0.4
* Fix for draft posts when preview setting is required
= 1.0.3 =
* Added the delete post button
* Option to disable "Pending" status
* More changes for custom fields
= 1.0.2 =
* Changes for custom fields
= 1.0.1 =
* A new option setting to make links editable under the Edit mode
* Fixed a bug with multiple custom field entries
= 1.0.0 =
* Added new UI color customization options
* The Post Settings button is now available under the edit mode
* Fixed a bug with automatically entering the edit mode
* Copy and paste from MS Word strips the formatting
* Fixed a bug with the new post dialog
= 0.10.2.2 =
* Fixed a bug for non-English installation
= 0.10.2.1 =
* A "Contributor" can now create posts, just not publish
= 0.10.2.0 =
* Posts can be now set to "Pending"
= 0.10.1.1 =
* Some style fixes and internal changes
= 0.10.1.0 =
* Fixed some issues with BR tags
= 0.10.0.3 =
* UI and language file adjustment
= 0.10.0.0 =
* NEW UI option to automatically add a Component button to an empty paragraph
* Now Insert HTML box can accept a URL to embed, such as Youtube, Twitter etc.
= 0.9.18.4 =
* NEW UI option to switch from Drag-Drop to simple click for inserting components
* Fix for shortcode features on the insert HTML button
= 0.9.18.1 =
* A bug fix for Quote when ASE is not installed
* Some mobile fixes
= 0.9.18.0 =
* Post setting dialog fix for mobile
= 0.9.17.9 =
* An error fix for tags/categories
= 0.9.17.8 =
* Improved the Aesop Component properties handling
* Fixed some compatibility issues with certain themes.
= 0.9.17.6 =
* Fixed a style bug with the category editing.
= 0.9.17.5 =
* Fixed a bug with the Set Date codes.
* Changed the way PASTE works when the source is an HTML code.
= 0.9.17.4 =
* Fixed a bug that happens when the "Post" type is not selected under the "Enable for" options
* Added an option allow users to create new categories for posts.
= 0.9.17.3 =
* Changed the code to obtain the REST API root
= 0.9.17.2 =
* A JS bug fix.
= 0.9.17.1 =
* Added support for subtitle editing, for Aesop themes and the Subtitle (https://wordpress.org/plugins/subtitles/) plugin.
* Added an option to enable changing post dates using the Post Setting dialog
* Changed the AJAX code to hide the tour dialog
= 0.9.16.8 =
* Added Twitter handling codes
* Tour dialog uses REST API to save settings
* More social share plugins supported.
= 0.9.16.4 =
* Added lasso_wrap_shortcode_exceptions filter
* Fixed a bug where you could delete readonly elements by selecting and hitting
a key other than BS and DEL.
= 0.9.16.3 =
* Adjusted the content filter so it can filter shortcode content
= 0.9.16.2 =
* Added lasso_required_plugins filter
= 0.9.16.1 =
* A bug fix for multisite installation.
* A bug fix for page list.
* Added a way to add a filter to the save operation.
= 0.9.16.0 =
* Option to work with custom fields from frontend: (https://edituswp.com/editing-and-updating-custom-fields-from-frontend/)
* Improvement to the Undo behavior.
* A bug fix for shortcode handling
* Aesop event support
= 0.9.15.3 =
* More fix for custom post types
* New option to set the tag for the "Italic" style
= 0.9.15.2 =
* Fix for post delete
* Settings page update. New option to set the tag for the "Bold" style
* Added style to hide controls from printing
= 0.9.15.1 =
* Insert HTML button can now process 3rd party shortcodes
= 0.9.15.0 =
* The Post List dialog now displays draft posts
* The Post List dialog now displays custom post types properly.
= 0.9.14.2 =
* Editus tag classes now removed when saving
* Fixed support email
= 0.9.14.1 =
* Fixed a bug involving an empty post
* Fixed the icon file missing.
= 0.9.14.0 =
* Inserting H2 and H3 now also inserts p tags
* Fixed the tour dialog getting stuck at loading
* Fixed an issue where a component somtimes goes invisible after editing
* All contenteditable attributes removed before being saved
= 0.9.13.9 =
* Fixed a bug where shortcodes were not properly restored while saving using REST API
* Links are now always clickable.
= 0.9.13.7 =
* Aesop Video Component is now updated using AJAX
* Fix for the publish button
= 0.9.13.6 =
* Fixed an issue with saving post titles
* Aesop Content Component is now updated using AJAX
* UI fixes for small mobile devices
= 0.9.13.5 =
* Now Editus uses REST API to save posts when it can.
* REST API saving can also be disabled from the options.
* Addressed the issue where cursor jumps when pasting texts.
* Filters \' in components when edited. Filters it back to single apostrophe
= 0.9.13.3 =
* Fixed an issue with REST API codes causing an error during the loading of javascripts.
* Fixes for dialog text colors on certain themes.
* Dialog behaviors improved for mobile platforms.
= 0.9.13.2 =
* Fixed some styling issues for mobile.
* Fixed an issue in third party shortcode handling.
= 0.9.13.1 =
* Save removes html comments
= 0.9.13.0 =
* Added REST API v2 support
* Added codes to check if someone else is editing the post/page.
* Fixed a bug automatically entering Edit Mode when it shouldn't.
= 0.9.12.2 =
* Fixed some issues with "Read Only" item options
* Added an option to show the "Ignored Items" and keep them read only
= 0.9.12.0 =
* Aesop Hero Gallery has been added
* Fixed several issues with Gallery AJAX update
* When a new post is created Editus automatically enters Edit Mode
= 0.9.11.1 =
* Added an option to open a link a new browser tab.
= 0.9.11.0 =
* Now Gallery components update without having to reload the page, using AJAX.
* Also fixed a bug in gallery image update.
= 0.9.10.5 =
* Major new features in Beta:
* Added Color Text Button Options.
* Added Text Alignment Button Options.
= 0.9.10.2 =
* Added a new option to set non-editable elements that are parts of the post.
* Live update improvement for Video Component.
= 0.9.10.1 =
* Restored mobile support, for both phones and tablets
* A few more style fixes
= 0.9.10.0 =
* Fixed a FireFox bug where links could not be inserted
* Fixed a bug involving texts without any tags, resulting in the first lines disappearing
* Further style fixes
* New components shows setting dialogs when inserted for more intuitive user interface
* Added Auto Save option
* Disabled for mobile devices for now.
* Added Aesop Gallery Pop support
= 0.9.9.10 =
* Fixed the error reporting for AJAX calls
* Fixed the short code wrapping for non core Aesop components
* Fixed a bug with creating gallery
= 0.9.9.9 =
* replaced the deprecated JQuery calls to live()
= 0.9.9.8 =
* fixed a bug in the shortcode saving codes
* some form style and color adjustments
= 0.9.9.7 =
* added the following filter:
lasso_user_can_filter
* fixed a bug in adding a custom type post
= 0.9.9.6 =
* added the following hooks:
lasso_title_class
lasso_content_class
lasso_featured_image_class
lasso_dont_save
* Tour dialog loading code has been changed.
= 0.9.9.5 =
* multi-site menu restored
* added an option to specify gallery name while creating a new gallery.
= 0.9.9.3 =
* fixed unsaved data check
* swapping gallery updates the images in the gallery sidebar
* added button to create gallery to the gallery sidebar.
= 0.9.9.1 =
* fixed some styling issues where edit boxes and some buttons were not readable under certain themes
* fixed the issue where featured images were not updated in the post settings dialog box
* Editus now auto-detects article class if it's .entry-content
* Editus now auto-detects title class if it's .entry-header
* most short codes are now preserved (props Rouven Hurling)
* multi-site menu has been changed (props Philipp Stracker)
* post type issue with non-english sites fixed (props Philipp Stracker)
= 0.9.8.2 =
* fixed references to lasso.is
= 0.9.8.1 = Oct 8 2015 =
* fixed a capability issue that was allowing contributors to edit other users posts
= 0.9.8 = Aug 14 2015
* renamed Lasso to Editus
= 0.9.7 = July 30 2015
* updated TGM Plugin Activation to latest (props Ahmad Awais)
* improved live editing video source switching in Video Component
* added dismissible license notices if license is not supplied, expired, or invalid
* fixed a capability issue with saving that was introduced with WordPress 4.2.3 (props Josh Polluck)
= 0.9.6 = June 30 2015
* added the ability to access and restore post and page revisions
* fixed a bug introduced on the last update with new posts/pages being duplicated when created
* fixed authors not being able to publish posts
* fixed a bug with Lasso Meta API not saving
= 0.9.5 = June 17 2015
* added ability to search posts and pages within the all posts modal
* added abilty to choose post type to create within new post creation modal
* component now slides into view on settings click
* fixed bug with video component not switching providers
* fixed bug with galleries not saving gallery images properly
* improved Meta API for developers wishing to integrate within Lassos post settings
* mobile style improvement - props @peiche
= 0.9.4.1 = May 28th 2015
* fixed bug with automatic updates - props @pippinsplugins
* fixed bug with admins not seeing all posts in addition to their own
= 0.9.4 = May 26 2015
* WARNING - PHP 5.4 or higher required!!
* added ability to access and delete posts and pages (and custom post types with a filter) from the front-end (requires the WP REST API plugin). If the user is an Author or Contributor they will only be shown their posts or pages.
* added ability to add a post from anywhere on the site
* added ability to set featured image within settings modal if current theme supports post thumbnails
* added ability to add categories and tags within settings modal
* added CMD + S hot key to save post while in editor
* added a close button to exit the editor
* added a new API to allow third-party addons to add new settings modals (beta). They appear as a tab and work with only a filter. This is in preparation for releasing ACF, CMB2, and Ninja Forms integration addons.
* added Canvas and Exposure themes to automatic theme support
* fixed bug with tour hide not calculating correctly
* fixed bug with Author or Contributor roles not being able to put a post in draft
* fixed options not being cleaned up on uninstall
* improved automatic theme support means supported themes work out of the box with no setup
* improved user interface colors to better match WordPress design patterns
* improved drag and drop detection between paragraphs
* improved toolbar width logic - props @peiche
* improved CSS selector performance
* replaced tour GIFs with images
= 0.9.3 = April 26th 2015
* fixed .entry-content being applied as a default Article CSS Class
* allow escaping the warning modal that warns users if no Article CSS class is present
* fixed image control setting with images inserted without Aesop Story Engine active
* fixed featured image not being saved
= 0.9.2 = April 14th 2015
* fixed links not working if editor was active but not in use
* massive internal rewrite to use a custom API for processing requests instead of hitting admin-ajax. This increases the saving speed and ensures compatibility for very large WordPress installations and Enterprise users. Tested and working on WordPress MU, Apache, Nginx , and HHVM.
= 0.9.1.1 = March 28th 2015
* fixed a js error that happened if an uploaded media item wasn't large enough to be resized to large
= 0.9.1 = March 27th 2015
* added ability to insert standard WordPress images and blockquote. If Aesop Story Engine is activated, it replaces these with Aesop Story Engine's story components.
* fixed css class names in toolbar components not being namespaced
* better iOS compatibility with editing toolbar
* removed H2 and H3 buttons from the insert HTML area if Extended Toolbar is selected as its redundant(Extended Toolbar puts H2, and H3 buttons into the toolbar)
* clarified in the instructions that the article class name in the settings should include the preceding dot
* if an embedded Tweet is in the content, we now remove it when you enter the editor so it's not save as HTML. In a future update, we plan to actually have some type of live ombed parsing system. This is a good fix for the time being.
* prepended a ul class to ul.editor-controls and ul.editor-component-controls as well as set letter-spacing to 0 in hopes of clearing up theme CSS conflicting with Lasso CSS. Normally this is bad practice (ul.this), but it's better than applying !important.
= 0.9 = March 21st 2015
* fixed a capability issue where contributors were allowed to publish posts
* class visibility methods
= 0.8.8 = March 19th 2015
* added an alert that pops up if the user tries to use the editor but hasn't added the required Article Class in order to use Lasso
* added all Aesop built themes to automatically supported themes list
* updated pot file
= 0.8.7 = March 16th 2015
* added a new option that lets you list CSS classes of items to ignore on save. This makes Lasso compatible wity 99.99% of all WordPress themes
= 0.8.6 = March 12th 2015
* new pre-flight function to check to ensure plugin settings are configured
* added automatic theme support for WordPress core themes and UpThemes
* added a new define define('LASSO_AGENCY_MODE') which removes the license page and links out to Lasso website
* added a new tab for Lasso to hold the status page, license page, and settings
* added new license menu page in preperation of the public launch of this plugin
* fixed an issue with the height in the Tour slider sometimes not calculating correctly
* fixed a permission issue where a user was allowed to edit another users posts. we were using edit_posts and switched to edit_post
= 0.8.5 = March 8th 2015
* misc bug fixes
* removed the "url helper" field for creating new posts as it was confusing some users
* added helper text to the field for creating new posts as a better visual guide
* new activation welcome screen in WordPress
* fixed the content component from not correctly saving
* added two actions: lasso_editor_controls_before && lasso_editor_controls_after
* added two css classes that get applied to the body when a featured thumbnail is added or removed : lasso-post-thumb-added && lasso-post-thumb-removed
================================================
FILE: admin/assets/css/lasso-editor-settings.css
================================================
.lasso--animate__spin{-webkit-animation:spin 2s infinite linear;animation:spin 2s infinite linear}.not-visible{opacity:0;filter:alpha(opacity=0);display:none;-webkit-transition:opacity .2s ease;-moz-transition:opacity .2s ease;transition:opacity .2s ease}.lasso--welcome{max-width:600px;margin:20px auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.lasso--welcome *{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.lasso--welcome p{font-size:15px}.lasso--welcome .lasso--welcome__steps{padding:0;list-style-type:none;margin:0 auto}.lasso--welcome .lasso--welcome__steps li{padding:25px;background:#fff;border:1px solid #d9d9d9;border-radius:5px;text-align:center;position:relative;margin-top:-25px;margin-bottom:100px}.lasso--welcome .lasso--welcome__steps li:before{font-family:Dashicons;color:#fff;padding:14px 27px 15px 14px;width:22px;font-size:36px;border-radius:100%;text-align:center;position:absolute;top:-33px;left:0;right:0;margin:0 auto;height:34px;line-height:37px}.lasso--welcome .lasso--welcome__steps li.info:before{content:'\f348';background:#2bc2ff}.lasso--welcome .lasso--welcome__steps li.success:before{content:'\f147';background:#4da34d}.lasso--welcome .lasso--welcome__steps li.error:before{content:'\f227';background:#d9534f}.lasso--welcome .lasso--welcome__steps li p{margin-bottom:0}.lasso--welcome .lasso--welcome__steps li h3{margin-bottom:5px}.lasso--welcome .lasso--welcome__top{text-align:center;margin-bottom:100px}.lasso--welcome .lasso--welcome__top:before,.lasso--welcome .lasso--welcome__top:after{content:" ";display:table}.lasso--welcome .lasso--welcome__top:after{clear:both}.lasso--welcome .lasso--welcome__top img{max-width:150px;margin:0 auto;border-radius:3px}.lasso--welcome .lasso--welcome__top h1+p{font-style:italic}.lasso--welcome .lasso--welcome__social{list-style:none;margin:0;padding:7px 0;border-top:1px solid #d9d9d9;border-bottom:1px solid #d9d9d9}.lasso--welcome .lasso--welcome__social:before,.lasso--welcome .lasso--welcome__social:after{content:" ";display:table}.lasso--welcome .lasso--welcome__social:after{clear:both}.lasso--welcome .lasso--welcome__social li{display:inline-block;line-height:1;margin:0}.lasso--welcome .lasso--welcome__social a{padding:2px 6px;display:block;text-decoration:none;color:inherit;line-height:1.5;font-weight:700}.lasso--welcome .lasso--welcome__social a:hover{color:#007aab;text-decoration:none}.lasso--welcome .lasso--welcome__social a i{font-size:16px;top:2px;line-height:19px;color:#007aab}.lasso--form-settings{max-width:500px;padding:20px;background:#fff;border-radius:5px;border:1px solid #cdcdcd;position:relative}.lasso--form-settings *{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.lasso--form-settings:before,.lasso--form-settings:after{content:" ";display:table}.lasso--form-settings:after{clear:both}.lasso--form-settings .iris-picker{box-sizing:initial}.lasso--form-settings .iris-picker *{box-sizing:inherit}.lasso--form-settings .lasso-editor-settings--option-wrap{margin-bottom:25px;margin-left:15px}.lasso--form-settings .lasso-editor-settings--option-wrap.last .lasso-editor-settings--option-inner{border-bottom:0;padding-bottom:0}.lasso--form-settings .lasso-editor-settings--option-inner{border-bottom:1px solid #e7e7e7;padding-bottom:25px}.lasso--form-settings label{font-weight:700;font-size:110%;display:block}.lasso--form-settings textarea,.lasso--form-settings input[type=text]{border-radius:3px;width:240px;background-color:#f8f8f8;color:#000;-webkit-box-shadow:inset 1px 1px 1px rgba(0,0,0,.1);box-shadow:inset 1px 1px 1px rgba(0,0,0,.1)}.lasso--form-settings input[type=checkbox]{float:left}.lasso--form-settings input[type=checkbox]~label{float:left;position:relative;top:-4px;left:4px}.lasso--form-settings input[type=submit]:active{outline:0}.lasso--form-settings input[type=submit]:disabled{opacity:.4;filter:alpha(opacity=40)}.lasso--form-settings .lasso--setting-description{display:block;margin:5px 0 10px;max-width:400px;color:#888;line-height:1.3;clear:left}.lasso--form-settings .lasso-editor-settings--submit{position:fixed;top:88px;left:760px}.lasso--form-settings .lasso-editor-settings--confirm{background:#fff;border:1px solid #cdcdcd;border-radius:3px;padding:10px 20px 14px 12px;margin-top:10px;-webkit-transition:all .2s linear;-moz-transition:all .2s linear;transition:all .2s linear}.lasso--form-settings .lasso-editor-settings--confirm.success:before,.lasso--form-settings .lasso-editor-settings--confirm.error:before{font-family:Dashicons;speak:none;font-size:18px;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;position:relative;top:4px;right:3px}.lasso--form-settings .lasso-editor-settings--confirm.success:before{content:'\f147';color:#5CB85C}.lasso--form-settings .lasso-editor-settings--confirm.error:before{content:'\f158';color:#d9534f}#wpbody #lasso-editor-settings-form .button-primary.saved{background:#5CB85C!important}
================================================
FILE: admin/assets/js/lasso-editor-settings.js
================================================
jQuery(document).ready(function($){
// entry handler
$('#lasso-editor-settings-form').submit(function(e) {
var $this = $(this);
e.preventDefault();
$this.find(':submit').attr( 'disabled','disabled' );
var data = $this.serialize();
$.post( ajaxurl, data, function(response) {
if ( response.success ) {
$this.find(':submit').addClass('saved');
$this.find('.lasso-editor-settings--submit').append('<div class="lasso-editor-settings--confirm success">Settings Saved!</div>');
setTimeout( function(){
$this.find(':submit').removeClass('saved');
$this.find('.lasso-editor-settings--confirm').remove();
$this.find(':submit').attr( 'disabled',false );
}, 2000 );
} else {
$this.find('.lasso-editor-settings--submit').append('<div class="lasso-editor-settings--confirm error">Something went wrong! :(</div>');
}
}).fail(function(xhr, err) {
var responseTitle= $(xhr.responseText).filter('title').get(0);
alert($(responseTitle).text() + "\n" + EditusFormatAJAXErrorMessage(xhr, err) );
$this.find('.lasso-editor-settings--submit').append('<div class="lasso-editor-settings--confirm error">Something went wrong! :(</div>');
});
});
$('.color-picker').wpColorPicker();
// initialize color pickers with default values
$('#lasso-editor-settings--default-colors').click(function() {
$($(".color-picker")[0]).wpColorPicker('color', "#0000ff");
$($(".color-picker")[1]).wpColorPicker('color', "#000030");
$($(".color-picker")[2]).wpColorPicker('color', "#000055");
$($(".color-picker")[3]).wpColorPicker('color', "#ffffff");
});
$('#lasso_editor_use_old_ui').change(function() {
if(this.checked) {
$('#lasso-editor-settings--colors').slideUp();
} else {
$('#lasso-editor-settings--colors').slideDown();
}
});
});
================================================
FILE: admin/assets/less/style.less
================================================
@import '../../../public/assets/less/source/mixins.less';
@import 'welcome.less';
@main: #fff;
@border: #cdcdcd;
@desc-color: #888;
@main-width: 500px;
@admin-bar-width: 160px;
.lasso--form-settings{
* { .box-sizing(border-box); }
max-width:@main-width;
padding:20px;
background:@main;
border-radius:5px;
border:1px solid @border;
position: relative;
.clearfix();
.iris-picker {
box-sizing: initial;
* {
box-sizing: inherit;
}
}
.lasso-editor-settings--option-wrap {
margin-bottom:25px;
margin-left:15px;
&.last .lasso-editor-settings--option-inner{
border-bottom: none;
padding-bottom:0;
}
}
.lasso-editor-settings--option-inner {
border-bottom:1px solid lighten(@border,10);
padding-bottom:25px;
}
label {
font-weight:bold;
font-size:110%;
display:block;
}
textarea,
input[type="text"] {
border-radius:3px;
width:240px;
background-color: #f8f8f8;
color: #000;
.box-shadow(inset 1px 1px 1px rgba(0,0,0,0.1));
}
input[type="checkbox"] {
float: left;
& ~ label {
float: left;
position: relative;
top:-4px;
left:4px;
}
}
input[type="submit"]{
&:active {
outline:none;
}
&:disabled {
.opacity(0.4);
}
}
.lasso--setting-description {
display:block;
margin:5px 0 10px;
max-width:400px;
color:@desc-color;
line-height: 1.3;
clear:left;
}
// sunmit
.lasso-editor-settings--submit {
position: fixed;
top:88px;
left: @main-width + @admin-bar-width + 100;
}
.lasso-editor-settings--confirm {
background: @main;
border:1px solid @border;
border-radius:3px;
padding:10px 20px 14px 12px;
margin-top:10px;
.transition(all .2s linear);
&.success:before,
&.error:before {
font-family: 'Dashicons';
speak: none;
font-size:18px;
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
line-height: 1;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
position: relative;
top:4px;
right:3px;
}
&.success:before { content:'\f147'; color:#5CB85C; }
&.error:before { content: '\f158'; color:#d9534f; }
}
}
#wpbody #lasso-editor-settings-form .button-primary.saved {
background: #5CB85C !important;
}
================================================
FILE: admin/assets/less/welcome.less
================================================
.lasso--welcome {
* { .box-sizing(border-box); }
max-width:600px;
margin:20px auto;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
@bg: white;
@accent: darken(@bg,5);
@border: darken(@bg, 15);
@link: #007aab;
@success: #4DA34D;
@error: #d9534f;
@info: lighten(@link,25);
p {
font-size:15px;
}
// initial welcome steps
.lasso--welcome__steps {
padding:0;
list-style-type:none;
margin:0 auto;
li {
padding:25px;
background: @bg;
border:1px solid @border;
border-radius:5px;
text-align: center;
position: relative;
margin-top:-25px;
margin-bottom: 100px;
&:before {
font-family: Dashicons;
color:white;
padding: 14px 27px 15px 14px;
width: 22px;
font-size: 36px;
border-radius: 100%;
text-align: center;
position: absolute;
top: -33px;
left: 0;
right: 0;
margin: 0 auto;
height: 34px;
line-height: 37px;
}
&.info:before {
content: '\f348';
background: @info;
}
&.success:before {
content: '\f147';
background: @success;
}
&.error:before {
content: '\f227';
background:@error;
}
p{
margin-bottom: 0;
}
h3 {
margin-bottom: 5px;
}
}
}
.lasso--welcome__top{
.clearfix();
text-align: center;
img {
max-width:150px;
margin:0 auto;
border-radius:3px;
}
h1 + p {
font-style: italic;
}
margin-bottom:100px;
}
// social
.lasso--welcome__social {
list-style: none;
margin:0;
padding:7px 0;
.clearfix();
border-top:1px solid @border;
border-bottom:1px solid @border;
li {
display: inline-block;
line-height: 1;
margin:0;
}
a {
padding:2px 6px;
display: block;
text-decoration: none;
color:inherit;
line-height: 1.5;
font-weight: bold;
&:hover {
color:@link;
text-decoration: none;
}
i {
font-size:16px;
top:2px;
line-height: 19px;
color:@link;
}
}
}
}
================================================
FILE: admin/includes/EDD_SL_Plugin_Updater.php
================================================
<?php
// uncomment this line for testing
//set_site_transient( 'update_plugins', null );
/**
* Allows plugins to use their own update API.
*
* @author Pippin Williamson
* @version 1.6
*/
class EDD_SL_Plugin_Updater {
private $api_url = '';
private $api_data = array();
private $name = '';
private $slug = '';
/**
* Class constructor.
*
* @uses plugin_basename()
* @uses hook()
*
* @param string $_api_url The URL pointing to the custom API endpoint.
* @param string $_plugin_file Path to the plugin file.
* @param array $_api_data Optional data to send with API calls.
* @return void
*/
function __construct( $_api_url, $_plugin_file, $_api_data = null ) {
$this->api_url = trailingslashit( $_api_url );
$this->api_data = $_api_data;
$this->name = plugin_basename( $_plugin_file );
$this->slug = basename( $_plugin_file, '.php' );
$this->version = $_api_data['version'];
// Set up hooks.
$this->init();
add_action( 'admin_init', array( $this, 'show_changelog' ) );
}
/**
* Set up WordPress filters to hook into WP's update process.
*
* @uses add_filter()
*
* @return void
*/
public function init() {
add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ) );
add_filter( 'plugins_api', array( $this, 'plugins_api_filter' ), 10, 3 );
add_action( 'after_plugin_row_' . $this->name, array( $this, 'show_update_notification' ), 10, 2 );
}
/**
* Check for Updates at the defined API endpoint and modify the update array.
*
* This function dives into the update API just when WordPress creates its update array,
* then adds a custom API call and injects the custom plugin data retrieved from the API.
* It is reassembled from parts of the native WordPress plugin update code.
* See wp-includes/update.php line 121 for the original wp_update_plugins() function.
*
* @uses api_request()
*
* @param array $_transient_data Update array build by WordPress.
* @return array Modified update array with custom plugin data.
*/
function check_update( $_transient_data ) {
global $pagenow;
if ( ! is_object( $_transient_data ) ) {
$_transient_data = new stdClass;
}
if ( 'plugins.php' == $pagenow && is_multisite() ) {
return $_transient_data;
}
if ( empty( $_transient_data->response ) || empty( $_transient_data->response[ $this->name ] ) ) {
$version_info = $this->api_request( 'plugin_latest_version', array( 'slug' => $this->slug ) );
if ( false !== $version_info && is_object( $version_info ) && isset( $version_info->new_version ) ) {
$this->did_check = true;
if ( version_compare( $this->version, $version_info->new_version, '<' ) ) {
$_transient_data->response[ $this->name ] = $version_info;
}
$_transient_data->last_checked = time();
$_transient_data->checked[ $this->name ] = $this->version;
}
}
return $_transient_data;
}
/**
* show update nofication row -- needed for multisite subsites, because WP won't tell you otherwise!
*
* @param string $file
* @param array $plugin
*/
public function show_update_notification( $file, $plugin ) {
if ( ! current_user_can( 'update_plugins' ) ) {
return;
}
if ( ! is_multisite() ) {
return;
}
if ( $this->name != $file ) {
return;
}
// Remove our filter on the site transient
remove_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ), 10 );
$update_cache = get_site_transient( 'update_plugins' );
if ( ! is_object( $update_cache ) || empty( $update_cache->response ) || empty( $update_cache->response[ $this->name ] ) ) {
$cache_key = md5( 'edd_plugin_' .sanitize_key( $this->name ) . '_version_info' );
$version_info = get_transient( $cache_key );
if ( false === $version_info ) {
$version_info = $this->api_request( 'plugin_latest_version', array( 'slug' => $this->slug ) );
set_transient( $cache_key, $version_info, 3600 );
}
if ( ! is_object( $version_info ) ) {
return;
}
if ( version_compare( $this->version, $version_info->new_version, '<' ) ) {
$update_cache->response[ $this->name ] = $version_info;
}
$update_cache->last_checked = time();
$update_cache->checked[ $this->name ] = $this->version;
set_site_transient( 'update_plugins', $update_cache );
} else {
$version_info = $update_cache->response[ $this->name ];
}
// Restore our filter
add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ) );
if ( ! empty( $update_cache->response[ $this->name ] ) && version_compare( $this->version, $version_info->new_version, '<' ) ) {
// build a plugin list row, with update notification
$wp_list_table = _get_list_table( 'WP_Plugins_List_Table' );
echo '<tr class="plugin-update-tr"><td colspan="' . $wp_list_table->get_column_count() . '" class="plugin-update colspanchange"><div class="update-message">';
$changelog_link = self_admin_url( 'index.php?edd_sl_action=view_plugin_changelog&plugin=' . $this->name . '&slug=' . $this->slug . '&TB_iframe=true&width=772&height=911' );
if ( empty( $version_info->download_link ) ) {
printf(
__( 'There is a new version of %1$s available. <a target="_blank" class="thickbox" href="%2$s">View version %3$s details</a>.', 'lasso' ),
esc_html( $version_info->name ),
esc_url( $changelog_link ),
esc_html( $version_info->new_version )
);
} else {
printf(
__( 'There is a new version of %1$s available. <a target="_blank" class="thickbox" href="%2$s">View version %3$s details</a> or <a href="%4$s">update now</a>.', 'lasso' ),
esc_html( $version_info->name ),
esc_url( $changelog_link ),
esc_html( $version_info->new_version ),
esc_url( wp_nonce_url( self_admin_url( 'update.php?action=upgrade-plugin&plugin=' ) . $this->name, 'upgrade-plugin_' . $this->name ) )
);
}
echo '</div></td></tr>';
}
}
/**
* Updates information on the "View version x.x details" page with custom data.
*
* @uses api_request()
*
* @param mixed $_data
* @param string $_action
* @param object $_args
* @return object $_data
*/
function plugins_api_filter( $_data, $_action = '', $_args = null ) {
if ( $_action != 'plugin_information' ) {
return $_data;
}
if ( ! isset( $_args->slug ) || ( $_args->slug != $this->slug ) ) {
return $_data;
}
$to_send = array(
'slug' => $this->slug,
'is_ssl' => is_ssl(),
'fields' => array(
'banners' => false, // These will be supported soon hopefully
'reviews' => false
)
);
$api_response = $this->api_request( 'plugin_information', $to_send );
if ( false !== $api_response ) {
$_data = $api_response;
}
return $_data;
}
/**
* Disable SSL verification in order to prevent download update failures
*
* @param array $args
* @param string $url
* @return object $array
*/
function http_request_args( $args, $url ) {
// If it is an https request and we are performing a package download, disable ssl verification
if ( strpos( $url, 'https://' ) !== false && strpos( $url, 'edd_action=package_download' ) ) {
$args['sslverify'] = false;
}
return $args;
}
/**
* Calls the API and, if successfull, returns the object delivered by the API.
*
* @uses get_bloginfo()
* @uses wp_remote_post()
* @uses is_wp_error()
*
* @param string $_action The requested action.
* @param array $_data Parameters for the API action.
* @return false||object
*/
private function api_request( $_action, $_data ) {
global $wp_version;
$data = array_merge( $this->api_data, $_data );
if ( $data['slug'] != $this->slug )
return;
if ( empty( $data['license'] ) )
return;
if ( $this->api_url == home_url() ) {
return false; // Don't allow a plugin to ping itself
}
$api_params = array(
'edd_action' => 'get_version',
'license' => $data['license'],
'item_name' => isset( $data['item_name'] ) ? $data['item_name'] : false,
'item_id' => isset( $data['item_id'] ) ? $data['item_id'] : false,
'slug' => $data['slug'],
'author' => $data['author'],
'url' => home_url()
);
$request = wp_remote_post( $this->api_url, array( 'timeout' => 15, 'sslverify' => false, 'body' => $api_params ) );
if ( ! is_wp_error( $request ) ) {
$request = json_decode( wp_remote_retrieve_body( $request ) );
}
if ( $request && isset( $request->sections ) ) {
$request->sections = maybe_unserialize( $request->sections );
} else {
$request = false;
}
return $request;
}
public function show_changelog() {
if ( empty( $_REQUEST['edd_sl_action'] ) || 'view_plugin_changelog' != $_REQUEST['edd_sl_action'] ) {
return;
}
if ( empty( $_REQUEST['plugin'] ) ) {
return;
}
if ( empty( $_REQUEST['slug'] ) ) {
return;
}
if ( ! current_user_can( 'update_plugins' ) ) {
wp_die( __( 'You do not have permission to install plugin updates', 'lasso' ), __( 'Error', 'lasso' ), array( 'response' => 403 ) );
}
$response = $this->api_request( 'plugin_latest_version', array( 'slug' => $_REQUEST['slug'] ) );
if ( $response && isset( $response->sections['changelog'] ) ) {
echo '<div style="background:#fff;padding:10px;">' . $response->sections['changelog'] . '</div>';
}
exit;
}
}
================================================
FILE: admin/includes/class-tgm-plugin-activation.php
================================================
<?php
/**
* Plugin installation and activation for WordPress themes.
*
* Please note that this is a drop-in library for a theme or plugin.
* The authors of this library (Thomas, Gary and Juliette) are NOT responsible
* for the support of your plugin or theme. Please contact the plugin
* or theme author for support.
*
* @package TGM-Plugin-Activation
* @version 2.5.2
* @link http://tgmpluginactivation.com/
* @author Thomas Griffin, Gary Jones, Juliette Reinders Folmer
* @copyright Copyright (c) 2011, Thomas Griffin
* @license GPL-2.0+
*
* @wordpress-plugin
* Plugin Name: TGM Plugin Activation
* Plugin URI:
* Description: Plugin installation and activation for WordPress themes.
* Version: 2.5.2
* Author: Thomas Griffin, Gary Jones, Juliette Reinders Folmer
* Author URI: http://tgmpluginactivation.com/
* Text Domain: tgmpa
* Domain Path: /languages/
* Copyright: 2011, Thomas Griffin
*/
/*
Copyright 2011 Thomas Griffin (thomasgriffinmedia.com)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License, version 2, as
published by the Free Software Foundation.
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 St, Fifth Floor, Boston, MA 02110-1301 USA
*/
if ( ! class_exists( 'TGM_Plugin_Activation' ) ) {
/**
* Automatic plugin installation and activation library.
*
* Creates a way to automatically install and activate plugins from within themes.
* The plugins can be either bundled, downloaded from the WordPress
* Plugin Repository or downloaded from another external source.
*
* @since 1.0.0
*
* @package TGM-Plugin-Activation
* @author Thomas Griffin
* @author Gary Jones
*/
class TGM_Plugin_Activation {
/**
* TGMPA version number.
*
* @since 2.5.0
*
* @const string Version number.
*/
const TGMPA_VERSION = '2.5.2';
/**
* Regular expression to test if a URL is a WP plugin repo URL.
*
* @const string Regex.
*
* @since 2.5.0
*/
const WP_REPO_REGEX = '|^http[s]?://wordpress\.org/(?:extend/)?plugins/|';
/**
* Arbitrary regular expression to test if a string starts with a URL.
*
* @const string Regex.
*
* @since 2.5.0
*/
const IS_URL_REGEX = '|^http[s]?://|';
/**
* Holds a copy of itself, so it can be referenced by the class name.
*
* @since 1.0.0
*
* @var TGM_Plugin_Activation
*/
public static $instance;
/**
* Holds arrays of plugin details.
*
* @since 1.0.0
*
* @since 2.5.0 the array has the plugin slug as an associative key.
*
* @var array
*/
public $plugins = array();
/**
* Holds arrays of plugin names to use to sort the plugins array.
*
* @since 2.5.0
*
* @var array
*/
protected $sort_order = array();
/**
* Whether any plugins have the 'force_activation' setting set to true.
*
* @since 2.5.0
*
* @var bool
*/
protected $has_forced_activation = false;
/**
* Whether any plugins have the 'force_deactivation' setting set to true.
*
* @since 2.5.0
*
* @var bool
*/
protected $has_forced_deactivation = false;
/**
* Name of the unique ID to hash notices.
*
* @since 2.4.0
*
* @var string
*/
public $id = 'tgmpa';
/**
* Name of the query-string argument for the admin page.
*
* @since 1.0.0
*
* @var string
*/
protected $menu = 'tgmpa-install-plugins';
/**
* Parent menu file slug.
*
* @since 2.5.0
*
* @var string
*/
public $parent_slug = 'themes.php';
/**
* Capability needed to view the plugin installation menu item.
*
* @since 2.5.0
*
* @var string
*/
public $capability = 'edit_theme_options';
/**
* Default absolute path to folder containing bundled plugin zip files.
*
* @since 2.0.0
*
* @var string Absolute path prefix to zip file location for bundled plugins. Default is empty string.
*/
public $default_path = '';
/**
* Flag to show admin notices or not.
*
* @since 2.1.0
*
* @var boolean
*/
public $has_notices = true;
/**
* Flag to determine if the user can dismiss the notice nag.
*
* @since 2.4.0
*
* @var boolean
*/
public $dismissable = true;
/**
* Message to be output above nag notice if dismissable is false.
*
* @since 2.4.0
*
* @var string
*/
public $dismiss_msg = '';
/**
* Flag to set automatic activation of plugins. Off by default.
*
* @since 2.2.0
*
* @var boolean
*/
public $is_automatic = false;
/**
* Optional message to display before the plugins table.
*
* @since 2.2.0
*
* @var string Message filtered by wp_kses_post(). Default is empty string.
*/
public $message = '';
/**
* Holds configurable array of strings.
*
* Default values are added in the constructor.
*
* @since 2.0.0
*
* @var array
*/
public $strings = array();
/**
* Holds the version of WordPress.
*
* @since 2.4.0
*
* @var int
*/
public $wp_version;
/**
* Holds the hook name for the admin page.
*
* @since 2.5.0
*
* @var string
*/
public $page_hook;
/**
* Adds a reference of this object to $instance, populates default strings,
* does the tgmpa_init action hook, and hooks in the interactions to init.
*
* @internal This method should be `protected`, but as too many TGMPA implementations
* haven't upgraded beyond v2.3.6 yet, this gives backward compatibility issues.
* Reverted back to public for the time being.
*
* @since 1.0.0
*
* @see TGM_Plugin_Activation::init()
*/
public function __construct() {
// Set the current WordPress version.
$this->wp_version = $GLOBALS['wp_version'];
// Announce that the class is ready, and pass the object (for advanced use).
do_action_ref_array( 'tgmpa_init', array( $this ) );
// When the rest of WP has loaded, kick-start the rest of the class.
add_action( 'init', array( $this, 'init' ) );
}
/**
* Magic method to (not) set protected properties from outside of this class.
*
* @internal hackedihack... There is a serious bug in v2.3.2 - 2.3.6 where the `menu` property
* is being assigned rather than tested in a conditional, effectively rendering it useless.
* This 'hack' prevents this from happening.
*
* @see https://github.com/TGMPA/TGM-Plugin-Activation/blob/2.3.6/tgm-plugin-activation/class-tgm-plugin-activation.php#L1593
*
* @param string $name Name of an inaccessible property.
* @param mixed $value Value to assign to the property.
* @return void Silently fail to set the property when this is tried from outside of this class context.
* (Inside this class context, the __set() method if not used as there is direct access.)
*/
public function __set( $name, $value ) {
return;
}
/**
* Magic method to get the value of a protected property outside of this class context.
*
* @param string $name Name of an inaccessible property.
* @return mixed The property value.
*/
public function __get( $name ) {
return $this->{$name};
}
/**
* Initialise the interactions between this class and WordPress.
*
* Hooks in three new methods for the class: admin_menu, notices and styles.
*
* @since 2.0.0
*
* @see TGM_Plugin_Activation::admin_menu()
* @see TGM_Plugin_Activation::notices()
* @see TGM_Plugin_Activation::styles()
*/
public function init() {
/**
* By default TGMPA only loads on the WP back-end and not in an Ajax call. Using this filter
* you can overrule that behaviour.
*
* @since 2.5.0
*
* @param bool $load Whether or not TGMPA should load.
* Defaults to the return of `is_admin() && ! defined( 'DOING_AJAX' )`.
*/
if ( true !== apply_filters( 'tgmpa_load', ( is_admin() && ! defined( 'DOING_AJAX' ) ) ) ) {
return;
}
// Load class strings.
$this->strings = array(
'page_title' => __( 'Install Required Plugins', 'tgmpa' ),
'menu_title' => __( 'Install Plugins', 'tgmpa' ),
'installing' => __( 'Installing Plugin: %s', 'tgmpa' ),
'oops' => __( 'Something went wrong with the plugin API.', 'tgmpa' ),
'notice_can_install_required' => _n_noop(
'This theme requires the following plugin: %1$s.',
'This theme requires the following plugins: %1$s.',
'tgmpa'
),
'notice_can_install_recommended' => _n_noop(
'This theme recommends the following plugin: %1$s.',
'This theme recommends the following plugins: %1$s.',
'tgmpa'
),
'notice_cannot_install' => _n_noop(
'Sorry, but you do not have the correct permissions to install the %1$s plugin.',
'Sorry, but you do not have the correct permissions to install the %1$s plugins.',
'tgmpa'
),
'notice_ask_to_update' => _n_noop(
'The following plugin needs to be updated to its latest version to ensure maximum compatibility with this theme: %1$s.',
'The following plugins need to be updated to their latest version to ensure maximum compatibility with this theme: %1$s.',
'tgmpa'
),
'notice_ask_to_update_maybe' => _n_noop(
'There is an update available for: %1$s.',
'There are updates available for the following plugins: %1$s.',
'tgmpa'
),
'notice_cannot_update' => _n_noop(
'Sorry, but you do not have the correct permissions to update the %1$s plugin.',
'Sorry, but you do not have the correct permissions to update the %1$s plugins.',
'tgmpa'
),
'notice_can_activate_required' => _n_noop(
'The following required plugin is currently inactive: %1$s.',
'The following required plugins are currently inactive: %1$s.',
'tgmpa'
),
'notice_can_activate_recommended' => _n_noop(
'The following recommended plugin is currently inactive: %1$s.',
'The following recommended plugins are currently inactive: %1$s.',
'tgmpa'
),
'notice_cannot_activate' => _n_noop(
'Sorry, but you do not have the correct permissions to activate the %1$s plugin.',
'Sorry, but you do not have the correct permissions to activate the %1$s plugins.',
'tgmpa'
),
'install_link' => _n_noop(
'Begin installing plugin',
'Begin installing plugins',
'tgmpa'
),
'update_link' => _n_noop(
'Begin updating plugin',
'Begin updating plugins',
'tgmpa'
),
'activate_link' => _n_noop(
'Begin activating plugin',
'Begin activating plugins',
'tgmpa'
),
'return' => __( 'Return to Required Plugins Installer', 'tgmpa' ),
'dashboard' => __( 'Return to the dashboard', 'tgmpa' ),
'plugin_activated' => __( 'Plugin activated successfully.', 'tgmpa' ),
'activated_successfully' => __( 'The following plugin was activated successfully:', 'tgmpa' ),
'plugin_already_active' => __( 'No action taken. Plugin %1$s was already active.', 'tgmpa' ),
'plugin_needs_higher_version' => __( 'Plugin not activated. A higher version of %s is needed for this theme. Please update the plugin.', 'tgmpa' ),
'complete' => __( 'All plugins installed and activated successfully. %1$s', 'tgmpa' ),
'dismiss' => __( 'Dismiss this notice', 'tgmpa' ),
'contact_admin' => __( 'Please contact the administrator of this site for help.', 'tgmpa' ),
);
do_action( 'tgmpa_register' );
/* After this point, the plugins should be registered and the configuration set. */
// Proceed only if we have plugins to handle.
if ( empty( $this->plugins ) || ! is_array( $this->plugins ) ) {
return;
}
// Set up the menu and notices if we still have outstanding actions.
if ( true !== $this->is_tgmpa_complete() ) {
// Sort the plugins.
array_multisort( $this->sort_order, SORT_ASC, $this->plugins );
add_action( 'admin_menu', array( $this, 'admin_menu' ) );
add_action( 'admin_head', array( $this, 'dismiss' ) );
// Prevent the normal links from showing underneath a single install/update page.
add_filter( 'install_plugin_complete_actions', array( $this, 'actions' ) );
add_filter( 'update_plugin_complete_actions', array( $this, 'actions' ) );
if ( $this->has_notices ) {
add_action( 'admin_notices', array( $this, 'notices' ) );
add_action( 'admin_init', array( $this, 'admin_init' ), 1 );
add_action( 'admin_enqueue_scripts', array( $this, 'thickbox' ) );
}
add_action( 'load-plugins.php', array( $this, 'add_plugin_action_link_filters' ), 1 );
}
// Make sure things get reset on switch theme.
add_action( 'switch_theme', array( $this, 'flush_plugins_cache' ) );
if ( $this->has_notices ) {
add_action( 'switch_theme', array( $this, 'update_dismiss' ) );
}
// Setup the force activation hook.
if ( true === $this->has_forced_activation ) {
add_action( 'admin_init', array( $this, 'force_activation' ) );
}
// Setup the force deactivation hook.
if ( true === $this->has_forced_deactivation ) {
add_action( 'switch_theme', array( $this, 'force_deactivation' ) );
}
}
/**
* Prevent activation of plugins which don't meet the minimum version requirement from the
* WP native plugins page.
*
* @since 2.5.0
*/
public function add_plugin_action_link_filters() {
foreach ( $this->plugins as $slug => $plugin ) {
if ( false === $this->can_plugin_activate( $slug ) ) {
add_filter( 'plugin_action_links_' . $plugin['file_path'], array( $this, 'filter_plugin_action_links_activate' ), 20 );
}
if ( true === $plugin['force_activation'] ) {
add_filter( 'plugin_action_links_' . $plugin['file_path'], array( $this, 'filter_plugin_action_links_deactivate' ), 20 );
}
if ( false !== $this->does_plugin_require_update( $slug ) ) {
add_filter( 'plugin_action_links_' . $plugin['file_path'], array( $this, 'filter_plugin_action_links_update' ), 20 );
}
}
}
/**
* Remove the 'Activate' link on the WP native plugins page if the plugin does not meet the
* minimum version requirements.
*
* @since 2.5.0
*
* @param array $actions Action links.
* @return array
*/
public function filter_plugin_action_links_activate( $actions ) {
unset( $actions['activate'] );
return $actions;
}
/**
* Remove the 'Deactivate' link on the WP native plugins page if the plugin has been set to force activate.
*
* @since 2.5.0
*
* @param array $actions Action links.
* @return array
*/
public function filter_plugin_action_links_deactivate( $actions ) {
unset( $actions['deactivate'] );
return $actions;
}
/**
* Add a 'Requires update' link on the WP native plugins page if the plugin does not meet the
* minimum version requirements.
*
* @since 2.5.0
*
* @param array $actions Action links.
* @return array
*/
public function filter_plugin_action_links_update( $actions ) {
$actions['update'] = sprintf(
'<a href="%1$s" title="%2$s" class="edit">%3$s</a>',
esc_url( $this->get_tgmpa_status_url( 'update' ) ),
esc_attr__( 'This plugin needs to be updated to be compatible with your theme.', 'tgmpa' ),
esc_html__( 'Update Required', 'tgmpa' )
);
return $actions;
}
/**
* Handles calls to show plugin information via links in the notices.
*
* We get the links in the admin notices to point to the TGMPA page, rather
* than the typical plugin-install.php file, so we can prepare everything
* beforehand.
*
* WP does not make it easy to show the plugin information in the thickbox -
* here we have to require a file that includes a function that does the
* main work of displaying it, enqueue some styles, set up some globals and
* finally call that function before exiting.
*
* Down right easy once you know how...
*
* Returns early if not the TGMPA page.
*
* @since 2.1.0
*
* @global string $tab Used as iframe div class names, helps with styling
* @global string $body_id Used as the iframe body ID, helps with styling
*
* @return null Returns early if not the TGMPA page.
*/
public function admin_init() {
if ( ! $this->is_tgmpa_page() ) {
return;
}
if ( isset( $_REQUEST['tab'] ) && 'plugin-information' === $_REQUEST['tab'] ) {
// Needed for install_plugin_information().
require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
wp_enqueue_style( 'plugin-install' );
global $tab, $body_id;
$body_id = 'plugin-information';
// @codingStandardsIgnoreStart
$tab = 'plugin-information';
// @codingStandardsIgnoreEnd
install_plugin_information();
exit;
}
}
/**
* Enqueue thickbox scripts/styles for plugin info.
*
* Thickbox is not automatically included on all admin pages, so we must
* manually enqueue it for those pages.
*
* Thickbox is only loaded if the user has not dismissed the admin
* notice or if there are any plugins left to install and activate.
*
* @since 2.1.0
*/
public function thickbox() {
if ( ! get_user_meta( get_current_user_id(), 'tgmpa_dismissed_notice_' . $this->id, true ) ) {
add_thickbox();
}
}
/**
* Adds submenu page if there are plugin actions to take.
*
* This method adds the submenu page letting users know that a required
* plugin needs to be installed.
*
* This page disappears once the plugin has been installed and activated.
*
* @since 1.0.0
*
* @see TGM_Plugin_Activation::init()
* @see TGM_Plugin_Activation::install_plugins_page()
*
* @return null Return early if user lacks capability to install a plugin.
*/
public function admin_menu() {
// Make sure privileges are correct to see the page.
if ( ! current_user_can( 'install_plugins' ) ) {
return;
}
$args = apply_filters(
'tgmpa_admin_menu_args',
array(
'parent_slug' => $this->parent_slug, // Parent Menu slug.
'page_title' => $this->strings['page_title'], // Page title.
'menu_title' => $this->strings['menu_title'], // Menu title.
'capability' => $this->capability, // Capability.
'menu_slug' => $this->menu, // Menu slug.
'function' => array( $this, 'install_plugins_page' ), // Callback.
)
);
$this->add_admin_menu( $args );
}
/**
* Add the menu item.
*
* @since 2.5.0
*
* @param array $args Menu item configuration.
*/
protected function add_admin_menu( array $args ) {
if ( has_filter( 'tgmpa_admin_menu_use_add_theme_page' ) ) {
_deprecated_function( 'The "tgmpa_admin_menu_use_add_theme_page" filter', '2.5.0', esc_html__( 'Set the parent_slug config variable instead.', 'tgmpa' ) );
}
if ( 'themes.php' === $this->parent_slug ) {
$this->page_hook = call_user_func( 'add_theme_page', $args['page_title'], $args['menu_title'], $args['capability'], $args['menu_slug'], $args['function'] );
} else {
$this->page_hook = call_user_func( 'add_submenu_page', $args['parent_slug'], $args['page_title'], $args['menu_title'], $args['capability'], $args['menu_slug'], $args['function'] );
}
}
/**
* Echoes plugin installation form.
*
* This method is the callback for the admin_menu method function.
* This displays the admin page and form area where the user can select to install and activate the plugin.
* Aborts early if we're processing a plugin installation action.
*
* @since 1.0.0
*
* @return null Aborts early if we're processing a plugin installation action.
*/
public function install_plugins_page() {
// Store new instance of plugin table in object.
$plugin_table = new TGMPA_List_Table;
// Return early if processing a plugin installation action.
if ( ( ( 'tgmpa-bulk-install' === $plugin_table->current_action() || 'tgmpa-bulk-update' === $plugin_table->current_action() ) && $plugin_table->process_bulk_actions() ) || $this->do_plugin_install() ) {
return;
}
// Force refresh of available plugin information so we'll know about manual updates/deletes.
wp_clean_plugins_cache( false );
?>
<div class="tgmpa wrap">
<h2><?php echo esc_html( get_admin_page_title() ); ?></h2>
<?php $plugin_table->prepare_items(); ?>
<?php
if ( ! empty( $this->message ) && is_string( $this->message ) ) {
echo wp_kses_post( $this->message );
}
?>
<?php $plugin_table->views(); ?>
<form id="tgmpa-plugins" action="" method="post">
<input type="hidden" name="tgmpa-page" value="<?php echo esc_attr( $this->menu ); ?>" />
<input type="hidden" name="plugin_status" value="<?php echo esc_attr( $plugin_table->view_context ); ?>" />
<?php $plugin_table->display(); ?>
</form>
</div>
<?php
}
/**
* Installs, updates or activates a plugin depending on the action link clicked by the user.
*
* Checks the $_GET variable to see which actions have been
* passed and responds with the appropriate method.
*
* Uses WP_Filesystem to process and handle the plugin installation
* method.
*
* @since 1.0.0
*
* @uses WP_Filesystem
* @uses WP_Error
* @uses WP_Upgrader
* @uses Plugin_Upgrader
* @uses Plugin_Installer_Skin
* @uses Plugin_Upgrader_Skin
*
* @return boolean True on success, false on failure.
*/
protected function do_plugin_install() {
if ( empty( $_GET['plugin'] ) ) {
return false;
}
// All plugin information will be stored in an array for processing.
$slug = $this->sanitize_key( urldecode( $_GET['plugin'] ) );
if ( ! isset( $this->plugins[ $slug ] ) ) {
return false;
}
// Was an install or upgrade action link clicked?
if ( ( isset( $_GET['tgmpa-install'] ) && 'install-plugin' === $_GET['tgmpa-install'] ) || ( isset( $_GET['tgmpa-update'] ) && 'update-plugin' === $_GET['tgmpa-update'] ) ) {
$install_type = 'install';
if ( isset( $_GET['tgmpa-update'] ) && 'update-plugin' === $_GET['tgmpa-update'] ) {
$install_type = 'update';
}
check_admin_referer( 'tgmpa-' . $install_type, 'tgmpa-nonce' );
// Pass necessary information via URL if WP_Filesystem is needed.
$url = wp_nonce_url(
add_query_arg(
array(
'plugin' => urlencode( $slug ),
'tgmpa-' . $install_type => $install_type . '-plugin',
),
$this->get_tgmpa_url()
),
'tgmpa-' . $install_type,
'tgmpa-nonce'
);
$method = ''; // Leave blank so WP_Filesystem can populate it as necessary.
if ( false === ( $creds = request_filesystem_credentials( esc_url_raw( $url ), $method, false, false, array() ) ) ) {
return true;
}
if ( ! WP_Filesystem( $creds ) ) {
request_filesystem_credentials( esc_url_raw( $url ), $method, true, false, array() ); // Setup WP_Filesystem.
return true;
}
/* If we arrive here, we have the filesystem. */
// Prep variables for Plugin_Installer_Skin class.
$extra = array();
$extra['slug'] = $slug; // Needed for potentially renaming of directory name.
$source = $this->get_download_url( $slug );
$api = ( 'repo' === $this->plugins[ $slug ]['source_type'] ) ? $this->get_plugins_api( $slug ) : null;
$api = ( false !== $api ) ? $api : null;
$url = add_query_arg(
array(
'action' => $install_type . '-plugin',
'plugin' => urlencode( $slug ),
),
'update.php'
);
if ( ! class_exists( 'Plugin_Upgrader', false ) ) {
require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
}
$skin_args = array(
'type' => ( 'bundled' !== $this->plugins[ $slug ]['source_type'] ) ? 'web' : 'upload',
'title' => sprintf( $this->strings['installing'], $this->plugins[ $slug ]['name'] ),
'url' => esc_url_raw( $url ),
'nonce' => $install_type . '-plugin_' . $slug,
'plugin' => '',
'api' => $api,
'extra' => $extra,
);
if ( 'update' === $install_type ) {
$skin_args['plugin'] = $this->plugins[ $slug ]['file_path'];
$skin = new Plugin_Upgrader_Skin( $skin_args );
} else {
$skin = new Plugin_Installer_Skin( $skin_args );
}
// Create a new instance of Plugin_Upgrader.
$upgrader = new Plugin_Upgrader( $skin );
// Perform the action and install the plugin from the $source urldecode().
add_filter( 'upgrader_source_selection', array( $this, 'maybe_adjust_source_dir' ), 1, 3 );
if ( 'update' === $install_type ) {
// Inject our info into the update transient.
$to_inject = array( $slug => $this->plugins[ $slug ] );
$to_inject[ $slug ]['source'] = $source;
$this->inject_update_info( $to_inject );
$upgrader->upgrade( $this->plugins[ $slug ]['file_path'] );
} else {
$upgrader->install( $source );
}
remove_filter( 'upgrader_source_selection', array( $this, 'maybe_adjust_source_dir' ), 1, 3 );
// Make sure we have the correct file path now the plugin is installed/updated.
$this->populate_file_path( $slug );
// Only activate plugins if the config option is set to true and the plugin isn't
// already active (upgrade).
if ( $this->is_automatic && ! $this->is_plugin_active( $slug ) ) {
$plugin_activate = $upgrader->plugin_info(); // Grab the plugin info from the Plugin_Upgrader method.
if ( false === $this->activate_single_plugin( $plugin_activate, $slug, true ) ) {
return true; // Finish execution of the function early as we encountered an error.
}
}
$this->show_tgmpa_version();
// Display message based on if all plugins are now active or not.
if ( $this->is_tgmpa_complete() ) {
echo '<p>', sprintf( esc_html( $this->strings['complete'] ), '<a href="' . esc_url( self_admin_url() ) . '">' . esc_html__( 'Return to the Dashboard', 'tgmpa' ) . '</a>' ), '</p>';
echo '<style type="text/css">#adminmenu .wp-submenu li.current { display: none !important; }</style>';
} else {
echo '<p><a href="', esc_url( $this->get_tgmpa_url() ), '" target="_parent">', esc_html( $this->strings['return'] ), '</a></p>';
}
return true;
} elseif ( isset( $this->plugins[ $slug ]['file_path'], $_GET['tgmpa-activate'] ) && 'activate-plugin' === $_GET['tgmpa-activate'] ) {
// Activate action link was clicked.
check_admin_referer( 'tgmpa-activate', 'tgmpa-nonce' );
if ( false === $this->activate_single_plugin( $this->plugins[ $slug ]['file_path'], $slug ) ) {
return true; // Finish execution of the function early as we encountered an error.
}
}
return false;
}
/**
* Inject information into the 'update_plugins' site transient as WP checks that before running an update.
*
* @since 2.5.0
*
* @param array $plugins The plugin information for the plugins which are to be updated.
*/
public function inject_update_info( $plugins ) {
$repo_updates = get_site_transient( 'update_plugins' );
if ( ! is_object( $repo_updates ) ) {
$repo_updates = new stdClass;
}
foreach ( $plugins as $slug => $plugin ) {
$file_path = $plugin['file_path'];
if ( empty( $repo_updates->response[ $file_path ] ) ) {
$repo_updates->response[ $file_path ] = new stdClass;
}
// We only really need to set package, but let's do all we can in case WP changes something.
$repo_updates->response[ $file_path ]->slug = $slug;
$repo_updates->response[ $file_path ]->plugin = $file_path;
$repo_updates->response[ $file_path ]->new_version = $plugin['version'];
$repo_updates->response[ $file_path ]->package = $plugin['source'];
if ( empty( $repo_updates->response[ $file_path ]->url ) && ! empty( $plugin['external_url'] ) ) {
$repo_updates->response[ $file_path ]->url = $plugin['external_url'];
}
}
set_site_transient( 'update_plugins', $repo_updates );
}
/**
* Adjust the plugin directory name if necessary.
*
* The final destination directory of a plugin is based on the subdirectory name found in the
* (un)zipped source. In some cases - most notably GitHub repository plugin downloads -, this
* subdirectory name is not the same as the expected slug and the plugin will not be recognized
* as installed. This is fixed by adjusting the temporary unzipped source subdirectory name to
* the expected plugin slug.
*
* @since 2.5.0
*
* @param string $source Path to upgrade/zip-file-name.tmp/subdirectory/.
* @param string $remote_source Path to upgrade/zip-file-name.tmp.
* @param \WP_Upgrader $upgrader Instance of the upgrader which installs the plugin.
* @return string $source
*/
public function maybe_adjust_source_dir( $source, $remote_source, $upgrader ) {
if ( ! $this->is_tgmpa_page() || ! is_object( $GLOBALS['wp_filesystem'] ) ) {
return $source;
}
// Check for single file plugins.
$source_files = array_keys( $GLOBALS['wp_filesystem']->dirlist( $remote_source ) );
if ( 1 === count( $source_files ) && false === $GLOBALS['wp_filesystem']->is_dir( $source ) ) {
return $source;
}
// Multi-file plugin, let's see if the directory is correctly named.
$desired_slug = '';
// Figure out what the slug is supposed to be.
if ( false === $upgrader->bulk && ! empty( $upgrader->skin->options['extra']['slug'] ) ) {
$desired_slug = $upgrader->skin->options['extra']['slug'];
} else {
// Bulk installer contains less info, so fall back on the info registered here.
foreach ( $this->plugins as $slug => $plugin ) {
if ( ! empty( $upgrader->skin->plugin_names[ $upgrader->skin->i ] ) && $plugin['name'] === $upgrader->skin->plugin_names[ $upgrader->skin->i ] ) {
$desired_slug = $slug;
break;
}
}
unset( $slug, $plugin );
}
if ( ! empty( $desired_slug ) ) {
$subdir_name = untrailingslashit( str_replace( trailingslashit( $remote_source ), '', $source ) );
if ( ! empty( $subdir_name ) && $subdir_name !== $desired_slug ) {
$from = untrailingslashit( $source );
$to = trailingslashit( $remote_source ) . $desired_slug;
if ( true === $GLOBALS['wp_filesystem']->move( $from, $to ) ) {
return trailingslashit( $to );
} else {
return new WP_Error( 'rename_failed', esc_html__( 'The remote plugin package does not contain a folder with the desired slug and renaming did not work.', 'tgmpa' ) . ' ' . esc_html__( 'Please contact the plugin provider and ask them to package their plugin according to the WordPress guidelines.', 'tgmpa' ), array( 'found' => $subdir_name, 'expected' => $desired_slug ) );
}
} elseif ( empty( $subdir_name ) ) {
return new WP_Error( 'packaged_wrong', esc_html__( 'The remote plugin package consists of more than one file, but the files are not packaged in a folder.', 'tgmpa' ) . ' ' . esc_html__( 'Please contact the plugin provider and ask them to package their plugin according to the WordPress guidelines.', 'tgmpa' ), array( 'found' => $subdir_name, 'expected' => $desired_slug ) );
}
}
return $source;
}
/**
* Activate a single plugin and send feedback about the result to the screen.
*
* @since 2.5.0
*
* @param string $file_path Path within wp-plugins/ to main plugin file.
* @param string $slug Plugin slug.
* @param bool $automatic Whether this is an automatic activation after an install. Defaults to false.
* This determines the styling of the output messages.
* @return bool False if an error was encountered, true otherwise.
*/
protected function activate_single_plugin( $file_path, $slug, $automatic = false ) {
if ( $this->can_plugin_activate( $slug ) ) {
$activate = activate_plugin( $file_path );
if ( is_wp_error( $activate ) ) {
echo '<div id="message" class="error"><p>', wp_kses_post( $activate->get_error_message() ), '</p></div>',
'<p><a href="', esc_url( $this->get_tgmpa_url() ), '" target="_parent">', esc_html( $this->strings['return'] ), '</a></p>';
return false; // End it here if there is an error with activation.
} else {
if ( ! $automatic ) {
// Make sure message doesn't display again if bulk activation is performed
// immediately after a single activation.
if ( ! isset( $_POST['action'] ) ) { // WPCS: CSRF OK.
echo '<div id="message" class="updated"><p>', esc_html( $this->strings['activated_successfully'] ), ' <strong>', esc_html( $this->plugins[ $slug ]['name'] ), '.</strong></p></div>';
}
} else {
// Simpler message layout for use on the plugin install page.
echo '<p>', esc_html( $this->strings['plugin_activated'] ), '</p>';
}
}
} elseif ( $this->is_plugin_active( $slug ) ) {
// No simpler message format provided as this message should never be encountered
// on the plugin install page.
echo '<div id="message" class="error"><p>',
sprintf(
esc_html( $this->strings['plugin_already_active'] ),
'<strong>' . esc_html( $this->plugins[ $slug ]['name'] ) . '</strong>'
),
'</p></div>';
} elseif ( $this->does_plugin_require_update( $slug ) ) {
if ( ! $automatic ) {
// Make sure message doesn't display again if bulk activation is performed
// immediately after a single activation.
if ( ! isset( $_POST['action'] ) ) { // WPCS: CSRF OK.
echo '<div id="message" class="error"><p>',
sprintf(
esc_html( $this->strings['plugin_needs_higher_version'] ),
'<strong>' . esc_html( $this->plugins[ $slug ]['name'] ) . '</strong>'
),
'</p></div>';
}
} else {
// Simpler message layout for use on the plugin install page.
echo '<p>', sprintf( esc_html( $this->strings['plugin_needs_higher_version'] ), esc_html( $this->plugins[ $slug ]['name'] ) ), '</p>';
}
}
return true;
}
/**
* Echoes required plugin notice.
*
* Outputs a message telling users that a specific plugin is required for
* their theme. If appropriate, it includes a link to the form page where
* users can install and activate the plugin.
*
* Returns early if we're on the Install page.
*
* @since 1.0.0
*
* @global object $current_screen
*
* @return null Returns early if we're on the Install page.
*/
public function notices() {
// Remove nag on the install page / Return early if the nag message has been dismissed.
if ( $this->is_tgmpa_page() || get_user_meta( get_current_user_id(), 'tgmpa_dismissed_notice_' . $this->id, true ) ) {
return;
}
// Store for the plugin slugs by message type.
$message = array();
// Initialize counters used to determine plurality of action link texts.
$install_link_count = 0;
$update_link_count = 0;
$activate_link_count = 0;
foreach ( $this->plugins as $slug => $plugin ) {
if ( $this->is_plugin_active( $slug ) && false === $this->does_plugin_have_update( $slug ) ) {
continue;
}
if ( ! $this->is_plugin_installed( $slug ) ) {
if ( current_user_can( 'install_plugins' ) ) {
$install_link_count++;
if ( true === $plugin['required'] ) {
$message['notice_can_install_required'][] = $slug;
} else {
$message['notice_can_install_recommended'][] = $slug;
}
} else {
// Need higher privileges to install the plugin.
$message['notice_cannot_install'][] = $slug;
}
} else {
if ( ! $this->is_plugin_active( $slug ) && $this->can_plugin_activate( $slug ) ) {
if ( current_user_can( 'activate_plugins' ) ) {
$activate_link_count++;
if ( true === $plugin['required'] ) {
$message['notice_can_activate_required'][] = $slug;
} else {
$message['notice_can_activate_recommended'][] = $slug;
}
} else {
// Need higher privileges to activate the plugin.
$message['notice_cannot_activate'][] = $slug;
}
}
if ( $this->does_plugin_require_update( $slug ) || false !== $this->does_plugin_have_update( $slug ) ) {
if ( current_user_can( 'install_plugins' ) ) {
$update_link_count++;
if ( $this->does_plugin_require_update( $slug ) ) {
$message['notice_ask_to_update'][] = $slug;
} elseif ( false !== $this->does_plugin_have_update( $slug ) ) {
$message['notice_ask_to_update_maybe'][] = $slug;
}
} else {
// Need higher privileges to update the plugin.
$message['notice_cannot_update'][] = $slug;
}
}
}
}
unset( $slug, $plugin );
// If we have notices to display, we move forward.
if ( ! empty( $message ) ) {
krsort( $message ); // Sort messages.
$rendered = '';
// As add_settings_error() wraps the final message in a <p> and as the final message can't be
// filtered, using <p>'s in our html would render invalid html output.
$line_template = '<span style="display: block; margin: 0.5em 0.5em 0 0; clear: both;">%s</span>' . "\n";
// If dismissable is false and a message is set, output it now.
if ( ! $this->dismissable && ! empty( $this->dismiss_msg ) ) {
$rendered .= sprintf( $line_template, wp_kses_post( $this->dismiss_msg ) );
}
// Render the individual message lines for the notice.
foreach ( $message as $type => $plugin_group ) {
$linked_plugins = array();
// Get the external info link for a plugin if one is available.
foreach ( $plugin_group as $plugin_slug ) {
$linked_plugins[] = $this->get_info_link( $plugin_slug );
}
unset( $plugin_slug );
$count = count( $plugin_group );
$linked_plugins = array_map( array( 'TGMPA_Utils', 'wrap_in_em' ), $linked_plugins );
$last_plugin = array_pop( $linked_plugins ); // Pop off last name to prep for readability.
$imploded = empty( $linked_plugins ) ? $last_plugin : ( implode( ', ', $linked_plugins ) . ' ' . esc_html_x( 'and', 'plugin A *and* plugin B', 'tgmpa' ) . ' ' . $last_plugin );
$rendered .= sprintf(
$line_template,
sprintf(
translate_nooped_plural( $this->strings[ $type ], $count, 'tgmpa' ),
$imploded,
$count
)
);
if ( 0 === strpos( $type, 'notice_cannot' ) ) {
$rendered .= $this->strings['contact_admin'];
}
}
unset( $type, $plugin_group, $linked_plugins, $count, $last_plugin, $imploded );
// Setup action links.
$action_links = array(
'install' => '',
'update' => '',
'activate' => '',
'dismiss' => $this->dismissable ? '<a href="' . esc_url( add_query_arg( 'tgmpa-dismiss', 'dismiss_admin_notices' ) ) . '" class="dismiss-notice" target="_parent">' . esc_html( $this->strings['dismiss'] ) . '</a>' : '',
);
$link_template = '<a href="%2$s">%1$s</a>';
if ( current_user_can( 'install_plugins' ) ) {
if ( $install_link_count > 0 ) {
$action_links['install'] = sprintf(
$link_template,
translate_nooped_plural( $this->strings['install_link'], $install_link_count, 'tgmpa' ),
esc_url( $this->get_tgmpa_status_url( 'install' ) )
);
}
if ( $update_link_count > 0 ) {
$action_links['update'] = sprintf(
$link_template,
translate_nooped_plural( $this->strings['update_link'], $update_link_count, 'tgmpa' ),
esc_url( $this->get_tgmpa_status_url( 'update' ) )
);
}
}
if ( current_user_can( 'activate_plugins' ) && $activate_link_count > 0 ) {
$action_links['activate'] = sprintf(
$link_template,
translate_nooped_plural( $this->strings['activate_link'], $activate_link_count, 'tgmpa' ),
esc_url( $this->get_tgmpa_status_url( 'activate' ) )
);
}
$action_links = apply_filters( 'tgmpa_notice_action_links', $action_links );
$action_links = array_filter( (array) $action_links ); // Remove any empty array items.
if ( ! empty( $action_links ) && is_array( $action_links ) ) {
$action_links = sprintf( $line_template, implode( ' | ', $action_links ) );
$rendered .= apply_filters( 'tgmpa_notice_rendered_action_links', $action_links );
}
// Register the nag messages and prepare them to be processed.
if ( ! empty( $this->strings['nag_type'] ) ) {
add_settings_error( 'tgmpa', 'tgmpa', $rendered, sanitize_html_class( strtolower( $this->strings['nag_type'] ) ) );
} else {
$nag_class = version_compare( $this->wp_version, '3.8', '<' ) ? 'updated' : 'update-nag';
add_settings_error( 'tgmpa', 'tgmpa', $rendered, $nag_class );
}
}
// Admin options pages already output settings_errors, so this is to avoid duplication.
if ( 'options-general' !== $GLOBALS['current_screen']->parent_base ) {
$this->display_settings_errors();
}
}
/**
* Display settings errors and remove those which have been displayed to avoid duplicate messages showing
*
* @since 2.5.0
*/
protected function display_settings_errors() {
global $wp_settings_errors;
settings_errors( 'tgmpa' );
foreach ( (array) $wp_settings_errors as $key => $details ) {
if ( 'tgmpa' === $details['setting'] ) {
unset( $wp_settings_errors[ $key ] );
break;
}
}
}
/**
* Add dismissable admin notices.
*
* Appends a link to the admin nag messages. If clicked, the admin notice disappears and no longer is visible to users.
*
* @since 2.1.0
*/
public function dismiss() {
if ( isset( $_GET['tgmpa-dismiss'] ) ) {
update_user_meta( get_current_user_id(), 'tgmpa_dismissed_notice_' . $this->id, 1 );
}
}
/**
* Add individual plugin to our collection of plugins.
*
* If the required keys are not set or the plugin has already
* been registered, the plugin is not added.
*
* @since 2.0.0
*
* @param array|null $plugin Array of plugin arguments or null if invalid argument.
* @return null Return early if incorrect argument.
*/
public function register( $plugin ) {
if ( empty( $plugin['slug'] ) || empty( $plugin['name'] ) ) {
return;
}
if ( empty( $plugin['slug'] ) || ! is_string( $plugin['slug'] ) || isset( $this->plugins[ $plugin['slug'] ] ) ) {
return;
}
$defaults = array(
'name' => '', // String
'slug' => '', // String
'source' => 'repo', // String
'required' => false, // Boolean
'version' => '', // String
'force_activation' => false, // Boolean
'force_deactivation' => false, // Boolean
'external_url' => '', // String
'is_callable' => '', // String|Array.
);
// Prepare the received data.
$plugin = wp_parse_args( $plugin, $defaults );
// Standardize the received slug.
$plugin['slug'] = $this->sanitize_key( $plugin['slug'] );
// Forgive users for using string versions of booleans or floats for version number.
$plugin['version'] = (string) $plugin['version'];
$plugin['source'] = empty( $plugin['source'] ) ? 'repo' : $plugin['source'];
$plugin['required'] = TGMPA_Utils::validate_bool( $plugin['required'] );
$plugin['force_activation'] = TGMPA_Utils::validate_bool( $plugin['force_activation'] );
$plugin['force_deactivation'] = TGMPA_Utils::validate_bool( $plugin['force_deactivation'] );
// Enrich the received data.
$plugin['file_path'] = $this->_get_plugin_basename_from_slug( $plugin['slug'] );
$plugin['source_type'] = $this->get_plugin_source_type( $plugin['source'] );
// Set the class properties.
$this->plugins[ $plugin['slug'] ] = $plugin;
$this->sort_order[ $plugin['slug'] ] = $plugin['name'];
// Should we add the force activation hook ?
if ( true === $plugin['force_activation'] ) {
$this->has_forced_activation = true;
}
// Should we add the force deactivation hook ?
if ( true === $plugin['force_deactivation'] ) {
$this->has_forced_deactivation = true;
}
}
/**
* Determine what type of source the plugin comes from.
*
* @since 2.5.0
*
* @param string $source The source of the plugin as provided, either empty (= WP repo), a file path
* (= bundled) or an external URL.
* @return string 'repo', 'external', or 'bundled'
*/
protected function get_plugin_source_type( $source ) {
if ( 'repo' === $source || preg_match( self::WP_REPO_REGEX, $source ) ) {
return 'repo';
} elseif ( preg_match( self::IS_URL_REGEX, $source ) ) {
return 'external';
} else {
return 'bundled';
}
}
/**
* Sanitizes a string key.
*
* Near duplicate of WP Core `sanitize_key()`. The difference is that uppercase characters *are*
* allowed, so as not to break upgrade paths from non-standard bundled plugins using uppercase
* characters in the plugin directory path/slug. Silly them.
*
* @see https://developer.wordpress.org/reference/hooks/sanitize_key/
*
* @since 2.5.0
*
* @param string $key String key.
* @return string Sanitized key
*/
public function sanitize_key( $key ) {
$raw_key = $key;
$key = preg_replace( '`[^A-Za-z0-9_-]`', '', $key );
/**
* Filter a sanitized key string.
*
* @since 3.0.0
*
* @param string $key Sanitized key.
* @param string $raw_key The key prior to sanitization.
*/
return apply_filters( 'tgmpa_sanitize_key', $key, $raw_key );
}
/**
* Amend default configuration settings.
*
* @since 2.0.0
*
* @param array $config Array of config options to pass as class properties.
*/
public function config( $config ) {
$keys = array(
'id',
'default_path',
'has_notices',
'dismissable',
'dismiss_msg',
'menu',
'parent_slug',
'capability',
'is_automatic',
'message',
'strings',
);
foreach ( $keys as $key ) {
if ( isset( $config[ $key ] ) ) {
if ( is_array( $config[ $key ] ) ) {
$this->$key = array_merge( $this->$key, $config[ $key ] );
} else {
$this->$key = $config[ $key ];
}
}
}
}
/**
* Amend action link after plugin installation.
*
* @since 2.0.0
*
* @param array $install_actions Existing array of actions.
* @return array Amended array of actions.
*/
public function actions( $install_actions ) {
// Remove action links on the TGMPA install page.
if ( $this->is_tgmpa_page() ) {
return false;
}
return $install_actions;
}
/**
* Flushes the plugins cache on theme switch to prevent stale entries
* from remaining in the plugin table.
*
* @since 2.4.0
*
* @param bool $clear_update_cache Optional. Whether to clear the Plugin updates cache.
* Parameter added in v2.5.0.
*/
public function flush_plugins_cache( $clear_update_cache = true ) {
wp_clean_plugins_cache( $clear_update_cache );
}
/**
* Set file_path key for each installed plugin.
*
* @since 2.1.0
*
* @param string $plugin_slug Optional. If set, only (re-)populates the file path for that specific plugin.
* Parameter added in v2.5.0.
*/
public function populate_file_path( $plugin_slug = '' ) {
if ( ! empty( $plugin_slug ) && is_string( $plugin_slug ) && isset( $this->plugins[ $plugin_slug ] ) ) {
$this->plugins[ $plugin_slug ]['file_path'] = $this->_get_plugin_basename_from_slug( $plugin_slug );
} else {
// Add file_path key for all plugins.
foreach ( $this->plugins as $slug => $values ) {
$this->plugins[ $slug ]['file_path'] = $this->_get_plugin_basename_from_slug( $slug );
}
}
}
/**
* Helper function to extract the file path of the plugin file from the
* plugin slug, if the plugin is installed.
*
* @since 2.0.0
*
* @param string $slug Plugin slug (typically folder name) as provided by the developer.
* @return string Either file path for plugin if installed, or just the plugin slug.
*/
protected function _get_plugin_basename_from_slug( $slug ) {
$keys = array_keys( $this->get_plugins() );
foreach ( $keys as $key ) {
if ( preg_match( '|^' . $slug . '/|', $key ) ) {
return $key;
}
}
return $slug;
}
/**
* Retrieve plugin data, given the plugin name.
*
* Loops through the registered plugins looking for $name. If it finds it,
* it returns the $data from that plugin. Otherwise, returns false.
*
* @since 2.1.0
*
* @param string $name Name of the plugin, as it was registered.
* @param string $data Optional. Array key of plugin data to return. Default is slug.
* @return string|boolean Plugin slug if found, false otherwise.
*/
public function _get_plugin_data_from_name( $name, $data = 'slug' ) {
foreach ( $this->plugins as $values ) {
if ( $name === $values['name'] && isset( $values[ $data ] ) ) {
return $values[ $data ];
}
}
return false;
}
/**
* Retrieve the download URL for a package.
*
* @since 2.5.0
*
* @param string $slug Plugin slug.
* @return string Plugin download URL or path to local file or empty string if undetermined.
*/
public function get_download_url( $slug ) {
$dl_source = '';
switch ( $this->plugins[ $slug ]['source_type'] ) {
case 'repo':
return $this->get_wp_repo_download_url( $slug );
case 'external':
return $this->plugins[ $slug ]['source'];
case 'bundled':
return $this->default_path . $this->plugins[ $slug ]['source'];
}
return $dl_source; // Should never happen.
}
/**
* Retrieve the download URL for a WP repo package.
*
* @since 2.5.0
*
* @param string $slug Plugin slug.
* @return string Plugin download URL.
*/
protected function get_wp_repo_download_url( $slug ) {
$source = '';
$api = $this->get_plugins_api( $slug );
if ( false !== $api && isset( $api->download_link ) ) {
$source = $api->download_link;
}
return $source;
}
/**
* Try to grab information from WordPress API.
*
* @since 2.5.0
*
* @param string $slug Plugin slug.
* @return object Plugins_api response object on success, WP_Error on failure.
*/
protected function get_plugins_api( $slug ) {
static $api = array(); // Cache received responses.
if ( ! isset( $api[ $slug ] ) ) {
if ( ! function_exists( 'plugins_api' ) ) {
require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
}
$response = plugins_api( 'plugin_information', array( 'slug' => $slug, 'fields' => array( 'sections' => false ) ) );
$api[ $slug ] = false;
if ( is_wp_error( $response ) ) {
wp_die( esc_html( $this->strings['oops'] ) );
} else {
$api[ $slug ] = $response;
}
}
return $api[ $slug ];
}
/**
* Retrieve a link to a plugin information page.
*
* @since 2.5.0
*
* @param string $slug Plugin slug.
* @return string Fully formed html link to a plugin information page if available
* or the plugin name if not.
*/
public function get_info_link( $slug ) {
if ( ! empty( $this->plugins[ $slug ]['external_url'] ) && preg_match( self::IS_URL_REGEX, $this->plugins[ $slug ]['external_url'] ) ) {
$link = sprintf(
'<a href="%1$s" target="_blank">%2$s</a>',
esc_url( $this->plugins[ $slug ]['external_url'] ),
esc_html( $this->plugins[ $slug ]['name'] )
);
} elseif ( 'repo' === $this->plugins[ $slug ]['source_type'] ) {
$url = add_query_arg(
array(
'tab' => 'plugin-information',
'plugin' => urlencode( $slug ),
'TB_iframe' => 'true',
'width' => '640',
'height' => '500',
),
self_admin_url( 'plugin-install.php' )
);
$link = sprintf(
'<a href="%1$s" class="thickbox">%2$s</a>',
esc_url( $url ),
esc_html( $this->plugins[ $slug ]['name'] )
);
} else {
$link = esc_html( $this->plugins[ $slug ]['name'] ); // No hyperlink.
}
return $link;
}
/**
* Determine if we're on the TGMPA Install page.
*
* @since 2.1.0
*
* @return boolean True when on the TGMPA page, false otherwise.
*/
protected function is_tgmpa_page() {
return isset( $_GET['page'] ) && $this->menu === $_GET['page'];
}
/**
* Retrieve the URL to the TGMPA Install page.
*
* I.e. depending on the config settings passed something along the lines of:
* http://example.com/wp-admin/themes.php?page=tgmpa-install-plugins
*
* @since 2.5.0
*
* @return string Properly encoded URL (not escaped).
*/
public function get_tgmpa_url() {
static $url;
if ( ! isset( $url ) ) {
$parent = $this->parent_slug;
if ( false === strpos( $parent, '.php' ) ) {
$parent = 'admin.php';
}
$url = add_query_arg(
array(
'page' => urlencode( $this->menu ),
),
self_admin_url( $parent )
);
}
return $url;
}
/**
* Retrieve the URL to the TGMPA Install page for a specific plugin status (view).
*
* I.e. depending on the config settings passed something along the lines of:
* http://example.com/wp-admin/themes.php?page=tgmpa-install-plugins&plugin_status=install
*
* @since 2.5.0
*
* @param string $status Plugin status - either 'install', 'update' or 'activate'.
* @return string Properly encoded URL (not escaped).
*/
public function get_tgmpa_status_url( $status ) {
return add_query_arg(
array(
'plugin_status' => urlencode( $status ),
),
$this->get_tgmpa_url()
);
}
/**
* Determine whether there are open actions for plugins registered with TGMPA.
*
* @since 2.5.0
*
* @return bool True if complete, i.e. no outstanding actions. False otherwise.
*/
public function is_tgmpa_complete() {
$complete = true;
foreach ( $this->plugins as $slug => $plugin ) {
if ( ! $this->is_plugin_active( $slug ) || false !== $this->does_plugin_have_update( $slug ) ) {
$complete = false;
break;
}
}
return $complete;
}
/**
* Check if a plugin is installed. Does not take must-use plugins into account.
*
* @since 2.5.0
*
* @param string $slug Plugin slug.
* @return bool True if installed, false otherwise.
*/
public function is_plugin_installed( $slug ) {
$installed_plugins = $this->get_plugins(); // Retrieve a list of all installed plugins (WP cached).
return ( ! empty( $installed_plugins[ $this->plugins[ $slug ]['file_path'] ] ) );
}
/**
* Check if a plugin is active.
*
* @since 2.5.0
*
* @param string $slug Plugin slug.
* @return bool True if active, false otherwise.
*/
public function is_plugin_active( $slug ) {
return ( ( ! empty( $this->plugins[ $slug ]['is_callable'] ) && is_callable( $this->plugins[ $slug ]['is_callable'] ) ) || is_plugin_active( $this->plugins[ $slug ]['file_path'] ) );
}
/**
* Check if a plugin can be updated, i.e. if we have information on the minimum WP version required
* available, check whether the current install meets them.
*
* @since 2.5.0
*
* @param string $slug Plugin slug.
* @return bool True if OK to update, false otherwise.
*/
public function can_plugin_update( $slug ) {
// We currently can't get reliable info on non-WP-repo plugins - issue #380.
if ( 'repo' !== $this->plugins[ $slug ]['source_type'] ) {
return true;
}
$api = $this->get_plugins_api( $slug );
if ( false !== $api && isset( $api->requires ) ) {
return version_compare( $GLOBALS['wp_version'], $api->requires, '>=' );
}
// No usable info received from the plugins API, presume we can update.
return true;
}
/**
* Check if a plugin can be activated, i.e. is not currently active and meets the minimum
* plugin version requirements set in TGMPA (if any).
*
* @since 2.5.0
*
* @param string $slug Plugin slug.
* @return bool True if OK to activate, false otherwise.
*/
public function can_plugin_activate( $slug ) {
return ( ! $this->is_plugin_active( $slug ) && ! $this->does_plugin_require_update( $slug ) );
}
/**
* Retrieve the version number of an installed plugin.
*
* @since 2.5.0
*
* @param string $slug Plugin slug.
* @return string Version number as string or an empty string if the plugin is not installed
* or version unknown (plugins which don't comply with the plugin header standard).
*/
public function get_installed_version( $slug ) {
$installed_plugins = $this->get_plugins(); // Retrieve a list of all installed plugins (WP cached).
if ( ! empty( $installed_plugins[ $this->plugins[ $slug ]['file_path'] ]['Version'] ) ) {
return $installed_plugins[ $this->plugins[ $slug ]['file_path'] ]['Version'];
}
return '';
}
/**
* Check whether a plugin complies with the minimum version requirements.
*
* @since 2.5.0
*
* @param string $slug Plugin slug.
* @return bool True when a plugin needs to be updated, otherwise false.
*/
public function does_plugin_require_update( $slug ) {
$installed_version = $this->get_installed_version( $slug );
$minimum_version = $this->plugins[ $slug ]['version'];
return version_compare( $minimum_version, $installed_version, '>' );
}
/**
* Check whether there is an update available for a plugin.
*
* @since 2.5.0
*
* @param string $slug Plugin slug.
* @return false|string Version number string of the available update or false if no update available.
*/
public function does_plugin_have_update( $slug ) {
// Presume bundled and external plugins will point to a package which meets the minimum required version.
if ( 'repo' !== $this->plugins[ $slug ]['source_type'] ) {
if ( $this->does_plugin_require_update( $slug ) ) {
return $this->plugins[ $slug ]['version'];
}
return false;
}
$repo_updates = get_site_transient( 'update_plugins' );
if ( isset( $repo_updates->response[ $this->plugins[ $slug ]['file_path'] ]->new_version ) ) {
return $repo_updates->response[ $this->plugins[ $slug ]['file_path'] ]->new_version;
}
return false;
}
/**
* Retrieve potential upgrade notice for a plugin.
*
* @since 2.5.0
*
* @param string $slug Plugin slug.
* @return string The upgrade notice or an empty string if no message was available or provided.
*/
public function get_upgrade_notice( $slug ) {
// We currently can't get reliable info on non-WP-repo plugins - issue #380.
if ( 'repo' !== $this->plugins[ $slug ]['source_type'] ) {
return '';
}
$repo_updates = get_site_transient( 'update_plugins' );
if ( ! empty( $repo_updates->response[ $this->plugins[ $slug ]['file_path'] ]->upgrade_notice ) ) {
return $repo_updates->response[ $this->plugins[ $slug ]['file_path'] ]->upgrade_notice;
}
return '';
}
/**
* Wrapper around the core WP get_plugins function, making sure it's actually available.
*
* @since 2.5.0
*
* @param string $plugin_folder Optional. Relative path to single plugin folder.
* @return array Array of installed plugins with plugin information.
*/
public function get_plugins( $plugin_folder = '' ) {
if ( ! function_exists( 'get_plugins' ) ) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
return get_plugins( $plugin_folder );
}
/**
* Delete dismissable nag option when theme is switched.
*
* This ensures that the user(s) is/are again reminded via nag of required
* and/or recommended plugins if they re-activate the theme.
*
* @since 2.1.1
*/
public function update_dismiss() {
delete_metadata( 'user', null, 'tgmpa_dismissed_notice_' . $this->id, null, true );
}
/**
* Forces plugin activation if the parameter 'force_activation' is
* set to true.
*
* This allows theme authors to specify certain plugins that must be
* active at all times while using the current theme.
*
* Please take special care when using this parameter as it has the
* potential to be harmful if not used correctly. Setting this parameter
* to true will not allow the specified plugin to be deactivated unless
* the user switches themes.
*
* @since 2.2.0
*/
public function force_activation() {
foreach ( $this->plugins as $slug => $plugin ) {
if ( true === $plugin['force_activation'] ) {
if ( ! $this->is_plugin_installed( $slug ) ) {
// Oops, plugin isn't there so iterate to next condition.
continue;
} elseif ( $this->can_plugin_activate( $slug ) ) {
// There we go, activate the plugin.
activate_plugin( $plugin['file_path'] );
}
}
}
}
/**
* Forces plugin deactivation if the parameter 'force_deactivation'
* is set to true.
*
* This allows theme authors to specify certain plugins that must be
* deactivated upon switching from the current theme to another.
*
* Please take special care when using this parameter as it has the
* potential to be harmful if not used correctly.
*
* @since 2.2.0
*/
public function force_deactivation() {
foreach ( $this->plugins as $slug => $plugin ) {
// Only proceed forward if the parameter is set to true and plugin is active.
if ( true === $plugin['force_deactivation'] && $this->is_plugin_active( $slug ) ) {
deactivate_plugins( $plugin['file_path'] );
}
}
}
/**
* Echo the current TGMPA version number to the page.
*/
public function show_tgmpa_version() {
echo '<p style="float: right; padding: 0em 1.5em 0.5em 0;"><strong><small>',
esc_html( sprintf( _x( 'TGMPA v%s', '%s = version number', 'tgmpa' ), self::TGMPA_VERSION ) ),
'</small></strong></p>';
}
/**
* Returns the singleton instance of the class.
*
* @since 2.4.0
*
* @return object The TGM_Plugin_Activation object.
*/
public static function get_instance() {
if ( ! isset( self::$instance ) && ! ( self::$instance instanceof self ) ) {
self::$instance = new self();
}
return self::$instance;
}
}
if ( ! function_exists( 'load_tgm_plugin_activation' ) ) {
/**
* Ensure only one instance of the class is ever invoked.
*/
function load_tgm_plugin_activation() {
$GLOBALS['tgmpa'] = TGM_Plugin_Activation::get_instance();
}
}
if ( did_action( 'plugins_loaded' ) ) {
load_tgm_plugin_activation();
} else {
add_action( 'plugins_loaded', 'load_tgm_plugin_activation' );
}
}
if ( ! function_exists( 'tgmpa' ) ) {
/**
* Helper function to register a collection of required plugins.
*
* @since 2.0.0
* @api
*
* @param array $plugins An array of plugin arrays.
* @param array $config Optional. An array of configuration values.
*/
function tgmpa( $plugins, $config = array() ) {
$instance = call_user_func( array( get_class( $GLOBALS['tgmpa'] ), 'get_instance' ) );
foreach ( $plugins as $plugin ) {
call_user_func( array( $instance, 'register' ), $plugin );
}
if ( ! empty( $config ) && is_array( $config ) ) {
// Send out notices for deprecated arguments passed.
if ( isset( $config['notices'] ) ) {
_deprecated_argument( __FUNCTION__, '2.2.0', 'The `notices` config parameter was renamed to `has_notices` in TGMPA 2.2.0. Please adjust your configuration.' );
if ( ! isset( $config['has_notices'] ) ) {
$config['has_notices'] = $config['notices'];
}
}
if ( isset( $config['parent_menu_slug'] ) ) {
_deprecated_argument( __FUNCTION__, '2.4.0', 'The `parent_menu_slug` config parameter was removed in TGMPA 2.4.0. In TGMPA 2.5.0 an alternative was (re-)introduced. Please adjust your configuration. For more information visit the website: http://tgmpluginactivation.com/configuration/#h-configuration-options.' );
}
if ( isset( $config['parent_url_slug'] ) ) {
_deprecated_argument( __FUNCTION__, '2.4.0', 'The `parent_url_slug` config parameter was removed in TGMPA 2.4.0. In TGMPA 2.5.0 an alternative was (re-)introduced. Please adjust your configuration. For more information visit the website: http://tgmpluginactivation.com/configuration/#h-configuration-options.' );
}
call_user_func( array( $instance, 'config' ), $config );
}
}
}
/**
* WP_List_Table isn't always available. If it isn't available,
* we load it here.
*
* @since 2.2.0
*/
if ( ! class_exists( 'WP_List_Table' ) ) {
require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
}
if ( ! class_exists( 'TGMPA_List_Table' ) ) {
/**
* List table class for handling plugins.
*
* Extends the WP_List_Table class to provide a future-compatible
* way of listing out all required/recommended plugins.
*
* Gives users an interface similar to the Plugin Administration
* area with similar (albeit stripped down) capabilities.
*
* This class also allows for the bulk install of plugins.
*
* @since 2.2.0
*
* @package TGM-Plugin-Activation
* @author Thomas Griffin
* @author Gary Jones
*/
class TGMPA_List_Table extends WP_List_Table {
/**
* TGMPA instance.
*
* @since 2.5.0
*
* @var object
*/
protected $tgmpa;
/**
* The currently chosen view.
*
* @since 2.5.0
*
* @var string One of: 'all', 'install', 'update', 'activate'
*/
public $view_context = 'all';
/**
* The plugin counts for the various views.
*
* @since 2.5.0
*
* @var array
*/
protected $view_totals = array(
'all' => 0,
'install' => 0,
'update' => 0,
'activate' => 0,
);
/**
* References parent constructor and sets defaults for class.
*
* @since 2.2.0
*/
public function __construct() {
$this->tgmpa = call_user_func( array( get_class( $GLOBALS['tgmpa'] ), 'get_instance' ) );
parent::__construct(
array(
'singular' => 'plugin',
'plural' => 'plugins',
'ajax' => false,
)
);
if ( isset( $_REQUEST['plugin_status'] ) && in_array( $_REQUEST['plugin_status'], array( 'install', 'update', 'activate' ), true ) ) {
$this->view_context = sanitize_key( $_REQUEST['plugin_status'] );
}
add_filter( 'tgmpa_table_data_items', array( $this, 'sort_table_items' ) );
}
/**
* Get a list of CSS classes for the <table> tag.
*
* Overruled to prevent the 'plural' argument from being added.
*
* @since 2.5.0
*
* @return array CSS classnames.
*/
public function get_table_classes() {
return array( 'widefat', 'fixed' );
}
/**
* Gathers and renames all of our plugin information to be used by WP_List_Table to create our table.
*
* @since 2.2.0
*
* @return array $table_data Information for use in table.
*/
protected function _gather_plugin_data() {
// Load thickbox for plugin links.
$this->tgmpa->admin_init();
$this->tgmpa->thickbox();
// Categorize the plugins which have open actions.
$plugins = $this->categorize_plugins_to_views();
// Set the counts for the view links.
$this->set_view_totals( $plugins );
// Prep variables for use and grab list of all installed plugins.
$table_data = array();
$i = 0;
// Redirect to the 'all' view if no plugins were found for the selected view context.
if ( empty( $plugins[ $this->view_context ] ) ) {
$this->view_context = 'all';
}
foreach ( $plugins[ $this->view_context ] as $slug => $plugin ) {
$table_data[ $i ]['sanitized_plugin'] = $plugin['name'];
$table_data[ $i ]['slug'] = $slug;
$table_data[ $i ]['plugin'] = '<strong>' . $this->tgmpa->get_info_link( $slug ) . '</strong>';
$table_data[ $i ]['source'] = $this->get_plugin_source_type_text( $plugin['source_type'] );
$table_data[ $i ]['type'] = $this->get_plugin_advise_type_text( $plugin['required'] );
$table_data[ $i ]['status'] = $this->get_plugin_status_text( $slug );
$table_data[ $i ]['installed_version'] = $this->tgmpa->get_installed_version( $slug );
$table_data[ $i ]['minimum_version'] = $plugin['version'];
$table_data[ $i ]['available_version'] = $this->tgmpa->does_plugin_have_update( $slug );
// Prep the upgrade notice info.
$upgrade_notice = $this->tgmpa->get_upgrade_notice( $slug );
if ( ! empty( $upgrade_notice ) ) {
$table_data[ $i ]['upgrade_notice'] = $upgrade_notice;
add_action( "tgmpa_after_plugin_row_$slug", array( $this, 'wp_plugin_update_row' ), 10, 2 );
}
$table_data[ $i ] = apply_filters( 'tgmpa_table_data_item', $table_data[ $i ], $plugin );
$i++;
}
return $table_data;
}
/**
* Categorize the plugins which have open actions into views for the TGMPA page.
*
* @since 2.5.0
*/
protected function categorize_plugins_to_views() {
$plugins = array(
'all' => array(), // Meaning: all plugins which still have open actions.
'install' => array(),
'update' => array(),
'activate' => array(),
);
foreach ( $this->tgmpa->plugins as $slug => $plugin ) {
if ( $this->tgmpa->is_plugin_active( $slug ) && false === $this->tgmpa->does_plugin_have_update( $slug ) ) {
// No need to display plugins if they are installed, up-to-date and active.
continue;
} else {
$plugins['all'][ $slug ] = $plugin;
if ( ! $this->tgmpa->is_plugin_installed( $slug ) ) {
$plugins['install'][ $slug ] = $plugin;
} else {
if ( false !== $this->tgmpa->does_plugin_have_update( $slug ) ) {
$plugins['update'][ $slug ] = $plugin;
}
if ( $this->tgmpa->can_plugin_activate( $slug ) ) {
$plugins['activate'][ $slug ] = $plugin;
}
}
}
}
return $plugins;
}
/**
* Set the counts for the view links.
*
* @since 2.5.0
*
* @param array $plugins Plugins order by view.
*/
protected function set_view_totals( $plugins ) {
foreach ( $plugins as $type => $list ) {
$this->view_totals[ $type ] = count( $list );
}
}
/**
* Get the plugin required/recommended text string.
*
* @since 2.5.0
*
* @param string $required Plugin required setting.
* @return string
*/
protected function get_plugin_advise_type_text( $required ) {
if ( true === $required ) {
return __( 'Required', 'tgmpa' );
}
return __( 'Recommended', 'tgmpa' );
}
/**
* Get the plugin source type text string.
*
* @since 2.5.0
*
* @param string $type Plugin type.
* @return string
*/
protected function get_plugin_source_type_text( $type ) {
$string = '';
switch ( $type ) {
case 'repo':
$string = __( 'WordPress Repository', 'tgmpa' );
break;
case 'external':
$string = __( 'External Source', 'tgmpa' );
break;
case 'bundled':
$string = __( 'Pre-Packaged', 'tgmpa' );
break;
}
return $string;
}
/**
* Determine the plugin status message.
*
* @since 2.5.0
*
* @param string $slug Plugin slug.
* @return string
*/
protected function get_plugin_status_text( $slug ) {
if ( ! $this->tgmpa->is_plugin_installed( $slug ) ) {
return __( 'Not Installed', 'tgmpa' );
}
if ( ! $this->tgmpa->is_plugin_active( $slug ) ) {
$install_status = __( 'Installed But Not Activated', 'tgmpa' );
} else {
$install_status = __( 'Active', 'tgmpa' );
}
$update_status = '';
if ( $this->tgmpa->does_plugin_require_update( $slug ) && false === $this->tgmpa->does_plugin_have_update( $slug ) ) {
$update_status = __( 'Required Update not Available', 'tgmpa' );
} elseif ( $this->tgmpa->does_plugin_require_update( $slug ) ) {
$update_status = __( 'Requires Update', 'tgmpa' );
} elseif ( false !== $this->tgmpa->does_plugin_have_update( $slug ) ) {
$update_status = __( 'Update recommended', 'tgmpa' );
}
if ( '' === $update_status ) {
return $install_status;
}
return sprintf(
_x( '%1$s, %2$s', '%1$s = install status, %2$s = update status', 'tgmpa' ),
$install_status,
$update_status
);
}
/**
* Sort plugins by Required/Recommended type and by alphabetical plugin name within each type.
*
* @since 2.5.0
*
* @param array $items Prepared table items.
* @return array Sorted table items.
*/
public function sort_table_items( $items ) {
$type = array();
$name = array();
foreach ( $items as $i => $plugin ) {
$type[ $i ] = $plugin['type']; // Required / recommended.
$name[ $i ] = $plugin['sanitized_plugin'];
}
array_multisort( $type, SORT_DESC, $name, SORT_ASC, $items );
return $items;
}
/**
* Get an associative array ( id => link ) of the views available on this table.
*
* @since 2.5.0
*
* @return array
*/
public function get_views() {
$status_links = array();
foreach ( $this->view_totals as $type => $count ) {
if ( $count < 1 ) {
continue;
}
switch ( $type ) {
case 'all':
$text = _nx( 'All <span class="count">(%s)</span>', 'All <span class="count">(%s)</span>', $count, 'plugins', 'tgmpa' );
break;
case 'install':
$text = _n( 'To Install <span class="count">(%s)</span>', 'To Install <span class="count">(%s)</span>', $count, 'tgmpa' );
break;
case 'update':
$text = _n( 'Update Available <span class="count">(%s)</span>', 'Update Available <span class="count">(%s)</span>', $count, 'tgmpa' );
break;
case 'activate':
$text = _n( 'To Activate <span class="count">(%s)</span>', 'To Activate <span class="count">(%s)</span>', $count, 'tgmpa' );
break;
default:
$text = '';
break;
}
if ( ! empty( $text ) ) {
$status_links[ $type ] = sprintf(
'<a href="%s"%s>%s</a>',
esc_url( $this->tgmpa->get_tgmpa_status_url( $type ) ),
( $type === $this->view_context ) ? ' class="current"' : '',
sprintf( $text, number_format_i18n( $count ) )
);
}
}
return $status_links;
}
/**
* Create default columns to display important plugin information
* like type, action and status.
*
* @since 2.2.0
*
* @param array $item Array of item data.
* @param string $column_name The name of the column.
* @return string
*/
public function column_default( $item, $column_name ) {
return $item[ $column_name ];
}
/**
* Required for bulk installing.
*
* Adds a checkbox for each plugin.
*
* @since 2.2.0
*
* @param array $item Array of item data.
* @return string The input checkbox with all necessary info.
*/
public function column_cb( $item ) {
return sprintf(
'<input type="checkbox" name="%1$s[]" value="%2$s" id="%3$s" />',
esc_attr( $this->_args['singular'] ),
esc_attr( $item['slug'] ),
esc_attr( $item['sanitized_plugin'] )
);
}
/**
* Create default title column along with the action links.
*
* @since 2.2.0
*
* @param array $item Array of item data.
* @return string The plugin name and action links.
*/
public function column_plugin( $item ) {
return sprintf(
'%1$s %2$s',
$item['plugin'],
$this->row_actions( $this->get_row_actions( $item ), true )
);
}
/**
* Create version information column.
*
* @since 2.5.0
*
* @param array $item Array of item data.
* @return string HTML-formatted version information.
*/
public function column_version( $item ) {
$output = array();
if ( $this->tgmpa->is_plugin_installed( $item['slug'] ) ) {
$installed = ! empty( $item['installed_version'] ) ? $item['installed_version'] : _x( 'unknown', 'as in: "version nr unknown"', 'tgmpa' );
$color = '';
if ( ! empty( $item['minimum_version'] ) && $this->tgmpa->does_plugin_require_update( $item['slug'] ) ) {
$color = ' color: #ff0000; font-weight: bold;';
}
$output[] = sprintf(
'<p><span style="min-width: 32px; text-align: right; float: right;%1$s">%2$s</span>' . __( 'Installed version:', 'tgmpa' ) . '</p>',
$color,
$installed
);
}
if ( ! empty( $item['minimum_version'] ) ) {
$output[] = sprintf(
'<p><span style="min-width: 32px; text-align: right; float: right;">%1$s</span>' . __( 'Minimum required version:', 'tgmpa' ) . '</p>',
$item['minimum_version']
);
}
if ( ! empty( $item['available_version'] ) ) {
$color = '';
if ( ! empty( $item['minimum_version'] ) && version_compare( $item['available_version'], $item['minimum_version'], '>=' ) ) {
$color = ' color: #71C671; font-weight: bold;';
}
$output[] = sprintf(
'<p><span style="min-width: 32px; text-align: right; float: right;%1$s">%2$s</span>' . __( 'Available version:', 'tgmpa' ) . '</p>',
$color,
$item['available_version']
);
}
if ( empty( $output ) ) {
return ' '; // Let's not break the table layout.
} else {
return implode( "\n", $output );
}
}
/**
* Sets default message within the plugins table if no plugins
* are left for interaction.
*
* Hides the menu item to prevent the user from clicking and
* getting a permissions error.
*
* @since 2.2.0
*/
public function no_items() {
printf( wp_kses_post( __( 'No plugins to install, update or activate. <a href="%1$s">Return to the Dashboard</a>', 'tgmpa' ) ), esc_url( self_admin_url() ) );
echo '<style type="text/css">#adminmenu .wp-submenu li.current { display: none !important; }</style>';
}
/**
* Output all the column information within the table.
*
* @since 2.2.0
*
* @return array $columns The column names.
*/
public function get_columns() {
$columns = array(
'cb' => '<input type="checkbox" />',
'plugin' => __( 'Plugin', 'tgmpa' ),
'source' => __( 'Source', 'tgmpa' ),
'type' => __( 'Type', 'tgmpa' ),
);
if ( 'all' === $this->view_context || 'update' === $this->view_context ) {
$columns['version'] = __( 'Version', 'tgmpa' );
$columns['status'] = __( 'Status', 'tgmpa' );
}
return apply_filters( 'tgmpa_table_columns', $columns );
}
/**
* Get name of default primary column
*
* @since 2.5.0 / WP 4.3+ compatibility
* @access protected
*
* @return string
*/
protected function get_default_primary_column_name() {
return 'plugin';
}
/**
* Get the name of the primary column.
*
* @since 2.5.0 / WP 4.3+ compatibility
* @access protected
*
* @return string The name of the primary column.
*/
protected function get_primary_column_name() {
if ( method_exists( 'WP_List_Table', 'get_primary_column_name' ) ) {
return parent::get_primary_column_name();
} else {
return $this->get_default_primary_column_name();
}
}
/**
* Get the actions which are relevant for a specific plugin row.
*
* @since 2.5.0
*
* @param array $item Array of item data.
* @return array Array with relevant action links.
*/
protected function get_row_actions( $item ) {
$actions = array();
$action_links = array();
// Display the 'Install' action link if the plugin is not yet available.
if ( ! $this->tgmpa->is_plugin_installed( $item['slug'] ) ) {
$actions['install'] = _x( 'Install %2$s', '%2$s = plugin name in screen reader markup', 'tgmpa' );
} else {
// Display the 'Update' action link if an update is available and WP complies with plugin minimum.
if ( false !== $this->tgmpa->does_plugin_have_update( $item['slug'] ) && $this->tgmpa->can_plugin_update( $item['slug'] ) ) {
$actions['update'] = _x( 'Update %2$s', '%2$s = plugin name in screen reader markup', 'tgmpa' );
}
// Display the 'Activate' action link, but only if the plugin meets the minimum version.
if ( $this->tgmpa->can_plugin_activate( $item['slug'] ) ) {
$actions['activate'] = _x( 'Activate %2$s', '%2$s = plugin name in screen reader markup', 'tgmpa' );
}
}
// Create the actual links.
foreach ( $actions as $action => $text ) {
$nonce_url = wp_nonce_url(
add_query_arg(
array(
'plugin' => urlencode( $item['slug'] ),
'tgmpa-' . $action => $action . '-plugin',
),
$this->tgmpa->get_tgmpa_url()
),
'tgmpa-' . $action,
'tgmpa-nonce'
);
$action_links[ $action ] = sprintf(
'<a href="%1$s">' . esc_html( $text ) . '</a>',
esc_url( $nonce_url ),
'<span class="screen-reader-text">' . esc_html( $item['sanitized_plugin'] ) . '</span>'
);
}
$prefix = ( defined( 'WP_NETWORK_ADMIN' ) && WP_NETWORK_ADMIN ) ? 'network_admin_' : '';
return apply_filters( "tgmpa_{$prefix}plugin_action_links", array_filter( $action_links ), $item['slug'], $item, $this->view_context );
}
/**
* Generates content for a single row of the table.
*
* @since 2.5.0
*
* @param object $item The current item.
*/
public function single_row( $item ) {
parent::single_row( $item );
/**
* Fires after each specific row in the TGMPA Plugins list table.
*
* The dynamic portion of the hook name, `$item['slug']`, refers to the slug
* for the plugin.
*
* @since 2.5.0
*/
do_action( "tgmpa_after_plugin_row_{$item['slug']}", $item['slug'], $item, $this->view_context );
}
/**
* Show the upgrade notice below a plugin row if there is one.
*
* @since 2.5.0
*
* @see /wp-admin/includes/update.php
*
* @param string $slug Plugin slug.
* @param array $item The information available in this table row.
* @return null Return early if upgrade notice is empty.
*/
public function wp_plugin_update_row( $slug, $item ) {
if ( empty( $item['upgrade_notice'] ) ) {
return;
}
echo '
<tr class="plugin-update-tr">
<td colspan="', absint( $this->get_column_count() ), '" class="plugin-update colspanchange">
<div class="update-message">',
esc_html__( 'Upgrade message from the plugin author:', 'tgmpa' ),
' <strong>', wp_kses_data( $item['upgrade_notice'] ), '</strong>
</div>
</td>
</tr>';
}
/**
* Extra controls to be displayed between bulk actions and pagination.
*
* @since 2.5.0
*
* @param string $which 'top' or 'bottom' table navigation.
*/
public function extra_tablenav( $which ) {
if ( 'bottom' === $which ) {
$this->tgmpa->show_tgmpa_version();
}
}
/**
* Defines the bulk actions for handling registered plugins.
*
* @since 2.2.0
*
* @return array $actions The bulk actions for the plugin install table.
*/
public function get_bulk_actions() {
$actions = array();
if ( 'update' !== $this->view_context && 'activate' !== $this->view_context ) {
if ( current_user_can( 'install_plugins' ) ) {
$actions['tgmpa-bulk-install'] = __( 'Install', 'tgmpa' );
}
}
if ( 'install' !== $this->view_context ) {
if ( current_user_can( 'update_plugins' ) ) {
$actions['tgmpa-bulk-update'] = __( 'Update', 'tgmpa' );
}
if ( current_user_can( 'activate_plugins' ) ) {
$actions['tgmpa-bulk-activate'] = __( 'Activate', 'tgmpa' );
}
}
return $actions;
}
/**
* Processes bulk installation and activation actions.
*
* The bulk installation process looks for the $_POST information and passes that
* through if a user has to use WP_Filesystem to enter their credentials.
*
* @since 2.2.0
*/
public function process_bulk_actions() {
// Bulk installation process.
if ( 'tgmpa-bulk-install' === $this->current_action() || 'tgmpa-bulk-update' === $this->current_action() ) {
check_admin_referer( 'bulk-' . $this->_args['plural'] );
$install_type = 'install';
if ( 'tgmpa-bulk-update' === $this->current_action() ) {
$install_type = 'update';
}
$plugins_to_install = array();
// Did user actually select any plugins to install/update ?
if ( empty( $_POST['plugin'] ) ) {
if ( 'install' === $install_type ) {
$message = __( 'No plugins were selected to be installed. No action taken.', 'tgmpa' );
} else {
$message = __( 'No plugins were selected to be updated. No action taken.', 'tgmpa' );
}
echo '<div id="message" class="error"><p>', esc_html( $message ), '</p></div>';
return false;
}
if ( is_array( $_POST['plugin'] ) ) {
$plugins_to_install = (array) $_POST['plugin'];
} elseif ( is_string( $_POST['plugin'] ) ) {
// Received via Filesystem page - un-flatten array (WP bug #19643).
$plugins_to_install = explode( ',', $_POST['plugin'] );
}
// Sanitize the received input.
$plugins_to_install = array_map( 'urldecode', $plugins_to_install );
$plugins_to_install = array_map( array( $this->tgmpa, 'sanitize_key' ), $plugins_to_install );
// Validate the received input.
foreach ( $plugins_to_install as $key => $slug ) {
// Check if the plugin was registered with TGMPA and remove if not.
if ( ! isset( $this->tgmpa->plugins[ $slug ] ) ) {
unset( $plugins_to_install[ $key ] );
continue;
}
// For updates: make sure this is a plugin we *can* update (update available and WP version ok).
if ( 'update' === $install_type && ( $this->tgmpa->is_plugin_installed( $slug ) && ( false === $this->tgmpa->does_plugin_have_update( $slug ) || ! $this->tgmpa->can_plugin_update( $slug ) ) ) ) {
unset( $plugins_to_install[ $key ] );
}
}
// No need to proceed further if we have no plugins to handle.
if ( empty( $plugins_to_install ) ) {
if ( 'install' === $install_type ) {
$message = __( 'No plugins are available to be installed at this time.', 'tgmpa' );
} else {
$message = __( 'No plugins are available to be updated at this time.', 'tgmpa' );
}
echo '<div id="message" class="error"><p>', esc_html( $message ), '</p></div>';
return false;
}
// Pass all necessary information if WP_Filesystem is needed.
$url = wp_nonce_url(
$this->tgmpa->get_tgmpa_url(),
'bulk-' . $this->_args['plural']
);
// Give validated data back to $_POST which is the only place the filesystem looks for extra fields.
$_POST['plugin'] = implode( ',', $plugins_to_install ); // Work around for WP bug #19643.
$method = ''; // Leave blank so WP_Filesystem can populate it as necessary.
$fields = array_keys( $_POST ); // Extra fields to pass to WP_Filesystem.
if ( false === ( $creds = request_filesystem_credentials( esc_url_raw( $url ), $method, false, false, $fields ) ) ) {
return true; // Stop the normal page form from displaying, credential request form will be shown.
}
// Now we have some credentials, setup WP_Filesystem.
if ( ! WP_Filesystem( $creds ) ) {
// Our credentials were no good, ask the user for them again.
request_filesystem_credentials( esc_url_raw( $url ), $method, true, false, $fields );
return true;
}
/* If we arrive here, we have the filesystem */
// Store all information in arrays since we are processing a bulk installation.
$names = array();
$sources = array(); // Needed for installs.
$file_paths = array(); // Needed for upgrades.
$to_inject = array(); // Information to inject into the update_plugins transient.
// Prepare the data for validated plugins for the install/upgrade.
foreach ( $plugins_to_install as $slug ) {
$name = $this->tgmpa->plugins[ $slug ]['name'];
$source = $this->tgmpa->get_download_url( $slug );
if ( ! empty( $name ) && ! empty( $source ) ) {
$names[] = $name;
switch ( $install_type ) {
case 'install':
$sources[] = $source;
break;
case 'update':
$file_paths[] = $this->tgmpa->plugins[ $slug ]['file_path'];
$to_inject[ $slug ] = $this->tgmpa->plugins[ $slug ];
$to_inject[ $slug ]['source'] = $source;
break;
}
}
}
unset( $slug, $name, $source );
// Create a new instance of TGMPA_Bulk_Installer.
$installer = new TGMPA_Bulk_Installer(
new TGMPA_Bulk_Installer_Skin(
array(
'url' => esc_url_raw( $this->tgmpa->get_tgmpa_url() ),
'nonce' => 'bulk-' . $this->_args['plural'],
'names' => $names,
'install_type' => $install_type,
)
)
);
// Wrap the install process with the appropriate HTML.
echo '<div class="tgmpa wrap">',
'<h2>', esc_html( get_admin_page_title() ), '</h2>';
// Process the bulk installation submissions.
add_filter( 'upgrader_source_selection', array( $this->tgmpa, 'maybe_adjust_source_dir' ), 1, 3 );
if ( 'tgmpa-bulk-update' === $this->current_action() ) {
// Inject our info into the update transient.
$this->tgmpa->inject_update_info( $to_inject );
$installer->bulk_upgrade( $file_paths );
} else {
$installer->bulk_install( $sources );
}
remove_filter( 'upgrader_source_selection', array( $this->tgmpa, 'maybe_adjust_source_dir' ), 1, 3 );
echo '</div>';
return true;
}
// Bulk activation process.
if ( 'tgmpa-bulk-activate' === $this->current_action() ) {
check_admin_referer( 'bulk-' . $this->_args['plural'] );
// Did user actually select any plugins to activate ?
if ( empty( $_POST['plugin'] ) ) {
echo '<div id="message" class="error"><p>', esc_html__( 'No plugins were selected to be activated. No action taken.', 'tgmpa' ), '</p></div>';
return false;
}
// Grab plugin data from $_POST.
$plugins = array();
if ( isset( $_POST['plugin'] ) ) {
$plugins = array_map( 'urldecode', (array) $_POST['plugin'] );
$plugins = array_map( array( $this->tgmpa, 'sanitize_key' ), $plugins );
}
$plugins_to_activate = array();
$plugin_names = array();
// Grab the file paths for the selected & inactive plugins from the registration array.
foreach ( $plugins as $slug ) {
if ( $this->tgmpa->can_plugin_activate( $slug ) ) {
$plugins_to_activate[] = $this->tgmpa->plugins[ $slug ]['file_path'];
$plugin_names[] = $this->tgmpa->plugins[ $slug ]['name'];
}
}
unset( $slug );
// Return early if there are no plugins to activate.
if ( empty( $plugins_to_activate ) ) {
echo '<div id="message" class="error"><p>', esc_html__( 'No plugins are available to be activated at this time.', 'tgmpa' ), '</p></div>';
return false;
}
// Now we are good to go - let's start activating plugins.
$activate = activate_plugins( $plugins_to_activate );
if ( is_wp_error( $activate ) ) {
echo '<div id="message" class="error"><p>', wp_kses_post( $activate->get_error_message() ), '</p></div>';
} else {
$count = count( $plugin_names ); // Count so we can use _n function.
$plugin_names = array_map( array( 'TGMPA_Utils', 'wrap_in_strong' ), $plugin_names );
$last_plugin = array_pop( $plugin_names ); // Pop off last name to prep for readability.
$imploded = empty( $plugin_names ) ? $last_plugin : ( implode( ', ', $plugin_names ) . ' ' . esc_html_x( 'and', 'plugin A *and* plugin B', 'tgmpa' ) . ' ' . $last_plugin );
printf( // WPCS: xss ok.
'<div id="message" class="updated"><p>%1$s %2$s.</p></div>',
esc_html( _n( 'The following plugin was activated successfully:', 'The following plugins were activated successfully:', $count, 'tgmpa' ) ),
$imploded
);
// Update recently activated plugins option.
$recent = (array) get_option( 'recently_activated' );
foreach ( $plugins_to_activate as $plugin => $time ) {
if ( isset( $recent[ $plugin ] ) ) {
unset( $recent[ $plugin ] );
}
}
update_option( 'recently_activated', $recent );
}
unset( $_POST ); // Reset the $_POST variable in case user wants to perform one action after another.
return true;
}
return false;
}
/**
* Prepares all of our information to be outputted into a usable table.
*
* @since 2.2.0
*/
public function prepare_items() {
$columns = $this->get_columns(); // Get all necessary column information.
$hidden = array(); // No columns to hide, but we must set as an array.
$sortable = array(); // No reason to make sortable columns.
$primary = $this->get_primary_column_name(); // Column which has the row actions.
$this->_column_headers = array( $columns, $hidden, $sortable, $primary ); // Get all necessary column headers.
// Process our bulk activations here.
if ( 'tgmpa-bulk-activate' === $this->current_action() ) {
$this->process_bulk_actions();
}
// Store all of our plugin data into $items array so WP_List_Table can use it.
$this->items = apply_filters( 'tgmpa_table_data_items', $this->_gather_plugin_data() );
}
/* *********** DEPRECATED METHODS *********** */
/**
* Retrieve plugin data, given the plugin name.
*
* @since 2.2.0
* @deprecated 2.5.0 use {@see TGM_Plugin_Activation::_get_plugin_data_from_name()} instead.
* @see TGM_Plugin_Activation::_get_plugin_data_from_name()
*
* @param string $name Name of the plugin, as it was registered.
* @param string $data Optional. Array key of plugin data to return. Default is slug.
* @return string|boolean Plugin slug if found, false otherwise.
*/
protected function _get_plugin_data_from_name( $name, $data = 'slug' ) {
_deprecated_function( __FUNCTION__, 'TGMPA 2.5.0', 'TGM_Plugin_Activation::_get_plugin_data_from_name()' );
return $this->tgmpa->_get_plugin_data_from_name( $name, $data );
}
}
}
if ( ! class_exists( 'TGM_Bulk_Installer' ) ) {
/**
* Hack: Prevent TGMPA v2.4.1- bulk installer class from being loaded if 2.4.1- is loaded after 2.5+.
*/
class TGM_Bulk_Installer {
}
}
if ( ! class_exists( 'TGM_Bulk_Installer_Skin' ) ) {
/**
* Hack: Prevent TGMPA v2.4.1- bulk installer skin class from being loaded if 2.4.1- is loaded after 2.5+.
*/
class TGM_Bulk_Installer_Skin {
}
}
/**
* The WP_Upgrader file isn't always available. If it isn't available,
* we load it here.
*
* We check to make sure no action or activation keys are set so that WordPress
* does not try to re-include the class when processing upgrades or installs outside
* of the class.
*
* @since 2.2.0
*/
add_action( 'admin_init', 'tgmpa_load_bulk_installer' );
if ( ! function_exists( 'tgmpa_load_bulk_installer' ) ) {
/**
* Load bulk installer
*/
function tgmpa_load_bulk_installer() {
// Silently fail if 2.5+ is loaded *after* an older version.
if ( ! isset( $GLOBALS['tgmpa'] ) ) {
return;
}
// Get TGMPA class instance.
$tgmpa_instance = call_user_func( array( get_class( $GLOBALS['tgmpa'] ), 'get_instance' ) );
if ( isset( $_GET['page'] ) && $tgmpa_instance->menu === $_GET['page'] ) {
if ( ! class_exists( 'Plugin_Upgrader', false ) ) {
require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
}
if ( ! class_exists( 'TGMPA_Bulk_Installer' ) ) {
/**
* Installer class to handle bulk plugin installations.
*
* Extends WP_Upgrader and customizes to suit the installation of multiple
* plugins.
*
* @since 2.2.0
*
* @internal Since 2.5.0 the class is an extension of Plugin_Upgrader rather than WP_Upgrader
* @internal Since 2.5.2 the class has been renamed from TGM_Bulk_Installer to TGMPA_Bulk_Installer.
* This was done to prevent backward compatibility issues with v2.3.6.
*
* @package TGM-Plugin-Activation
* @author Thomas Griffin
* @author Gary Jones
*/
class TGMPA_Bulk_Installer extends Plugin_Upgrader {
/**
* Holds result of bulk plugin installation.
*
* @since 2.2.0
*
* @var string
*/
public $result;
/**
* Flag to check if bulk installation is occurring or not.
*
* @since 2.2.0
*
* @var boolean
*/
public $bulk = false;
/**
* TGMPA instance
*
* @since 2.5.0
*
* @var object
*/
protected $tgmpa;
/**
* Whether or not the destination directory needs to be cleared ( = on update).
*
* @since 2.5.0
*
* @var bool
*/
protected $clear_destination = false;
/**
* References parent constructor and sets defaults for class.
*
* @since 2.2.0
*
* @param \Bulk_Upgrader_Skin|null $skin Installer skin.
*/
public function __construct( $skin = null ) {
// Get TGMPA class instance.
$this->tgmpa = call_user_func( array( get_class( $GLOBALS['tgmpa'] ), 'get_instance' ) );
parent::__construct( $skin );
if ( isset( $this->skin->options['install_type'] ) && 'update' === $this->skin->options['install_type'] ) {
$this->clear_destination = true;
}
if ( $this->tgmpa->is_automatic ) {
$this->activate_strings();
}
add_action( 'upgrader_process_complete', array( $this->tgmpa, 'populate_file_path' ) );
}
/**
* Sets the correct activation strings for the installer skin to use.
*
* @since 2.2.0
*/
public function activate_strings() {
$this->strings['activation_failed'] = __( 'Plugin activation failed.', 'tgmpa' );
$this->strings['activation_success'] = __( 'Plugin activated successfully.', 'tgmpa' );
}
/**
* Performs the actual installation of each plugin.
*
* @since 2.2.0
*
* @see WP_Upgrader::run()
*
* @param array $options The installation config options.
* @return null|array Return early if error, array of installation data on success.
*/
public function run( $options ) {
$result = parent::run( $options );
// Reset the strings in case we changed one during automatic activation.
if ( $this->tgmpa->is_automatic ) {
if ( 'update' === $this->skin->options['install_type'] ) {
$this->upgrade_strings();
} else {
$this->install_strings();
}
}
return $result;
}
/**
* Processes the bulk installation of plugins.
*
* @since 2.2.0
*
* @internal This is basically a near identical copy of the WP Core Plugin_Upgrader::bulk_upgrade()
* method, with minor adjustments to deal with new installs instead of upgrades.
* For ease of future synchronizations, the adjustments are clearly commented, but no other
* comments are added. Code style has been made to comply.
*
* @see Plugin_Upgrader::bulk_upgrade()
* @see https://core.trac.wordpress.org/browser/tags/4.2.1/src/wp-admin/includes/class-wp-upgrader.php#L838
*
* @param array $plugins The plugin sources needed for installation.
* @param array $args Arbitrary passed extra arguments.
* @return string|bool Install confirmation messages on success, false on failure.
*/
public function bulk_install( $plugins, $args = array() ) {
// [TGMPA + ] Hook auto-activation in.
add_filter( 'upgrader_post_install', array( $this, 'auto_activate' ), 10 );
$defaults = array(
'clear_update_cache' => true,
);
$parsed_args = wp_parse_args( $args, $defaults );
$this->init();
$this->bulk = true;
$this->install_strings(); // [TGMPA + ] adjusted.
/* [TGMPA - ] $current = get_site_transient( 'update_plugins' ); */
/* [TGMPA - ] add_filter('upgrader_clear_destination', array($this, 'delete_old_plugin'), 10, 4); */
$this->skin->header();
// Connect to the Filesystem first.
$res = $this->fs_connect( array( WP_CONTENT_DIR, WP_PLUGIN_DIR ) );
if ( ! $res ) {
$this->skin->footer();
return false;
}
$this->skin->bulk_header();
// Only start maintenance mode if:
// - running Multisite and there are one or more plugins specified, OR
// - a plugin with an update available is currently active.
// @TODO: For multisite, maintenance mode should only kick in for individual sites if at all possible.
$maintenance = ( is_multisite() && ! empty( $plugins ) );
/*
[TGMPA - ]
foreach ( $plugins as $plugin )
$maintenance = $maintenance || ( is_plugin_active( $plugin ) && isset( $current->response[ $plugin] ) );
*/
if ( $maintenance ) {
$this->maintenance_mode( true );
}
$results = array();
$this->update_count = count( $plugins );
$this->update_current = 0;
foreach ( $plugins as $plugin ) {
$this->update_current++;
/*
[TGMPA - ]
$this->skin->plugin_info = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin, false, true);
if ( !isset( $current->response[ $plugin ] ) ) {
$this->skin->set_result('up_to_date');
$this->skin->before();
$this->skin->feedback('up_to_date');
$this->skin->after();
$results[$plugin] = true;
continue;
}
// Get the URL to the zip file
$r = $current->response[ $plugin ];
$this->skin->plugin_active = is_plugin_active($plugin);
*/
$result = $this->run( array(
'package' => $plugin, // [TGMPA + ] adjusted.
'destination' => WP_PLUGIN_DIR,
'clear_destination' => false, // [TGMPA + ] adjusted.
'clear_working' => true,
'is_multi' => true,
'hook_extra' => array(
'plugin' => $plugin,
),
) );
$results[ $plugin ] = $this->result;
// Prevent credentials auth screen from displaying multiple times.
if ( false === $result ) {
break;
}
} //end foreach $plugins
$this->maintenance_mode( false );
/**
* Fires when the bulk upgrader process is complete.
*
* @since WP 3.6.0 / TGMPA 2.5.0
*
* @param Plugin_Upgrader $this Plugin_Upgrader instance. In other contexts, $this, might
* be a Theme_Upgrader or Core_Upgrade instance.
* @param array $data {
* Array of bulk item update data.
*
* @type string $action Type of action. Default 'update'.
* @type string $type Type of update process. Accepts 'plugin', 'theme', or 'core'.
* @type bool $bulk Whether the update process is a bulk update. Default true.
* @type array $packages Array of plugin, theme, or core packages to update.
* }
*/
do_action( 'upgrader_process_complete', $this, array(
'action' => 'install', // [TGMPA + ] adjusted.
'type' => 'plugin',
'bulk' => true,
'plugins' => $plugins,
) );
$this->skin->bulk_footer();
$this->skin->footer();
// Cleanup our hooks, in case something else does a upgrade on this connection.
/* [TGMPA - ] remove_filter('upgrader_clear_destination', array($this, 'delete_old_plugin')); */
// [TGMPA + ] Remove our auto-activation hook.
remove_filter( 'upgrader_post_install', array( $this, 'auto_activate' ), 10 );
// Force refresh of plugin update information.
wp_clean_plugins_cache( $parsed_args['clear_update_cache'] );
return $results;
}
/**
* Handle a bulk upgrade request.
*
* @since 2.5.0
*
* @see Plugin_Upgrader::bulk_upgrade()
*
* @param array $plugins The local WP file_path's of the plugins which should be upgraded.
* @param array $args Arbitrary passed extra arguments.
* @return string|bool Install confirmation messages on success, false on failure.
*/
public function bulk_upgrade( $plugins, $args = array() ) {
add_filter( 'upgrader_post_install', array( $this, 'auto_activate' ), 10 );
$result = parent::bulk_upgrade( $plugins, $args );
remove_filter( 'upgrader_post_install', array( $this, 'auto_activate' ), 10 );
return $result;
}
/**
* Abuse a filter to auto-activate plugins after installation.
*
* Hooked into the 'upgrader_post_install' filter hook.
*
* @since 2.5.0
*
* @param bool $bool The value we need to give back (true).
* @return bool
*/
public function auto_activate( $bool ) {
// Only process the activation of installed plugins if the automatic flag is set to true.
if ( $this->tgmpa->is_automatic ) {
// Flush plugins cache so the headers of the newly installed plugins will be read correctly.
wp_clean_plugins_cache();
// Get the installed plugin file.
$plugin_info = $this->plugin_info();
// Don't try to activate on upgrade of active plugin as WP will do this already.
if ( ! is_plugin_active( $plugin_info ) ) {
$activate = activate_plugin( $plugin_info );
// Adjust the success string based on the activation result.
$this->strings['process_success'] = $this->strings['process_success'] . "<br />\n";
if ( is_wp_error( $activate ) ) {
$this->skin->error( $activate );
$this->strings['process_success'] .= $this->strings['activation_failed'];
} else {
$this->strings['process_success'] .= $this->strings['activation_success'];
}
}
}
return $bool;
}
}
}
if ( ! class_exists( 'TGMPA_Bulk_Installer_Skin' ) ) {
/**
* Installer skin to set strings for the bulk plugin installations..
*
* Extends Bulk_Upgrader_Skin and customizes to suit the installation of multiple
* plugins.
*
* @since 2.2.0
*
* @internal Since 2.5.2 the class has been renamed from TGM_Bulk_Installer_Skin to
* TGMPA_Bulk_Installer_Skin.
* This was done to prevent backward compatibility issues with v2.3.6.
*
* @see https://core.trac.wordpress.org/browser/trunk/src/wp-admin/includes/class-wp-upgrader-skins.php
*
* @package TGM-Plugin-Activation
* @author Thomas Griffin
* @author Gary Jones
*/
class TGMPA_Bulk_Installer_Skin extends Bulk_Upgrader_Skin {
/**
* Holds plugin info for each individual plugin installation.
*
* @since 2.2.0
*
* @var array
*/
public $plugin_info = array();
/**
* Holds names of plugins that are undergoing bulk installations.
*
* @since 2.2.0
*
* @var array
*/
public $plugin_names = array();
/**
* Integer to use for iteration through each plugin installation.
*
* @since 2.2.0
*
* @var integer
*/
public $i = 0;
/**
* TGMPA instance
*
* @since 2.5.0
*
* @var object
*/
protected $tgmpa;
/**
* Constructor. Parses default args with new ones and extracts them for use.
*
* @since 2.2.0
*
* @param array $args Arguments to pass for use within the class.
*/
public function __construct( $args = array() ) {
// Get TGMPA class instance.
$this->tgmpa = call_user_func( array( get_class( $GLOBALS['tgmpa'] ), 'get_instance' ) );
// Parse default and new args.
$defaults = array(
'url' => '',
'nonce' => '',
'names' => array(),
'install_type' => 'install',
);
$args = wp_parse_args( $args, $defaults );
// Set plugin names to $this->plugin_names property.
$this->plugin_names = $args['names'];
// Extract the new args.
parent::__construct( $args );
}
/**
* Sets install skin strings for each individual plugin.
*
* Checks to see if the automatic activation flag is set and uses the
* the proper strings accordingly.
*
* @since 2.2.0
*/
public function add_strings() {
if ( 'update' === $this->options['install_type'] ) {
parent::add_strings();
$this->upgrader->strings['skin_before_update_header'] = __( 'Updating Plugin %1$s (%2$d/%3$d)', 'tgmpa' );
} else {
$this->upgrader->strings['skin_update_failed_error'] = __( 'An error occurred while installing %1$s: <strong>%2$s</strong>.', 'tgmpa' );
$this->upgrader->strings['skin_update_failed'] = __( 'The installation of %1$s failed.', 'tgmpa' );
if ( $this->tgmpa->is_automatic ) {
// Automatic activation strings.
$this->upgrader->strings['skin_upgrade_start'] = __( 'The installation and activation process is starting. This process may take a while on some hosts, so please be patient.', 'tgmpa' );
$this->upgrader->strings['skin_update_successful'] = __( '%1$s installed and activated successfully.', 'tgmpa' ) . ' <a href="#" class="hide-if-no-js" onclick="%2$s"><span>' . esc_html__( 'Show Details', 'tgmpa' ) . '</span><span class="hidden">' . esc_html__( 'Hide Details', 'tgmpa' ) . '</span>.</a>';
$this->upgrader->strings['skin_upgrade_end'] = __( 'All installations and activations have been completed.', 'tgmpa' );
$this->upgrader->strings['skin_before_update_header'] = __( 'Installing and Activating Plugin %1$s (%2$d/%3$d)', 'tgmpa' );
} else {
// Default installation strings.
$this->upgrader->strings['skin_upgrade_start'] = __( 'The installation process is starting. This process may take a while on some hosts, so please be patient.', 'tgmpa' );
$this->upgrader->strings['skin_update_successful'] = esc_html__( '%1$s installed successfully.', 'tgmpa' ) . ' <a href="#" class="hide-if-no-js" onclick="%2$s"><span>' . esc_html__( 'Show Details', 'tgmpa' ) . '</span><span class="hidden">' . esc_html__( 'Hide Details', 'tgmpa' ) . '</span>.</a>';
$this->upgrader->strings['skin_upgrade_end'] = __( 'All installations have been completed.', 'tgmpa' );
$this->upgrader->strings['skin_before_update_header'] = __( 'Installing Plugin %1$s (%2$d/%3$d)', 'tgmpa' );
}
}
}
/**
* Outputs the header strings and necessary JS before each plugin installation.
*
* @since 2.2.0
*
* @param string $title Unused in this implementation.
*/
public function before( $title = '' ) {
if ( empty( $title ) ) {
$title = esc_html( $this->plugin_names[ $this->i ] );
}
parent::before( $title );
}
/**
* Outputs the footer strings and necessary JS after each plugin installation.
*
* Checks for any errors and outputs them if they exist, else output
* success strings.
*
* @since 2.2.0
*
* @param string $title Unused in this implementation.
*/
public function after( $title = '' ) {
if ( empty( $title ) ) {
$title = esc_html( $this->plugin_names[ $this->i ] );
}
parent::after( $title );
$this->i++;
}
/**
* Outputs links after bulk plugin installation is complete.
*
* @since 2.2.0
*/
public function bulk_footer() {
// Serve up the string to say installations (and possibly activations) are complete.
parent::bulk_footer();
// Flush plugins cache so we can make sure that the installed plugins list is always up to date.
wp_clean_plugins_cache();
$this->tgmpa->show_tgmpa_version();
// Display message based on if all plugins are now active or not.
$update_actions = array();
if ( $this->tgmpa->is_tgmpa_complete() ) {
// All plugins are active, so we display the complete string and hide the menu to protect users.
echo '<style type="text/css">#adminmenu .wp-submenu li.current { display: none !important; }</style>';
$update_actions['dashboard'] = sprintf(
esc_html( $this->tgmpa->strings['complete'] ),
'<a href="' . esc_url( self_admin_url() ) . '">' . esc_html__( 'Return to the Dashboard', 'tgmpa' ) . '</a>'
);
} else {
$update_actions['tgmpa_page'] = '<a href="' . esc_url( $this->tgmpa->get_tgmpa_url() ) . '" target="_parent">' . esc_html( $this->tgmpa->strings['return'] ) . '</a>';
}
/**
* Filter the list of action links available following bulk plugin installs/updates.
*
* @since 2.5.0
*
* @param array $update_actions Array of plugin action links.
* @param array $plugin_info Array of information for the last-handled plugin.
*/
$update_actions = apply_filters( 'tgmpa_update_bulk_plugins_complete_actions', $update_actions, $this->plugin_info );
if ( ! empty( $update_actions ) ) {
$this->feedback( implode( ' | ', (array) $update_actions ) );
}
}
/* *********** DEPRECATED METHODS *********** */
/**
* Flush header output buffer.
*
* @since 2.2.0
* @deprecated 2.5.0 use {@see Bulk_Upgrader_Skin::flush_output()} instead
* @see Bulk_Upgrader_Skin::flush_output()
*/
public function before_flush_output() {
_deprecated_function( __FUNCTION__, 'TGMPA 2.5.0', 'Bulk_Upgrader_Skin::flush_output()' );
$this->flush_output();
}
/**
* Flush footer output buffer and iterate $this->i to make sure the
* installation strings reference the correct plugin.
*
* @since 2.2.0
* @deprecated 2.5.0 use {@see Bulk_Upgrader_Skin::flush_output()} instead
* @see Bulk_Upgrader_Skin::flush_output()
*/
public function after_flush_output() {
_deprecated_function( __FUNCTION__, 'TGMPA 2.5.0', 'Bulk_Upgrader_Skin::flush_output()' );
$this->flush_output();
$this->i++;
}
}
}
}
}
}
if ( ! class_exists( 'TGMPA_Utils' ) ) {
/**
* Generic utilities for TGMPA.
*
* All methods are static, poor-dev name-spacing class wrapper.
*
* Class was called TGM_Utils in 2.5.0 but renamed TGMPA_Utils in 2.5.1 as this was conflicting with Soliloquy.
*
* @since 2.5.0
*
* @package TGM-Plugin-Activation
* @author Juliette Reinders Folmer
*/
class TGMPA_Utils {
/**
* Whether the PHP filter extension is enabled.
*
* @see http://php.net/book.filter
*
* @since 2.5.0
*
* @static
*
* @var bool $has_filters True is the extension is enabled.
*/
public static $has_filters;
/**
* Wrap an arbitrary string in <em> tags. Meant to be used in combination with array_map().
*
* @since 2.5.0
*
* @static
*
* @param string $string Text to be wrapped.
* @return string
*/
public static function wrap_in_em( $string ) {
return '<em>' . wp_kses_post( $string ) . '</em>';
}
/**
* Wrap an arbitrary string in <strong> tags. Meant to be used in combination with array_map().
*
* @since 2.5.0
*
* @static
*
* @param string $string Text to be wrapped.
* @return string
*/
public static function wrap_in_strong( $string ) {
return '<strong>' . wp_kses_post( $string ) . '</strong>';
}
/**
* Helper function: Validate a value as boolean
*
* @since 2.5.0
*
* @static
*
* @param mixed $value Arbitrary value.
* @return bool
*/
public static function validate_bool( $value ) {
if ( ! isset( self::$has_filters ) ) {
self::$has_filters = extension_loaded( 'filter' );
}
if ( self::$has_filters ) {
return filter_var( $value, FILTER_VALIDATE_BOOLEAN );
} else {
return self::emulate_filter_bool( $value );
}
}
/**
* Helper function: Cast a value to bool
*
* @since 2.5.0
*
* @static
*
* @param mixed $value Value to cast.
* @return bool
*/
protected static function emulate_filter_bool( $value ) {
// @codingStandardsIgnoreStart
static $true = array(
'1',
'true', 'True', 'TRUE',
'y', 'Y',
'yes', 'Yes', 'YES',
'on', 'On', 'ON',
);
static $false = array(
'0',
'false', 'False', 'FALSE',
'n', 'N',
'no', 'No', 'NO',
'off', 'Off', 'OFF',
);
// @codingStandardsIgnoreEnd
if ( is_bool( $value ) ) {
return $value;
} else if ( is_int( $value ) && ( 0 === $value || 1 === $value ) ) {
return (bool) $value;
} else if ( ( is_float( $value ) && ! is_nan( $value ) ) && ( (float) 0 === $value || (float) 1 === $value ) ) {
return (bool) $value;
} else if ( is_string( $value ) ) {
$value = trim( $value );
if ( in_array( $value, $true, true ) ) {
return true;
} else if ( in_array( $value, $false, true ) ) {
return false;
} else {
return false;
}
}
return false;
}
} // End of class TGMPA_Utils
} // End of class_exists wrapper
================================================
FILE: admin/includes/load_admin.php
================================================
<?php
/**
* AH Stripe
*
* @package Editus_Admin
* @author Nick Haskins <nick@aesopinteractive.com>
* @license GPL-2.0+
* @link http://aesopinteractive.com
* @copyright 2015 Aesopinteractive LLC
*/
namespace lasso_admin;
use lasso_public_facing\lasso;
class load_admin {
/**
* Instance of this class.
*
* @since 0.0.1
*
* @var object
*/
protected static $instance = null;
/**
* Slug of the plugin screen.
*
* @since 0.0.1
*
* @var string
*/
protected $plugin_screen_hook_suffix = null;
/**
* Initialize the plugin by loading admin scripts & styles and adding a
* settings page and menu.
*
* @since 0.0.1
*/
private function __construct() {
$plugin = lasso::get_instance();
$this->plugin_slug = $plugin->get_plugin_slug();
add_action( 'admin_head', array( $this, 'admin_assets' ) );
add_action( 'admin_notices', array( $this, 'license_nag' ) );
add_action( 'admin_head', array( $this, 'dismiss_nag' ) );
add_filter( 'plugin_row_meta', array( $this, 'plugin_meta' ), 10, 2 );
if ( !class_exists( 'EDD_SL_Plugin_Updater' ) ) {
include LASSO_DIR.'admin/includes/EDD_SL_Plugin_Updater.php';
}
if ( !class_exists( 'TGM_Plugin_Activation' ) ) {
include LASSO_DIR.'admin/includes/class-tgm-plugin-activation.php';
}
new menus\welcome();
new menus\settings();
if ( !defined( 'LASSO_AGENCY_MODE' ) ) {
new menus\license();
}
}
/**
* Return an instance of this class.
*
* @since 0.0.1
*
* @return object A single instance of this class.
*/
public static function get_instance() {
// If the single instance hasn't been set, set it now.
if ( null == self::$instance ) {
self::$instance = new self;
}
return self::$instance;
}
/**
* Load some assets for the appropriate pages in admin
*
* @since 1.0
*/
public function admin_assets() {
$screen = get_current_screen();
$pages = array(
'settings_page_lasso-editor-settings',
'settings_page_lasso-editor-settings-network',
'dashboard_page_lasso-welcome-screen'
);
foreach ( $pages as $page ) {
wp_enqueue_media();
wp_enqueue_style( 'wp-color-picker');
wp_enqueue_script( 'wp-color-picker');
wp_enqueue_script( 'lasso-editor-settings-script', LASSO_URL.'/admin/assets/js/lasso-editor-settings.js', array( 'jquery','wp-color-picker' ), LASSO_VERSION, true );
wp_enqueue_style( 'lasso-editor-settings-style', LASSO_URL.'/admin/assets/css/lasso-editor-settings.css', LASSO_VERSION );
}
}
/**
* Add some custom links to the plugins.php page
*
* @since 0.8.8
* @param unknown $links array array of new links
* @param unknown $file
*
* @return array new array of links for our plugin listing on plugins.php
*/
public function plugin_meta( $links, $file ) {
if ( strpos( $file, 'lasso.php' ) !== false && !defined( 'LASSO_AGENCY_MODE' ) ) {
$new_links = array(
'<a href="http://edituswp.com/help" target="_blank">Help</a>'
);
$links = array_merge( $links, $new_links );
}
return $links;
}
/**
* Adds an admin notice reminding the user if their license key has not been saved
*
* @since 0.9.7
* @todo make dismissible
*/
public function license_nag(){
$screen = get_current_screen();
$welcome = 'toplevel_page_lasso-editor' == $screen->id;
$license = get_option( 'lasso_license_key' );
$status = get_option( 'lasso_license_status' );
$message_empty = apply_filters('lasso_empty_license_message','Your license key for support and automatic updates for Editus is missing!');
$message_invalid = apply_filters('lasso_invalid_license_message','Oh snap! It looks like your Editus license key is invalid. Might check here to see if its been added correctly.');
$message_inactive = apply_filters('lasso_inactive_license_message','It looks like your license key has not yet been activated.');
$license_link = sprintf('<a href="%s">Update License</a>', esc_url( add_query_arg( array( 'page' => 'lasso-license' ), admin_url('admin.php') ) ) );
$dismiss_link = sprintf('<a style="text-decoration:none;" href="%s" id="lasso-dismiss-notice" class="notice-dismiss"><span class="screen-reader-text">%s</span></a>', esc_url( add_query_arg( 'lasso-notice', 'dismiss' ) ), __('Dismiss this notice.','lasso') );
$not_hidden = get_user_meta( get_current_user_ID(), 'lasso_license_nag_dismissed', true );
if ( current_user_can('manage_options') && !$welcome && !defined( 'LASSO_AGENCY_MODE') && !$not_hidden ) {
if ( empty( $license ) ) {
printf('<div class="lasso-notice error" style="position:relative;"><p>%s %s</p>%s</div>', $message_empty, $license_link, $dismiss_link );
} else if ( 'invalid' == $status ){ // license key entered wrong or something
printf('<div class="lasso-notice error" style="position:relative;"><p>%s %s</p>%s</div>', $message_invalid, $license_link , $dismiss_link );
} else if ( empty( $status ) ){ // license key saved but not activated
printf('<div class="lasso-notice error" style="position:relative;"><p>%s %s</p>%s</div>', $message_inactive, $license_link, $dismiss_link );
}
}
}
/**
* Process hiding the dimiss
*
* @since 0.9.7
*/
public function dismiss_nag() {
if ( isset( $_GET['lasso-notice'] ) && 'dismiss' == $_GET['lasso-notice'] && current_user_can('manage_options') ) {
update_user_meta( get_current_user_id(), 'lasso_license_nag_dismissed', 1 );
}
}
}
================================================
FILE: admin/includes/menus/license.php
================================================
<?php
namespace lasso_admin\menus;
class license {
function __construct() {
define( 'LASSO_STORE_ITEM_NAME', 'lasso' );
define( 'LASSO_STORE_URL', 'https://edituswp.com' );
add_action( 'admin_init', array( $this, 'plugin_updater' ), 0 );
add_action( 'admin_menu', array( $this, 'license_menu' ) );
add_action( 'network_admin_menu', array( $this, 'license_menu' ) ); // CHANGED Added hook.
add_action( 'admin_init', array( $this, 'register_option' ) );
add_action( 'admin_init', array( $this, 'activate_license' ) );
add_action( 'admin_init', array( $this, 'deactivate_license' ) );
}
function plugin_updater() {
// retrieve our license key from the DB
$license_key = trim( get_option( 'lasso_license_key' ) );
// setup the updater
$edd_updater = new \EDD_SL_Plugin_Updater( LASSO_STORE_URL , LASSO_FILE, array(
'version' => LASSO_VERSION,
'license' => $license_key,
'item_name' => LASSO_STORE_ITEM_NAME,
'author' => __( 'Aesopinteractive LLC', 'lasso' )
)
);
}
function license_menu() {
// CHANGED Removed condition.
add_submenu_page( 'lasso-editor', __( 'License Key', 'lasso' ), __( 'License', 'lasso' ), 'manage_options', 'lasso-license', array( $this, 'license_page' ) );
}
function license_page() {
$license = get_option( 'lasso_license_key' );
$status = get_option( 'lasso_license_status' );
?>
<div class="wrap">
<h2><?php _e( 'Editus License', 'lasso' ); ?></h2>
<p><?php _e( 'Input the license key you recieved with your purchase to ensure your version of Editus stays updated.', 'lasso' );?></p>
<form class="lasso--form-settings" method="post" action="options.php">
<?php settings_fields( 'lasso_license' ); ?>
<table class="form-table">
<tbody>
<tr valign="top">
<th scope="row" valign="top">
<?php _e( 'License Key', 'lasso' ); ?>
</th>
<td>
<input id="lasso_license_key" name="lasso_license_key" type="text" class="regular-text" value="<?php esc_attr_e( $license ); ?>" />
</td>
</tr>
<?php if ( false !== $license ) { ?>
<tr valign="top">
<th scope="row" valign="top">
<?php _e( 'Activate License', 'lasso' ); ?>
</th>
<td>
<?php if ( $status !== false && $status == 'valid' ) { ?>
<span style="color:green;"><?php _e( 'active' ); ?></span>
<?php wp_nonce_field( 'lasso_license_nonce', 'lasso_license_nonce' ); ?>
<input type="submit" class="button-secondary" name="edd_license_deactivate" value="<?php esc_attr_e( 'Deactivate License', 'lasso' ); ?>"/>
<?php } else {
wp_nonce_field( 'lasso_license_nonce', 'lasso_license_nonce' ); ?>
<input type="submit" class="button-secondary" name="edd_license_activate" value="<?php esc_attr_e( 'Activate License', 'lasso' ); ?>"/>
<?php } ?>
</td>
</tr>
<?php } ?>
</tbody>
</table>
<?php submit_button( 'Save License' ); ?>
</form>
<?php
}
// register option
function register_option() {
register_setting( 'lasso_license', 'lasso_license_key', array( $this, 'sanitize_license' ) );
}
// santize
function sanitize_license( $new ) {
$old = get_option( 'lasso_license_key' );
if ( $old && $old != $new ) {
delete_option( 'lasso_license_status' ); // new license has been entered, so must reactivate
}
return $new;
}
// activate
function activate_license() {
// listen for our activate button to be clicked
if ( isset( $_POST['edd_license_activate'] ) ) {
// run a quick security check
if ( ! check_admin_referer( 'lasso_license_nonce', 'lasso_license_nonce' ) )
return; // get out if we didn't click the Activate button
// retrieve the license from the database
$license = trim( get_option( 'lasso_license_key' ) );
// data to send in our API request
$api_params = array(
'edd_action'=> 'activate_license',
'license' => $license,
'item_name' => urlencode( LASSO_STORE_ITEM_NAME ), // the name of our product in EDD
'url' => home_url()
);
// Call the custom API.
$response = wp_remote_post( LASSO_STORE_URL, array( 'body' => $api_params, 'timeout' => 15, 'sslverify' => false ) );
// make sure the response came back okay
if ( is_wp_error( $response ) )
return false;
// decode the license data
$license_data = json_decode( wp_remote_retrieve_body( $response ) );
// $license_data->license will be either "valid" or "invalid"
update_option( 'lasso_license_status', $license_data->license );
}
}
function deactivate_license() {
// listen for our activate button to be clicked
if ( isset( $_POST['edd_license_deactivate'] ) ) {
// run a quick security check
if ( ! check_admin_referer( 'lasso_license_nonce', 'lasso_license_nonce' ) )
return; // get out if we didn't click the Activate button
// retrieve the license from the database
$license = trim( get_option( 'lasso_license_key' ) );
// data to send in our API request
$api_params = array(
'edd_action'=> 'deactivate_license',
'license' => $license,
'item_name' => urlencode( LASSO_STORE_ITEM_NAME ), // the name of our product in EDD
'url' => home_url()
);
// Call the custom API.
$response = wp_remote_post( LASSO_STORE_URL, array( 'body' => $api_params, 'timeout' => 15, 'sslverify' => false ) );
// make sure the response came back okay
if ( is_wp_error( $response ) )
return false;
// decode the license data
$license_data = json_decode( wp_remote_retrieve_body( $response ) );
// $license_data->license will be either "deactivated" or "failed"
if ( $license_data->license == 'deactivated' )
delete_option( 'lasso_license_status' );
}
}
// check status of license
function check_license() {
global $wp_version;
$license = trim( get_option( 'lasso_license_key' ) );
$api_params = array(
'edd_action' => 'check_license',
'license' => $license,
'item_name' => urlencode( LASSO_STORE_ITEM_NAME ),
'url' => home_url()
);
// Call the custom API.
$response = wp_remote_post( LASSO_STORE_URL, array( 'body' => $api_params, 'timeout' => 15, 'sslverify' => false ) );
if ( is_wp_error( $response ) )
return false;
$license_data = json_decode( wp_remote_retrieve_body( $response ) );
if ( $license_data->license == 'valid' ) {
echo 'valid'; exit;
// this license is still valid
} else {
echo 'invalid'; exit;
// this license is no longer valid
}
}
}
================================================
FILE: admin/includes/menus/settings.php
================================================
<?php
/**
* Class responsible for adding a settings submenu
*
*/
namespace lasso_admin\menus;
class settings {
function __construct() {
add_action( 'admin_menu', array( $this, 'menu' ) );
add_action( 'network_admin_menu', array( $this, 'menu' ) );
add_action( 'wp_ajax_lasso-editor-settings', array( $this, 'process_settings' ) );
}
/**
* Add a submenu page to the "Settings" tab if network activated, otherwise add to our menu page
*
* @since 1.0
*/
function menu() {
// CHANGED Removed condition.
add_submenu_page( 'lasso-editor', __( 'Settings', 'lasso' ), __( 'Settings', 'lasso' ), 'manage_options', 'lasso-editor-settings', array( $this, 'settings' ) );
}
/**
* Submenu page callback
*
* @since 1.0
*/
function settings() {
echo self::lasso_editor_settings_form();
}
/**
* Save settings via ajax
*
* @since 1.0
*/
function process_settings() {
// bail out if current user isn't and administrator and they are not logged in
if ( !current_user_can( 'manage_options' ) || !is_user_logged_in() )
return;
if ( isset( $_POST['action'] ) && 'lasso-editor-settings' == $_POST['action'] && check_admin_referer( 'nonce', 'lasso_editor_settings' ) ) {
$options = isset( $_POST['lasso_editor'] ) ? $_POST['lasso_editor'] : false;
$arr = $options['allowed_post_types'];
$options = array_map( 'sanitize_text_field', $options );
$options['allowed_post_types'] = array_keys( $arr);
if ( function_exists( 'is_multisite' ) && is_multisite() ) {
update_site_option( 'lasso_editor', $options );
} else {
update_option( 'lasso_editor', $options );
}
wp_send_json_success();
} else {
wp_send_json_error();
}
die();
}
function create_section_for_color_picker($id, $title, $defvalue) {
$color_value = lasso_editor_get_option( $id, 'lasso_editor',$defvalue );
echo '<div lass="lasso-editor-settings--option-inner">'."\n";
echo '<label>'.$title.'</label>';
echo '<input type="text" name="lasso_editor['.$id.']" value="'.$color_value.'" id="lasso-editor-'.$title.'" class="color-picker"/>';
echo "</div>\n";
}
/**
* Draw the settings form
*
* @since 1.0
*/
function lasso_editor_settings_form() {
if ( !is_user_logged_in() )
return;
// check for lasso story engine and add a class doniting this
$ase_status = class_exists( 'Aesop_Core' ) || defined( 'LASSO_CUSTOM' ) ? 'ase-active' : 'ase-not-active';
$article_object = lasso_editor_get_option( 'article_class', 'lasso_editor' );
$featImgClass = lasso_editor_get_option( 'featimg_class', 'lasso_editor' );
$titleClass = lasso_editor_get_option( 'title_class', 'lasso_editor' );
$post_new_disabled = lasso_editor_get_option( 'post_adding_disabled', 'lasso_editor' );
$save_to_post_disabled = lasso_editor_get_option( 'post_save_disabled', 'lasso_editor' );
$edit_post_disabled = lasso_editor_get_option( 'post_edit_disabled', 'lasso_editor' );
$post_settings_disabled = lasso_editor_get_option( 'post_settings_disabled', 'lasso_editor' );
$allow_chang
gitextract_5b5hx62o/ ├── .gitattributes ├── .gitignore ├── .travis.yml ├── CONTRIBUTING.md ├── Gruntfile.js ├── LICENSE.txt ├── README.md ├── README.txt ├── admin/ │ ├── assets/ │ │ ├── css/ │ │ │ └── lasso-editor-settings.css │ │ ├── js/ │ │ │ └── lasso-editor-settings.js │ │ └── less/ │ │ ├── style.less │ │ └── welcome.less │ └── includes/ │ ├── EDD_SL_Plugin_Updater.php │ ├── class-tgm-plugin-activation.php │ ├── load_admin.php │ └── menus/ │ ├── license.php │ ├── settings.php │ └── welcome.php ├── bootstrap.php ├── composer.json ├── includes/ │ ├── lasso_autoloader.php │ ├── process/ │ │ ├── delete.php │ │ ├── gallery.php │ │ ├── map.php │ │ ├── meta.php │ │ ├── new_object.php │ │ ├── revision.php │ │ ├── save.php │ │ ├── title_update.php │ │ ├── tour.php │ │ ├── update_object.php │ │ └── upload_image.php │ ├── sanatize.php │ └── save_gallery.php ├── internal-api/ │ ├── api_action.php │ ├── auth.php │ ├── docs.md │ ├── end_points.php │ ├── find_data.php │ └── route.php ├── languages/ │ ├── lasso-de_DE.mo │ ├── lasso-de_DE.po │ ├── lasso-es_ES.mo │ ├── lasso-es_ES.po │ ├── lasso-ko_KR.mo │ ├── lasso-ko_KR.po │ └── lasso.pot ├── lasso.php ├── package.json ├── public/ │ ├── assets/ │ │ ├── css/ │ │ │ ├── editus-table-edit-public.css │ │ │ ├── lasso.css │ │ │ └── style.css │ │ ├── js/ │ │ │ ├── editus-table-edit-public.js │ │ │ ├── lasso.js │ │ │ ├── source/ │ │ │ │ ├── all-posts.js │ │ │ │ ├── enter-editor.js │ │ │ │ ├── modal-sizing.js │ │ │ │ ├── post-settings.js │ │ │ │ ├── process-gallery-opts.js │ │ │ │ ├── process-gallery.js │ │ │ │ ├── process-image-upload.js │ │ │ │ ├── process-map.js │ │ │ │ ├── process-new-post.js │ │ │ │ ├── process-save-component.js │ │ │ │ ├── process-save-meta.js │ │ │ │ ├── process-save-title.js │ │ │ │ ├── process-save.js │ │ │ │ ├── process-wpimg.js │ │ │ │ ├── revisions.js │ │ │ │ ├── settings-live-editing.js │ │ │ │ ├── settings-panel.js │ │ │ │ ├── toolbar.js │ │ │ │ ├── tour.js │ │ │ │ ├── util--color-picker.js │ │ │ │ ├── util--content-editable.js │ │ │ │ ├── util--geo-complete.js │ │ │ │ ├── util--imagesloaded.js │ │ │ │ ├── util--rangy-classapplier.js │ │ │ │ ├── util--rangy-core.js │ │ │ │ ├── util--scrollbar.js │ │ │ │ ├── util--slider.js │ │ │ │ ├── util--sweet-alert.js │ │ │ │ ├── util--tagit.js │ │ │ │ ├── util--touch-punch.js │ │ │ │ ├── util--undo.js │ │ │ │ └── util--wp-api.js │ │ │ └── tour.js │ │ └── less/ │ │ ├── source/ │ │ │ ├── all-posts.less │ │ │ ├── animations.less │ │ │ ├── component-controls.less │ │ │ ├── component-settings--gallery.less │ │ │ ├── component-settings--map.less │ │ │ ├── component-settings.less │ │ │ ├── editor-controls.less │ │ │ ├── editor.less │ │ │ ├── featimg-controls.less │ │ │ ├── fonts.css │ │ │ ├── fonts.less │ │ │ ├── form-controls.less │ │ │ ├── mixins.css │ │ │ ├── mixins.less │ │ │ ├── mobile.less │ │ │ ├── post-settings.less │ │ │ ├── revisions.less │ │ │ ├── scrollbar.less │ │ │ ├── sidebar.less │ │ │ ├── sweet-alert.less │ │ │ ├── toolbar.less │ │ │ ├── tour.less │ │ │ ├── util--tags.less │ │ │ ├── util--tooltips.less │ │ │ ├── variables.css │ │ │ ├── variables.less │ │ │ └── wpimg-controls.less │ │ └── style.less │ └── includes/ │ ├── assets.php │ ├── components.php │ ├── editor-modules--gallery.php │ ├── editor-modules.php │ ├── helpers.php │ ├── lasso.php │ ├── option-engine.php │ ├── register_meta_field.php │ ├── tour.php │ ├── underscore-templates.php │ └── wrap-shortcodes.php └── uninstall.php
SYMBOL INDEX (867 symbols across 59 files)
FILE: admin/includes/EDD_SL_Plugin_Updater.php
class EDD_SL_Plugin_Updater (line 12) | class EDD_SL_Plugin_Updater {
method __construct (line 29) | function __construct( $_api_url, $_plugin_file, $_api_data = null ) {
method init (line 48) | public function init() {
method check_update (line 69) | function check_update( $_transient_data ) {
method show_update_notification (line 111) | public function show_update_notification( $file, $plugin ) {
method plugins_api_filter (line 207) | function plugins_api_filter( $_data, $_action = '', $_args = null ) {
method http_request_args (line 248) | function http_request_args( $args, $url ) {
method api_request (line 267) | private function api_request( $_action, $_data ) {
method show_changelog (line 308) | public function show_changelog() {
FILE: admin/includes/class-tgm-plugin-activation.php
class TGM_Plugin_Activation (line 61) | class TGM_Plugin_Activation {
method __construct (line 267) | public function __construct() {
method __set (line 292) | public function __set( $name, $value ) {
method __get (line 302) | public function __get( $name ) {
method init (line 317) | public function init() {
method add_plugin_action_link_filters (line 462) | public function add_plugin_action_link_filters() {
method filter_plugin_action_links_activate (line 487) | public function filter_plugin_action_links_activate( $actions ) {
method filter_plugin_action_links_deactivate (line 501) | public function filter_plugin_action_links_deactivate( $actions ) {
method filter_plugin_action_links_update (line 516) | public function filter_plugin_action_links_update( $actions ) {
method admin_init (line 550) | public function admin_init() {
method thickbox (line 584) | public function thickbox() {
method admin_menu (line 605) | public function admin_menu() {
method add_admin_menu (line 633) | protected function add_admin_menu( array $args ) {
method install_plugins_page (line 656) | public function install_plugins_page() {
method do_plugin_install (line 709) | protected function do_plugin_install() {
method inject_update_info (line 854) | public function inject_update_info( $plugins ) {
method maybe_adjust_source_dir (line 897) | public function maybe_adjust_source_dir( $source, $remote_source, $upg...
method activate_single_plugin (line 956) | protected function activate_single_plugin( $file_path, $slug, $automat...
method notices (line 1022) | public function notices() {
method display_settings_errors (line 1197) | protected function display_settings_errors() {
method dismiss (line 1217) | public function dismiss() {
method register (line 1234) | public function register( $plugin ) {
method get_plugin_source_type (line 1296) | protected function get_plugin_source_type( $source ) {
method sanitize_key (line 1320) | public function sanitize_key( $key ) {
method config (line 1342) | public function config( $config ) {
method actions (line 1376) | public function actions( $install_actions ) {
method flush_plugins_cache (line 1394) | public function flush_plugins_cache( $clear_update_cache = true ) {
method populate_file_path (line 1406) | public function populate_file_path( $plugin_slug = '' ) {
method _get_plugin_basename_from_slug (line 1426) | protected function _get_plugin_basename_from_slug( $slug ) {
method _get_plugin_data_from_name (line 1450) | public function _get_plugin_data_from_name( $name, $data = 'slug' ) {
method get_download_url (line 1468) | public function get_download_url( $slug ) {
method get_wp_repo_download_url (line 1491) | protected function get_wp_repo_download_url( $slug ) {
method get_plugins_api (line 1510) | protected function get_plugins_api( $slug ) {
method get_info_link (line 1541) | public function get_info_link( $slug ) {
method is_tgmpa_page (line 1579) | protected function is_tgmpa_page() {
method get_tgmpa_url (line 1593) | public function get_tgmpa_url() {
method get_tgmpa_status_url (line 1623) | public function get_tgmpa_status_url( $status ) {
method is_tgmpa_complete (line 1639) | public function is_tgmpa_complete() {
method is_plugin_installed (line 1659) | public function is_plugin_installed( $slug ) {
method is_plugin_active (line 1673) | public function is_plugin_active( $slug ) {
method can_plugin_update (line 1686) | public function can_plugin_update( $slug ) {
method can_plugin_activate (line 1711) | public function can_plugin_activate( $slug ) {
method get_installed_version (line 1724) | public function get_installed_version( $slug ) {
method does_plugin_require_update (line 1742) | public function does_plugin_require_update( $slug ) {
method does_plugin_have_update (line 1757) | public function does_plugin_have_update( $slug ) {
method get_upgrade_notice (line 1784) | public function get_upgrade_notice( $slug ) {
method get_plugins (line 1807) | public function get_plugins( $plugin_folder = '' ) {
method update_dismiss (line 1823) | public function update_dismiss() {
method force_activation (line 1841) | public function force_activation() {
method force_deactivation (line 1867) | public function force_deactivation() {
method show_tgmpa_version (line 1879) | public function show_tgmpa_version() {
method get_instance (line 1892) | public static function get_instance() {
function load_tgm_plugin_activation (line 1905) | function load_tgm_plugin_activation() {
function tgmpa (line 1927) | function tgmpa( $plugins, $config = array() ) {
class TGMPA_List_Table (line 1984) | class TGMPA_List_Table extends WP_List_Table {
method __construct (line 2022) | public function __construct() {
method get_table_classes (line 2049) | public function get_table_classes() {
method _gather_plugin_data (line 2060) | protected function _gather_plugin_data() {
method categorize_plugins_to_views (line 2112) | protected function categorize_plugins_to_views() {
method set_view_totals (line 2151) | protected function set_view_totals( $plugins ) {
method get_plugin_advise_type_text (line 2165) | protected function get_plugin_advise_type_text( $required ) {
method get_plugin_source_type_text (line 2181) | protected function get_plugin_source_type_text( $type ) {
method get_plugin_status_text (line 2207) | protected function get_plugin_status_text( $slug ) {
method sort_table_items (line 2249) | public function sort_table_items( $items ) {
method get_views (line 2270) | public function get_views() {
method column_default (line 2320) | public function column_default( $item, $column_name ) {
method column_cb (line 2334) | public function column_cb( $item ) {
method column_plugin (line 2351) | public function column_plugin( $item ) {
method column_version (line 2367) | public function column_version( $item ) {
method no_items (line 2421) | public function no_items() {
method get_columns (line 2433) | public function get_columns() {
method get_default_primary_column_name (line 2457) | protected function get_default_primary_column_name() {
method get_primary_column_name (line 2469) | protected function get_primary_column_name() {
method get_row_actions (line 2485) | protected function get_row_actions( $item ) {
method single_row (line 2536) | public function single_row( $item ) {
method wp_plugin_update_row (line 2561) | public function wp_plugin_update_row( $slug, $item ) {
method extra_tablenav (line 2584) | public function extra_tablenav( $which ) {
method get_bulk_actions (line 2597) | public function get_bulk_actions() {
method process_bulk_actions (line 2627) | public function process_bulk_actions() {
method prepare_items (line 2859) | public function prepare_items() {
method _get_plugin_data_from_name (line 2888) | protected function _get_plugin_data_from_name( $name, $data = 'slug' ) {
class TGM_Bulk_Installer (line 2902) | class TGM_Bulk_Installer {
class TGM_Bulk_Installer_Skin (line 2910) | class TGM_Bulk_Installer_Skin {
function tgmpa_load_bulk_installer (line 2929) | function tgmpa_load_bulk_installer() {
class TGMPA_Utils (line 3506) | class TGMPA_Utils {
method wrap_in_em (line 3530) | public static function wrap_in_em( $string ) {
method wrap_in_strong (line 3544) | public static function wrap_in_strong( $string ) {
method validate_bool (line 3558) | public static function validate_bool( $value ) {
method emulate_filter_bool (line 3580) | protected static function emulate_filter_bool( $value ) {
FILE: admin/includes/load_admin.php
class load_admin (line 15) | class load_admin {
method __construct (line 41) | private function __construct() {
method get_instance (line 75) | public static function get_instance() {
method admin_assets (line 90) | public function admin_assets() {
method plugin_meta (line 119) | public function plugin_meta( $links, $file ) {
method license_nag (line 139) | public function license_nag(){
method dismiss_nag (line 179) | public function dismiss_nag() {
FILE: admin/includes/menus/license.php
class license (line 5) | class license {
method __construct (line 7) | function __construct() {
method plugin_updater (line 20) | function plugin_updater() {
method license_menu (line 35) | function license_menu() {
method license_page (line 41) | function license_page() {
method register_option (line 89) | function register_option() {
method sanitize_license (line 95) | function sanitize_license( $new ) {
method activate_license (line 104) | function activate_license() {
method deactivate_license (line 141) | function deactivate_license() {
method check_license (line 180) | function check_license() {
FILE: admin/includes/menus/settings.php
class settings (line 8) | class settings {
method __construct (line 10) | function __construct() {
method menu (line 23) | function menu() {
method settings (line 35) | function settings() {
method process_settings (line 45) | function process_settings() {
method create_section_for_color_picker (line 82) | function create_section_for_color_picker($id, $title, $defvalue) {
method lasso_editor_settings_form (line 96) | function lasso_editor_settings_form() {
FILE: admin/includes/menus/welcome.php
class welcome (line 9) | class welcome {
method __construct (line 11) | function __construct() {
method redirect (line 21) | function redirect() {
method lasso_welcome (line 45) | function lasso_welcome() {
method welcome (line 58) | function welcome() {
method header (line 110) | function header() {
method lasso_preflight_check (line 140) | function lasso_preflight_check() {
method required_plugins (line 206) | function required_plugins() {
FILE: includes/lasso_autoloader.php
class lasso_autoloader (line 12) | class lasso_autoloader {
method register (line 26) | public function register() {
method addNamespace (line 41) | public function addNamespace($prefix, $base_dir, $prepend = false) {
method loadClass (line 68) | public function loadClass($class) {
method loadMappedFile (line 105) | protected function loadMappedFile($prefix, $relative_class) {
method requireFile (line 138) | protected function requireFile($file) {
FILE: includes/process/delete.php
class delete (line 11) | class delete implements api_action {
method post (line 28) | public function post( $data ) {
method params (line 55) | public static function params(){
method auth_callbacks (line 70) | public static function auth_callbacks() {
FILE: includes/process/gallery.php
class gallery (line 12) | class gallery implements api_action {
method swap (line 32) | public function swap( $data ) {
method create (line 57) | public function create( $data ) {
method update (line 117) | public function update( $data ) {
method get_images (line 148) | public function get_images( $data ) {
method get_the_images (line 176) | private function get_the_images( $image_ids = '' ) {
method params (line 222) | public static function params(){
method auth_callbacks (line 265) | public static function auth_callbacks() {
FILE: includes/process/map.php
class map (line 11) | class map implements api_action {
method save (line 31) | public function save( $data ) {
method params (line 66) | public static function params(){
method auth_callbacks (line 90) | public static function auth_callbacks() {
FILE: includes/process/meta.php
class meta (line 11) | class meta implements api_action {
method update (line 31) | public function update( $data ) {
method params (line 69) | public static function params(){
method auth_callbacks (line 86) | public static function auth_callbacks() {
FILE: includes/process/new_object.php
class new_object (line 12) | class new_object implements api_action {
method post (line 31) | public function post( $data ) {
method params (line 65) | public static function params() {
method auth_callbacks (line 82) | public static function auth_callbacks() {
FILE: includes/process/revision.php
class revision (line 8) | class revision implements api_action {
method get (line 30) | public static function get( $data ) {
method set_revisions (line 56) | protected static function set_revisions( $id, $revisions ) {
method params (line 76) | public static function params(){
method auth_callbacks (line 92) | public static function auth_callbacks() {
FILE: includes/process/save.php
class save (line 11) | class save implements api_action {
method content (line 22) | public function content( $data ) {
method publish_content (line 57) | public function publish_content( $data ) {
method params (line 88) | public static function params(){
method auth_callbacks (line 109) | public static function auth_callbacks() {
method save_to_post_disables (line 129) | protected function save_to_post_disables() {
method replace_rendered_shortcodes (line 147) | protected function replace_rendered_shortcodes( $content ) {
method remove_comments (line 166) | protected function remove_comments($content) {
FILE: includes/process/title_update.php
class title_update (line 11) | class title_update implements api_action {
method post (line 31) | public function post( $data ) {
method params (line 56) | public static function params(){
method auth_callbacks (line 73) | public static function auth_callbacks() {
FILE: includes/process/tour.php
class tour (line 11) | class tour implements api_action {
method hide (line 29) | public function hide( $data ) {
method params (line 48) | public static function params(){
method auth_callbacks (line 63) | public static function auth_callbacks() {
FILE: includes/process/update_object.php
class update_object (line 12) | class update_object implements api_action{
method post (line 32) | public function post( $data ) {
method params (line 81) | public static function params(){
method auth_callbacks (line 119) | public static function auth_callbacks() {
method set_post_terms (line 142) | public function set_post_terms( $postid, $value, $taxonomy ) {
method set_custom_taxonomy (line 187) | public function set_custom_taxonomy( $postid, $value) {
method set_date (line 213) | public function set_date( $postid, $value) {
method has_multiple_objects (line 235) | public function has_multiple_objects( $value ) {
FILE: includes/process/upload_image.php
class upload_image (line 11) | class upload_image implements api_action {
method upload (line 31) | public function upload( $data ) {
method delete (line 53) | public function delete( $data ) {
method params (line 72) | public static function params(){
method auth_callbacks (line 93) | public static function auth_callbacks() {
FILE: includes/sanatize.php
class sanatize (line 17) | class sanatize {
method do_sanitize (line 31) | public static function do_sanitize( $input, $params = array() ) {
method sanitize_like (line 102) | public static function sanitize_like( $input ) {
method unslash (line 153) | public static function unslash( $input ) {
FILE: includes/save_gallery.php
class save_gallery (line 9) | class save_gallery {
method save_gallery_options (line 15) | public static function save_gallery_options( $postid, $gallery_ids, $o...
FILE: internal-api/api_action.php
type api_action (line 14) | interface api_action {
method params (line 25) | public static function params();
method auth_callbacks (line 36) | public static function auth_callbacks();
FILE: internal-api/auth.php
class auth (line 13) | class auth {
method __construct (line 55) | public function __construct( $action, $callback_class) {
method other_auth_checks (line 92) | protected function other_auth_checks( $action ) {
method if_implements (line 128) | protected function if_implements() {
method check_nonce (line 149) | protected function check_nonce() {
FILE: internal-api/end_points.php
class end_points (line 13) | class end_points {
method __construct (line 20) | public function __construct() {
method add_endpoints (line 30) | public function add_endpoints() {
FILE: internal-api/find_data.php
class find_data (line 13) | class find_data {
method __construct (line 32) | public function __construct( $callback_instance, $action ) {
method get_data (line 52) | protected function get_data( $callback_instance, $action ) {
method sanitize (line 101) | protected function sanitize( $key, $cb ) {
FILE: internal-api/route.php
class route (line 13) | class route {
method do_api (line 22) | public static function do_api() {
method auth (line 88) | protected static function auth( $action, $callback ) {
method find_callback (line 102) | protected static function find_callback( $action ) {
method route (line 139) | protected static function route( $action, $callback, $method, $data ) {
method respond (line 159) | protected static function respond( $response, $code ) {
method init (line 201) | public static function init() {
FILE: lasso.php
function lasso_fail_notice (line 41) | function lasso_fail_notice(){
function lasso_show_in_rest (line 49) | function lasso_show_in_rest($args, $post_type){
function lasso_editor_get_option (line 64) | function lasso_editor_get_option( $option, $section, $default = '' ) {
function add_raw_to_post (line 92) | function add_raw_to_post( $response, $post, $request ) {
class editus_table (line 107) | class editus_table {
method __construct (line 109) | public function __construct(){
method scripts (line 117) | function scripts()
method editus_table_edit_menu (line 126) | function editus_table_edit_menu()
method editus_html_table (line 140) | function editus_html_table()
method editus_components_add_table (line 146) | function editus_components_add_table( $array ){
method editus_toolbar_components_add_table (line 157) | function editus_toolbar_components_add_table( ) {
class editus_paragraph (line 170) | class editus_paragraph {
method __construct (line 172) | public function __construct(){
method scripts (line 180) | function scripts()
method editus_components_add_paragraph (line 189) | function editus_components_add_paragraph( $array ){
method editus_html_paragraph (line 200) | function editus_html_paragraph()
method editus_paragraph_style (line 205) | function editus_paragraph_style()
method editus_toolbar_components_add_paragraph (line 218) | function editus_toolbar_components_add_paragraph( ) {
FILE: public/assets/js/editus-table-edit-public.js
function addColumn (line 86) | function addColumn(n) {
function addRow (line 95) | function addRow(n) {
function deleteColumn (line 104) | function deleteColumn(n) {
function deleteRow (line 113) | function deleteRow(n) {
function deleteTable (line 117) | function deleteTable() {
function whenExitEditor (line 121) | function whenExitEditor(){
function whenEnterEditor (line 125) | function whenEnterEditor(){
FILE: public/assets/js/lasso.js
function extend (line 45) | function extend(target, ref) {
function isHostMethod (line 185) | function isHostMethod(o, p) {
function isHostObject (line 190) | function isHostObject(o, p) {
function isHostProperty (line 194) | function isHostProperty(o, p) {
function createMultiplePropertyTest (line 199) | function createMultiplePropertyTest(testFunc) {
function isTextRange (line 216) | function isTextRange(range) {
function getBody (line 220) | function getBody(doc) {
function consoleLog (line 255) | function consoleLog(msg) {
function alertOrLog (line 261) | function alertOrLog(msg, shouldAlert) {
function fail (line 269) | function fail(reason) {
function warn (line 277) | function warn(msg) {
function getErrorDesc (line 373) | function getErrorDesc(ex) {
function init (line 378) | function init() {
function shim (line 455) | function shim(win) {
function Module (line 469) | function Module(name, dependencies, initializer) {
function createModule (line 519) | function createModule(name, dependencies, initFunc) {
function RangePrototype (line 563) | function RangePrototype() {}
function SelectionPrototype (line 567) | function SelectionPrototype() {}
function isHtmlNamespace (line 625) | function isHtmlNamespace(node) {
function parentElement (line 630) | function parentElement(node) {
function getNodeIndex (line 635) | function getNodeIndex(node) {
function getNodeLength (line 643) | function getNodeLength(node) {
function getCommonAncestor (line 656) | function getCommonAncestor(node1, node2) {
function isAncestorOf (line 671) | function isAncestorOf(ancestor, descendant, selfIsAncestor) {
function isOrIsAncestorOf (line 683) | function isOrIsAncestorOf(ancestor, descendant) {
function getClosestAncestorIn (line 687) | function getClosestAncestorIn(node, ancestor, selfIsAncestor) {
function isCharacterDataNode (line 699) | function isCharacterDataNode(node) {
function isTextOrCommentNode (line 704) | function isTextOrCommentNode(node) {
function insertAfter (line 712) | function insertAfter(node, precedingNode) {
function splitDataNode (line 723) | function splitDataNode(node, index, positionsToPreserve) {
function getDocument (line 746) | function getDocument(node) {
function getWindow (line 760) | function getWindow(node) {
function getIframeDocument (line 771) | function getIframeDocument(iframeEl) {
function getIframeWindow (line 781) | function getIframeWindow(iframeEl) {
function isWindow (line 792) | function isWindow(obj) {
function getContentDocument (line 796) | function getContentDocument(obj, module, methodName) {
function getRootContainer (line 821) | function getRootContainer(node) {
function comparePoints (line 829) | function comparePoints(nodeA, offsetA, nodeB, offsetB) {
function isBrokenNode (line 873) | function isBrokenNode(node) {
function inspectNode (line 895) | function inspectNode(node) {
function fragmentFromNodeChildren (line 912) | function fragmentFromNodeChildren(node) {
function NodeIterator (line 933) | function NodeIterator(root) {
function createIterator (line 968) | function createIterator(root) {
function DomPosition (line 972) | function DomPosition(node, offset) {
function DOMException (line 991) | function DOMException(codeName) {
function isNonTextPartiallySelected (line 1071) | function isNonTextPartiallySelected(node, range) {
function getRangeDocument (line 1076) | function getRangeDocument(range) {
function getBoundaryBeforeNode (line 1080) | function getBoundaryBeforeNode(node) {
function getBoundaryAfterNode (line 1084) | function getBoundaryAfterNode(node) {
function insertNodeAtPosition (line 1088) | function insertNodeAtPosition(node, n, o) {
function rangesIntersect (line 1104) | function rangesIntersect(rangeA, rangeB, touchingIsIntersecting) {
function cloneSubtree (line 1118) | function cloneSubtree(iterator) {
function iterateSubtree (line 1137) | function iterateSubtree(rangeIterator, func, iteratorState) {
function deleteSubtree (line 1169) | function deleteSubtree(iterator) {
function extractSubtree (line 1182) | function extractSubtree(iterator) {
function getNodesInRange (line 1201) | function getNodesInRange(range, nodeTypes, filter) {
function inspect (line 1233) | function inspect(range) {
function RangeIterator (line 1243) | function RangeIterator(range, clonePartiallySelectedTextNodes) {
function createAncestorFinder (line 1363) | function createAncestorFinder(nodeTypes) {
function assertNoDocTypeNotationEntityAncestor (line 1381) | function assertNoDocTypeNotationEntityAncestor(node, allowSelf) {
function assertValidNodeType (line 1387) | function assertValidNodeType(node, invalidTypes) {
function assertValidOffset (line 1393) | function assertValidOffset(node, offset) {
function assertSameDocumentOrFragment (line 1399) | function assertSameDocumentOrFragment(node1, node2) {
function assertNodeNotReadOnly (line 1405) | function assertNodeNotReadOnly(node) {
function assertNode (line 1411) | function assertNode(node, codeName) {
function isOrphan (line 1417) | function isOrphan(node) {
function isValidOffset (line 1422) | function isValidOffset(node, offset) {
function isRangeValid (line 1426) | function isRangeValid(range) {
function assertRangeValid (line 1434) | function assertRangeValid(range) {
function splitRangeBoundaries (line 1525) | function splitRangeBoundaries(range, positionsToPreserve) {
function rangeToHtml (line 1548) | function rangeToHtml(range) {
function copyComparisonConstantsToObject (line 1918) | function copyComparisonConstantsToObject(obj) {
function copyComparisonConstants (line 1930) | function copyComparisonConstants(constructor) {
function createRangeContentRemover (line 1935) | function createRangeContentRemover(remover, boundaryUpdater) {
function createPrototypeRange (line 1968) | function createPrototypeRange(constructor, boundaryUpdater) {
function updateCollapsedAndCommonAncestor (line 2196) | function updateCollapsedAndCommonAncestor(range) {
function updateBoundaries (line 2202) | function updateBoundaries(range, startContainer, startOffset, endContain...
function Range (line 2212) | function Range(doc) {
function updateRangeProperties (line 2267) | function updateRangeProperties(range) {
function updateNativeRange (line 2277) | function updateNativeRange(range, startContainer, startOffset, endContai...
function isDirectionBackward (line 2883) | function isDirectionBackward(dir) {
function getWindow (line 2887) | function getWindow(win, methodName) {
function getWinSelection (line 2900) | function getWinSelection(winParam) {
function getDocSelection (line 2904) | function getDocSelection(winParam) {
function winSelectionIsBackward (line 2908) | function winSelectionIsBackward(sel) {
function updateAnchorAndFocusFromRange (line 3078) | function updateAnchorAndFocusFromRange(sel, range, backward) {
function updateAnchorAndFocusFromNativeSelection (line 3086) | function updateAnchorAndFocusFromNativeSelection(sel) {
function updateEmptySelection (line 3094) | function updateEmptySelection(sel) {
function getNativeRange (line 3102) | function getNativeRange(range) {
function rangeContainsSingleElement (line 3116) | function rangeContainsSingleElement(rangeNodes) {
function getSingleElementFromRange (line 3128) | function getSingleElementFromRange(range) {
function isTextRange (line 3137) | function isTextRange(range) {
function updateFromTextRange (line 3141) | function updateFromTextRange(sel, range) {
function updateControlSelection (line 3151) | function updateControlSelection(sel) {
function addRangeToControlSelection (line 3177) | function addRangeToControlSelection(sel, range) {
function WrappedSelection (line 3228) | function WrappedSelection(selection, docSelection, win) {
function deleteProperties (line 3238) | function deleteProperties(sel) {
function actOnCachedSelection (line 3246) | function actOnCachedSelection(win, action) {
function createControlSelection (line 3299) | function createControlSelection(sel, ranges) {
function assertNodeInSameDocument (line 3623) | function assertNodeInSameDocument(sel, node) {
function createStartOrEndSetter (line 3720) | function createStartOrEndSetter(isStart) {
function inspect (line 3812) | function inspect(sel) {
function each (line 3927) | function each(obj, func) {
function trim (line 3938) | function trim(str) {
function hasClass (line 3942) | function hasClass(el, className) {
function addClass (line 3946) | function addClass(el, className) {
function replacer (line 3957) | function replacer(matched, whiteSpaceBefore, whiteSpaceAfter) {
function sortClassName (line 3968) | function sortClassName(className) {
function getSortedClassName (line 3972) | function getSortedClassName(el) {
function haveSameClasses (line 3976) | function haveSameClasses(el1, el2) {
function movePosition (line 3980) | function movePosition(position, oldParent, oldIndex, newParent, newIndex) {
function movePositionWhenRemovingNode (line 4001) | function movePositionWhenRemovingNode(position, parentNode, index) {
function movePreservingPositions (line 4007) | function movePreservingPositions(node, newParent, newIndex, positionsToP...
function removePreservingPositions (line 4028) | function removePreservingPositions(node, positionsToPreserve) {
function moveChildrenPreservingPositions (line 4040) | function moveChildrenPreservingPositions(node, newParent, newIndex, remo...
function replaceWithOwnChildrenPreservingPositions (line 4052) | function replaceWithOwnChildrenPreservingPositions(element, positionsToP...
function rangeSelectsAnyText (line 4056) | function rangeSelectsAnyText(range, textNode) {
function getEffectiveTextNodes (line 4066) | function getEffectiveTextNodes(range) {
function elementsHaveSameNonClassAttributes (line 4086) | function elementsHaveSameNonClassAttributes(el1, el2) {
function elementHasNonClassAttributes (line 4101) | function elementHasNonClassAttributes(el, exceptions) {
function elementHasProperties (line 4111) | function elementHasProperties(el, props) {
function isEditingHost (line 4138) | function isEditingHost(node) {
function isEditable (line 4145) | function isEditable(node) {
function isNonInlineElement (line 4151) | function isNonInlineElement(node) {
function isUnrenderedWhiteSpaceNode (line 4158) | function isUnrenderedWhiteSpaceNode(node) {
function getRangeBoundaries (line 4182) | function getRangeBoundaries(ranges) {
function updateRangesFromBoundaries (line 4193) | function updateRangesFromBoundaries(ranges, positions) {
function isSplitPoint (line 4202) | function isSplitPoint(node, offset) {
function splitNodeAt (line 4216) | function splitNodeAt(node, descendantNode, descendantOffset, positionsTo...
function areElementsMergeable (line 4265) | function areElementsMergeable(el1, el2) {
function createAdjacentMergeableTextNodeGetter (line 4274) | function createAdjacentMergeableTextNodeGetter(forward) {
function Merge (line 4303) | function Merge(firstNode) {
function ClassApplier (line 4376) | function ClassApplier(className, options, tagNames) {
function createClassApplier (line 4879) | function createClassApplier(className, options, tagNames) {
function checkNonEditable (line 4917) | function checkNonEditable(e, selRange) {
function checkBackspaceForNoEditable (line 4929) | function checkBackspaceForNoEditable(elem)
function checkDeleteForNoEditable (line 4945) | function checkDeleteForNoEditable(elem)
function getInt (line 7001) | function getInt(x) {
function updateScrollTop (line 7111) | function updateScrollTop(currentTop, deltaY) {
function updateScrollLeft (line 7127) | function updateScrollLeft(currentLeft, deltaX) {
function getThumbSize (line 7143) | function getThumbSize(thumbSize) {
function updateCss (line 7153) | function updateCss() {
function updateGeometry (line 7188) | function updateGeometry() {
function bindMouseScrollXHandler (line 7239) | function bindMouseScrollXHandler() {
function bindMouseScrollYHandler (line 7271) | function bindMouseScrollYHandler() {
function shouldPreventWheel (line 7303) | function shouldPreventWheel(deltaX, deltaY) {
function shouldPreventSwipe (line 7326) | function shouldPreventSwipe(deltaX, deltaY) {
function bindMouseWheelHandler (line 7351) | function bindMouseWheelHandler() {
function bindKeyboardHandler (line 7434) | function bindKeyboardHandler() {
function bindRailClickHandler (line 7513) | function bindRailClickHandler() {
function bindSelectionHandler (line 7549) | function bindSelectionHandler() {
function bindTouchHandler (line 7649) | function bindTouchHandler(supportsTouch, supportsIePointer) {
function bindScrollHandler (line 7783) | function bindScrollHandler() {
function destroy (line 7789) | function destroy() {
function initialize (line 7830) | function initialize() {
function modalDependant (line 8071) | function modalDependant() {
function setParameters (line 8358) | function setParameters(params) {
function colorLuminance (line 8484) | function colorLuminance(hex, lum) {
function extend (line 8503) | function extend(a, b){
function hexToRgb (line 8513) | function hexToRgb(hex) {
function setFocusStyle (line 8519) | function setFocusStyle($button, bgColor) {
function openModal (line 8530) | function openModal() {
function closeModal (line 8554) | function closeModal() {
function fixVerticalPosition (line 8595) | function fixVerticalPosition() {
function GeoComplete (line 8636) | function GeoComplete(input,options){this.options=$.extend(true,{},defaul...
function setDetail (line 8636) | function setDetail(value){details[value]=$details.find("["+attribute+"="...
function EventEmitter (line 8646) | function EventEmitter() {}
function indexOfListener (line 8661) | function indexOfListener(listeners, listener) {
function alias (line 8679) | function alias(name) {
function getIEEvent (line 9121) | function getIEEvent( obj ) {
function extend (line 9231) | function extend( a, b ) {
function isArray (line 9239) | function isArray( obj ) {
function makeArray (line 9244) | function makeArray( obj ) {
function ImagesLoaded (line 9268) | function ImagesLoaded( elem, options, onAlways ) {
function onConfirm (line 9353) | function onConfirm( image, message ) {
function LoadingImage (line 9412) | function LoadingImage( img ) {
function Resource (line 9456) | function Resource( src ) {
function simulateMouseEvent (line 9741) | function simulateMouseEvent (event, simulatedType) {
function restoreSelection (line 10510) | function restoreSelection(range) {
function saveSelection (line 10522) | function saveSelection() {
function lockPost (line 10623) | function lockPost() {
function rgb2hex (line 10949) | function rgb2hex(rgb) {
function alignHelper (line 11010) | function alignHelper(align) {
function makeList (line 11042) | function makeList(list_type) {
function processShortcodes (line 11065) | function processShortcodes()
function taghelper (line 11118) | function taghelper(tag) {
function heading_helper (line 11149) | function heading_helper(heading) {
function do_shortcode_ajax (line 11247) | function do_shortcode_ajax(content)
function insert_html (line 11267) | function insert_html(htmlContent, contentishtml) {
function isURL (line 11337) | function isURL(str) {
function autoSave (line 11369) | function autoSave() {
function clearTimer (line 11376) | function clearTimer()
function exitEditor (line 11398) | function exitEditor(){
function setMapCenter (line 11571) | function setMapCenter(k, B) {
function setMapZoom (line 11578) | function setMapZoom(z) {
function onMarkerDrag (line 11583) | function onMarkerDrag(e) {
function onMapDrag (line 11587) | function onMapDrag(e) {
function onMapZoom (line 11592) | function onMapZoom(e) {
function rnd (line 11596) | function rnd(n) {
function onMapClick (line 11600) | function onMapClick(e) {
function onPopupOpen (line 11643) | function onPopupOpen() {
function createMapMarker (line 11669) | function createMapMarker(latlng, title) {
function getAllMarkers (line 11685) | function getAllMarkers() {
function createMarkerField (line 11697) | function createMarkerField(mid, mdata) {
function updateMarkerField (line 11701) | function updateMarkerField(m) {
function encodeMarkerData (line 11707) | function encodeMarkerData(mlat, mlng, mtitle) {
function encodeLocationData (line 11712) | function encodeLocationData(mlat, mlng) {
function decodeMarkerData (line 11717) | function decodeMarkerData(mdata) {
function setComponent (line 11728) | function setComponent(type) {
function postComponent (line 11748) | function postComponent(comp,type) {
function imgDialog (line 11765) | function imgDialog( ){
function initVideoProvider (line 12981) | function initVideoProvider( settings, component, type ){
function saveSelection (line 13004) | function saveSelection() {
function restoreSelection (line 13016) | function restoreSelection(range) {
function process_html (line 13595) | function process_html(html, do_shortcodify) {
function removeComment (line 13679) | function removeComment(content) {
function removeEditable (line 13683) | function removeEditable(content)
function saveCustomFields (line 13690) | function saveCustomFields(content) {
function shortcodify (line 13724) | function shortcodify(content,selector){
function process_twitter (line 13803) | function process_twitter(html)
function shortcodify_su (line 13822) | function shortcodify_su(content,selector){
function process_gutenberg (line 13889) | function process_gutenberg(content){
function shortcodify_avia (line 14129) | function shortcodify_avia(content,selector){
function replace_rendered_shortcodes (line 14185) | function replace_rendered_shortcodes( content ) {
function savePublishREST (line 14220) | function savePublishREST(postid, title, subtitle, content_, type_,status...
function saveSuccess (line 14286) | function saveSuccess() {
function runSavePublish (line 14318) | function runSavePublish(forcePublish){
function EditusFormatAJAXErrorMessage (line 14391) | function EditusFormatAJAXErrorMessage(jqXHR, exception) {
function editus_gallery_swap (line 14548) | function editus_gallery_swap(galleryID){
function ase_string_encode (line 14568) | function ase_string_encode(gData){
function ase_string_decode (line 14572) | function ase_string_decode(gData){
function ase_encode_gallery_items (line 14576) | function ase_encode_gallery_items(){
function ase_insert_gallery_item (line 14585) | function ase_insert_gallery_item(id, url){
function ase_edit_gallery_item (line 14639) | function ase_edit_gallery_item(id, url, editable){
function get_aesop_options (line 15138) | function get_aesop_options(comp)
function newPostREST (line 15403) | function newPostREST(title_, type_,content_){
function destroyLoader (line 15690) | function destroyLoader(){
function initScroll (line 15697) | function initScroll() {
function fetchError (line 15707) | function fetchError(xhr){
function fetchPosts (line 15728) | function fetchPosts( type ){
function dispPosts (line 15895) | function dispPosts(data, type) {
function getParams (line 15925) | function getParams( draft, page, author ) {
function setOptions (line 15944) | function setOptions( type, page, author ) {
function setOptionsPost (line 15972) | function setOptionsPost( type, page, author ) {
function destroyClose (line 16258) | function destroyClose(){
function destroySearch (line 16269) | function destroySearch( type ){
function destroyLoader (line 16405) | function destroyLoader(){
function maybeRestoreCurrent (line 16569) | function maybeRestoreCurrent(){
function addBackupNotice (line 16579) | function addBackupNotice(){
function removeRevisionCount (line 16588) | function removeRevisionCount(){
FILE: public/assets/js/source/all-posts.js
function destroyLoader (line 45) | function destroyLoader(){
function initScroll (line 52) | function initScroll() {
function fetchError (line 62) | function fetchError(xhr){
function fetchPosts (line 83) | function fetchPosts( type ){
function dispPosts (line 250) | function dispPosts(data, type) {
function getParams (line 280) | function getParams( draft, page, author ) {
function setOptions (line 299) | function setOptions( type, page, author ) {
function setOptionsPost (line 327) | function setOptionsPost( type, page, author ) {
function destroyClose (line 613) | function destroyClose(){
function destroySearch (line 624) | function destroySearch( type ){
FILE: public/assets/js/source/enter-editor.js
function restoreSelection (line 28) | function restoreSelection(range) {
function saveSelection (line 40) | function saveSelection() {
function lockPost (line 141) | function lockPost() {
function rgb2hex (line 467) | function rgb2hex(rgb) {
function alignHelper (line 528) | function alignHelper(align) {
function makeList (line 560) | function makeList(list_type) {
function processShortcodes (line 583) | function processShortcodes()
function taghelper (line 636) | function taghelper(tag) {
function heading_helper (line 667) | function heading_helper(heading) {
function do_shortcode_ajax (line 765) | function do_shortcode_ajax(content)
function insert_html (line 785) | function insert_html(htmlContent, contentishtml) {
function isURL (line 855) | function isURL(str) {
function autoSave (line 887) | function autoSave() {
function clearTimer (line 894) | function clearTimer()
function exitEditor (line 916) | function exitEditor(){
function setMapCenter (line 1089) | function setMapCenter(k, B) {
function setMapZoom (line 1096) | function setMapZoom(z) {
function onMarkerDrag (line 1101) | function onMarkerDrag(e) {
function onMapDrag (line 1105) | function onMapDrag(e) {
function onMapZoom (line 1110) | function onMapZoom(e) {
function rnd (line 1114) | function rnd(n) {
function onMapClick (line 1118) | function onMapClick(e) {
function onPopupOpen (line 1161) | function onPopupOpen() {
function createMapMarker (line 1187) | function createMapMarker(latlng, title) {
function getAllMarkers (line 1203) | function getAllMarkers() {
function createMarkerField (line 1215) | function createMarkerField(mid, mdata) {
function updateMarkerField (line 1219) | function updateMarkerField(m) {
function encodeMarkerData (line 1225) | function encodeMarkerData(mlat, mlng, mtitle) {
function encodeLocationData (line 1230) | function encodeLocationData(mlat, mlng) {
function decodeMarkerData (line 1235) | function decodeMarkerData(mdata) {
function setComponent (line 1246) | function setComponent(type) {
function postComponent (line 1266) | function postComponent(comp,type) {
function imgDialog (line 1283) | function imgDialog( ){
FILE: public/assets/js/source/process-gallery.js
function editus_gallery_swap (line 140) | function editus_gallery_swap(galleryID){
function ase_string_encode (line 160) | function ase_string_encode(gData){
function ase_string_decode (line 164) | function ase_string_decode(gData){
function ase_encode_gallery_items (line 168) | function ase_encode_gallery_items(){
function ase_insert_gallery_item (line 177) | function ase_insert_gallery_item(id, url){
function ase_edit_gallery_item (line 231) | function ase_edit_gallery_item(id, url, editable){
FILE: public/assets/js/source/process-new-post.js
function newPostREST (line 100) | function newPostREST(title_, type_,content_){
FILE: public/assets/js/source/process-save-component.js
function get_aesop_options (line 82) | function get_aesop_options(comp)
FILE: public/assets/js/source/process-save.js
function process_html (line 232) | function process_html(html, do_shortcodify) {
function removeComment (line 316) | function removeComment(content) {
function removeEditable (line 320) | function removeEditable(content)
function saveCustomFields (line 327) | function saveCustomFields(content) {
function shortcodify (line 361) | function shortcodify(content,selector){
function process_twitter (line 440) | function process_twitter(html)
function shortcodify_su (line 459) | function shortcodify_su(content,selector){
function process_gutenberg (line 526) | function process_gutenberg(content){
function shortcodify_avia (line 766) | function shortcodify_avia(content,selector){
function replace_rendered_shortcodes (line 822) | function replace_rendered_shortcodes( content ) {
function savePublishREST (line 857) | function savePublishREST(postid, title, subtitle, content_, type_,status...
function saveSuccess (line 923) | function saveSuccess() {
function runSavePublish (line 955) | function runSavePublish(forcePublish){
function EditusFormatAJAXErrorMessage (line 1028) | function EditusFormatAJAXErrorMessage(jqXHR, exception) {
FILE: public/assets/js/source/revisions.js
function destroyLoader (line 22) | function destroyLoader(){
function maybeRestoreCurrent (line 186) | function maybeRestoreCurrent(){
function addBackupNotice (line 196) | function addBackupNotice(){
function removeRevisionCount (line 205) | function removeRevisionCount(){
FILE: public/assets/js/source/settings-live-editing.js
function initVideoProvider (line 303) | function initVideoProvider( settings, component, type ){
FILE: public/assets/js/source/toolbar.js
function saveSelection (line 3) | function saveSelection() {
function restoreSelection (line 15) | function restoreSelection(range) {
FILE: public/assets/js/source/util--color-picker.js
function singleColorTpl (line 6) | function singleColorTpl(color, index, picked) {
function addBasicStyling (line 12) | function addBasicStyling() {
function MessageMediator (line 29) | function MessageMediator() {
function SinglePicker (line 45) | function SinglePicker(elem, colors, className) {
function PickerHolder (line 131) | function PickerHolder(elem) {
function vanillaColorPicker (line 199) | function vanillaColorPicker(element, options) {
FILE: public/assets/js/source/util--content-editable.js
function checkNonEditable (line 16) | function checkNonEditable(e, selRange) {
function checkBackspaceForNoEditable (line 28) | function checkBackspaceForNoEditable(elem)
function checkDeleteForNoEditable (line 44) | function checkDeleteForNoEditable(elem)
FILE: public/assets/js/source/util--geo-complete.js
function GeoComplete (line 8) | function GeoComplete(input,options){this.options=$.extend(true,{},defaul...
function setDetail (line 8) | function setDetail(value){details[value]=$details.find("["+attribute+"="...
FILE: public/assets/js/source/util--imagesloaded.js
function EventEmitter (line 10) | function EventEmitter() {}
function indexOfListener (line 25) | function indexOfListener(listeners, listener) {
function alias (line 43) | function alias(name) {
function getIEEvent (line 485) | function getIEEvent( obj ) {
function extend (line 595) | function extend( a, b ) {
function isArray (line 603) | function isArray( obj ) {
function makeArray (line 608) | function makeArray( obj ) {
function ImagesLoaded (line 632) | function ImagesLoaded( elem, options, onAlways ) {
function onConfirm (line 717) | function onConfirm( image, message ) {
function LoadingImage (line 776) | function LoadingImage( img ) {
function Resource (line 820) | function Resource( src ) {
FILE: public/assets/js/source/util--rangy-classapplier.js
function each (line 36) | function each(obj, func) {
function trim (line 47) | function trim(str) {
function hasClass (line 51) | function hasClass(el, className) {
function addClass (line 55) | function addClass(el, className) {
function replacer (line 66) | function replacer(matched, whiteSpaceBefore, whiteSpaceAfter) {
function sortClassName (line 77) | function sortClassName(className) {
function getSortedClassName (line 81) | function getSortedClassName(el) {
function haveSameClasses (line 85) | function haveSameClasses(el1, el2) {
function movePosition (line 89) | function movePosition(position, oldParent, oldIndex, newParent, newIndex) {
function movePositionWhenRemovingNode (line 110) | function movePositionWhenRemovingNode(position, parentNode, index) {
function movePreservingPositions (line 116) | function movePreservingPositions(node, newParent, newIndex, positionsToP...
function removePreservingPositions (line 137) | function removePreservingPositions(node, positionsToPreserve) {
function moveChildrenPreservingPositions (line 149) | function moveChildrenPreservingPositions(node, newParent, newIndex, remo...
function replaceWithOwnChildrenPreservingPositions (line 161) | function replaceWithOwnChildrenPreservingPositions(element, positionsToP...
function rangeSelectsAnyText (line 165) | function rangeSelectsAnyText(range, textNode) {
function getEffectiveTextNodes (line 175) | function getEffectiveTextNodes(range) {
function elementsHaveSameNonClassAttributes (line 195) | function elementsHaveSameNonClassAttributes(el1, el2) {
function elementHasNonClassAttributes (line 210) | function elementHasNonClassAttributes(el, exceptions) {
function elementHasProperties (line 220) | function elementHasProperties(el, props) {
function isEditingHost (line 247) | function isEditingHost(node) {
function isEditable (line 254) | function isEditable(node) {
function isNonInlineElement (line 260) | function isNonInlineElement(node) {
function isUnrenderedWhiteSpaceNode (line 267) | function isUnrenderedWhiteSpaceNode(node) {
function getRangeBoundaries (line 291) | function getRangeBoundaries(ranges) {
function updateRangesFromBoundaries (line 302) | function updateRangesFromBoundaries(ranges, positions) {
function isSplitPoint (line 311) | function isSplitPoint(node, offset) {
function splitNodeAt (line 325) | function splitNodeAt(node, descendantNode, descendantOffset, positionsTo...
function areElementsMergeable (line 374) | function areElementsMergeable(el1, el2) {
function createAdjacentMergeableTextNodeGetter (line 383) | function createAdjacentMergeableTextNodeGetter(forward) {
function Merge (line 412) | function Merge(firstNode) {
function ClassApplier (line 485) | function ClassApplier(className, options, tagNames) {
function createClassApplier (line 988) | function createClassApplier(className, options, tagNames) {
FILE: public/assets/js/source/util--rangy-core.js
function isHostMethod (line 46) | function isHostMethod(o, p) {
function isHostObject (line 51) | function isHostObject(o, p) {
function isHostProperty (line 55) | function isHostProperty(o, p) {
function createMultiplePropertyTest (line 60) | function createMultiplePropertyTest(testFunc) {
function isTextRange (line 77) | function isTextRange(range) {
function getBody (line 81) | function getBody(doc) {
function consoleLog (line 116) | function consoleLog(msg) {
function alertOrLog (line 122) | function alertOrLog(msg, shouldAlert) {
function fail (line 130) | function fail(reason) {
function warn (line 138) | function warn(msg) {
function getErrorDesc (line 234) | function getErrorDesc(ex) {
function init (line 239) | function init() {
function shim (line 316) | function shim(win) {
function Module (line 330) | function Module(name, dependencies, initializer) {
function createModule (line 380) | function createModule(name, dependencies, initFunc) {
function RangePrototype (line 424) | function RangePrototype() {}
function SelectionPrototype (line 428) | function SelectionPrototype() {}
function isHtmlNamespace (line 486) | function isHtmlNamespace(node) {
function parentElement (line 491) | function parentElement(node) {
function getNodeIndex (line 496) | function getNodeIndex(node) {
function getNodeLength (line 504) | function getNodeLength(node) {
function getCommonAncestor (line 517) | function getCommonAncestor(node1, node2) {
function isAncestorOf (line 532) | function isAncestorOf(ancestor, descendant, selfIsAncestor) {
function isOrIsAncestorOf (line 544) | function isOrIsAncestorOf(ancestor, descendant) {
function getClosestAncestorIn (line 548) | function getClosestAncestorIn(node, ancestor, selfIsAncestor) {
function isCharacterDataNode (line 560) | function isCharacterDataNode(node) {
function isTextOrCommentNode (line 565) | function isTextOrCommentNode(node) {
function insertAfter (line 573) | function insertAfter(node, precedingNode) {
function splitDataNode (line 584) | function splitDataNode(node, index, positionsToPreserve) {
function getDocument (line 607) | function getDocument(node) {
function getWindow (line 621) | function getWindow(node) {
function getIframeDocument (line 632) | function getIframeDocument(iframeEl) {
function getIframeWindow (line 642) | function getIframeWindow(iframeEl) {
function isWindow (line 653) | function isWindow(obj) {
function getContentDocument (line 657) | function getContentDocument(obj, module, methodName) {
function getRootContainer (line 682) | function getRootContainer(node) {
function comparePoints (line 690) | function comparePoints(nodeA, offsetA, nodeB, offsetB) {
function isBrokenNode (line 734) | function isBrokenNode(node) {
function inspectNode (line 756) | function inspectNode(node) {
function fragmentFromNodeChildren (line 773) | function fragmentFromNodeChildren(node) {
function NodeIterator (line 794) | function NodeIterator(root) {
function createIterator (line 829) | function createIterator(root) {
function DomPosition (line 833) | function DomPosition(node, offset) {
function DOMException (line 852) | function DOMException(codeName) {
function isNonTextPartiallySelected (line 932) | function isNonTextPartiallySelected(node, range) {
function getRangeDocument (line 937) | function getRangeDocument(range) {
function getBoundaryBeforeNode (line 941) | function getBoundaryBeforeNode(node) {
function getBoundaryAfterNode (line 945) | function getBoundaryAfterNode(node) {
function insertNodeAtPosition (line 949) | function insertNodeAtPosition(node, n, o) {
function rangesIntersect (line 965) | function rangesIntersect(rangeA, rangeB, touchingIsIntersecting) {
function cloneSubtree (line 979) | function cloneSubtree(iterator) {
function iterateSubtree (line 998) | function iterateSubtree(rangeIterator, func, iteratorState) {
function deleteSubtree (line 1030) | function deleteSubtree(iterator) {
function extractSubtree (line 1043) | function extractSubtree(iterator) {
function getNodesInRange (line 1062) | function getNodesInRange(range, nodeTypes, filter) {
function inspect (line 1094) | function inspect(range) {
function RangeIterator (line 1104) | function RangeIterator(range, clonePartiallySelectedTextNodes) {
function createAncestorFinder (line 1224) | function createAncestorFinder(nodeTypes) {
function assertNoDocTypeNotationEntityAncestor (line 1242) | function assertNoDocTypeNotationEntityAncestor(node, allowSelf) {
function assertValidNodeType (line 1248) | function assertValidNodeType(node, invalidTypes) {
function assertValidOffset (line 1254) | function assertValidOffset(node, offset) {
function assertSameDocumentOrFragment (line 1260) | function assertSameDocumentOrFragment(node1, node2) {
function assertNodeNotReadOnly (line 1266) | function assertNodeNotReadOnly(node) {
function assertNode (line 1272) | function assertNode(node, codeName) {
function isOrphan (line 1278) | function isOrphan(node) {
function isValidOffset (line 1283) | function isValidOffset(node, offset) {
function isRangeValid (line 1287) | function isRangeValid(range) {
function assertRangeValid (line 1295) | function assertRangeValid(range) {
function splitRangeBoundaries (line 1386) | function splitRangeBoundaries(range, positionsToPreserve) {
function rangeToHtml (line 1409) | function rangeToHtml(range) {
function copyComparisonConstantsToObject (line 1779) | function copyComparisonConstantsToObject(obj) {
function copyComparisonConstants (line 1791) | function copyComparisonConstants(constructor) {
function createRangeContentRemover (line 1796) | function createRangeContentRemover(remover, boundaryUpdater) {
function createPrototypeRange (line 1829) | function createPrototypeRange(constructor, boundaryUpdater) {
function updateCollapsedAndCommonAncestor (line 2057) | function updateCollapsedAndCommonAncestor(range) {
function updateBoundaries (line 2063) | function updateBoundaries(range, startContainer, startOffset, endContain...
function Range (line 2073) | function Range(doc) {
function updateRangeProperties (line 2128) | function updateRangeProperties(range) {
function updateNativeRange (line 2138) | function updateNativeRange(range, startContainer, startOffset, endContai...
function isDirectionBackward (line 2744) | function isDirectionBackward(dir) {
function getWindow (line 2748) | function getWindow(win, methodName) {
function getWinSelection (line 2761) | function getWinSelection(winParam) {
function getDocSelection (line 2765) | function getDocSelection(winParam) {
function winSelectionIsBackward (line 2769) | function winSelectionIsBackward(sel) {
function updateAnchorAndFocusFromRange (line 2939) | function updateAnchorAndFocusFromRange(sel, range, backward) {
function updateAnchorAndFocusFromNativeSelection (line 2947) | function updateAnchorAndFocusFromNativeSelection(sel) {
function updateEmptySelection (line 2955) | function updateEmptySelection(sel) {
function getNativeRange (line 2963) | function getNativeRange(range) {
function rangeContainsSingleElement (line 2977) | function rangeContainsSingleElement(rangeNodes) {
function getSingleElementFromRange (line 2989) | function getSingleElementFromRange(range) {
function isTextRange (line 2998) | function isTextRange(range) {
function updateFromTextRange (line 3002) | function updateFromTextRange(sel, range) {
function updateControlSelection (line 3012) | function updateControlSelection(sel) {
function addRangeToControlSelection (line 3038) | function addRangeToControlSelection(sel, range) {
function WrappedSelection (line 3089) | function WrappedSelection(selection, docSelection, win) {
function deleteProperties (line 3099) | function deleteProperties(sel) {
function actOnCachedSelection (line 3107) | function actOnCachedSelection(win, action) {
function createControlSelection (line 3160) | function createControlSelection(sel, ranges) {
function assertNodeInSameDocument (line 3484) | function assertNodeInSameDocument(sel, node) {
function createStartOrEndSetter (line 3581) | function createStartOrEndSetter(isStart) {
function inspect (line 3673) | function inspect(sel) {
FILE: public/assets/js/source/util--scrollbar.js
function getInt (line 20) | function getInt(x) {
function updateScrollTop (line 130) | function updateScrollTop(currentTop, deltaY) {
function updateScrollLeft (line 146) | function updateScrollLeft(currentLeft, deltaX) {
function getThumbSize (line 162) | function getThumbSize(thumbSize) {
function updateCss (line 172) | function updateCss() {
function updateGeometry (line 207) | function updateGeometry() {
function bindMouseScrollXHandler (line 258) | function bindMouseScrollXHandler() {
function bindMouseScrollYHandler (line 290) | function bindMouseScrollYHandler() {
function shouldPreventWheel (line 322) | function shouldPreventWheel(deltaX, deltaY) {
function shouldPreventSwipe (line 345) | function shouldPreventSwipe(deltaX, deltaY) {
function bindMouseWheelHandler (line 370) | function bindMouseWheelHandler() {
function bindKeyboardHandler (line 453) | function bindKeyboardHandler() {
function bindRailClickHandler (line 532) | function bindRailClickHandler() {
function bindSelectionHandler (line 568) | function bindSelectionHandler() {
function bindTouchHandler (line 668) | function bindTouchHandler(supportsTouch, supportsIePointer) {
function bindScrollHandler (line 802) | function bindScrollHandler() {
function destroy (line 808) | function destroy() {
function initialize (line 849) | function initialize() {
FILE: public/assets/js/source/util--sweet-alert.js
function modalDependant (line 215) | function modalDependant() {
function setParameters (line 502) | function setParameters(params) {
function colorLuminance (line 628) | function colorLuminance(hex, lum) {
function extend (line 647) | function extend(a, b){
function hexToRgb (line 657) | function hexToRgb(hex) {
function setFocusStyle (line 663) | function setFocusStyle($button, bgColor) {
function openModal (line 674) | function openModal() {
function closeModal (line 698) | function closeModal() {
function fixVerticalPosition (line 739) | function fixVerticalPosition() {
FILE: public/assets/js/source/util--touch-punch.js
function simulateMouseEvent (line 31) | function simulateMouseEvent (event, simulatedType) {
FILE: public/assets/js/source/util--undo.js
function extend (line 45) | function extend(target, ref) {
FILE: public/assets/js/source/util--wp-api.js
function WP_API (line 5) | function WP_API() {
function WP_API_Utils (line 43) | function WP_API_Utils() {
FILE: public/includes/assets.php
class assets (line 11) | class assets {
method __construct (line 13) | public function __construct(){
method is_multipage (line 18) | function is_multipage()
method scripts (line 30) | public function scripts(){
method gutenberg_active (line 380) | function gutenberg_active() {
method is_classic_editor_plugin_active (line 407) | function is_classic_editor_plugin_active() {
FILE: public/includes/components.php
function lasso_editor_components (line 15) | function lasso_editor_components() {
function lasso_quote_component (line 123) | function lasso_quote_component() {
function lasso_image_component (line 131) | function lasso_image_component() {
function lasso_parallax_component (line 139) | function lasso_parallax_component() {
function lasso_audio_component (line 147) | function lasso_audio_component() {
function lasso_content_component (line 156) | function lasso_content_component() {
function lasso_character_component (line 164) | function lasso_character_component() {
function lasso_collections_component (line 173) | function lasso_collections_component() {
function lasso_document_component (line 181) | function lasso_document_component() {
function lasso_gallery_component (line 190) | function lasso_gallery_component() {
function lasso_heading_component (line 199) | function lasso_heading_component() {
function lasso_map_component (line 207) | function lasso_map_component() {
function lasso_timeline_component (line 219) | function lasso_timeline_component() {
function lasso_video_component (line 228) | function lasso_video_component() {
function lasso_wp_image (line 238) | function lasso_wp_image(){
function lasso_wp_quote (line 256) | function lasso_wp_quote(){
function lasso_gallery_pop_component (line 265) | function lasso_gallery_pop_component() {
function lasso_event_component (line 273) | function lasso_event_component() {
function lasso_wp_video (line 282) | function lasso_wp_video(){
function lasso_wp_image_block (line 289) | function lasso_wp_image_block(){
function editus_get_one_id (line 296) | function editus_get_one_id($type)
FILE: public/includes/editor-modules--gallery.php
function lasso_gallery_editor_module (line 8) | function lasso_gallery_editor_module() {
FILE: public/includes/editor-modules.php
function lasso_editor_controls (line 15) | function lasso_editor_controls() {
function lasso_editor_component_sidebar (line 193) | function lasso_editor_component_sidebar() {
function lasso_editor_selected_text_toolbar (line 211) | function lasso_editor_selected_text_toolbar() {
function lasso_editor_text_toolbar (line 298) | function lasso_editor_text_toolbar() {
function lasso_editor_settings_toolbar (line 480) | function lasso_editor_settings_toolbar() {
function lasso_editor_image_controls (line 507) | function lasso_editor_image_controls() {
function lasso_editor_component_modal (line 534) | function lasso_editor_component_modal() {
function lasso_editor_newpost_modal (line 734) | function lasso_editor_newpost_modal() {
function lasso_editor_allpost_modal (line 817) | function lasso_editor_allpost_modal() {
function lasso_editor_wpimg_edit (line 878) | function lasso_editor_wpimg_edit() {
function lasso_editor_wpimg_block_edit (line 903) | function lasso_editor_wpimg_block_edit() {
function lasso_editor_wpvideo_edit (line 917) | function lasso_editor_wpvideo_edit() {
function lasso_map_form_footer (line 941) | function lasso_map_form_footer() {
function lasso_editor_refresh_message (line 964) | function lasso_editor_refresh_message() {
function lasso_editor_options_blob (line 982) | function lasso_editor_options_blob() {
function add_wpimg_options (line 1100) | function add_wpimg_options( $shortcodes ) {
function add_wpimg_block_options (line 1215) | function add_wpimg_block_options( $shortcodes ) {
function add_wpcover_block_options (line 1280) | function add_wpcover_block_options( $shortcodes ) {
function lasso_editor_revision_modal (line 1313) | function lasso_editor_revision_modal() {
function lasso_editor_adjustBrightness (line 1347) | function lasso_editor_adjustBrightness($hex, $steps) {
FILE: public/includes/helpers.php
function lasso_editor_get_option (line 16) | function lasso_editor_get_option( $option, $section, $default = '' ) {
function lasso_editor_galleries_exist (line 45) | function lasso_editor_galleries_exist() {
function lasso_get_supported_theme_class (line 61) | function lasso_get_supported_theme_class() {
function lasso_get_supported_theme_title_class (line 119) | function lasso_get_supported_theme_title_class() {
function lasso_get_supported_theme_featured_image_class (line 156) | function lasso_get_supported_theme_featured_image_class() {
function lasso_supported_no_save (line 172) | function lasso_supported_no_save(){
function lasso_sanitize_data (line 186) | function lasso_sanitize_data( $data ) {
function lasso_get_post_objects (line 197) | function lasso_get_post_objects( $postid, $taxonomy) {
function lasso_get_objects (line 228) | function lasso_get_objects( $taxonomy = 'category' ) {
function lasso_post_types_names (line 259) | function lasso_post_types_names() {
function lasso_post_types (line 287) | function lasso_post_types() {
function lasso_post_types_rest_base (line 310) | function lasso_post_types_rest_base() {
function lasso_modal_addons_content (line 332) | function lasso_modal_addons_content( $tab = '', $type ){
function lasso_clean_string (line 362) | function lasso_clean_string( $string = '' ) {
function lasso_unclean_string (line 380) | function lasso_unclean_string( $string = '' ) {
function lasso_user_can (line 402) | function lasso_user_can( $action = '', $postid = 0 ) {
function lasso_editor_empty_results (line 445) | function lasso_editor_empty_results( $type = 'posts' ){
FILE: public/includes/lasso.php
class lasso (line 18) | class lasso {
method __construct (line 43) | private function __construct() {
method get_plugin_slug (line 98) | public function get_plugin_slug() {
method get_instance (line 109) | public static function get_instance() {
method activate (line 129) | public static function activate( $network_wide ) {
method deactivate (line 166) | public static function deactivate( $network_wide ) {
method activate_new_site (line 201) | public function activate_new_site( $blog_id ) {
method get_blog_ids (line 223) | private static function get_blog_ids() {
method single_activate (line 241) | private static function single_activate() {
method single_deactivate (line 264) | private static function single_deactivate() {
method load_plugin_textdomain (line 273) | public function load_plugin_textdomain() {
method editus_lock_post (line 282) | public function editus_lock_post()
method editus_unlock_post (line 297) | public function editus_unlock_post()
method editus_hide_tour (line 310) | public function editus_hide_tour()
method editus_set_post_setting (line 318) | public function editus_set_post_setting()
method enable_metasave (line 373) | public static function enable_metasave($type)
method editus_do_shortcode (line 388) | public function editus_do_shortcode()
method editus_do_block (line 413) | public function editus_do_block()
method get_aesop_component (line 424) | public function get_aesop_component()
method wpimg (line 506) | public static function wpimg($atts) {
method wpimg_block (line 564) | public static function wpimg_block($atts) {
method get_ase_options (line 604) | public function get_ase_options()
method delete_post (line 612) | public function delete_post( ) {
method on_publish_post (line 638) | public function on_publish_post( ) {
method set_featured_img (line 647) | public function set_featured_img( ) {
method del_featured_img (line 663) | public function del_featured_img( ) {
method set_post_terms (line 694) | public function set_post_terms( $postid, $value, $taxonomy ) {
method create_gallery (line 727) | public function create_gallery( ) {
method update_gallery (line 784) | public function update_gallery( ) {
method save_gallery_options (line 805) | public function save_gallery_options( $postid, $gallery_ids, $options,...
method getEnglishMonthName (line 867) | function getEnglishMonthName($foreignMonthName){
method set_date (line 886) | public function set_date( $postid, $value) {
FILE: public/includes/option-engine.php
function lasso_get_modal_tabs (line 46) | function lasso_get_modal_tabs(){
function lasso_modal_addons (line 63) | function lasso_modal_addons( $type = 'tab' ){
function lasso_option_form (line 118) | function lasso_option_form( $name = '', $options = array() ){
function lasso_option_fields (line 195) | function lasso_option_fields( $name = '', $options = array() ){
function lasso_option_engine_option (line 226) | function lasso_option_engine_option( $name = '', $option = '', $type = '...
FILE: public/includes/register_meta_field.php
class register_meta_field (line 9) | class register_meta_field {
method __construct (line 18) | public function __construct( $fields ) {
FILE: public/includes/tour.php
class tour (line 10) | class tour {
method __construct (line 12) | public function __construct() {
method draw_tour (line 24) | public function draw_tour() {
method tour_slides (line 87) | public function tour_slides() { ?>
FILE: public/includes/underscore-templates.php
function lasso_backbone_templates (line 6) | function lasso_backbone_templates(){
FILE: public/includes/wrap-shortcodes.php
function lasso_wrap_shortcodes (line 23) | function lasso_wrap_shortcodes( $content ) {
function lasso_wrap_shortcode_tag (line 69) | function lasso_wrap_shortcode_tag( $m ) {
function strpos_arr (line 92) | function strpos_arr($haystack, $needle) {
Condensed preview — 127 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (2,338K chars).
[
{
"path": ".gitattributes",
"chars": 237,
"preview": ".gitattributes export-ignore\n.gitignore export-ignore\n.travis.yml export-ignore\ncomposer.json export-ignore\nCONTRIBUTING"
},
{
"path": ".gitignore",
"chars": 35,
"preview": ".DS_Store\nnode_modules\n.sass-cache\n"
},
{
"path": ".travis.yml",
"chars": 572,
"preview": "language: php\n\nsudo: false\n\nphp:\n - 5.4\n - 5.5\n - 5.6\n - hhvm\n - nightly\n\n# Specify versions of WordPress to test a"
},
{
"path": "CONTRIBUTING.md",
"chars": 418,
"preview": "This repository is for reporting Editus bugs only. This is not a support forum. If you need any help with Editus please "
},
{
"path": "Gruntfile.js",
"chars": 4696,
"preview": "'use strict';\nmodule.exports = function(grunt) {\n\n require('load-grunt-tasks')(grunt);\n\n grunt.initConfig({\n\n "
},
{
"path": "LICENSE.txt",
"chars": 18091,
"preview": " GNU GENERAL PUBLIC LICENSE\n Version 2, June 1991\n\n Copyright (C) 1989, 1991 Fr"
},
{
"path": "README.md",
"chars": 1464,
"preview": " <table width=\"100%\">\n\t<tr>\n\t\t<td align=\"left\" width=\"70%\">\n\t\t\t<strong><a href=\"https://edituswp.com\">Editus</a></strong"
},
{
"path": "README.txt",
"chars": 17160,
"preview": "=== Editus ===\nContributors: nphaskins, hyunster, michaelbeil\nPlugin URI: https://edituswp.com\nRequires at least: 3.5\nTe"
},
{
"path": "admin/assets/css/lasso-editor-settings.css",
"chars": 5073,
"preview": ".lasso--animate__spin{-webkit-animation:spin 2s infinite linear;animation:spin 2s infinite linear}.not-visible{opacity:0"
},
{
"path": "admin/assets/js/lasso-editor-settings.js",
"chars": 1882,
"preview": "jQuery(document).ready(function($){\n\n\t// entry handler\n \t$('#lasso-editor-settings-form').submit(function(e) {\n\n \t\tvar"
},
{
"path": "admin/assets/less/style.less",
"chars": 2779,
"preview": "@import '../../../public/assets/less/source/mixins.less';\n@import 'welcome.less';\n\n@main: #fff;\n@border: #cdcdcd;\n"
},
{
"path": "admin/assets/less/welcome.less",
"chars": 2875,
"preview": ".lasso--welcome {\n\n * { .box-sizing(border-box); }\n\n max-width:600px;\n margin:20px auto;\n -webkit-font-smoot"
},
{
"path": "admin/includes/EDD_SL_Plugin_Updater.php",
"chars": 9408,
"preview": "<?php\n\n// uncomment this line for testing\n//set_site_transient( 'update_plugins', null );\n\n/**\n * Allows plugins to use "
},
{
"path": "admin/includes/class-tgm-plugin-activation.php",
"chars": 117887,
"preview": "<?php\n/**\n * Plugin installation and activation for WordPress themes.\n *\n * Please note that this is a drop-in library f"
},
{
"path": "admin/includes/load_admin.php",
"chars": 5531,
"preview": "<?php\n/**\n * AH Stripe\n *\n * @package Editus_Admin\n * @author Nick Haskins <nick@aesopinteractive.com>\n * @license "
},
{
"path": "admin/includes/menus/license.php",
"chars": 6555,
"preview": "<?php\n\nnamespace lasso_admin\\menus;\n\nclass license {\n\n\tfunction __construct() {\n\n\t\tdefine( 'LASSO_STORE_ITEM_NAME', 'las"
},
{
"path": "admin/includes/menus/settings.php",
"chars": 34617,
"preview": "<?php\n/**\n * Class responsible for adding a settings submenu\n *\n */\nnamespace lasso_admin\\menus;\n\nclass settings {\n\n\tfun"
},
{
"path": "admin/includes/menus/welcome.php",
"chars": 12308,
"preview": "<?php\n/**\n * Creates a welcome screen with pre-flight check sequence\n *\n * @since 0.8.2\n */\nnamespace lasso_admin\\menus;"
},
{
"path": "bootstrap.php",
"chars": 1760,
"preview": "<?php\n/**\n * Bootstrap the plugin if version check passed.\n *\n * @package @lasso\n * @author Josh Pollock <Josh@Josh"
},
{
"path": "composer.json",
"chars": 379,
"preview": "{\n \"name\": \"aesop/lasso\",\n \"type\": \"wordpress-plugin\",\n \"description\": \"Lasso Front-end Creator\",\n \"homepage\": \""
},
{
"path": "includes/lasso_autoloader.php",
"chars": 3936,
"preview": "<?php\n/**\n * PSR-4 Autoloader\n *\n * Copied from http://www.php-fig.org/psr/psr-4/examples/\n *\n * @package Lasso\n * @au"
},
{
"path": "includes/process/delete.php",
"chars": 1471,
"preview": "<?php\n\n/**\n * This class is responsible for deleting apost through all-posts menu\n *\n * @since 0.9.3\n */\nnamespace lasso"
},
{
"path": "includes/process/gallery.php",
"chars": 6422,
"preview": "<?php\n/**\n * Process various gallery fucntions like fetching and saving images\n *\n * @since 1.0\n */\nnamespace lasso\\proc"
},
{
"path": "includes/process/map.php",
"chars": 2308,
"preview": "<?php\n/**\n * Process saving a maps locations\n *\n * @since 1.0\n */\nnamespace lasso\\process;\n\nuse lasso\\internal_api\\api_a"
},
{
"path": "includes/process/meta.php",
"chars": 1873,
"preview": "<?php\n/**\n * Class responsible for processing optoins from lasso post meta api\n *\n * @since 1.0\n */\nnamespace lasso\\proc"
},
{
"path": "includes/process/new_object.php",
"chars": 1951,
"preview": "<?php\n/**\n * Adds a new post object\n *\n * @since 1.0\n */\n\nnamespace lasso\\process;\n\nuse lasso\\internal_api\\api_action;\n\n"
},
{
"path": "includes/process/revision.php",
"chars": 2031,
"preview": "<?php\n\nnamespace lasso\\process;\n\n\nuse lasso\\internal_api\\api_action;\n\nclass revision implements api_action {\n\n\t/**\n\t * A"
},
{
"path": "includes/process/save.php",
"chars": 3635,
"preview": "<?php\n/**\n * Main class responsible for saving the post object\n *\n * @since 1.0\n */\nnamespace lasso\\process;\n\nuse lasso\\"
},
{
"path": "includes/process/title_update.php",
"chars": 1576,
"preview": "<?php\n/**\n * Class responsible for processing the post title change\n *\n * @since 1.0\n */\nnamespace lasso\\process;\n\nuse l"
},
{
"path": "includes/process/tour.php",
"chars": 1324,
"preview": "<?php\n/**\n * Class responsible for creating the welcome walkthrough on the editor\n *\n * @since 0.6\n */\n\nnamespace lasso\\"
},
{
"path": "includes/process/update_object.php",
"chars": 5617,
"preview": "<?php\n/**\n * This class is responsible for updating the post settings such as the post slug or post status\n * and is tog"
},
{
"path": "includes/process/upload_image.php",
"chars": 2057,
"preview": "<?php\n/**\n * Process a user uploading an image for the featured image in a post\n *\n * @since 1.0\n */\nnamespace lasso\\pro"
},
{
"path": "includes/sanatize.php",
"chars": 3863,
"preview": "<?php\n/**\n * Generic sanitization, useful for sanitization of arrays.\n *\n * The code in this class is largely lifted fro"
},
{
"path": "includes/save_gallery.php",
"chars": 2542,
"preview": "<?php\n/**\n * Process various gallery fucntions like fetching and saving images\n *\n * @since 1.0\n */\nnamespace lasso;\n\ncl"
},
{
"path": "internal-api/api_action.php",
"chars": 1179,
"preview": "<?php\n/**\n * Interface that all classes used as callbacks for internal API must implement.\n *\n * @since 0.9.2\n * @pa"
},
{
"path": "internal-api/auth.php",
"chars": 3358,
"preview": "<?php\n/**\n * Check if a request is authorized.\n *\n * @package lasso\n * @author Josh Pollock <Josh@JoshPress.net>\n *"
},
{
"path": "internal-api/docs.md",
"chars": 1481,
"preview": "# How Internal API Works\n\n* All requests must be sent to the URL `home_url( 'internal-api' );`.\n* All requests must use "
},
{
"path": "internal-api/end_points.php",
"chars": 782,
"preview": "<?php\n/**\n * Add hooks for internal API.\n *\n * @package lasso\n * @author Josh Pollock <Josh@JoshPress.net>\n * @lice"
},
{
"path": "internal-api/find_data.php",
"chars": 2365,
"preview": "<?php\n/**\n * Find data & sanatize data for this request.\n *\n * @package lasso\n * @author Josh Pollock <Josh@JoshPre"
},
{
"path": "internal-api/route.php",
"chars": 4439,
"preview": "<?php\n/**\n * Route the requests\n *\n * @package lasso\n * @author Josh Pollock <Josh@JoshPress.net>\n * @license GPL"
},
{
"path": "languages/lasso-de_DE.po",
"chars": 70516,
"preview": "msgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: Editus\\n\"\n\"POT-Creation-Date: 2022-08-02 15:40-0400\\n\"\n\"PO-Revision-Date: 2022-0"
},
{
"path": "languages/lasso-es_ES.po",
"chars": 45111,
"preview": "msgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: Editus\\n\"\n\"POT-Creation-Date: 2022-08-02 15:42-0400\\n\"\n\"PO-Revision-Date: 2022-0"
},
{
"path": "languages/lasso-ko_KR.po",
"chars": 44737,
"preview": "msgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: Editus\\n\"\n\"POT-Creation-Date: 2022-08-02 15:43-0400\\n\"\n\"PO-Revision-Date: 2022-0"
},
{
"path": "languages/lasso.pot",
"chars": 53036,
"preview": "# Copyright (C) 2015 Aesopinteractive LLC\n# This file is distributed under the same license as the Lasso (beta) package."
},
{
"path": "lasso.php",
"chars": 6846,
"preview": "<?php\n/**\n *\n *\n * @package Editus\n * @author Hyun Supul <hyun@aesopinteractive.com>, Nick Haskins <nick@aesopinter"
},
{
"path": "package.json",
"chars": 458,
"preview": "{\n \"name\": \"lasso\",\n \"version\": \"0.9.4\",\n \"dependencies\": {\n \"load-grunt-tasks\": \"~0.2.1\"\n },\n \"devDependencies\""
},
{
"path": "public/assets/css/editus-table-edit-public.css",
"chars": 760,
"preview": "ul.lasso-editor-controls .lasso-toolbar--component__htmltable:before,\n#lasso-toolbar--components__list .lasso-toolbar--c"
},
{
"path": "public/assets/css/lasso.css",
"chars": 114050,
"preview": ".lasso--animate__spin{-webkit-animation:spin 2s infinite linear;animation:spin 2s infinite linear}.not-visible{opacity:0"
},
{
"path": "public/assets/css/style.css",
"chars": 98103,
"preview": ".lasso--animate__spin{-webkit-animation:spin 2s infinite linear;animation:spin 2s infinite linear}.not-visible{opacity:0"
},
{
"path": "public/assets/js/editus-table-edit-public.js",
"chars": 3285,
"preview": "jQuery(document).ready(function($){\n\t'use strict';\n\tif (typeof lasso_editor !== 'undefined') {\n\n\t\t// JAVASCRIPT (jQuery)"
},
{
"path": "public/assets/js/lasso.js",
"chars": 566173,
"preview": "/* ways to inject JS Codes\n\nlasso_editor.setupHookArray\nlasso_editor.enterEditorHookArray\nlasso_editor.enterEditorHookAr"
},
{
"path": "public/assets/js/source/all-posts.js",
"chars": 18981,
"preview": "(function( $, Backbone, _, WP_API_Settings, undefined ) {\n\n\tvar contentTemplate = $('#lasso-tmpl--post' )\n\t, \tpostTempla"
},
{
"path": "public/assets/js/source/enter-editor.js",
"chars": 49945,
"preview": "jQuery(document).ready(function($){\n\n\tvar editor \t\t\t= lasso_editor.editor,\n\t\tstrings \t\t= lasso_editor.strings,\n\t\tsetting"
},
{
"path": "public/assets/js/source/modal-sizing.js",
"chars": 639,
"preview": "(function( $ ) {\n\n\t// dyanmically center modals vertically based on size of modal\n\tjQuery(document).ready(function($){\n\n"
},
{
"path": "public/assets/js/source/post-settings.js",
"chars": 8084,
"preview": "(function( $ ) {\n\n\t$(document).ready(function(){\n\n\t\t/////////////////\n\t\t/// MODAL LOGIC\n\t\t///////////////////\n\n\t\t// meth"
},
{
"path": "public/assets/js/source/process-gallery-opts.js",
"chars": 1896,
"preview": "(function( $ ) {\n\n\t$(document).ready(function($){\n\n\t\t// this function is repeated on settings-panel.js\n\t\tvar value_check"
},
{
"path": "public/assets/js/source/process-gallery.js",
"chars": 8099,
"preview": "(function( $ ) {\n\t'use strict';\n\n\t/////////////\n\t// NEW GALLERY CREATE\n\t////////////\n\t//$('#lasso--gallery__create').liv"
},
{
"path": "public/assets/js/source/process-image-upload.js",
"chars": 6364,
"preview": "(function( $ ) {\n\t'use strict';\n\n\t//$( '#lasso--featImgSave a' ).live('click', function(e) {\n\tjQuery(document).on('click"
},
{
"path": "public/assets/js/source/process-map.js",
"chars": 813,
"preview": "(function( $ ) {\n\n\tvar form;\n\n\t//$('#lasso--map-form').live('submit', function(e) {\n\tjQuery(document).on('submit','#lass"
},
{
"path": "public/assets/js/source/process-new-post.js",
"chars": 3865,
"preview": "(function( $ ) {\n\n\t$(document).ready(function(){\n\n\t\t// method to destroy the modal\n\t\tvar destroyModal = function(){\n\t\t\t$"
},
{
"path": "public/assets/js/source/process-save-component.js",
"chars": 8003,
"preview": "(function( $ ) {\n\n\tvar form;\n // get updated aesop componets through ajax calls (global function)\n\twindow.get_aesop_c"
},
{
"path": "public/assets/js/source/process-save-meta.js",
"chars": 849,
"preview": "(function( $ ) {\n\n\t$(document).on('submit', '#lasso--custom-field-form', function(e) {\n\n\t\te.preventDefault();\n\t\t$('#lass"
},
{
"path": "public/assets/js/source/process-save-title.js",
"chars": 901,
"preview": "(function( $ ) {\n\n\t$(document).ready(function(){\n\n\t\t/////////////\n\t\t// SAVE TITLE\n\t\t/////////////\n\n\t\t$(lasso_editor.titl"
},
{
"path": "public/assets/js/source/process-save.js",
"chars": 34454,
"preview": "jQuery(document).ready(function($){\n\n\tvar ajaxurl \t= lasso_editor.ajaxurl,\n\t\tsave \t= $('.lasso--controls__right a')"
},
{
"path": "public/assets/js/source/process-wpimg.js",
"chars": 2374,
"preview": "(function( $ ) {\n\n\t$(document).ready(function(){\n\n\t\t// get the attachment id from teh class wp-image-XXX, where XXX is t"
},
{
"path": "public/assets/js/source/revisions.js",
"chars": 5684,
"preview": "(function( $ ) {\n\n $(document).ready(function(){\n\n var vars \t\t= lasso_editor\n ,\trevisions\n , \tre"
},
{
"path": "public/assets/js/source/settings-live-editing.js",
"chars": 12049,
"preview": "(function( $ ) {\n\n\t$(document).ready(function(){\n\n\t\t/////////////\n\t\t// LIVE EDITING COMPONENTS\n\t\t// @todo - this is hell"
},
{
"path": "public/assets/js/source/settings-panel.js",
"chars": 12162,
"preview": "(function( $ ) {\n\n\t$(document).ready(function(){\n\n\t\t// helper to dstry the sidebar\n\t\tvar destroySidebar = function(){\n\t\t"
},
{
"path": "public/assets/js/source/toolbar.js",
"chars": 10250,
"preview": "jQuery(function( $ ) {\n\n\tfunction saveSelection() {\n\t if (window.getSelection) {\n\t sel = window.getSelection()"
},
{
"path": "public/assets/js/source/tour.js",
"chars": 1807,
"preview": "(function( $ ) {\n\n\t$(document).ready(function(){\n\n\t\tdestroyModal = function(){\n\t\t\t$('body').removeClass('lasso-modal-ope"
},
{
"path": "public/assets/js/source/util--color-picker.js",
"chars": 6690,
"preview": "//color picker\n(function(global) {\n\n // @todo: bind in as a build step, so css is readable\n var basicCSS = '.vanilla-c"
},
{
"path": "public/assets/js/source/util--content-editable.js",
"chars": 53986,
"preview": "/*\n * Medium.js\n *\n * Copyright 2013, Jacob Kelley - http://jakiestfu.com/\n * Released under the MIT Licence\n * http://o"
},
{
"path": "public/assets/js/source/util--geo-complete.js",
"chars": 7376,
"preview": "/**\n * jQuery Geocoding and Places Autocomplete Plugin - V 1.6.4\n *\n * @author Martin Kleppe <kleppe@ubilabs.net>, 2014\n"
},
{
"path": "public/assets/js/source/util--imagesloaded.js",
"chars": 26451,
"preview": "// packaged - 3.1.8\n(function () {\n\n\t/**\n\t * Class for managing events.\n\t * Can be extended to provide event functionali"
},
{
"path": "public/assets/js/source/util--rangy-classapplier.js",
"chars": 42243,
"preview": "/**\n * Class Applier module for Rangy.\n * Adds, removes and toggles classes on Ranges and Selections\n *\n * Part of Rangy"
},
{
"path": "public/assets/js/source/util--rangy-core.js",
"chars": 158302,
"preview": "/**\n * Rangy, a cross-browser JavaScript range and selection library\n * http://code.google.com/p/rangy/\n *\n * Copyright "
},
{
"path": "public/assets/js/source/util--scrollbar.js",
"chars": 29353,
"preview": "/* Copyright (c) 2012, 2014 Hyunje Alex Jun and other contributors\n * Licensed under the MIT License\n */\n(function (fact"
},
{
"path": "public/assets/js/source/util--slider.js",
"chars": 5056,
"preview": "/**\n * Unslider by @idiot\n */\n\n(function($, f) {\n\t// If there's no jQuery, Unslider can't work, so kill the operation"
},
{
"path": "public/assets/js/source/util--sweet-alert.js",
"chars": 24904,
"preview": "// SweetAlert\n// 2014 (c) - Tristan Edwards\n// github.com/t4t5/sweetalert\n;(function(window, document) {\n\n var modalCla"
},
{
"path": "public/assets/js/source/util--tagit.js",
"chars": 23468,
"preview": "/*\n* jQuery UI Tag-it!\n*\n* @version v2.0 (06/2011)\n*\n* Copyright 2011, Levy Carneiro Jr.\n* Released under the MIT licens"
},
{
"path": "public/assets/js/source/util--touch-punch.js",
"chars": 5072,
"preview": "/*!\n * jQuery UI Touch Punch 0.2.3\n *\n * Copyright 2011–2014, Dave Furfero\n * Dual licensed under the MIT or GPL Version"
},
{
"path": "public/assets/js/source/util--undo.js",
"chars": 2714,
"preview": "/* ways to inject JS Codes\n\nlasso_editor.setupHookArray\nlasso_editor.enterEditorHookArray\nlasso_editor.enterEditorHookAr"
},
{
"path": "public/assets/js/source/util--wp-api.js",
"chars": 20440,
"preview": "(function( window, undefined ) {\n\n\t'use strict';\n\n\tfunction WP_API() {\n\t\tthis.models = {};\n\t\tthis.collections = {};\n\t\tth"
},
{
"path": "public/assets/js/tour.js",
"chars": 319,
"preview": "(function( $ ) {\n\t\t\t\t\t\tjQuery(document).ready(function($){\n\n\t\t\t\t\t\t\t$('body').addClass('lasso-modal-open');\n\n\t\t\t\t\t\t\t$('.l"
},
{
"path": "public/assets/less/source/all-posts.less",
"chars": 7628,
"preview": "// modal outer\n.lasso--modal{\n top:10vh;\n\n &.lasso--modal__full {\n\n width:100%;\n max-width:@modal--w"
},
{
"path": "public/assets/less/source/animations.less",
"chars": 1516,
"preview": ".lasso-editing {\n\n .aesop-content-comp-wrap,\n .aesop-video-container,\n .aesop-image-component-image {\n ."
},
{
"path": "public/assets/less/source/component-controls.less",
"chars": 3120,
"preview": "// draggable handle\nul.lasso-component--controls {\n * { .box-sizing(border-box); }\n .editor--tool__bg();\n posit"
},
{
"path": "public/assets/less/source/component-settings--gallery.less",
"chars": 5484,
"preview": "\n// gallery thumb images container\n#lasso--gallery__images {\n min-height: 65px;\n position: relative;\n\n .lasso-i"
},
{
"path": "public/assets/less/source/component-settings--map.less",
"chars": 3364,
"preview": "#lasso--map-form {\n position: relative;\n\n .lasso--map-form__submit {\n position: absolute;\n top:10px;"
},
{
"path": "public/assets/less/source/component-settings.less",
"chars": 5134,
"preview": "#lasso--component__settings {\n\n form {\n margin:0;\n position: relative;\n padding-bottom:@insert--"
},
{
"path": "public/assets/less/source/editor-controls.less",
"chars": 4763,
"preview": "// do not print\n@media print {\n\t#lasso--controls {\n display: none;\n\t}\n}\n\n\n#lasso--controls{\n .lasso--controls__"
},
{
"path": "public/assets/less/source/editor.less",
"chars": 4465,
"preview": ".aesop-component {\n position: relative;\n}\n\n// missing wp media modal styles\n.screen-reader-text, .screen-reader-text "
},
{
"path": "public/assets/less/source/featimg-controls.less",
"chars": 1767,
"preview": "#lasso--featImgControls {\n position: relative;\n z-index: 1;\n left:0;\n right:0;\n text-align: center;\n t"
},
{
"path": "public/assets/less/source/fonts.css",
"chars": 2306,
"preview": "@font-face{font-family:icomoon;src:url(../../../public/assets/fonts/icomoon.eot?ua4grz);src:url(../../../public/assets/f"
},
{
"path": "public/assets/less/source/fonts.less",
"chars": 2742,
"preview": "@font-path: \"../../../public/assets/fonts\";\n\n@font-face {\n\tfont-family: 'icomoon-editus';\n\tsrc:url('@{font-path}/"
},
{
"path": "public/assets/less/source/form-controls.less",
"chars": 9770,
"preview": ".lasso--btn-primary {\n .editor-btn-primary();\n}\n.lasso--btn-secondary {\n .editor-btn-secondary();\n}\n\n.lasso--post-"
},
{
"path": "public/assets/less/source/mixins.css",
"chars": 255,
"preview": ".lasso--animate__spin{-webkit-animation:spin 2s infinite linear;animation:spin 2s infinite linear}.not-visible{opacity:0"
},
{
"path": "public/assets/less/source/mixins.less",
"chars": 12645,
"preview": ".editor--input(){\n background: @input--bg;\n\tbackground-color: @input--bg !important;\n border:1px solid @input--bor"
},
{
"path": "public/assets/less/source/mobile.less",
"chars": 4571,
"preview": "// iOS\n.os-ios {\n .lasso-component--controls {\n .opacity(1);\n left:0;\n }\n}\n\n// small screens\n@media("
},
{
"path": "public/assets/less/source/post-settings.less",
"chars": 6796,
"preview": ".lasso-modal-open {\n overflow: hidden;\n}\n\n// modal overlay\n#lasso--modal__overlay {\n z-index: 9999;\n position: "
},
{
"path": "public/assets/less/source/revisions.less",
"chars": 2979,
"preview": "#lasso--revision__modal {\n\n .lasso--slider_wrap {\n padding:0 16px;\n margin-top:@editor--padding + 8;\n "
},
{
"path": "public/assets/less/source/scrollbar.less",
"chars": 2737,
"preview": ".ps-container.ps-active-x>.ps-scrollbar-x-rail,\n.ps-container.ps-active-y>.ps-scrollbar-y-rail {\n display: block;\n}\n\n"
},
{
"path": "public/assets/less/source/sidebar.less",
"chars": 1527,
"preview": ".lasso-sidebar-open {\n overflow: hidden;\n .lasso-buttoninsert-wrap,\n #lasso--sidebar {\n right:0;\n\n }\n"
},
{
"path": "public/assets/less/source/sweet-alert.less",
"chars": 9298,
"preview": ".sweet-overlay {\n background-color: rgba(0, 0, 0, 0.4);\n position: fixed;\n left: 0;\n right: 0;\n top: 0;\n "
},
{
"path": "public/assets/less/source/toolbar.less",
"chars": 15265,
"preview": "// main toolbar layout\n.lasso--toolbar_wrap {\n\n width: auto;\n left: 50%;\n .translate(-50%, 0);\n\n &.toolbar-e"
},
{
"path": "public/assets/less/source/tour.less",
"chars": 3411,
"preview": ".lasso--tour__modal {\n\n .lasso--postsettings__footer {\n .clearfix();\n }\n\n .lasso--modal__inner {\n "
},
{
"path": "public/assets/less/source/util--tags.less",
"chars": 4080,
"preview": ".story-tags-option,\n.story-categories-option,\n.story-custom-taxonomy-option {\n\n // the tags\n .tagit {\n padd"
},
{
"path": "public/assets/less/source/util--tooltips.less",
"chars": 4679,
"preview": "// lasso tooltip\n.lasso-util--help {\n position: relative;\n cursor: pointer;\n color: @tooltip--icon__color;\n "
},
{
"path": "public/assets/less/source/variables.css",
"chars": 0,
"preview": ""
},
{
"path": "public/assets/less/source/variables.less",
"chars": 6218,
"preview": "// EDITOR GLOBALS\n@editor--font: 'Arial';\n@editor--font__size: 14px;\n@editor--color__success"
},
{
"path": "public/assets/less/source/wpimg-controls.less",
"chars": 662,
"preview": "// edit wp-image -wrap .\n.lasso--wpquote, \n.lasso--wpimg__wrap {\n position: relative;\n}\n\n.lasso--wpquote:hover{\n ."
},
{
"path": "public/assets/less/style.less",
"chars": 888,
"preview": "@import 'source/mixins.less';\n@import 'source/variables.less';\n@import 'source/fonts.less';\n@import 'source/animations.l"
},
{
"path": "public/includes/assets.php",
"chars": 17897,
"preview": "<?php\n/**\n*\tLoad the assets used for Editus\n*\n*\t@since 1.0\n*/\nnamespace lasso_public_facing;\n\nuse lasso\\process\\gallery;"
},
{
"path": "public/includes/components.php",
"chars": 8323,
"preview": "<?php\n/**\n * The functions in this file register the components that will be shown in the component drop-up menu\n * and "
},
{
"path": "public/includes/editor-modules--gallery.php",
"chars": 8611,
"preview": "<?php\n\n/**\n * Build the gallery creation and management area shown in panel\n *\n * @since 1.0\n */\nfunction lasso_gallery_"
},
{
"path": "public/includes/editor-modules.php",
"chars": 57307,
"preview": "<?php\n\n/**\n * These functions are then localized and then appended with JS in enter-editor.js\n *\n * @since 1.0\n */\n\n/**\n"
},
{
"path": "public/includes/helpers.php",
"chars": 11878,
"preview": "<?php\n\n/**\n * Grab an option from our settings\n *\n * If we're on multsite we'll grab the site option which is stored in "
},
{
"path": "public/includes/lasso.php",
"chars": 25691,
"preview": "<?php\n/**\n * AH Editor\n *\n * @package Lasso\n * @author Nick Haskins <nick@aesopinteractive.com>\n * @license GPL-2"
},
{
"path": "public/includes/option-engine.php",
"chars": 7836,
"preview": "<?php\n/**\n*\tThis is used by addons to add cool stuff to the settings modal as an additional tab\n*\n*\tExample:\n*\tadd_filte"
},
{
"path": "public/includes/register_meta_field.php",
"chars": 809,
"preview": "<?php\n/**\n * Helper class for registering meta fields to work with Editus Options API\n */\n\nnamespace lasso_public_facing"
},
{
"path": "public/includes/tour.php",
"chars": 3512,
"preview": "<?php\n/**\n * Class responsible for creating the welcome walkthrough on the editor\n *\n * @since 0.6\n */\n\nnamespace lasso_"
},
{
"path": "public/includes/underscore-templates.php",
"chars": 1757,
"preview": "<?php\n\nif ( !function_exists( 'lasso_backbone_templates' ) ):\n\n\tadd_action('wp_footer', 'lasso_backbone_templates');\n\tfu"
},
{
"path": "public/includes/wrap-shortcodes.php",
"chars": 2689,
"preview": "<?php\n/**\n * Wraps shortcodes of other Plugins in prep for later replacement on save to preserve the shortcodes\n */\n\n\n\n "
},
{
"path": "uninstall.php",
"chars": 485,
"preview": "<?php\n/**\n * Fired when the plugin is uninstalled.\n *\n * @package Lasso\n * @author Nick Haskins <nick@aesopinteract"
}
]
// ... and 3 more files (download for full content)
About this extraction
This page contains the full source code of the AesopInteractive/lasso GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 127 files (2.1 MB), approximately 548.4k tokens, and a symbol index with 867 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.