first commit
BIN
wp-content/plugins/.DS_Store
vendored
Normal file
34
wp-content/plugins/akismet/.htaccess
Normal file
@@ -0,0 +1,34 @@
|
||||
# Only allow direct access to specific Web-available files.
|
||||
|
||||
# Apache 2.2
|
||||
<IfModule !mod_authz_core.c>
|
||||
Order Deny,Allow
|
||||
Deny from all
|
||||
</IfModule>
|
||||
|
||||
# Apache 2.4
|
||||
<IfModule mod_authz_core.c>
|
||||
Require all denied
|
||||
</IfModule>
|
||||
|
||||
# Akismet CSS and JS
|
||||
<FilesMatch "^(form\.js|akismet(-frontend|-admin)?\.js|akismet(-admin)?(-rtl)?\.css|inter\.css)$">
|
||||
<IfModule !mod_authz_core.c>
|
||||
Allow from all
|
||||
</IfModule>
|
||||
|
||||
<IfModule mod_authz_core.c>
|
||||
Require all granted
|
||||
</IfModule>
|
||||
</FilesMatch>
|
||||
|
||||
# Akismet images
|
||||
<FilesMatch "^(logo-a-2x\.png|akismet-refresh-logo\.svg|akismet-refresh-logo@2x\.png|arrow-left\.svg|akismet-activation-banner-elements\.png)$">
|
||||
<IfModule !mod_authz_core.c>
|
||||
Allow from all
|
||||
</IfModule>
|
||||
|
||||
<IfModule mod_authz_core.c>
|
||||
Require all granted
|
||||
</IfModule>
|
||||
</FilesMatch>
|
||||
339
wp-content/plugins/akismet/LICENSE.txt
Normal file
@@ -0,0 +1,339 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
716
wp-content/plugins/akismet/_inc/akismet-admin.css
Normal file
@@ -0,0 +1,716 @@
|
||||
body {
|
||||
--akismet-color-charcoal: #272635;
|
||||
--akismet-color-light-grey: #f6f7f7;
|
||||
--akismet-color-mid-grey: #a7aaad;
|
||||
--akismet-color-dark-grey: #646970;
|
||||
--akismet-color-grey-80: #2c3338;
|
||||
--akismet-color-grey-100: #101517;
|
||||
--akismet-color-grey-border: #dcdcde;
|
||||
--akismet-color-white: #fff;
|
||||
--akismet-color-dark-green: #2d6a40;
|
||||
--akismet-color-mid-green: #357b49;
|
||||
--akismet-color-light-green: #4eb26a;
|
||||
--akismet-color-mid-red: #e82c3f;
|
||||
--akismet-color-light-blue: #256eff;
|
||||
--akismet-color-notice-light-green: #dbf0e1;
|
||||
--akismet-color-notice-dark-green: #69bf82;
|
||||
--akismet-color-notice-light-red: #ffdbde;
|
||||
--akismet-color-notice-dark-red: #ff6676;
|
||||
--akismet-color-notice-yellow: #e5c133;
|
||||
}
|
||||
|
||||
/* UI components */
|
||||
.akismet-new-feature {
|
||||
background-color: var(--akismet-color-mid-green);
|
||||
border-radius: 4px;
|
||||
color: var(--akismet-color-white);
|
||||
font-size: 10px;
|
||||
padding: 4px 6px;
|
||||
text-transform: uppercase;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
#akismet-plugin-container {
|
||||
background-color: var(--akismet-color-light-grey);
|
||||
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen-Sans', 'Ubuntu', 'Cantarell', 'Helvetica Neue', sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
#akismet-plugin-container a {
|
||||
color: var(--akismet-color-mid-green);
|
||||
}
|
||||
|
||||
#akismet-plugin-container a.akismet-button {
|
||||
background-color: var(--akismet-color-mid-green);
|
||||
color: var(--akismet-color-white);
|
||||
}
|
||||
|
||||
#akismet-plugin-container button:focus-visible,
|
||||
#akismet-plugin-container input:focus-visible,
|
||||
#akismet-plugin-container a:focus-visible {
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
outline: 2px solid var(--akismet-color-light-blue);
|
||||
}
|
||||
|
||||
.akismet-masthead {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.akismet-masthead__logo {
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.akismet-section-header {
|
||||
box-shadow: none;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.akismet-section-header__label {
|
||||
color: var(--akismet-color-charcoal);
|
||||
font-weight: 600;
|
||||
padding-left: 0.2em;
|
||||
}
|
||||
|
||||
.akismet-button,
|
||||
.akismet-button:hover {
|
||||
border: 0;
|
||||
color: var(--akismet-color-white);
|
||||
}
|
||||
|
||||
.akismet-button {
|
||||
background-color: var(--akismet-color-mid-green);
|
||||
}
|
||||
|
||||
.akismet-button:hover {
|
||||
background-color: var(--akismet-color-dark-green);
|
||||
}
|
||||
|
||||
.akismet-external-link::after {
|
||||
content: "↗";
|
||||
display: inline-block;
|
||||
padding-left: 2px;
|
||||
text-decoration: none;
|
||||
vertical-align: text-top;
|
||||
}
|
||||
|
||||
/* Need this specificity to override the existing header rule */
|
||||
.akismet-new-snapshot h3.akismet-new-snapshot__header {
|
||||
background: none;
|
||||
font-size: 13px;
|
||||
color: var(--akismet-color-charcoal);
|
||||
text-align: left;
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
.akismet-new-snapshot__number {
|
||||
color: var(--akismet-color-charcoal);
|
||||
display: block;
|
||||
font-size: 32px;
|
||||
font-weight: 400;
|
||||
letter-spacing: -1px;
|
||||
line-height: 1.5em;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.akismet-new-snapshot li.akismet-new-snapshot__item {
|
||||
color: var(--akismet-color-dark-grey);
|
||||
font-size: 13px;
|
||||
text-align: left;
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
.akismet-masthead__logo-link {
|
||||
min-height: 50px;
|
||||
}
|
||||
|
||||
.akismet-masthead__back-link-container {
|
||||
margin-top: 16px;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
/* Need this specificity to override the existing link rule */
|
||||
#akismet-plugin-container a.akismet-masthead__back-link {
|
||||
background-image: url(img/arrow-left.svg);
|
||||
background-position: left;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 16px;
|
||||
color: var(--akismet-color-charcoal);
|
||||
font-weight: 400;
|
||||
padding-left: 20px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#akismet-plugin-container a.akismet-masthead__back-link:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.akismet-new-snapshot__item {
|
||||
border-top: 1px solid var(--akismet-color-light-grey);
|
||||
border-left: 1px solid var(--akismet-color-light-grey);
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
.akismet-new-snapshot li:first-child {
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
.akismet-new-snapshot__list {
|
||||
display: flex;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.akismet-new-snapshot__item {
|
||||
flex: 1 0 33.33%;
|
||||
margin-bottom: 0;
|
||||
padding-left: 1.5em;
|
||||
padding-right: 1.5em;
|
||||
}
|
||||
|
||||
.akismet-new-snapshot__chart {
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
.akismet-box {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.akismet-box:not(:first-child) {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.akismet-box,
|
||||
.akismet-card {
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.06), 0 0 2px rgba(0, 0, 0, 0.16);
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.akismet-card {
|
||||
margin: 32px auto 0 auto;
|
||||
}
|
||||
|
||||
.akismet-lower {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.akismet-lower .inside {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.akismet-section-header__label {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.akismet-settings__row {
|
||||
border-bottom: 1px solid var(--akismet-color-light-grey);
|
||||
display: block;
|
||||
padding: 1em 1.5em;
|
||||
}
|
||||
|
||||
.akismet-settings__row-input {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.akismet-settings__row-title {
|
||||
font-weight: 500;
|
||||
font-size: 1em;
|
||||
margin: 0;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.akismet-settings__row-description {
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
|
||||
.akismet-card-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
.akismet-card-actions__secondary-action {
|
||||
align-self: center;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.akismet-settings__row label {
|
||||
padding-bottom: 1em;
|
||||
}
|
||||
|
||||
.akismet-settings__row-note {
|
||||
font-size: 0.9em;
|
||||
margin-top: 0.4em;
|
||||
}
|
||||
|
||||
.akismet-settings__row input[type="checkbox"],
|
||||
.akismet-settings__row input[type="radio"] {
|
||||
accent-color: var(--akismet-color-mid-green);
|
||||
box-shadow: none;
|
||||
flex-shrink: 0;
|
||||
margin: 2px 0 0 0;
|
||||
}
|
||||
|
||||
.akismet-settings__row input[type="checkbox"] {
|
||||
margin-top: 1px;
|
||||
vertical-align: top;
|
||||
-webkit-appearance: checkbox;
|
||||
}
|
||||
|
||||
.akismet-settings__row input[type="radio"] {
|
||||
-webkit-appearance: radio;
|
||||
}
|
||||
|
||||
/* Fix up misbehaving wp-admin styles in Chrome (from forms and colors stylesheets) */
|
||||
.akismet-settings__row input[type="checkbox"]:checked:before {
|
||||
content: '';
|
||||
}
|
||||
|
||||
.akismet-settings__row input[type="radio"]:checked:before {
|
||||
background: none;
|
||||
}
|
||||
|
||||
.akismet-settings__row input[type="checkbox"]:checked:hover,
|
||||
.akismet-settings__row input[type="radio"]:checked:hover {
|
||||
accent-color: var(--akismet-color-mid-green);
|
||||
}
|
||||
|
||||
.akismet-button:disabled {
|
||||
background-color: var(--akismet-color-mid-grey);
|
||||
color: var(--akismet-color-white);
|
||||
cursor: arrow;
|
||||
}
|
||||
|
||||
.akismet-awaiting-stats,
|
||||
.akismet-account {
|
||||
padding: 0 1rem 1rem 1rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.akismet-account {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.akismet-account th {
|
||||
font-weight: 500;
|
||||
padding-right: 1em;
|
||||
}
|
||||
|
||||
.akismet-account th, .akismet-account td {
|
||||
padding-bottom: 1em;
|
||||
}
|
||||
|
||||
.akismet-settings__row-input-label {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.akismet-settings__row-label-text {
|
||||
padding-left: 0.5em;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.akismet-alert {
|
||||
border-left: 8px solid;
|
||||
border-radius: 8px;
|
||||
margin: 20px 0;
|
||||
padding: 0.2em 1em;
|
||||
}
|
||||
|
||||
.akismet-alert__heading {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
.akismet-alert.is-good {
|
||||
background-color: var(--akismet-color-notice-light-green);
|
||||
border-left-color: var(--akismet-color-notice-dark-green);
|
||||
}
|
||||
|
||||
.akismet-alert.is-neutral {
|
||||
background-color: var(--akismet-color-white);
|
||||
border-left-color: var(--akismet-color-dark-grey);
|
||||
}
|
||||
|
||||
.akismet-alert.is-bad {
|
||||
background-color: var(--akismet-color-notice-light-red);
|
||||
border-left-color: var(--akismet-color-notice-dark-red);
|
||||
}
|
||||
|
||||
.akismet-alert.is-commercial {
|
||||
background-color: var(--akismet-color-white);
|
||||
border-color: var(--akismet-color-mid-grey);
|
||||
border-bottom-width: 1px;
|
||||
border-left-color: var(--akismet-color-notice-yellow);
|
||||
display: flex;
|
||||
padding-bottom: 1em;
|
||||
}
|
||||
|
||||
#akismet-plugin-container .akismet-alert.is-good a,
|
||||
#akismet-plugin-container .akismet-alert.is-bad a {
|
||||
/* For better contrast - green isn't great */
|
||||
color: var(--akismet-color-grey-80);
|
||||
}
|
||||
|
||||
.akismet-alert-header {
|
||||
font-size: 16px;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
.akismet-alert-button-wrapper {
|
||||
align-self: center;
|
||||
margin-left: 2em;
|
||||
min-width: 120px;
|
||||
}
|
||||
|
||||
.akismet-alert-info {
|
||||
text-wrap: pretty;
|
||||
margin: 0.5em 0;
|
||||
}
|
||||
|
||||
/* Setup */
|
||||
.akismet-setup-instructions__heading {
|
||||
font-size: 1.375rem;
|
||||
font-weight: 700;
|
||||
padding-block-end: 0;
|
||||
}
|
||||
|
||||
h3.akismet-setup-instructions__subheading {
|
||||
color: var(--akismet-color-dark-grey);
|
||||
font-size: 1rem;
|
||||
font-weight: 400;
|
||||
line-height: 1.5;
|
||||
margin: 0 0 1.25rem;
|
||||
padding-block-start: 1rem;
|
||||
}
|
||||
|
||||
.akismet-setup-instructions__feature-list {
|
||||
list-style: none;
|
||||
margin: 1rem 0.5rem 1.5rem;
|
||||
max-width: 640px;
|
||||
padding: 0 1rem;
|
||||
}
|
||||
|
||||
.akismet-setup-instructions__feature {
|
||||
align-items: start;
|
||||
display: flex;
|
||||
margin-block-end: 1rem;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.akismet-setup-instructions__icon {
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
}
|
||||
|
||||
.akismet-setup-instructions__body {
|
||||
flex: 1;
|
||||
padding-inline-start: 0.5rem;
|
||||
}
|
||||
|
||||
.akismet-setup-instructions__title {
|
||||
color: #1d2327;
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
line-height: 1.3;
|
||||
margin: 0;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
p.akismet-setup-instructions__text {
|
||||
color: var(--akismet-color-grey-80);
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.5;
|
||||
margin: 0.25rem 0 0;
|
||||
padding: 0;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.akismet-setup-instructions__button,
|
||||
.akismet-setup-instructions__button:hover,
|
||||
.akismet-setup-instructions__button:visited {
|
||||
font-size: 1rem;
|
||||
margin-inline-start: 1.5rem;
|
||||
}
|
||||
|
||||
.akismet-setup__connection {
|
||||
background: var(--akismet-color-light-grey);
|
||||
border: 1px solid var(--akismet-color-grey-border);
|
||||
border-radius: 8px;
|
||||
margin: 1rem 1rem 2rem 1rem;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.akismet-setup__connection-action:not(:last-child) {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.akismet-setup__connection-user {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.akismet-setup__connection-avatar {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.akismet-setup__connection-avatar-image {
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.akismet-setup__connection-account-name {
|
||||
color: var(--akismet-color-charcoal);
|
||||
font-size: 0.9rem;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.akismet-setup__connection-account-email {
|
||||
margin-top: 0.1rem;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.akismet-setup__connection-action {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.akismet-setup__connection-button {
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
p.akismet-setup__connection-action-intro,
|
||||
p.akismet-setup__connection-action-description {
|
||||
color: var(--akismet-color-dark-grey);
|
||||
font-size: 0.875rem;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
p.akismet-setup__connection-action-intro {
|
||||
margin: 0 0 1rem 0;
|
||||
}
|
||||
|
||||
p.akismet-setup__connection-action-description {
|
||||
margin: 1rem 0 0;
|
||||
}
|
||||
|
||||
/* Setup - API key input */
|
||||
.akismet-enter-api-key-box {
|
||||
margin: 1.5rem 0;
|
||||
}
|
||||
|
||||
.akismet-enter-api-key-box__reveal {
|
||||
background: none;
|
||||
border: 0;
|
||||
color: var(--akismet-color-mid-green);
|
||||
cursor: pointer;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.akismet-enter-api-key-box__form-wrapper {
|
||||
display: none;
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
|
||||
.akismet-enter-api-key-box__input-wrapper {
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
padding: 0 1.5rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.akismet-enter-api-key-box__key-input {
|
||||
flex-grow: 1;
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
h3.akismet-enter-api-key-box__header {
|
||||
padding-top: 0;
|
||||
padding-bottom: 1em;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
/* Notices > Activation (shown on edit-comments.php) */
|
||||
#akismet-setup-prompt {
|
||||
background: none;
|
||||
border: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.akismet-activate {
|
||||
align-items: center;
|
||||
/* background-image is defined via an inline style in class.akismet-admin.php */
|
||||
background-color: var(--akismet-color-light-grey);
|
||||
background-position: calc(100% - 1em) center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 140px;
|
||||
border: 1px solid var(--akismet-color-mid-green);
|
||||
border-left-width: 4px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin: 15px 0;
|
||||
min-height: 60px;
|
||||
overflow: hidden;
|
||||
padding: 5px 160px 5px 5px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.akismet-activate__button,
|
||||
.akismet-activate__button:hover,
|
||||
.akismet-activate__button:visited {
|
||||
margin: 0 1em;
|
||||
}
|
||||
|
||||
.akismet-activate__description {
|
||||
color: var(--akismet-color-charcoal);
|
||||
flex-grow: 1;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
text-wrap: pretty;
|
||||
}
|
||||
|
||||
/* Compatible plugins section */
|
||||
.akismet-compatible-plugins__content {
|
||||
padding: 0 1.5em 1.5em 1.5em;
|
||||
}
|
||||
|
||||
.akismet-compatible-plugins__intro {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.akismet-compatible-plugins__section-header-label {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.akismet-compatible-plugins__section-header-label-text {
|
||||
padding-right: 0.5em;
|
||||
}
|
||||
|
||||
.akismet-compatible-plugins__list {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(245px, 1fr));
|
||||
gap: 20px;
|
||||
margin: 1.5em 0 1em 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.akismet-compatible-plugins__card {
|
||||
border: 1px solid var(--akismet-color-light-grey);
|
||||
border-radius: 4px;
|
||||
flex: 1 1 calc(50% - 5px);
|
||||
padding: 1em;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.akismet-compatible-plugins__card-logo {
|
||||
padding: 0 1.5em 0 0;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.akismet-compatible-plugins__card-title {
|
||||
font-size: 1.2em;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.akismet-compatible-plugins__docs {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.akismet-compatible-plugins__show-more {
|
||||
all: unset;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Generates the show/hide chevron */
|
||||
.akismet-compatible-plugins__show-more::after {
|
||||
align-self: center;
|
||||
border-bottom: 2px solid black;
|
||||
border-right: 2px solid black;
|
||||
content: "";
|
||||
height: 8px;
|
||||
transform: rotate(45deg);
|
||||
transition: transform 0.2s ease;
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
.akismet-compatible-plugins__list.is-expanded + .akismet-compatible-plugins__show-more::after {
|
||||
align-self: end;
|
||||
transform: rotate(225deg);
|
||||
}
|
||||
|
||||
/* Gutenberg medium breakpoint */
|
||||
@media screen and (max-width: 782px) {
|
||||
.akismet-new-snapshot__list {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.akismet-new-snapshot__number {
|
||||
float: right;
|
||||
font-size: 20px;
|
||||
font-weight: 500;
|
||||
margin-top: -16px;
|
||||
}
|
||||
|
||||
.akismet-new-snapshot__header {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.akismet-new-snapshot__text {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.akismet-settings__row input[type="checkbox"],
|
||||
.akismet-settings__row input[type="radio"] {
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
}
|
||||
|
||||
.akismet-settings__row-label-text {
|
||||
padding-left: 0.8em;
|
||||
}
|
||||
|
||||
.akismet-settings__row input[type="checkbox"],
|
||||
.akismet-settings__row input[type="radio"] {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.akismet-activate {
|
||||
background-size: 120px;
|
||||
padding-right: 134px;
|
||||
}
|
||||
|
||||
.akismet-activate__button {
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.akismet-activate__description {
|
||||
font-size: 14px;
|
||||
margin-right: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
/* Gutenberg small breakpoint */
|
||||
@media screen and (max-width: 600px) {
|
||||
.akismet-compatible-plugins__list {
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.akismet-activate__button,
|
||||
.akismet-activate__button:hover {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.akismet-activate__description {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
37
wp-content/plugins/akismet/_inc/akismet-admin.js
Normal file
@@ -0,0 +1,37 @@
|
||||
document.addEventListener( 'DOMContentLoaded', function() {
|
||||
// Prevent aggressive iframe caching in Firefox
|
||||
var statsIframe = document.getElementById( 'stats-iframe' );
|
||||
if ( statsIframe ) {
|
||||
statsIframe.contentWindow.location.href = statsIframe.src;
|
||||
}
|
||||
|
||||
initCompatiblePluginsShowMoreToggle();
|
||||
} );
|
||||
|
||||
function initCompatiblePluginsShowMoreToggle() {
|
||||
const section = document.querySelector( '.akismet-compatible-plugins' );
|
||||
const list = document.querySelector( '.akismet-compatible-plugins__list' );
|
||||
const button = document.querySelector( '.akismet-compatible-plugins__show-more' );
|
||||
|
||||
if ( ! section || ! list || ! button ) {
|
||||
return;
|
||||
}
|
||||
|
||||
function isElementInViewport( element ) {
|
||||
const rect = element.getBoundingClientRect();
|
||||
return rect.top >= 0 && rect.bottom <= window.innerHeight;
|
||||
}
|
||||
|
||||
function toggleCards() {
|
||||
list.classList.toggle( 'is-expanded' );
|
||||
const isExpanded = list.classList.contains( 'is-expanded' );
|
||||
button.textContent = isExpanded ? button.dataset.labelOpen : button.dataset.labelClosed;
|
||||
button.setAttribute( 'aria-expanded', isExpanded.toString() );
|
||||
|
||||
if ( ! isExpanded && ! isElementInViewport( section ) ) {
|
||||
section.scrollIntoView( { block: 'start' } );
|
||||
}
|
||||
}
|
||||
|
||||
button.addEventListener( 'click', toggleCards );
|
||||
}
|
||||
376
wp-content/plugins/akismet/_inc/akismet-frontend.js
Normal file
@@ -0,0 +1,376 @@
|
||||
/**
|
||||
* Observe how the user enters content into the comment form in order to determine whether it's a bot or not.
|
||||
*
|
||||
* Note that no actual input is being saved here, only counts and timings between events.
|
||||
*/
|
||||
|
||||
( function() {
|
||||
// Passive event listeners are guaranteed to never call e.preventDefault(),
|
||||
// but they're not supported in all browsers. Use this feature detection
|
||||
// to determine whether they're available for use.
|
||||
var supportsPassive = false;
|
||||
|
||||
try {
|
||||
var opts = Object.defineProperty( {}, 'passive', {
|
||||
get : function() {
|
||||
supportsPassive = true;
|
||||
}
|
||||
} );
|
||||
|
||||
window.addEventListener( 'testPassive', null, opts );
|
||||
window.removeEventListener( 'testPassive', null, opts );
|
||||
} catch ( e ) {}
|
||||
|
||||
function init() {
|
||||
var input_begin = '';
|
||||
|
||||
var keydowns = {};
|
||||
var lastKeyup = null;
|
||||
var lastKeydown = null;
|
||||
var keypresses = [];
|
||||
|
||||
var modifierKeys = [];
|
||||
var correctionKeys = [];
|
||||
|
||||
var lastMouseup = null;
|
||||
var lastMousedown = null;
|
||||
var mouseclicks = [];
|
||||
|
||||
var mousemoveTimer = null;
|
||||
var lastMousemoveX = null;
|
||||
var lastMousemoveY = null;
|
||||
var mousemoveStart = null;
|
||||
var mousemoves = [];
|
||||
|
||||
var touchmoveCountTimer = null;
|
||||
var touchmoveCount = 0;
|
||||
|
||||
var lastTouchEnd = null;
|
||||
var lastTouchStart = null;
|
||||
var touchEvents = [];
|
||||
|
||||
var scrollCountTimer = null;
|
||||
var scrollCount = 0;
|
||||
|
||||
var correctionKeyCodes = [ 'Backspace', 'Delete', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'Home', 'End', 'PageUp', 'PageDown' ];
|
||||
var modifierKeyCodes = [ 'Shift', 'CapsLock' ];
|
||||
|
||||
var forms = document.querySelectorAll( 'form[method=post]' );
|
||||
|
||||
for ( var i = 0; i < forms.length; i++ ) {
|
||||
var form = forms[i];
|
||||
|
||||
var formAction = form.getAttribute( 'action' );
|
||||
|
||||
// Ignore forms that POST directly to other domains; these could be things like payment forms.
|
||||
if ( formAction ) {
|
||||
// Check that the form is posting to an external URL, not a path.
|
||||
if ( formAction.indexOf( 'http://' ) == 0 || formAction.indexOf( 'https://' ) == 0 ) {
|
||||
if ( formAction.indexOf( 'http://' + window.location.hostname + '/' ) != 0 && formAction.indexOf( 'https://' + window.location.hostname + '/' ) != 0 ) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
form.addEventListener( 'submit', function () {
|
||||
var ak_bkp = prepare_timestamp_array_for_request( keypresses );
|
||||
var ak_bmc = prepare_timestamp_array_for_request( mouseclicks );
|
||||
var ak_bte = prepare_timestamp_array_for_request( touchEvents );
|
||||
var ak_bmm = prepare_timestamp_array_for_request( mousemoves );
|
||||
|
||||
var input_fields = {
|
||||
// When did the user begin entering any input?
|
||||
'bib': input_begin,
|
||||
|
||||
// When was the form submitted?
|
||||
'bfs': Date.now(),
|
||||
|
||||
// How many keypresses did they make?
|
||||
'bkpc': keypresses.length,
|
||||
|
||||
// How quickly did they press a sample of keys, and how long between them?
|
||||
'bkp': ak_bkp,
|
||||
|
||||
// How quickly did they click the mouse, and how long between clicks?
|
||||
'bmc': ak_bmc,
|
||||
|
||||
// How many mouseclicks did they make?
|
||||
'bmcc': mouseclicks.length,
|
||||
|
||||
// When did they press modifier keys (like Shift or Capslock)?
|
||||
'bmk': modifierKeys.join( ';' ),
|
||||
|
||||
// When did they correct themselves? e.g., press Backspace, or use the arrow keys to move the cursor back
|
||||
'bck': correctionKeys.join( ';' ),
|
||||
|
||||
// How many times did they move the mouse?
|
||||
'bmmc': mousemoves.length,
|
||||
|
||||
// How many times did they move around using a touchscreen?
|
||||
'btmc': touchmoveCount,
|
||||
|
||||
// How many times did they scroll?
|
||||
'bsc': scrollCount,
|
||||
|
||||
// How quickly did they perform touch events, and how long between them?
|
||||
'bte': ak_bte,
|
||||
|
||||
// How many touch events were there?
|
||||
'btec' : touchEvents.length,
|
||||
|
||||
// How quickly did they move the mouse, and how long between moves?
|
||||
'bmm' : ak_bmm
|
||||
};
|
||||
|
||||
var akismet_field_prefix = 'ak_';
|
||||
|
||||
if ( this.getElementsByClassName ) {
|
||||
// Check to see if we've used an alternate field name prefix. We store this as an attribute of the container around some of the Akismet fields.
|
||||
var possible_akismet_containers = this.getElementsByClassName( 'akismet-fields-container' );
|
||||
|
||||
for ( var containerIndex = 0; containerIndex < possible_akismet_containers.length; containerIndex++ ) {
|
||||
var container = possible_akismet_containers.item( containerIndex );
|
||||
|
||||
if ( container.getAttribute( 'data-prefix' ) ) {
|
||||
akismet_field_prefix = container.getAttribute( 'data-prefix' );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for ( var field_name in input_fields ) {
|
||||
var field = document.createElement( 'input' );
|
||||
field.setAttribute( 'type', 'hidden' );
|
||||
field.setAttribute( 'name', akismet_field_prefix + field_name );
|
||||
field.setAttribute( 'value', input_fields[ field_name ] );
|
||||
this.appendChild( field );
|
||||
}
|
||||
}, supportsPassive ? { passive: true } : false );
|
||||
|
||||
form.addEventListener( 'keydown', function ( e ) {
|
||||
// If you hold a key down, some browsers send multiple keydown events in a row.
|
||||
// Ignore any keydown events for a key that hasn't come back up yet.
|
||||
if ( e.key in keydowns ) {
|
||||
return;
|
||||
}
|
||||
|
||||
var keydownTime = ( new Date() ).getTime();
|
||||
keydowns[ e.key ] = [ keydownTime ];
|
||||
|
||||
if ( ! input_begin ) {
|
||||
input_begin = keydownTime;
|
||||
}
|
||||
|
||||
// In some situations, we don't want to record an interval since the last keypress -- for example,
|
||||
// on the first keypress, or on a keypress after focus has changed to another element. Normally,
|
||||
// we want to record the time between the last keyup and this keydown. But if they press a
|
||||
// key while already pressing a key, we want to record the time between the two keydowns.
|
||||
|
||||
var lastKeyEvent = Math.max( lastKeydown, lastKeyup );
|
||||
|
||||
if ( lastKeyEvent ) {
|
||||
keydowns[ e.key ].push( keydownTime - lastKeyEvent );
|
||||
}
|
||||
|
||||
lastKeydown = keydownTime;
|
||||
}, supportsPassive ? { passive: true } : false );
|
||||
|
||||
form.addEventListener( 'keyup', function ( e ) {
|
||||
if ( ! ( e.key in keydowns ) ) {
|
||||
// This key was pressed before this script was loaded, or a mouseclick happened during the keypress, or...
|
||||
return;
|
||||
}
|
||||
|
||||
var keyupTime = ( new Date() ).getTime();
|
||||
|
||||
if ( 'TEXTAREA' === e.target.nodeName || 'INPUT' === e.target.nodeName ) {
|
||||
if ( -1 !== modifierKeyCodes.indexOf( e.key ) ) {
|
||||
modifierKeys.push( keypresses.length - 1 );
|
||||
} else if ( -1 !== correctionKeyCodes.indexOf( e.key ) ) {
|
||||
correctionKeys.push( keypresses.length - 1 );
|
||||
} else {
|
||||
// ^ Don't record timings for keys like Shift or backspace, since they
|
||||
// typically get held down for longer than regular typing.
|
||||
|
||||
var keydownTime = keydowns[ e.key ][0];
|
||||
|
||||
var keypress = [];
|
||||
|
||||
// Keypress duration.
|
||||
keypress.push( keyupTime - keydownTime );
|
||||
|
||||
// Amount of time between this keypress and the previous keypress.
|
||||
if ( keydowns[ e.key ].length > 1 ) {
|
||||
keypress.push( keydowns[ e.key ][1] );
|
||||
}
|
||||
|
||||
keypresses.push( keypress );
|
||||
}
|
||||
}
|
||||
|
||||
delete keydowns[ e.key ];
|
||||
|
||||
lastKeyup = keyupTime;
|
||||
}, supportsPassive ? { passive: true } : false );
|
||||
|
||||
form.addEventListener( "focusin", function ( e ) {
|
||||
lastKeydown = null;
|
||||
lastKeyup = null;
|
||||
keydowns = {};
|
||||
}, supportsPassive ? { passive: true } : false );
|
||||
|
||||
form.addEventListener( "focusout", function ( e ) {
|
||||
lastKeydown = null;
|
||||
lastKeyup = null;
|
||||
keydowns = {};
|
||||
}, supportsPassive ? { passive: true } : false );
|
||||
}
|
||||
|
||||
document.addEventListener( 'mousedown', function ( e ) {
|
||||
lastMousedown = ( new Date() ).getTime();
|
||||
}, supportsPassive ? { passive: true } : false );
|
||||
|
||||
document.addEventListener( 'mouseup', function ( e ) {
|
||||
if ( ! lastMousedown ) {
|
||||
// If the mousedown happened before this script was loaded, but the mouseup happened after...
|
||||
return;
|
||||
}
|
||||
|
||||
var now = ( new Date() ).getTime();
|
||||
|
||||
var mouseclick = [];
|
||||
mouseclick.push( now - lastMousedown );
|
||||
|
||||
if ( lastMouseup ) {
|
||||
mouseclick.push( lastMousedown - lastMouseup );
|
||||
}
|
||||
|
||||
mouseclicks.push( mouseclick );
|
||||
|
||||
lastMouseup = now;
|
||||
|
||||
// If the mouse has been clicked, don't record this time as an interval between keypresses.
|
||||
lastKeydown = null;
|
||||
lastKeyup = null;
|
||||
keydowns = {};
|
||||
}, supportsPassive ? { passive: true } : false );
|
||||
|
||||
document.addEventListener( 'mousemove', function ( e ) {
|
||||
if ( mousemoveTimer ) {
|
||||
clearTimeout( mousemoveTimer );
|
||||
mousemoveTimer = null;
|
||||
}
|
||||
else {
|
||||
mousemoveStart = ( new Date() ).getTime();
|
||||
lastMousemoveX = e.offsetX;
|
||||
lastMousemoveY = e.offsetY;
|
||||
}
|
||||
|
||||
mousemoveTimer = setTimeout( function ( theEvent, originalMousemoveStart ) {
|
||||
var now = ( new Date() ).getTime() - 500; // To account for the timer delay.
|
||||
|
||||
var mousemove = [];
|
||||
mousemove.push( now - originalMousemoveStart );
|
||||
mousemove.push(
|
||||
Math.round(
|
||||
Math.sqrt(
|
||||
Math.pow( theEvent.offsetX - lastMousemoveX, 2 ) +
|
||||
Math.pow( theEvent.offsetY - lastMousemoveY, 2 )
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
if ( mousemove[1] > 0 ) {
|
||||
// If there was no measurable distance, then it wasn't really a move.
|
||||
mousemoves.push( mousemove );
|
||||
}
|
||||
|
||||
mousemoveStart = null;
|
||||
mousemoveTimer = null;
|
||||
}, 500, e, mousemoveStart );
|
||||
}, supportsPassive ? { passive: true } : false );
|
||||
|
||||
document.addEventListener( 'touchmove', function ( e ) {
|
||||
if ( touchmoveCountTimer ) {
|
||||
clearTimeout( touchmoveCountTimer );
|
||||
}
|
||||
|
||||
touchmoveCountTimer = setTimeout( function () {
|
||||
touchmoveCount++;
|
||||
}, 500 );
|
||||
}, supportsPassive ? { passive: true } : false );
|
||||
|
||||
document.addEventListener( 'touchstart', function ( e ) {
|
||||
lastTouchStart = ( new Date() ).getTime();
|
||||
}, supportsPassive ? { passive: true } : false );
|
||||
|
||||
document.addEventListener( 'touchend', function ( e ) {
|
||||
if ( ! lastTouchStart ) {
|
||||
// If the touchstart happened before this script was loaded, but the touchend happened after...
|
||||
return;
|
||||
}
|
||||
|
||||
var now = ( new Date() ).getTime();
|
||||
|
||||
var touchEvent = [];
|
||||
touchEvent.push( now - lastTouchStart );
|
||||
|
||||
if ( lastTouchEnd ) {
|
||||
touchEvent.push( lastTouchStart - lastTouchEnd );
|
||||
}
|
||||
|
||||
touchEvents.push( touchEvent );
|
||||
|
||||
lastTouchEnd = now;
|
||||
|
||||
// Don't record this time as an interval between keypresses.
|
||||
lastKeydown = null;
|
||||
lastKeyup = null;
|
||||
keydowns = {};
|
||||
}, supportsPassive ? { passive: true } : false );
|
||||
|
||||
document.addEventListener( 'scroll', function ( e ) {
|
||||
if ( scrollCountTimer ) {
|
||||
clearTimeout( scrollCountTimer );
|
||||
}
|
||||
|
||||
scrollCountTimer = setTimeout( function () {
|
||||
scrollCount++;
|
||||
}, 500 );
|
||||
}, supportsPassive ? { passive: true } : false );
|
||||
}
|
||||
|
||||
/**
|
||||
* For the timestamp data that is collected, don't send more than `limit` data points in the request.
|
||||
* Choose a random slice and send those.
|
||||
*/
|
||||
function prepare_timestamp_array_for_request( a, limit ) {
|
||||
if ( ! limit ) {
|
||||
limit = 100;
|
||||
}
|
||||
|
||||
var rv = '';
|
||||
|
||||
if ( a.length > 0 ) {
|
||||
var random_starting_point = Math.max( 0, Math.floor( Math.random() * a.length - limit ) );
|
||||
|
||||
for ( var i = 0; i < limit && i < a.length; i++ ) {
|
||||
rv += a[ random_starting_point + i ][0];
|
||||
|
||||
if ( a[ random_starting_point + i ].length >= 2 ) {
|
||||
rv += "," + a[ random_starting_point + i ][1];
|
||||
}
|
||||
|
||||
rv += ";";
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
if ( document.readyState !== 'loading' ) {
|
||||
init();
|
||||
} else {
|
||||
document.addEventListener( 'DOMContentLoaded', init );
|
||||
}
|
||||
})();
|
||||
462
wp-content/plugins/akismet/_inc/akismet.css
Normal file
@@ -0,0 +1,462 @@
|
||||
.wp-admin.jetpack_page_akismet-key-config, .wp-admin.settings_page_akismet-key-config {
|
||||
background-color:#f3f6f8;
|
||||
}
|
||||
|
||||
#submitted-on {
|
||||
position: relative;
|
||||
}
|
||||
#the-comment-list .author .akismet-user-comment-count {
|
||||
display: inline;
|
||||
}
|
||||
#the-comment-list .author a span {
|
||||
text-decoration: none;
|
||||
color: #999;
|
||||
}
|
||||
#the-comment-list .author a span.akismet-span-link {
|
||||
text-decoration: inherit;
|
||||
color: inherit;
|
||||
}
|
||||
#the-comment-list .akismet_remove_url {
|
||||
margin-left: 3px;
|
||||
color: #999;
|
||||
padding: 2px 3px 2px 0;
|
||||
}
|
||||
#the-comment-list .akismet_remove_url:hover {
|
||||
color: #A7301F;
|
||||
font-weight: bold;
|
||||
padding: 2px 2px 2px 0;
|
||||
}
|
||||
#dashboard_recent_comments .akismet-status {
|
||||
display: none;
|
||||
}
|
||||
.akismet-status {
|
||||
float: right;
|
||||
}
|
||||
.akismet-status a {
|
||||
color: #AAA;
|
||||
font-style: italic;
|
||||
}
|
||||
table.comments td.comment p a {
|
||||
text-decoration: underline;
|
||||
}
|
||||
table.comments td.comment p a:after {
|
||||
content: attr(href);
|
||||
color: #aaa;
|
||||
display: inline-block; /* Show the URL without the link's underline extending under it. */
|
||||
padding: 0 1ex; /* Because it's inline block, we can't just use spaces in the content: attribute to separate it from the link text. */
|
||||
}
|
||||
.mshot-arrow {
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-top: 10px solid transparent;
|
||||
border-bottom: 10px solid transparent;
|
||||
border-right: 10px solid #5C5C5C;
|
||||
position: absolute;
|
||||
left: -6px;
|
||||
top: 91px;
|
||||
}
|
||||
.mshot-container {
|
||||
background: #5C5C5C;
|
||||
position: absolute;
|
||||
top: -94px;
|
||||
padding: 7px;
|
||||
width: 450px;
|
||||
height: 338px;
|
||||
z-index: 20000;
|
||||
border-radius: 6px;
|
||||
}
|
||||
.akismet-mshot {
|
||||
position: absolute;
|
||||
z-index: 100;
|
||||
}
|
||||
.akismet-mshot .mshot-image {
|
||||
margin: 0;
|
||||
height: 338px;
|
||||
width: 450px;
|
||||
}
|
||||
.checkforspam {
|
||||
display: inline-block !important;
|
||||
}
|
||||
|
||||
.checkforspam-spinner {
|
||||
display: inline-block;
|
||||
margin-top: 7px;
|
||||
}
|
||||
|
||||
.akismet-right {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.akismet-card .akismet-right {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
.akismet-new-snapshot {
|
||||
margin-top: 1em;
|
||||
text-align: center;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.akismet-new-snapshot h3 {
|
||||
background: #f5f5f5;
|
||||
color: #888;
|
||||
font-size: 11px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.akismet-new-snapshot ul li {
|
||||
color: #999;
|
||||
font-size: 11px;
|
||||
text-transform: uppercase;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
|
||||
.akismet-settings th:first-child {
|
||||
vertical-align: top;
|
||||
padding-top: 15px;
|
||||
}
|
||||
|
||||
.akismet-settings th.akismet-api-key {
|
||||
vertical-align: middle;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.akismet-settings span.akismet-note {
|
||||
float: left;
|
||||
padding-left: 23px;
|
||||
font-size: 75%;
|
||||
margin-top: -10px;
|
||||
}
|
||||
|
||||
.jetpack_page_akismet-key-config #wpcontent, .settings_page_akismet-key-config #wpcontent {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.akismet-masthead {
|
||||
background-color:#fff;
|
||||
text-align:center;
|
||||
box-shadow:0 1px 0 rgba(200,215,225,0.5),0 1px 2px #e9eff3
|
||||
}
|
||||
|
||||
@media (max-width: 45rem) {
|
||||
.akismet-masthead {
|
||||
padding:0 1.25rem
|
||||
}
|
||||
}
|
||||
|
||||
.akismet-masthead__inside-container {
|
||||
padding:.375rem 0;
|
||||
margin:0 auto;
|
||||
width:100%;
|
||||
max-width:45rem;
|
||||
text-align: left;
|
||||
}
|
||||
.akismet-masthead__logo-container {
|
||||
padding:.3125rem 0 0
|
||||
}
|
||||
.akismet-masthead__logo-link {
|
||||
display:inline-block;
|
||||
outline:none;
|
||||
vertical-align:middle
|
||||
}
|
||||
.akismet-masthead__logo-link:focus {
|
||||
line-height:0;
|
||||
box-shadow:0 0 0 2px #78dcfa
|
||||
}
|
||||
.akismet-masthead__logo-link+code {
|
||||
margin:0 10px;
|
||||
padding:5px 9px;
|
||||
border-radius:2px;
|
||||
background:#e6ecf1;
|
||||
color:#647a88
|
||||
}
|
||||
.akismet-masthead__links {
|
||||
display:flex;
|
||||
flex-flow:row wrap;
|
||||
flex:2 50%;
|
||||
justify-content:flex-end;
|
||||
margin:0
|
||||
}
|
||||
@media (max-width: 480px) {
|
||||
.akismet-masthead__links {
|
||||
padding-right:.625rem
|
||||
}
|
||||
}
|
||||
.akismet-masthead__link-li {
|
||||
margin:0;
|
||||
padding:0
|
||||
}
|
||||
.akismet-masthead__link {
|
||||
font-style:normal;
|
||||
color:#0087be;
|
||||
padding:.625rem;
|
||||
display:inline-block
|
||||
}
|
||||
.akismet-masthead__link:visited {
|
||||
color:#0087be
|
||||
}
|
||||
.akismet-masthead__link:active,.akismet-masthead__link:hover {
|
||||
color:#00aadc
|
||||
}
|
||||
.akismet-masthead__link:hover {
|
||||
text-decoration:underline
|
||||
}
|
||||
.akismet-masthead__link .dashicons {
|
||||
display:none
|
||||
}
|
||||
@media (max-width: 480px) {
|
||||
.akismet-masthead__link:hover,.akismet-masthead__link:active {
|
||||
text-decoration:none
|
||||
}
|
||||
.akismet-masthead__link .dashicons {
|
||||
display:block;
|
||||
font-size:1.75rem
|
||||
}
|
||||
.akismet-masthead__link span+span {
|
||||
display:none
|
||||
}
|
||||
}
|
||||
.akismet-masthead__link-li:last-of-type .akismet-masthead__link {
|
||||
padding-right:0
|
||||
}
|
||||
|
||||
.akismet-lower {
|
||||
margin: 0 auto;
|
||||
text-align: left;
|
||||
max-width: 45rem;
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
.akismet-lower .notice {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.akismet-card {
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 0;
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
background: white;
|
||||
}
|
||||
|
||||
.akismet-card:after, .akismet-card .inside:after, .akismet-masthead__logo-container:after {
|
||||
content: ".";
|
||||
display: block;
|
||||
height: 0;
|
||||
clear: both;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.akismet-card .inside {
|
||||
padding: 1.5rem;
|
||||
padding-top: 1rem;
|
||||
}
|
||||
|
||||
.akismet-card .akismet-card-actions {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.jetpack_page_akismet-key-config .update-nag, .settings_page_akismet-key-config .update-nag {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.akismet-masthead .akismet-right {
|
||||
line-height: 2.125rem;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.akismet-box {
|
||||
box-sizing: border-box;
|
||||
background: white;
|
||||
border: 1px solid rgba(200, 215, 225, 0.5);
|
||||
}
|
||||
|
||||
.akismet-box h2, .akismet-box h3 {
|
||||
padding: 1.5rem 1.5rem .5rem 1.5rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.akismet-box p {
|
||||
padding: 0 1.5rem 1.5rem 1.5rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.akismet-box p:after {
|
||||
content: ".";
|
||||
display: block;
|
||||
height: 0;
|
||||
clear: both;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.akismet-box .akismet-right {
|
||||
padding-right: 1.5rem;
|
||||
}
|
||||
|
||||
.akismet-boxes .akismet-box {
|
||||
margin-bottom: 0;
|
||||
padding: 0;
|
||||
margin-top: -1px;
|
||||
}
|
||||
|
||||
.akismet-boxes .akismet-box:last-child {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.akismet-boxes .akismet-box:first-child {
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
|
||||
.akismet-box .centered {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.akismet-button, .akismet-button:hover, .akismet-button:visited {
|
||||
background: white;
|
||||
border-color: #c8d7e1;
|
||||
border-style: solid;
|
||||
border-width: 1px 1px 2px;
|
||||
color: #2e4453;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
outline: 0;
|
||||
overflow: hidden;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
text-overflow: ellipsis;
|
||||
text-decoration: none;
|
||||
vertical-align: top;
|
||||
box-sizing: border-box;
|
||||
line-height: 21px;
|
||||
border-radius: 4px;
|
||||
padding: 7px 14px 9px;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
.akismet-button:hover {
|
||||
border-color: #a8bece;
|
||||
}
|
||||
|
||||
.akismet-button:active {
|
||||
border-width: 2px 1px 1px;
|
||||
}
|
||||
|
||||
.akismet-is-primary, .akismet-is-primary:hover, .akismet-is-primary:visited {
|
||||
background: #00aadc;
|
||||
border-color: #0087be;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.akismet-is-primary:hover, .akismet-is-primary:focus {
|
||||
border-color: #005082;
|
||||
}
|
||||
|
||||
.akismet-is-primary:hover {
|
||||
border-color: #005082;
|
||||
}
|
||||
|
||||
.akismet-section-header {
|
||||
position: relative;
|
||||
margin: 0 auto 0.625rem auto;
|
||||
padding: 1rem;
|
||||
box-sizing: border-box;
|
||||
box-shadow: 0 0 0 1px rgba(200, 215, 225, 0.5), 0 1px 2px #e9eff3;
|
||||
background: #ffffff;
|
||||
width: 100%;
|
||||
padding-top: 0.6875rem;
|
||||
padding-bottom: 0.6875rem;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.akismet-section-header__label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-grow: 1;
|
||||
line-height: 1.75rem;
|
||||
position: relative;
|
||||
font-size: 0.875rem;
|
||||
color: #4f748e;
|
||||
}
|
||||
|
||||
.akismet-section-header__actions {
|
||||
line-height: 1.75rem;
|
||||
}
|
||||
|
||||
.akismet-setup-instructions form {
|
||||
padding-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.akismet-setup-instructions > a.akismet-button {
|
||||
display: inline-block;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
div.error.akismet-usage-limit-alert {
|
||||
padding: 25px 45px 25px 15px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#akismet-plugin-container .akismet-usage-limit-alert {
|
||||
margin: 0 auto 0.625rem auto;
|
||||
box-sizing: border-box;
|
||||
box-shadow: 0 0 0 1px rgba(200, 215, 225, 0.5), 0 1px 2px #e9eff3;
|
||||
border: none;
|
||||
border-left: 4px solid #d63638;
|
||||
}
|
||||
|
||||
.akismet-usage-limit-alert .akismet-usage-limit-logo {
|
||||
width: 38px;
|
||||
min-width: 38px;
|
||||
height: 38px;
|
||||
border-radius: 20px;
|
||||
margin-right: 18px;
|
||||
background: black;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.akismet-usage-limit-alert .akismet-usage-limit-logo img {
|
||||
position: absolute;
|
||||
width: 22px;
|
||||
left: 8px;
|
||||
top: 10px;
|
||||
}
|
||||
|
||||
.akismet-usage-limit-alert .akismet-usage-limit-text {
|
||||
flex-grow: 1;
|
||||
margin-right: 18px;
|
||||
}
|
||||
|
||||
.akismet-usage-limit-alert h3 {
|
||||
line-height: 1.3;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.akismet-usage-limit-alert .akismet-usage-limit-cta {
|
||||
border-color: none;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
#akismet-plugin-container .akismet-usage-limit-cta a {
|
||||
color: #d63638;
|
||||
background: #fafafa;
|
||||
}
|
||||
|
||||
@media (max-width: 550px) {
|
||||
div.error.akismet-usage-limit-alert {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.akismet-usage-limit-alert .akismet-usage-limit-logo,
|
||||
.akismet-usage-limit-alert .akismet-usage-limit-text {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.akismet-usage-limit-alert .akismet-usage-limit-cta {
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
397
wp-content/plugins/akismet/_inc/akismet.js
Normal file
@@ -0,0 +1,397 @@
|
||||
jQuery( function ( $ ) {
|
||||
var mshotRemovalTimer = null;
|
||||
var mshotRetryTimer = null;
|
||||
var mshotTries = 0;
|
||||
var mshotRetryInterval = 1000;
|
||||
var mshotEnabledLinkSelector = 'a[id^="author_comment_url"], tr.pingback td.column-author a:first-of-type, td.comment p a';
|
||||
|
||||
var preloadedMshotURLs = [];
|
||||
|
||||
$('.akismet-status').each(function () {
|
||||
var thisId = $(this).attr('commentid');
|
||||
$(this).prependTo('#comment-' + thisId + ' .column-comment');
|
||||
});
|
||||
$('.akismet-user-comment-count').each(function () {
|
||||
var thisId = $(this).attr('commentid');
|
||||
$(this).insertAfter('#comment-' + thisId + ' .author strong:first').show();
|
||||
});
|
||||
|
||||
akismet_enable_comment_author_url_removal();
|
||||
|
||||
$( '#the-comment-list' ).on( 'click', '.akismet_remove_url', function () {
|
||||
var thisId = $(this).attr('commentid');
|
||||
var data = {
|
||||
action: 'comment_author_deurl',
|
||||
_wpnonce: WPAkismet.comment_author_url_nonce,
|
||||
id: thisId
|
||||
};
|
||||
$.ajax({
|
||||
url: ajaxurl,
|
||||
type: 'POST',
|
||||
data: data,
|
||||
beforeSend: function () {
|
||||
// Removes "x" link
|
||||
$("a[commentid='"+ thisId +"']").hide();
|
||||
// Show temp status
|
||||
$("#author_comment_url_"+ thisId).html( $( '<span/>' ).text( WPAkismet.strings['Removing...'] ) );
|
||||
},
|
||||
success: function (response) {
|
||||
if (response) {
|
||||
// Show status/undo link
|
||||
$("#author_comment_url_"+ thisId)
|
||||
.attr('cid', thisId)
|
||||
.addClass('akismet_undo_link_removal')
|
||||
.html(
|
||||
$( '<span/>' ).text( WPAkismet.strings['URL removed'] )
|
||||
)
|
||||
.append( ' ' )
|
||||
.append(
|
||||
$( '<span/>' )
|
||||
.text( WPAkismet.strings['(undo)'] )
|
||||
.addClass( 'akismet-span-link' )
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
}).on( 'click', '.akismet_undo_link_removal', function () {
|
||||
var thisId = $(this).attr('cid');
|
||||
var thisUrl = $(this).attr('href');
|
||||
var data = {
|
||||
action: 'comment_author_reurl',
|
||||
_wpnonce: WPAkismet.comment_author_url_nonce,
|
||||
id: thisId,
|
||||
url: thisUrl
|
||||
};
|
||||
$.ajax({
|
||||
url: ajaxurl,
|
||||
type: 'POST',
|
||||
data: data,
|
||||
beforeSend: function () {
|
||||
// Show temp status
|
||||
$("#author_comment_url_"+ thisId).html( $( '<span/>' ).text( WPAkismet.strings['Re-adding...'] ) );
|
||||
},
|
||||
success: function (response) {
|
||||
if (response) {
|
||||
// Add "x" link
|
||||
$("a[commentid='"+ thisId +"']").show();
|
||||
// Show link. Core strips leading http://, so let's do that too.
|
||||
$("#author_comment_url_"+ thisId).removeClass('akismet_undo_link_removal').text( thisUrl.replace( /^http:\/\/(www\.)?/ig, '' ) );
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
// Show a preview image of the hovered URL. Applies to author URLs and URLs inside the comments.
|
||||
if ( "enable_mshots" in WPAkismet && WPAkismet.enable_mshots ) {
|
||||
$( '#the-comment-list' ).on( 'mouseover', mshotEnabledLinkSelector, function () {
|
||||
clearTimeout( mshotRemovalTimer );
|
||||
|
||||
if ( $( '.akismet-mshot' ).length > 0 ) {
|
||||
if ( $( '.akismet-mshot:first' ).data( 'link' ) == this ) {
|
||||
// The preview is already showing for this link.
|
||||
return;
|
||||
}
|
||||
else {
|
||||
// A new link is being hovered, so remove the old preview.
|
||||
$( '.akismet-mshot' ).remove();
|
||||
}
|
||||
}
|
||||
|
||||
clearTimeout( mshotRetryTimer );
|
||||
|
||||
var linkUrl = $( this ).attr( 'href' );
|
||||
|
||||
if ( preloadedMshotURLs.indexOf( linkUrl ) !== -1 ) {
|
||||
// This preview image was already preloaded, so begin with a retry URL so the user doesn't see the placeholder image for the first second.
|
||||
mshotTries = 2;
|
||||
}
|
||||
else {
|
||||
mshotTries = 1;
|
||||
}
|
||||
|
||||
var mShot = $( '<div class="akismet-mshot mshot-container"><div class="mshot-arrow"></div><img src="' + akismet_mshot_url( linkUrl, mshotTries ) + '" width="450" height="338" class="mshot-image" /></div>' );
|
||||
mShot.data( 'link', this );
|
||||
mShot.data( 'url', linkUrl );
|
||||
|
||||
mShot.find( 'img' ).on( 'load', function () {
|
||||
$( '.akismet-mshot' ).data( 'pending-request', false );
|
||||
} );
|
||||
|
||||
var offset = $( this ).offset();
|
||||
|
||||
mShot.offset( {
|
||||
left : Math.min( $( window ).width() - 475, offset.left + $( this ).width() + 10 ), // Keep it on the screen if the link is near the edge of the window.
|
||||
top: offset.top + ( $( this ).height() / 2 ) - 101 // 101 = top offset of the arrow plus the top border thickness
|
||||
} );
|
||||
|
||||
$( 'body' ).append( mShot );
|
||||
|
||||
mshotRetryTimer = setTimeout( retryMshotUntilLoaded, mshotRetryInterval );
|
||||
} ).on( 'mouseout', 'a[id^="author_comment_url"], tr.pingback td.column-author a:first-of-type, td.comment p a', function () {
|
||||
mshotRemovalTimer = setTimeout( function () {
|
||||
clearTimeout( mshotRetryTimer );
|
||||
|
||||
$( '.akismet-mshot' ).remove();
|
||||
}, 200 );
|
||||
} );
|
||||
|
||||
var preloadDelayTimer = null;
|
||||
|
||||
$( window ).on( 'scroll resize', function () {
|
||||
clearTimeout( preloadDelayTimer );
|
||||
|
||||
preloadDelayTimer = setTimeout( preloadMshotsInViewport, 500 );
|
||||
} );
|
||||
|
||||
preloadMshotsInViewport();
|
||||
}
|
||||
|
||||
/**
|
||||
* The way mShots works is if there was no screenshot already recently generated for the URL,
|
||||
* it returns a "loading..." image for the first request. Then, some subsequent request will
|
||||
* receive the actual screenshot, but it's unknown how long it will take. So, what we do here
|
||||
* is continually re-request the mShot, waiting a second after every response until we get the
|
||||
* actual screenshot.
|
||||
*/
|
||||
function retryMshotUntilLoaded() {
|
||||
clearTimeout( mshotRetryTimer );
|
||||
|
||||
var imageWidth = $( '.akismet-mshot img' ).get(0).naturalWidth;
|
||||
|
||||
if ( imageWidth == 0 ) {
|
||||
// It hasn't finished loading yet the first time. Check again shortly.
|
||||
setTimeout( retryMshotUntilLoaded, mshotRetryInterval );
|
||||
}
|
||||
else if ( imageWidth == 400 ) {
|
||||
// It loaded the preview image.
|
||||
|
||||
if ( mshotTries == 20 ) {
|
||||
// Give up if we've requested the mShot 20 times already.
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! $( '.akismet-mshot' ).data( 'pending-request' ) ) {
|
||||
$( '.akismet-mshot' ).data( 'pending-request', true );
|
||||
|
||||
mshotTries++;
|
||||
|
||||
$( '.akismet-mshot .mshot-image' ).attr( 'src', akismet_mshot_url( $( '.akismet-mshot' ).data( 'url' ), mshotTries ) );
|
||||
}
|
||||
|
||||
mshotRetryTimer = setTimeout( retryMshotUntilLoaded, mshotRetryInterval );
|
||||
}
|
||||
else {
|
||||
// All done.
|
||||
}
|
||||
}
|
||||
|
||||
function preloadMshotsInViewport() {
|
||||
var windowWidth = $( window ).width();
|
||||
var windowHeight = $( window ).height();
|
||||
|
||||
$( '#the-comment-list' ).find( mshotEnabledLinkSelector ).each( function ( index, element ) {
|
||||
var linkUrl = $( this ).attr( 'href' );
|
||||
|
||||
// Don't attempt to preload an mshot for a single link twice.
|
||||
if ( preloadedMshotURLs.indexOf( linkUrl ) !== -1 ) {
|
||||
// The URL is already preloaded.
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( typeof element.getBoundingClientRect !== 'function' ) {
|
||||
// The browser is too old. Return false to stop this preloading entirely.
|
||||
return false;
|
||||
}
|
||||
|
||||
var rect = element.getBoundingClientRect();
|
||||
|
||||
if ( rect.top >= 0 && rect.left >= 0 && rect.bottom <= windowHeight && rect.right <= windowWidth ) {
|
||||
akismet_preload_mshot( linkUrl );
|
||||
$( this ).data( 'akismet-mshot-preloaded', true );
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
$( '.checkforspam.enable-on-load' ).on( 'click', function( e ) {
|
||||
if ( $( this ).hasClass( 'ajax-disabled' ) ) {
|
||||
// Akismet hasn't been configured yet. Allow the user to proceed to the button's link.
|
||||
return;
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
if ( $( this ).hasClass( 'button-disabled' ) ) {
|
||||
window.location.href = $( this ).data( 'success-url' ).replace( '__recheck_count__', 0 ).replace( '__spam_count__', 0 );
|
||||
return;
|
||||
}
|
||||
|
||||
$('.checkforspam').addClass('button-disabled').addClass( 'checking' );
|
||||
$('.checkforspam-spinner').addClass( 'spinner' ).addClass( 'is-active' );
|
||||
|
||||
akismet_check_for_spam(0, 100);
|
||||
}).removeClass( 'button-disabled' );
|
||||
|
||||
var spam_count = 0;
|
||||
var recheck_count = 0;
|
||||
|
||||
function akismet_check_for_spam(offset, limit) {
|
||||
var check_for_spam_buttons = $( '.checkforspam' );
|
||||
|
||||
var nonce = check_for_spam_buttons.data( 'nonce' );
|
||||
|
||||
// We show the percentage complete down to one decimal point so even queues with 100k
|
||||
// pending comments will show some progress pretty quickly.
|
||||
var percentage_complete = Math.round( ( recheck_count / check_for_spam_buttons.data( 'pending-comment-count' ) ) * 1000 ) / 10;
|
||||
|
||||
// Update the progress counter on the "Check for Spam" button.
|
||||
$( '.checkforspam' ).text( check_for_spam_buttons.data( 'progress-label' ).replace( '%1$s', percentage_complete ) );
|
||||
|
||||
$.post(
|
||||
ajaxurl,
|
||||
{
|
||||
'action': 'akismet_recheck_queue',
|
||||
'offset': offset,
|
||||
'limit': limit,
|
||||
'nonce': nonce
|
||||
},
|
||||
function(result) {
|
||||
if ( 'error' in result ) {
|
||||
// An error is only returned in the case of a missing nonce, so we don't need the actual error message.
|
||||
window.location.href = check_for_spam_buttons.data( 'failure-url' );
|
||||
return;
|
||||
}
|
||||
|
||||
recheck_count += result.counts.processed;
|
||||
spam_count += result.counts.spam;
|
||||
|
||||
if (result.counts.processed < limit) {
|
||||
window.location.href = check_for_spam_buttons.data( 'success-url' ).replace( '__recheck_count__', recheck_count ).replace( '__spam_count__', spam_count );
|
||||
}
|
||||
else {
|
||||
// Account for comments that were caught as spam and moved out of the queue.
|
||||
akismet_check_for_spam(offset + limit - result.counts.spam, limit);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if ( "start_recheck" in WPAkismet && WPAkismet.start_recheck ) {
|
||||
$( '.checkforspam:first' ).click();
|
||||
}
|
||||
|
||||
if ( typeof MutationObserver !== 'undefined' ) {
|
||||
// Dynamically add the "X" next the the author URL links when a comment is quick-edited.
|
||||
var comment_list_container = document.getElementById( 'the-comment-list' );
|
||||
|
||||
if ( comment_list_container ) {
|
||||
var observer = new MutationObserver( function ( mutations ) {
|
||||
for ( var i = 0, _len = mutations.length; i < _len; i++ ) {
|
||||
if ( mutations[i].addedNodes.length > 0 ) {
|
||||
akismet_enable_comment_author_url_removal();
|
||||
|
||||
// Once we know that we'll have to check for new author links, skip the rest of the mutations.
|
||||
break;
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
observer.observe( comment_list_container, { attributes: true, childList: true, characterData: true } );
|
||||
}
|
||||
}
|
||||
|
||||
function akismet_enable_comment_author_url_removal() {
|
||||
$( '#the-comment-list' )
|
||||
.find( 'tr.comment, tr[id ^= "comment-"]' )
|
||||
.find( '.column-author a[href^="http"]:first' ) // Ignore mailto: links, which would be the comment author's email.
|
||||
.each(function () {
|
||||
if ( $( this ).parent().find( '.akismet_remove_url' ).length > 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
var linkHref = $(this).attr( 'href' );
|
||||
|
||||
// Ignore any links to the current domain, which are diagnostic tools, like the IP address link
|
||||
// or any other links another plugin might add.
|
||||
var currentHostParts = document.location.href.split( '/' );
|
||||
var currentHost = currentHostParts[0] + '//' + currentHostParts[2] + '/';
|
||||
|
||||
if ( linkHref.indexOf( currentHost ) != 0 ) {
|
||||
var thisCommentId = $(this).parents('tr:first').attr('id').split("-");
|
||||
|
||||
$(this)
|
||||
.attr("id", "author_comment_url_"+ thisCommentId[1])
|
||||
.after(
|
||||
$( '<a href="#" class="akismet_remove_url">x</a>' )
|
||||
.attr( 'commentid', thisCommentId[1] )
|
||||
.attr( 'title', WPAkismet.strings['Remove this URL'] )
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an mShot URL if given a link URL.
|
||||
*
|
||||
* @param string linkUrl
|
||||
* @param int retry If retrying a request, the number of the retry.
|
||||
* @return string The mShot URL;
|
||||
*/
|
||||
function akismet_mshot_url( linkUrl, retry ) {
|
||||
var mshotUrl = '//s0.wp.com/mshots/v1/' + encodeURIComponent( linkUrl ) + '?w=900';
|
||||
|
||||
if ( retry > 1 ) {
|
||||
mshotUrl += '&r=' + encodeURIComponent( retry );
|
||||
}
|
||||
|
||||
mshotUrl += '&source=akismet';
|
||||
|
||||
return mshotUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Begin loading an mShot preview of a link.
|
||||
*
|
||||
* @param string linkUrl
|
||||
*/
|
||||
function akismet_preload_mshot( linkUrl ) {
|
||||
var img = new Image();
|
||||
img.src = akismet_mshot_url( linkUrl );
|
||||
|
||||
preloadedMshotURLs.push( linkUrl );
|
||||
}
|
||||
|
||||
$( '.akismet-could-be-primary' ).each( function () {
|
||||
var form = $( this ).closest( 'form' );
|
||||
|
||||
form.data( 'initial-state', form.serialize() );
|
||||
|
||||
form.on( 'change keyup', function () {
|
||||
var self = $( this );
|
||||
var submit_button = self.find( '.akismet-could-be-primary' );
|
||||
|
||||
if ( self.serialize() != self.data( 'initial-state' ) ) {
|
||||
submit_button.addClass( 'akismet-is-primary' );
|
||||
}
|
||||
else {
|
||||
submit_button.removeClass( 'akismet-is-primary' );
|
||||
}
|
||||
} );
|
||||
} );
|
||||
|
||||
/**
|
||||
* Shows the Enter API key form
|
||||
*/
|
||||
$( '.akismet-enter-api-key-box__reveal' ).on( 'click', function ( e ) {
|
||||
e.preventDefault();
|
||||
|
||||
var div = $( '.akismet-enter-api-key-box__form-wrapper' );
|
||||
div.show( 500 );
|
||||
div.find( 'input[name=key]' ).focus();
|
||||
|
||||
$( this ).hide();
|
||||
} );
|
||||
});
|
||||
67
wp-content/plugins/akismet/_inc/fonts/inter.css
Normal file
@@ -0,0 +1,67 @@
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url("https://s0.wp.com/i/fonts/inter/Inter-Regular.woff2?v=3.19") format("woff2"),
|
||||
url("https://s0.wp.com/i/fonts/inter/Inter-Regular.woff?v=3.19") format("woff");
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url("https://s0.wp.com/i/fonts/inter/Inter-Italic.woff2?v=3.19") format("woff2"),
|
||||
url("https://s0.wp.com/i/fonts/inter/Inter-Italic.woff?v=3.19") format("woff");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url("https://s0.wp.com/i/fonts/inter/Inter-Medium.woff2?v=3.19") format("woff2"),
|
||||
url("https://s0.wp.com/i/fonts/inter/Inter-Medium.woff?v=3.19") format("woff");
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: italic;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url("https://s0.wp.com/i/fonts/inter/Inter-MediumItalic.woff2?v=3.19") format("woff2"),
|
||||
url("https://s0.wp.com/i/fonts/inter/Inter-MediumItalic.woff?v=3.19") format("woff");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url("https://s0.wp.com/i/fonts/inter/Inter-SemiBold.woff2?v=3.19") format("woff2"),
|
||||
url("https://s0.wp.com/i/fonts/inter/Inter-SemiBold.woff?v=3.19") format("woff");
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: italic;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url("https://s0.wp.com/i/fonts/inter/Inter-SemiBoldItalic.woff2?v=3.19") format("woff2"),
|
||||
url("https://s0.wp.com/i/fonts/inter/Inter-SemiBoldItalic.woff?v=3.19") format("woff");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url("https://s0.wp.com/i/fonts/inter/Inter-Bold.woff2?v=3.19") format("woff2"),
|
||||
url("https://s0.wp.com/i/fonts/inter/Inter-Bold.woff?v=3.19") format("woff");
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url("https://s0.wp.com/i/fonts/inter/Inter-BoldItalic.woff2?v=3.19") format("woff2"),
|
||||
url("https://s0.wp.com/i/fonts/inter/Inter-BoldItalic.woff?v=3.19") format("woff");
|
||||
}
|
||||
|
After Width: | Height: | Size: 5.6 KiB |
|
After Width: | Height: | Size: 8.4 KiB |
BIN
wp-content/plugins/akismet/_inc/img/akismet-refresh-logo@2x.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
1
wp-content/plugins/akismet/_inc/img/arrow-left.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" focusable="false"><path d="M20 11.2H6.8l3.7-3.7-1-1L3.9 12l5.6 5.5 1-1-3.7-3.7H20z"></path></svg>
|
||||
|
After Width: | Height: | Size: 199 B |
BIN
wp-content/plugins/akismet/_inc/img/logo-a-2x.png
Normal file
|
After Width: | Height: | Size: 904 B |
718
wp-content/plugins/akismet/_inc/rtl/akismet-admin-rtl.css
Normal file
@@ -0,0 +1,718 @@
|
||||
/* This file was automatically generated on Oct 23 2025 00:26:05 */
|
||||
|
||||
body {
|
||||
--akismet-color-charcoal: #272635;
|
||||
--akismet-color-light-grey: #f6f7f7;
|
||||
--akismet-color-mid-grey: #a7aaad;
|
||||
--akismet-color-dark-grey: #646970;
|
||||
--akismet-color-grey-80: #2c3338;
|
||||
--akismet-color-grey-100: #101517;
|
||||
--akismet-color-grey-border: #dcdcde;
|
||||
--akismet-color-white: #fff;
|
||||
--akismet-color-dark-green: #2d6a40;
|
||||
--akismet-color-mid-green: #357b49;
|
||||
--akismet-color-light-green: #4eb26a;
|
||||
--akismet-color-mid-red: #e82c3f;
|
||||
--akismet-color-light-blue: #256eff;
|
||||
--akismet-color-notice-light-green: #dbf0e1;
|
||||
--akismet-color-notice-dark-green: #69bf82;
|
||||
--akismet-color-notice-light-red: #ffdbde;
|
||||
--akismet-color-notice-dark-red: #ff6676;
|
||||
--akismet-color-notice-yellow: #e5c133;
|
||||
}
|
||||
|
||||
/* UI components */
|
||||
.akismet-new-feature {
|
||||
background-color: var(--akismet-color-mid-green);
|
||||
border-radius: 4px;
|
||||
color: var(--akismet-color-white);
|
||||
font-size: 10px;
|
||||
padding: 4px 6px;
|
||||
text-transform: uppercase;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
#akismet-plugin-container {
|
||||
background-color: var(--akismet-color-light-grey);
|
||||
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen-Sans', 'Ubuntu', 'Cantarell', 'Helvetica Neue', sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
#akismet-plugin-container a {
|
||||
color: var(--akismet-color-mid-green);
|
||||
}
|
||||
|
||||
#akismet-plugin-container a.akismet-button {
|
||||
background-color: var(--akismet-color-mid-green);
|
||||
color: var(--akismet-color-white);
|
||||
}
|
||||
|
||||
#akismet-plugin-container button:focus-visible,
|
||||
#akismet-plugin-container input:focus-visible,
|
||||
#akismet-plugin-container a:focus-visible {
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
outline: 2px solid var(--akismet-color-light-blue);
|
||||
}
|
||||
|
||||
.akismet-masthead {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.akismet-masthead__logo {
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.akismet-section-header {
|
||||
box-shadow: none;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.akismet-section-header__label {
|
||||
color: var(--akismet-color-charcoal);
|
||||
font-weight: 600;
|
||||
padding-right: 0.2em;
|
||||
}
|
||||
|
||||
.akismet-button,
|
||||
.akismet-button:hover {
|
||||
border: 0;
|
||||
color: var(--akismet-color-white);
|
||||
}
|
||||
|
||||
.akismet-button {
|
||||
background-color: var(--akismet-color-mid-green);
|
||||
}
|
||||
|
||||
.akismet-button:hover {
|
||||
background-color: var(--akismet-color-dark-green);
|
||||
}
|
||||
|
||||
.akismet-external-link::after {
|
||||
content: "↗";
|
||||
display: inline-block;
|
||||
padding-right: 2px;
|
||||
text-decoration: none;
|
||||
vertical-align: text-top;
|
||||
}
|
||||
|
||||
/* Need this specificity to override the existing header rule */
|
||||
.akismet-new-snapshot h3.akismet-new-snapshot__header {
|
||||
background: none;
|
||||
font-size: 13px;
|
||||
color: var(--akismet-color-charcoal);
|
||||
text-align: right;
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
.akismet-new-snapshot__number {
|
||||
color: var(--akismet-color-charcoal);
|
||||
display: block;
|
||||
font-size: 32px;
|
||||
font-weight: 400;
|
||||
letter-spacing: -1px;
|
||||
line-height: 1.5em;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.akismet-new-snapshot li.akismet-new-snapshot__item {
|
||||
color: var(--akismet-color-dark-grey);
|
||||
font-size: 13px;
|
||||
text-align: right;
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
.akismet-masthead__logo-link {
|
||||
min-height: 50px;
|
||||
}
|
||||
|
||||
.akismet-masthead__back-link-container {
|
||||
margin-top: 16px;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
/* Need this specificity to override the existing link rule */
|
||||
#akismet-plugin-container a.akismet-masthead__back-link {
|
||||
background-image: url(../img/arrow-left.svg);
|
||||
background-position: right;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 16px;
|
||||
color: var(--akismet-color-charcoal);
|
||||
font-weight: 400;
|
||||
padding-right: 20px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#akismet-plugin-container a.akismet-masthead__back-link:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.akismet-new-snapshot__item {
|
||||
border-top: 1px solid var(--akismet-color-light-grey);
|
||||
border-right: 1px solid var(--akismet-color-light-grey);
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
.akismet-new-snapshot li:first-child {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.akismet-new-snapshot__list {
|
||||
display: flex;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.akismet-new-snapshot__item {
|
||||
flex: 1 0 33.33%;
|
||||
margin-bottom: 0;
|
||||
padding-right: 1.5em;
|
||||
padding-left: 1.5em;
|
||||
}
|
||||
|
||||
.akismet-new-snapshot__chart {
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
.akismet-box {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.akismet-box:not(:first-child) {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.akismet-box,
|
||||
.akismet-card {
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.06), 0 0 2px rgba(0, 0, 0, 0.16);
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.akismet-card {
|
||||
margin: 32px auto 0 auto;
|
||||
}
|
||||
|
||||
.akismet-lower {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.akismet-lower .inside {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.akismet-section-header__label {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.akismet-settings__row {
|
||||
border-bottom: 1px solid var(--akismet-color-light-grey);
|
||||
display: block;
|
||||
padding: 1em 1.5em;
|
||||
}
|
||||
|
||||
.akismet-settings__row-input {
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.akismet-settings__row-title {
|
||||
font-weight: 500;
|
||||
font-size: 1em;
|
||||
margin: 0;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.akismet-settings__row-description {
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
|
||||
.akismet-card-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
.akismet-card-actions__secondary-action {
|
||||
align-self: center;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.akismet-settings__row label {
|
||||
padding-bottom: 1em;
|
||||
}
|
||||
|
||||
.akismet-settings__row-note {
|
||||
font-size: 0.9em;
|
||||
margin-top: 0.4em;
|
||||
}
|
||||
|
||||
.akismet-settings__row input[type="checkbox"],
|
||||
.akismet-settings__row input[type="radio"] {
|
||||
accent-color: var(--akismet-color-mid-green);
|
||||
box-shadow: none;
|
||||
flex-shrink: 0;
|
||||
margin: 2px 0 0 0;
|
||||
}
|
||||
|
||||
.akismet-settings__row input[type="checkbox"] {
|
||||
margin-top: 1px;
|
||||
vertical-align: top;
|
||||
-webkit-appearance: checkbox;
|
||||
}
|
||||
|
||||
.akismet-settings__row input[type="radio"] {
|
||||
-webkit-appearance: radio;
|
||||
}
|
||||
|
||||
/* Fix up misbehaving wp-admin styles in Chrome (from forms and colors stylesheets) */
|
||||
.akismet-settings__row input[type="checkbox"]:checked:before {
|
||||
content: '';
|
||||
}
|
||||
|
||||
.akismet-settings__row input[type="radio"]:checked:before {
|
||||
background: none;
|
||||
}
|
||||
|
||||
.akismet-settings__row input[type="checkbox"]:checked:hover,
|
||||
.akismet-settings__row input[type="radio"]:checked:hover {
|
||||
accent-color: var(--akismet-color-mid-green);
|
||||
}
|
||||
|
||||
.akismet-button:disabled {
|
||||
background-color: var(--akismet-color-mid-grey);
|
||||
color: var(--akismet-color-white);
|
||||
cursor: arrow;
|
||||
}
|
||||
|
||||
.akismet-awaiting-stats,
|
||||
.akismet-account {
|
||||
padding: 0 1rem 1rem 1rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.akismet-account {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.akismet-account th {
|
||||
font-weight: 500;
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
.akismet-account th, .akismet-account td {
|
||||
padding-bottom: 1em;
|
||||
}
|
||||
|
||||
.akismet-settings__row-input-label {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.akismet-settings__row-label-text {
|
||||
padding-right: 0.5em;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.akismet-alert {
|
||||
border-right: 8px solid;
|
||||
border-radius: 8px;
|
||||
margin: 20px 0;
|
||||
padding: 0.2em 1em;
|
||||
}
|
||||
|
||||
.akismet-alert__heading {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
.akismet-alert.is-good {
|
||||
background-color: var(--akismet-color-notice-light-green);
|
||||
border-right-color: var(--akismet-color-notice-dark-green);
|
||||
}
|
||||
|
||||
.akismet-alert.is-neutral {
|
||||
background-color: var(--akismet-color-white);
|
||||
border-right-color: var(--akismet-color-dark-grey);
|
||||
}
|
||||
|
||||
.akismet-alert.is-bad {
|
||||
background-color: var(--akismet-color-notice-light-red);
|
||||
border-right-color: var(--akismet-color-notice-dark-red);
|
||||
}
|
||||
|
||||
.akismet-alert.is-commercial {
|
||||
background-color: var(--akismet-color-white);
|
||||
border-color: var(--akismet-color-mid-grey);
|
||||
border-bottom-width: 1px;
|
||||
border-right-color: var(--akismet-color-notice-yellow);
|
||||
display: flex;
|
||||
padding-bottom: 1em;
|
||||
}
|
||||
|
||||
#akismet-plugin-container .akismet-alert.is-good a,
|
||||
#akismet-plugin-container .akismet-alert.is-bad a {
|
||||
/* For better contrast - green isn't great */
|
||||
color: var(--akismet-color-grey-80);
|
||||
}
|
||||
|
||||
.akismet-alert-header {
|
||||
font-size: 16px;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
.akismet-alert-button-wrapper {
|
||||
align-self: center;
|
||||
margin-right: 2em;
|
||||
min-width: 120px;
|
||||
}
|
||||
|
||||
.akismet-alert-info {
|
||||
text-wrap: pretty;
|
||||
margin: 0.5em 0;
|
||||
}
|
||||
|
||||
/* Setup */
|
||||
.akismet-setup-instructions__heading {
|
||||
font-size: 1.375rem;
|
||||
font-weight: 700;
|
||||
padding-block-end: 0;
|
||||
}
|
||||
|
||||
h3.akismet-setup-instructions__subheading {
|
||||
color: var(--akismet-color-dark-grey);
|
||||
font-size: 1rem;
|
||||
font-weight: 400;
|
||||
line-height: 1.5;
|
||||
margin: 0 0 1.25rem;
|
||||
padding-block-start: 1rem;
|
||||
}
|
||||
|
||||
.akismet-setup-instructions__feature-list {
|
||||
list-style: none;
|
||||
margin: 1rem 0.5rem 1.5rem;
|
||||
max-width: 640px;
|
||||
padding: 0 1rem;
|
||||
}
|
||||
|
||||
.akismet-setup-instructions__feature {
|
||||
align-items: start;
|
||||
display: flex;
|
||||
margin-block-end: 1rem;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.akismet-setup-instructions__icon {
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
}
|
||||
|
||||
.akismet-setup-instructions__body {
|
||||
flex: 1;
|
||||
padding-inline-start: 0.5rem;
|
||||
}
|
||||
|
||||
.akismet-setup-instructions__title {
|
||||
color: #1d2327;
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
line-height: 1.3;
|
||||
margin: 0;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
p.akismet-setup-instructions__text {
|
||||
color: var(--akismet-color-grey-80);
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.5;
|
||||
margin: 0.25rem 0 0;
|
||||
padding: 0;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.akismet-setup-instructions__button,
|
||||
.akismet-setup-instructions__button:hover,
|
||||
.akismet-setup-instructions__button:visited {
|
||||
font-size: 1rem;
|
||||
margin-inline-start: 1.5rem;
|
||||
}
|
||||
|
||||
.akismet-setup__connection {
|
||||
background: var(--akismet-color-light-grey);
|
||||
border: 1px solid var(--akismet-color-grey-border);
|
||||
border-radius: 8px;
|
||||
margin: 1rem 1rem 2rem 1rem;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.akismet-setup__connection-action:not(:last-child) {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.akismet-setup__connection-user {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.akismet-setup__connection-avatar {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.akismet-setup__connection-avatar-image {
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.akismet-setup__connection-account-name {
|
||||
color: var(--akismet-color-charcoal);
|
||||
font-size: 0.9rem;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.akismet-setup__connection-account-email {
|
||||
margin-top: 0.1rem;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.akismet-setup__connection-action {
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.akismet-setup__connection-button {
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
p.akismet-setup__connection-action-intro,
|
||||
p.akismet-setup__connection-action-description {
|
||||
color: var(--akismet-color-dark-grey);
|
||||
font-size: 0.875rem;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
p.akismet-setup__connection-action-intro {
|
||||
margin: 0 0 1rem 0;
|
||||
}
|
||||
|
||||
p.akismet-setup__connection-action-description {
|
||||
margin: 1rem 0 0;
|
||||
}
|
||||
|
||||
/* Setup - API key input */
|
||||
.akismet-enter-api-key-box {
|
||||
margin: 1.5rem 0;
|
||||
}
|
||||
|
||||
.akismet-enter-api-key-box__reveal {
|
||||
background: none;
|
||||
border: 0;
|
||||
color: var(--akismet-color-mid-green);
|
||||
cursor: pointer;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.akismet-enter-api-key-box__form-wrapper {
|
||||
display: none;
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
|
||||
.akismet-enter-api-key-box__input-wrapper {
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
padding: 0 1.5rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.akismet-enter-api-key-box__key-input {
|
||||
flex-grow: 1;
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
h3.akismet-enter-api-key-box__header {
|
||||
padding-top: 0;
|
||||
padding-bottom: 1em;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* Notices > Activation (shown on edit-comments.php) */
|
||||
#akismet-setup-prompt {
|
||||
background: none;
|
||||
border: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.akismet-activate {
|
||||
align-items: center;
|
||||
/* background-image is defined via an inline style in class.akismet-admin.php */
|
||||
background-color: var(--akismet-color-light-grey);
|
||||
background-position: calc(100% - (100% - 1em)) center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 140px;
|
||||
border: 1px solid var(--akismet-color-mid-green);
|
||||
border-right-width: 4px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin: 15px 0;
|
||||
min-height: 60px;
|
||||
overflow: hidden;
|
||||
padding: 5px 5px 5px 160px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.akismet-activate__button,
|
||||
.akismet-activate__button:hover,
|
||||
.akismet-activate__button:visited {
|
||||
margin: 0 1em;
|
||||
}
|
||||
|
||||
.akismet-activate__description {
|
||||
color: var(--akismet-color-charcoal);
|
||||
flex-grow: 1;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
text-wrap: pretty;
|
||||
}
|
||||
|
||||
/* Compatible plugins section */
|
||||
.akismet-compatible-plugins__content {
|
||||
padding: 0 1.5em 1.5em 1.5em;
|
||||
}
|
||||
|
||||
.akismet-compatible-plugins__intro {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.akismet-compatible-plugins__section-header-label {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.akismet-compatible-plugins__section-header-label-text {
|
||||
padding-left: 0.5em;
|
||||
}
|
||||
|
||||
.akismet-compatible-plugins__list {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(245px, 1fr));
|
||||
gap: 20px;
|
||||
margin: 1.5em 0 1em 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.akismet-compatible-plugins__card {
|
||||
border: 1px solid var(--akismet-color-light-grey);
|
||||
border-radius: 4px;
|
||||
flex: 1 1 calc(50% - 5px);
|
||||
padding: 1em;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.akismet-compatible-plugins__card-logo {
|
||||
padding: 0 0 0 1.5em;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.akismet-compatible-plugins__card-title {
|
||||
font-size: 1.2em;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.akismet-compatible-plugins__docs {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.akismet-compatible-plugins__show-more {
|
||||
all: unset;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Generates the show/hide chevron */
|
||||
.akismet-compatible-plugins__show-more::after {
|
||||
align-self: center;
|
||||
border-bottom: 2px solid black;
|
||||
border-left: 2px solid black;
|
||||
content: "";
|
||||
height: 8px;
|
||||
transform: rotate(-45deg);
|
||||
transition: transform 0.2s ease;
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
.akismet-compatible-plugins__list.is-expanded + .akismet-compatible-plugins__show-more::after {
|
||||
align-self: end;
|
||||
transform: rotate(-225deg);
|
||||
}
|
||||
|
||||
/* Gutenberg medium breakpoint */
|
||||
@media screen and (max-width: 782px) {
|
||||
.akismet-new-snapshot__list {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.akismet-new-snapshot__number {
|
||||
float: left;
|
||||
font-size: 20px;
|
||||
font-weight: 500;
|
||||
margin-top: -16px;
|
||||
}
|
||||
|
||||
.akismet-new-snapshot__header {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.akismet-new-snapshot__text {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.akismet-settings__row input[type="checkbox"],
|
||||
.akismet-settings__row input[type="radio"] {
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
}
|
||||
|
||||
.akismet-settings__row-label-text {
|
||||
padding-right: 0.8em;
|
||||
}
|
||||
|
||||
.akismet-settings__row input[type="checkbox"],
|
||||
.akismet-settings__row input[type="radio"] {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.akismet-activate {
|
||||
background-size: 120px;
|
||||
padding-left: 134px;
|
||||
}
|
||||
|
||||
.akismet-activate__button {
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.akismet-activate__description {
|
||||
font-size: 14px;
|
||||
margin-left: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
/* Gutenberg small breakpoint */
|
||||
@media screen and (max-width: 600px) {
|
||||
.akismet-compatible-plugins__list {
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.akismet-activate__button,
|
||||
.akismet-activate__button:hover {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.akismet-activate__description {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
464
wp-content/plugins/akismet/_inc/rtl/akismet-rtl.css
Normal file
@@ -0,0 +1,464 @@
|
||||
/* This file was automatically generated on Oct 30 2025 21:26:42 */
|
||||
|
||||
.wp-admin.jetpack_page_akismet-key-config, .wp-admin.settings_page_akismet-key-config {
|
||||
background-color:#f3f6f8;
|
||||
}
|
||||
|
||||
#submitted-on {
|
||||
position: relative;
|
||||
}
|
||||
#the-comment-list .author .akismet-user-comment-count {
|
||||
display: inline;
|
||||
}
|
||||
#the-comment-list .author a span {
|
||||
text-decoration: none;
|
||||
color: #999;
|
||||
}
|
||||
#the-comment-list .author a span.akismet-span-link {
|
||||
text-decoration: inherit;
|
||||
color: inherit;
|
||||
}
|
||||
#the-comment-list .akismet_remove_url {
|
||||
margin-right: 3px;
|
||||
color: #999;
|
||||
padding: 2px 0 2px 3px;
|
||||
}
|
||||
#the-comment-list .akismet_remove_url:hover {
|
||||
color: #A7301F;
|
||||
font-weight: bold;
|
||||
padding: 2px 0 2px 2px;
|
||||
}
|
||||
#dashboard_recent_comments .akismet-status {
|
||||
display: none;
|
||||
}
|
||||
.akismet-status {
|
||||
float: left;
|
||||
}
|
||||
.akismet-status a {
|
||||
color: #AAA;
|
||||
font-style: italic;
|
||||
}
|
||||
table.comments td.comment p a {
|
||||
text-decoration: underline;
|
||||
}
|
||||
table.comments td.comment p a:after {
|
||||
content: attr(href);
|
||||
color: #aaa;
|
||||
display: inline-block; /* Show the URL without the link's underline extending under it. */
|
||||
padding: 0 1ex; /* Because it's inline block, we can't just use spaces in the content: attribute to separate it from the link text. */
|
||||
}
|
||||
.mshot-arrow {
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-top: 10px solid transparent;
|
||||
border-bottom: 10px solid transparent;
|
||||
border-left: 10px solid #5C5C5C;
|
||||
position: absolute;
|
||||
right: -6px;
|
||||
top: 91px;
|
||||
}
|
||||
.mshot-container {
|
||||
background: #5C5C5C;
|
||||
position: absolute;
|
||||
top: -94px;
|
||||
padding: 7px;
|
||||
width: 450px;
|
||||
height: 338px;
|
||||
z-index: 20000;
|
||||
border-radius: 6px;
|
||||
}
|
||||
.akismet-mshot {
|
||||
position: absolute;
|
||||
z-index: 100;
|
||||
}
|
||||
.akismet-mshot .mshot-image {
|
||||
margin: 0;
|
||||
height: 338px;
|
||||
width: 450px;
|
||||
}
|
||||
.checkforspam {
|
||||
display: inline-block !important;
|
||||
}
|
||||
|
||||
.checkforspam-spinner {
|
||||
display: inline-block;
|
||||
margin-top: 7px;
|
||||
}
|
||||
|
||||
.akismet-right {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.akismet-card .akismet-right {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
.akismet-new-snapshot {
|
||||
margin-top: 1em;
|
||||
text-align: center;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.akismet-new-snapshot h3 {
|
||||
background: #f5f5f5;
|
||||
color: #888;
|
||||
font-size: 11px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.akismet-new-snapshot ul li {
|
||||
color: #999;
|
||||
font-size: 11px;
|
||||
text-transform: uppercase;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
|
||||
.akismet-settings th:first-child {
|
||||
vertical-align: top;
|
||||
padding-top: 15px;
|
||||
}
|
||||
|
||||
.akismet-settings th.akismet-api-key {
|
||||
vertical-align: middle;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.akismet-settings span.akismet-note {
|
||||
float: right;
|
||||
padding-right: 23px;
|
||||
font-size: 75%;
|
||||
margin-top: -10px;
|
||||
}
|
||||
|
||||
.jetpack_page_akismet-key-config #wpcontent, .settings_page_akismet-key-config #wpcontent {
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.akismet-masthead {
|
||||
background-color:#fff;
|
||||
text-align:center;
|
||||
box-shadow:0 1px 0 rgba(200,215,225,0.5),0 1px 2px #e9eff3
|
||||
}
|
||||
|
||||
@media (max-width: 45rem) {
|
||||
.akismet-masthead {
|
||||
padding:0 1.25rem
|
||||
}
|
||||
}
|
||||
|
||||
.akismet-masthead__inside-container {
|
||||
padding:.375rem 0;
|
||||
margin:0 auto;
|
||||
width:100%;
|
||||
max-width:45rem;
|
||||
text-align: right;
|
||||
}
|
||||
.akismet-masthead__logo-container {
|
||||
padding:.3125rem 0 0
|
||||
}
|
||||
.akismet-masthead__logo-link {
|
||||
display:inline-block;
|
||||
outline:none;
|
||||
vertical-align:middle
|
||||
}
|
||||
.akismet-masthead__logo-link:focus {
|
||||
line-height:0;
|
||||
box-shadow:0 0 0 2px #78dcfa
|
||||
}
|
||||
.akismet-masthead__logo-link+code {
|
||||
margin:0 10px;
|
||||
padding:5px 9px;
|
||||
border-radius:2px;
|
||||
background:#e6ecf1;
|
||||
color:#647a88
|
||||
}
|
||||
.akismet-masthead__links {
|
||||
display:flex;
|
||||
flex-flow:row wrap;
|
||||
flex:2 50%;
|
||||
justify-content:flex-end;
|
||||
margin:0
|
||||
}
|
||||
@media (max-width: 480px) {
|
||||
.akismet-masthead__links {
|
||||
padding-left:.625rem
|
||||
}
|
||||
}
|
||||
.akismet-masthead__link-li {
|
||||
margin:0;
|
||||
padding:0
|
||||
}
|
||||
.akismet-masthead__link {
|
||||
font-style:normal;
|
||||
color:#0087be;
|
||||
padding:.625rem;
|
||||
display:inline-block
|
||||
}
|
||||
.akismet-masthead__link:visited {
|
||||
color:#0087be
|
||||
}
|
||||
.akismet-masthead__link:active,.akismet-masthead__link:hover {
|
||||
color:#00aadc
|
||||
}
|
||||
.akismet-masthead__link:hover {
|
||||
text-decoration:underline
|
||||
}
|
||||
.akismet-masthead__link .dashicons {
|
||||
display:none
|
||||
}
|
||||
@media (max-width: 480px) {
|
||||
.akismet-masthead__link:hover,.akismet-masthead__link:active {
|
||||
text-decoration:none
|
||||
}
|
||||
.akismet-masthead__link .dashicons {
|
||||
display:block;
|
||||
font-size:1.75rem
|
||||
}
|
||||
.akismet-masthead__link span+span {
|
||||
display:none
|
||||
}
|
||||
}
|
||||
.akismet-masthead__link-li:last-of-type .akismet-masthead__link {
|
||||
padding-left:0
|
||||
}
|
||||
|
||||
.akismet-lower {
|
||||
margin: 0 auto;
|
||||
text-align: right;
|
||||
max-width: 45rem;
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
.akismet-lower .notice {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.akismet-card {
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 0;
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
background: white;
|
||||
}
|
||||
|
||||
.akismet-card:after, .akismet-card .inside:after, .akismet-masthead__logo-container:after {
|
||||
content: ".";
|
||||
display: block;
|
||||
height: 0;
|
||||
clear: both;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.akismet-card .inside {
|
||||
padding: 1.5rem;
|
||||
padding-top: 1rem;
|
||||
}
|
||||
|
||||
.akismet-card .akismet-card-actions {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.jetpack_page_akismet-key-config .update-nag, .settings_page_akismet-key-config .update-nag {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.akismet-masthead .akismet-right {
|
||||
line-height: 2.125rem;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.akismet-box {
|
||||
box-sizing: border-box;
|
||||
background: white;
|
||||
border: 1px solid rgba(200, 215, 225, 0.5);
|
||||
}
|
||||
|
||||
.akismet-box h2, .akismet-box h3 {
|
||||
padding: 1.5rem 1.5rem .5rem 1.5rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.akismet-box p {
|
||||
padding: 0 1.5rem 1.5rem 1.5rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.akismet-box p:after {
|
||||
content: ".";
|
||||
display: block;
|
||||
height: 0;
|
||||
clear: both;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.akismet-box .akismet-right {
|
||||
padding-left: 1.5rem;
|
||||
}
|
||||
|
||||
.akismet-boxes .akismet-box {
|
||||
margin-bottom: 0;
|
||||
padding: 0;
|
||||
margin-top: -1px;
|
||||
}
|
||||
|
||||
.akismet-boxes .akismet-box:last-child {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.akismet-boxes .akismet-box:first-child {
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
|
||||
.akismet-box .centered {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.akismet-button, .akismet-button:hover, .akismet-button:visited {
|
||||
background: white;
|
||||
border-color: #c8d7e1;
|
||||
border-style: solid;
|
||||
border-width: 1px 1px 2px;
|
||||
color: #2e4453;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
outline: 0;
|
||||
overflow: hidden;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
text-overflow: ellipsis;
|
||||
text-decoration: none;
|
||||
vertical-align: top;
|
||||
box-sizing: border-box;
|
||||
line-height: 21px;
|
||||
border-radius: 4px;
|
||||
padding: 7px 14px 9px;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
.akismet-button:hover {
|
||||
border-color: #a8bece;
|
||||
}
|
||||
|
||||
.akismet-button:active {
|
||||
border-width: 2px 1px 1px;
|
||||
}
|
||||
|
||||
.akismet-is-primary, .akismet-is-primary:hover, .akismet-is-primary:visited {
|
||||
background: #00aadc;
|
||||
border-color: #0087be;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.akismet-is-primary:hover, .akismet-is-primary:focus {
|
||||
border-color: #005082;
|
||||
}
|
||||
|
||||
.akismet-is-primary:hover {
|
||||
border-color: #005082;
|
||||
}
|
||||
|
||||
.akismet-section-header {
|
||||
position: relative;
|
||||
margin: 0 auto 0.625rem auto;
|
||||
padding: 1rem;
|
||||
box-sizing: border-box;
|
||||
box-shadow: 0 0 0 1px rgba(200, 215, 225, 0.5), 0 1px 2px #e9eff3;
|
||||
background: #ffffff;
|
||||
width: 100%;
|
||||
padding-top: 0.6875rem;
|
||||
padding-bottom: 0.6875rem;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.akismet-section-header__label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-grow: 1;
|
||||
line-height: 1.75rem;
|
||||
position: relative;
|
||||
font-size: 0.875rem;
|
||||
color: #4f748e;
|
||||
}
|
||||
|
||||
.akismet-section-header__actions {
|
||||
line-height: 1.75rem;
|
||||
}
|
||||
|
||||
.akismet-setup-instructions form {
|
||||
padding-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.akismet-setup-instructions > a.akismet-button {
|
||||
display: inline-block;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
div.error.akismet-usage-limit-alert {
|
||||
padding: 25px 15px 25px 45px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#akismet-plugin-container .akismet-usage-limit-alert {
|
||||
margin: 0 auto 0.625rem auto;
|
||||
box-sizing: border-box;
|
||||
box-shadow: 0 0 0 1px rgba(200, 215, 225, 0.5), 0 1px 2px #e9eff3;
|
||||
border: none;
|
||||
border-right: 4px solid #d63638;
|
||||
}
|
||||
|
||||
.akismet-usage-limit-alert .akismet-usage-limit-logo {
|
||||
width: 38px;
|
||||
min-width: 38px;
|
||||
height: 38px;
|
||||
border-radius: 20px;
|
||||
margin-left: 18px;
|
||||
background: black;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.akismet-usage-limit-alert .akismet-usage-limit-logo img {
|
||||
position: absolute;
|
||||
width: 22px;
|
||||
right: 8px;
|
||||
top: 10px;
|
||||
}
|
||||
|
||||
.akismet-usage-limit-alert .akismet-usage-limit-text {
|
||||
flex-grow: 1;
|
||||
margin-left: 18px;
|
||||
}
|
||||
|
||||
.akismet-usage-limit-alert h3 {
|
||||
line-height: 1.3;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.akismet-usage-limit-alert .akismet-usage-limit-cta {
|
||||
border-color: none;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
#akismet-plugin-container .akismet-usage-limit-cta a {
|
||||
color: #d63638;
|
||||
background: #fafafa;
|
||||
}
|
||||
|
||||
@media (max-width: 550px) {
|
||||
div.error.akismet-usage-limit-alert {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.akismet-usage-limit-alert .akismet-usage-limit-logo,
|
||||
.akismet-usage-limit-alert .akismet-usage-limit-text {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.akismet-usage-limit-alert .akismet-usage-limit-cta {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
71
wp-content/plugins/akismet/akismet.php
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Akismet
|
||||
*/
|
||||
/*
|
||||
Plugin Name: Akismet Anti-spam: Spam Protection
|
||||
Plugin URI: https://akismet.com/
|
||||
Description: Used by millions, Akismet is quite possibly the best way in the world to <strong>protect your blog from spam</strong>. Akismet Anti-spam keeps your site protected even while you sleep. To get started: activate the Akismet plugin and then go to your Akismet Settings page to set up your API key.
|
||||
Version: 5.6
|
||||
Requires at least: 5.8
|
||||
Requires PHP: 7.2
|
||||
Author: Automattic - Anti-spam Team
|
||||
Author URI: https://automattic.com/wordpress-plugins/
|
||||
License: GPLv2 or later
|
||||
Text Domain: akismet
|
||||
*/
|
||||
|
||||
/*
|
||||
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.
|
||||
|
||||
Copyright 2005-2025 Automattic, Inc.
|
||||
*/
|
||||
|
||||
// Make sure we don't expose any info if called directly
|
||||
if ( ! function_exists( 'add_action' ) ) {
|
||||
echo 'Hi there! I\'m just a plugin, not much I can do when called directly.';
|
||||
exit;
|
||||
}
|
||||
|
||||
define( 'AKISMET_VERSION', '5.6' );
|
||||
define( 'AKISMET__MINIMUM_WP_VERSION', '5.8' );
|
||||
define( 'AKISMET__PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
|
||||
define( 'AKISMET_DELETE_LIMIT', 10000 );
|
||||
|
||||
register_activation_hook( __FILE__, array( 'Akismet', 'plugin_activation' ) );
|
||||
register_deactivation_hook( __FILE__, array( 'Akismet', 'plugin_deactivation' ) );
|
||||
|
||||
require_once AKISMET__PLUGIN_DIR . 'class.akismet.php';
|
||||
require_once AKISMET__PLUGIN_DIR . 'class.akismet-widget.php';
|
||||
require_once AKISMET__PLUGIN_DIR . 'class.akismet-rest-api.php';
|
||||
require_once AKISMET__PLUGIN_DIR . 'class-akismet-compatible-plugins.php';
|
||||
|
||||
add_action( 'init', array( 'Akismet', 'init' ) );
|
||||
|
||||
add_action( 'rest_api_init', array( 'Akismet_REST_API', 'init' ) );
|
||||
|
||||
add_action( 'init', array( 'Akismet_Compatible_Plugins', 'init' ) );
|
||||
|
||||
if ( is_admin() || ( defined( 'WP_CLI' ) && WP_CLI ) ) {
|
||||
require_once AKISMET__PLUGIN_DIR . 'class.akismet-admin.php';
|
||||
add_action( 'init', array( 'Akismet_Admin', 'init' ) );
|
||||
}
|
||||
|
||||
// add wrapper class around deprecated akismet functions that are referenced elsewhere
|
||||
require_once AKISMET__PLUGIN_DIR . 'wrapper.php';
|
||||
|
||||
if ( defined( 'WP_CLI' ) && WP_CLI ) {
|
||||
require_once AKISMET__PLUGIN_DIR . 'class.akismet-cli.php';
|
||||
}
|
||||
550
wp-content/plugins/akismet/changelog.txt
Normal file
@@ -0,0 +1,550 @@
|
||||
=== Akismet Anti-spam ===
|
||||
|
||||
== Archived Changelog Entries ==
|
||||
|
||||
This file contains older changelog entries, so we can keep the size of the standard WordPress readme.txt file reasonable.
|
||||
For the latest changes, please see the "Changelog" section of the [readme.txt file](https://plugins.svn.wordpress.org/akismet/trunk/readme.txt).
|
||||
|
||||
= 4.2.5 =
|
||||
*Release Date - 11 July 2022*
|
||||
|
||||
* Fixed a bug that added unnecessary comment history entries after comment rechecks.
|
||||
* Added a notice that displays when WP-Cron is disabled and might be affecting comment rechecks.
|
||||
|
||||
= 4.2.4 =
|
||||
*Release Date - 20 May 2022*
|
||||
|
||||
* Improved translator instructions for comment history.
|
||||
* Bumped the "Tested up to" tag to WP 6.0.
|
||||
|
||||
= 4.2.3 =
|
||||
*Release Date - 25 April 2022*
|
||||
|
||||
* Improved compatibility with Fluent Forms
|
||||
* Fixed missing translation domains
|
||||
* Updated stats URL.
|
||||
* Improved accessibility of elements on the config page.
|
||||
|
||||
= 4.2.2 =
|
||||
*Release Date - 24 January 2022*
|
||||
|
||||
* Improved compatibility with Formidable Forms
|
||||
* Fixed a bug that could cause issues when multiple contact forms appear on one page.
|
||||
* Updated delete_comment and deleted_comment actions to pass two arguments to match WordPress core since 4.9.0.
|
||||
* Added a filter that allows comment types to be excluded when counting users' approved comments.
|
||||
|
||||
= 4.2.1 =
|
||||
*Release Date - 1 October 2021*
|
||||
|
||||
* Fixed a bug causing AMP validation to fail on certain pages with forms.
|
||||
|
||||
= 4.2 =
|
||||
*Release Date - 30 September 2021*
|
||||
|
||||
* Added links to additional information on API usage notifications.
|
||||
* Reduced the number of network requests required for a comment page when running Akismet.
|
||||
* Improved compatibility with the most popular contact form plugins.
|
||||
* Improved API usage buttons for clarity on what upgrade is needed.
|
||||
|
||||
= 4.1.12 =
|
||||
*Release Date - 3 September 2021*
|
||||
|
||||
* Fixed "Use of undefined constant" notice.
|
||||
* Improved styling of alert notices.
|
||||
|
||||
= 4.1.11 =
|
||||
*Release Date - 23 August 2021*
|
||||
|
||||
* Added support for Akismet API usage notifications on Akismet settings and edit-comments admin pages.
|
||||
* Added support for the deleted_comment action when bulk-deleting comments from Spam.
|
||||
|
||||
= 4.1.10 =
|
||||
*Release Date - 6 July 2021*
|
||||
|
||||
* Simplified the code around checking comments in REST API and XML-RPC requests.
|
||||
* Updated Plus plan terminology in notices to match current subscription names.
|
||||
* Added `rel="noopener"` to the widget link to avoid warnings in Google Lighthouse.
|
||||
* Set the Akismet JavaScript as deferred instead of async to improve responsiveness.
|
||||
* Improved the preloading of screenshot popups on the edit comments admin page.
|
||||
|
||||
= 4.1.9 =
|
||||
*Release Date - 2 March 2021*
|
||||
|
||||
* Improved handling of pingbacks in XML-RPC multicalls
|
||||
|
||||
= 4.1.8 =
|
||||
*Release Date - 6 January 2021*
|
||||
|
||||
* Fixed missing fields in submit-spam and submit-ham calls that could lead to reduced accuracy.
|
||||
* Fixed usage of deprecated jQuery function.
|
||||
|
||||
= 4.1.7 =
|
||||
*Release Date - 22 October 2020*
|
||||
|
||||
* Show the "Set up your Akismet account" banner on the comments admin screen, where it's relevant to mention if Akismet hasn't been configured.
|
||||
* Don't use wp_blacklist_check when the new wp_check_comment_disallowed_list function is available.
|
||||
|
||||
= 4.1.6 =
|
||||
*Release Date - 4 June 2020*
|
||||
|
||||
* Disable "Check for Spam" button until the page is loaded to avoid errors with clicking through to queue recheck endpoint directly.
|
||||
* Added filter "akismet_enable_mshots" to allow disabling screenshot popups on the edit comments admin page.
|
||||
|
||||
= 4.1.5 =
|
||||
*Release Date - 29 April 2020*
|
||||
|
||||
* Based on user feedback, we have dropped the in-admin notice explaining the availability of the "privacy notice" option in the AKismet settings screen. The option itself is available, but after displaying the notice for the last 2 years, it is now considered a known fact.
|
||||
* Updated the "Requires at least" to WP 4.6, based on recommendations from https://wp-info.org/tools/checkplugini18n.php?slug=akismet
|
||||
* Moved older changelog entries to a separate file to keep the size of this readme reasonable, also based on recommendations from https://wp-info.org/tools/checkplugini18n.php?slug=akismet
|
||||
|
||||
= 4.1.4 =
|
||||
*Release Date - 17 March 2020*
|
||||
|
||||
* Only redirect to the Akismet setup screen upon plugin activation if the plugin was activated manually from within the plugin-related screens, to help users with non-standard install workflows, like WP-CLI.
|
||||
* Update the layout of the initial setup screen to be more readable on small screens.
|
||||
* If no API key has been entered, don't run code that expects an API key.
|
||||
* Improve the readability of the comment history entries.
|
||||
* Don't modify the comment form HTML if no API key has been set.
|
||||
|
||||
= 4.1.3 =
|
||||
*Release Date - 31 October 2019*
|
||||
|
||||
* Prevented an attacker from being able to cause a user to unknowingly recheck their Pending comments for spam.
|
||||
* Improved compatibility with Jetpack 7.7+.
|
||||
* Updated the plugin activation page to use consistent language and markup.
|
||||
* Redirecting users to the Akismet connnection/settings screen upon plugin activation, in an effort to make it easier for people to get setup.
|
||||
|
||||
= 4.1.2 =
|
||||
*Release Date - 14 May 2019*
|
||||
|
||||
* Fixed a conflict between the Akismet setup banner and other plugin notices.
|
||||
* Reduced the number of API requests made by the plugin when attempting to verify the API key.
|
||||
* Include additional data in the pingback pre-check API request to help make the stats more accurate.
|
||||
* Fixed a bug that was enabling the "Check for Spam" button when no comments were eligible to be checked.
|
||||
* Improved Akismet's AMP compatibility.
|
||||
|
||||
= 4.1.1 =
|
||||
*Release Date - 31 January 2019*
|
||||
|
||||
* Fixed the "Setup Akismet" notice so it resizes responsively.
|
||||
* Only highlight the "Save Changes" button in the Akismet config when changes have been made.
|
||||
* The count of comments in your spam queue shown on the dashboard show now always be up-to-date.
|
||||
|
||||
= 4.1 =
|
||||
*Release Date - 12 November 2018*
|
||||
|
||||
* Added a WP-CLI method for retrieving stats.
|
||||
* Hooked into the new "Personal Data Eraser" functionality from WordPress 4.9.6.
|
||||
* Added functionality to clear outdated alerts from Akismet.com.
|
||||
|
||||
= 4.0.8 =
|
||||
*Release Date - 19 June 2018*
|
||||
|
||||
* Improved the grammar and consistency of the in-admin privacy related notes (notice and config).
|
||||
* Revised in-admin explanation of the comment form privacy notice to make its usage clearer.
|
||||
* Added `rel="nofollow noopener"` to the comment form privacy notice to improve SEO and security.
|
||||
|
||||
= 4.0.7 =
|
||||
*Release Date - 28 May 2018*
|
||||
|
||||
* Based on user feedback, the link on "Learn how your comment data is processed." in the optional privacy notice now has a `target` of `_blank` and opens in a new tab/window.
|
||||
* Updated the in-admin privacy notice to use the term "comment" instead of "contact" in "Akismet can display a notice to your users under your comment forms."
|
||||
* Only show in-admin privacy notice if Akismet has an API Key configured
|
||||
|
||||
= 4.0.6 =
|
||||
*Release Date - 26 May 2018*
|
||||
|
||||
* Moved away from using `empty( get_option() )` to instantiating a variable to be compatible with older versions of PHP (5.3, 5.4, etc).
|
||||
|
||||
= 4.0.5 =
|
||||
*Release Date - 26 May 2018*
|
||||
|
||||
* Corrected version number after tagging. Sorry...
|
||||
|
||||
= 4.0.4 =
|
||||
*Release Date - 26 May 2018*
|
||||
|
||||
* Added a hook to provide Akismet-specific privacy information for a site's privacy policy.
|
||||
* Added tools to control the display of a privacy related notice under comment forms.
|
||||
* Fixed HTML in activation failure message to close META and HEAD tag properly.
|
||||
* Fixed a bug that would sometimes prevent Akismet from being correctly auto-configured.
|
||||
|
||||
= 4.0.3 =
|
||||
*Release Date - 19 February 2018*
|
||||
|
||||
* Added a scheduled task to remove entries in wp_commentmeta that no longer have corresponding comments in wp_comments.
|
||||
* Added a new `akismet_batch_delete_count` action to the batch delete methods for people who'd like to keep track of the numbers of records being processed by those methods.
|
||||
|
||||
= 4.0.2 =
|
||||
*Release Date - 18 December 2017*
|
||||
|
||||
* Fixed a bug that could cause Akismet to recheck a comment that has already been manually approved or marked as spam.
|
||||
* Fixed a bug that could cause Akismet to claim that some comments are still waiting to be checked when no comments are waiting to be checked.
|
||||
|
||||
= 4.0.1 =
|
||||
*Release Date - 6 November 2017*
|
||||
|
||||
* Fixed a bug that could prevent some users from connecting Akismet via their Jetpack connection.
|
||||
* Ensured that any pending Akismet-related events are unscheduled if the plugin is deactivated.
|
||||
* Allow some JavaScript to be run asynchronously to avoid affecting page render speeds.
|
||||
|
||||
= 4.0 =
|
||||
*Release Date - 19 September 2017*
|
||||
|
||||
* Added REST API endpoints for configuring Akismet and retrieving stats.
|
||||
* Increased the minimum supported WordPress version to 4.0.
|
||||
* Added compatibility with comments submitted via the REST API.
|
||||
* Improved the progress indicator on the "Check for Spam" button.
|
||||
|
||||
= 3.3.4 =
|
||||
*Release Date - 3 August 2017*
|
||||
|
||||
* Disabled Akismet's debug log output by default unless AKISMET_DEBUG is defined.
|
||||
* URL previews now begin preloading when the mouse moves near them in the comments section of wp-admin.
|
||||
* When a comment is caught by the Comment Blacklist, Akismet will always allow it to stay in the trash even if it is spam as well.
|
||||
* Fixed a bug that was preventing an error from being shown when a site can't reach Akismet's servers.
|
||||
|
||||
= 3.3.3 =
|
||||
*Release Date - 13 July 2017*
|
||||
|
||||
* Reduced amount of bandwidth used by the URL Preview feature.
|
||||
* Improved the admin UI when the API key is manually pre-defined for the site.
|
||||
* Removed a workaround for WordPress installations older than 3.3 that will improve Akismet's compatibility with other plugins.
|
||||
* The number of spam blocked that is displayed on the WordPress dashboard will now be more accurate and updated more frequently.
|
||||
* Fixed a bug in the Akismet widget that could cause PHP warnings.
|
||||
|
||||
= 3.3.2 =
|
||||
*Release Date - 10 May 2017*
|
||||
|
||||
* Fixed a bug causing JavaScript errors in some browsers.
|
||||
|
||||
= 3.3.1 =
|
||||
*Release Date - 2 May 2017*
|
||||
|
||||
* Improve performance by only requesting the akismet_comment_nonce option when absolutely necessary.
|
||||
* Fixed two bugs that could cause PHP warnings.
|
||||
* Fixed a bug that was preventing the "Remove author URL" feature from working after a comment was edited using "Quick Edit."
|
||||
* Fixed a bug that was preventing the URL preview feature from working after a comment was edited using "Quick Edit."
|
||||
|
||||
= 3.3 =
|
||||
*Release Date - 23 February 2017*
|
||||
|
||||
* Updated the Akismet admin pages with a new clean design.
|
||||
* Fixed bugs preventing the `akismet_add_comment_nonce` and `akismet_update_alert` wrapper functions from working properly.
|
||||
* Fixed bug preventing the loading indicator from appearing when re-checking all comments for spam.
|
||||
* Added a progress indicator to the "Check for Spam" button.
|
||||
* Added a success message after manually rechecking the Pending queue for spam.
|
||||
|
||||
= 3.2 =
|
||||
*Release Date - 6 September 2016*
|
||||
|
||||
* Added a WP-CLI module. You can now check comments and recheck the moderation queue from the command line.
|
||||
* Stopped using the deprecated jQuery function `.live()`.
|
||||
* Fixed a bug in `remove_comment_author_url()` and `add_comment_author_url()` that could generate PHP notices.
|
||||
* Fixed a bug that could cause an infinite loop for sites with very very very large comment IDs.
|
||||
* Fixed a bug that could cause the Akismet widget title to be blank.
|
||||
|
||||
= 3.1.11 =
|
||||
*Release Date - 12 May 2016*
|
||||
|
||||
* Fixed a bug that could cause the "Check for Spam" button to skip some comments.
|
||||
* Fixed a bug that could prevent some spam submissions from being sent to Akismet.
|
||||
* Updated all links to use https:// when possible.
|
||||
* Disabled Akismet debug logging unless WP_DEBUG and WP_DEBUG_LOG are both enabled.
|
||||
|
||||
= 3.1.10 =
|
||||
*Release Date - 1 April 2016*
|
||||
|
||||
* Fixed a bug that could cause comments caught as spam to be placed in the Pending queue.
|
||||
* Fixed a bug that could have resulted in comments that were caught by the core WordPress comment blacklist not to have a corresponding History entry.
|
||||
* Fixed a bug that could have caused avoidable PHP warnings in the error log.
|
||||
|
||||
= 3.1.9 =
|
||||
*Release Date - 28 March 2016*
|
||||
|
||||
* Add compatibility with Jetpack so that Jetpack can automatically configure Akismet settings when appropriate.
|
||||
* Fixed a bug preventing some comment data from being sent to Akismet.
|
||||
|
||||
= 3.1.8 =
|
||||
*Release Date - 4 March 2016*
|
||||
|
||||
* Fixed a bug preventing Akismet from being used with some plugins that rewrite admin URLs.
|
||||
* Reduced the amount of bandwidth used on Akismet API calls
|
||||
* Reduced the amount of space Akismet uses in the database
|
||||
* Fixed a bug that could cause comments caught as spam to be placed in the Pending queue.
|
||||
|
||||
= 3.1.7 =
|
||||
*Release Date - 4 January 2016*
|
||||
|
||||
* Added documentation for the 'akismet_comment_nonce' filter.
|
||||
* The post-install activation button is now accessible to screen readers and keyboard-only users.
|
||||
* Fixed a bug that was preventing the "Remove author URL" feature from working in WordPress 4.4
|
||||
|
||||
= 3.1.6 =
|
||||
*Release Date - 14 December 2015*
|
||||
|
||||
* Improve the notices shown after activating Akismet.
|
||||
* Update some strings to allow for the proper plural forms in all languages.
|
||||
|
||||
= 3.1.5 =
|
||||
*Release Date - 13 October 2015*
|
||||
|
||||
* Closes a potential XSS vulnerability.
|
||||
|
||||
= 3.1.4 =
|
||||
*Release Date - 24 September 2015*
|
||||
|
||||
* Fixed a bug that was preventing some users from automatically connecting using Jetpack if they didn't have a current Akismet subscription.
|
||||
* Fixed a bug that could cause comments caught as spam to be placed in the Pending queue.
|
||||
* Error messages and instructions have been simplified to be more understandable.
|
||||
* Link previews are enabled for all links inside comments, not just the author's website link.
|
||||
|
||||
= 3.1.3 =
|
||||
*Release Date - 6 July 2015*
|
||||
|
||||
* Notify users when their account status changes after previously being successfully set up. This should help any users who are seeing blank Akismet settings screens.
|
||||
|
||||
= 3.1.2 =
|
||||
*Release Date - 7 June 2015*
|
||||
|
||||
* Reduced the amount of space Akismet uses in the commentmeta table.
|
||||
* Fixed a bug where some comments with quotes in the author name weren't getting history entries
|
||||
* Pre-emptive security improvements to ensure that the Akismet plugin can't be used by attackers to compromise a WordPress installation.
|
||||
* Better UI for the key entry field: allow whitespace to be included at the beginning or end of the key and strip it out automatically when the form is submitted.
|
||||
* When deactivating the plugin, notify the Akismet API so the site can be marked as inactive.
|
||||
* Clearer error messages.
|
||||
|
||||
= 3.1.1 =
|
||||
*Release Date - 17th March, 2015*
|
||||
|
||||
* Improvements to the "Remove comment author URL" JavaScript
|
||||
* Include the pingback pre-check from the 2.6 branch.
|
||||
|
||||
= 3.1 =
|
||||
*Release Date - 11th March, 2015*
|
||||
|
||||
* Use HTTPS by default for all requests to Akismet.
|
||||
* Fix for a situation where Akismet might strip HTML from a comment.
|
||||
|
||||
= 3.0.4 =
|
||||
*Release Date - 11th December, 2014*
|
||||
|
||||
* Fix to make .htaccess compatible with Apache 2.4.
|
||||
* Fix to allow removal of https author URLs.
|
||||
* Fix to avoid stripping part of the author URL when removing and re-adding.
|
||||
* Removed the "Check for Spam" button from the "Trash" and "Approved" queues, where it would have no effect.
|
||||
* Allow automatic API key configuration when Jetpack is installed and connected to a WordPress.com account
|
||||
|
||||
= 3.0.3 =
|
||||
*Release Date - 3rd November, 2014*
|
||||
|
||||
* Fix for sending the wrong data to delete_comment action that could have prevented old spam comments from being deleted.
|
||||
* Added a filter to disable logging of Akismet debugging information.
|
||||
* Added a filter for the maximum comment age when deleting old spam comments.
|
||||
* Added a filter for the number per batch when deleting old spam comments.
|
||||
* Removed the "Check for Spam" button from the Spam folder.
|
||||
|
||||
= 3.0.2 =
|
||||
*Release Date - 18th August, 2014*
|
||||
|
||||
* Performance improvements.
|
||||
* Fixed a bug that could truncate the comment data being sent to Akismet for checking.
|
||||
|
||||
= 3.0.1 =
|
||||
*Release Date - 9th July, 2014*
|
||||
|
||||
* Removed dependency on PHP's fsockopen function
|
||||
* Fix spam/ham reports to work when reported outside of the WP dashboard, e.g., from Notifications or the WP app
|
||||
* Remove jQuery dependency for comment form JavaScript
|
||||
* Remove unnecessary data from some Akismet comment meta
|
||||
* Suspended keys will now result in all comments being put in moderation, not spam.
|
||||
|
||||
= 3.0.0 =
|
||||
*Release Date - 15th April, 2014*
|
||||
|
||||
* Move Akismet to Settings menu
|
||||
* Drop Akismet Stats menu
|
||||
* Add stats snapshot to Akismet settings
|
||||
* Add Akismet subscription details and status to Akismet settings
|
||||
* Add contextual help for each page
|
||||
* Improve Akismet setup to use Jetpack to automate plugin setup
|
||||
* Fix "Check for Spam" to use AJAX to avoid page timing out
|
||||
* Fix Akismet settings page to be responsive
|
||||
* Drop legacy code
|
||||
* Tidy up CSS and Javascript
|
||||
* Replace the old discard setting with a new "discard pervasive spam" feature.
|
||||
|
||||
= 2.6.0 =
|
||||
*Release Date - 18th March, 2014*
|
||||
|
||||
* Add ajax paging to the check for spam button to handle large volumes of comments
|
||||
* Optimize javascript and add localization support
|
||||
* Fix bug in link to spam comments from right now dashboard widget
|
||||
* Fix bug with deleting old comments to avoid timeouts dealing with large volumes of comments
|
||||
* Include X-Pingback-Forwarded-For header in outbound WordPress pingback verifications
|
||||
* Add pre-check for pingbacks, to stop spam before an outbound verification request is made
|
||||
|
||||
= 2.5.9 =
|
||||
*Release Date - 1st August, 2013*
|
||||
|
||||
* Update 'Already have a key' link to redirect page rather than depend on javascript
|
||||
* Fix some non-translatable strings to be translatable
|
||||
* Update Activation banner in plugins page to redirect user to Akismet config page
|
||||
|
||||
= 2.5.8 =
|
||||
*Release Date - 20th January, 2013*
|
||||
|
||||
* Simplify the activation process for new users
|
||||
* Remove the reporter_ip parameter
|
||||
* Minor preventative security improvements
|
||||
|
||||
= 2.5.7 =
|
||||
*Release Date - 13th December, 2012*
|
||||
|
||||
* FireFox Stats iframe preview bug
|
||||
* Fix mshots preview when using https
|
||||
* Add .htaccess to block direct access to files
|
||||
* Prevent some PHP notices
|
||||
* Fix Check For Spam return location when referrer is empty
|
||||
* Fix Settings links for network admins
|
||||
* Fix prepare() warnings in WP 3.5
|
||||
|
||||
= 2.5.6 =
|
||||
*Release Date - 26th April, 2012*
|
||||
|
||||
* Prevent retry scheduling problems on sites where wp_cron is misbehaving
|
||||
* Preload mshot previews
|
||||
* Modernize the widget code
|
||||
* Fix a bug where comments were not held for moderation during an error condition
|
||||
* Improve the UX and display when comments are temporarily held due to an error
|
||||
* Make the Check For Spam button force a retry when comments are held due to an error
|
||||
* Handle errors caused by an invalid key
|
||||
* Don't retry comments that are too old
|
||||
* Improve error messages when verifying an API key
|
||||
|
||||
= 2.5.5 =
|
||||
*Release Date - 11th January, 2012*
|
||||
|
||||
* Add nonce check for comment author URL remove action
|
||||
* Fix the settings link
|
||||
|
||||
= 2.5.4 =
|
||||
*Release Date - 5th January, 2012*
|
||||
|
||||
* Limit Akismet CSS and Javascript loading in wp-admin to just the pages that need it
|
||||
* Added author URL quick removal functionality
|
||||
* Added mShot preview on Author URL hover
|
||||
* Added empty index.php to prevent directory listing
|
||||
* Move wp-admin menu items under Jetpack, if it is installed
|
||||
* Purge old Akismet comment meta data, default of 15 days
|
||||
|
||||
= 2.5.3 =
|
||||
*Release Date - 8th Febuary, 2011*
|
||||
|
||||
* Specify the license is GPL v2 or later
|
||||
* Fix a bug that could result in orphaned commentmeta entries
|
||||
* Include hotfix for WordPress 3.0.5 filter issue
|
||||
|
||||
= 2.5.2 =
|
||||
*Release Date - 14th January, 2011*
|
||||
|
||||
* Properly format the comment count for author counts
|
||||
* Look for super admins on multisite installs when looking up user roles
|
||||
* Increase the HTTP request timeout
|
||||
* Removed padding for author approved count
|
||||
* Fix typo in function name
|
||||
* Set Akismet stats iframe height to fixed 2500px. Better to have one tall scroll bar than two side by side.
|
||||
|
||||
= 2.5.1 =
|
||||
*Release Date - 17th December, 2010*
|
||||
|
||||
* Fix a bug that caused the "Auto delete" option to fail to discard comments correctly
|
||||
* Remove the comment nonce form field from the 'Akismet Configuration' page in favor of using a filter, akismet_comment_nonce
|
||||
* Fixed padding bug in "author" column of posts screen
|
||||
* Added margin-top to "cleared by ..." badges on dashboard
|
||||
* Fix possible error when calling akismet_cron_recheck()
|
||||
* Fix more PHP warnings
|
||||
* Clean up XHTML warnings for comment nonce
|
||||
* Fix for possible condition where scheduled comment re-checks could get stuck
|
||||
* Clean up the comment meta details after deleting a comment
|
||||
* Only show the status badge if the comment status has been changed by someone/something other than Akismet
|
||||
* Show a 'History' link in the row-actions
|
||||
* Translation fixes
|
||||
* Reduced font-size on author name
|
||||
* Moved "flagged by..." notification to top right corner of comment container and removed heavy styling
|
||||
* Hid "flagged by..." notification while on dashboard
|
||||
|
||||
= 2.5.0 =
|
||||
*Release Date - 7th December, 2010*
|
||||
|
||||
* Track comment actions under 'Akismet Status' on the edit comment screen
|
||||
* Fix a few remaining deprecated function calls ( props Mike Glendinning )
|
||||
* Use HTTPS for the stats IFRAME when wp-admin is using HTTPS
|
||||
* Use the WordPress HTTP class if available
|
||||
* Move the admin UI code to a separate file, only loaded when needed
|
||||
* Add cron retry feature, to replace the old connectivity check
|
||||
* Display Akismet status badge beside each comment
|
||||
* Record history for each comment, and display it on the edit page
|
||||
* Record the complete comment as originally submitted in comment_meta, to use when reporting spam and ham
|
||||
* Highlight links in comment content
|
||||
* New option, "Show the number of comments you've approved beside each comment author."
|
||||
* New option, "Use a nonce on the comment form."
|
||||
|
||||
= 2.4.0 =
|
||||
*Release Date - 23rd August, 2010*
|
||||
|
||||
* Spell out that the license is GPLv2
|
||||
* Fix PHP warnings
|
||||
* Fix WordPress deprecated function calls
|
||||
* Fire the delete_comment action when deleting comments
|
||||
* Move code specific for older WP versions to legacy.php
|
||||
* General code clean up
|
||||
|
||||
= 2.3.0 =
|
||||
*Release Date - 5th June, 2010*
|
||||
|
||||
* Fix "Are you sure" nonce message on config screen in WPMU
|
||||
* Fix XHTML compliance issue in sidebar widget
|
||||
* Change author link; remove some old references to WordPress.com accounts
|
||||
* Localize the widget title (core ticket #13879)
|
||||
|
||||
= 2.2.9 =
|
||||
*Release Date - 2nd June, 2010*
|
||||
|
||||
* Eliminate a potential conflict with some plugins that may cause spurious reports
|
||||
|
||||
= 2.2.8 =
|
||||
*Release Date - 27th May, 2010*
|
||||
|
||||
* Fix bug in initial comment check for ipv6 addresses
|
||||
* Report comments as ham when they are moved from spam to moderation
|
||||
* Report comments as ham when clicking undo after spam
|
||||
* Use transition_comment_status action when available instead of older actions for spam/ham submissions
|
||||
* Better diagnostic messages when PHP network functions are unavailable
|
||||
* Better handling of comments by logged-in users
|
||||
|
||||
= 2.2.7 =
|
||||
*Release Date - 17th December, 2009*
|
||||
|
||||
* Add a new AKISMET_VERSION constant
|
||||
* Reduce the possibility of over-counting spam when another spam filter plugin is in use
|
||||
* Disable the connectivity check when the API key is hard-coded for WPMU
|
||||
|
||||
= 2.2.6 =
|
||||
*Release Date - 20th July, 2009*
|
||||
|
||||
* Fix a global warning introduced in 2.2.5
|
||||
* Add changelog and additional readme.txt tags
|
||||
* Fix an array conversion warning in some versions of PHP
|
||||
* Support a new WPCOM_API_KEY constant for easier use with WordPress MU
|
||||
|
||||
= 2.2.5 =
|
||||
*Release Date - 13th July, 2009*
|
||||
|
||||
* Include a new Server Connectivity diagnostic check, to detect problems caused by firewalls
|
||||
|
||||
= 2.2.4 =
|
||||
*Release Date - 3rd June, 2009*
|
||||
|
||||
* Fixed a key problem affecting the stats feature in WordPress MU
|
||||
* Provide additional blog information in Akismet API calls
|
||||
309
wp-content/plugins/akismet/class-akismet-compatible-plugins.php
Normal file
@@ -0,0 +1,309 @@
|
||||
<?php
|
||||
/**
|
||||
* Handles compatibility checks for Akismet with other plugins.
|
||||
*
|
||||
* @package Akismet
|
||||
* @since 5.4.0
|
||||
*/
|
||||
|
||||
declare( strict_types = 1 );
|
||||
|
||||
// Following existing Akismet convention for file naming.
|
||||
// phpcs:ignore WordPress.Files.FileName.NotHyphenatedLowercase
|
||||
|
||||
/**
|
||||
* Class for managing compatibility checks for Akismet with other plugins.
|
||||
*
|
||||
* This class includes methods for determining whether specific plugins are
|
||||
* installed and active relative to the ability to work with Akismet.
|
||||
*/
|
||||
class Akismet_Compatible_Plugins {
|
||||
/**
|
||||
* The endpoint for the compatible plugins API.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected const COMPATIBLE_PLUGIN_ENDPOINT = 'https://rest.akismet.com/1.2/compatible-plugins';
|
||||
|
||||
/**
|
||||
* The error key for the compatible plugins API error.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected const COMPATIBLE_PLUGIN_API_ERROR = 'akismet_compatible_plugins_api_error';
|
||||
|
||||
/**
|
||||
* The valid fields for a compatible plugin object.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected const COMPATIBLE_PLUGIN_FIELDS = array(
|
||||
'slug',
|
||||
'name',
|
||||
'logo',
|
||||
'help_url',
|
||||
'path',
|
||||
);
|
||||
|
||||
/**
|
||||
* The cache key for the compatible plugins.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected const CACHE_KEY = 'akismet_compatible_plugin_list';
|
||||
|
||||
|
||||
/**
|
||||
* How many plugins should be visible by default?
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public const DEFAULT_VISIBLE_PLUGIN_COUNT = 2;
|
||||
|
||||
/**
|
||||
* Get the list of active, installed compatible plugins.
|
||||
*
|
||||
* @param bool $bypass_cache Whether to bypass the cache and fetch fresh data.
|
||||
* @return WP_Error|array {
|
||||
* Array of active, installed compatible plugins with their metadata.
|
||||
* @type string $name The display name of the plugin
|
||||
* @type string $help_url URL to the plugin's help documentation
|
||||
* @type string $logo URL or path to the plugin's logo
|
||||
* }
|
||||
*/
|
||||
public static function get_installed_compatible_plugins( bool $bypass_cache = false ) {
|
||||
// Retrieve and validate the full compatible plugins list.
|
||||
$compatible_plugins = static::get_compatible_plugins( $bypass_cache );
|
||||
|
||||
if ( empty( $compatible_plugins ) ) {
|
||||
return new WP_Error(
|
||||
self::COMPATIBLE_PLUGIN_API_ERROR,
|
||||
__( 'Error getting compatible plugins.', 'akismet' )
|
||||
);
|
||||
}
|
||||
|
||||
// Retrieve all installed plugins once.
|
||||
$all_plugins = get_plugins();
|
||||
|
||||
// Build list of compatible plugins that are both installed and active.
|
||||
$active_compatible_plugins = array();
|
||||
|
||||
foreach ( $compatible_plugins as $slug => $data ) {
|
||||
$path = $data['path'];
|
||||
// Skip if not installed.
|
||||
if ( ! isset( $all_plugins[ $path ] ) ) {
|
||||
continue;
|
||||
}
|
||||
// Check activation: per-site or network-wide (multisite).
|
||||
$site_active = is_plugin_active( $path );
|
||||
$network_active = is_multisite() && is_plugin_active_for_network( $path );
|
||||
if ( $site_active || $network_active ) {
|
||||
$active_compatible_plugins[ $slug ] = $data;
|
||||
}
|
||||
}
|
||||
|
||||
return $active_compatible_plugins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes action hooks for the class.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function init(): void {
|
||||
add_action( 'activated_plugin', array( static::class, 'handle_plugin_change' ), true );
|
||||
add_action( 'deactivated_plugin', array( static::class, 'handle_plugin_change' ), true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles plugin activation and deactivation events.
|
||||
*
|
||||
* @param string $plugin The path to the main plugin file from plugins directory.
|
||||
* @return void
|
||||
*/
|
||||
public static function handle_plugin_change( string $plugin ): void {
|
||||
$cached_plugins = static::get_cached_plugins();
|
||||
|
||||
/**
|
||||
* Terminate if nothing's cached.
|
||||
*/
|
||||
if ( false === $cached_plugins ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$plugin_change_should_invalidate_cache = in_array( $plugin, array_column( $cached_plugins, 'path' ) );
|
||||
|
||||
/**
|
||||
* Purge the cache if the plugin is activated or deactivated.
|
||||
*/
|
||||
if ( $plugin_change_should_invalidate_cache ) {
|
||||
static::purge_cache();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets plugins that are compatible with Akismet from the Akismet API.
|
||||
*
|
||||
* @param bool $bypass_cache Whether to bypass the cache and fetch fresh data.
|
||||
* @return array
|
||||
*/
|
||||
private static function get_compatible_plugins( bool $bypass_cache = false ): array {
|
||||
// Return cached result if present (false => cache miss; empty array is valid).
|
||||
$cached_plugins = static::get_cached_plugins();
|
||||
|
||||
if ( false !== $cached_plugins && ! $bypass_cache ) {
|
||||
return $cached_plugins;
|
||||
}
|
||||
|
||||
$response = wp_remote_get(
|
||||
self::COMPATIBLE_PLUGIN_ENDPOINT
|
||||
);
|
||||
|
||||
$sanitized = static::validate_compatible_plugin_response( $response );
|
||||
|
||||
if ( false === $sanitized ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets local static associative array of plugin data keyed by plugin slug.
|
||||
*/
|
||||
$compatible_plugins = array();
|
||||
|
||||
foreach ( $sanitized as $plugin ) {
|
||||
$compatible_plugins[ $plugin['slug'] ] = $plugin;
|
||||
}
|
||||
|
||||
static::set_cached_plugins( $compatible_plugins );
|
||||
|
||||
return $compatible_plugins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates a response object from the Compatible Plugins API.
|
||||
*
|
||||
* @param array|WP_Error $response
|
||||
* @return array|false
|
||||
*/
|
||||
private static function validate_compatible_plugin_response( $response ) {
|
||||
/**
|
||||
* Terminates the function if the response is a WP_Error object.
|
||||
*/
|
||||
if ( is_wp_error( $response ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* The response returned is an array of header + body string data.
|
||||
* This pops off the body string for processing.
|
||||
*/
|
||||
$response_body = wp_remote_retrieve_body( $response );
|
||||
|
||||
if ( empty( $response_body ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$plugins = json_decode( $response_body, true );
|
||||
|
||||
if ( false === is_array( $plugins ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ( $plugins as $plugin ) {
|
||||
if ( ! is_array( $plugin ) ) {
|
||||
/**
|
||||
* Skips to the next iteration if for some reason the plugin is not an array.
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ensure that the plugin config read in from the API has all the required fields.
|
||||
$plugin_key_count = count(
|
||||
array_intersect_key( $plugin, array_flip( static::COMPATIBLE_PLUGIN_FIELDS ) )
|
||||
);
|
||||
|
||||
$does_not_have_all_required_fields = ! (
|
||||
$plugin_key_count === count( static::COMPATIBLE_PLUGIN_FIELDS )
|
||||
);
|
||||
|
||||
if ( $does_not_have_all_required_fields ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( false === static::has_valid_plugin_path( $plugin['path'] ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return static::sanitize_compatible_plugin_response( $plugins );
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates a plugin path format.
|
||||
*
|
||||
* The path should be in the format of 'plugin-name/plugin-name.php'.
|
||||
* Allows alphanumeric characters, dashes, underscores, and optional dots in folder names.
|
||||
*
|
||||
* @param string $path
|
||||
* @return bool
|
||||
*/
|
||||
private static function has_valid_plugin_path( string $path ): bool {
|
||||
return preg_match( '/^[a-zA-Z0-9._-]+\/[a-zA-Z0-9_-]+\.php$/', $path ) === 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitizes a response object from the Compatible Plugins API.
|
||||
*
|
||||
* @param array $plugins
|
||||
* @return array
|
||||
*/
|
||||
private static function sanitize_compatible_plugin_response( array $plugins = array() ): array {
|
||||
foreach ( $plugins as $key => $plugin ) {
|
||||
$plugins[ $key ] = array_map( 'sanitize_text_field', $plugin );
|
||||
$plugins[ $key ]['help_url'] = sanitize_url( $plugins[ $key ]['help_url'] );
|
||||
$plugins[ $key ]['logo'] = sanitize_url( $plugins[ $key ]['logo'] );
|
||||
}
|
||||
|
||||
return $plugins;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $plugins
|
||||
* @return bool
|
||||
*/
|
||||
private static function set_cached_plugins( array $plugins ): bool {
|
||||
$_blog_id = (int) get_current_blog_id();
|
||||
|
||||
return set_transient(
|
||||
static::CACHE_KEY . "_$_blog_id",
|
||||
$plugins,
|
||||
DAY_IN_SECONDS
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to get cached compatible plugins.
|
||||
*
|
||||
* @return mixed|false
|
||||
*/
|
||||
private static function get_cached_plugins() {
|
||||
$_blog_id = (int) get_current_blog_id();
|
||||
|
||||
return get_transient(
|
||||
static::CACHE_KEY . "_$_blog_id"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Purges the cache for the compatible plugins.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private static function purge_cache(): bool {
|
||||
$_blog_id = (int) get_current_blog_id();
|
||||
|
||||
return delete_transient(
|
||||
static::CACHE_KEY . "_$_blog_id"
|
||||
);
|
||||
}
|
||||
}
|
||||
1637
wp-content/plugins/akismet/class.akismet-admin.php
Normal file
186
wp-content/plugins/akismet/class.akismet-cli.php
Normal file
@@ -0,0 +1,186 @@
|
||||
<?php
|
||||
|
||||
WP_CLI::add_command( 'akismet', 'Akismet_CLI' );
|
||||
|
||||
/**
|
||||
* Filter spam comments.
|
||||
*/
|
||||
class Akismet_CLI extends WP_CLI_Command {
|
||||
/**
|
||||
* Checks one or more comments against the Akismet API.
|
||||
*
|
||||
* ## OPTIONS
|
||||
* <comment_id>...
|
||||
* : The ID(s) of the comment(s) to check.
|
||||
*
|
||||
* [--noaction]
|
||||
* : Don't change the status of the comment. Just report what Akismet thinks it is.
|
||||
*
|
||||
* ## EXAMPLES
|
||||
*
|
||||
* wp akismet check 12345
|
||||
*
|
||||
* @alias comment-check
|
||||
*/
|
||||
public function check( $args, $assoc_args ) {
|
||||
foreach ( $args as $comment_id ) {
|
||||
if ( isset( $assoc_args['noaction'] ) ) {
|
||||
// Check the comment, but don't reclassify it.
|
||||
$api_response = Akismet::check_db_comment( $comment_id, 'wp-cli' );
|
||||
} else {
|
||||
$api_response = Akismet::recheck_comment( $comment_id, 'wp-cli' );
|
||||
}
|
||||
|
||||
if ( 'true' === $api_response ) {
|
||||
/* translators: %d: Comment ID. */
|
||||
WP_CLI::line( sprintf( __( 'Comment #%d is spam.', 'akismet' ), $comment_id ) );
|
||||
} elseif ( 'false' === $api_response ) {
|
||||
/* translators: %d: Comment ID. */
|
||||
WP_CLI::line( sprintf( __( 'Comment #%d is not spam.', 'akismet' ), $comment_id ) );
|
||||
} elseif ( false === $api_response ) {
|
||||
/* translators: %d: Comment ID. */
|
||||
WP_CLI::error( __( 'Failed to connect to Akismet.', 'akismet' ) );
|
||||
} elseif ( is_wp_error( $api_response ) ) {
|
||||
/* translators: %d: Comment ID. */
|
||||
WP_CLI::warning( sprintf( __( 'Comment #%d could not be checked.', 'akismet' ), $comment_id ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recheck all comments in the Pending queue.
|
||||
*
|
||||
* ## EXAMPLES
|
||||
*
|
||||
* wp akismet recheck_queue
|
||||
*
|
||||
* @alias recheck-queue
|
||||
*/
|
||||
public function recheck_queue() {
|
||||
$batch_size = 100;
|
||||
$start = 0;
|
||||
|
||||
$total_counts = array();
|
||||
|
||||
do {
|
||||
$result_counts = Akismet_Admin::recheck_queue_portion( $start, $batch_size );
|
||||
|
||||
if ( $result_counts['processed'] > 0 ) {
|
||||
foreach ( $result_counts as $key => $count ) {
|
||||
if ( ! isset( $total_counts[ $key ] ) ) {
|
||||
$total_counts[ $key ] = $count;
|
||||
} else {
|
||||
$total_counts[ $key ] += $count;
|
||||
}
|
||||
}
|
||||
$start += $batch_size;
|
||||
$start -= $result_counts['spam']; // These comments will have been removed from the queue.
|
||||
}
|
||||
} while ( $result_counts['processed'] > 0 );
|
||||
|
||||
/* translators: %d: Number of comments. */
|
||||
WP_CLI::line( sprintf( _n( 'Processed %d comment.', 'Processed %d comments.', $total_counts['processed'], 'akismet' ), number_format( $total_counts['processed'] ) ) );
|
||||
|
||||
/* translators: %d: Number of comments. */
|
||||
WP_CLI::line( sprintf( _n( '%d comment moved to Spam.', '%d comments moved to Spam.', $total_counts['spam'], 'akismet' ), number_format( $total_counts['spam'] ) ) );
|
||||
|
||||
if ( $total_counts['error'] ) {
|
||||
/* translators: %d: Number of comments. */
|
||||
WP_CLI::line( sprintf( _n( '%d comment could not be checked.', '%d comments could not be checked.', $total_counts['error'], 'akismet' ), number_format( $total_counts['error'] ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches stats from the Akismet API.
|
||||
*
|
||||
* ## OPTIONS
|
||||
*
|
||||
* [<interval>]
|
||||
* : The time period for which to retrieve stats.
|
||||
* ---
|
||||
* default: all
|
||||
* options:
|
||||
* - days
|
||||
* - months
|
||||
* - all
|
||||
* ---
|
||||
*
|
||||
* [--format=<format>]
|
||||
* : Allows overriding the output of the command when listing connections.
|
||||
* ---
|
||||
* default: table
|
||||
* options:
|
||||
* - table
|
||||
* - json
|
||||
* - csv
|
||||
* - yaml
|
||||
* - count
|
||||
* ---
|
||||
*
|
||||
* [--summary]
|
||||
* : When set, will display a summary of the stats.
|
||||
*
|
||||
* ## EXAMPLES
|
||||
*
|
||||
* wp akismet stats
|
||||
* wp akismet stats all
|
||||
* wp akismet stats days
|
||||
* wp akismet stats months
|
||||
* wp akismet stats all --summary
|
||||
*/
|
||||
public function stats( $args, $assoc_args ) {
|
||||
$api_key = Akismet::get_api_key();
|
||||
|
||||
if ( empty( $api_key ) ) {
|
||||
WP_CLI::error( __( 'API key must be set to fetch stats.', 'akismet' ) );
|
||||
}
|
||||
|
||||
switch ( $args[0] ) {
|
||||
case 'days':
|
||||
$interval = '60-days';
|
||||
break;
|
||||
case 'months':
|
||||
$interval = '6-months';
|
||||
break;
|
||||
default:
|
||||
$interval = 'all';
|
||||
break;
|
||||
}
|
||||
|
||||
$request_args = array(
|
||||
'blog' => get_option( 'home' ),
|
||||
'key' => $api_key,
|
||||
'from' => $interval,
|
||||
);
|
||||
|
||||
$request_args = apply_filters( 'akismet_request_args', $request_args, 'get-stats' );
|
||||
|
||||
$response = Akismet::http_post( Akismet::build_query( $request_args ), 'get-stats' );
|
||||
|
||||
if ( empty( $response[1] ) ) {
|
||||
WP_CLI::error( __( 'Currently unable to fetch stats. Please try again.', 'akismet' ) );
|
||||
}
|
||||
|
||||
$response_body = json_decode( $response[1], true );
|
||||
|
||||
if ( is_null( $response_body ) ) {
|
||||
WP_CLI::error( __( 'Stats response could not be decoded.', 'akismet' ) );
|
||||
}
|
||||
|
||||
if ( isset( $assoc_args['summary'] ) ) {
|
||||
$keys = array(
|
||||
'spam',
|
||||
'ham',
|
||||
'missed_spam',
|
||||
'false_positives',
|
||||
'accuracy',
|
||||
'time_saved',
|
||||
);
|
||||
|
||||
WP_CLI\Utils\format_items( $assoc_args['format'], array( $response_body ), $keys );
|
||||
} else {
|
||||
$stats = $response_body['breakdown'];
|
||||
WP_CLI\Utils\format_items( $assoc_args['format'], $stats, array_keys( end( $stats ) ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
616
wp-content/plugins/akismet/class.akismet-rest-api.php
Normal file
@@ -0,0 +1,616 @@
|
||||
<?php
|
||||
|
||||
class Akismet_REST_API {
|
||||
/**
|
||||
* Register the REST API routes.
|
||||
*/
|
||||
public static function init() {
|
||||
if ( ! function_exists( 'register_rest_route' ) ) {
|
||||
// The REST API wasn't integrated into core until 4.4, and we support 4.0+ (for now).
|
||||
return false;
|
||||
}
|
||||
|
||||
register_rest_route(
|
||||
'akismet/v1',
|
||||
'/key',
|
||||
array(
|
||||
array(
|
||||
'methods' => WP_REST_Server::READABLE,
|
||||
'permission_callback' => array( 'Akismet_REST_API', 'privileged_permission_callback' ),
|
||||
'callback' => array( 'Akismet_REST_API', 'get_key' ),
|
||||
),
|
||||
array(
|
||||
'methods' => WP_REST_Server::EDITABLE,
|
||||
'permission_callback' => array( 'Akismet_REST_API', 'privileged_permission_callback' ),
|
||||
'callback' => array( 'Akismet_REST_API', 'set_key' ),
|
||||
'args' => array(
|
||||
'key' => array(
|
||||
'required' => true,
|
||||
'type' => 'string',
|
||||
'sanitize_callback' => array( 'Akismet_REST_API', 'sanitize_key' ),
|
||||
'description' => __( 'A 12-character Akismet API key. Available at akismet.com/account', 'akismet' ),
|
||||
),
|
||||
),
|
||||
),
|
||||
array(
|
||||
'methods' => WP_REST_Server::DELETABLE,
|
||||
'permission_callback' => array( 'Akismet_REST_API', 'privileged_permission_callback' ),
|
||||
'callback' => array( 'Akismet_REST_API', 'delete_key' ),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
register_rest_route(
|
||||
'akismet/v1',
|
||||
'/settings/',
|
||||
array(
|
||||
array(
|
||||
'methods' => WP_REST_Server::READABLE,
|
||||
'permission_callback' => array( 'Akismet_REST_API', 'privileged_permission_callback' ),
|
||||
'callback' => array( 'Akismet_REST_API', 'get_settings' ),
|
||||
),
|
||||
array(
|
||||
'methods' => WP_REST_Server::EDITABLE,
|
||||
'permission_callback' => array( 'Akismet_REST_API', 'privileged_permission_callback' ),
|
||||
'callback' => array( 'Akismet_REST_API', 'set_boolean_settings' ),
|
||||
'args' => array(
|
||||
'akismet_strictness' => array(
|
||||
'required' => false,
|
||||
'type' => 'boolean',
|
||||
'description' => __( 'If true, Akismet will automatically discard the worst spam automatically rather than putting it in the spam folder.', 'akismet' ),
|
||||
),
|
||||
'akismet_show_user_comments_approved' => array(
|
||||
'required' => false,
|
||||
'type' => 'boolean',
|
||||
'description' => __( 'If true, show the number of approved comments beside each comment author in the comments list page.', 'akismet' ),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
register_rest_route(
|
||||
'akismet/v1',
|
||||
'/stats',
|
||||
array(
|
||||
'methods' => WP_REST_Server::READABLE,
|
||||
'permission_callback' => array( 'Akismet_REST_API', 'privileged_permission_callback' ),
|
||||
'callback' => array( 'Akismet_REST_API', 'get_stats' ),
|
||||
'args' => array(
|
||||
'interval' => array(
|
||||
'required' => false,
|
||||
'type' => 'string',
|
||||
'sanitize_callback' => array( 'Akismet_REST_API', 'sanitize_interval' ),
|
||||
'description' => __( 'The time period for which to retrieve stats. Options: 60-days, 6-months, all', 'akismet' ),
|
||||
'default' => 'all',
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
register_rest_route(
|
||||
'akismet/v1',
|
||||
'/stats/(?P<interval>[\w+])',
|
||||
array(
|
||||
'args' => array(
|
||||
'interval' => array(
|
||||
'description' => __( 'The time period for which to retrieve stats. Options: 60-days, 6-months, all', 'akismet' ),
|
||||
'type' => 'string',
|
||||
),
|
||||
),
|
||||
array(
|
||||
'methods' => WP_REST_Server::READABLE,
|
||||
'permission_callback' => array( 'Akismet_REST_API', 'privileged_permission_callback' ),
|
||||
'callback' => array( 'Akismet_REST_API', 'get_stats' ),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
register_rest_route(
|
||||
'akismet/v1',
|
||||
'/alert',
|
||||
array(
|
||||
array(
|
||||
'methods' => WP_REST_Server::READABLE,
|
||||
'permission_callback' => array( 'Akismet_REST_API', 'remote_call_permission_callback' ),
|
||||
'callback' => array( 'Akismet_REST_API', 'get_alert' ),
|
||||
'args' => array(
|
||||
'key' => array(
|
||||
'required' => false,
|
||||
'type' => 'string',
|
||||
'sanitize_callback' => array( 'Akismet_REST_API', 'sanitize_key' ),
|
||||
'description' => __( 'A 12-character Akismet API key. Available at akismet.com/account', 'akismet' ),
|
||||
),
|
||||
),
|
||||
),
|
||||
array(
|
||||
'methods' => WP_REST_Server::EDITABLE,
|
||||
'permission_callback' => array( 'Akismet_REST_API', 'remote_call_permission_callback' ),
|
||||
'callback' => array( 'Akismet_REST_API', 'set_alert' ),
|
||||
'args' => array(
|
||||
'key' => array(
|
||||
'required' => false,
|
||||
'type' => 'string',
|
||||
'sanitize_callback' => array( 'Akismet_REST_API', 'sanitize_key' ),
|
||||
'description' => __( 'A 12-character Akismet API key. Available at akismet.com/account', 'akismet' ),
|
||||
),
|
||||
),
|
||||
),
|
||||
array(
|
||||
'methods' => WP_REST_Server::DELETABLE,
|
||||
'permission_callback' => array( 'Akismet_REST_API', 'remote_call_permission_callback' ),
|
||||
'callback' => array( 'Akismet_REST_API', 'delete_alert' ),
|
||||
'args' => array(
|
||||
'key' => array(
|
||||
'required' => false,
|
||||
'type' => 'string',
|
||||
'sanitize_callback' => array( 'Akismet_REST_API', 'sanitize_key' ),
|
||||
'description' => __( 'A 12-character Akismet API key. Available at akismet.com/account', 'akismet' ),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
register_rest_route(
|
||||
'akismet/v1',
|
||||
'/webhook',
|
||||
array(
|
||||
'methods' => WP_REST_Server::CREATABLE,
|
||||
'callback' => array( 'Akismet_REST_API', 'receive_webhook' ),
|
||||
'permission_callback' => array( 'Akismet_REST_API', 'remote_call_permission_callback' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current Akismet API key.
|
||||
*
|
||||
* @param WP_REST_Request $request
|
||||
* @return WP_Error|WP_REST_Response
|
||||
*/
|
||||
public static function get_key( $request = null ) {
|
||||
return rest_ensure_response( Akismet::get_api_key() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the API key, if possible.
|
||||
*
|
||||
* @param WP_REST_Request $request
|
||||
* @return WP_Error|WP_REST_Response
|
||||
*/
|
||||
public static function set_key( $request ) {
|
||||
if ( defined( 'WPCOM_API_KEY' ) ) {
|
||||
return rest_ensure_response( new WP_Error( 'hardcoded_key', __( 'This site\'s API key is hardcoded and cannot be changed via the API.', 'akismet' ), array( 'status' => 409 ) ) );
|
||||
}
|
||||
|
||||
$new_api_key = $request->get_param( 'key' );
|
||||
|
||||
if ( ! self::key_is_valid( $new_api_key ) ) {
|
||||
return rest_ensure_response( new WP_Error( 'invalid_key', __( 'The value provided is not a valid and registered API key.', 'akismet' ), array( 'status' => 400 ) ) );
|
||||
}
|
||||
|
||||
update_option( 'wordpress_api_key', $new_api_key );
|
||||
|
||||
return self::get_key();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unset the API key, if possible.
|
||||
*
|
||||
* @param WP_REST_Request $request
|
||||
* @return WP_Error|WP_REST_Response
|
||||
*/
|
||||
public static function delete_key( $request ) {
|
||||
if ( defined( 'WPCOM_API_KEY' ) ) {
|
||||
return rest_ensure_response( new WP_Error( 'hardcoded_key', __( 'This site\'s API key is hardcoded and cannot be deleted.', 'akismet' ), array( 'status' => 409 ) ) );
|
||||
}
|
||||
|
||||
delete_option( 'wordpress_api_key' );
|
||||
|
||||
return rest_ensure_response( true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Akismet settings.
|
||||
*
|
||||
* @param WP_REST_Request $request
|
||||
* @return WP_Error|WP_REST_Response
|
||||
*/
|
||||
public static function get_settings( $request = null ) {
|
||||
return rest_ensure_response(
|
||||
array(
|
||||
'akismet_strictness' => ( get_option( 'akismet_strictness', '1' ) === '1' ),
|
||||
'akismet_show_user_comments_approved' => ( get_option( 'akismet_show_user_comments_approved', '1' ) === '1' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the Akismet settings.
|
||||
*
|
||||
* @param WP_REST_Request $request
|
||||
* @return WP_Error|WP_REST_Response
|
||||
*/
|
||||
public static function set_boolean_settings( $request ) {
|
||||
foreach ( array(
|
||||
'akismet_strictness',
|
||||
'akismet_show_user_comments_approved',
|
||||
) as $setting_key ) {
|
||||
|
||||
$setting_value = $request->get_param( $setting_key );
|
||||
if ( is_null( $setting_value ) ) {
|
||||
// This setting was not specified.
|
||||
continue;
|
||||
}
|
||||
|
||||
// From 4.7+, WP core will ensure that these are always boolean
|
||||
// values because they are registered with 'type' => 'boolean',
|
||||
// but we need to do this ourselves for prior versions.
|
||||
$setting_value = self::parse_boolean( $setting_value );
|
||||
|
||||
update_option( $setting_key, $setting_value ? '1' : '0' );
|
||||
}
|
||||
|
||||
return self::get_settings();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a numeric or string boolean value into a boolean.
|
||||
*
|
||||
* @param mixed $value The value to convert into a boolean.
|
||||
* @return bool The converted value.
|
||||
*/
|
||||
public static function parse_boolean( $value ) {
|
||||
switch ( $value ) {
|
||||
case true:
|
||||
case 'true':
|
||||
case '1':
|
||||
case 1:
|
||||
return true;
|
||||
|
||||
case false:
|
||||
case 'false':
|
||||
case '0':
|
||||
case 0:
|
||||
return false;
|
||||
|
||||
default:
|
||||
return (bool) $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Akismet stats for a given time period.
|
||||
*
|
||||
* Possible `interval` values:
|
||||
* - all
|
||||
* - 60-days
|
||||
* - 6-months
|
||||
*
|
||||
* @param WP_REST_Request $request
|
||||
* @return WP_Error|WP_REST_Response
|
||||
*/
|
||||
public static function get_stats( $request ) {
|
||||
$api_key = Akismet::get_api_key();
|
||||
|
||||
$interval = $request->get_param( 'interval' );
|
||||
|
||||
$stat_totals = array();
|
||||
|
||||
$request_args = array(
|
||||
'blog' => get_option( 'home' ),
|
||||
'key' => $api_key,
|
||||
'from' => $interval,
|
||||
);
|
||||
|
||||
$request_args = apply_filters( 'akismet_request_args', $request_args, 'get-stats' );
|
||||
|
||||
$response = Akismet::http_post( Akismet::build_query( $request_args ), 'get-stats' );
|
||||
|
||||
if ( ! empty( $response[1] ) ) {
|
||||
$stat_totals[ $interval ] = json_decode( $response[1] );
|
||||
}
|
||||
|
||||
return rest_ensure_response( $stat_totals );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current alert code and message. Alert codes are used to notify the site owner
|
||||
* if there's a problem, like a connection issue between their site and the Akismet API,
|
||||
* invalid requests being sent, etc.
|
||||
*
|
||||
* @param WP_REST_Request $request
|
||||
* @return WP_Error|WP_REST_Response
|
||||
*/
|
||||
public static function get_alert( $request ) {
|
||||
return rest_ensure_response(
|
||||
array(
|
||||
'code' => get_option( 'akismet_alert_code' ),
|
||||
'message' => get_option( 'akismet_alert_msg' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the current alert code and message by triggering a call to the Akismet server.
|
||||
*
|
||||
* @param WP_REST_Request $request
|
||||
* @return WP_Error|WP_REST_Response
|
||||
*/
|
||||
public static function set_alert( $request ) {
|
||||
delete_option( 'akismet_alert_code' );
|
||||
delete_option( 'akismet_alert_msg' );
|
||||
|
||||
// Make a request so the most recent alert code and message are retrieved.
|
||||
Akismet::verify_key( Akismet::get_api_key() );
|
||||
|
||||
return self::get_alert( $request );
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the current alert code and message.
|
||||
*
|
||||
* @param WP_REST_Request $request
|
||||
* @return WP_Error|WP_REST_Response
|
||||
*/
|
||||
public static function delete_alert( $request ) {
|
||||
delete_option( 'akismet_alert_code' );
|
||||
delete_option( 'akismet_alert_msg' );
|
||||
|
||||
return self::get_alert( $request );
|
||||
}
|
||||
|
||||
private static function key_is_valid( $key ) {
|
||||
$request_args = array(
|
||||
'key' => $key,
|
||||
'blog' => get_option( 'home' ),
|
||||
);
|
||||
|
||||
$request_args = apply_filters( 'akismet_request_args', $request_args, 'verify-key' );
|
||||
|
||||
$response = Akismet::http_post( Akismet::build_query( $request_args ), 'verify-key' );
|
||||
|
||||
if ( $response[1] == 'valid' ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function privileged_permission_callback() {
|
||||
return current_user_can( 'manage_options' );
|
||||
}
|
||||
|
||||
/**
|
||||
* For calls that Akismet.com makes to the site to clear outdated alert codes, use the API key for authorization.
|
||||
*/
|
||||
public static function remote_call_permission_callback( $request ) {
|
||||
$local_key = Akismet::get_api_key();
|
||||
|
||||
return $local_key && ( strtolower( $request->get_param( 'key' ) ?? '' ) === strtolower( $local_key ) );
|
||||
}
|
||||
|
||||
public static function sanitize_interval( $interval, $request, $param ) {
|
||||
$interval = trim( $interval );
|
||||
|
||||
$valid_intervals = array( '60-days', '6-months', 'all' );
|
||||
|
||||
if ( ! in_array( $interval, $valid_intervals ) ) {
|
||||
$interval = 'all';
|
||||
}
|
||||
|
||||
return $interval;
|
||||
}
|
||||
|
||||
public static function sanitize_key( $key, $request, $param ) {
|
||||
return trim( $key );
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a webhook request from the Akismet servers.
|
||||
*
|
||||
* @param WP_REST_Request $request
|
||||
* @return WP_Error|WP_REST_Response
|
||||
*/
|
||||
public static function receive_webhook( $request ) {
|
||||
Akismet::log( array( 'Webhook request received', $request->get_body() ) );
|
||||
|
||||
/**
|
||||
* The request body should look like this:
|
||||
* array(
|
||||
* 'key' => '1234567890abcd',
|
||||
* 'endpoint' => '[comment-check|submit-ham|submit-spam]',
|
||||
* 'comments' => array(
|
||||
* array(
|
||||
* 'guid' => '[...]',
|
||||
* 'result' => '[true|false]',
|
||||
* 'comment_author' => '[...]',
|
||||
* [...]
|
||||
* ),
|
||||
* array(
|
||||
* 'guid' => '[...]',
|
||||
* [...],
|
||||
* ),
|
||||
* [...]
|
||||
* )
|
||||
* )
|
||||
*
|
||||
* Multiple comments can be included in each request, and the only truly required
|
||||
* field for each is the guid, although it would be friendly to include also
|
||||
* comment_post_ID, comment_parent, and comment_author_email, if possible to make
|
||||
* searching easier.
|
||||
*/
|
||||
|
||||
// The response will include statuses for the result of each comment that was supplied.
|
||||
$response = array(
|
||||
'comments' => array(),
|
||||
);
|
||||
|
||||
$endpoint = $request->get_param( 'endpoint' );
|
||||
|
||||
switch ( $endpoint ) {
|
||||
case 'comment-check':
|
||||
$webhook_comments = $request->get_param( 'comments' );
|
||||
|
||||
if ( ! is_array( $webhook_comments ) ) {
|
||||
return rest_ensure_response( new WP_Error( 'malformed_request', __( 'The \'comments\' parameter must be an array.', 'akismet' ), array( 'status' => 400 ) ) );
|
||||
}
|
||||
|
||||
foreach ( $webhook_comments as $webhook_comment ) {
|
||||
$guid = $webhook_comment['guid'];
|
||||
|
||||
if ( ! $guid ) {
|
||||
// Without the GUID, we can't be sure that we're matching the right comment.
|
||||
// We'll make it a rule that any comment without a GUID is ignored intentionally.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Search on the fields that are indexed in the comments table, plus the GUID.
|
||||
// The GUID is the only thing we really need to search on, but comment_meta
|
||||
// is not indexed in a useful way if there are many many comments. This
|
||||
// should help narrow it down first.
|
||||
$queryable_fields = array(
|
||||
'comment_post_ID' => 'post_id',
|
||||
'comment_parent' => 'parent',
|
||||
'comment_author_email' => 'author_email',
|
||||
);
|
||||
|
||||
$query_args = array();
|
||||
$query_args['status'] = 'any';
|
||||
$query_args['meta_key'] = 'akismet_guid';
|
||||
$query_args['meta_value'] = $guid;
|
||||
|
||||
foreach ( $queryable_fields as $queryable_field => $wp_comment_query_field ) {
|
||||
if ( isset( $webhook_comment[ $queryable_field ] ) ) {
|
||||
$query_args[ $wp_comment_query_field ] = $webhook_comment[ $queryable_field ];
|
||||
}
|
||||
}
|
||||
|
||||
$comments_query = new WP_Comment_Query( $query_args );
|
||||
$comments = $comments_query->comments;
|
||||
|
||||
if ( ! $comments ) {
|
||||
// Unexpected, although the comment could have been deleted since being submitted.
|
||||
Akismet::log( 'Webhook failed: no matching comment found.' );
|
||||
|
||||
$response['comments'][ $guid ] = array(
|
||||
'status' => 'error',
|
||||
'message' => __( 'Could not find matching comment.', 'akismet' ),
|
||||
);
|
||||
|
||||
continue;
|
||||
} if ( count( $comments ) > 1 ) {
|
||||
// Two comments shouldn't be able to match the same GUID.
|
||||
Akismet::log( 'Webhook failed: multiple matching comments found.', $comments );
|
||||
|
||||
$response['comments'][ $guid ] = array(
|
||||
'status' => 'error',
|
||||
'message' => __( 'Multiple comments matched request.', 'akismet' ),
|
||||
);
|
||||
|
||||
continue;
|
||||
} else {
|
||||
// We have one single match, as hoped for.
|
||||
Akismet::log( 'Found matching comment.', $comments );
|
||||
|
||||
$comment = $comments[0];
|
||||
|
||||
$current_status = wp_get_comment_status( $comment );
|
||||
|
||||
$result = $webhook_comment['result'];
|
||||
|
||||
if ( 'true' == $result ) {
|
||||
Akismet::log( 'Comment should be spam' );
|
||||
|
||||
// The comment should be classified as spam.
|
||||
if ( 'spam' != $current_status ) {
|
||||
// The comment is not classified as spam. If Akismet was the one to act on it, move it to spam.
|
||||
if ( Akismet::last_comment_status_change_came_from_akismet( $comment->comment_ID ) ) {
|
||||
Akismet::log( 'Comment is not spam; marking as spam.' );
|
||||
|
||||
wp_spam_comment( $comment );
|
||||
Akismet::update_comment_history( $comment->comment_ID, '', 'webhook-spam' );
|
||||
} else {
|
||||
Akismet::log( 'Comment is not spam, but it has already been manually handled by some other process.' );
|
||||
Akismet::update_comment_history( $comment->comment_ID, '', 'webhook-spam-noaction' );
|
||||
}
|
||||
}
|
||||
} elseif ( 'false' == $result ) {
|
||||
Akismet::log( 'Comment should be ham' );
|
||||
|
||||
// The comment should be classified as ham.
|
||||
if ( 'spam' == $current_status ) {
|
||||
Akismet::log( 'Comment is spam.' );
|
||||
|
||||
// The comment is classified as spam. If Akismet was the one to label it as spam, unspam it.
|
||||
if ( Akismet::last_comment_status_change_came_from_akismet( $comment->comment_ID ) ) {
|
||||
Akismet::log( 'Akismet marked it as spam; unspamming.' );
|
||||
|
||||
wp_unspam_comment( $comment );
|
||||
|
||||
akismet::update_comment_history( $comment->comment_ID, '', 'webhook-ham' );
|
||||
} else {
|
||||
Akismet::log( 'Comment is not spam, but it has already been manually handled by some other process.' );
|
||||
Akismet::update_comment_history( $comment->comment_ID, '', 'webhook-ham-noaction' );
|
||||
}
|
||||
} else if ( 'unapproved' == $current_status ) {
|
||||
Akismet::log( 'Comment is pending.' );
|
||||
|
||||
// The comment is in Pending. If Akismet was the one to put it there, approve it (but only if the site
|
||||
// settings dictate that).
|
||||
if ( Akismet::last_comment_status_change_came_from_akismet( $comment->comment_ID ) ) {
|
||||
Akismet::log( 'Akismet marked it as Pending; approving.' );
|
||||
|
||||
if ( check_comment( $comment->comment_author, $comment->comment_author_email, $comment->comment_author_url, $comment->comment_content, $comment->comment_author_IP, $comment->comment_agent, $comment->comment_type ) ) {
|
||||
wp_set_comment_status( $comment->comment_ID, 1 );
|
||||
}
|
||||
|
||||
akismet::update_comment_history( $comment->comment_ID, '', 'webhook-ham' );
|
||||
} else {
|
||||
Akismet::log( 'Comment is not spam, but it has already been manually handled by some other process.' );
|
||||
Akismet::update_comment_history( $comment->comment_ID, '', 'webhook-ham-noaction' );
|
||||
}
|
||||
}
|
||||
|
||||
$moderation_email_was_delayed = get_comment_meta( $comment->comment_ID, 'akismet_delayed_moderation_email', true );
|
||||
|
||||
if ( $moderation_email_was_delayed ) {
|
||||
Akismet::log( 'Moderation email was delayed for comment #' . $comment->comment_ID . '; sending now.' );
|
||||
|
||||
delete_comment_meta( $comment->comment_ID, 'akismet_delayed_moderation_email' );
|
||||
wp_new_comment_notify_moderator( $comment->comment_ID );
|
||||
wp_new_comment_notify_postauthor( $comment->comment_ID );
|
||||
}
|
||||
|
||||
delete_comment_meta( $comment->comment_ID, 'akismet_delay_moderation_email' );
|
||||
}
|
||||
|
||||
$response['comments'][ $guid ] = array( 'status' => 'success' );
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case 'submit-ham':
|
||||
case 'submit-spam':
|
||||
// Nothing to do for submit-ham or submit-spam.
|
||||
break;
|
||||
default:
|
||||
// Unsupported endpoint.
|
||||
break;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow plugins to do things with a successfully processed webhook request, like logging.
|
||||
*
|
||||
* @since 5.3.2
|
||||
*
|
||||
* @param WP_REST_Request $request The REST request object.
|
||||
*/
|
||||
do_action( 'akismet_webhook_received', $request );
|
||||
|
||||
Akismet::log( 'Done processing webhook.' );
|
||||
|
||||
return rest_ensure_response( $response );
|
||||
}
|
||||
}
|
||||
177
wp-content/plugins/akismet/class.akismet-widget.php
Normal file
@@ -0,0 +1,177 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Akismet
|
||||
*/
|
||||
|
||||
// We plan to gradually remove all of the disabled lint rules below.
|
||||
// phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
|
||||
/**
|
||||
* Akismet Widget Class
|
||||
*/
|
||||
class Akismet_Widget extends WP_Widget {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
function __construct() {
|
||||
parent::__construct(
|
||||
'akismet_widget',
|
||||
__( 'Akismet Widget', 'akismet' ),
|
||||
array( 'description' => __( 'Display the number of spam comments Akismet has caught', 'akismet' ) )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs the widget settings form
|
||||
*
|
||||
* @param array $instance The widget options
|
||||
*/
|
||||
public function form( $instance ) {
|
||||
if ( $instance && isset( $instance['title'] ) ) {
|
||||
$title = $instance['title'];
|
||||
} else {
|
||||
$title = __( 'Spam Blocked', 'akismet' );
|
||||
}
|
||||
?>
|
||||
|
||||
<p>
|
||||
<label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php esc_html_e( 'Title:', 'akismet' ); ?></label>
|
||||
<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>" />
|
||||
</p>
|
||||
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the widget settings
|
||||
*
|
||||
* @param array $new_instance New widget instance
|
||||
* @param array $old_instance Old widget instance
|
||||
* @return array Updated widget instance
|
||||
*/
|
||||
public function update( $new_instance, $old_instance ) {
|
||||
$instance = array();
|
||||
$instance['title'] = sanitize_text_field( $new_instance['title'] );
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs the widget content
|
||||
*
|
||||
* @param array $args Widget arguments
|
||||
* @param array $instance Widget instance
|
||||
*/
|
||||
public function widget( $args, $instance ) {
|
||||
$count = get_option( 'akismet_spam_count' );
|
||||
|
||||
if ( ! isset( $instance['title'] ) ) {
|
||||
$instance['title'] = __( 'Spam Blocked', 'akismet' );
|
||||
}
|
||||
|
||||
echo $args['before_widget'];
|
||||
if ( ! empty( $instance['title'] ) ) {
|
||||
echo $args['before_title'];
|
||||
echo esc_html( $instance['title'] );
|
||||
echo $args['after_title'];
|
||||
}
|
||||
?>
|
||||
|
||||
<style>
|
||||
.a-stats {
|
||||
--akismet-color-mid-green: #357b49;
|
||||
--akismet-color-white: #fff;
|
||||
--akismet-color-light-grey: #f6f7f7;
|
||||
|
||||
max-width: 350px;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.a-stats * {
|
||||
all: unset;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.a-stats strong {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.a-stats a.a-stats__link,
|
||||
.a-stats a.a-stats__link:visited,
|
||||
.a-stats a.a-stats__link:active {
|
||||
background: var(--akismet-color-mid-green);
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
border-radius: 8px;
|
||||
color: var(--akismet-color-white);
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen-Sans', 'Ubuntu', 'Cantarell', 'Helvetica Neue', sans-serif;
|
||||
font-weight: 500;
|
||||
padding: 12px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
/* Extra specificity to deal with TwentyTwentyOne focus style */
|
||||
.widget .a-stats a.a-stats__link:focus {
|
||||
background: var(--akismet-color-mid-green);
|
||||
color: var(--akismet-color-white);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.a-stats a.a-stats__link:hover {
|
||||
filter: brightness(110%);
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.06), 0 0 2px rgba(0, 0, 0, 0.16);
|
||||
}
|
||||
|
||||
.a-stats .count {
|
||||
color: var(--akismet-color-white);
|
||||
display: block;
|
||||
font-size: 1.5em;
|
||||
line-height: 1.4;
|
||||
padding: 0 13px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="a-stats">
|
||||
<a href="https://akismet.com?utm_source=akismet_plugin&utm_campaign=plugin_static_link&utm_medium=in_plugin&utm_content=widget_stats" class="a-stats__link" target="_blank" rel="noopener" style="background-color: var(--akismet-color-mid-green); color: var(--akismet-color-white);">
|
||||
<?php
|
||||
|
||||
echo wp_kses(
|
||||
sprintf(
|
||||
/* translators: The placeholder is the number of pieces of spam blocked by Akismet. */
|
||||
_n(
|
||||
'<strong class="count">%1$s spam</strong> blocked by <strong>Akismet</strong>',
|
||||
'<strong class="count">%1$s spam</strong> blocked by <strong>Akismet</strong>',
|
||||
$count,
|
||||
'akismet'
|
||||
),
|
||||
number_format_i18n( $count )
|
||||
),
|
||||
array(
|
||||
'strong' => array(
|
||||
'class' => true,
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
?>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
echo $args['after_widget'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the Akismet widget
|
||||
*/
|
||||
function akismet_register_widgets() {
|
||||
register_widget( 'Akismet_Widget' );
|
||||
}
|
||||
|
||||
add_action( 'widgets_init', 'akismet_register_widgets' );
|
||||
2242
wp-content/plugins/akismet/class.akismet.php
Normal file
4
wp-content/plugins/akismet/index.php
Normal file
@@ -0,0 +1,4 @@
|
||||
<?php
|
||||
declare( strict_types = 1 );
|
||||
|
||||
// Silence is golden.
|
||||
149
wp-content/plugins/akismet/readme.txt
Normal file
@@ -0,0 +1,149 @@
|
||||
=== Akismet Anti-spam: Spam Protection ===
|
||||
Contributors: matt, ryan, andy, mdawaffe, tellyworth, josephscott, lessbloat, eoigal, cfinke, automattic, jgs, procifer, stephdau, kbrownkd, bluefuton, derekspringer, lschuyler, andyperdomo, akismetantispam
|
||||
Tags: comments, spam, antispam, anti-spam, contact form
|
||||
Requires at least: 5.8
|
||||
Tested up to: 6.9
|
||||
Stable tag: 5.6
|
||||
License: GPLv2 or later
|
||||
|
||||
The best anti-spam protection to block spam comments and spam in a contact form. The most trusted antispam solution for WordPress and WooCommerce.
|
||||
|
||||
== Description ==
|
||||
|
||||
The best anti-spam protection to block spam comments and spam in a contact form. The most trusted antispam solution for WordPress and WooCommerce.
|
||||
|
||||
Akismet checks your comments and contact form submissions against our global database of spam to prevent your site from publishing malicious content. You can review the comment spam it catches on your blog's "Comments" admin screen.
|
||||
|
||||
Major features in Akismet include:
|
||||
|
||||
* Automatically checks all comments and filters out the ones that look like spam.
|
||||
* Each comment has a status history, so you can easily see which comments were caught or cleared by Akismet and which were spammed or unspammed by a moderator.
|
||||
* URLs are shown in the comment body to reveal hidden or misleading links.
|
||||
* Moderators can see the number of approved comments for each user.
|
||||
* A discard feature that outright blocks the worst spam, saving you disk space and speeding up your site.
|
||||
|
||||
PS: You'll be prompted to get an Akismet.com API key to use it, once activated. Keys are free for personal blogs; paid subscriptions are available for businesses and commercial sites.
|
||||
|
||||
== Installation ==
|
||||
|
||||
Upload the Akismet plugin to your blog, activate it, and then enter your Akismet.com API key.
|
||||
|
||||
1, 2, 3: You're done!
|
||||
|
||||
== Changelog ==
|
||||
|
||||
= 5.6 =
|
||||
*Release Date - 12 November 2025*
|
||||
|
||||
* Improve caching of compatible plugins.
|
||||
* Explain the key features of Akismet more clearly on the setup page.
|
||||
* Improve the configuration process to better explain errors when they occur.
|
||||
* UI cleanup and refresh
|
||||
* Improve messaging related to usage limits.
|
||||
|
||||
= 5.5 =
|
||||
*Release Date - 15 July 2025*
|
||||
|
||||
* Enable webhooks so that Akismet can process comments asynchronously to detect more types of spam.
|
||||
* Only include the Akismet widget CSS when the Akismet widget is present
|
||||
* Improve contrast/readability for certain UI elements
|
||||
|
||||
= 5.4 =
|
||||
*Release Date - 7 May 2025*
|
||||
|
||||
* The stats pages now use the user's locale instead of the site's locale if they're different.
|
||||
* Adds a 'Compatible plugins' section that will show installed and active plugins that are compatible with Akismet.
|
||||
* Akismet now requires PHP version 7.2 or above.
|
||||
|
||||
= 5.3.7 =
|
||||
*Release Date - 14 February 2025*
|
||||
|
||||
* Simplify the logic used during a comment-check request to compare comments.
|
||||
|
||||
= 5.3.6 =
|
||||
*Release Date - 4 February 2025*
|
||||
|
||||
* Improve the utility of submit-spam and submit-ham requests.
|
||||
* Modernize styles for the Akismet classic widget.
|
||||
|
||||
= 5.3.5 =
|
||||
*Release Date - 18 November 2024*
|
||||
|
||||
* Address compatibility issues with < PHP 7.3 in v5.3.4 release.
|
||||
|
||||
= 5.3.4 =
|
||||
*Release Date - 18 November 2024*
|
||||
|
||||
* Improve activation notice on Comments for users who haven't set up their API key yet.
|
||||
* Improve notice about commercial site status.
|
||||
|
||||
= 5.3.3 =
|
||||
*Release Date - 10 July 2024*
|
||||
|
||||
* Make setup step clearer for new users.
|
||||
* Remove the stats section from the configuration page if the site has been revoked from the key.
|
||||
* Skip the Akismet comment check when the comment matches something in the disallowed list.
|
||||
* Prompt users on legacy plans to contact Akismet support for upgrades.
|
||||
|
||||
= 5.3.2 =
|
||||
*Release Date - 21 March 2024*
|
||||
|
||||
* Improve the empty state shown to new users when no spam has been caught yet.
|
||||
* Update the message shown to users without a current subscription.
|
||||
* Add foundations for future webhook support.
|
||||
|
||||
= 5.3.1 =
|
||||
*Release Date - 17 January 2024*
|
||||
|
||||
* Make the plugin more resilient when asset files are missing (as seen in WordPress Playground).
|
||||
* Add a link to the 'Account overview' page on akismet.com.
|
||||
* Fix a minor error that occurs when another plugin removes all comment actions from the dashboard.
|
||||
* Add the akismet_request_args filter to allow request args in Akismet API requests to be filtered.
|
||||
* Fix a bug that causes some contact forms to include unnecessary data in the comment_content parameter.
|
||||
|
||||
= 5.3 =
|
||||
*Release Date - 14 September 2023*
|
||||
|
||||
* Improve display of user notices.
|
||||
* Add stylesheets for RTL languages.
|
||||
* Remove initial disabled state from 'Save changes' button.
|
||||
* Improve accessibility of API key entry form.
|
||||
* Add new filter hooks for Fluent Forms.
|
||||
* Fix issue with PHP 8.1 compatibility.
|
||||
|
||||
= 5.2 =
|
||||
*Release Date - 21 June 2023*
|
||||
|
||||
* Visual refresh of Akismet stats.
|
||||
* Improve PHP 8.1 compatibility.
|
||||
* Improve appearance of plugin to match updated stats.
|
||||
* Change minimum supported PHP version to 5.6 to match WordPress.
|
||||
* Drop IE11 support and update minimum WordPress version to 5.8 (where IE11 support was removed from WP Core).
|
||||
|
||||
= 5.1 =
|
||||
*Release Date - 20 March 2023*
|
||||
|
||||
* Removed unnecessary limit notices from admin page.
|
||||
* Improved spam detection by including post taxonomies in the comment-check call.
|
||||
* Removed API keys from stats iframes to avoid possible inadvertent exposure.
|
||||
|
||||
= 5.0.2 =
|
||||
*Release Date - 1 December 2022*
|
||||
|
||||
* Improved compatibility with themes that hide or show UI elements based on mouse movements.
|
||||
* Increased security of API keys by sending them in request bodies instead of subdomains.
|
||||
|
||||
= 5.0.1 =
|
||||
*Release Date - 28 September 2022*
|
||||
|
||||
* Added an empty state for the Statistics section on the admin page.
|
||||
* Fixed a bug that broke some admin page links when Jetpack plugins are active.
|
||||
* Marked some event listeners as passive to improve performance in newer browsers.
|
||||
* Disabled interaction observation on forms that post to other domains.
|
||||
|
||||
= 5.0 =
|
||||
*Release Date - 26 July 2022*
|
||||
|
||||
* Added a new feature to catch spammers by observing how they interact with the page.
|
||||
|
||||
For older changelog entries, please see the [additional changelog.txt file](https://plugins.svn.wordpress.org/akismet/trunk/changelog.txt) delivered with the plugin.
|
||||
7
wp-content/plugins/akismet/views/activate.php
Normal file
@@ -0,0 +1,7 @@
|
||||
<div class="akismet-box">
|
||||
<?php Akismet::view( 'setup' ); ?>
|
||||
</div>
|
||||
|
||||
<div class="akismet-box">
|
||||
<?php Akismet::view( 'enter' ); ?>
|
||||
</div>
|
||||
126
wp-content/plugins/akismet/views/compatible-plugins.php
Normal file
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
|
||||
/** @var array|WP_Error $compatible_plugins */
|
||||
$bypass_cache = ! empty( $_GET['akismet_refresh_compatible_plugins'] );
|
||||
$compatible_plugins = Akismet_Compatible_Plugins::get_installed_compatible_plugins( $bypass_cache );
|
||||
if ( is_array( $compatible_plugins ) ) :
|
||||
|
||||
$compatible_plugin_count = count( $compatible_plugins );
|
||||
?>
|
||||
<div class="akismet-card akismet-compatible-plugins">
|
||||
<div class="akismet-section-header">
|
||||
<h2 class="akismet-section-header__label akismet-compatible-plugins__section-header-label" aria-label="<?php esc_attr_e( 'Compatible plugins (new feature)', 'akismet' ); ?>">
|
||||
<span class="akismet-compatible-plugins__section-header-label-text"><?php esc_html_e( 'Compatible plugins', 'akismet' ); ?></span>
|
||||
<span class="akismet-new-feature"><?php esc_html_e( 'New', 'akismet' ); ?></span>
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div class="akismet-compatible-plugins__content">
|
||||
<?php
|
||||
|
||||
echo '<p>';
|
||||
echo esc_html( __( 'Akismet works with other plugins to keep spam away.', 'akismet' ) );
|
||||
echo '</p>';
|
||||
|
||||
echo '<p>';
|
||||
|
||||
if ( 0 === $compatible_plugin_count ) {
|
||||
echo '<a class="akismet-external-link" href="https://akismet.com/developers/plugins-and-libraries/?utm_source=akismet_plugin&utm_campaign=plugin_static_link&utm_medium=in_plugin&utm_content=compatible_plugins">';
|
||||
echo esc_html( __( 'See supported integrations', 'akismet' ) );
|
||||
echo '</a>';
|
||||
} else {
|
||||
echo esc_html(
|
||||
_n(
|
||||
"This plugin you've installed is compatible. Follow the documentation link to get started.",
|
||||
"These plugins you've installed are compatible. Follow the documentation links to get started.",
|
||||
$compatible_plugin_count,
|
||||
'akismet'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
echo '</p>';
|
||||
|
||||
?>
|
||||
|
||||
<?php if ( ! empty( $compatible_plugins ) ) : ?>
|
||||
<ul class="akismet-compatible-plugins__list" id="akismet-compatible-plugins__list">
|
||||
<?php
|
||||
|
||||
foreach ( $compatible_plugins as $compatible_plugin ) :
|
||||
if ( empty( $compatible_plugin['help_url'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
?>
|
||||
<li class="akismet-compatible-plugins__card">
|
||||
<?php if ( strlen( $compatible_plugin['logo'] ) > 0 ) : ?>
|
||||
<?php
|
||||
|
||||
$logo_alt = sprintf(
|
||||
/* translators: The placeholder is the name of a plugin, like "Jetpack" . */
|
||||
__( '%s logo', 'akismet' ),
|
||||
$compatible_plugin['name']
|
||||
);
|
||||
|
||||
?>
|
||||
<img
|
||||
src="<?php echo esc_url( $compatible_plugin['logo'] ); ?>"
|
||||
alt="<?php echo esc_attr( $logo_alt ); ?>"
|
||||
class="akismet-compatible-plugins__card-logo"
|
||||
width="55"
|
||||
height="55"
|
||||
/>
|
||||
<?php endif ?>
|
||||
<div class="akismet-compatible-plugins__card-detail">
|
||||
<h3 class="akismet-compatible-plugins__card-title"><?php echo esc_html( $compatible_plugin['name'] ); ?></h3>
|
||||
<div class="akismet-compatible-plugins__docs">
|
||||
<a
|
||||
class="akismet-external-link"
|
||||
href="<?php echo esc_url( $compatible_plugin['help_url'] ); ?>"
|
||||
aria-label="
|
||||
<?php
|
||||
|
||||
echo esc_attr(
|
||||
sprintf(
|
||||
/* translators: The placeholder is the name of a plugin, like "Jetpack" . */
|
||||
__( 'Documentation for %s', 'akismet' ),
|
||||
$compatible_plugin['name']
|
||||
)
|
||||
);
|
||||
|
||||
?>
|
||||
"><?php esc_html_e( 'View documentation', 'akismet' ); ?></a>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
|
||||
<?php if ( $compatible_plugin_count > Akismet_Compatible_Plugins::DEFAULT_VISIBLE_PLUGIN_COUNT ) : ?>
|
||||
<button class="akismet-compatible-plugins__show-more"
|
||||
aria-expanded="false"
|
||||
aria-controls="akismet-compatible-plugins__list"
|
||||
data-label-closed="
|
||||
<?php
|
||||
|
||||
/* translators: %d: number of compatible plugins, which is guaranteed to be more than 1. */
|
||||
echo esc_attr( sprintf( __( 'Show all %d plugins', 'akismet' ), $compatible_plugin_count ) );
|
||||
|
||||
?>
|
||||
"
|
||||
data-label-open="<?php echo esc_attr( __( 'Show less', 'akismet' ) ); ?>">
|
||||
<?php
|
||||
|
||||
/* translators: %d: number of compatible plugins, which is guaranteed to be more than 1. */
|
||||
echo esc_html( sprintf( __( 'Show all %d plugins', 'akismet' ), $compatible_plugin_count ) );
|
||||
|
||||
?>
|
||||
</button>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
endif;
|
||||
325
wp-content/plugins/akismet/views/config.php
Normal file
@@ -0,0 +1,325 @@
|
||||
<?php
|
||||
|
||||
//phpcs:disable VariableAnalysis
|
||||
// There are "undefined" variables here because they're defined in the code that includes this file as a template.
|
||||
$kses_allow_link_href = array(
|
||||
'a' => array(
|
||||
'href' => true,
|
||||
),
|
||||
);
|
||||
?>
|
||||
<div id="akismet-plugin-container">
|
||||
<div class="akismet-masthead">
|
||||
<div class="akismet-masthead__inside-container">
|
||||
<?php Akismet::view( 'logo' ); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="akismet-lower">
|
||||
<?php if ( Akismet::get_api_key() ) { ?>
|
||||
<?php Akismet_Admin::display_status(); ?>
|
||||
<?php } ?>
|
||||
<?php if ( ! empty( $notices ) ) { ?>
|
||||
<?php foreach ( $notices as $notice ) { ?>
|
||||
<?php Akismet::view( 'notice', array_merge( $notice, array( 'parent_view' => $name ) ) ); ?>
|
||||
<?php } ?>
|
||||
<?php } ?>
|
||||
|
||||
<?php if ( isset( $stat_totals['all'] ) && isset( $stat_totals['6-months'] ) ) : ?>
|
||||
<div class="akismet-card">
|
||||
<div class="akismet-section-header">
|
||||
<h2 class="akismet-section-header__label">
|
||||
<span><?php esc_html_e( 'Statistics', 'akismet' ); ?></span>
|
||||
</h2>
|
||||
|
||||
<div class="akismet-section-header__actions">
|
||||
<a href="<?php echo esc_url( Akismet_Admin::get_page_url( 'stats' ) ); ?>">
|
||||
<?php esc_html_e( 'Detailed stats', 'akismet' ); ?>
|
||||
</a>
|
||||
</div>
|
||||
</div> <!-- close akismet-section-header -->
|
||||
|
||||
<div class="akismet-new-snapshot">
|
||||
<?php /* name attribute on iframe is used as a cache-buster here to force Firefox to load the new style charts: https://bugzilla.mozilla.org/show_bug.cgi?id=356558 */ ?>
|
||||
<div class="akismet-new-snapshot__chart">
|
||||
<iframe id="stats-iframe" allowtransparency="true" scrolling="no" frameborder="0" style="width: 100%; height: 220px; overflow: hidden;" src="<?php echo esc_url( sprintf( 'https://tools.akismet.com/1.0/snapshot.php?blog=%s&token=%s&height=200&locale=%s&is_redecorated=1', rawurlencode( get_option( 'home' ) ), rawurlencode( Akismet::get_access_token() ), get_user_locale() ) ); ?>" name="<?php echo esc_attr( 'snapshot-' . filemtime( __FILE__ ) ); ?>" title="<?php echo esc_attr__( 'Akismet stats', 'akismet' ); ?>"></iframe>
|
||||
</div>
|
||||
|
||||
<ul class="akismet-new-snapshot__list">
|
||||
<li class="akismet-new-snapshot__item">
|
||||
<h3 class="akismet-new-snapshot__header"><?php esc_html_e( 'Past six months', 'akismet' ); ?></h3>
|
||||
<span class="akismet-new-snapshot__number"><?php echo number_format( $stat_totals['6-months']->spam ); ?></span>
|
||||
<span class="akismet-new-snapshot__text"><?php echo esc_html( _n( 'Spam blocked', 'Spam blocked', $stat_totals['6-months']->spam, 'akismet' ) ); ?></span>
|
||||
</li>
|
||||
<li class="akismet-new-snapshot__item">
|
||||
<h3 class="akismet-new-snapshot__header"><?php esc_html_e( 'All time', 'akismet' ); ?></h3>
|
||||
<span class="akismet-new-snapshot__number"><?php echo number_format( $stat_totals['all']->spam ); ?></span>
|
||||
<span class="akismet-new-snapshot__text"><?php echo esc_html( _n( 'Spam blocked', 'Spam blocked', $stat_totals['all']->spam, 'akismet' ) ); ?></span>
|
||||
</li>
|
||||
<li class="akismet-new-snapshot__item">
|
||||
<h3 class="akismet-new-snapshot__header"><?php esc_html_e( 'Accuracy', 'akismet' ); ?></h3>
|
||||
<span class="akismet-new-snapshot__number"><?php echo floatval( $stat_totals['all']->accuracy ); ?>%</span>
|
||||
<span class="akismet-new-snapshot__text">
|
||||
<?php
|
||||
/* translators: %s: number of spam missed by Akismet */
|
||||
echo esc_html( sprintf( _n( '%s missed spam', '%s missed spam', $stat_totals['all']->missed_spam, 'akismet' ), number_format( $stat_totals['all']->missed_spam ) ) ) . ', ';
|
||||
/* translators: %s: number of false positive spam flagged by Akismet */
|
||||
echo esc_html( sprintf( _n( '%s false positive', '%s false positives', $stat_totals['all']->false_positives, 'akismet' ), number_format( $stat_totals['all']->false_positives ) ) );
|
||||
?>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div> <!-- close akismet-new-snapshot -->
|
||||
</div> <!-- close akismet-card -->
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ( apply_filters( 'akismet_show_compatible_plugins', true ) ) : ?>
|
||||
<?php Akismet::view( 'compatible-plugins' ); ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ( $akismet_user ) : ?>
|
||||
<div class="akismet-card">
|
||||
<div class="akismet-section-header">
|
||||
<h2 class="akismet-section-header__label">
|
||||
<span><?php esc_html_e( 'Settings', 'akismet' ); ?></span>
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div class="inside">
|
||||
<form action="<?php echo esc_url( Akismet_Admin::get_page_url() ); ?>" autocomplete="off" method="POST" id="akismet-settings-form">
|
||||
|
||||
<div class="akismet-settings">
|
||||
<?php if ( ! Akismet::predefined_api_key() ) : ?>
|
||||
<div class="akismet-settings__row">
|
||||
<h3 class="akismet-settings__row-title">
|
||||
<label class="akismet-settings__row-label" for="key"><?php esc_html_e( 'API key', 'akismet' ); ?></label>
|
||||
</h3>
|
||||
<div class="akismet-settings__row-input">
|
||||
<span class="api-key"><input id="key" name="key" type="text" size="15" value="<?php echo esc_attr( get_option( 'wordpress_api_key' ) ); ?>" class="<?php echo esc_attr( 'regular-text code ' . $akismet_user->status ); ?>"></span>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php
|
||||
//phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
||||
if ( isset( $_GET['ssl_status'] ) ) :
|
||||
?>
|
||||
<div class="akismet-settings__row">
|
||||
<div class="akismet-settings__row-text">
|
||||
<h3 class="akismet-settings__row-title"><?php esc_html_e( 'SSL status', 'akismet' ); ?></h3>
|
||||
<div class="akismet-settings__row-description">
|
||||
<?php if ( ! wp_http_supports( array( 'ssl' ) ) ) : ?>
|
||||
<strong><?php esc_html_e( 'Disabled.', 'akismet' ); ?></strong>
|
||||
<?php esc_html_e( 'Your Web server cannot make SSL requests; contact your Web host and ask them to add support for SSL requests.', 'akismet' ); ?>
|
||||
<?php else : ?>
|
||||
<?php $ssl_disabled = get_option( 'akismet_ssl_disabled' ); ?>
|
||||
|
||||
<?php if ( $ssl_disabled ) : ?>
|
||||
<strong><?php esc_html_e( 'Temporarily disabled.', 'akismet' ); ?></strong>
|
||||
<?php esc_html_e( 'Akismet encountered a problem with a previous SSL request and disabled it temporarily. It will begin using SSL for requests again shortly.', 'akismet' ); ?>
|
||||
<?php else : ?>
|
||||
<strong><?php esc_html_e( 'Enabled.', 'akismet' ); ?></strong>
|
||||
<?php esc_html_e( 'All systems functional.', 'akismet' ); ?>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="akismet-settings__row">
|
||||
<div class="akismet-settings__row-text">
|
||||
<h3 class="akismet-settings__row-title"><?php esc_html_e( 'Comments', 'akismet' ); ?></h3>
|
||||
</div>
|
||||
<div class="akismet-settings__row-input">
|
||||
<label class="akismet-settings__row-input-label" for="akismet_show_user_comments_approved">
|
||||
<input
|
||||
name="akismet_show_user_comments_approved"
|
||||
id="akismet_show_user_comments_approved"
|
||||
value="1"
|
||||
type="checkbox"
|
||||
<?php
|
||||
// If the option isn't set, or if it's enabled ('1'), or if it was enabled a long time ago ('true'), check the checkbox.
|
||||
checked( true, ( in_array( get_option( 'akismet_show_user_comments_approved' ), array( false, '1', 'true' ), true ) ) );
|
||||
?>
|
||||
/>
|
||||
<span class="akismet-settings__row-label-text">
|
||||
<?php esc_html_e( 'Show the number of approved comments beside each comment author.', 'akismet' ); ?>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="akismet-settings__row is-radio">
|
||||
<div class="akismet-settings__row-text">
|
||||
<h3 class="akismet-settings__row-title"><?php esc_html_e( 'Spam filtering', 'akismet' ); ?></h3>
|
||||
</div>
|
||||
<div class="akismet-settings__row-input">
|
||||
<fieldset>
|
||||
<legend class="screen-reader-text">
|
||||
<span><?php esc_html_e( 'Akismet Anti-spam strictness', 'akismet' ); ?></span>
|
||||
</legend>
|
||||
<div>
|
||||
<label class="akismet-settings__row-input-label" for="akismet_strictness_1">
|
||||
<input type="radio" name="akismet_strictness" id="akismet_strictness_1" value="1" <?php checked( '1', get_option( 'akismet_strictness' ) ); ?> />
|
||||
<span class="akismet-settings__row-label-text">
|
||||
<?php esc_html_e( 'Silently discard the worst and most pervasive spam so I never see it.', 'akismet' ); ?>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<label class="akismet-settings__row-input-label" for="akismet_strictness_0">
|
||||
<input type="radio" name="akismet_strictness" id="akismet_strictness_0" value="0" <?php checked( true, get_option( 'akismet_strictness' ) !== '1' ); ?> />
|
||||
<span class="akismet-settings__row-label-text">
|
||||
<?php esc_html_e( 'Always put spam in the Spam folder for review.', 'akismet' ); ?>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<div class="akismet-settings__row-note">
|
||||
<strong><?php esc_html_e( 'Note:', 'akismet' ); ?></strong>
|
||||
<?php
|
||||
$delete_interval = max( 1, intval( apply_filters( 'akismet_delete_comment_interval', 15 ) ) );
|
||||
|
||||
$spam_folder_link = sprintf(
|
||||
'<a href="%s">%s</a>',
|
||||
esc_url( admin_url( 'edit-comments.php?comment_status=spam' ) ),
|
||||
esc_html__( 'spam folder', 'akismet' )
|
||||
);
|
||||
|
||||
// The _n() needs to be on one line so the i18n tooling can extract the translator comment.
|
||||
/* translators: %1$s: spam folder link, %2$d: delete interval in days */
|
||||
$delete_message = _n( 'Spam in the %1$s older than %2$d day is deleted automatically.', 'Spam in the %1$s older than %2$d days is deleted automatically.', $delete_interval, 'akismet' );
|
||||
|
||||
printf(
|
||||
wp_kses( $delete_message, $kses_allow_link_href ),
|
||||
wp_kses( $spam_folder_link, $kses_allow_link_href ),
|
||||
esc_html( $delete_interval )
|
||||
);
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="akismet-settings__row is-radio">
|
||||
<div class="akismet-settings__row-text">
|
||||
<h3 class="akismet-settings__row-title"><?php esc_html_e( 'Privacy', 'akismet' ); ?></h3>
|
||||
</div>
|
||||
<div class="akismet-settings__row-input">
|
||||
<fieldset>
|
||||
<legend class="screen-reader-text">
|
||||
<span><?php esc_html_e( 'Akismet privacy notice', 'akismet' ); ?></span>
|
||||
</legend>
|
||||
<div>
|
||||
<label class="akismet-settings__row-input-label" for="akismet_comment_form_privacy_notice_display">
|
||||
<input type="radio" name="akismet_comment_form_privacy_notice" id="akismet_comment_form_privacy_notice_display" value="display" <?php checked( 'display', get_option( 'akismet_comment_form_privacy_notice' ) ); ?> />
|
||||
<span class="akismet-settings__row-label-text">
|
||||
<?php esc_html_e( 'Display a privacy notice under your comment forms.', 'akismet' ); ?>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<label class="akismet-settings__row-input-label" for="akismet_comment_form_privacy_notice_hide">
|
||||
<input type="radio" name="akismet_comment_form_privacy_notice" id="akismet_comment_form_privacy_notice_hide" value="hide" <?php echo in_array( get_option( 'akismet_comment_form_privacy_notice' ), array( 'display', 'hide' ), true ) ? checked( 'hide', get_option( 'akismet_comment_form_privacy_notice' ), false ) : 'checked="checked"'; ?> />
|
||||
<span class="akismet-settings__row-label-text">
|
||||
<?php esc_html_e( 'Do not display privacy notice.', 'akismet' ); ?>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<div class="akismet-settings__row-note">
|
||||
<?php esc_html_e( 'To help your site with transparency under privacy laws like the GDPR, Akismet can display a notice to your users under your comment forms.', 'akismet' ); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="akismet-card-actions">
|
||||
<?php if ( ! Akismet::predefined_api_key() ) : ?>
|
||||
<div id="delete-action" class="akismet-card-actions__secondary-action">
|
||||
<a class="submitdelete deletion" href="<?php echo esc_url( Akismet_Admin::get_page_url( 'delete_key' ) ); ?>"><?php esc_html_e( 'Disconnect this account', 'akismet' ); ?></a>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php wp_nonce_field( Akismet_Admin::NONCE ); ?>
|
||||
|
||||
<div id="publishing-action">
|
||||
<input type="hidden" name="action" value="enter-key">
|
||||
<input type="submit" name="submit" id="submit" class="akismet-button akismet-could-be-primary" value="<?php esc_attr_e( 'Save changes', 'akismet' ); ?>">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if ( ! Akismet::predefined_api_key() ) : ?>
|
||||
<div class="akismet-card">
|
||||
<div class="akismet-section-header">
|
||||
<h2 class="akismet-section-header__label">
|
||||
<span><?php esc_html_e( 'Account', 'akismet' ); ?></span>
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div class="inside">
|
||||
<table class="akismet-account">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th scope="row"><?php esc_html_e( 'Subscription type', 'akismet' ); ?></th>
|
||||
<td>
|
||||
<?php echo esc_html( $akismet_user->account_name ); ?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><?php esc_html_e( 'Status', 'akismet' ); ?></th>
|
||||
<td>
|
||||
<?php
|
||||
if ( Akismet::USER_STATUS_CANCELLED === $akismet_user->status ) :
|
||||
esc_html_e( 'Cancelled', 'akismet' );
|
||||
elseif ( Akismet::USER_STATUS_SUSPENDED === $akismet_user->status ) :
|
||||
esc_html_e( 'Suspended', 'akismet' );
|
||||
elseif ( Akismet::USER_STATUS_MISSING === $akismet_user->status ) :
|
||||
esc_html_e( 'Missing', 'akismet' );
|
||||
elseif ( Akismet::USER_STATUS_NO_SUB === $akismet_user->status ) :
|
||||
esc_html_e( 'No subscription found', 'akismet' );
|
||||
else :
|
||||
esc_html_e( 'Active', 'akismet' );
|
||||
endif;
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php if ( $akismet_user->next_billing_date ) : ?>
|
||||
<tr>
|
||||
<th scope="row"><?php esc_html_e( 'Next billing date', 'akismet' ); ?></th>
|
||||
<td>
|
||||
<?php echo esc_html( gmdate( 'F j, Y', $akismet_user->next_billing_date ) ); ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="akismet-card-actions">
|
||||
<?php if ( $akismet_user->status === Akismet::USER_STATUS_ACTIVE ) : ?>
|
||||
<div class="akismet-card-actions__secondary-action">
|
||||
<a href="https://akismet.com/account?utm_source=akismet_plugin&utm_campaign=plugin_static_link&utm_medium=in_plugin&utm_content=account_overview" class="akismet-external-link" aria-label="Account overview on akismet.com"><?php esc_html_e( 'Account overview', 'akismet' ); ?></a>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div id="publishing-action">
|
||||
<?php
|
||||
Akismet::view(
|
||||
'get',
|
||||
array(
|
||||
'text' => ( $akismet_user->account_type === 'free-api-key' && $akismet_user->status === Akismet::USER_STATUS_ACTIVE ? __( 'Upgrade', 'akismet' ) : __( 'Change', 'akismet' ) ),
|
||||
'redirect' => 'upgrade',
|
||||
'utm_content' => ( $akismet_user->account_type === 'free-api-key' && $akismet_user->status === Akismet::USER_STATUS_ACTIVE ? 'config_upgrade' : 'config_change' ),
|
||||
)
|
||||
);
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
14
wp-content/plugins/akismet/views/connect-jp.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
declare( strict_types = 1 );
|
||||
|
||||
//phpcs:disable VariableAnalysis
|
||||
// There are "undefined" variables here because they're defined in the code that includes this file as a template.
|
||||
?>
|
||||
<div class="akismet-box">
|
||||
<?php Akismet::view( 'setup', array( 'use_jetpack_connection' => true ) ); ?>
|
||||
<?php Akismet::view( 'setup-jetpack', array( 'akismet_user' => $akismet_user ) ); ?>
|
||||
</div>
|
||||
|
||||
<div class="akismet-box">
|
||||
<?php Akismet::view( 'enter' ); ?>
|
||||
</div>
|
||||
14
wp-content/plugins/akismet/views/enter.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<div class="akismet-enter-api-key-box centered">
|
||||
<button class="akismet-enter-api-key-box__reveal"><?php esc_html_e( 'Manually enter an API key', 'akismet' ); ?></button>
|
||||
<div class="akismet-enter-api-key-box__form-wrapper">
|
||||
<form action="<?php echo esc_url( Akismet_Admin::get_page_url() ); ?>" method="post">
|
||||
<?php wp_nonce_field( Akismet_Admin::NONCE ); ?>
|
||||
<input type="hidden" name="action" value="enter-key">
|
||||
<h3 class="akismet-enter-api-key-box__header" id="akismet-enter-api-key-box__header"><?php esc_html_e( 'Enter your API key', 'akismet' ); ?></h3>
|
||||
<div class="akismet-enter-api-key-box__input-wrapper">
|
||||
<input id="key" name="key" type="text" size="15" value="" placeholder="<?php esc_attr_e( 'API key', 'akismet' ); ?>" class="akismet-enter-api-key-box__key-input regular-text code" aria-labelledby="akismet-enter-api-key-box__header">
|
||||
<input type="submit" name="submit" id="submit" class="akismet-button" value="<?php esc_attr_e( 'Connect with API key', 'akismet' ); ?>">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
32
wp-content/plugins/akismet/views/get.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
//phpcs:disable VariableAnalysis
|
||||
// There are "undefined" variables here because they're defined in the code that includes this file as a template.
|
||||
|
||||
$submit_classes_attr = 'akismet-button';
|
||||
|
||||
if ( isset( $classes ) && ( is_countable( $classes ) ? count( $classes ) : 0 ) > 0 ) {
|
||||
$submit_classes_attr = implode( ' ', $classes );
|
||||
}
|
||||
|
||||
$query_args = array(
|
||||
'passback_url' => Akismet_Admin::get_page_url(),
|
||||
'redirect' => isset( $redirect ) ? $redirect : 'plugin-signup',
|
||||
);
|
||||
|
||||
// Set default UTM parameters, overriding with any provided values.
|
||||
$utm_args = array(
|
||||
'utm_source' => isset( $utm_source ) ? $utm_source : 'akismet_plugin',
|
||||
'utm_medium' => isset( $utm_medium ) ? $utm_medium : 'in_plugin',
|
||||
'utm_campaign' => isset( $utm_campaign ) ? $utm_campaign : 'plugin_static_link',
|
||||
'utm_content' => isset( $utm_content ) ? $utm_content : 'get_view_link',
|
||||
);
|
||||
|
||||
$query_args = array_merge( $query_args, $utm_args );
|
||||
|
||||
$url = add_query_arg( $query_args, 'https://akismet.com/get/' );
|
||||
?>
|
||||
<a href="<?php echo esc_url( $url ); ?>" class="<?php echo esc_attr( $submit_classes_attr ); ?>" target="_blank">
|
||||
<?php echo esc_html( is_string( $text ) ? $text : '' ); ?>
|
||||
<span class="screen-reader-text"><?php esc_html_e( '(opens in a new tab)', 'akismet' ); ?></span>
|
||||
</a>
|
||||
13
wp-content/plugins/akismet/views/logo.php
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
//phpcs:disable VariableAnalysis
|
||||
// There are "undefined" variables here because they're defined in the code that includes this file as a template.
|
||||
?>
|
||||
<div class="akismet-masthead__logo-container">
|
||||
<?php if ( isset( $include_logo_link ) && $include_logo_link === true ) : ?>
|
||||
<a href="<?php echo esc_url( Akismet_Admin::get_page_url() ); ?>" class="akismet-masthead__logo-link">
|
||||
<?php endif; ?>
|
||||
<img class="akismet-masthead__logo" src="<?php echo esc_url( plugins_url( '../_inc/img/akismet-refresh-logo@2x.png', __FILE__ ) ); ?>" srcset="<?php echo esc_url( plugins_url( '../_inc/img/akismet-refresh-logo.svg', __FILE__ ) ); ?>" alt="Akismet logo" />
|
||||
<?php if ( isset( $include_logo_link ) && $include_logo_link === true ) : ?>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
379
wp-content/plugins/akismet/views/notice.php
Normal file
@@ -0,0 +1,379 @@
|
||||
<?php
|
||||
//phpcs:disable VariableAnalysis
|
||||
// There are "undefined" variables here because they're defined in the code that includes this file as a template.
|
||||
$kses_allow_link = array(
|
||||
'a' => array(
|
||||
'href' => true,
|
||||
'target' => true,
|
||||
'class' => true,
|
||||
),
|
||||
);
|
||||
$kses_allow_strong = array( 'strong' => true );
|
||||
|
||||
if ( ! isset( $type ) ) {
|
||||
$type = false; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
|
||||
}
|
||||
|
||||
/*
|
||||
* Some notices (plugin, spam-check, spam-check-cron-disabled, alert and usage-limit) are also shown elsewhere in wp-admin, so have different classes applied so that they match the standard WordPress notice format.
|
||||
*/
|
||||
?>
|
||||
<?php if ( $type === 'plugin' ) : ?>
|
||||
<?php // Displayed on edit-comments.php to users who have not set up Akismet yet. ?>
|
||||
<div class="updated" id="akismet-setup-prompt">
|
||||
<form name="akismet_activate" action="<?php echo esc_url( Akismet_Admin::get_page_url() ); ?>" method="post">
|
||||
<div class="akismet-activate">
|
||||
<input type="submit" class="akismet-activate__button akismet-button" value="<?php esc_attr_e( 'Set up your Akismet account', 'akismet' ); ?>" />
|
||||
<div class="akismet-activate__description">
|
||||
<?php esc_html_e( 'Almost done! Configure Akismet and say goodbye to spam', 'akismet' ); ?>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<?php elseif ( $type === 'spam-check' ) : ?>
|
||||
<?php // This notice is only displayed on edit-comments.php. ?>
|
||||
<div class="notice notice-warning">
|
||||
<p><strong><?php esc_html_e( 'Akismet has detected a problem.', 'akismet' ); ?></strong></p>
|
||||
<p><?php esc_html_e( 'Some comments have not yet been checked for spam by Akismet. They have been temporarily held for moderation and will automatically be rechecked later.', 'akismet' ); ?></p>
|
||||
<?php if ( ! empty( $link_text ) ) : ?>
|
||||
<p><?php echo wp_kses( $link_text, $kses_allow_link ); ?></p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php elseif ( $type === 'spam-check-cron-disabled' ) : ?>
|
||||
<?php // This notice is only displayed on edit-comments.php. ?>
|
||||
<div class="notice notice-warning">
|
||||
<p><strong><?php esc_html_e( 'Akismet has detected a problem.', 'akismet' ); ?></strong></p>
|
||||
<p><?php esc_html_e( 'WP-Cron has been disabled using the DISABLE_WP_CRON constant. Comment rechecks may not work properly.', 'akismet' ); ?></p>
|
||||
</div>
|
||||
|
||||
<?php elseif ( $type === 'alert' && $code === Akismet::ALERT_CODE_COMMERCIAL && isset( $parent_view ) && $parent_view === 'config' ) : ?>
|
||||
<?php // Display a different commercial warning alert on the config page ?>
|
||||
<div class="akismet-card akismet-alert is-commercial">
|
||||
<div>
|
||||
<h3 class="akismet-alert-header"><?php esc_html_e( 'We detected commercial activity on your site', 'akismet' ); ?></h3>
|
||||
<p class="akismet-alert-info">
|
||||
<?php
|
||||
/* translators: The placeholder is a URL. */
|
||||
echo wp_kses( sprintf( __( 'Your current subscription is for <a class="akismet-external-link" href="%s">personal, non-commercial use</a>. Please upgrade your plan to continue using Akismet.', 'akismet' ), esc_url( 'https://akismet.com/support/getting-started/free-or-paid/?utm_source=akismet_plugin&utm_campaign=plugin_static_link&utm_medium=in_plugin&utm_content=commercial_support' ) ), $kses_allow_link );
|
||||
?>
|
||||
</p>
|
||||
<p class="akismet-alert-info">
|
||||
<?php
|
||||
/* translators: The placeholder is a URL to the contact form. */
|
||||
echo wp_kses( sprintf( __( 'If you believe your site should not be classified as commercial, <a class="akismet-external-link" href="%s">please get in touch</a>', 'akismet' ), esc_url( 'https://akismet.com/contact/?purpose=commercial&utm_source=akismet_plugin&utm_campaign=plugin_static_link&utm_medium=in_plugin&utm_content=commercial_contact' ) ), $kses_allow_link );
|
||||
?>
|
||||
</p>
|
||||
</div>
|
||||
<div class="akismet-alert-button-wrapper">
|
||||
<?php
|
||||
Akismet::view(
|
||||
'get',
|
||||
array(
|
||||
'text' => __( 'Upgrade plan', 'akismet' ),
|
||||
'classes' => array( 'akismet-alert-button', 'akismet-button' ),
|
||||
'redirect' => 'upgrade',
|
||||
'utm_content' => 'commercial_upgrade',
|
||||
)
|
||||
);
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php elseif ( $type === 'alert' ) : ?>
|
||||
<div class="<?php echo isset( $parent_view ) && $parent_view === 'config' ? 'akismet-alert is-bad' : 'error'; ?>">
|
||||
<?php /* translators: The placeholder is an error code returned by Akismet. */ ?>
|
||||
<p><strong><?php printf( esc_html__( 'Akismet error code: %s', 'akismet' ), esc_html( $code ) ); ?></strong></p>
|
||||
<p><?php echo isset( $msg ) ? esc_html( $msg ) : ''; ?></p>
|
||||
<p>
|
||||
<?php
|
||||
echo wp_kses(
|
||||
sprintf(
|
||||
/* translators: the placeholder is a clickable URL that leads to more information regarding an error code. */
|
||||
__( 'For more information, see the <a class="akismet-external-link" href="%s">error documentation on akismet.com</a>', 'akismet' ),
|
||||
esc_url( 'https://akismet.com/developers/detailed-docs/errors/akismet-error-' . absint( $code ) . '?utm_source=akismet_plugin&utm_campaign=plugin_static_link&utm_medium=in_plugin&utm_content=error_info' )
|
||||
),
|
||||
$kses_allow_link
|
||||
);
|
||||
?>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<?php elseif ( $type === 'notice' ) : ?>
|
||||
<div class="akismet-alert is-bad">
|
||||
<h3 class="akismet-alert__heading"><?php echo wp_kses( $notice_header, Akismet_Admin::get_notice_kses_allowed_elements() ); ?></h3>
|
||||
<p>
|
||||
<?php echo wp_kses( $notice_text, Akismet_Admin::get_notice_kses_allowed_elements() ); ?>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<?php elseif ( $type === 'missing-functions' ) : ?>
|
||||
<div class="akismet-alert is-bad">
|
||||
<h3 class="akismet-alert__heading"><?php esc_html_e( 'Network functions are disabled.', 'akismet' ); ?></h3>
|
||||
<p>
|
||||
<?php
|
||||
echo wp_kses( __( 'Your web host or server administrator has disabled PHP’s <code>gethostbynamel</code> function.', 'akismet' ), array_merge( $kses_allow_link, $kses_allow_strong, array( 'code' => true ) ) );
|
||||
?>
|
||||
</p>
|
||||
<p>
|
||||
<?php
|
||||
/* translators: The placeholder is a URL. */
|
||||
echo wp_kses( sprintf( __( 'Please contact your web host or firewall administrator and give them <a class="akismet-external-link" href="%s" target="_blank">this information about Akismet’s system requirements</a>', 'akismet' ), esc_url( 'https://akismet.com/akismet-hosting-faq/?utm_source=akismet_plugin&utm_campaign=plugin_static_link&utm_medium=in_plugin&utm_content=hosting_faq_php' ) ), array_merge( $kses_allow_link, $kses_allow_strong, array( 'code' => true ) ) );
|
||||
?>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<?php elseif ( $type === 'servers-be-down' ) : ?>
|
||||
<div class="akismet-alert is-bad">
|
||||
<h3 class="akismet-alert__heading"><?php esc_html_e( 'Your site can’t connect to the Akismet servers.', 'akismet' ); ?></h3>
|
||||
<p>
|
||||
<?php
|
||||
/* translators: The placeholder is a URL. */
|
||||
echo wp_kses( sprintf( __( 'Your firewall may be blocking Akismet from connecting to its API. Please contact your host and refer to <a class="akismet-external-link" href="%s" target="_blank">our guide about firewalls</a>', 'akismet' ), esc_url( 'https://akismet.com/akismet-hosting-faq/?utm_source=akismet_plugin&utm_campaign=plugin_static_link&utm_medium=in_plugin&utm_content=hosting_faq_firewall' ) ), $kses_allow_link );
|
||||
?>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<?php elseif ( $type === 'active-dunning' ) : ?>
|
||||
<div class="akismet-alert is-bad">
|
||||
<h3 class="akismet-alert__heading"><?php esc_html_e( 'Please update your payment information.', 'akismet' ); ?></h3>
|
||||
<p>
|
||||
<?php
|
||||
/* translators: The placeholder is a URL. */
|
||||
echo wp_kses( sprintf( __( 'We cannot process your payment. Please <a class="akismet-external-link" href="%s" target="_blank">update your payment details</a>', 'akismet' ), esc_url( 'https://wordpress.com/me/purchases/payment-methods?utm_source=akismet_plugin&utm_campaign=plugin_static_link&utm_medium=in_plugin&utm_content=payment_update' ) ), $kses_allow_link );
|
||||
?>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<?php elseif ( $type === 'cancelled' ) : ?>
|
||||
<div class="akismet-alert is-bad">
|
||||
<h3 class="akismet-alert__heading"><?php esc_html_e( 'Your Akismet plan has been cancelled.', 'akismet' ); ?></h3>
|
||||
<p>
|
||||
<?php
|
||||
/* translators: The placeholder is a URL. */
|
||||
echo wp_kses( sprintf( __( 'Please visit <a class="akismet-external-link" href="%s" target="_blank">Akismet.com</a> to purchase a new subscription.', 'akismet' ), esc_url( 'https://akismet.com/pricing/?utm_source=akismet_plugin&utm_campaign=plugin_static_link&utm_medium=in_plugin&utm_content=pricing_cancelled' ) ), $kses_allow_link );
|
||||
?>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<?php elseif ( $type === 'suspended' ) : ?>
|
||||
<div class="akismet-alert is-bad">
|
||||
<h3 class="akismet-alert__heading"><?php esc_html_e( 'Your Akismet subscription is suspended.', 'akismet' ); ?></h3>
|
||||
<p>
|
||||
<?php
|
||||
/* translators: The placeholder is a URL. */
|
||||
echo wp_kses( sprintf( __( 'Please contact <a class="akismet-external-link" href="%s" target="_blank">Akismet support</a> for assistance.', 'akismet' ), esc_url( 'https://akismet.com/contact/?utm_source=akismet_plugin&utm_campaign=plugin_static_link&utm_medium=in_plugin&utm_content=support_suspended' ) ), $kses_allow_link );
|
||||
?>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<?php elseif ( $type === 'active-notice' && $time_saved ) : ?>
|
||||
<div class="akismet-alert is-neutral">
|
||||
<h3 class="akismet-alert__heading"><?php echo esc_html( $time_saved ); ?></h3>
|
||||
<p>
|
||||
<?php
|
||||
/* translators: the placeholder is a clickable URL to the Akismet account upgrade page. */
|
||||
echo wp_kses( sprintf( __( 'You can help us fight spam and upgrade your account by <a class="akismet-external-link" href="%s" target="_blank">contributing a token amount</a>', 'akismet' ), esc_url( 'https://akismet.com/pricing?utm_source=akismet_plugin&utm_campaign=plugin_static_link&utm_medium=in_plugin&utm_content=upgrade_contribution' ) ), $kses_allow_link );
|
||||
?>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<?php elseif ( $type === 'missing' ) : ?>
|
||||
<div class="akismet-alert is-bad">
|
||||
<h3 class="akismet-alert__heading"><?php esc_html_e( 'There is a problem with your API key.', 'akismet' ); ?></h3>
|
||||
<p>
|
||||
<?php
|
||||
/* translators: The placeholder is a URL to the Akismet contact form. */
|
||||
echo wp_kses( sprintf( __( 'Please contact <a class="akismet-external-link" href="%s" target="_blank">Akismet support</a> for assistance.', 'akismet' ), esc_url( 'https://akismet.com/contact/?utm_source=akismet_plugin&utm_campaign=plugin_static_link&utm_medium=in_plugin&utm_content=support_missing' ) ), $kses_allow_link );
|
||||
?>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<?php elseif ( $type === 'no-sub' ) : ?>
|
||||
<div class="akismet-alert is-bad">
|
||||
<h3 class="akismet-alert__heading"><?php esc_html_e( 'You don’t have an Akismet plan.', 'akismet' ); ?></h3>
|
||||
<p>
|
||||
<?php
|
||||
/* translators: the placeholder is the URL to the Akismet pricing page. */
|
||||
echo wp_kses( sprintf( __( 'Please <a class="akismet-external-link" href="%s" target="_blank">choose a free or paid plan</a> so Akismet can protect your site from spam.', 'akismet' ), esc_url( 'https://akismet.com/pricing?utm_source=akismet_plugin&utm_campaign=plugin_static_link&utm_medium=in_plugin&utm_content=choose_plan' ) ), $kses_allow_link );
|
||||
?>
|
||||
</p>
|
||||
<p><?php echo esc_html__( 'Once you\'ve chosen a plan, return here to complete your setup.', 'akismet' ); ?></p>
|
||||
</div>
|
||||
|
||||
<?php elseif ( $type === 'new-key-valid' ) : ?>
|
||||
<?php
|
||||
global $wpdb;
|
||||
|
||||
$check_pending_link = false;
|
||||
|
||||
$at_least_one_comment_in_moderation = ! ! $wpdb->get_var( "SELECT comment_ID FROM {$wpdb->comments} WHERE comment_approved = '0' LIMIT 1" );
|
||||
|
||||
if ( $at_least_one_comment_in_moderation ) {
|
||||
$check_pending_link = 'edit-comments.php?akismet_recheck=' . wp_create_nonce( 'akismet_recheck' );
|
||||
}
|
||||
?>
|
||||
<div class="akismet-alert is-good">
|
||||
<p><?php esc_html_e( 'Akismet is now protecting your site from spam.', 'akismet' ); ?></p>
|
||||
<?php if ( $check_pending_link ) : ?>
|
||||
<p>
|
||||
<?php
|
||||
echo wp_kses(
|
||||
sprintf(
|
||||
/* translators: The placeholder is a URL for checking pending comments. */
|
||||
__( 'Would you like to <a href="%s">check pending comments</a>?', 'akismet' ),
|
||||
esc_url( $check_pending_link )
|
||||
),
|
||||
$kses_allow_link
|
||||
);
|
||||
?>
|
||||
</p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php elseif ( $type === 'new-key-invalid' ) : ?>
|
||||
<div class="akismet-alert is-bad">
|
||||
<p><?php esc_html_e( 'The key you entered is invalid. Please double-check it.', 'akismet' ); ?></p>
|
||||
</div>
|
||||
|
||||
<?php elseif ( $type === Akismet_Admin::NOTICE_EXISTING_KEY_INVALID ) : ?>
|
||||
<div class="akismet-alert is-bad">
|
||||
<h3 class="akismet-alert__heading"><?php echo esc_html( __( 'Your API key is no longer valid.', 'akismet' ) ); ?></h3>
|
||||
<p>
|
||||
<?php
|
||||
echo wp_kses(
|
||||
sprintf(
|
||||
/* translators: The placeholder is a URL to the Akismet contact form. */
|
||||
__( 'Please enter a new key or <a class="akismet-external-link" href="%s" target="_blank">contact Akismet support</a>', 'akismet' ),
|
||||
'https://akismet.com/contact/?utm_source=akismet_plugin&utm_campaign=plugin_static_link&utm_medium=in_plugin&utm_content=support_invalid_key'
|
||||
),
|
||||
$kses_allow_link
|
||||
);
|
||||
?>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<?php elseif ( $type === 'new-key-failed' ) : ?>
|
||||
<div class="akismet-alert is-bad">
|
||||
<h3 class="akismet-alert__heading"><?php esc_html_e( 'The API key you entered could not be verified.', 'akismet' ); ?></h3>
|
||||
<p>
|
||||
<?php
|
||||
echo wp_kses(
|
||||
sprintf(
|
||||
/* translators: The placeholder is a URL. */
|
||||
__( 'The connection to akismet.com could not be established. Please refer to <a class="akismet-external-link" href="%s" target="_blank">our guide about firewalls</a> and check your server configuration.', 'akismet' ),
|
||||
'https://akismet.com/akismet-hosting-faq/?utm_source=akismet_plugin&utm_campaign=plugin_static_link&utm_medium=in_plugin&utm_content=hosting_faq'
|
||||
),
|
||||
$kses_allow_link
|
||||
);
|
||||
?>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<?php elseif ( $type === 'usage-limit' && isset( Akismet::$limit_notices[ $code ] ) ) : ?>
|
||||
<div class="error akismet-usage-limit-alert">
|
||||
<div class="akismet-usage-limit-logo">
|
||||
<img src="<?php echo esc_url( plugins_url( '../_inc/img/logo-a-2x.png', __FILE__ ) ); ?>" alt="Akismet logo" />
|
||||
</div>
|
||||
<div class="akismet-usage-limit-text">
|
||||
<h3>
|
||||
<?php
|
||||
switch ( Akismet::$limit_notices[ $code ] ) {
|
||||
case 'FIRST_MONTH_OVER_LIMIT':
|
||||
case 'SECOND_MONTH_OVER_LIMIT':
|
||||
esc_html_e( 'Your Akismet account usage is over your plan’s limit', 'akismet' );
|
||||
break;
|
||||
case 'THIRD_MONTH_APPROACHING_LIMIT':
|
||||
esc_html_e( 'Your Akismet account usage is approaching your plan’s limit', 'akismet' );
|
||||
break;
|
||||
case 'THIRD_MONTH_OVER_LIMIT':
|
||||
case 'FOUR_PLUS_MONTHS_OVER_LIMIT':
|
||||
esc_html_e( 'Your account has been restricted', 'akismet' );
|
||||
break;
|
||||
default:
|
||||
}
|
||||
?>
|
||||
</h3>
|
||||
<p>
|
||||
<?php
|
||||
switch ( Akismet::$limit_notices[ $code ] ) {
|
||||
case 'FIRST_MONTH_OVER_LIMIT':
|
||||
echo esc_html(
|
||||
sprintf(
|
||||
/* translators: The first placeholder is a date, the second is a (formatted) number, the third is another formatted number. */
|
||||
__( 'Since %1$s, your account made %2$s API calls, compared to your plan’s limit of %3$s.', 'akismet' ),
|
||||
esc_html( gmdate( 'F' ) . ' 1' ),
|
||||
number_format( $api_calls ),
|
||||
number_format( $usage_limit )
|
||||
)
|
||||
);
|
||||
echo ' ';
|
||||
echo '<a class="akismet-external-link" href="https://akismet.com/support/general/akismet-api-usage-limits/?utm_source=akismet_plugin&utm_campaign=plugin_static_link&utm_medium=in_plugin&utm_content=usage_limit_docs" target="_blank">';
|
||||
echo esc_html( __( 'Learn more about usage limits', 'akismet' ) );
|
||||
echo '</a>';
|
||||
|
||||
break;
|
||||
case 'SECOND_MONTH_OVER_LIMIT':
|
||||
echo esc_html( __( 'Your Akismet usage has been over your plan’s limit for two consecutive months. Next month, we will restrict your account after you reach the limit. Increase your limit to make sure your site stays protected from spam.', 'akismet' ) );
|
||||
echo ' ';
|
||||
echo '<a class="akismet-external-link" href="https://akismet.com/support/general/akismet-api-usage-limits/?utm_source=akismet_plugin&utm_campaign=plugin_static_link&utm_medium=in_plugin&utm_content=usage_limit_docs" target="_blank">';
|
||||
echo esc_html( __( 'Learn more about usage limits', 'akismet' ) );
|
||||
echo '</a>';
|
||||
|
||||
break;
|
||||
case 'THIRD_MONTH_APPROACHING_LIMIT':
|
||||
echo esc_html( __( 'Your Akismet usage is nearing your plan’s limit for the third consecutive month. We will restrict your account after you reach the limit. Increase your limit to make sure your site stays protected from spam.', 'akismet' ) );
|
||||
echo ' ';
|
||||
echo '<a class="akismet-external-link" href="https://akismet.com/support/general/akismet-api-usage-limits/?utm_source=akismet_plugin&utm_campaign=plugin_static_link&utm_medium=in_plugin&utm_content=usage_limit_docs" target="_blank">';
|
||||
echo esc_html( __( 'Learn more about usage limits', 'akismet' ) );
|
||||
echo '</a>';
|
||||
|
||||
break;
|
||||
case 'THIRD_MONTH_OVER_LIMIT':
|
||||
case 'FOUR_PLUS_MONTHS_OVER_LIMIT':
|
||||
echo esc_html( __( 'Your Akismet usage has been over your plan’s limit for three consecutive months. We have restricted your account for the rest of the month. Increase your limit to make sure your site stays protected from spam.', 'akismet' ) );
|
||||
echo ' ';
|
||||
echo '<a class="akismet-external-link" href="https://akismet.com/support/general/akismet-api-usage-limits/?utm_source=akismet_plugin&utm_campaign=plugin_static_link&utm_medium=in_plugin&utm_content=usage_limit_docs" target="_blank">';
|
||||
echo esc_html( __( 'Learn more about usage limits', 'akismet' ) );
|
||||
echo '</a>';
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
}
|
||||
?>
|
||||
</p>
|
||||
</div>
|
||||
<div class="akismet-usage-limit-cta">
|
||||
<a href="<?php echo esc_attr( $upgrade_url . ( strpos( $upgrade_url, '?' ) !== false ? '&' : '?' ) . 'utm_source=akismet_plugin&utm_campaign=plugin_static_link&utm_medium=in_plugin&utm_content=usage_limit_upgrade' ); ?>" class="button" target="_blank">
|
||||
<?php
|
||||
if ( isset( $upgrade_via_support ) && $upgrade_via_support ) {
|
||||
// Direct user to contact support.
|
||||
esc_html_e( 'Contact Akismet support', 'akismet' );
|
||||
} elseif ( ! empty( $upgrade_type ) && 'qty' === $upgrade_type ) {
|
||||
// If a qty upgrade is required, use recommended plan name if available.
|
||||
if ( ! empty( $recommended_plan_name ) && is_string( $recommended_plan_name ) ) {
|
||||
echo esc_html(
|
||||
sprintf(
|
||||
/* translators: The placeholder is the name of an Akismet subscription plan, like "Akismet Pro" or "Akismet Business" . */
|
||||
__( 'Add an %s subscription', 'akismet' ),
|
||||
$recommended_plan_name
|
||||
)
|
||||
);
|
||||
} else {
|
||||
esc_html_e( 'Increase your limit', 'akismet' );
|
||||
}
|
||||
} else {
|
||||
echo esc_html(
|
||||
sprintf(
|
||||
/* translators: The placeholder is the name of a subscription level, like "Akismet Business" or "Akismet Enterprise" . */
|
||||
__( 'Upgrade to %s', 'akismet' ),
|
||||
$upgrade_plan
|
||||
)
|
||||
);
|
||||
}
|
||||
?>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
11
wp-content/plugins/akismet/views/predefined.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<div class="akismet-box">
|
||||
<h2><?php esc_html_e( 'Manual Configuration', 'akismet' ); ?></h2>
|
||||
<p>
|
||||
<?php
|
||||
|
||||
/* translators: %s is the wp-config.php file */
|
||||
printf( esc_html__( 'An Akismet API key has been defined in the %s file for this site.', 'akismet' ), '<code>wp-config.php</code>' );
|
||||
|
||||
?>
|
||||
</p>
|
||||
</div>
|
||||
97
wp-content/plugins/akismet/views/setup-jetpack.php
Normal file
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
declare( strict_types = 1 );
|
||||
|
||||
//phpcs:disable VariableAnalysis
|
||||
// There are "undefined" variables here because they're defined in the code that includes this file as a template.
|
||||
|
||||
$user_status = $akismet_user->status ?? null;
|
||||
?>
|
||||
<div class="akismet-setup__connection">
|
||||
<?php if ( ! empty( $akismet_user->user_email ) && ! empty( $akismet_user->user_login ) ) : ?>
|
||||
<div class="akismet-setup__connection-user">
|
||||
<div class="akismet-setup__connection-avatar">
|
||||
<?php
|
||||
// Decorative avatar; empty alt for screen readers.
|
||||
echo get_avatar(
|
||||
$akismet_user->user_email,
|
||||
48,
|
||||
'',
|
||||
'',
|
||||
array(
|
||||
'class' => 'akismet-setup__connection-avatar-image',
|
||||
'alt' => '',
|
||||
)
|
||||
);
|
||||
?>
|
||||
<div class="akismet-setup__connection-account">
|
||||
<div class="akismet-setup__connection-account-name">
|
||||
<?php
|
||||
printf(
|
||||
/* translators: %s is the WordPress.com username */
|
||||
esc_html__( 'Signed in as %s', 'akismet' ),
|
||||
'<strong>' . esc_html( $akismet_user->user_login ) . '</strong>'
|
||||
);
|
||||
?>
|
||||
</div>
|
||||
<div class="akismet-setup__connection-account-email"><?php echo esc_html( $akismet_user->user_email ); ?></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="akismet-setup__connection-action">
|
||||
<?php if ( in_array( $user_status, array( Akismet::USER_STATUS_CANCELLED, Akismet::USER_STATUS_MISSING, Akismet::USER_STATUS_NO_SUB ) ) ) : ?>
|
||||
|
||||
<p class="akismet-setup__connection-action-intro">
|
||||
<?php esc_html_e( "Your Jetpack account is connected, but it doesn't have an active Akismet subscription yet. To continue, please choose a plan on Akismet.com.", 'akismet' ); ?>
|
||||
</p>
|
||||
|
||||
<a href="https://akismet.com/get?utm_source=akismet_plugin&utm_campaign=plugin_static_link&utm_medium=in_plugin&utm_content=jetpack_flow_<?php echo esc_attr( str_replace( '-', '_', $user_status ) ); ?>" class="akismet-setup__connection-button akismet-button">
|
||||
<?php esc_html_e( 'Choose a plan on Akismet.com', 'akismet' ); ?>
|
||||
</a>
|
||||
|
||||
<p class="akismet-setup__connection-action-description">
|
||||
<?php esc_html_e( "Once you've chosen a plan, return here to complete your setup.", 'akismet' ); ?>
|
||||
</p>
|
||||
|
||||
<?php elseif ( $user_status === Akismet::USER_STATUS_SUSPENDED ) : ?>
|
||||
<p class="akismet-setup__connection-action-intro">
|
||||
<?php esc_html_e( "Your Akismet account appears to be suspended. This sometimes happens if there's a billing or verification issue. Please contact our support team so we can help you get it sorted.", 'akismet' ); ?>
|
||||
</p>
|
||||
|
||||
<a href="https://akismet.com/contact?utm_source=akismet_plugin&utm_campaign=plugin_static_link&utm_medium=in_plugin&utm_content=jetpack_flow_suspended" class="akismet-setup__connection-button akismet-button">
|
||||
<?php esc_html_e( 'Contact support', 'akismet' ); ?>
|
||||
</a>
|
||||
<?php else : ?>
|
||||
<form name="akismet_use_wpcom_key" action="<?php echo esc_url( Akismet_Admin::get_page_url() ); ?>" method="post" id="akismet-activate">
|
||||
<input type="hidden" name="key" value="<?php echo esc_attr( $akismet_user->api_key ); ?>"/>
|
||||
<input type="hidden" name="action" value="enter-key">
|
||||
<?php wp_nonce_field( Akismet_Admin::NONCE ); ?>
|
||||
<input type="submit" class="akismet-setup__connection-button akismet-button" value="<?php esc_attr_e( 'Connect with Jetpack', 'akismet' ); ?>"/>
|
||||
</form>
|
||||
|
||||
<p class="akismet-setup__connection-action-description">
|
||||
<?php esc_html_e( "By connecting, we'll use your Jetpack account to activate Akismet on this site.", 'akismet' ); ?>
|
||||
</p>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ( ! in_array( $user_status, array( Akismet::USER_STATUS_CANCELLED, Akismet::USER_STATUS_MISSING, Akismet::USER_STATUS_NO_SUB ) ) ) : ?>
|
||||
<p class="akismet-setup__connection-action-description">
|
||||
<?php
|
||||
echo wp_kses(
|
||||
sprintf(
|
||||
/* translators: The placeholder is a URL. */
|
||||
__( 'Want to use a different account? <a href="%s" class="akismet-external-link">Visit akismet.com</a> to set it up and get your API key.', 'akismet' ),
|
||||
esc_url( 'https://akismet.com/get?utm_source=akismet_plugin&utm_campaign=plugin_static_link&utm_medium=in_plugin&utm_content=jetpack_flow_different_account' )
|
||||
),
|
||||
array(
|
||||
'a' => array(
|
||||
'href' => array(),
|
||||
'class' => array(),
|
||||
),
|
||||
)
|
||||
);
|
||||
?>
|
||||
</p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
78
wp-content/plugins/akismet/views/setup.php
Normal file
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
declare( strict_types = 1 );
|
||||
|
||||
//phpcs:disable VariableAnalysis
|
||||
// There are "undefined" variables here because they're defined in the code that includes this file as a template.
|
||||
|
||||
$tick_icon = '<svg class="akismet-setup-instructions__icon" width="48" height="48" viewBox="0 0 48 48" aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx="24" cy="24" r="22" fill="#2E7D32"/>
|
||||
<path d="M16 24l6 6 12-14" fill="none" stroke="#FFFFFF" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>';
|
||||
?>
|
||||
<section class="akismet-setup-instructions">
|
||||
<h2 class="akismet-setup-instructions__heading"><?php esc_html_e( 'Eliminate spam from your site', 'akismet' ); ?></h2>
|
||||
|
||||
<h3 class="akismet-setup-instructions__subheading">
|
||||
<?php echo esc_html__( 'Protect your site from comment spam and contact form spam — automatically.', 'akismet' ); ?>
|
||||
</h3>
|
||||
|
||||
<ul class="akismet-setup-instructions__feature-list">
|
||||
<li class="akismet-setup-instructions__feature">
|
||||
<?php echo $tick_icon; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
|
||||
<div class="akismet-setup-instructions__body">
|
||||
<h4 class="akismet-setup-instructions__title">
|
||||
<?php echo esc_html__( 'Machine learning accuracy', 'akismet' ); ?>
|
||||
</h4>
|
||||
<p class="akismet-setup-instructions__text">
|
||||
<?php echo esc_html__( 'Learns from billions of spam signals across the web to stop junk before it reaches you.', 'akismet' ); ?>
|
||||
</p>
|
||||
</div>
|
||||
</li>
|
||||
<li class="akismet-setup-instructions__feature">
|
||||
<?php echo $tick_icon; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
|
||||
<div class="akismet-setup-instructions__body">
|
||||
<h4 class="akismet-setup-instructions__title">
|
||||
<?php echo esc_html__( 'Zero effort', 'akismet' ); ?>
|
||||
</h4>
|
||||
<p class="akismet-setup-instructions__text">
|
||||
<?php echo esc_html__( 'Akismet runs quietly in the background, saving you hours of manual moderation.', 'akismet' ); ?>
|
||||
</p>
|
||||
</div>
|
||||
</li>
|
||||
<li class="akismet-setup-instructions__feature">
|
||||
<?php echo $tick_icon; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
|
||||
<div class="akismet-setup-instructions__body">
|
||||
<h4 class="akismet-setup-instructions__title">
|
||||
<?php echo esc_html__( 'Works with popular contact forms', 'akismet' ); ?>
|
||||
</h4>
|
||||
<p class="akismet-setup-instructions__text">
|
||||
<?php echo esc_html__( 'Seamlessly integrates with plugins like Elementor, Contact Form 7, Jetpack and WPForms.', 'akismet' ); ?>
|
||||
</p>
|
||||
</div>
|
||||
</li>
|
||||
<li class="akismet-setup-instructions__feature">
|
||||
<?php echo $tick_icon; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
|
||||
<div class="akismet-setup-instructions__body">
|
||||
<h4 class="akismet-setup-instructions__title">
|
||||
<?php echo esc_html__( 'Flexible pricing', 'akismet' ); ?>
|
||||
</h4>
|
||||
<p class="akismet-setup-instructions__text">
|
||||
<?php echo esc_html__( 'Name your own price for personal sites. Businesses start on a paid plan.', 'akismet' ); ?>
|
||||
</p>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<?php
|
||||
if ( empty( $use_jetpack_connection ) ) :
|
||||
Akismet::view(
|
||||
'get',
|
||||
array(
|
||||
'text' => __( 'Get started', 'akismet' ),
|
||||
'classes' => array( 'akismet-button', 'akismet-is-primary', 'akismet-setup-instructions__button' ),
|
||||
'utm_content' => 'setup_instructions',
|
||||
)
|
||||
);
|
||||
endif;
|
||||
?>
|
||||
</section>
|
||||
26
wp-content/plugins/akismet/views/start.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
//phpcs:disable VariableAnalysis
|
||||
// There are "undefined" variables here because they're defined in the code that includes this file as a template.
|
||||
?>
|
||||
<div id="akismet-plugin-container">
|
||||
<div class="akismet-masthead">
|
||||
<div class="akismet-masthead__inside-container">
|
||||
<?php Akismet::view( 'logo' ); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="akismet-lower">
|
||||
<?php Akismet_Admin::display_status(); ?>
|
||||
<div class="akismet-boxes">
|
||||
<?php
|
||||
if ( Akismet::predefined_api_key() ) {
|
||||
Akismet::view( 'predefined' );
|
||||
} elseif ( $akismet_user && in_array( $akismet_user->status, array( Akismet::USER_STATUS_ACTIVE, 'active-dunning', Akismet::USER_STATUS_NO_SUB, Akismet::USER_STATUS_MISSING, Akismet::USER_STATUS_CANCELLED, Akismet::USER_STATUS_SUSPENDED ) ) ) {
|
||||
Akismet::view( 'connect-jp', compact( 'akismet_user' ) );
|
||||
} else {
|
||||
Akismet::view( 'activate' );
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
12
wp-content/plugins/akismet/views/stats.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<div id="akismet-plugin-container">
|
||||
<div class="akismet-masthead">
|
||||
<div class="akismet-masthead__inside-container">
|
||||
<?php Akismet::view( 'logo', array( 'include_logo_link' => true ) ); ?>
|
||||
<div class="akismet-masthead__back-link-container">
|
||||
<a class="akismet-masthead__back-link" href="<?php echo esc_url( Akismet_Admin::get_page_url() ); ?>"><?php esc_html_e( 'Back to settings', 'akismet' ); ?></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php /* name attribute on iframe is used as a cache-buster here to force Firefox to load the new style charts: https://bugzilla.mozilla.org/show_bug.cgi?id=356558 */ ?>
|
||||
<iframe id="stats-iframe" src="<?php echo esc_url( sprintf( 'https://tools.akismet.com/1.0/user-stats.php?blog=%s&token=%s&locale=%s&is_redecorated=1', urlencode( get_option( 'home' ) ), urlencode( Akismet::get_access_token() ), esc_attr( get_user_locale() ) ) ); ?>" name="<?php echo esc_attr( 'user-stats- ' . filemtime( __FILE__ ) ); ?>" width="100%" height="2500px" frameborder="0" title="<?php echo esc_attr__( 'Akismet detailed stats', 'akismet' ); ?>"></iframe>
|
||||
</div>
|
||||
215
wp-content/plugins/akismet/wrapper.php
Normal file
@@ -0,0 +1,215 @@
|
||||
<?php
|
||||
|
||||
global $wpcom_api_key, $akismet_api_host, $akismet_api_port;
|
||||
|
||||
$wpcom_api_key = defined( 'WPCOM_API_KEY' ) ? constant( 'WPCOM_API_KEY' ) : '';
|
||||
$akismet_api_host = Akismet::get_api_key() . '.rest.akismet.com';
|
||||
$akismet_api_port = 80;
|
||||
|
||||
function akismet_test_mode() {
|
||||
return Akismet::is_test_mode();
|
||||
}
|
||||
|
||||
function akismet_http_post( $request, $host, $path, $port = 80, $ip = null ) {
|
||||
$path = str_replace( '/1.1/', '', $path );
|
||||
|
||||
return Akismet::http_post( $request, $path, $ip );
|
||||
}
|
||||
|
||||
function akismet_microtime() {
|
||||
return Akismet::_get_microtime();
|
||||
}
|
||||
|
||||
function akismet_delete_old() {
|
||||
return Akismet::delete_old_comments();
|
||||
}
|
||||
|
||||
function akismet_delete_old_metadata() {
|
||||
return Akismet::delete_old_comments_meta();
|
||||
}
|
||||
|
||||
function akismet_check_db_comment( $id, $recheck_reason = 'recheck_queue' ) {
|
||||
return Akismet::check_db_comment( $id, $recheck_reason );
|
||||
}
|
||||
|
||||
function akismet_rightnow() {
|
||||
if ( ! class_exists( 'Akismet_Admin' ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Akismet_Admin::rightnow_stats();
|
||||
}
|
||||
|
||||
function akismet_admin_init() {
|
||||
_deprecated_function( __FUNCTION__, '3.0' );
|
||||
}
|
||||
function akismet_version_warning() {
|
||||
_deprecated_function( __FUNCTION__, '3.0' );
|
||||
}
|
||||
function akismet_load_js_and_css() {
|
||||
_deprecated_function( __FUNCTION__, '3.0' );
|
||||
}
|
||||
function akismet_nonce_field( $action = -1 ) {
|
||||
return wp_nonce_field( $action );
|
||||
}
|
||||
function akismet_plugin_action_links( $links, $file ) {
|
||||
return Akismet_Admin::plugin_action_links( $links, $file );
|
||||
}
|
||||
function akismet_conf() {
|
||||
_deprecated_function( __FUNCTION__, '3.0' );
|
||||
}
|
||||
function akismet_stats_display() {
|
||||
_deprecated_function( __FUNCTION__, '3.0' );
|
||||
}
|
||||
function akismet_stats() {
|
||||
return Akismet_Admin::dashboard_stats();
|
||||
}
|
||||
function akismet_admin_warnings() {
|
||||
_deprecated_function( __FUNCTION__, '3.0' );
|
||||
}
|
||||
function akismet_comment_row_action( $a, $comment ) {
|
||||
return Akismet_Admin::comment_row_actions( $a, $comment );
|
||||
}
|
||||
function akismet_comment_status_meta_box( $comment ) {
|
||||
return Akismet_Admin::comment_status_meta_box( $comment );
|
||||
}
|
||||
function akismet_comments_columns( $columns ) {
|
||||
_deprecated_function( __FUNCTION__, '3.0' );
|
||||
|
||||
return $columns;
|
||||
}
|
||||
function akismet_comment_column_row( $column, $comment_id ) {
|
||||
_deprecated_function( __FUNCTION__, '3.0' );
|
||||
}
|
||||
function akismet_text_add_link_callback( $m ) {
|
||||
return Akismet_Admin::text_add_link_callback( $m );
|
||||
}
|
||||
function akismet_text_add_link_class( $comment_text ) {
|
||||
return Akismet_Admin::text_add_link_class( $comment_text );
|
||||
}
|
||||
function akismet_check_for_spam_button( $comment_status ) {
|
||||
return Akismet_Admin::check_for_spam_button( $comment_status );
|
||||
}
|
||||
function akismet_submit_nonspam_comment( $comment_id ) {
|
||||
return Akismet::submit_nonspam_comment( $comment_id );
|
||||
}
|
||||
function akismet_submit_spam_comment( $comment_id ) {
|
||||
return Akismet::submit_spam_comment( $comment_id );
|
||||
}
|
||||
function akismet_transition_comment_status( $new_status, $old_status, $comment ) {
|
||||
return Akismet::transition_comment_status( $new_status, $old_status, $comment );
|
||||
}
|
||||
function akismet_spam_count( $type = false ) {
|
||||
return Akismet_Admin::get_spam_count( $type );
|
||||
}
|
||||
function akismet_recheck_queue() {
|
||||
return Akismet_Admin::recheck_queue();
|
||||
}
|
||||
function akismet_remove_comment_author_url() {
|
||||
return Akismet_Admin::remove_comment_author_url();
|
||||
}
|
||||
function akismet_add_comment_author_url() {
|
||||
return Akismet_Admin::add_comment_author_url();
|
||||
}
|
||||
function akismet_check_server_connectivity() {
|
||||
return Akismet_Admin::check_server_connectivity();
|
||||
}
|
||||
function akismet_get_server_connectivity( $cache_timeout = 86400 ) {
|
||||
return Akismet_Admin::get_server_connectivity( $cache_timeout );
|
||||
}
|
||||
function akismet_server_connectivity_ok() {
|
||||
_deprecated_function( __FUNCTION__, '3.0' );
|
||||
|
||||
return true;
|
||||
}
|
||||
function akismet_admin_menu() {
|
||||
return Akismet_Admin::admin_menu();
|
||||
}
|
||||
function akismet_load_menu() {
|
||||
return Akismet_Admin::load_menu();
|
||||
}
|
||||
function akismet_init() {
|
||||
_deprecated_function( __FUNCTION__, '3.0' );
|
||||
}
|
||||
function akismet_get_key() {
|
||||
return Akismet::get_api_key();
|
||||
}
|
||||
function akismet_check_key_status( $key, $ip = null ) {
|
||||
return Akismet::check_key_status( $key, $ip );
|
||||
}
|
||||
function akismet_update_alert( $response ) {
|
||||
return Akismet::update_alert( $response );
|
||||
}
|
||||
function akismet_verify_key( $key, $ip = null ) {
|
||||
return Akismet::verify_key( $key, $ip );
|
||||
}
|
||||
function akismet_get_user_roles( $user_id ) {
|
||||
return Akismet::get_user_roles( $user_id );
|
||||
}
|
||||
function akismet_result_spam( $approved ) {
|
||||
return Akismet::comment_is_spam( $approved );
|
||||
}
|
||||
function akismet_result_hold( $approved ) {
|
||||
return Akismet::comment_needs_moderation( $approved );
|
||||
}
|
||||
function akismet_get_user_comments_approved( $user_id, $comment_author_email, $comment_author, $comment_author_url ) {
|
||||
return Akismet::get_user_comments_approved( $user_id, $comment_author_email, $comment_author, $comment_author_url );
|
||||
}
|
||||
function akismet_update_comment_history( $comment_id, $message, $event = null ) {
|
||||
return Akismet::update_comment_history( $comment_id, $message, $event );
|
||||
}
|
||||
function akismet_get_comment_history( $comment_id ) {
|
||||
return Akismet::get_comment_history( $comment_id );
|
||||
}
|
||||
function akismet_cmp_time( $a, $b ) {
|
||||
return Akismet::_cmp_time( $a, $b );
|
||||
}
|
||||
function akismet_auto_check_update_meta( $id, $comment ) {
|
||||
return Akismet::auto_check_update_meta( $id, $comment );
|
||||
}
|
||||
function akismet_auto_check_comment( $commentdata ) {
|
||||
return Akismet::auto_check_comment( $commentdata );
|
||||
}
|
||||
function akismet_get_ip_address() {
|
||||
return Akismet::get_ip_address();
|
||||
}
|
||||
function akismet_cron_recheck() {
|
||||
return Akismet::cron_recheck();
|
||||
}
|
||||
function akismet_add_comment_nonce( $post_id ) {
|
||||
return Akismet::add_comment_nonce( $post_id );
|
||||
}
|
||||
function akismet_fix_scheduled_recheck() {
|
||||
return Akismet::fix_scheduled_recheck();
|
||||
}
|
||||
function akismet_spam_comments() {
|
||||
_deprecated_function( __FUNCTION__, '3.0' );
|
||||
|
||||
return array();
|
||||
}
|
||||
function akismet_spam_totals() {
|
||||
_deprecated_function( __FUNCTION__, '3.0' );
|
||||
|
||||
return array();
|
||||
}
|
||||
function akismet_manage_page() {
|
||||
_deprecated_function( __FUNCTION__, '3.0' );
|
||||
}
|
||||
function akismet_caught() {
|
||||
_deprecated_function( __FUNCTION__, '3.0' );
|
||||
}
|
||||
function redirect_old_akismet_urls() {
|
||||
_deprecated_function( __FUNCTION__, '3.0' );
|
||||
}
|
||||
function akismet_kill_proxy_check( $option ) {
|
||||
_deprecated_function( __FUNCTION__, '3.0' );
|
||||
|
||||
return 0;
|
||||
}
|
||||
function akismet_pingback_forwarded_for( $r, $url ) {
|
||||
// This functionality is now in core.
|
||||
return false;
|
||||
}
|
||||
function akismet_pre_check_pingback( $method ) {
|
||||
return Akismet::pre_check_pingback( $method );
|
||||
}
|
||||
759
wp-content/plugins/contact-form-7/admin/admin.php
Normal file
@@ -0,0 +1,759 @@
|
||||
<?php
|
||||
|
||||
require_once WPCF7_PLUGIN_DIR . '/admin/includes/admin-functions.php';
|
||||
require_once WPCF7_PLUGIN_DIR . '/admin/includes/help-tabs.php';
|
||||
require_once WPCF7_PLUGIN_DIR . '/admin/includes/tag-generator.php';
|
||||
require_once WPCF7_PLUGIN_DIR . '/admin/includes/welcome-panel.php';
|
||||
require_once WPCF7_PLUGIN_DIR . '/admin/includes/config-validator.php';
|
||||
|
||||
|
||||
add_action(
|
||||
'admin_init',
|
||||
static function () {
|
||||
do_action( 'wpcf7_admin_init' );
|
||||
},
|
||||
10, 0
|
||||
);
|
||||
|
||||
|
||||
add_action(
|
||||
'admin_menu',
|
||||
'wpcf7_admin_menu',
|
||||
9, 0
|
||||
);
|
||||
|
||||
function wpcf7_admin_menu() {
|
||||
do_action( 'wpcf7_admin_menu' );
|
||||
|
||||
add_menu_page(
|
||||
__( 'Contact Form 7', 'contact-form-7' ),
|
||||
__( 'Contact', 'contact-form-7' )
|
||||
. wpcf7_admin_menu_change_notice(),
|
||||
'wpcf7_read_contact_forms',
|
||||
'wpcf7',
|
||||
'wpcf7_admin_management_page',
|
||||
'dashicons-email',
|
||||
30
|
||||
);
|
||||
|
||||
$edit = add_submenu_page( 'wpcf7',
|
||||
__( 'Edit Contact Form', 'contact-form-7' ),
|
||||
__( 'Contact Forms', 'contact-form-7' )
|
||||
. wpcf7_admin_menu_change_notice( 'wpcf7' ),
|
||||
'wpcf7_read_contact_forms',
|
||||
'wpcf7',
|
||||
'wpcf7_admin_management_page'
|
||||
);
|
||||
|
||||
add_action( 'load-' . $edit, 'wpcf7_load_contact_form_admin', 10, 0 );
|
||||
|
||||
$addnew = add_submenu_page( 'wpcf7',
|
||||
__( 'Add Contact Form', 'contact-form-7' ),
|
||||
__( 'Add Contact Form', 'contact-form-7' )
|
||||
. wpcf7_admin_menu_change_notice( 'wpcf7-new' ),
|
||||
'wpcf7_edit_contact_forms',
|
||||
'wpcf7-new',
|
||||
'wpcf7_admin_add_new_page'
|
||||
);
|
||||
|
||||
add_action( 'load-' . $addnew, 'wpcf7_load_contact_form_admin', 10, 0 );
|
||||
|
||||
$integration = WPCF7_Integration::get_instance();
|
||||
|
||||
if ( $integration->service_exists() ) {
|
||||
$integration = add_submenu_page( 'wpcf7',
|
||||
__( 'Integration with External API', 'contact-form-7' ),
|
||||
__( 'Integration', 'contact-form-7' )
|
||||
. wpcf7_admin_menu_change_notice( 'wpcf7-integration' ),
|
||||
'wpcf7_manage_integration',
|
||||
'wpcf7-integration',
|
||||
'wpcf7_admin_integration_page'
|
||||
);
|
||||
|
||||
add_action( 'load-' . $integration, 'wpcf7_load_integration_page', 10, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function wpcf7_admin_menu_change_notice( $menu_slug = '' ) {
|
||||
$counts = apply_filters( 'wpcf7_admin_menu_change_notice',
|
||||
array(
|
||||
'wpcf7' => 0,
|
||||
'wpcf7-new' => 0,
|
||||
'wpcf7-integration' => 0,
|
||||
)
|
||||
);
|
||||
|
||||
if ( empty( $menu_slug ) ) {
|
||||
$count = absint( array_sum( $counts ) );
|
||||
} elseif ( isset( $counts[$menu_slug] ) ) {
|
||||
$count = absint( $counts[$menu_slug] );
|
||||
} else {
|
||||
$count = 0;
|
||||
}
|
||||
|
||||
if ( $count ) {
|
||||
return sprintf(
|
||||
' <span class="update-plugins %1$d"><span class="plugin-count">%2$s</span></span>',
|
||||
$count,
|
||||
esc_html( number_format_i18n( $count ) )
|
||||
);
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
add_action(
|
||||
'admin_enqueue_scripts',
|
||||
'wpcf7_admin_enqueue_scripts',
|
||||
10, 1
|
||||
);
|
||||
|
||||
function wpcf7_admin_enqueue_scripts( $hook_suffix ) {
|
||||
if ( false === strpos( $hook_suffix, 'wpcf7' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
wp_enqueue_style( 'contact-form-7-admin',
|
||||
wpcf7_plugin_url( 'admin/includes/css/styles.css' ),
|
||||
array(), WPCF7_VERSION, 'all'
|
||||
);
|
||||
|
||||
if ( wpcf7_is_rtl() ) {
|
||||
wp_enqueue_style( 'contact-form-7-admin-rtl',
|
||||
wpcf7_plugin_url( 'admin/includes/css/styles-rtl.css' ),
|
||||
array(), WPCF7_VERSION, 'all'
|
||||
);
|
||||
}
|
||||
|
||||
$assets = include wpcf7_plugin_path( 'admin/includes/js/index.asset.php' );
|
||||
|
||||
$assets = wp_parse_args( $assets, array(
|
||||
'dependencies' => array(),
|
||||
'version' => WPCF7_VERSION,
|
||||
) );
|
||||
|
||||
wp_enqueue_script( 'wpcf7-admin',
|
||||
wpcf7_plugin_url( 'admin/includes/js/index.js' ),
|
||||
$assets['dependencies'],
|
||||
$assets['version'],
|
||||
array( 'in_footer' => true )
|
||||
);
|
||||
|
||||
wp_set_script_translations( 'wpcf7-admin', 'contact-form-7' );
|
||||
|
||||
$wpcf7_obj = array(
|
||||
'apiSettings' => array(
|
||||
'root' => sanitize_url( rest_url( 'contact-form-7/v1' ) ),
|
||||
'namespace' => 'contact-form-7/v1',
|
||||
),
|
||||
);
|
||||
|
||||
$post = wpcf7_get_current_contact_form();
|
||||
|
||||
if ( $post ) {
|
||||
$wpcf7_obj = array_merge( $wpcf7_obj, array(
|
||||
'nonce' => array(
|
||||
'save' => wp_create_nonce(
|
||||
sprintf(
|
||||
'wpcf7-save-contact-form_%s',
|
||||
$post->initial() ? -1 : $post->id()
|
||||
)
|
||||
),
|
||||
'copy' => wp_create_nonce(
|
||||
sprintf(
|
||||
'wpcf7-copy-contact-form_%s',
|
||||
$post->initial() ? -1 : $post->id()
|
||||
)
|
||||
),
|
||||
'delete' => wp_create_nonce(
|
||||
sprintf(
|
||||
'wpcf7-delete-contact-form_%s',
|
||||
$post->initial() ? -1 : $post->id()
|
||||
)
|
||||
),
|
||||
),
|
||||
'configValidator' => array(
|
||||
'errors' => array(),
|
||||
'docUrl' => WPCF7_ConfigValidator::get_doc_link(),
|
||||
),
|
||||
) );
|
||||
|
||||
if (
|
||||
current_user_can( 'wpcf7_edit_contact_form', $post->id() ) and
|
||||
wpcf7_validate_configuration()
|
||||
) {
|
||||
$config_validator = new WPCF7_ConfigValidator( $post );
|
||||
$config_validator->restore();
|
||||
|
||||
$wpcf7_obj['configValidator'] = array_merge(
|
||||
$wpcf7_obj['configValidator'],
|
||||
array(
|
||||
'errors' => $config_validator->collect_error_messages(
|
||||
array( 'decodes_html_entities' => true )
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
wp_add_inline_script( 'wpcf7-admin',
|
||||
sprintf(
|
||||
'var wpcf7 = %s;',
|
||||
wp_json_encode( $wpcf7_obj, JSON_PRETTY_PRINT )
|
||||
),
|
||||
'before'
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
add_filter(
|
||||
'set_screen_option_wpcf7_contact_forms_per_page',
|
||||
static function ( $result, $option, $value ) {
|
||||
$wpcf7_screens = array(
|
||||
'wpcf7_contact_forms_per_page',
|
||||
);
|
||||
|
||||
if ( in_array( $option, $wpcf7_screens, true ) ) {
|
||||
$result = $value;
|
||||
}
|
||||
|
||||
return $result;
|
||||
},
|
||||
10, 3
|
||||
);
|
||||
|
||||
|
||||
function wpcf7_load_contact_form_admin() {
|
||||
global $plugin_page;
|
||||
|
||||
$action = wpcf7_current_action();
|
||||
|
||||
do_action( 'wpcf7_admin_load',
|
||||
wpcf7_superglobal_get( 'page' ),
|
||||
$action
|
||||
);
|
||||
|
||||
if ( 'save' === $action ) {
|
||||
$id = wpcf7_superglobal_post( 'post_ID', '-1' );
|
||||
|
||||
check_admin_referer( 'wpcf7-save-contact-form_' . $id );
|
||||
|
||||
if ( ! current_user_can( 'wpcf7_edit_contact_form', $id ) ) {
|
||||
wp_die(
|
||||
esc_html( __( 'You are not allowed to edit this item.', 'contact-form-7' ) )
|
||||
);
|
||||
}
|
||||
|
||||
$contact_form = wpcf7_save_contact_form(
|
||||
array_merge(
|
||||
wp_unslash( $_REQUEST ),
|
||||
array(
|
||||
'id' => $id,
|
||||
'title' => wpcf7_superglobal_post( 'post_title', null ),
|
||||
'locale' => wpcf7_superglobal_post( 'wpcf7-locale', null ),
|
||||
'form' => wpcf7_superglobal_post( 'wpcf7-form', '' ),
|
||||
'mail' => wpcf7_superglobal_post( 'wpcf7-mail', array() ),
|
||||
'mail_2' => wpcf7_superglobal_post( 'wpcf7-mail-2', array() ),
|
||||
'messages' => wpcf7_superglobal_post( 'wpcf7-messages', array() ),
|
||||
'additional_settings' => wpcf7_superglobal_post( 'wpcf7-additional-settings', '' ),
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
if ( $contact_form and wpcf7_validate_configuration() ) {
|
||||
$config_validator = new WPCF7_ConfigValidator( $contact_form );
|
||||
$config_validator->validate();
|
||||
$config_validator->save();
|
||||
}
|
||||
|
||||
$query = array(
|
||||
'post' => $contact_form ? $contact_form->id() : 0,
|
||||
'active-tab' => wpcf7_canonicalize_name(
|
||||
wpcf7_superglobal_post( 'active-tab' )
|
||||
),
|
||||
);
|
||||
|
||||
if ( ! $contact_form ) {
|
||||
$query['message'] = 'failed';
|
||||
} elseif ( -1 === (int) $id ) {
|
||||
$query['message'] = 'created';
|
||||
} else {
|
||||
$query['message'] = 'saved';
|
||||
}
|
||||
|
||||
$redirect_to = add_query_arg( $query, menu_page_url( 'wpcf7', false ) );
|
||||
wp_safe_redirect( $redirect_to );
|
||||
exit();
|
||||
}
|
||||
|
||||
if ( 'copy' === $action ) {
|
||||
$id = absint( $_POST['post_ID'] ?? $_REQUEST['post'] ?? '' );
|
||||
|
||||
check_admin_referer( 'wpcf7-copy-contact-form_' . $id );
|
||||
|
||||
if ( ! current_user_can( 'wpcf7_edit_contact_form', $id ) ) {
|
||||
wp_die(
|
||||
esc_html( __( 'You are not allowed to edit this item.', 'contact-form-7' ) )
|
||||
);
|
||||
}
|
||||
|
||||
$query = array();
|
||||
|
||||
if ( $contact_form = wpcf7_contact_form( $id ) ) {
|
||||
$new_contact_form = $contact_form->copy();
|
||||
$new_contact_form->save();
|
||||
|
||||
$query['post'] = $new_contact_form->id();
|
||||
$query['message'] = 'created';
|
||||
}
|
||||
|
||||
$redirect_to = add_query_arg( $query, menu_page_url( 'wpcf7', false ) );
|
||||
|
||||
wp_safe_redirect( $redirect_to );
|
||||
exit();
|
||||
}
|
||||
|
||||
if ( 'delete' === $action ) {
|
||||
$nonce_action = 'bulk-posts';
|
||||
|
||||
if (
|
||||
$post_id = wpcf7_superglobal_post( 'post_ID' ) or
|
||||
! is_array( $post_id = wpcf7_superglobal_request( 'post', array() ) )
|
||||
) {
|
||||
$nonce_action = sprintf( 'wpcf7-delete-contact-form_%s', $post_id );
|
||||
}
|
||||
|
||||
check_admin_referer( $nonce_action );
|
||||
|
||||
$posts = array_filter( (array) $post_id );
|
||||
|
||||
$deleted = 0;
|
||||
|
||||
foreach ( $posts as $post ) {
|
||||
$post = WPCF7_ContactForm::get_instance( $post );
|
||||
|
||||
if ( empty( $post ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( ! current_user_can( 'wpcf7_delete_contact_form', $post->id() ) ) {
|
||||
wp_die(
|
||||
esc_html( __( 'You are not allowed to delete this item.', 'contact-form-7' ) )
|
||||
);
|
||||
}
|
||||
|
||||
if ( ! $post->delete() ) {
|
||||
wp_die(
|
||||
esc_html( __( 'Error in deleting.', 'contact-form-7' ) )
|
||||
);
|
||||
}
|
||||
|
||||
$deleted += 1;
|
||||
}
|
||||
|
||||
$query = array();
|
||||
|
||||
if ( ! empty( $deleted ) ) {
|
||||
$query['message'] = 'deleted';
|
||||
}
|
||||
|
||||
$redirect_to = add_query_arg( $query, menu_page_url( 'wpcf7', false ) );
|
||||
|
||||
wp_safe_redirect( $redirect_to );
|
||||
exit();
|
||||
}
|
||||
|
||||
$post = null;
|
||||
|
||||
if ( 'wpcf7-new' === $plugin_page ) {
|
||||
$post = WPCF7_ContactForm::get_template( array(
|
||||
'locale' => wpcf7_superglobal_get( 'locale', null ),
|
||||
) );
|
||||
} elseif ( $post_id = wpcf7_superglobal_get( 'post' ) ) {
|
||||
$post = WPCF7_ContactForm::get_instance( $post_id );
|
||||
}
|
||||
|
||||
$current_screen = get_current_screen();
|
||||
|
||||
$help_tabs = new WPCF7_Help_Tabs( $current_screen );
|
||||
|
||||
if ( $post and current_user_can( 'wpcf7_edit_contact_form', $post->id() ) ) {
|
||||
$help_tabs->set_help_tabs( 'edit' );
|
||||
} else {
|
||||
$help_tabs->set_help_tabs( 'list' );
|
||||
|
||||
if ( ! class_exists( 'WPCF7_Contact_Form_List_Table' ) ) {
|
||||
require_once WPCF7_PLUGIN_DIR . '/admin/includes/class-contact-forms-list-table.php';
|
||||
}
|
||||
|
||||
add_filter(
|
||||
'manage_' . $current_screen->id . '_columns',
|
||||
array( 'WPCF7_Contact_Form_List_Table', 'define_columns' ),
|
||||
10, 0
|
||||
);
|
||||
|
||||
add_screen_option( 'per_page', array(
|
||||
'default' => 20,
|
||||
'option' => 'wpcf7_contact_forms_per_page',
|
||||
) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function wpcf7_admin_management_page() {
|
||||
if ( $post = wpcf7_get_current_contact_form() ) {
|
||||
$post_id = $post->initial() ? -1 : $post->id();
|
||||
|
||||
require_once WPCF7_PLUGIN_DIR . '/admin/includes/editor.php';
|
||||
require_once WPCF7_PLUGIN_DIR . '/admin/edit-contact-form.php';
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
'validate' === wpcf7_current_action() and
|
||||
wpcf7_validate_configuration() and
|
||||
current_user_can( 'wpcf7_edit_contact_forms' )
|
||||
) {
|
||||
wpcf7_admin_bulk_validate_page();
|
||||
return;
|
||||
}
|
||||
|
||||
$list_table = new WPCF7_Contact_Form_List_Table();
|
||||
$list_table->prepare_items();
|
||||
|
||||
$formatter = new WPCF7_HTMLFormatter( array(
|
||||
'allowed_html' => array_merge( wpcf7_kses_allowed_html(), array(
|
||||
'form' => array(
|
||||
'method' => true,
|
||||
),
|
||||
) ),
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'div', array(
|
||||
'class' => 'wrap',
|
||||
'id' => 'wpcf7-contact-form-list-table',
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'h1', array(
|
||||
'class' => 'wp-heading-inline',
|
||||
) );
|
||||
|
||||
$formatter->append_preformatted(
|
||||
esc_html( __( 'Contact Forms', 'contact-form-7' ) )
|
||||
);
|
||||
|
||||
$formatter->end_tag( 'h1' );
|
||||
|
||||
if ( current_user_can( 'wpcf7_edit_contact_forms' ) ) {
|
||||
$formatter->append_preformatted(
|
||||
wpcf7_link(
|
||||
menu_page_url( 'wpcf7-new', false ),
|
||||
__( 'Add Contact Form', 'contact-form-7' ),
|
||||
array( 'class' => 'page-title-action' )
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if ( $search_keyword = wpcf7_superglobal_request( 's' ) ) {
|
||||
$formatter->append_start_tag( 'span', array(
|
||||
'class' => 'subtitle',
|
||||
) );
|
||||
|
||||
$formatter->append_preformatted(
|
||||
sprintf(
|
||||
/* translators: %s: Search query. */
|
||||
__( 'Search results for: <strong>%s</strong>', 'contact-form-7' ),
|
||||
esc_html( $search_keyword )
|
||||
)
|
||||
);
|
||||
|
||||
$formatter->end_tag( 'span' );
|
||||
}
|
||||
|
||||
$formatter->append_start_tag( 'hr', array(
|
||||
'class' => 'wp-header-end',
|
||||
) );
|
||||
|
||||
$formatter->call_user_func( static function () {
|
||||
do_action( 'wpcf7_admin_warnings',
|
||||
'wpcf7', wpcf7_current_action(), null
|
||||
);
|
||||
|
||||
wpcf7_welcome_panel();
|
||||
|
||||
do_action( 'wpcf7_admin_notices',
|
||||
'wpcf7', wpcf7_current_action(), null
|
||||
);
|
||||
} );
|
||||
|
||||
$formatter->append_start_tag( 'form', array(
|
||||
'method' => 'get',
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'input', array(
|
||||
'type' => 'hidden',
|
||||
'name' => 'page',
|
||||
'value' => wpcf7_superglobal_request( 'page' ),
|
||||
) );
|
||||
|
||||
$formatter->call_user_func( static function () use ( $list_table ) {
|
||||
$list_table->search_box(
|
||||
__( 'Search Contact Forms', 'contact-form-7' ),
|
||||
'wpcf7-contact'
|
||||
);
|
||||
|
||||
$list_table->display();
|
||||
} );
|
||||
|
||||
$formatter->print();
|
||||
}
|
||||
|
||||
|
||||
function wpcf7_admin_add_new_page() {
|
||||
$post = wpcf7_get_current_contact_form();
|
||||
|
||||
if ( ! $post ) {
|
||||
$post = WPCF7_ContactForm::get_template();
|
||||
}
|
||||
|
||||
$post_id = -1;
|
||||
|
||||
require_once WPCF7_PLUGIN_DIR . '/admin/includes/editor.php';
|
||||
require_once WPCF7_PLUGIN_DIR . '/admin/edit-contact-form.php';
|
||||
}
|
||||
|
||||
|
||||
function wpcf7_load_integration_page() {
|
||||
do_action( 'wpcf7_admin_load',
|
||||
wpcf7_superglobal_get( 'page' ),
|
||||
wpcf7_current_action()
|
||||
);
|
||||
|
||||
$integration = WPCF7_Integration::get_instance();
|
||||
|
||||
if (
|
||||
$service_name = wpcf7_superglobal_request( 'service' ) and
|
||||
$integration->service_exists( $service_name )
|
||||
) {
|
||||
$service = $integration->get_service( $service_name );
|
||||
$service->load( wpcf7_current_action() );
|
||||
}
|
||||
|
||||
$help_tabs = new WPCF7_Help_Tabs( get_current_screen() );
|
||||
$help_tabs->set_help_tabs( 'integration' );
|
||||
}
|
||||
|
||||
|
||||
function wpcf7_admin_integration_page() {
|
||||
$integration = WPCF7_Integration::get_instance();
|
||||
|
||||
$service_name = wpcf7_superglobal_request( 'service' );
|
||||
$service = null;
|
||||
|
||||
if ( $service_name and $integration->service_exists( $service_name ) ) {
|
||||
$service = $integration->get_service( $service_name );
|
||||
}
|
||||
|
||||
$formatter = new WPCF7_HTMLFormatter( array(
|
||||
'allowed_html' => array_merge( wpcf7_kses_allowed_html(), array(
|
||||
'form' => array(
|
||||
'action' => true,
|
||||
'method' => true,
|
||||
),
|
||||
) ),
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'div', array(
|
||||
'class' => 'wrap',
|
||||
'id' => 'wpcf7-integration',
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'h1' );
|
||||
|
||||
$formatter->append_preformatted(
|
||||
esc_html( __( 'Integration with External API', 'contact-form-7' ) )
|
||||
);
|
||||
|
||||
$formatter->end_tag( 'h1' );
|
||||
|
||||
$formatter->append_start_tag( 'p' );
|
||||
|
||||
$formatter->append_preformatted(
|
||||
sprintf(
|
||||
/* translators: %s: URL to support page about integration with external APIs */
|
||||
__( 'You can expand the possibilities of your contact forms by integrating them with external services. For details, see <a href="%s">Integration with external APIs</a>.', 'contact-form-7' ),
|
||||
__( 'https://contactform7.com/integration-with-external-apis/', 'contact-form-7' )
|
||||
)
|
||||
);
|
||||
|
||||
$formatter->end_tag( 'p' );
|
||||
|
||||
$formatter->call_user_func(
|
||||
static function () use ( $integration, $service, $service_name ) {
|
||||
do_action( 'wpcf7_admin_warnings',
|
||||
'wpcf7-integration', wpcf7_current_action(), $service
|
||||
);
|
||||
|
||||
do_action( 'wpcf7_admin_notices',
|
||||
'wpcf7-integration', wpcf7_current_action(), $service
|
||||
);
|
||||
|
||||
if ( $service ) {
|
||||
$message = wpcf7_superglobal_request( 'message' );
|
||||
$service->admin_notice( $message );
|
||||
|
||||
$integration->list_services( array(
|
||||
'include' => $service_name,
|
||||
) );
|
||||
} else {
|
||||
$integration->list_services();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
$formatter->print();
|
||||
}
|
||||
|
||||
|
||||
add_action( 'wpcf7_admin_notices', 'wpcf7_admin_updated_message', 10, 3 );
|
||||
|
||||
function wpcf7_admin_updated_message( $page, $action, $object ) {
|
||||
if ( ! in_array( $page, array( 'wpcf7', 'wpcf7-new' ), true ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$message_type = wpcf7_superglobal_request( 'message' );
|
||||
|
||||
if ( ! $message_type ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$notice_type = 'success';
|
||||
|
||||
if ( 'created' === $message_type ) {
|
||||
$message = __( 'Contact form created.', 'contact-form-7' );
|
||||
} elseif ( 'saved' === $message_type ) {
|
||||
$message = __( 'Contact form saved.', 'contact-form-7' );
|
||||
} elseif ( 'deleted' === $message_type ) {
|
||||
$message = __( 'Contact form deleted.', 'contact-form-7' );
|
||||
} elseif ( 'failed' === $message_type ) {
|
||||
$notice_type = 'error';
|
||||
$message = __( 'There was an error saving the contact form.', 'contact-form-7' );
|
||||
} elseif ( 'validated' === $message_type ) {
|
||||
$bulk_validate = WPCF7::get_option( 'bulk_validate', array() );
|
||||
$count_invalid = absint( $bulk_validate['count_invalid'] ?? 0 );
|
||||
|
||||
if ( $count_invalid ) {
|
||||
$notice_type = 'warning';
|
||||
|
||||
$message = sprintf(
|
||||
/* translators: %s: number of contact forms */
|
||||
_n(
|
||||
'Configuration validation completed. %s invalid contact form was found.',
|
||||
'Configuration validation completed. %s invalid contact forms were found.',
|
||||
$count_invalid, 'contact-form-7'
|
||||
),
|
||||
number_format_i18n( $count_invalid )
|
||||
);
|
||||
} else {
|
||||
$message = __( 'Configuration validation completed. No invalid contact form was found.', 'contact-form-7' );
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! empty( $message ) ) {
|
||||
wp_admin_notice(
|
||||
$message,
|
||||
array( 'type' => $notice_type )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
add_filter( 'plugin_action_links', 'wpcf7_plugin_action_links', 10, 2 );
|
||||
|
||||
function wpcf7_plugin_action_links( $links, $file ) {
|
||||
if ( WPCF7_PLUGIN_BASENAME !== $file ) {
|
||||
return $links;
|
||||
}
|
||||
|
||||
if ( ! current_user_can( 'wpcf7_read_contact_forms' ) ) {
|
||||
return $links;
|
||||
}
|
||||
|
||||
$settings_link = wpcf7_link(
|
||||
menu_page_url( 'wpcf7', false ),
|
||||
__( 'Settings', 'contact-form-7' )
|
||||
);
|
||||
|
||||
array_unshift( $links, $settings_link );
|
||||
|
||||
return $links;
|
||||
}
|
||||
|
||||
|
||||
add_action( 'wpcf7_admin_warnings', 'wpcf7_old_wp_version_error', 10, 3 );
|
||||
|
||||
function wpcf7_old_wp_version_error( $page, $action, $object ) {
|
||||
$wp_version = get_bloginfo( 'version' );
|
||||
|
||||
if ( version_compare( $wp_version, WPCF7_REQUIRED_WP_VERSION, '<' ) ) {
|
||||
wp_admin_notice(
|
||||
sprintf(
|
||||
/* translators: 1: version of Contact Form 7, 2: version of WordPress, 3: URL */
|
||||
__( '<strong>Contact Form 7 %1$s requires WordPress %2$s or higher.</strong> Please <a href="%3$s">update WordPress</a> first.', 'contact-form-7' ),
|
||||
WPCF7_VERSION,
|
||||
WPCF7_REQUIRED_WP_VERSION,
|
||||
admin_url( 'update-core.php' )
|
||||
),
|
||||
array( 'type' => 'warning' )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
add_action( 'wpcf7_admin_warnings', 'wpcf7_not_allowed_to_edit', 10, 3 );
|
||||
|
||||
function wpcf7_not_allowed_to_edit( $page, $action, $object ) {
|
||||
if ( $object instanceof WPCF7_ContactForm ) {
|
||||
$contact_form = $object;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! current_user_can( 'wpcf7_edit_contact_form', $contact_form->id() ) ) {
|
||||
wp_admin_notice(
|
||||
__( 'You are not allowed to edit this contact form.', 'contact-form-7' ),
|
||||
array( 'type' => 'warning' )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
add_action( 'wpcf7_admin_warnings', 'wpcf7_ctct_deprecated_warning', 10, 3 );
|
||||
|
||||
function wpcf7_ctct_deprecated_warning( $page, $action, $object ) {
|
||||
$service = WPCF7_ConstantContact::get_instance();
|
||||
|
||||
if ( $service->is_active() ) {
|
||||
wp_admin_notice(
|
||||
__( 'Contact Form 7 has completed the <a href="https://contactform7.com/2025/01/08/complete-removal-of-constant-contact-integration/">removal of the Constant Contact integration</a>. We recommend <a href="https://contactform7.com/sendinblue-integration/">Brevo</a> as an alternative.', 'contact-form-7' ),
|
||||
array( 'type' => 'warning' )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
add_action( 'wpcf7_admin_warnings', 'wpcf7_captcha_future_warning', 10, 3 );
|
||||
|
||||
function wpcf7_captcha_future_warning( $page, $action, $object ) {
|
||||
$service = WPCF7_RECAPTCHA::get_instance();
|
||||
|
||||
if ( $service->is_active() ) {
|
||||
wp_admin_notice(
|
||||
__( '<strong>Attention reCAPTCHA users:</strong> Google attempts to make all reCAPTCHA users migrate to reCAPTCHA Enterprise, meaning Google charges you for API calls exceeding the free tier. Contact Form 7 supports <a href="https://contactform7.com/turnstile-integration/">Cloudflare Turnstile</a>, and we recommend it unless you have reasons to use reCAPTCHA.', 'contact-form-7' ),
|
||||
array( 'type' => 'warning' )
|
||||
);
|
||||
}
|
||||
}
|
||||
484
wp-content/plugins/contact-form-7/admin/edit-contact-form.php
Normal file
@@ -0,0 +1,484 @@
|
||||
<?php
|
||||
|
||||
// don't load directly
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
die( '-1' );
|
||||
}
|
||||
|
||||
$save_button = sprintf(
|
||||
'<input %s />',
|
||||
wpcf7_format_atts( array(
|
||||
'type' => 'submit',
|
||||
'class' => 'button-primary',
|
||||
'name' => 'wpcf7-save',
|
||||
'value' => __( 'Save', 'contact-form-7' ),
|
||||
) )
|
||||
);
|
||||
|
||||
$formatter = new WPCF7_HTMLFormatter( array(
|
||||
'allowed_html' => array_merge( wpcf7_kses_allowed_html(), array(
|
||||
'form' => array(
|
||||
'method' => true,
|
||||
'action' => true,
|
||||
'id' => true,
|
||||
'class' => true,
|
||||
'disabled' => true,
|
||||
),
|
||||
) ),
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'div', array(
|
||||
'class' => 'wrap',
|
||||
'id' => 'wpcf7-contact-form-editor',
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'h1', array(
|
||||
'class' => 'wp-heading-inline',
|
||||
) );
|
||||
|
||||
$formatter->append_preformatted(
|
||||
esc_html( $post->initial()
|
||||
? __( 'Add Contact Form', 'contact-form-7' )
|
||||
: __( 'Edit Contact Form', 'contact-form-7' )
|
||||
)
|
||||
);
|
||||
|
||||
$formatter->end_tag( 'h1' );
|
||||
|
||||
if ( ! $post->initial() and current_user_can( 'wpcf7_edit_contact_forms' ) ) {
|
||||
$formatter->append_whitespace();
|
||||
|
||||
$formatter->append_preformatted(
|
||||
wpcf7_link(
|
||||
menu_page_url( 'wpcf7-new', false ),
|
||||
__( 'Add Contact Form', 'contact-form-7' ),
|
||||
array( 'class' => 'page-title-action' )
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$formatter->append_start_tag( 'hr', array(
|
||||
'class' => 'wp-header-end',
|
||||
) );
|
||||
|
||||
$formatter->call_user_func( static function () use ( $post ) {
|
||||
do_action( 'wpcf7_admin_warnings',
|
||||
$post->initial() ? 'wpcf7-new' : 'wpcf7',
|
||||
wpcf7_current_action(),
|
||||
$post
|
||||
);
|
||||
|
||||
do_action( 'wpcf7_admin_notices',
|
||||
$post->initial() ? 'wpcf7-new' : 'wpcf7',
|
||||
wpcf7_current_action(),
|
||||
$post
|
||||
);
|
||||
} );
|
||||
|
||||
if ( $post ) {
|
||||
$formatter->append_start_tag( 'form', array(
|
||||
'method' => 'post',
|
||||
'action' => esc_url( add_query_arg(
|
||||
array( 'post' => $post_id ),
|
||||
menu_page_url( 'wpcf7', false )
|
||||
) ),
|
||||
'id' => 'wpcf7-admin-form-element',
|
||||
'disabled' => ! current_user_can( 'wpcf7_edit_contact_form', $post_id ),
|
||||
) );
|
||||
|
||||
if ( current_user_can( 'wpcf7_edit_contact_form', $post_id ) ) {
|
||||
$formatter->call_user_func( static function () use ( $post_id ) {
|
||||
wp_nonce_field( 'wpcf7-save-contact-form_' . $post_id );
|
||||
} );
|
||||
}
|
||||
|
||||
$formatter->append_start_tag( 'input', array(
|
||||
'type' => 'hidden',
|
||||
'id' => 'post_ID',
|
||||
'name' => 'post_ID',
|
||||
'value' => (int) $post_id,
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'input', array(
|
||||
'type' => 'hidden',
|
||||
'id' => 'wpcf7-locale',
|
||||
'name' => 'wpcf7-locale',
|
||||
'value' => $post->locale(),
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'input', array(
|
||||
'type' => 'hidden',
|
||||
'id' => 'hiddenaction',
|
||||
'name' => 'action',
|
||||
'value' => 'save',
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'input', array(
|
||||
'type' => 'hidden',
|
||||
'id' => 'active-tab',
|
||||
'name' => 'active-tab',
|
||||
'value' => wpcf7_superglobal_get( 'active-tab' ),
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'div', array(
|
||||
'id' => 'poststuff',
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'div', array(
|
||||
'id' => 'post-body',
|
||||
'class' => 'metabox-holder columns-2 wp-clearfix',
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'div', array(
|
||||
'id' => 'post-body-content',
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'div', array(
|
||||
'id' => 'titlediv',
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'div', array(
|
||||
'id' => 'titlewrap',
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'input', array(
|
||||
'type' => 'text',
|
||||
'name' => 'post_title',
|
||||
'value' => $post->initial() ? '' : $post->title(),
|
||||
'id' => 'title',
|
||||
'spellcheck' => 'true',
|
||||
'autocomplete' => 'off',
|
||||
'disabled' => ! current_user_can( 'wpcf7_edit_contact_form', $post_id ),
|
||||
'placeholder' => __( 'Enter title here', 'contact-form-7' ),
|
||||
'aria-label' => __( 'Enter title here', 'contact-form-7' ),
|
||||
) );
|
||||
|
||||
$formatter->end_tag( 'div' ); // #titlewrap
|
||||
|
||||
$formatter->append_start_tag( 'div', array(
|
||||
'class' => 'inside',
|
||||
) );
|
||||
|
||||
if ( ! $post->initial() ) {
|
||||
if ( $shortcode = $post->shortcode() ) {
|
||||
$formatter->append_start_tag( 'p', array(
|
||||
'class' => 'description',
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'label', array(
|
||||
'for' => 'wpcf7-shortcode',
|
||||
) );
|
||||
|
||||
$formatter->append_preformatted(
|
||||
esc_html( __( 'Copy this shortcode and paste it into your post, page, or text widget content:', 'contact-form-7' ) )
|
||||
);
|
||||
|
||||
$formatter->end_tag( 'label' );
|
||||
|
||||
$formatter->append_whitespace();
|
||||
|
||||
$formatter->append_start_tag( 'span', array(
|
||||
'class' => 'shortcode wp-ui-highlight',
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'input', array(
|
||||
'type' => 'text',
|
||||
'id' => 'wpcf7-shortcode',
|
||||
'readonly' => true,
|
||||
'class' => 'large-text code selectable',
|
||||
'value' => $shortcode,
|
||||
) );
|
||||
|
||||
$formatter->end_tag( 'p' );
|
||||
}
|
||||
|
||||
if ( $shortcode = $post->shortcode( array( 'use_old_format' => true ) ) ) {
|
||||
$formatter->append_start_tag( 'p', array(
|
||||
'class' => 'description',
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'label', array(
|
||||
'for' => 'wpcf7-shortcode-old',
|
||||
) );
|
||||
|
||||
$formatter->append_preformatted(
|
||||
esc_html( __( 'You can also use this old-style shortcode:', 'contact-form-7' ) )
|
||||
);
|
||||
|
||||
$formatter->end_tag( 'label' );
|
||||
|
||||
$formatter->append_whitespace();
|
||||
|
||||
$formatter->append_start_tag( 'span', array(
|
||||
'class' => 'shortcode old',
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'input', array(
|
||||
'type' => 'text',
|
||||
'id' => 'wpcf7-shortcode-old',
|
||||
'readonly' => true,
|
||||
'class' => 'large-text code selectable',
|
||||
'value' => $shortcode,
|
||||
) );
|
||||
|
||||
$formatter->end_tag( 'p' );
|
||||
}
|
||||
}
|
||||
|
||||
$formatter->end_tag( 'div' ); // .inside
|
||||
$formatter->end_tag( 'div' ); // #titlediv
|
||||
$formatter->end_tag( 'div' ); // #post-body-content
|
||||
|
||||
$formatter->append_start_tag( 'div', array(
|
||||
'id' => 'postbox-container-1',
|
||||
'class' => 'postbox-container',
|
||||
) );
|
||||
|
||||
if ( current_user_can( 'wpcf7_edit_contact_form', $post_id ) ) {
|
||||
$formatter->append_start_tag( 'section', array(
|
||||
'id' => 'submitdiv',
|
||||
'class' => 'postbox',
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'h2' );
|
||||
|
||||
$formatter->append_preformatted(
|
||||
esc_html( __( 'Status', 'contact-form-7' ) )
|
||||
);
|
||||
|
||||
$formatter->end_tag( 'h2' );
|
||||
|
||||
$formatter->append_start_tag( 'div', array(
|
||||
'class' => 'inside',
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'div', array(
|
||||
'class' => 'submitbox',
|
||||
'id' => 'submitpost',
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'div', array(
|
||||
'id' => 'minor-publishing-actions',
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'div', array(
|
||||
'class' => 'hidden',
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'input', array(
|
||||
'type' => 'submit',
|
||||
'class' => 'button-primary',
|
||||
'name' => 'wpcf7-save',
|
||||
'value' => __( 'Save', 'contact-form-7' ),
|
||||
) );
|
||||
|
||||
$formatter->end_tag( 'div' ); // .hidden
|
||||
|
||||
if ( ! $post->initial() ) {
|
||||
$formatter->append_start_tag( 'input', array(
|
||||
'type' => 'submit',
|
||||
'name' => 'wpcf7-copy',
|
||||
'class' => 'copy button',
|
||||
'value' => __( 'Duplicate', 'contact-form-7' ),
|
||||
) );
|
||||
}
|
||||
|
||||
$formatter->end_tag( 'div' ); // #minor-publishing-actions
|
||||
|
||||
$formatter->append_start_tag( 'div', array(
|
||||
'id' => 'misc-publishing-actions',
|
||||
) );
|
||||
|
||||
$formatter->call_user_func( static function () use ( $post_id ) {
|
||||
do_action( 'wpcf7_admin_misc_pub_section', $post_id );
|
||||
} );
|
||||
|
||||
$formatter->end_tag( 'div' ); // #misc-publishing-actions
|
||||
|
||||
$formatter->append_start_tag( 'div', array(
|
||||
'id' => 'major-publishing-actions',
|
||||
) );
|
||||
|
||||
if ( ! $post->initial() ) {
|
||||
$formatter->append_start_tag( 'div', array(
|
||||
'id' => 'delete-action',
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'input', array(
|
||||
'type' => 'submit',
|
||||
'name' => 'wpcf7-delete',
|
||||
'class' => 'delete submitdelete',
|
||||
'value' => __( 'Delete', 'contact-form-7' ),
|
||||
) );
|
||||
|
||||
$formatter->end_tag( 'div' ); // #delete-action
|
||||
}
|
||||
|
||||
$formatter->append_start_tag( 'div', array(
|
||||
'id' => 'publishing-action',
|
||||
) );
|
||||
|
||||
$formatter->append_preformatted( '<span class="spinner"></span>' );
|
||||
$formatter->append_preformatted( $save_button );
|
||||
|
||||
$formatter->end_tag( 'div' ); // #publishing-action
|
||||
|
||||
$formatter->append_preformatted( '<div class="clear"></div>' );
|
||||
|
||||
$formatter->end_tag( 'div' ); // #major-publishing-actions
|
||||
$formatter->end_tag( 'div' ); // #submitpost
|
||||
$formatter->end_tag( 'div' ); // .inside
|
||||
$formatter->end_tag( 'section' ); // #submitdiv
|
||||
}
|
||||
|
||||
$formatter->append_start_tag( 'section', array(
|
||||
'id' => 'informationdiv',
|
||||
'class' => 'postbox',
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'h2' );
|
||||
|
||||
$formatter->append_preformatted(
|
||||
esc_html( __( 'Do you need help?', 'contact-form-7' ) )
|
||||
);
|
||||
|
||||
$formatter->end_tag( 'h2' );
|
||||
|
||||
$formatter->append_start_tag( 'div', array(
|
||||
'class' => 'inside',
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'p' );
|
||||
|
||||
$formatter->append_preformatted(
|
||||
esc_html( __( 'Here are some available options to help solve your problems.', 'contact-form-7' ) )
|
||||
);
|
||||
|
||||
$formatter->end_tag( 'p' );
|
||||
|
||||
$formatter->append_start_tag( 'ol' );
|
||||
|
||||
$formatter->append_start_tag( 'li' );
|
||||
|
||||
$formatter->append_preformatted(
|
||||
sprintf(
|
||||
/* translators: 1: URL to FAQ, 2: URL to docs */
|
||||
'<a href="%1$s">FAQ</a> and <a href="%2$s">docs</a>',
|
||||
__( 'https://contactform7.com/faq/', 'contact-form-7' ),
|
||||
__( 'https://contactform7.com/docs/', 'contact-form-7' )
|
||||
)
|
||||
);
|
||||
|
||||
$formatter->append_start_tag( 'li' );
|
||||
|
||||
$formatter->append_preformatted(
|
||||
wpcf7_link(
|
||||
__( 'https://wordpress.org/support/plugin/contact-form-7/', 'contact-form-7' ),
|
||||
__( 'Support forums', 'contact-form-7' )
|
||||
)
|
||||
);
|
||||
|
||||
$formatter->append_start_tag( 'li' );
|
||||
|
||||
$formatter->append_preformatted(
|
||||
wpcf7_link(
|
||||
__( 'https://contactform7.com/custom-development/', 'contact-form-7' ),
|
||||
__( 'Professional services', 'contact-form-7' )
|
||||
)
|
||||
);
|
||||
|
||||
$formatter->end_tag( 'ol' );
|
||||
$formatter->end_tag( 'div' ); // .inside
|
||||
$formatter->end_tag( 'section' ); // #informationdiv
|
||||
$formatter->end_tag( 'div' ); // #postbox-container-1
|
||||
|
||||
$formatter->append_start_tag( 'div', array(
|
||||
'id' => 'postbox-container-2',
|
||||
'class' => 'postbox-container',
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'div', array(
|
||||
'id' => 'contact-form-editor',
|
||||
) );
|
||||
|
||||
$formatter->call_user_func( static function () use ( $post, $post_id ) {
|
||||
$editor = new WPCF7_Editor( $post );
|
||||
$panels = array();
|
||||
|
||||
if ( current_user_can( 'wpcf7_edit_contact_form', $post_id ) ) {
|
||||
$panels = array(
|
||||
'form-panel' => array(
|
||||
'title' => __( 'Form', 'contact-form-7' ),
|
||||
'callback' => 'wpcf7_editor_panel_form',
|
||||
),
|
||||
'mail-panel' => array(
|
||||
'title' => __( 'Mail', 'contact-form-7' ),
|
||||
'callback' => 'wpcf7_editor_panel_mail',
|
||||
),
|
||||
'messages-panel' => array(
|
||||
'title' => __( 'Messages', 'contact-form-7' ),
|
||||
'callback' => 'wpcf7_editor_panel_messages',
|
||||
),
|
||||
);
|
||||
|
||||
$additional_settings = $post->prop( 'additional_settings' );
|
||||
|
||||
if ( ! is_scalar( $additional_settings ) ) {
|
||||
$additional_settings = '';
|
||||
}
|
||||
|
||||
$additional_settings = trim( $additional_settings );
|
||||
$additional_settings = explode( "\n", $additional_settings );
|
||||
$additional_settings = array_filter( $additional_settings );
|
||||
$additional_settings = count( $additional_settings );
|
||||
|
||||
$panels['additional-settings-panel'] = array(
|
||||
'title' => $additional_settings
|
||||
? sprintf(
|
||||
/* translators: %d: number of additional settings */
|
||||
__( 'Additional Settings (%d)', 'contact-form-7' ),
|
||||
$additional_settings
|
||||
)
|
||||
: __( 'Additional Settings', 'contact-form-7' ),
|
||||
'callback' => 'wpcf7_editor_panel_additional_settings',
|
||||
);
|
||||
}
|
||||
|
||||
$panels = apply_filters( 'wpcf7_editor_panels', $panels );
|
||||
|
||||
foreach ( $panels as $id => $panel ) {
|
||||
$editor->add_panel( $id, $panel['title'], $panel['callback'] );
|
||||
}
|
||||
|
||||
$editor->display();
|
||||
} );
|
||||
|
||||
$formatter->end_tag( 'div' ); // #contact-form-editor
|
||||
|
||||
if ( current_user_can( 'wpcf7_edit_contact_form', $post_id ) ) {
|
||||
$formatter->append_start_tag( 'p', array(
|
||||
'class' => 'submit',
|
||||
) );
|
||||
|
||||
$formatter->append_preformatted( $save_button );
|
||||
|
||||
$formatter->end_tag( 'p' );
|
||||
}
|
||||
|
||||
$formatter->end_tag( 'div' ); // #postbox-container-2
|
||||
$formatter->end_tag( 'div' ); // #post-body
|
||||
|
||||
$formatter->append_preformatted( '<br class="clear" />' );
|
||||
|
||||
$formatter->end_tag( 'div' ); // #poststuff
|
||||
$formatter->end_tag( 'form' );
|
||||
}
|
||||
|
||||
$formatter->end_tag( 'div' ); // .wrap
|
||||
|
||||
$formatter->print();
|
||||
|
||||
$tag_generator = WPCF7_TagGenerator::get_instance();
|
||||
$tag_generator->print_panels( $post );
|
||||
|
||||
do_action( 'wpcf7_admin_footer', $post );
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
function wpcf7_current_action() {
|
||||
foreach ( array( 'action', 'action2' ) as $var ) {
|
||||
$action = wpcf7_superglobal_request( $var, null );
|
||||
|
||||
if ( isset( $action ) and -1 !== $action ) {
|
||||
return $action;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function wpcf7_admin_has_edit_cap() {
|
||||
return current_user_can( 'wpcf7_edit_contact_forms' );
|
||||
}
|
||||
|
||||
function wpcf7_add_tag_generator( $name, $title, $elm_id, $callback, $options = array() ) {
|
||||
$tag_generator = WPCF7_TagGenerator::get_instance();
|
||||
return $tag_generator->add( $name, $title, $callback, $options );
|
||||
}
|
||||
@@ -0,0 +1,241 @@
|
||||
<?php
|
||||
|
||||
if ( ! class_exists( 'WP_List_Table' ) ) {
|
||||
require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
|
||||
}
|
||||
|
||||
class WPCF7_Contact_Form_List_Table extends WP_List_Table {
|
||||
|
||||
public static function define_columns() {
|
||||
$columns = array(
|
||||
'cb' => '<input type="checkbox" />',
|
||||
'title' => __( 'Title', 'contact-form-7' ),
|
||||
'shortcode' => __( 'Shortcode', 'contact-form-7' ),
|
||||
'author' => __( 'Author', 'contact-form-7' ),
|
||||
'date' => __( 'Date', 'contact-form-7' ),
|
||||
);
|
||||
|
||||
return $columns;
|
||||
}
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct( array(
|
||||
'singular' => 'post',
|
||||
'plural' => 'posts',
|
||||
'ajax' => false,
|
||||
) );
|
||||
}
|
||||
|
||||
public function prepare_items() {
|
||||
$current_screen = get_current_screen();
|
||||
$per_page = $this->get_items_per_page( 'wpcf7_contact_forms_per_page' );
|
||||
|
||||
$args = array(
|
||||
'posts_per_page' => $per_page,
|
||||
'orderby' => 'title',
|
||||
'order' => 'ASC',
|
||||
'offset' => ( $this->get_pagenum() - 1 ) * $per_page,
|
||||
);
|
||||
|
||||
if ( $search_keyword = wpcf7_superglobal_request( 's' ) ) {
|
||||
$args['s'] = $search_keyword;
|
||||
}
|
||||
|
||||
if ( $order_by = wpcf7_superglobal_request( 'orderby' ) ) {
|
||||
$args['orderby'] = $order_by;
|
||||
}
|
||||
|
||||
if (
|
||||
$order = wpcf7_superglobal_request( 'order' ) and
|
||||
'desc' === strtolower( $order )
|
||||
) {
|
||||
$args['order'] = 'DESC';
|
||||
}
|
||||
|
||||
$this->items = WPCF7_ContactForm::find( $args );
|
||||
|
||||
$total_items = WPCF7_ContactForm::count();
|
||||
$total_pages = ceil( $total_items / $per_page );
|
||||
|
||||
$this->set_pagination_args( array(
|
||||
'total_items' => $total_items,
|
||||
'total_pages' => $total_pages,
|
||||
'per_page' => $per_page,
|
||||
) );
|
||||
}
|
||||
|
||||
public function get_columns() {
|
||||
return get_column_headers( get_current_screen() );
|
||||
}
|
||||
|
||||
protected function get_sortable_columns() {
|
||||
$columns = array(
|
||||
'title' => array( 'title', true ),
|
||||
'author' => array( 'author', false ),
|
||||
'date' => array( 'date', false ),
|
||||
);
|
||||
|
||||
return $columns;
|
||||
}
|
||||
|
||||
protected function get_bulk_actions() {
|
||||
$actions = array(
|
||||
'delete' => __( 'Delete', 'contact-form-7' ),
|
||||
);
|
||||
|
||||
return $actions;
|
||||
}
|
||||
|
||||
protected function column_default( $item, $column_name ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
public function column_cb( $item ) {
|
||||
return sprintf(
|
||||
'<input type="checkbox" name="%1$s[]" value="%2$s" />',
|
||||
$this->_args['singular'],
|
||||
$item->id()
|
||||
);
|
||||
}
|
||||
|
||||
public function column_title( $item ) {
|
||||
$edit_link = add_query_arg(
|
||||
array(
|
||||
'post' => absint( $item->id() ),
|
||||
'action' => 'edit',
|
||||
),
|
||||
menu_page_url( 'wpcf7', false )
|
||||
);
|
||||
|
||||
$output = sprintf(
|
||||
'<a class="row-title" href="%1$s" aria-label="%2$s">%3$s</a>',
|
||||
esc_url( $edit_link ),
|
||||
esc_attr( sprintf(
|
||||
/* translators: %s: title of contact form */
|
||||
__( 'Edit “%s”', 'contact-form-7' ),
|
||||
$item->title()
|
||||
) ),
|
||||
esc_html( $item->title() )
|
||||
);
|
||||
|
||||
$output = sprintf( '<strong>%s</strong>', $output );
|
||||
|
||||
if ( wpcf7_validate_configuration()
|
||||
and current_user_can( 'wpcf7_edit_contact_form', $item->id() ) ) {
|
||||
$config_validator = new WPCF7_ConfigValidator( $item );
|
||||
$config_validator->restore();
|
||||
|
||||
if ( $count_errors = $config_validator->count_errors() ) {
|
||||
$error_notice = sprintf(
|
||||
/* translators: %s: number of errors detected */
|
||||
_n(
|
||||
'%s configuration error detected',
|
||||
'%s configuration errors detected',
|
||||
$count_errors, 'contact-form-7' ),
|
||||
number_format_i18n( $count_errors )
|
||||
);
|
||||
|
||||
$output .= sprintf(
|
||||
'<div class="config-error"><span class="icon-in-circle" aria-hidden="true">!</span> %s</div>',
|
||||
$error_notice
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
protected function handle_row_actions( $item, $column_name, $primary ) {
|
||||
if ( $column_name !== $primary ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$edit_link = add_query_arg(
|
||||
array(
|
||||
'post' => absint( $item->id() ),
|
||||
'action' => 'edit',
|
||||
),
|
||||
menu_page_url( 'wpcf7', false )
|
||||
);
|
||||
|
||||
$actions = array(
|
||||
'edit' => wpcf7_link( $edit_link, __( 'Edit', 'contact-form-7' ) ),
|
||||
);
|
||||
|
||||
if ( current_user_can( 'wpcf7_edit_contact_form', $item->id() ) ) {
|
||||
$copy_link = add_query_arg(
|
||||
array(
|
||||
'post' => absint( $item->id() ),
|
||||
'action' => 'copy',
|
||||
),
|
||||
menu_page_url( 'wpcf7', false )
|
||||
);
|
||||
|
||||
$copy_link = wp_nonce_url(
|
||||
$copy_link,
|
||||
'wpcf7-copy-contact-form_' . absint( $item->id() )
|
||||
);
|
||||
|
||||
$actions = array_merge( $actions, array(
|
||||
'copy' => wpcf7_link( $copy_link, __( 'Duplicate', 'contact-form-7' ) ),
|
||||
) );
|
||||
}
|
||||
|
||||
return $this->row_actions( $actions );
|
||||
}
|
||||
|
||||
public function column_author( $item ) {
|
||||
$post = get_post( $item->id() );
|
||||
|
||||
if ( ! $post ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$author = get_userdata( $post->post_author );
|
||||
|
||||
if ( false === $author ) {
|
||||
return;
|
||||
}
|
||||
|
||||
return esc_html( $author->display_name );
|
||||
}
|
||||
|
||||
public function column_shortcode( $item ) {
|
||||
$shortcodes = array( $item->shortcode() );
|
||||
|
||||
$output = '';
|
||||
|
||||
foreach ( $shortcodes as $shortcode ) {
|
||||
$output .= "\n" . sprintf(
|
||||
'<span class="shortcode"><input %s /></span>',
|
||||
wpcf7_format_atts( array(
|
||||
'type' => 'text',
|
||||
'readonly' => true,
|
||||
'value' => $shortcode,
|
||||
'class' => 'large-text code selectable',
|
||||
) )
|
||||
);
|
||||
}
|
||||
|
||||
return trim( $output );
|
||||
}
|
||||
|
||||
public function column_date( $item ) {
|
||||
$datetime = get_post_datetime( $item->id() );
|
||||
|
||||
if ( false === $datetime ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$t_time = sprintf(
|
||||
/* translators: 1: date, 2: time */
|
||||
__( '%1$s at %2$s', 'contact-form-7' ),
|
||||
/* translators: date format, see https://www.php.net/date */
|
||||
$datetime->format( __( 'Y/m/d', 'contact-form-7' ) ),
|
||||
/* translators: time format, see https://www.php.net/date */
|
||||
$datetime->format( __( 'g:i a', 'contact-form-7' ) )
|
||||
);
|
||||
|
||||
return $t_time;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
<?php
|
||||
|
||||
add_action( 'wpcf7_admin_menu', 'wpcf7_admin_init_bulk_cv', 10, 0 );
|
||||
|
||||
function wpcf7_admin_init_bulk_cv() {
|
||||
if (
|
||||
! wpcf7_validate_configuration() or
|
||||
! current_user_can( 'wpcf7_edit_contact_forms' )
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
$result = WPCF7::get_option( 'bulk_validate' );
|
||||
$last_important_update = WPCF7_ConfigValidator::last_important_update;
|
||||
|
||||
if (
|
||||
! empty( $result['version'] ) and
|
||||
version_compare( $last_important_update, $result['version'], '<=' )
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
add_filter( 'wpcf7_admin_menu_change_notice',
|
||||
'wpcf7_admin_menu_change_notice_bulk_cv',
|
||||
10, 1
|
||||
);
|
||||
|
||||
add_action( 'wpcf7_admin_warnings',
|
||||
'wpcf7_admin_warnings_bulk_cv',
|
||||
5, 3
|
||||
);
|
||||
}
|
||||
|
||||
function wpcf7_admin_menu_change_notice_bulk_cv( $counts ) {
|
||||
$counts['wpcf7'] += 1;
|
||||
return $counts;
|
||||
}
|
||||
|
||||
function wpcf7_admin_warnings_bulk_cv( $page, $action, $object ) {
|
||||
if ( 'wpcf7' === $page and 'validate' === $action ) {
|
||||
return;
|
||||
}
|
||||
|
||||
wp_admin_notice(
|
||||
sprintf(
|
||||
'%1$s » %2$s',
|
||||
__( 'Misconfiguration leads to mail delivery failure or other troubles. Validate your contact forms now.', 'contact-form-7' ),
|
||||
wpcf7_link(
|
||||
add_query_arg(
|
||||
array( 'action' => 'validate' ),
|
||||
menu_page_url( 'wpcf7', false )
|
||||
),
|
||||
__( 'Validate Contact Form 7 Configuration', 'contact-form-7' )
|
||||
)
|
||||
),
|
||||
array( 'type' => 'warning' )
|
||||
);
|
||||
}
|
||||
|
||||
add_action( 'wpcf7_admin_load', 'wpcf7_load_bulk_validate_page', 10, 2 );
|
||||
|
||||
function wpcf7_load_bulk_validate_page( $page, $action ) {
|
||||
if (
|
||||
'wpcf7' !== $page or
|
||||
'validate' !== $action or
|
||||
! wpcf7_validate_configuration() or
|
||||
'POST' !== wpcf7_superglobal_server( 'REQUEST_METHOD' )
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
check_admin_referer( 'wpcf7-bulk-validate' );
|
||||
|
||||
if ( ! current_user_can( 'wpcf7_edit_contact_forms' ) ) {
|
||||
wp_die( wp_kses_data( __( 'You are not allowed to validate configuration.', 'contact-form-7' ) ) );
|
||||
}
|
||||
|
||||
$contact_forms = WPCF7_ContactForm::find();
|
||||
|
||||
$result = array(
|
||||
'timestamp' => time(),
|
||||
'version' => WPCF7_VERSION,
|
||||
'count_valid' => 0,
|
||||
'count_invalid' => 0,
|
||||
);
|
||||
|
||||
foreach ( $contact_forms as $contact_form ) {
|
||||
$config_validator = new WPCF7_ConfigValidator( $contact_form );
|
||||
$config_validator->validate();
|
||||
$config_validator->save();
|
||||
|
||||
if ( $config_validator->is_valid() ) {
|
||||
$result['count_valid'] += 1;
|
||||
} else {
|
||||
$result['count_invalid'] += 1;
|
||||
}
|
||||
}
|
||||
|
||||
WPCF7::update_option( 'bulk_validate', $result );
|
||||
|
||||
$redirect_to = add_query_arg(
|
||||
array(
|
||||
'message' => 'validated',
|
||||
),
|
||||
menu_page_url( 'wpcf7', false )
|
||||
);
|
||||
|
||||
wp_safe_redirect( $redirect_to );
|
||||
exit();
|
||||
}
|
||||
|
||||
function wpcf7_admin_bulk_validate_page() {
|
||||
$contact_forms = WPCF7_ContactForm::find();
|
||||
$count = WPCF7_ContactForm::count();
|
||||
|
||||
$submit_text = sprintf(
|
||||
/* translators: %s: number of contact forms */
|
||||
_n(
|
||||
'Validate %s contact form now',
|
||||
'Validate %s contact forms now',
|
||||
$count, 'contact-form-7'
|
||||
),
|
||||
number_format_i18n( $count )
|
||||
);
|
||||
|
||||
$formatter = new WPCF7_HTMLFormatter( array(
|
||||
'allowed_html' => array_merge( wpcf7_kses_allowed_html(), array(
|
||||
'form' => array(
|
||||
'action' => true,
|
||||
'method' => true,
|
||||
),
|
||||
) ),
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'div', array(
|
||||
'class' => 'wrap',
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'h1' );
|
||||
|
||||
$formatter->append_preformatted(
|
||||
esc_html( __( 'Validate Configuration', 'contact-form-7' ) )
|
||||
);
|
||||
|
||||
$formatter->end_tag( 'h1' );
|
||||
|
||||
$formatter->append_start_tag( 'form', array(
|
||||
'method' => 'post',
|
||||
'action' => '',
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'p' );
|
||||
|
||||
$formatter->call_user_func( static function () {
|
||||
wp_nonce_field( 'wpcf7-bulk-validate' );
|
||||
} );
|
||||
|
||||
$formatter->append_start_tag( 'input', array(
|
||||
'type' => 'hidden',
|
||||
'name' => 'action',
|
||||
'value' => 'validate',
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'input', array(
|
||||
'type' => 'submit',
|
||||
'class' => 'button',
|
||||
'value' => $submit_text,
|
||||
) );
|
||||
|
||||
$formatter->end_tag( 'form' );
|
||||
|
||||
$formatter->append_preformatted(
|
||||
wpcf7_link(
|
||||
__( 'https://contactform7.com/configuration-validator-faq/', 'contact-form-7' ),
|
||||
__( 'FAQ about Configuration Validator', 'contact-form-7' )
|
||||
)
|
||||
);
|
||||
|
||||
$formatter->print();
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Form Tab
|
||||
*/
|
||||
.tag-generator-panel {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.tag-generator-dialog > .close-button {
|
||||
right: auto;
|
||||
left: 8px;
|
||||
}
|
||||
|
||||
form.tag-generator-panel[data-version="1"] {
|
||||
.control-box > fieldset > legend {
|
||||
border: 1px solid #dfdfdf;
|
||||
border-right: 4px solid #00a0d2;
|
||||
}
|
||||
|
||||
.insert-box input.tag {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.insert-box .submitbox input[type="button"] {
|
||||
float: left;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Mail Tab
|
||||
*/
|
||||
.contact-form-editor-box-mail span.mailtag {
|
||||
margin: 0 4px 0 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Welcome Panel
|
||||
*/
|
||||
.wpcf7-welcome-panel .welcome-panel-close {
|
||||
left: 10px;
|
||||
right: auto;
|
||||
padding: 10px 21px 10px 15px;
|
||||
}
|
||||
|
||||
.wpcf7-welcome-panel .welcome-panel-close::before {
|
||||
right: 0;
|
||||
left: auto;
|
||||
}
|
||||
|
||||
.wpcf7-welcome-panel .welcome-panel-content {
|
||||
margin-right: 13px;
|
||||
}
|
||||
|
||||
.wpcf7-welcome-panel .welcome-panel-column {
|
||||
float: right;
|
||||
padding: 0 0 0 2%;
|
||||
}
|
||||
|
||||
/*
|
||||
* Integration
|
||||
*/
|
||||
.card {
|
||||
border-left: 1px solid #e5e5e5;
|
||||
border-right: 4px solid #e5e5e5;
|
||||
}
|
||||
|
||||
.card img.icon {
|
||||
float: right;
|
||||
margin: 8px -8px 8px 8px;
|
||||
}
|
||||
|
||||
.card h2.title {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.card .infobox {
|
||||
float: left;
|
||||
}
|
||||
614
wp-content/plugins/contact-form-7/admin/includes/css/styles.css
Normal file
@@ -0,0 +1,614 @@
|
||||
#titlediv .inside p.description {
|
||||
margin: 8px 2px 0;
|
||||
}
|
||||
|
||||
#titlediv .inside p.description label {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
span.shortcode {
|
||||
display: block;
|
||||
margin: 2px 0;
|
||||
}
|
||||
|
||||
span.shortcode.old {
|
||||
background: #777;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
span.shortcode input {
|
||||
font-size: 12px;
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
padding: 4px 8px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#wpcf7-contact-form-list-table span.shortcode input,
|
||||
#wpcf7-contact-form-editor span.shortcode input {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
#wpcf7-contact-form-list-table span.shortcode input {
|
||||
color: #444;
|
||||
}
|
||||
|
||||
#wpcf7-contact-form-editor span.shortcode input {
|
||||
color: #fff;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#submitpost input.copy {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#submitpost input.delete {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
background: inherit;
|
||||
color: #a00;
|
||||
}
|
||||
|
||||
#submitpost input.delete:hover {
|
||||
color: #dc3232; /* Red */
|
||||
}
|
||||
|
||||
#submitpost input.delete:focus {
|
||||
outline: thin dotted;
|
||||
}
|
||||
|
||||
.postbox-container .postbox h3 {
|
||||
border-bottom: 1px solid transparent;
|
||||
}
|
||||
|
||||
div.config-error, span.config-error, ul.config-error {
|
||||
color: #444;
|
||||
font-style: normal;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
ul.config-error {
|
||||
margin: 2px 0;
|
||||
}
|
||||
|
||||
ul.config-error li {
|
||||
list-style: none;
|
||||
padding: 2px 2px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#misc-publishing-actions .config-error {
|
||||
line-height: 2;
|
||||
}
|
||||
|
||||
[data-config-field][aria-invalid="true"] {
|
||||
border-color: #dc3232;
|
||||
}
|
||||
|
||||
#contact-form-editor-tabs .icon-in-circle,
|
||||
#contact-form-editor .config-error .icon-in-circle,
|
||||
.wp-list-table .config-error .icon-in-circle,
|
||||
.icon-in-circle {
|
||||
display: inline-block;
|
||||
vertical-align: baseline;
|
||||
margin: 1px 6px 0;
|
||||
padding: 0 5px;
|
||||
min-width: 7px;
|
||||
height: 17px;
|
||||
border-radius: 11px;
|
||||
background-color: #ca4a1f;
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
line-height: 17px;
|
||||
text-align: center;
|
||||
z-index: 26;
|
||||
}
|
||||
|
||||
/*
|
||||
* Tabs
|
||||
*/
|
||||
#contact-form-editor-tabs {
|
||||
border-bottom: 1px solid #aaa;
|
||||
padding: 9px 10px 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#contact-form-editor-tabs button {
|
||||
display: inline-block;
|
||||
border: 1px solid #ccc;
|
||||
border-bottom: 1px solid #aaa;
|
||||
padding: 6px 10px;
|
||||
margin: 0 4px -1px;
|
||||
color: #333;
|
||||
background-color: #e4e4e4;
|
||||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
#contact-form-editor-tabs button[aria-selected="true"] {
|
||||
border-top: 1px solid #aaa;
|
||||
border-right: 1px solid #aaa;
|
||||
border-left: 1px solid #aaa;
|
||||
border-bottom: 1px solid #f5f5f5;
|
||||
color: #000;
|
||||
background-color: #f5f5f5;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#contact-form-editor-tabs button:hover {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
#contact-form-editor .contact-form-editor-panel > div.config-error {
|
||||
margin-bottom: 1.4em;
|
||||
}
|
||||
|
||||
#contact-form-editor-tabs button[aria-selected="true"] .icon-in-circle {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#contact-form-editor .contact-form-editor-panel h2 {
|
||||
font-size: 18px;
|
||||
font-weight: 400;
|
||||
line-height: 24px;
|
||||
margin: 8px 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#contact-form-editor .contact-form-editor-panel {
|
||||
background-color: #f5f5f5;
|
||||
border: 1px solid #aaa;
|
||||
border-top: none;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
#contact-form-editor .form-table th {
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
#contact-form-editor .contact-form-editor-panel fieldset legend {
|
||||
line-height: 1.5;
|
||||
margin: .6em 0 .4em;
|
||||
}
|
||||
|
||||
/*
|
||||
* Form Tab
|
||||
*/
|
||||
#tag-generator-list button {
|
||||
font-size: 12px;
|
||||
height: 26px;
|
||||
line-height: 24px;
|
||||
margin: 2px;
|
||||
padding: 0 8px 1px;
|
||||
}
|
||||
|
||||
.tag-generator-dialog {
|
||||
padding: 12px;
|
||||
border: 1px solid #c3c4c7;
|
||||
box-shadow: 0 1px 1px rgba( 0, 0, 0, 0.04 );
|
||||
height: 720px;
|
||||
width: 720px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.tag-generator-dialog::backdrop {
|
||||
background: rgb( 0 0 0 / 50% );
|
||||
}
|
||||
|
||||
.tag-generator-dialog > .close-button {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 8px;
|
||||
}
|
||||
|
||||
form.tag-generator-panel {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 720px;
|
||||
width: 720px;
|
||||
max-height: 100%;
|
||||
max-width: 100%;
|
||||
margin-block-end: 0;
|
||||
}
|
||||
|
||||
form.tag-generator-panel[data-version="2"] {
|
||||
&:invalid .mail-tag-tip {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.description-box {
|
||||
box-sizing: border-box;
|
||||
flex: none;
|
||||
margin-inline: -12px;
|
||||
padding-inline: 12px;
|
||||
border-bottom: 1px solid #dfdfdf;
|
||||
}
|
||||
|
||||
.control-box {
|
||||
box-sizing: border-box;
|
||||
flex: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px 0;
|
||||
min-height: 120px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.control-box > fieldset {
|
||||
margin-block: 8px;
|
||||
margin-inline-start: 10em;
|
||||
line-height: 2.25;
|
||||
}
|
||||
|
||||
.control-box > fieldset > legend {
|
||||
font-weight: bolder;
|
||||
margin-block: 8px;
|
||||
margin-inline-start: -10em;
|
||||
line-height: 1.25;
|
||||
}
|
||||
|
||||
.control-box input[type="text"] {
|
||||
width: 20rem;
|
||||
max-width: 88%;
|
||||
}
|
||||
|
||||
.control-box input[type="number"] {
|
||||
width: 8rem;
|
||||
max-width: 44%;
|
||||
}
|
||||
|
||||
.control-box textarea {
|
||||
height: 12ex;
|
||||
width: 20rem;
|
||||
max-width: 88%;
|
||||
}
|
||||
|
||||
.control-box select {
|
||||
width: 20rem;
|
||||
max-width: 88%;
|
||||
}
|
||||
|
||||
.control-box input:invalid,
|
||||
.control-box textarea:invalid {
|
||||
background-color: #ffe9de;
|
||||
}
|
||||
|
||||
.insert-box {
|
||||
box-sizing: border-box;
|
||||
flex: none;
|
||||
margin-block-end: -12px;
|
||||
margin-inline: -12px;
|
||||
padding-block: 24px 12px;
|
||||
padding-inline: 12px;
|
||||
background-color: #fcfcfc;
|
||||
border-top: 1px solid #dfdfdf;
|
||||
}
|
||||
|
||||
.insert-box .flex-container {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.insert-box .flex-container > [data-tag-part="tag"] {
|
||||
flex: auto;
|
||||
margin-inline-end: 8px;
|
||||
}
|
||||
|
||||
.insert-box .mail-tag-tip::before {
|
||||
font: 1.2rem dashicons;
|
||||
content: "\f348" / '';
|
||||
color: #646970;
|
||||
padding-inline-end: 4px;
|
||||
vertical-align: top;
|
||||
}
|
||||
}
|
||||
|
||||
form.tag-generator-panel[data-version="1"] {
|
||||
.control-box {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
overflow: auto;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.control-box > fieldset > legend {
|
||||
border: 1px solid #dfdfdf;
|
||||
border-left: 4px solid #00a0d2;
|
||||
background: #f7fcfe;
|
||||
padding: 4px 12px;
|
||||
margin: 4px 0;
|
||||
line-height: 1.4em;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
table.form-table th {
|
||||
width: 120px;
|
||||
padding: 4px 10px 4px 0;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
table.form-table td {
|
||||
padding: 4px 10px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.control-box input.oneline {
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
.control-box input.large-text {
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
.control-box textarea.values {
|
||||
width: 200px;
|
||||
height: 6em;
|
||||
}
|
||||
|
||||
.control-box input[type="number"],
|
||||
.control-box input[type="date"] {
|
||||
width: 88px;
|
||||
}
|
||||
|
||||
.control-box table caption {
|
||||
text-align: left;
|
||||
font-size: 110%;
|
||||
font-weight: bold;
|
||||
color: #777;
|
||||
margin: 10px 0 5px;
|
||||
}
|
||||
|
||||
.control-box table.form-table td label {
|
||||
line-height: 1.1em;
|
||||
}
|
||||
|
||||
.control-box table.form-table td label .description {
|
||||
line-height: 1.4em;
|
||||
}
|
||||
|
||||
.insert-box {
|
||||
margin: 0 -15px -15px;
|
||||
padding: 8px 16px;
|
||||
background-color: #fcfcfc;
|
||||
border-top: 1px solid #dfdfdf;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.insert-box input.tag {
|
||||
width: 510px;
|
||||
float: left;
|
||||
background-color: transparent;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.insert-box .submitbox {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.insert-box .submitbox input[type="button"] {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.insert-box .description label {
|
||||
cursor: text;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Mail Tab
|
||||
*/
|
||||
.contact-form-editor-box-mail span.mailtag {
|
||||
display: inline-block;
|
||||
margin: 0 0 0 4px;
|
||||
padding: 1px 2px;
|
||||
cursor: pointer;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.contact-form-editor-box-mail span.mailtag.used {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.contact-form-editor-box-mail span.mailtag.unused {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/*
|
||||
* Messages Tab
|
||||
*/
|
||||
#messages-panel p.description {
|
||||
margin: 5px 0 10px;
|
||||
}
|
||||
|
||||
/*
|
||||
* Tabs for integration modules
|
||||
*/
|
||||
#sendinblue-panel table tr.inactive ~ tr {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#sendinblue-panel .dashicons {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#sendinblue-panel td p {
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
/*
|
||||
* List Table
|
||||
*/
|
||||
.fixed .column-title {
|
||||
width: 38%;
|
||||
}
|
||||
|
||||
.fixed .column-shortcode {
|
||||
width: 38%;
|
||||
}
|
||||
|
||||
/*
|
||||
* Welcome Panel
|
||||
*/
|
||||
.wpcf7-welcome-panel {
|
||||
position: relative;
|
||||
overflow: auto;
|
||||
margin: 16px 0;
|
||||
padding: 23px 10px 0;
|
||||
border: 1px solid #c3c4c7;
|
||||
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04);
|
||||
background: #fff;
|
||||
font-size: 13px;
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
.wpcf7-welcome-panel h3 {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
line-height: 2.1em;
|
||||
margin: 1em 0 1.2em;
|
||||
}
|
||||
|
||||
.wpcf7-welcome-panel h3 .dashicons {
|
||||
position: relative;
|
||||
top: -2px;
|
||||
display: inline-block;
|
||||
width: 60px;
|
||||
color: #575757;
|
||||
font-size: 40px;
|
||||
}
|
||||
|
||||
.wpcf7-welcome-panel p {
|
||||
color: #646970;
|
||||
}
|
||||
|
||||
.wpcf7-welcome-panel p a {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.wpcf7-welcome-panel .welcome-panel-close {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
padding: 10px 15px 10px 21px;
|
||||
font-size: 13px;
|
||||
line-height: 1.23076923; /* Chrome rounding, needs to be 16px equivalent */
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.wpcf7-welcome-panel .welcome-panel-close::before {
|
||||
background: 0 0;
|
||||
color: #787c82;
|
||||
content: "\f153" / '';
|
||||
display: block;
|
||||
font: normal 16px/20px dashicons;
|
||||
speak: never;
|
||||
height: 20px;
|
||||
text-align: center;
|
||||
width: 20px;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
left: 0;
|
||||
transition: all .1s ease-in-out;
|
||||
}
|
||||
|
||||
.wpcf7-welcome-panel .welcome-panel-content {
|
||||
display: block;
|
||||
margin-left: 13px;
|
||||
max-width: 1500px;
|
||||
min-height: auto;
|
||||
}
|
||||
|
||||
.wpcf7-welcome-panel .welcome-panel-column-container {
|
||||
clear: both;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.wpcf7-welcome-panel .welcome-panel-column {
|
||||
display: block;
|
||||
width: 48%;
|
||||
min-width: 200px;
|
||||
float: left;
|
||||
padding: 0 2% 0 0;
|
||||
margin: 0 0 1em 0;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 870px) {
|
||||
.wpcf7-welcome-panel .welcome-panel-column {
|
||||
display: block;
|
||||
float: none;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.wpcf7-welcome-panel .welcome-panel-column p {
|
||||
margin-top: 7px;
|
||||
color: #3c434a;
|
||||
}
|
||||
|
||||
/*
|
||||
* Integration
|
||||
*/
|
||||
.card {
|
||||
background: #fff none repeat scroll 0 0;
|
||||
border: 1px solid #e5e5e5;
|
||||
border-left: 4px solid #e5e5e5;
|
||||
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04);
|
||||
margin-top: 20px;
|
||||
max-width: 520px;
|
||||
min-width: 255px;
|
||||
padding: 0.7em 2em 1em;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.card.active {
|
||||
border-color: #00a0d2;
|
||||
}
|
||||
|
||||
#constant_contact.card.active {
|
||||
border-color: #dc3232;
|
||||
}
|
||||
|
||||
.card img.icon {
|
||||
float: left;
|
||||
margin: 8px 8px 8px -8px;
|
||||
}
|
||||
|
||||
.card h2.title {
|
||||
float: left;
|
||||
max-width: 240px;
|
||||
font-size: 1.3em;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.card .infobox {
|
||||
float: right;
|
||||
font-size: 13px;
|
||||
color: #666;
|
||||
margin: 1em;
|
||||
line-height: 1.5;
|
||||
max-width: 240px;
|
||||
}
|
||||
|
||||
.card .inside .form-table th {
|
||||
padding: 15px 10px 15px 0;
|
||||
width: 160px;
|
||||
}
|
||||
|
||||
.card .inside .form-table td {
|
||||
padding: 10px 10px;
|
||||
}
|
||||
|
||||
.card .checkboxes li {
|
||||
margin: 0;
|
||||
}
|
||||
556
wp-content/plugins/contact-form-7/admin/includes/editor.php
Normal file
@@ -0,0 +1,556 @@
|
||||
<?php
|
||||
|
||||
class WPCF7_Editor {
|
||||
|
||||
private $contact_form;
|
||||
private $panels = array();
|
||||
|
||||
public function __construct( WPCF7_ContactForm $contact_form ) {
|
||||
$this->contact_form = $contact_form;
|
||||
}
|
||||
|
||||
public function add_panel( $panel_id, $title, $callback ) {
|
||||
if ( wpcf7_is_name( $panel_id ) ) {
|
||||
$this->panels[$panel_id] = array(
|
||||
'title' => $title,
|
||||
'callback' => $callback,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function display() {
|
||||
if ( empty( $this->panels ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$active_panel_id = wpcf7_superglobal_get( 'active-tab' );
|
||||
|
||||
if ( ! array_key_exists( $active_panel_id, $this->panels ) ) {
|
||||
$active_panel_id = array_key_first( $this->panels );
|
||||
}
|
||||
|
||||
$formatter = new WPCF7_HTMLFormatter();
|
||||
|
||||
$formatter->append_start_tag( 'nav', array(
|
||||
'id' => 'contact-form-editor-tabs',
|
||||
'role' => 'tablist',
|
||||
'aria-label' => __( 'Contact form editor tabs', 'contact-form-7' ),
|
||||
'data-active-tab' => absint( array_search(
|
||||
$active_panel_id, array_keys( $this->panels ), true
|
||||
) ),
|
||||
) );
|
||||
|
||||
foreach ( $this->panels as $panel_id => $panel ) {
|
||||
$active = $panel_id === $active_panel_id;
|
||||
|
||||
$formatter->append_start_tag( 'button', array(
|
||||
'type' => 'button',
|
||||
'role' => 'tab',
|
||||
'aria-selected' => $active ? 'true' : 'false',
|
||||
'aria-controls' => $panel_id,
|
||||
'id' => sprintf( '%s-tab', $panel_id ),
|
||||
'tabindex' => $active ? '0' : '-1',
|
||||
) );
|
||||
|
||||
$formatter->append_preformatted( esc_html( $panel['title'] ) );
|
||||
}
|
||||
|
||||
$formatter->end_tag( 'nav' );
|
||||
|
||||
foreach ( $this->panels as $panel_id => $panel ) {
|
||||
$active = $panel_id === $active_panel_id;
|
||||
|
||||
$formatter->append_start_tag( 'section', array(
|
||||
'role' => 'tabpanel',
|
||||
'aria-labelledby' => sprintf( '%s-tab', $panel_id ),
|
||||
'id' => $panel_id,
|
||||
'class' => 'contact-form-editor-panel',
|
||||
'tabindex' => '0',
|
||||
'hidden' => ! $active,
|
||||
) );
|
||||
|
||||
if ( is_callable( $panel['callback'] ) ) {
|
||||
$formatter->call_user_func( $panel['callback'], $this->contact_form );
|
||||
}
|
||||
|
||||
$formatter->end_tag( 'section' );
|
||||
}
|
||||
|
||||
$formatter->print();
|
||||
}
|
||||
}
|
||||
|
||||
function wpcf7_editor_panel_form( $post ) {
|
||||
$description = sprintf(
|
||||
/* translators: %s: URL to support page about the form template */
|
||||
__( 'You can edit the form template here. For details, see <a href="%s">Editing form template</a>.', 'contact-form-7' ),
|
||||
__( 'https://contactform7.com/editing-form-template/', 'contact-form-7' )
|
||||
);
|
||||
|
||||
$formatter = new WPCF7_HTMLFormatter();
|
||||
|
||||
$formatter->append_start_tag( 'h2' );
|
||||
$formatter->append_preformatted( esc_html( __( 'Form', 'contact-form-7' ) ) );
|
||||
$formatter->end_tag( 'h2' );
|
||||
|
||||
$formatter->append_start_tag( 'fieldset' );
|
||||
|
||||
$formatter->append_start_tag( 'legend' );
|
||||
$formatter->append_preformatted( $description );
|
||||
$formatter->end_tag( 'legend' );
|
||||
|
||||
$formatter->call_user_func( static function () {
|
||||
$tag_generator = WPCF7_TagGenerator::get_instance();
|
||||
$tag_generator->print_buttons();
|
||||
} );
|
||||
|
||||
$formatter->append_start_tag( 'textarea', array(
|
||||
'id' => 'wpcf7-form',
|
||||
'name' => 'wpcf7-form',
|
||||
'cols' => 100,
|
||||
'rows' => 24,
|
||||
'class' => 'large-text code',
|
||||
'data-config-field' => 'form.body',
|
||||
) );
|
||||
|
||||
$formatter->append_preformatted( esc_textarea( $post->prop( 'form' ) ) );
|
||||
|
||||
$formatter->end_tag( 'textarea' );
|
||||
|
||||
$formatter->print();
|
||||
}
|
||||
|
||||
function wpcf7_editor_panel_mail( $post ) {
|
||||
wpcf7_editor_box_mail( $post );
|
||||
|
||||
echo '<br class="clear" />';
|
||||
|
||||
wpcf7_editor_box_mail( $post, array(
|
||||
'id' => 'wpcf7-mail-2',
|
||||
'name' => 'mail_2',
|
||||
'title' => __( 'Mail (2)', 'contact-form-7' ),
|
||||
'use' => __( 'Use Mail (2)', 'contact-form-7' ),
|
||||
) );
|
||||
}
|
||||
|
||||
function wpcf7_editor_box_mail( $post, $options = '' ) {
|
||||
$options = wp_parse_args( $options, array(
|
||||
'id' => 'wpcf7-mail',
|
||||
'name' => 'mail',
|
||||
'title' => __( 'Mail', 'contact-form-7' ),
|
||||
'use' => null,
|
||||
) );
|
||||
|
||||
$id = esc_attr( $options['id'] );
|
||||
|
||||
$mail = wp_parse_args( $post->prop( $options['name'] ), array(
|
||||
'active' => false,
|
||||
'recipient' => '',
|
||||
'sender' => '',
|
||||
'subject' => '',
|
||||
'body' => '',
|
||||
'additional_headers' => '',
|
||||
'attachments' => '',
|
||||
'use_html' => false,
|
||||
'exclude_blank' => false,
|
||||
) );
|
||||
|
||||
$formatter = new WPCF7_HTMLFormatter();
|
||||
|
||||
$formatter->append_start_tag( 'div', array(
|
||||
'class' => 'contact-form-editor-box-mail',
|
||||
'id' => $id,
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'h2' );
|
||||
$formatter->append_preformatted( esc_html( $options['title'] ) );
|
||||
$formatter->end_tag( 'h2' );
|
||||
|
||||
if ( ! empty( $options['use'] ) ) {
|
||||
$formatter->append_start_tag( 'label', array(
|
||||
'for' => sprintf( '%s-active', $id ),
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'input', array(
|
||||
'type' => 'checkbox',
|
||||
'id' => sprintf( '%s-active', $id ),
|
||||
'name' => sprintf( '%s[active]', $id ),
|
||||
'data-config-field' => '',
|
||||
'data-toggle' => sprintf( '%s-fieldset', $id ),
|
||||
'value' => '1',
|
||||
'checked' => $mail['active'],
|
||||
) );
|
||||
|
||||
$formatter->append_whitespace();
|
||||
$formatter->append_preformatted( esc_html( $options['use'] ) );
|
||||
$formatter->end_tag( 'label' );
|
||||
|
||||
$formatter->append_start_tag( 'p', array(
|
||||
'class' => 'description',
|
||||
) );
|
||||
|
||||
$formatter->append_preformatted(
|
||||
esc_html( __( 'Mail (2) is an additional mail template often used as an autoresponder.', 'contact-form-7' ) )
|
||||
);
|
||||
|
||||
$formatter->end_tag( 'p' );
|
||||
}
|
||||
|
||||
$formatter->append_start_tag( 'fieldset', array(
|
||||
'id' => sprintf( '%s-fieldset', $id ),
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'legend' );
|
||||
|
||||
$description = sprintf(
|
||||
/* translators: %s: URL to support page about the email template */
|
||||
__( 'You can edit the email template here. For details, see <a href="%s">Setting up mail</a>.', 'contact-form-7' ),
|
||||
__( 'https://contactform7.com/setting-up-mail/', 'contact-form-7' )
|
||||
);
|
||||
|
||||
$formatter->append_preformatted( $description );
|
||||
|
||||
$formatter->append_start_tag( 'br' );
|
||||
|
||||
$formatter->append_preformatted(
|
||||
esc_html( __( 'In the following fields, you can use these mail-tags:', 'contact-form-7' ) )
|
||||
);
|
||||
|
||||
$formatter->append_start_tag( 'br' );
|
||||
|
||||
$formatter->call_user_func( static function () use ( $post, $options ) {
|
||||
$post->suggest_mail_tags( $options['name'] );
|
||||
} );
|
||||
|
||||
$formatter->end_tag( 'legend' );
|
||||
|
||||
$formatter->append_start_tag( 'table', array(
|
||||
'class' => 'form-table',
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'tbody' );
|
||||
|
||||
$formatter->append_start_tag( 'tr' );
|
||||
|
||||
$formatter->append_start_tag( 'th', array(
|
||||
'scope' => 'row',
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'label', array(
|
||||
'for' => sprintf( '%s-recipient', $id ),
|
||||
) );
|
||||
|
||||
$formatter->append_preformatted(
|
||||
esc_html( __( 'To', 'contact-form-7' ) )
|
||||
);
|
||||
|
||||
$formatter->append_start_tag( 'td' );
|
||||
|
||||
$formatter->append_start_tag( 'input', array(
|
||||
'type' => 'text',
|
||||
'id' => sprintf( '%s-recipient', $id ),
|
||||
'name' => sprintf( '%s[recipient]', $id ),
|
||||
'class' => 'large-text code',
|
||||
'size' => 70,
|
||||
'value' => $mail['recipient'],
|
||||
'data-config-field' => sprintf( '%s.recipient', $options['name'] ),
|
||||
) );
|
||||
|
||||
$formatter->end_tag( 'tr' );
|
||||
|
||||
$formatter->append_start_tag( 'tr' );
|
||||
|
||||
$formatter->append_start_tag( 'th', array(
|
||||
'scope' => 'row',
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'label', array(
|
||||
'for' => sprintf( '%s-sender', $id ),
|
||||
) );
|
||||
|
||||
$formatter->append_preformatted(
|
||||
esc_html( __( 'From', 'contact-form-7' ) )
|
||||
);
|
||||
|
||||
$formatter->append_start_tag( 'td' );
|
||||
|
||||
$formatter->append_start_tag( 'input', array(
|
||||
'type' => 'text',
|
||||
'id' => sprintf( '%s-sender', $id ),
|
||||
'name' => sprintf( '%s[sender]', $id ),
|
||||
'class' => 'large-text code',
|
||||
'size' => 70,
|
||||
'value' => $mail['sender'],
|
||||
'data-config-field' => sprintf( '%s.sender', $options['name'] ),
|
||||
) );
|
||||
|
||||
$formatter->end_tag( 'tr' );
|
||||
|
||||
$formatter->append_start_tag( 'tr' );
|
||||
|
||||
$formatter->append_start_tag( 'th', array(
|
||||
'scope' => 'row',
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'label', array(
|
||||
'for' => sprintf( '%s-subject', $id ),
|
||||
) );
|
||||
|
||||
$formatter->append_preformatted(
|
||||
esc_html( __( 'Subject', 'contact-form-7' ) )
|
||||
);
|
||||
|
||||
$formatter->append_start_tag( 'td' );
|
||||
|
||||
$formatter->append_start_tag( 'input', array(
|
||||
'type' => 'text',
|
||||
'id' => sprintf( '%s-subject', $id ),
|
||||
'name' => sprintf( '%s[subject]', $id ),
|
||||
'class' => 'large-text code',
|
||||
'size' => 70,
|
||||
'value' => $mail['subject'],
|
||||
'data-config-field' => sprintf( '%s.subject', $options['name'] ),
|
||||
) );
|
||||
|
||||
$formatter->end_tag( 'tr' );
|
||||
|
||||
$formatter->append_start_tag( 'tr' );
|
||||
|
||||
$formatter->append_start_tag( 'th', array(
|
||||
'scope' => 'row',
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'label', array(
|
||||
'for' => sprintf( '%s-additional-headers', $id ),
|
||||
) );
|
||||
|
||||
$formatter->append_preformatted(
|
||||
esc_html( __( 'Additional headers', 'contact-form-7' ) )
|
||||
);
|
||||
|
||||
$formatter->append_start_tag( 'td' );
|
||||
|
||||
$formatter->append_start_tag( 'textarea', array(
|
||||
'id' => sprintf( '%s-additional-headers', $id ),
|
||||
'name' => sprintf( '%s[additional_headers]', $id ),
|
||||
'cols' => 100,
|
||||
'rows' => 4,
|
||||
'class' => 'large-text code',
|
||||
'data-config-field' => sprintf( '%s.additional_headers', $options['name'] ),
|
||||
) );
|
||||
|
||||
$formatter->append_preformatted(
|
||||
esc_textarea( $mail['additional_headers'] )
|
||||
);
|
||||
|
||||
$formatter->end_tag( 'tr' );
|
||||
|
||||
$formatter->append_start_tag( 'tr' );
|
||||
|
||||
$formatter->append_start_tag( 'th', array(
|
||||
'scope' => 'row',
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'label', array(
|
||||
'for' => sprintf( '%s-body', $id ),
|
||||
) );
|
||||
|
||||
$formatter->append_preformatted(
|
||||
esc_html( __( 'Message body', 'contact-form-7' ) )
|
||||
);
|
||||
|
||||
$formatter->append_start_tag( 'td' );
|
||||
|
||||
$formatter->append_start_tag( 'textarea', array(
|
||||
'id' => sprintf( '%s-body', $id ),
|
||||
'name' => sprintf( '%s[body]', $id ),
|
||||
'cols' => 100,
|
||||
'rows' => 18,
|
||||
'class' => 'large-text code',
|
||||
'data-config-field' => sprintf( '%s.body', $options['name'] ),
|
||||
) );
|
||||
|
||||
$formatter->append_preformatted(
|
||||
esc_textarea( $mail['body'] )
|
||||
);
|
||||
|
||||
$formatter->end_tag( 'textarea' );
|
||||
|
||||
$formatter->append_start_tag( 'p' );
|
||||
|
||||
$formatter->append_start_tag( 'label', array(
|
||||
'for' => sprintf( '%s-exclude-blank', $id ),
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'input', array(
|
||||
'type' => 'checkbox',
|
||||
'id' => sprintf( '%s-exclude-blank', $id ),
|
||||
'name' => sprintf( '%s[exclude_blank]', $id ),
|
||||
'value' => '1',
|
||||
'checked' => $mail['exclude_blank'],
|
||||
) );
|
||||
|
||||
$formatter->append_whitespace();
|
||||
|
||||
$formatter->append_preformatted(
|
||||
esc_html( __( 'Exclude a line from output if all of its mail-tags are blank', 'contact-form-7' ) )
|
||||
);
|
||||
|
||||
$formatter->append_start_tag( 'p' );
|
||||
|
||||
$formatter->append_start_tag( 'label', array(
|
||||
'for' => sprintf( '%s-use-html', $id ),
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'input', array(
|
||||
'type' => 'checkbox',
|
||||
'id' => sprintf( '%s-use-html', $id ),
|
||||
'name' => sprintf( '%s[use_html]', $id ),
|
||||
'value' => '1',
|
||||
'checked' => $mail['use_html'],
|
||||
) );
|
||||
|
||||
$formatter->append_whitespace();
|
||||
|
||||
$formatter->append_preformatted(
|
||||
esc_html( __( 'Use HTML content type', 'contact-form-7' ) )
|
||||
);
|
||||
|
||||
$formatter->end_tag( 'tr' );
|
||||
|
||||
$formatter->append_start_tag( 'tr' );
|
||||
|
||||
$formatter->append_start_tag( 'th', array(
|
||||
'scope' => 'row',
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'label', array(
|
||||
'for' => sprintf( '%s-attachments', $id ),
|
||||
) );
|
||||
|
||||
$formatter->append_preformatted(
|
||||
esc_html( __( 'File attachments', 'contact-form-7' ) )
|
||||
);
|
||||
|
||||
$formatter->append_start_tag( 'td' );
|
||||
|
||||
$formatter->append_start_tag( 'textarea', array(
|
||||
'id' => sprintf( '%s-attachments', $id ),
|
||||
'name' => sprintf( '%s[attachments]', $id ),
|
||||
'cols' => 100,
|
||||
'rows' => 4,
|
||||
'class' => 'large-text code',
|
||||
'data-config-field' => sprintf( '%s.attachments', $options['name'] ),
|
||||
) );
|
||||
|
||||
$formatter->append_preformatted(
|
||||
esc_textarea( $mail['attachments'] )
|
||||
);
|
||||
|
||||
$formatter->end_tag( 'textarea' );
|
||||
$formatter->end_tag( 'tr' );
|
||||
|
||||
$formatter->print();
|
||||
}
|
||||
|
||||
function wpcf7_editor_panel_messages( $post ) {
|
||||
$description = sprintf(
|
||||
/* translators: %s: URL to support page about the messages editor */
|
||||
__( 'You can edit messages used in various situations here. For details, see <a href="%s">Editing messages</a>.', 'contact-form-7' ),
|
||||
__( 'https://contactform7.com/editing-messages/', 'contact-form-7' )
|
||||
);
|
||||
|
||||
$messages = wpcf7_messages();
|
||||
|
||||
if (
|
||||
isset( $messages['captcha_not_match'] ) and
|
||||
! wpcf7_use_really_simple_captcha()
|
||||
) {
|
||||
unset( $messages['captcha_not_match'] );
|
||||
}
|
||||
|
||||
$formatter = new WPCF7_HTMLFormatter();
|
||||
|
||||
$formatter->append_start_tag( 'h2' );
|
||||
|
||||
$formatter->append_preformatted(
|
||||
esc_html( __( 'Messages', 'contact-form-7' ) )
|
||||
);
|
||||
|
||||
$formatter->end_tag( 'h2' );
|
||||
|
||||
$formatter->append_start_tag( 'fieldset' );
|
||||
|
||||
$formatter->append_start_tag( 'legend' );
|
||||
$formatter->append_preformatted( $description );
|
||||
$formatter->end_tag( 'legend' );
|
||||
|
||||
foreach ( $messages as $key => $arr ) {
|
||||
$field_id = sprintf( 'wpcf7-message-%s', strtr( $key, '_', '-' ) );
|
||||
$field_name = sprintf( 'wpcf7-messages[%s]', $key );
|
||||
|
||||
$formatter->append_start_tag( 'p', array(
|
||||
'class' => 'description',
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'label', array(
|
||||
'for' => $field_id,
|
||||
) );
|
||||
|
||||
$formatter->append_preformatted( esc_html( $arr['description'] ) );
|
||||
$formatter->append_start_tag( 'br' );
|
||||
|
||||
$formatter->append_start_tag( 'input', array(
|
||||
'type' => 'text',
|
||||
'id' => $field_id,
|
||||
'name' => $field_name,
|
||||
'class' => 'large-text',
|
||||
'size' => 70,
|
||||
'value' => $post->message( $key, false ),
|
||||
'data-config-field' => sprintf( 'messages.%s', $key ),
|
||||
) );
|
||||
}
|
||||
|
||||
$formatter->print();
|
||||
}
|
||||
|
||||
function wpcf7_editor_panel_additional_settings( $post ) {
|
||||
$description = sprintf(
|
||||
/* translators: %s: URL to support page about the additional settings editor */
|
||||
__( 'You can add customization code snippets here. For details, see <a href="%s">Additional settings</a>.', 'contact-form-7' ),
|
||||
__( 'https://contactform7.com/additional-settings/', 'contact-form-7' )
|
||||
);
|
||||
|
||||
$formatter = new WPCF7_HTMLFormatter();
|
||||
|
||||
$formatter->append_start_tag( 'h2' );
|
||||
|
||||
$formatter->append_preformatted(
|
||||
esc_html( __( 'Additional Settings', 'contact-form-7' ) )
|
||||
);
|
||||
|
||||
$formatter->end_tag( 'h2' );
|
||||
|
||||
$formatter->append_start_tag( 'fieldset' );
|
||||
|
||||
$formatter->append_start_tag( 'legend' );
|
||||
$formatter->append_preformatted( $description );
|
||||
$formatter->end_tag( 'legend' );
|
||||
|
||||
$formatter->append_start_tag( 'textarea', array(
|
||||
'id' => 'wpcf7-additional-settings',
|
||||
'name' => 'wpcf7-additional-settings',
|
||||
'cols' => 100,
|
||||
'rows' => 24,
|
||||
'class' => 'large-text',
|
||||
'data-config-field' => 'additional_settings.body',
|
||||
) );
|
||||
|
||||
$formatter->append_preformatted(
|
||||
esc_textarea( $post->prop( 'additional_settings' ) )
|
||||
);
|
||||
|
||||
$formatter->end_tag( 'textarea' );
|
||||
|
||||
$formatter->print();
|
||||
}
|
||||
104
wp-content/plugins/contact-form-7/admin/includes/help-tabs.php
Normal file
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
class WPCF7_Help_Tabs {
|
||||
|
||||
private $screen;
|
||||
|
||||
public function __construct( WP_Screen $screen ) {
|
||||
$this->screen = $screen;
|
||||
}
|
||||
|
||||
public function set_help_tabs( $screen_type ) {
|
||||
switch ( $screen_type ) {
|
||||
case 'list':
|
||||
$this->screen->add_help_tab( array(
|
||||
'id' => 'list_overview',
|
||||
'title' => __( 'Overview', 'contact-form-7' ),
|
||||
'content' => $this->content( 'list_overview' ),
|
||||
) );
|
||||
|
||||
$this->screen->add_help_tab( array(
|
||||
'id' => 'list_available_actions',
|
||||
'title' => __( 'Available Actions', 'contact-form-7' ),
|
||||
'content' => $this->content( 'list_available_actions' ),
|
||||
) );
|
||||
|
||||
$this->sidebar();
|
||||
|
||||
return;
|
||||
case 'edit':
|
||||
$this->screen->add_help_tab( array(
|
||||
'id' => 'edit_overview',
|
||||
'title' => __( 'Overview', 'contact-form-7' ),
|
||||
'content' => $this->content( 'edit_overview' ),
|
||||
) );
|
||||
|
||||
$this->screen->add_help_tab( array(
|
||||
'id' => 'edit_form_tags',
|
||||
'title' => __( 'Form-tags', 'contact-form-7' ),
|
||||
'content' => $this->content( 'edit_form_tags' ),
|
||||
) );
|
||||
|
||||
$this->screen->add_help_tab( array(
|
||||
'id' => 'edit_mail_tags',
|
||||
'title' => __( 'Mail-tags', 'contact-form-7' ),
|
||||
'content' => $this->content( 'edit_mail_tags' ),
|
||||
) );
|
||||
|
||||
$this->sidebar();
|
||||
|
||||
return;
|
||||
case 'integration':
|
||||
$this->screen->add_help_tab( array(
|
||||
'id' => 'integration_overview',
|
||||
'title' => __( 'Overview', 'contact-form-7' ),
|
||||
'content' => $this->content( 'integration_overview' ),
|
||||
) );
|
||||
|
||||
$this->sidebar();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private function content( $name ) {
|
||||
$content = array();
|
||||
|
||||
$content['list_overview'] = '<p>' . __( 'On this screen, you can manage contact forms provided by Contact Form 7. You can manage an unlimited number of contact forms. Each contact form has a unique ID and Contact Form 7 shortcode ([contact-form-7 ...]). To insert a contact form into a post or a text widget, insert the shortcode into the target.', 'contact-form-7' ) . '</p>';
|
||||
|
||||
$content['list_available_actions'] = '<p>' . __( 'Hovering over a row in the contact forms list will display action links that allow you to manage your contact form. You can perform the following actions:', 'contact-form-7' ) . '</p>';
|
||||
$content['list_available_actions'] .= '<p>' . __( '<strong>Edit</strong> - Navigates to the editing screen for that contact form. You can also reach that screen by clicking on the contact form title.', 'contact-form-7' ) . '</p>';
|
||||
$content['list_available_actions'] .= '<p>' . __( '<strong>Duplicate</strong> - Clones that contact form. A cloned contact form inherits all content from the original, but has a different ID.', 'contact-form-7' ) . '</p>';
|
||||
|
||||
$content['edit_overview'] = '<p>' . __( 'On this screen, you can edit a contact form. A contact form is comprised of the following components:', 'contact-form-7' ) . '</p>';
|
||||
$content['edit_overview'] .= '<p>' . __( '<strong>Title</strong> is the title of a contact form. This title is only used for labeling a contact form, and can be edited.', 'contact-form-7' ) . '</p>';
|
||||
$content['edit_overview'] .= '<p>' . __( '<strong>Form</strong> is a content of HTML form. You can use arbitrary HTML, which is allowed inside a form element. You can also use Contact Form 7’s form-tags here.', 'contact-form-7' ) . '</p>';
|
||||
$content['edit_overview'] .= '<p>' . __( '<strong>Mail</strong> manages a mail template (headers and message body) that this contact form will send when users submit it. You can use Contact Form 7’s mail-tags here.', 'contact-form-7' ) . '</p>';
|
||||
$content['edit_overview'] .= '<p>' . __( '<strong>Mail (2)</strong> is an additional mail template that works similar to Mail. Mail (2) is different in that it is sent only when Mail has been sent successfully.', 'contact-form-7' ) . '</p>';
|
||||
$content['edit_overview'] .= '<p>' . __( 'In <strong>Messages</strong>, you can edit various types of messages used for this contact form. These messages are relatively short messages, like a validation error message you see when you leave a required field blank.', 'contact-form-7' ) . '</p>';
|
||||
$content['edit_overview'] .= '<p>' . __( '<strong>Additional Settings</strong> provides a place where you can customize the behavior of this contact form by adding code snippets.', 'contact-form-7' ) . '</p>';
|
||||
|
||||
$content['edit_form_tags'] = '<p>' . __( 'A form-tag is a short code enclosed in square brackets used in a form content. A form-tag generally represents an input field, and its components can be separated into four parts: type, name, options, and values. Contact Form 7 supports several types of form-tags including text fields, number fields, date fields, checkboxes, radio buttons, menus, file-uploading fields, CAPTCHAs, and quiz fields.', 'contact-form-7' ) . '</p>';
|
||||
$content['edit_form_tags'] .= '<p>' . __( 'While form-tags have a comparatively complex syntax, you do not need to know the syntax to add form-tags because you can use the straightforward tag generator (<strong>Generate Tag</strong> button on this screen).', 'contact-form-7' ) . '</p>';
|
||||
|
||||
$content['edit_mail_tags'] = '<p>' . __( 'A mail-tag is also a short code enclosed in square brackets that you can use in every Mail and Mail (2) field. A mail-tag represents a user input value through an input field of a corresponding form-tag.', 'contact-form-7' ) . '</p>';
|
||||
$content['edit_mail_tags'] .= '<p>' . __( 'There are also special mail-tags that have specific names, but do not have corresponding form-tags. They are used to represent meta information of form submissions like the submitter’s IP address or the URL of the page.', 'contact-form-7' ) . '</p>';
|
||||
|
||||
$content['integration_overview'] = '<p>' . __( 'On this screen, you can manage services that are available through Contact Form 7. Using API will allow you to collaborate with any services that are available.', 'contact-form-7' ) . '</p>';
|
||||
$content['integration_overview'] .= '<p>' . __( 'You may need to first sign up for an account with the service that you plan to use. When you do so, you would need to authorize Contact Form 7 to access the service with your account.', 'contact-form-7' ) . '</p>';
|
||||
$content['integration_overview'] .= '<p>' . __( 'Any information you provide will not be shared with service providers without your authorization.', 'contact-form-7' ) . '</p>';
|
||||
|
||||
if ( ! empty( $content[$name] ) ) {
|
||||
return $content[$name];
|
||||
}
|
||||
}
|
||||
|
||||
public function sidebar() {
|
||||
$content = '<p><strong>' . __( 'For more information:', 'contact-form-7' ) . '</strong></p>';
|
||||
$content .= '<p>' . wpcf7_link( __( 'https://contactform7.com/docs/', 'contact-form-7' ), __( 'Docs', 'contact-form-7' ) ) . '</p>';
|
||||
$content .= '<p>' . wpcf7_link( __( 'https://contactform7.com/faq/', 'contact-form-7' ), __( 'FAQ', 'contact-form-7' ) ) . '</p>';
|
||||
$content .= '<p>' . wpcf7_link( __( 'https://contactform7.com/support/', 'contact-form-7' ), __( 'Support', 'contact-form-7' ) ) . '</p>';
|
||||
|
||||
$this->screen->set_help_sidebar( $content );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'dependencies' => array(
|
||||
'wp-api-fetch',
|
||||
'wp-i18n',
|
||||
),
|
||||
'version' => WPCF7_VERSION,
|
||||
);
|
||||
@@ -0,0 +1,627 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* The base class for form-tag generators management.
|
||||
*/
|
||||
class WPCF7_TagGenerator {
|
||||
|
||||
private static $instance;
|
||||
|
||||
private $panels = array();
|
||||
|
||||
private function __construct() {}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the singleton instance of this class.
|
||||
*/
|
||||
public static function get_instance() {
|
||||
if ( empty( self::$instance ) ) {
|
||||
self::$instance = new self();
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a form-tag generator instance.
|
||||
*/
|
||||
public function add( $id, $title, $callback, $options = '' ) {
|
||||
$id = trim( $id );
|
||||
|
||||
if (
|
||||
'' === $id or
|
||||
! wpcf7_is_name( $id ) or
|
||||
! is_callable( $callback )
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$options = wp_parse_args( $options, array(
|
||||
'version' => '1',
|
||||
) );
|
||||
|
||||
$this->panels[$id] = array(
|
||||
'title' => $title,
|
||||
'content' => 'tag-generator-panel-' . $id,
|
||||
'options' => $options,
|
||||
'callback' => $callback,
|
||||
);
|
||||
|
||||
if ( version_compare( $options['version'], '2', '<' ) ) {
|
||||
$message = sprintf(
|
||||
/* translators: 1: version, 2: tag generator title */
|
||||
__( 'Use of tag generator instances older than version 2 is deprecated. Version %1$s instance (%2$s) detected.', 'contact-form-7' ),
|
||||
$options['version'],
|
||||
$title
|
||||
);
|
||||
|
||||
wp_trigger_error( __METHOD__, $message, E_USER_DEPRECATED );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Renders form-tag generator calling buttons.
|
||||
*/
|
||||
public function print_buttons() {
|
||||
$formatter = new WPCF7_HTMLFormatter();
|
||||
|
||||
$formatter->append_start_tag( 'span', array(
|
||||
'id' => 'tag-generator-list',
|
||||
'class' => 'hide-if-no-js',
|
||||
) );
|
||||
|
||||
foreach ( (array) $this->panels as $panel ) {
|
||||
$formatter->append_start_tag( 'button', array(
|
||||
'type' => 'button',
|
||||
'data-taggen' => 'open-dialog',
|
||||
'data-target' => $panel['content'],
|
||||
'title' => sprintf(
|
||||
/* translators: %s: title of form-tag */
|
||||
__( 'Form-tag Generator: %s', 'contact-form-7' ),
|
||||
$panel['title']
|
||||
),
|
||||
) );
|
||||
|
||||
$formatter->append_preformatted( esc_html( $panel['title'] ) );
|
||||
}
|
||||
|
||||
$formatter->print();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Renders form-tag generator dialog panels (hidden until called).
|
||||
*/
|
||||
public function print_panels( WPCF7_ContactForm $contact_form ) {
|
||||
$formatter = new WPCF7_HTMLFormatter( array(
|
||||
'allowed_html' => array_merge( wpcf7_kses_allowed_html(), array(
|
||||
'dialog' => array(
|
||||
'id' => true,
|
||||
'class' => true,
|
||||
),
|
||||
'form' => array(
|
||||
'method' => true,
|
||||
'class' => true,
|
||||
'data-*' => true,
|
||||
),
|
||||
) ),
|
||||
) );
|
||||
|
||||
foreach ( (array) $this->panels as $id => $panel ) {
|
||||
$callback = $panel['callback'];
|
||||
|
||||
$options = array_merge( $panel['options'], array(
|
||||
'id' => $id,
|
||||
'title' => $panel['title'],
|
||||
'content' => $panel['content'],
|
||||
) );
|
||||
|
||||
if ( is_callable( $callback ) ) {
|
||||
$formatter->append_start_tag( 'dialog', array(
|
||||
'id' => $options['content'],
|
||||
'class' => 'tag-generator-dialog',
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'button', array(
|
||||
'class' => 'close-button',
|
||||
'title' => __( 'Close this dialog box', 'contact-form-7' ),
|
||||
'data-taggen' => 'close-dialog',
|
||||
) );
|
||||
|
||||
$formatter->append_preformatted(
|
||||
esc_html( __( 'Close', 'contact-form-7' ) )
|
||||
);
|
||||
|
||||
$formatter->end_tag( 'button' );
|
||||
|
||||
$formatter->append_start_tag( 'form', array(
|
||||
'method' => 'dialog',
|
||||
'class' => 'tag-generator-panel',
|
||||
'data-id' => $options['id'],
|
||||
'data-version' => $options['version'],
|
||||
) );
|
||||
|
||||
$formatter->call_user_func( $callback, $contact_form, $options );
|
||||
|
||||
$formatter->close_all_tags();
|
||||
}
|
||||
}
|
||||
|
||||
$formatter->print();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Class helps to implement a form-tag generator content.
|
||||
*/
|
||||
class WPCF7_TagGeneratorGenerator {
|
||||
|
||||
private $key = '';
|
||||
|
||||
|
||||
/**
|
||||
* The constructor.
|
||||
*/
|
||||
public function __construct( $key ) {
|
||||
$this->key = $key;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a unique reference ID.
|
||||
*/
|
||||
public function ref( $suffix = '' ) {
|
||||
$ref = sprintf( '%s-%s', $this->key, $suffix );
|
||||
$ref = strtolower( $ref );
|
||||
$ref = preg_replace( '/[^0-9a-z-]/', '', $ref );
|
||||
$ref = preg_replace( '/[-]+/', '-', $ref );
|
||||
$ref = trim( $ref, '-' );
|
||||
return $ref;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calls one of the template methods.
|
||||
*/
|
||||
public function print( $part, $options = '' ) {
|
||||
if ( is_callable( array( $this, $part ) ) ) {
|
||||
call_user_func( array( $this, $part ), $options );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Template method for field type field.
|
||||
*/
|
||||
private function field_type( $options = '' ) {
|
||||
$options = wp_parse_args( $options, array(
|
||||
'with_required' => false,
|
||||
'with_optional' => false,
|
||||
'select_options' => array(),
|
||||
) );
|
||||
|
||||
$formatter = new WPCF7_HTMLFormatter();
|
||||
|
||||
$formatter->append_start_tag( 'fieldset' );
|
||||
|
||||
$formatter->append_start_tag( 'legend', array(
|
||||
'id' => $this->ref( 'type-legend' ),
|
||||
) );
|
||||
|
||||
$formatter->append_preformatted(
|
||||
esc_html( __( 'Field type', 'contact-form-7' ) )
|
||||
);
|
||||
|
||||
$formatter->end_tag( 'legend' );
|
||||
|
||||
$formatter->append_start_tag( 'select', array(
|
||||
'data-tag-part' => 'basetype',
|
||||
'aria-labelledby' => $this->ref( 'type-legend' ),
|
||||
) );
|
||||
|
||||
foreach ( (array) $options['select_options'] as $basetype => $title ) {
|
||||
$formatter->append_start_tag( 'option', array(
|
||||
'value' => $basetype,
|
||||
) );
|
||||
|
||||
$formatter->append_preformatted( esc_html( $title ) );
|
||||
}
|
||||
|
||||
$formatter->end_tag( 'select' );
|
||||
|
||||
if ( $options['with_required'] ) {
|
||||
$formatter->append_start_tag( 'br' );
|
||||
$formatter->append_start_tag( 'label' );
|
||||
|
||||
$formatter->append_start_tag( 'input', array(
|
||||
'type' => 'checkbox',
|
||||
'data-tag-part' => 'type-suffix',
|
||||
'value' => '*',
|
||||
) );
|
||||
|
||||
$formatter->append_whitespace();
|
||||
|
||||
$formatter->append_preformatted(
|
||||
esc_html( __( 'This is a required field.', 'contact-form-7' ) )
|
||||
);
|
||||
}
|
||||
|
||||
if ( $options['with_optional'] ) {
|
||||
$formatter->append_start_tag( 'br' );
|
||||
$formatter->append_start_tag( 'label' );
|
||||
|
||||
$formatter->append_start_tag( 'input', array(
|
||||
'type' => 'checkbox',
|
||||
'data-tag-part' => 'option',
|
||||
'data-tag-option' => 'optional',
|
||||
'checked' => true,
|
||||
) );
|
||||
|
||||
$formatter->append_whitespace();
|
||||
|
||||
$formatter->append_preformatted(
|
||||
esc_html( __( 'This checkbox is optional.', 'contact-form-7' ) )
|
||||
);
|
||||
}
|
||||
|
||||
$formatter->print();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Template method for field name field.
|
||||
*/
|
||||
private function field_name( $options = '' ) {
|
||||
$options = wp_parse_args( $options, array(
|
||||
'ask_if' => '',
|
||||
) );
|
||||
|
||||
?>
|
||||
<fieldset>
|
||||
<legend id="<?php echo esc_attr( $this->ref( 'name-legend' ) ); ?>"><?php
|
||||
echo esc_html( __( 'Field name', 'contact-form-7' ) );
|
||||
?></legend>
|
||||
<input type="text" data-tag-part="name" pattern="[A-Za-z][A-Za-z0-9_\-]*" aria-labelledby="<?php echo esc_attr( $this->ref( 'name-legend' ) ); ?>" />
|
||||
|
||||
<?php
|
||||
$tag_option = $label = '';
|
||||
|
||||
if ( 'author_name' === $options['ask_if'] ) {
|
||||
$tag_option = 'autocomplete:name';
|
||||
|
||||
if ( wpcf7_akismet_is_available() ) {
|
||||
$tag_option .= ' akismet:author';
|
||||
}
|
||||
|
||||
$label = __( "This field expects the submitter name.", 'contact-form-7' );
|
||||
} elseif ( 'author_email' === $options['ask_if'] ) {
|
||||
$tag_option = 'autocomplete:email';
|
||||
|
||||
if ( wpcf7_akismet_is_available() ) {
|
||||
$tag_option .= ' akismet:author_email';
|
||||
}
|
||||
|
||||
$label = __( "This field expects the submitter email.", 'contact-form-7' );
|
||||
} elseif ( 'author_url' === $options['ask_if'] ) {
|
||||
$tag_option = 'autocomplete:url';
|
||||
|
||||
if ( wpcf7_akismet_is_available() ) {
|
||||
$tag_option .= ' akismet:author_url';
|
||||
}
|
||||
|
||||
$label = __( "This field expects the submitter URL.", 'contact-form-7' );
|
||||
} elseif ( 'author_tel' === $options['ask_if'] ) {
|
||||
$tag_option = 'autocomplete:tel';
|
||||
$label = __( "This field expects the submitter telephone number.", 'contact-form-7' );
|
||||
}
|
||||
|
||||
if ( $tag_option ) {
|
||||
?>
|
||||
<br />
|
||||
<label>
|
||||
<input type="checkbox" data-tag-part="option" data-tag-option="<?php echo esc_attr( $tag_option ); ?>" />
|
||||
<?php echo esc_html( $label ); ?>
|
||||
</label>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</fieldset>
|
||||
<?php
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Template method for ID attribute option field.
|
||||
*/
|
||||
private function id_attr( $options = '' ) {
|
||||
?>
|
||||
<fieldset>
|
||||
<legend id="<?php echo esc_attr( $this->ref( 'id-legend' ) ); ?>"><?php
|
||||
echo esc_html( __( 'ID attribute', 'contact-form-7' ) );
|
||||
?></legend>
|
||||
<input type="text" data-tag-part="option" data-tag-option="id:" pattern="[A-Za-z][A-Za-z0-9_\-]*" aria-labelledby="<?php echo esc_attr( $this->ref( 'id-legend' ) ); ?>" />
|
||||
</fieldset>
|
||||
<?php
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Template method for class attribute option field.
|
||||
*/
|
||||
private function class_attr( $options = '' ) {
|
||||
?>
|
||||
<fieldset>
|
||||
<legend id="<?php echo esc_attr( $this->ref( 'class-legend' ) ); ?>"><?php
|
||||
echo esc_html( __( 'Class attribute', 'contact-form-7' ) );
|
||||
?></legend>
|
||||
<input type="text" data-tag-part="option" data-tag-option="class:" pattern="[A-Za-z0-9_\-\s]*" aria-labelledby="<?php echo esc_attr( $this->ref( 'class-legend' ) ); ?>" />
|
||||
</fieldset>
|
||||
<?php
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Template method for min/max options.
|
||||
*/
|
||||
private function min_max( $options = '' ) {
|
||||
$options = wp_parse_args( $options, array(
|
||||
'type' => 'number',
|
||||
'title' => __( 'Length', 'contact-form-7' ),
|
||||
'min_option' => 'minlength:',
|
||||
'max_option' => 'maxlength:',
|
||||
'accept_minus' => false,
|
||||
) );
|
||||
|
||||
$formatter = new WPCF7_HTMLFormatter();
|
||||
|
||||
$formatter->append_start_tag( 'fieldset' );
|
||||
|
||||
$formatter->append_start_tag( 'legend' );
|
||||
$formatter->append_preformatted( esc_html( $options['title'] ) );
|
||||
$formatter->end_tag( 'legend' );
|
||||
|
||||
$formatter->append_start_tag( 'label' );
|
||||
|
||||
$formatter->append_preformatted(
|
||||
esc_html( __( 'Min', 'contact-form-7' ) )
|
||||
);
|
||||
|
||||
$formatter->append_whitespace();
|
||||
|
||||
$formatter->append_start_tag( 'input', array(
|
||||
'type' => $options['type'],
|
||||
'data-tag-part' => 'option',
|
||||
'data-tag-option' => $options['min_option'],
|
||||
'min' => $options['accept_minus'] ? null : 0,
|
||||
) );
|
||||
|
||||
$formatter->end_tag( 'label' );
|
||||
|
||||
$formatter->append_preformatted( ' ⇔ ' );
|
||||
|
||||
$formatter->append_start_tag( 'label' );
|
||||
|
||||
$formatter->append_preformatted(
|
||||
esc_html( __( 'Max', 'contact-form-7' ) )
|
||||
);
|
||||
|
||||
$formatter->append_whitespace();
|
||||
|
||||
$formatter->append_start_tag( 'input', array(
|
||||
'type' => $options['type'],
|
||||
'data-tag-part' => 'option',
|
||||
'data-tag-option' => $options['max_option'],
|
||||
'min' => $options['accept_minus'] ? null : 0,
|
||||
) );
|
||||
|
||||
$formatter->end_tag( 'label' );
|
||||
|
||||
$formatter->print();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Template method for default value field.
|
||||
*/
|
||||
private function default_value( $options = '' ) {
|
||||
$options = wp_parse_args( $options, array(
|
||||
'type' => 'text',
|
||||
'title' => __( 'Default value', 'contact-form-7' ),
|
||||
'with_placeholder' => false,
|
||||
'use_content' => false,
|
||||
) );
|
||||
|
||||
$formatter = new WPCF7_HTMLFormatter();
|
||||
|
||||
$formatter->append_start_tag( 'fieldset' );
|
||||
|
||||
$formatter->append_start_tag( 'legend', array(
|
||||
'id' => $this->ref( 'value-legend' ),
|
||||
) );
|
||||
|
||||
$formatter->append_preformatted( esc_html( $options['title'] ) );
|
||||
|
||||
$formatter->end_tag( 'legend' );
|
||||
|
||||
$formatter->append_start_tag( 'input', array(
|
||||
'type' => $options['type'],
|
||||
'data-tag-part' => $options['use_content'] ? 'content' : 'value',
|
||||
'aria-labelledby' => $this->ref( 'value-legend' ),
|
||||
) );
|
||||
|
||||
if ( $options['with_placeholder'] ) {
|
||||
$formatter->append_start_tag( 'br' );
|
||||
$formatter->append_start_tag( 'label' );
|
||||
|
||||
$formatter->append_start_tag( 'input', array(
|
||||
'type' => 'checkbox',
|
||||
'data-tag-part' => 'option',
|
||||
'data-tag-option' => 'placeholder',
|
||||
) );
|
||||
|
||||
$formatter->append_whitespace();
|
||||
|
||||
$formatter->append_preformatted(
|
||||
esc_html( __( 'Use this text as the placeholder.', 'contact-form-7' ) )
|
||||
);
|
||||
}
|
||||
|
||||
$formatter->print();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Template method for selectable values useful for checkboxes or a menu.
|
||||
*/
|
||||
private function selectable_values( $options = '' ) {
|
||||
$options = wp_parse_args( $options, array(
|
||||
'first_as_label' => false,
|
||||
'use_label_element' => false,
|
||||
) );
|
||||
|
||||
$formatter = new WPCF7_HTMLFormatter();
|
||||
|
||||
$formatter->append_start_tag( 'fieldset' );
|
||||
|
||||
$formatter->append_start_tag( 'legend', array(
|
||||
'id' => $this->ref( 'selectable-values-legend' ),
|
||||
) );
|
||||
|
||||
$formatter->append_preformatted(
|
||||
esc_html( __( 'Selectable values', 'contact-form-7' ) )
|
||||
);
|
||||
|
||||
$formatter->end_tag( 'legend' );
|
||||
|
||||
$formatter->append_start_tag( 'span', array(
|
||||
'id' => $this->ref( 'selectable-values-description' ),
|
||||
) );
|
||||
|
||||
$formatter->append_preformatted(
|
||||
esc_html( __( 'One item per line.', 'contact-form-7' ) )
|
||||
);
|
||||
|
||||
$formatter->end_tag( 'span' );
|
||||
|
||||
$formatter->append_start_tag( 'br' );
|
||||
|
||||
$formatter->append_start_tag( 'textarea', array(
|
||||
'required' => true,
|
||||
'data-tag-part' => 'value',
|
||||
'aria-labelledby' => $this->ref( 'selectable-values-legend' ),
|
||||
'aria-describedby' => $this->ref( 'selectable-values-description' ),
|
||||
) );
|
||||
|
||||
$formatter->append_preformatted(
|
||||
esc_html( __( "Option 1\nOption 2\nOption 3", 'contact-form-7' ) )
|
||||
);
|
||||
|
||||
$formatter->end_tag( 'textarea' );
|
||||
|
||||
if ( $options['first_as_label'] ) {
|
||||
$formatter->append_start_tag( 'br' );
|
||||
$formatter->append_start_tag( 'label' );
|
||||
|
||||
$formatter->append_start_tag( 'input', array(
|
||||
'type' => 'checkbox',
|
||||
'checked' => 'checked' === $options['first_as_label'],
|
||||
'data-tag-part' => 'option',
|
||||
'data-tag-option' => 'first_as_label',
|
||||
) );
|
||||
|
||||
$formatter->append_whitespace();
|
||||
|
||||
$formatter->append_preformatted(
|
||||
esc_html( __( 'Use the first item as a label.', 'contact-form-7' ) )
|
||||
);
|
||||
|
||||
$formatter->end_tag( 'label' );
|
||||
}
|
||||
|
||||
if ( $options['use_label_element'] ) {
|
||||
$formatter->append_start_tag( 'br' );
|
||||
$formatter->append_start_tag( 'label' );
|
||||
|
||||
$formatter->append_start_tag( 'input', array(
|
||||
'type' => 'checkbox',
|
||||
'checked' => 'checked' === $options['use_label_element'],
|
||||
'data-tag-part' => 'option',
|
||||
'data-tag-option' => 'use_label_element',
|
||||
) );
|
||||
|
||||
$formatter->append_whitespace();
|
||||
|
||||
$formatter->append_preformatted(
|
||||
esc_html( __( 'Wrap each item with a label element.', 'contact-form-7' ) )
|
||||
);
|
||||
|
||||
$formatter->end_tag( 'label' );
|
||||
}
|
||||
|
||||
$formatter->print();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Template method for insert-box content including the result form-tag.
|
||||
*/
|
||||
private function insert_box_content( $options = '' ) {
|
||||
$formatter = new WPCF7_HTMLFormatter();
|
||||
|
||||
$formatter->append_start_tag( 'div', array(
|
||||
'class' => 'flex-container',
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'input', array(
|
||||
'type' => 'text',
|
||||
'class' => 'code selectable',
|
||||
'readonly' => true,
|
||||
'data-tag-part' => 'tag',
|
||||
'aria-label' => __( 'The form-tag to be inserted into the form template', 'contact-form-7' ),
|
||||
) );
|
||||
|
||||
$formatter->append_whitespace();
|
||||
|
||||
$formatter->append_start_tag( 'button', array(
|
||||
'type' => 'button',
|
||||
'class' => 'button button-primary',
|
||||
'data-taggen' => 'insert-tag',
|
||||
) );
|
||||
|
||||
$formatter->append_preformatted(
|
||||
esc_html( __( 'Insert Tag', 'contact-form-7' ) )
|
||||
);
|
||||
|
||||
$formatter->end_tag( 'button' );
|
||||
|
||||
$formatter->print();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Template method for a tip message about mail-tag.
|
||||
*/
|
||||
private function mail_tag_tip( $options = '' ) {
|
||||
$formatter = new WPCF7_HTMLFormatter();
|
||||
|
||||
$formatter->append_start_tag( 'p', array(
|
||||
'class' => 'mail-tag-tip',
|
||||
) );
|
||||
|
||||
$formatter->append_preformatted( sprintf(
|
||||
/* translators: %s: mail-tag corresponding to the form-tag */
|
||||
esc_html( __( 'To use the user input in the email, insert the corresponding mail-tag %s into the email template.', 'contact-form-7' ) ),
|
||||
'<strong data-tag-part="mail-tag"></strong>'
|
||||
) );
|
||||
|
||||
$formatter->print();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,280 @@
|
||||
<?php
|
||||
|
||||
abstract class WPCF7_WelcomePanelColumn {
|
||||
|
||||
abstract protected function icon();
|
||||
abstract protected function title();
|
||||
abstract protected function content();
|
||||
|
||||
public function print_content() {
|
||||
$content = $this->content();
|
||||
|
||||
if ( is_array( $content ) ) {
|
||||
$content = implode( "\n\n", $content );
|
||||
}
|
||||
|
||||
$content = wp_kses_post( $content );
|
||||
$content = wptexturize( $content );
|
||||
$content = convert_chars( $content );
|
||||
$content = wpautop( $content );
|
||||
|
||||
$formatter = new WPCF7_HTMLFormatter();
|
||||
|
||||
$formatter->append_start_tag( 'div', array(
|
||||
'class' => 'welcome-panel-column',
|
||||
) );
|
||||
|
||||
$formatter->append_start_tag( 'h3' );
|
||||
|
||||
$formatter->append_start_tag( 'span', array(
|
||||
'class' => sprintf( 'dashicons dashicons-%s', $this->icon() ),
|
||||
'aria-hidden' => 'true',
|
||||
) );
|
||||
|
||||
$formatter->end_tag( 'span' );
|
||||
|
||||
$formatter->append_whitespace();
|
||||
|
||||
$formatter->append_preformatted( $this->title() );
|
||||
|
||||
$formatter->end_tag( 'h3' );
|
||||
|
||||
$formatter->append_preformatted( $content );
|
||||
|
||||
$formatter->print();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class WPCF7_WelcomePanelColumn_AntiSpam extends WPCF7_WelcomePanelColumn {
|
||||
|
||||
protected function icon() {
|
||||
return 'shield';
|
||||
}
|
||||
|
||||
protected function title() {
|
||||
return __( 'Getting spammed? You have protection.', 'contact-form-7' );
|
||||
}
|
||||
|
||||
protected function content() {
|
||||
return array(
|
||||
__( 'Spammers target everything; your contact forms are not an exception. Before you get spammed, protect your contact forms with the powerful anti-spam features Contact Form 7 provides.', 'contact-form-7' ),
|
||||
sprintf(
|
||||
/* translators: 1: URL to support page about Akismet, 2: Cloudflare Turnstile, 3: Disallowed list */
|
||||
__( 'Contact Form 7 supports spam-filtering with <a href="%1$s">Akismet</a>. <a href="%2$s">Cloudflare Turnstile</a> blocks annoying spambots. Plus, using <a href="%3$s">disallowed list</a>, you can block messages containing specified keywords or those sent from specified IP addresses.', 'contact-form-7' ),
|
||||
__( 'https://contactform7.com/spam-filtering-with-akismet/', 'contact-form-7' ),
|
||||
__( 'https://contactform7.com/turnstile-integration/', 'contact-form-7' ),
|
||||
__( 'https://contactform7.com/comment-blacklist/', 'contact-form-7' )
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class WPCF7_WelcomePanelColumn_Donation extends WPCF7_WelcomePanelColumn {
|
||||
|
||||
protected function icon() {
|
||||
return 'megaphone';
|
||||
}
|
||||
|
||||
protected function title() {
|
||||
return __( 'Contact Form 7 needs your support.', 'contact-form-7' );
|
||||
}
|
||||
|
||||
protected function content() {
|
||||
return array(
|
||||
__( 'It is hard to continue to maintain this plugin without support from users like you.', 'contact-form-7' ),
|
||||
sprintf(
|
||||
/* translators: %s: URL to support page about ways to contribute */
|
||||
__( 'There are several ways for you to <a href="%s">contribute to the project</a>: testing, coding, translating it into your local languages, helping other users, financial donations, etc, etc. We equally welcome you regardless of the way you contribute.', 'contact-form-7' ),
|
||||
__( 'https://contactform7.com/contributing/', 'contact-form-7' )
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class WPCF7_WelcomePanelColumn_Flamingo extends WPCF7_WelcomePanelColumn {
|
||||
|
||||
protected function icon() {
|
||||
return 'editor-help';
|
||||
}
|
||||
|
||||
protected function title() {
|
||||
return __( 'Before you cry over spilt mail…', 'contact-form-7' );
|
||||
}
|
||||
|
||||
protected function content() {
|
||||
return array(
|
||||
__( 'Contact Form 7 does not store submitted messages anywhere. Therefore, you may lose important messages forever if your mail server has issues or you make a mistake in mail configuration.', 'contact-form-7' ),
|
||||
sprintf(
|
||||
/* translators: %s: URL to support page about the Flamingo plugin */
|
||||
__( 'Install a message storage plugin before this happens to you. <a href="%s">Flamingo</a> saves all messages through contact forms into the database. Flamingo is a free WordPress plugin created by the same author as Contact Form 7.', 'contact-form-7' ),
|
||||
__( 'https://contactform7.com/save-submitted-messages-with-flamingo/', 'contact-form-7' )
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class WPCF7_WelcomePanelColumn_Integration extends WPCF7_WelcomePanelColumn {
|
||||
|
||||
protected function icon() {
|
||||
return 'superhero-alt';
|
||||
}
|
||||
|
||||
protected function title() {
|
||||
return __( 'You have strong allies to back you up.', 'contact-form-7' );
|
||||
}
|
||||
|
||||
protected function content() {
|
||||
return array(
|
||||
sprintf(
|
||||
/* translators: %s: URL to support page about the Brevo integration */
|
||||
__( 'Your contact forms will become more powerful and versatile by integrating them with external APIs. With CRM and email marketing services, you can build your own contact lists (<a href="%s">Brevo</a>).', 'contact-form-7' ),
|
||||
__( 'https://contactform7.com/sendinblue-integration/', 'contact-form-7' )
|
||||
),
|
||||
sprintf(
|
||||
/* translators: 1: URL to support page about Cloudflare Turnstile, 2: Stripe */
|
||||
__( 'With help from cloud-based machine learning, anti-spam services will protect your forms (<a href="%1$s">Cloudflare Turnstile</a>). Even payment services are natively supported (<a href="%2$s">Stripe</a>).', 'contact-form-7' ),
|
||||
__( 'https://contactform7.com/turnstile-integration/', 'contact-form-7' ),
|
||||
__( 'https://contactform7.com/stripe-integration/', 'contact-form-7' )
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function wpcf7_welcome_panel() {
|
||||
$columns = array();
|
||||
|
||||
$flamingo_is_active = defined( 'FLAMINGO_VERSION' );
|
||||
|
||||
$sendinblue_is_active = false;
|
||||
|
||||
if (
|
||||
class_exists( 'WPCF7_Sendinblue' ) and
|
||||
$sendinblue = WPCF7_Sendinblue::get_instance()
|
||||
) {
|
||||
$sendinblue_is_active = $sendinblue->is_active();
|
||||
}
|
||||
|
||||
if ( $flamingo_is_active and $sendinblue_is_active ) {
|
||||
$columns[] = new WPCF7_WelcomePanelColumn_AntiSpam();
|
||||
$columns[] = new WPCF7_WelcomePanelColumn_Donation();
|
||||
} elseif ( $flamingo_is_active ) {
|
||||
$columns[] = new WPCF7_WelcomePanelColumn_Integration();
|
||||
$columns[] = new WPCF7_WelcomePanelColumn_AntiSpam();
|
||||
} elseif ( $sendinblue_is_active ) {
|
||||
$columns[] = new WPCF7_WelcomePanelColumn_Flamingo();
|
||||
$columns[] = new WPCF7_WelcomePanelColumn_AntiSpam();
|
||||
} else {
|
||||
$columns[] = new WPCF7_WelcomePanelColumn_Flamingo();
|
||||
$columns[] = new WPCF7_WelcomePanelColumn_Integration();
|
||||
}
|
||||
|
||||
$classes = 'wpcf7-welcome-panel';
|
||||
|
||||
$vers = (array) get_user_meta( get_current_user_id(),
|
||||
'wpcf7_hide_welcome_panel_on', true
|
||||
);
|
||||
|
||||
if ( wpcf7_version_grep( wpcf7_version( 'only_major=1' ), $vers ) ) {
|
||||
$classes .= ' hidden';
|
||||
}
|
||||
|
||||
?>
|
||||
<div id="wpcf7-welcome-panel" class="<?php echo esc_attr( $classes ); ?>">
|
||||
<?php wp_nonce_field( 'wpcf7-welcome-panel-nonce', 'welcomepanelnonce', false ); ?>
|
||||
<a class="welcome-panel-close" href="<?php echo esc_url( menu_page_url( 'wpcf7', false ) ); ?>"><?php echo esc_html( __( 'Dismiss', 'contact-form-7' ) ); ?></a>
|
||||
|
||||
<div class="welcome-panel-content">
|
||||
<div class="welcome-panel-column-container">
|
||||
<?php
|
||||
|
||||
foreach ( $columns as $column ) {
|
||||
$column->print_content();
|
||||
}
|
||||
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
|
||||
add_action(
|
||||
'wp_ajax_wpcf7-update-welcome-panel',
|
||||
'wpcf7_admin_ajax_welcome_panel',
|
||||
10, 0
|
||||
);
|
||||
|
||||
function wpcf7_admin_ajax_welcome_panel() {
|
||||
check_ajax_referer( 'wpcf7-welcome-panel-nonce', 'welcomepanelnonce' );
|
||||
|
||||
$vers = get_user_meta( get_current_user_id(),
|
||||
'wpcf7_hide_welcome_panel_on', true
|
||||
);
|
||||
|
||||
if ( empty( $vers ) or ! is_array( $vers ) ) {
|
||||
$vers = array();
|
||||
}
|
||||
|
||||
if ( empty( $_POST['visible'] ) ) {
|
||||
$vers[] = wpcf7_version( 'only_major=1' );
|
||||
} else {
|
||||
$vers = array_diff( $vers, array( wpcf7_version( 'only_major=1' ) ) );
|
||||
}
|
||||
|
||||
$vers = array_unique( $vers );
|
||||
|
||||
update_user_meta( get_current_user_id(),
|
||||
'wpcf7_hide_welcome_panel_on', $vers
|
||||
);
|
||||
|
||||
wp_die( 1 );
|
||||
}
|
||||
|
||||
|
||||
add_filter(
|
||||
'screen_settings',
|
||||
'wpcf7_welcome_panel_screen_settings',
|
||||
10, 2
|
||||
);
|
||||
|
||||
function wpcf7_welcome_panel_screen_settings( $screen_settings, $screen ) {
|
||||
|
||||
if ( 'toplevel_page_wpcf7' !== $screen->id ) {
|
||||
return $screen_settings;
|
||||
}
|
||||
|
||||
$vers = (array) get_user_meta( get_current_user_id(),
|
||||
'wpcf7_hide_welcome_panel_on', true
|
||||
);
|
||||
|
||||
$checkbox_id = 'wpcf7-welcome-panel-show';
|
||||
$checked = ! in_array( wpcf7_version( 'only_major=1' ), $vers, true );
|
||||
|
||||
$checkbox = sprintf(
|
||||
'<input %s />',
|
||||
wpcf7_format_atts( array(
|
||||
'id' => $checkbox_id,
|
||||
'type' => 'checkbox',
|
||||
'checked' => $checked,
|
||||
) )
|
||||
);
|
||||
|
||||
$screen_settings .= sprintf( '
|
||||
<fieldset class="wpcf7-welcome-panel-options">
|
||||
<legend>%1$s</legend>
|
||||
<label for="%2$s">%3$s %4$s</label>
|
||||
</fieldset>',
|
||||
esc_html( __( 'Welcome panel', 'contact-form-7' ) ),
|
||||
esc_attr( $checkbox_id ),
|
||||
$checkbox,
|
||||
esc_html( __( 'Show welcome panel', 'contact-form-7' ) )
|
||||
);
|
||||
|
||||
return $screen_settings;
|
||||
}
|
||||
BIN
wp-content/plugins/contact-form-7/assets/icon.png
Normal file
|
After Width: | Height: | Size: 29 KiB |
1
wp-content/plugins/contact-form-7/assets/icon.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 242.5 239.46"><defs><style>.cls-1,.cls-6{fill:none;}.cls-2{clip-path:url(#clip-path);}.cls-3{fill:#33c6f4;}.cls-4{fill:#1b447e;}.cls-5{fill:#fff;}.cls-6{stroke:#221e1f;stroke-miterlimit:10;stroke-width:7.16px;}</style><clipPath id="clip-path" transform="translate(1.72)"><circle class="cls-1" cx="119.73" cy="119.73" r="116.15"/></clipPath></defs><g id="Layer_2" data-name="Layer 2"><g id="Layer_1" data-name="Layer 1"><g class="cls-2"><circle class="cls-3" cx="121.45" cy="119.73" r="116.15"/><path class="cls-4" d="M239.32,167.79c-53.41-24-108.37-91.46-113-94.55s-10.84.77-10.84.77c-3.87-6.19-10.06.77-10.06.77C76.77,123.55.14,170.11.14,170.11S36.94,237.79,122,237.79C208.48,237.79,239.32,167.79,239.32,167.79Z" transform="translate(1.72)"/><path class="cls-5" d="M67.48,116.58s15.48-7,12.38,4.65-15.48,28.64-11.61,29.41S83,140.58,86.06,142.12s5.42.78,3.87,6.2-3.1,9.29,0,9.29,5.42-7,9.29-13.94,10.06-3.87,12.38-1.55,9.29,15.49,14.71,13.94,8.51-8.52,6.19-24,1.55-20.12,1.55-20.12,4.64-2.32,13.16,8.51,24,27.09,26.31,26.32-10.83-17.8-7.74-19.35,15.48,2.32,21.68,7.74c0,0,2.12,8.87,2.12.36L126.31,73.24,115.47,74l-10.06.77S80.64,111.94,67.48,116.58Z" transform="translate(1.72)"/><path class="cls-6" d="M239.32,170.11c-53.41-24-108.37-93.78-113-96.87s-10.84.77-10.84.77c-3.87-6.19-10.06.77-10.06.77C76.77,123.55.14,170.11.14,170.11" transform="translate(1.72)"/></g><circle class="cls-6" cx="121.45" cy="119.73" r="116.15"/></g></g></svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
add_action(
|
||||
'init',
|
||||
'wpcf7_init_block_editor_assets',
|
||||
10, 0
|
||||
);
|
||||
|
||||
function wpcf7_init_block_editor_assets() {
|
||||
register_block_type(
|
||||
wpcf7_plugin_path( 'includes/block-editor' )
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"$schema": "https://schemas.wp.org/trunk/block.json",
|
||||
"apiVersion": 3,
|
||||
"name": "contact-form-7/contact-form-selector",
|
||||
"title": "Contact Form 7",
|
||||
"category": "widgets",
|
||||
"description": "Insert a contact form you have created with Contact Form 7.",
|
||||
"keywords": [ "form" ],
|
||||
"textdomain": "contact-form-7",
|
||||
"attributes": {
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"hash": {
|
||||
"type": "string"
|
||||
},
|
||||
"title": {
|
||||
"type": "string"
|
||||
},
|
||||
"htmlId": {
|
||||
"type": "string"
|
||||
},
|
||||
"htmlName": {
|
||||
"type": "string"
|
||||
},
|
||||
"htmlTitle": {
|
||||
"type": "string"
|
||||
},
|
||||
"htmlClass": {
|
||||
"type": "string"
|
||||
},
|
||||
"output": {
|
||||
"enum": [ "form", "raw_form" ],
|
||||
"default": "form"
|
||||
}
|
||||
},
|
||||
"editorScript": [ "file:./index.js", "contact-form-7-block-editor" ]
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'dependencies' => array(
|
||||
'react-jsx-runtime',
|
||||
'wp-api-fetch',
|
||||
'wp-block-editor',
|
||||
'wp-blocks',
|
||||
'wp-components',
|
||||
'wp-element',
|
||||
'wp-i18n',
|
||||
'wp-url',
|
||||
),
|
||||
'version' => WPCF7_VERSION,
|
||||
);
|
||||
26
wp-content/plugins/contact-form-7/includes/capabilities.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
add_filter( 'map_meta_cap', 'wpcf7_map_meta_cap', 10, 4 );
|
||||
|
||||
function wpcf7_map_meta_cap( $caps, $cap, $user_id, $args ) {
|
||||
$meta_caps = array(
|
||||
'wpcf7_edit_contact_form' => WPCF7_ADMIN_READ_WRITE_CAPABILITY,
|
||||
'wpcf7_edit_contact_forms' => WPCF7_ADMIN_READ_WRITE_CAPABILITY,
|
||||
'wpcf7_read_contact_form' => WPCF7_ADMIN_READ_CAPABILITY,
|
||||
'wpcf7_read_contact_forms' => WPCF7_ADMIN_READ_CAPABILITY,
|
||||
'wpcf7_delete_contact_form' => WPCF7_ADMIN_READ_WRITE_CAPABILITY,
|
||||
'wpcf7_delete_contact_forms' => WPCF7_ADMIN_READ_WRITE_CAPABILITY,
|
||||
'wpcf7_manage_integration' => 'manage_options',
|
||||
'wpcf7_submit' => 'read',
|
||||
);
|
||||
|
||||
$meta_caps = apply_filters( 'wpcf7_map_meta_cap', $meta_caps );
|
||||
|
||||
$caps = array_diff( $caps, array_keys( $meta_caps ) );
|
||||
|
||||
if ( isset( $meta_caps[$cap] ) ) {
|
||||
$caps[] = $meta_caps[$cap];
|
||||
}
|
||||
|
||||
return $caps;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
add_action(
|
||||
'wpcf7_update_option',
|
||||
'wpcf7_config_validator_update_option',
|
||||
10, 3
|
||||
);
|
||||
|
||||
/**
|
||||
* Runs bulk validation after the reCAPTCHA integration option is updated.
|
||||
*/
|
||||
function wpcf7_config_validator_update_option( $name, $value, $old_option ) {
|
||||
if ( 'recaptcha' === $name ) {
|
||||
$contact_forms = WPCF7_ContactForm::find();
|
||||
|
||||
$options = array(
|
||||
'include' => 'unsafe_email_without_protection',
|
||||
);
|
||||
|
||||
foreach ( $contact_forms as $contact_form ) {
|
||||
$config_validator = new WPCF7_ConfigValidator( $contact_form, $options );
|
||||
$config_validator->restore();
|
||||
$config_validator->validate();
|
||||
$config_validator->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
trait WPCF7_ConfigValidator_AdditionalSettings {
|
||||
|
||||
/**
|
||||
* Runs error detection for the additional settings section.
|
||||
*/
|
||||
public function validate_additional_settings() {
|
||||
$section = 'additional_settings.body';
|
||||
|
||||
if ( $this->supports( 'deprecated_settings' ) ) {
|
||||
$deprecated_settings_used =
|
||||
$this->contact_form->additional_setting( 'on_sent_ok' ) ||
|
||||
$this->contact_form->additional_setting( 'on_submit' );
|
||||
|
||||
if ( $deprecated_settings_used ) {
|
||||
$this->add_error( $section, 'deprecated_settings',
|
||||
array(
|
||||
'message' => __( 'Deprecated settings are used.', 'contact-form-7' ),
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$this->remove_error( $section, 'deprecated_settings' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,278 @@
|
||||
<?php
|
||||
|
||||
trait WPCF7_ConfigValidator_Form {
|
||||
|
||||
/**
|
||||
* Runs error detection for the form section.
|
||||
*/
|
||||
public function validate_form() {
|
||||
$section = 'form.body';
|
||||
$form = $this->contact_form->prop( 'form' );
|
||||
|
||||
if ( $this->supports( 'multiple_controls_in_label' ) ) {
|
||||
if ( $this->detect_multiple_controls_in_label( $section, $form ) ) {
|
||||
$this->add_error( $section, 'multiple_controls_in_label',
|
||||
array(
|
||||
'message' => __( 'Multiple form controls are in a single label element.', 'contact-form-7' ),
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$this->remove_error( $section, 'multiple_controls_in_label' );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $this->supports( 'unavailable_names' ) ) {
|
||||
$ng_names = $this->detect_unavailable_names( $section, $form );
|
||||
|
||||
if ( $ng_names ) {
|
||||
$this->add_error( $section, 'unavailable_names',
|
||||
array(
|
||||
'message' =>
|
||||
/* translators: %names%: a list of form control names */
|
||||
__( 'Unavailable names (%names%) are used for form controls.', 'contact-form-7' ),
|
||||
'params' => array( 'names' => implode( ', ', $ng_names ) ),
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$this->remove_error( $section, 'unavailable_names' );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $this->supports( 'unavailable_html_elements' ) ) {
|
||||
if ( $this->detect_unavailable_html_elements( $section, $form ) ) {
|
||||
$this->add_error( $section, 'unavailable_html_elements',
|
||||
array(
|
||||
'message' => __( 'Unavailable HTML elements are used in the form template.', 'contact-form-7' ),
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$this->remove_error( $section, 'unavailable_html_elements' );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $this->supports( 'dots_in_names' ) ) {
|
||||
if ( $this->detect_dots_in_names( $section, $form ) ) {
|
||||
$this->add_error( $section, 'dots_in_names',
|
||||
array(
|
||||
'message' => __( 'Dots are used in form-tag names.', 'contact-form-7' ),
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$this->remove_error( $section, 'dots_in_names' );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $this->supports( 'colons_in_names' ) ) {
|
||||
if ( $this->detect_colons_in_names( $section, $form ) ) {
|
||||
$this->add_error( $section, 'colons_in_names',
|
||||
array(
|
||||
'message' => __( 'Colons are used in form-tag names.', 'contact-form-7' ),
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$this->remove_error( $section, 'colons_in_names' );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $this->supports( 'upload_filesize_overlimit' ) ) {
|
||||
if ( $this->detect_upload_filesize_overlimit( $section, $form ) ) {
|
||||
$this->add_error( $section, 'upload_filesize_overlimit',
|
||||
array(
|
||||
'message' => __( 'Uploadable file size exceeds PHP’s maximum acceptable size.', 'contact-form-7' ),
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$this->remove_error( $section, 'upload_filesize_overlimit' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Detects errors of multiple form controls in a single label.
|
||||
*
|
||||
* @link https://contactform7.com/configuration-errors/multiple-controls-in-label/
|
||||
*/
|
||||
public function detect_multiple_controls_in_label( $section, $content ) {
|
||||
$pattern = '%<label(?:[ \t\n]+.*?)?>(.+?)</label>%s';
|
||||
|
||||
if ( preg_match_all( $pattern, $content, $matches ) ) {
|
||||
$form_tags_manager = WPCF7_FormTagsManager::get_instance();
|
||||
|
||||
foreach ( $matches[1] as $insidelabel ) {
|
||||
$tags = $form_tags_manager->scan( $insidelabel );
|
||||
$fields_count = 0;
|
||||
|
||||
foreach ( $tags as $tag ) {
|
||||
$is_multiple_controls_container = wpcf7_form_tag_supports(
|
||||
$tag->type, 'multiple-controls-container'
|
||||
);
|
||||
|
||||
$is_zero_controls_container = wpcf7_form_tag_supports(
|
||||
$tag->type, 'zero-controls-container'
|
||||
);
|
||||
|
||||
if ( $is_multiple_controls_container ) {
|
||||
$fields_count += count( $tag->values );
|
||||
|
||||
if ( $tag->has_option( 'free_text' ) ) {
|
||||
$fields_count += 1;
|
||||
}
|
||||
} elseif ( $is_zero_controls_container ) {
|
||||
$fields_count += 0;
|
||||
} elseif ( ! empty( $tag->name ) ) {
|
||||
$fields_count += 1;
|
||||
}
|
||||
|
||||
if ( 1 < $fields_count ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Detects errors of unavailable form-tag names.
|
||||
*
|
||||
* @link https://contactform7.com/configuration-errors/unavailable-names/
|
||||
*/
|
||||
public function detect_unavailable_names( $section, $content ) {
|
||||
$public_query_vars = array( 'm', 'p', 'posts', 'w', 'cat',
|
||||
'withcomments', 'withoutcomments', 's', 'search', 'exact', 'sentence',
|
||||
'calendar', 'page', 'paged', 'more', 'tb', 'pb', 'author', 'order',
|
||||
'orderby', 'year', 'monthnum', 'day', 'hour', 'minute', 'second',
|
||||
'name', 'category_name', 'tag', 'feed', 'author_name', 'static',
|
||||
'pagename', 'page_id', 'error', 'attachment', 'attachment_id',
|
||||
'subpost', 'subpost_id', 'preview', 'robots', 'taxonomy', 'term',
|
||||
'cpage', 'post_type', 'embed',
|
||||
);
|
||||
|
||||
$form_tags_manager = WPCF7_FormTagsManager::get_instance();
|
||||
|
||||
$ng_named_tags = $form_tags_manager->filter( $content, array(
|
||||
'name' => $public_query_vars,
|
||||
) );
|
||||
|
||||
$ng_names = array();
|
||||
|
||||
foreach ( $ng_named_tags as $tag ) {
|
||||
$ng_names[] = sprintf( '"%s"', $tag->name );
|
||||
}
|
||||
|
||||
if ( $ng_names ) {
|
||||
return array_unique( $ng_names );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Detects errors of unavailable HTML elements.
|
||||
*
|
||||
* @link https://contactform7.com/configuration-errors/unavailable-html-elements/
|
||||
*/
|
||||
public function detect_unavailable_html_elements( $section, $content ) {
|
||||
$pattern = '%(?:<form[\s\t>]|</form>)%i';
|
||||
|
||||
if ( preg_match( $pattern, $content ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Detects errors of dots in form-tag names.
|
||||
*
|
||||
* @link https://contactform7.com/configuration-errors/dots-in-names/
|
||||
*/
|
||||
public function detect_dots_in_names( $section, $content ) {
|
||||
$form_tags_manager = WPCF7_FormTagsManager::get_instance();
|
||||
|
||||
$tags = $form_tags_manager->filter( $content, array(
|
||||
'feature' => 'name-attr',
|
||||
) );
|
||||
|
||||
foreach ( $tags as $tag ) {
|
||||
if ( str_contains( $tag->raw_name, '.' ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Detects errors of colons in form-tag names.
|
||||
*
|
||||
* @link https://contactform7.com/configuration-errors/colons-in-names/
|
||||
*/
|
||||
public function detect_colons_in_names( $section, $content ) {
|
||||
$form_tags_manager = WPCF7_FormTagsManager::get_instance();
|
||||
|
||||
$tags = $form_tags_manager->filter( $content, array(
|
||||
'feature' => 'name-attr',
|
||||
) );
|
||||
|
||||
foreach ( $tags as $tag ) {
|
||||
if ( str_contains( $tag->raw_name, ':' ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Detects errors of uploadable file size overlimit.
|
||||
*
|
||||
* @link https://contactform7.com/configuration-errors/upload-filesize-overlimit
|
||||
*/
|
||||
public function detect_upload_filesize_overlimit( $section, $content ) {
|
||||
$upload_max_filesize = ini_get( 'upload_max_filesize' );
|
||||
|
||||
if ( ! $upload_max_filesize ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$upload_max_filesize = strtolower( $upload_max_filesize );
|
||||
$upload_max_filesize = trim( $upload_max_filesize );
|
||||
|
||||
if ( ! preg_match( '/^(\d+)([kmg]?)$/', $upload_max_filesize, $matches ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( 'k' === $matches[2] ) {
|
||||
$upload_max_filesize = (int) $matches[1] * KB_IN_BYTES;
|
||||
} elseif ( 'm' === $matches[2] ) {
|
||||
$upload_max_filesize = (int) $matches[1] * MB_IN_BYTES;
|
||||
} elseif ( 'g' === $matches[2] ) {
|
||||
$upload_max_filesize = (int) $matches[1] * GB_IN_BYTES;
|
||||
} else {
|
||||
$upload_max_filesize = (int) $matches[1];
|
||||
}
|
||||
|
||||
$form_tags_manager = WPCF7_FormTagsManager::get_instance();
|
||||
|
||||
$tags = $form_tags_manager->filter( $content, array(
|
||||
'basetype' => 'file',
|
||||
) );
|
||||
|
||||
foreach ( $tags as $tag ) {
|
||||
if ( $upload_max_filesize < $tag->get_limit_option() ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,583 @@
|
||||
<?php
|
||||
|
||||
trait WPCF7_ConfigValidator_Mail {
|
||||
|
||||
/**
|
||||
* Replaces all mail-tags in the given content.
|
||||
*/
|
||||
public function replace_mail_tags( $content, $options = '' ) {
|
||||
$options = wp_parse_args( $options, array(
|
||||
'html' => false,
|
||||
'callback' =>
|
||||
array( $this, 'replace_mail_tags_with_minimum_input_callback' ),
|
||||
) );
|
||||
|
||||
$content = new WPCF7_MailTaggedText( $content, $options );
|
||||
|
||||
return $content->replace_tags();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Callback function for WPCF7_MailTaggedText. Replaces mail-tags with
|
||||
* the most conservative inputs.
|
||||
*/
|
||||
public function replace_mail_tags_with_minimum_input_callback( $matches ) {
|
||||
// allow [[foo]] syntax for escaping a tag
|
||||
if ( '[' === $matches[1] and ']' === $matches[4] ) {
|
||||
return substr( $matches[0], 1, -1 );
|
||||
}
|
||||
|
||||
$tag = $matches[0];
|
||||
$tagname = $matches[2];
|
||||
$values = $matches[3];
|
||||
|
||||
$mail_tag = new WPCF7_MailTag( $tag, $tagname, $values );
|
||||
$field_name = $mail_tag->field_name();
|
||||
|
||||
$example_email = 'example@example.com';
|
||||
$example_text = 'example';
|
||||
$example_blank = '';
|
||||
|
||||
// for back-compat
|
||||
$field_name = preg_replace( '/^wpcf7\./', '_', $field_name );
|
||||
|
||||
if ( '_site_admin_email' === $field_name ) {
|
||||
return get_bloginfo( 'admin_email', 'raw' );
|
||||
|
||||
} elseif ( '_user_agent' === $field_name ) {
|
||||
return $example_text;
|
||||
|
||||
} elseif ( '_user_email' === $field_name ) {
|
||||
return $this->contact_form->is_true( 'subscribers_only' )
|
||||
? $example_email
|
||||
: $example_blank;
|
||||
|
||||
} elseif ( str_starts_with( $field_name, '_user_' ) ) {
|
||||
return $this->contact_form->is_true( 'subscribers_only' )
|
||||
? $example_text
|
||||
: $example_blank;
|
||||
|
||||
} elseif ( str_starts_with( $field_name, '_' ) ) {
|
||||
return str_ends_with( $field_name, '_email' )
|
||||
? $example_email
|
||||
: $example_text;
|
||||
|
||||
}
|
||||
|
||||
static $opcalcset = array();
|
||||
|
||||
if ( ! isset( $opcalcset[$this->contact_form->id()] ) ) {
|
||||
$opcalcset[$this->contact_form->id()] =
|
||||
new WPCF7_MailTag_OutputCalculator( $this->contact_form );
|
||||
}
|
||||
|
||||
$opcalc = $opcalcset[$this->contact_form->id()];
|
||||
$op = $opcalc->calc_output( $mail_tag );
|
||||
|
||||
if ( WPCF7_MailTag_OutputCalculator::email === $op ) {
|
||||
return $example_email;
|
||||
} elseif ( ! ( WPCF7_MailTag_OutputCalculator::blank & $op ) ) {
|
||||
return $example_text;
|
||||
} else {
|
||||
return $example_blank;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Runs error detection for the mail sections.
|
||||
*/
|
||||
public function validate_mail( $template = 'mail' ) {
|
||||
if (
|
||||
$this->contact_form->is_true( 'demo_mode' ) or
|
||||
$this->contact_form->is_true( 'skip_mail' )
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
$components = (array) $this->contact_form->prop( $template );
|
||||
|
||||
if ( ! $components ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( 'mail' !== $template and empty( $components['active'] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$components = wp_parse_args( $components, array(
|
||||
'subject' => '',
|
||||
'sender' => '',
|
||||
'recipient' => '',
|
||||
'additional_headers' => '',
|
||||
'body' => '',
|
||||
'attachments' => '',
|
||||
) );
|
||||
|
||||
$this->validate_mail_subject(
|
||||
$template,
|
||||
$components['subject']
|
||||
);
|
||||
|
||||
$this->validate_mail_sender(
|
||||
$template,
|
||||
$components['sender']
|
||||
);
|
||||
|
||||
$this->validate_mail_recipient(
|
||||
$template,
|
||||
$components['recipient']
|
||||
);
|
||||
|
||||
$this->validate_mail_additional_headers(
|
||||
$template,
|
||||
$components['additional_headers']
|
||||
);
|
||||
|
||||
$this->validate_mail_body(
|
||||
$template,
|
||||
$components['body']
|
||||
);
|
||||
|
||||
$this->validate_mail_attachments(
|
||||
$template,
|
||||
$components['attachments']
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Runs error detection for the mail subject section.
|
||||
*/
|
||||
public function validate_mail_subject( $template, $content ) {
|
||||
$section = sprintf( '%s.subject', $template );
|
||||
|
||||
if ( $this->supports( 'maybe_empty' ) ) {
|
||||
if ( $this->detect_maybe_empty( $section, $content ) ) {
|
||||
$this->add_error( $section, 'maybe_empty',
|
||||
array(
|
||||
'message' => __( 'There is a possible empty field.', 'contact-form-7' ),
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$this->remove_error( $section, 'maybe_empty' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Runs error detection for the mail sender section.
|
||||
*/
|
||||
public function validate_mail_sender( $template, $content ) {
|
||||
$section = sprintf( '%s.sender', $template );
|
||||
|
||||
if ( $this->supports( 'invalid_mailbox_syntax' ) ) {
|
||||
if ( $this->detect_invalid_mailbox_syntax( $section, $content ) ) {
|
||||
$this->add_error( $section, 'invalid_mailbox_syntax',
|
||||
array(
|
||||
'message' => __( 'Invalid mailbox syntax is used.', 'contact-form-7' ),
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$this->remove_error( $section, 'invalid_mailbox_syntax' );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $this->supports( 'email_not_in_site_domain' ) ) {
|
||||
$this->remove_error( $section, 'email_not_in_site_domain' );
|
||||
|
||||
if ( ! $this->has_error( $section, 'invalid_mailbox_syntax' ) ) {
|
||||
$sender = $this->replace_mail_tags( $content );
|
||||
$sender = wpcf7_strip_newline( $sender );
|
||||
|
||||
if ( ! wpcf7_is_email_in_site_domain( $sender ) ) {
|
||||
$this->add_error( $section, 'email_not_in_site_domain',
|
||||
array(
|
||||
'message' => __( 'Sender email address does not belong to the site domain.', 'contact-form-7' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Runs error detection for the mail recipient section.
|
||||
*/
|
||||
public function validate_mail_recipient( $template, $content ) {
|
||||
$section = sprintf( '%s.recipient', $template );
|
||||
|
||||
if ( $this->supports( 'invalid_mailbox_syntax' ) ) {
|
||||
if ( $this->detect_invalid_mailbox_syntax( $section, $content ) ) {
|
||||
$this->add_error( $section, 'invalid_mailbox_syntax',
|
||||
array(
|
||||
'message' => __( 'Invalid mailbox syntax is used.', 'contact-form-7' ),
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$this->remove_error( $section, 'invalid_mailbox_syntax' );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $this->supports( 'unsafe_email_without_protection' ) ) {
|
||||
$this->remove_error( $section, 'unsafe_email_without_protection' );
|
||||
|
||||
if ( ! $this->has_error( $section, 'invalid_mailbox_syntax' ) ) {
|
||||
if (
|
||||
$this->detect_unsafe_email_without_protection( $section, $content )
|
||||
) {
|
||||
$this->add_error( $section, 'unsafe_email_without_protection',
|
||||
array(
|
||||
'message' => __( 'Unsafe email config is used without sufficient protection.', 'contact-form-7' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Runs error detection for the mail additional headers section.
|
||||
*/
|
||||
public function validate_mail_additional_headers( $template, $content ) {
|
||||
$section = sprintf( '%s.additional_headers', $template );
|
||||
|
||||
$invalid_mail_headers = array();
|
||||
$invalid_mailbox_fields = array();
|
||||
$unsafe_email_fields = array();
|
||||
|
||||
foreach ( explode( "\n", $content ) as $header ) {
|
||||
$header = trim( $header );
|
||||
|
||||
if ( '' === $header ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$is_valid_header = preg_match(
|
||||
'/^([0-9A-Za-z-]+):(.*)$/',
|
||||
$header,
|
||||
$matches
|
||||
);
|
||||
|
||||
if ( ! $is_valid_header ) {
|
||||
$invalid_mail_headers[] = $header;
|
||||
continue;
|
||||
}
|
||||
|
||||
$header_name = $matches[1];
|
||||
$header_value = trim( $matches[2] );
|
||||
|
||||
if (
|
||||
in_array(
|
||||
strtolower( $header_name ), array( 'reply-to', 'cc', 'bcc' ), true
|
||||
) and
|
||||
'' !== $header_value and
|
||||
$this->detect_invalid_mailbox_syntax( $section, $header_value )
|
||||
) {
|
||||
$invalid_mailbox_fields[] = $header_name;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
in_array( strtolower( $header_name ), array( 'cc', 'bcc' ), true ) and
|
||||
$this->detect_unsafe_email_without_protection( $section, $header_value )
|
||||
) {
|
||||
$unsafe_email_fields[] = $header_name;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $this->supports( 'invalid_mail_header' ) ) {
|
||||
if ( ! empty( $invalid_mail_headers ) ) {
|
||||
$this->add_error( $section, 'invalid_mail_header',
|
||||
array(
|
||||
'message' => __( 'There are invalid mail header fields.', 'contact-form-7' ),
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$this->remove_error( $section, 'invalid_mail_header' );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $this->supports( 'invalid_mailbox_syntax' ) ) {
|
||||
if ( ! empty( $invalid_mailbox_fields ) ) {
|
||||
foreach ( $invalid_mailbox_fields as $header_name ) {
|
||||
$this->add_error( $section, 'invalid_mailbox_syntax',
|
||||
array(
|
||||
'message' => __( 'Invalid mailbox syntax is used in the %name% field.', 'contact-form-7' ),
|
||||
'params' => array( 'name' => $header_name ),
|
||||
)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$this->remove_error( $section, 'invalid_mailbox_syntax' );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $this->supports( 'unsafe_email_without_protection' ) ) {
|
||||
if ( ! empty( $unsafe_email_fields ) ) {
|
||||
$this->add_error( $section, 'unsafe_email_without_protection',
|
||||
array(
|
||||
'message' => __( 'Unsafe email config is used without sufficient protection.', 'contact-form-7' ),
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$this->remove_error( $section, 'unsafe_email_without_protection' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Runs error detection for the mail body section.
|
||||
*/
|
||||
public function validate_mail_body( $template, $content ) {
|
||||
$section = sprintf( '%s.body', $template );
|
||||
|
||||
if ( $this->supports( 'maybe_empty' ) ) {
|
||||
if ( $this->detect_maybe_empty( $section, $content ) ) {
|
||||
$this->add_error( $section, 'maybe_empty',
|
||||
array(
|
||||
'message' => __( 'There is a possible empty field.', 'contact-form-7' ),
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$this->remove_error( $section, 'maybe_empty' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Runs error detection for the mail attachments section.
|
||||
*/
|
||||
public function validate_mail_attachments( $template, $content ) {
|
||||
$section = sprintf( '%s.attachments', $template );
|
||||
|
||||
$total_size = 0;
|
||||
$files_not_found = array();
|
||||
$files_out_of_content = array();
|
||||
|
||||
if ( '' !== $content ) {
|
||||
$attachables = array();
|
||||
|
||||
$tags = $this->contact_form->scan_form_tags(
|
||||
array( 'type' => array( 'file', 'file*' ) )
|
||||
);
|
||||
|
||||
foreach ( $tags as $tag ) {
|
||||
$name = $tag->name;
|
||||
|
||||
if ( ! str_contains( $content, "[{$name}]" ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$limit = (int) $tag->get_limit_option();
|
||||
|
||||
if ( empty( $attachables[$name] ) or $attachables[$name] < $limit ) {
|
||||
$attachables[$name] = $limit;
|
||||
}
|
||||
}
|
||||
|
||||
$total_size = array_sum( $attachables );
|
||||
|
||||
foreach ( explode( "\n", $content ) as $line ) {
|
||||
$line = trim( $line );
|
||||
|
||||
if ( '' === $line or str_starts_with( $line, '[' ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( $this->detect_file_not_found( $section, $line ) ) {
|
||||
$files_not_found[] = $line;
|
||||
} elseif ( $this->detect_file_not_in_content_dir( $section, $line ) ) {
|
||||
$files_out_of_content[] = $line;
|
||||
} else {
|
||||
$total_size += (int) @filesize( path_join( WP_CONTENT_DIR, $line ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( $this->supports( 'file_not_found' ) ) {
|
||||
if ( ! empty( $files_not_found ) ) {
|
||||
foreach ( $files_not_found as $line ) {
|
||||
$this->add_error( $section, 'file_not_found',
|
||||
array(
|
||||
'message' => __( 'Attachment file does not exist at %path%.', 'contact-form-7' ),
|
||||
'params' => array( 'path' => $line ),
|
||||
)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$this->remove_error( $section, 'file_not_found' );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $this->supports( 'file_not_in_content_dir' ) ) {
|
||||
if ( ! empty( $files_out_of_content ) ) {
|
||||
$this->add_error( $section, 'file_not_in_content_dir',
|
||||
array(
|
||||
'message' => __( 'It is not allowed to use files outside the wp-content directory.', 'contact-form-7' ),
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$this->remove_error( $section, 'file_not_in_content_dir' );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $this->supports( 'attachments_overweight' ) ) {
|
||||
$max = 25 * MB_IN_BYTES; // 25 MB
|
||||
|
||||
if ( $max < $total_size ) {
|
||||
$this->add_error( $section, 'attachments_overweight',
|
||||
array(
|
||||
'message' => __( 'The total size of attachment files is too large.', 'contact-form-7' ),
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$this->remove_error( $section, 'attachments_overweight' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Detects errors of invalid mailbox syntax.
|
||||
*
|
||||
* @link https://contactform7.com/configuration-errors/invalid-mailbox-syntax/
|
||||
*/
|
||||
public function detect_invalid_mailbox_syntax( $section, $content ) {
|
||||
$content = $this->replace_mail_tags( $content );
|
||||
$content = wpcf7_strip_newline( $content );
|
||||
|
||||
if ( ! wpcf7_is_mailbox_list( $content ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Detects errors of empty message fields.
|
||||
*
|
||||
* @link https://contactform7.com/configuration-errors/maybe-empty/
|
||||
*/
|
||||
public function detect_maybe_empty( $section, $content ) {
|
||||
$content = $this->replace_mail_tags( $content );
|
||||
$content = wpcf7_strip_newline( $content );
|
||||
|
||||
if ( '' === $content ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Detects errors of nonexistent attachment files.
|
||||
*
|
||||
* @link https://contactform7.com/configuration-errors/file-not-found/
|
||||
*/
|
||||
public function detect_file_not_found( $section, $content ) {
|
||||
$path = path_join( WP_CONTENT_DIR, $content );
|
||||
|
||||
if ( ! is_readable( $path ) or ! is_file( $path ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Detects errors of attachment files out of the content directory.
|
||||
*
|
||||
* @link https://contactform7.com/configuration-errors/file-not-in-content-dir/
|
||||
*/
|
||||
public function detect_file_not_in_content_dir( $section, $content ) {
|
||||
$path = path_join( WP_CONTENT_DIR, $content );
|
||||
|
||||
if ( ! wpcf7_is_file_path_in_content_dir( $path ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Detects errors of that unsafe email config is used without
|
||||
* sufficient protection.
|
||||
*
|
||||
* @link https://contactform7.com/configuration-errors/unsafe-email-without-protection/
|
||||
*/
|
||||
public function detect_unsafe_email_without_protection( $section, $content ) {
|
||||
if ( $this->contact_form->is_true( 'subscribers_only' ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static $is_captcha_active = null;
|
||||
|
||||
if ( null === $is_captcha_active ) {
|
||||
$is_captcha_active = call_user_func( static function () {
|
||||
$recaptcha = WPCF7_RECAPTCHA::get_instance();
|
||||
$turnstile = WPCF7_Turnstile::get_instance();
|
||||
return $recaptcha->is_active() || $turnstile->is_active();
|
||||
} );
|
||||
}
|
||||
|
||||
if ( $is_captcha_active ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$example_email = 'user-specified@example.com';
|
||||
|
||||
// Replace mail-tags connected to an email type form-tag first.
|
||||
$content = $this->replace_mail_tags( $content, array(
|
||||
'callback' => function ( $matches ) use ( $example_email ) {
|
||||
// allow [[foo]] syntax for escaping a tag
|
||||
if ( '[' === $matches[1] and ']' === $matches[4] ) {
|
||||
return substr( $matches[0], 1, -1 );
|
||||
}
|
||||
|
||||
$tag = $matches[0];
|
||||
$tagname = $matches[2];
|
||||
$values = $matches[3];
|
||||
|
||||
$mail_tag = new WPCF7_MailTag( $tag, $tagname, $values );
|
||||
$field_name = $mail_tag->field_name();
|
||||
|
||||
$form_tags = $this->contact_form->scan_form_tags(
|
||||
array( 'name' => $field_name )
|
||||
);
|
||||
|
||||
if ( $form_tags ) {
|
||||
$form_tag = new WPCF7_FormTag( $form_tags[0] );
|
||||
|
||||
if ( 'email' === $form_tag->basetype ) {
|
||||
return $example_email;
|
||||
}
|
||||
}
|
||||
|
||||
return $tag;
|
||||
},
|
||||
) );
|
||||
|
||||
// Replace remaining mail-tags.
|
||||
$content = $this->replace_mail_tags( $content );
|
||||
|
||||
$content = wpcf7_strip_newline( $content );
|
||||
|
||||
if ( str_contains( $content, $example_email ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
trait WPCF7_ConfigValidator_Messages {
|
||||
|
||||
/**
|
||||
* Runs error detection for the messages section.
|
||||
*/
|
||||
public function validate_messages() {
|
||||
$messages = (array) $this->contact_form->prop( 'messages' );
|
||||
|
||||
if ( ! $messages ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
isset( $messages['captcha_not_match'] ) and
|
||||
! wpcf7_use_really_simple_captcha()
|
||||
) {
|
||||
unset( $messages['captcha_not_match'] );
|
||||
}
|
||||
|
||||
foreach ( $messages as $key => $message ) {
|
||||
$section = sprintf( 'messages.%s', $key );
|
||||
|
||||
if ( $this->supports( 'html_in_message' ) ) {
|
||||
if ( $this->detect_html_in_message( $section, $message ) ) {
|
||||
$this->add_error( $section, 'html_in_message',
|
||||
array(
|
||||
'message' => __( 'HTML tags are used in a message.', 'contact-form-7' ),
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$this->remove_error( $section, 'html_in_message' );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Detects errors of HTML uses in a message.
|
||||
*
|
||||
* @link https://contactform7.com/configuration-errors/html-in-message/
|
||||
*/
|
||||
public function detect_html_in_message( $section, $content ) {
|
||||
$stripped = wp_strip_all_tags( $content );
|
||||
|
||||
if ( $stripped !== $content ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,386 @@
|
||||
<?php
|
||||
|
||||
require_once path_join( __DIR__, 'form.php' );
|
||||
require_once path_join( __DIR__, 'mail.php' );
|
||||
require_once path_join( __DIR__, 'messages.php' );
|
||||
require_once path_join( __DIR__, 'additional-settings.php' );
|
||||
require_once path_join( __DIR__, 'actions.php' );
|
||||
|
||||
|
||||
/**
|
||||
* Configuration validator.
|
||||
*
|
||||
* @link https://contactform7.com/configuration-errors/
|
||||
*/
|
||||
class WPCF7_ConfigValidator {
|
||||
|
||||
/**
|
||||
* The plugin version in which important updates happened last time.
|
||||
*/
|
||||
const last_important_update = '5.8.1';
|
||||
|
||||
const error_codes = array(
|
||||
'maybe_empty',
|
||||
'invalid_mailbox_syntax',
|
||||
'email_not_in_site_domain',
|
||||
'html_in_message',
|
||||
'multiple_controls_in_label',
|
||||
'file_not_found',
|
||||
'unavailable_names',
|
||||
'invalid_mail_header',
|
||||
'deprecated_settings',
|
||||
'file_not_in_content_dir',
|
||||
'unavailable_html_elements',
|
||||
'attachments_overweight',
|
||||
'dots_in_names',
|
||||
'colons_in_names',
|
||||
'upload_filesize_overlimit',
|
||||
'unsafe_email_without_protection',
|
||||
);
|
||||
|
||||
use WPCF7_ConfigValidator_Form;
|
||||
use WPCF7_ConfigValidator_Mail;
|
||||
use WPCF7_ConfigValidator_Messages;
|
||||
use WPCF7_ConfigValidator_AdditionalSettings;
|
||||
|
||||
private $contact_form;
|
||||
private $errors = array();
|
||||
private $include;
|
||||
private $exclude;
|
||||
|
||||
|
||||
/**
|
||||
* Returns a URL linking to the documentation page for the error type.
|
||||
*/
|
||||
public static function get_doc_link( $child_page = '' ) {
|
||||
$url = __( 'https://contactform7.com/configuration-errors/',
|
||||
'contact-form-7'
|
||||
);
|
||||
|
||||
if ( '' !== $child_page ) {
|
||||
$child_page = strtr( $child_page, '_', '-' );
|
||||
|
||||
$url = sprintf( '%s/%s', untrailingslashit( $url ), $child_page );
|
||||
}
|
||||
|
||||
return esc_url( $url );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct( WPCF7_ContactForm $contact_form, $options = '' ) {
|
||||
$options = wp_parse_args( $options, array(
|
||||
'include' => null,
|
||||
'exclude' => null,
|
||||
) );
|
||||
|
||||
$this->contact_form = $contact_form;
|
||||
|
||||
if ( isset( $options['include'] ) ) {
|
||||
$this->include = (array) $options['include'];
|
||||
}
|
||||
|
||||
if ( isset( $options['exclude'] ) ) {
|
||||
$this->exclude = (array) $options['exclude'];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the contact form object that is tied to this validator.
|
||||
*/
|
||||
public function contact_form() {
|
||||
return $this->contact_form;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if no error has been detected.
|
||||
*/
|
||||
public function is_valid() {
|
||||
return ! $this->count_errors();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the given error code is supported by this instance.
|
||||
*/
|
||||
public function supports( $error_code ) {
|
||||
if ( isset( $this->include ) ) {
|
||||
$supported_codes = array_intersect( self::error_codes, $this->include );
|
||||
} else {
|
||||
$supported_codes = self::error_codes;
|
||||
}
|
||||
|
||||
if ( isset( $this->exclude ) ) {
|
||||
$supported_codes = array_diff( $supported_codes, $this->exclude );
|
||||
}
|
||||
|
||||
return in_array( $error_code, $supported_codes, true );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Counts detected errors.
|
||||
*/
|
||||
public function count_errors( $options = '' ) {
|
||||
$options = wp_parse_args( $options, array(
|
||||
'section' => '',
|
||||
'code' => '',
|
||||
) );
|
||||
|
||||
$count = 0;
|
||||
|
||||
foreach ( $this->errors as $key => $errors ) {
|
||||
if ( preg_match( '/^mail_[0-9]+\.(.*)$/', $key, $matches ) ) {
|
||||
$key = sprintf( 'mail.%s', $matches[1] );
|
||||
}
|
||||
|
||||
if (
|
||||
$options['section'] and
|
||||
$key !== $options['section'] and
|
||||
preg_replace( '/\..*$/', '', $key, 1 ) !== $options['section']
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ( $errors as $error ) {
|
||||
if ( empty( $error ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( $options['code'] and $error['code'] !== $options['code'] ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return $count;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Collects messages for detected errors.
|
||||
*/
|
||||
public function collect_error_messages( $options = '' ) {
|
||||
$options = wp_parse_args( $options, array(
|
||||
'decodes_html_entities' => false,
|
||||
) );
|
||||
|
||||
$error_messages = array();
|
||||
|
||||
foreach ( $this->errors as $section => $errors ) {
|
||||
$error_messages[$section] = array();
|
||||
|
||||
foreach ( $errors as $error ) {
|
||||
if ( empty( $error['args']['message'] ) ) {
|
||||
$message = $this->get_default_message( $error['code'] );
|
||||
} elseif ( empty( $error['args']['params'] ) ) {
|
||||
$message = $error['args']['message'];
|
||||
} else {
|
||||
$message = $this->build_message(
|
||||
$error['args']['message'],
|
||||
$error['args']['params']
|
||||
);
|
||||
}
|
||||
|
||||
if ( $options['decodes_html_entities'] ) {
|
||||
$message = html_entity_decode( $message, ENT_HTML5 );
|
||||
}
|
||||
|
||||
$link = '';
|
||||
|
||||
if ( ! empty( $error['args']['link'] ) ) {
|
||||
$link = $error['args']['link'];
|
||||
}
|
||||
|
||||
$error_messages[$section][] = array(
|
||||
'message' => $message,
|
||||
'link' => esc_url( $link ),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $error_messages;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Builds an error message by replacing placeholders.
|
||||
*/
|
||||
public function build_message( $message, $params = '' ) {
|
||||
$params = wp_parse_args( $params, array() );
|
||||
|
||||
foreach ( $params as $key => $val ) {
|
||||
if ( ! preg_match( '/^[0-9A-Za-z_]+$/', $key ) ) { // invalid key
|
||||
continue;
|
||||
}
|
||||
|
||||
$placeholder = '%' . $key . '%';
|
||||
|
||||
if ( false !== stripos( $message, $placeholder ) ) {
|
||||
$message = str_ireplace( $placeholder, $val, $message );
|
||||
}
|
||||
}
|
||||
|
||||
return $message;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a default message that is used when the message for the error
|
||||
* is not specified.
|
||||
*/
|
||||
public function get_default_message( $code = '' ) {
|
||||
return __( 'Configuration error is detected.', 'contact-form-7' );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the specified section has the specified error.
|
||||
*
|
||||
* @param string $section The section where the error detected.
|
||||
* @param string $code The unique code of the error.
|
||||
*/
|
||||
public function has_error( $section, $code ) {
|
||||
if ( empty( $this->errors[$section] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ( (array) $this->errors[$section] as $error ) {
|
||||
if ( isset( $error['code'] ) and $error['code'] === $code ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a validation error.
|
||||
*
|
||||
* @param string $section The section where the error detected.
|
||||
* @param string $code The unique code of the error.
|
||||
* @param string|array $args Optional options for the error.
|
||||
*/
|
||||
public function add_error( $section, $code, $args = '' ) {
|
||||
$args = wp_parse_args( $args, array(
|
||||
'message' => '',
|
||||
'params' => array(),
|
||||
) );
|
||||
|
||||
$available_error_codes = (array) apply_filters(
|
||||
'wpcf7_config_validator_available_error_codes',
|
||||
self::error_codes,
|
||||
$this->contact_form
|
||||
);
|
||||
|
||||
if ( ! in_array( $code, $available_error_codes, true ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! isset( $args['link'] ) ) {
|
||||
$args['link'] = self::get_doc_link( $code );
|
||||
}
|
||||
|
||||
if ( ! isset( $this->errors[$section] ) ) {
|
||||
$this->errors[$section] = array();
|
||||
}
|
||||
|
||||
$this->errors[$section][] = array(
|
||||
'code' => $code,
|
||||
'args' => $args,
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Removes an error.
|
||||
*
|
||||
* @param string $section The section where the error detected.
|
||||
* @param string $code The unique code of the error.
|
||||
*/
|
||||
public function remove_error( $section, $code ) {
|
||||
if ( empty( $this->errors[$section] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ( (array) $this->errors[$section] as $key => $error ) {
|
||||
if ( isset( $error['code'] ) and $error['code'] === $code ) {
|
||||
unset( $this->errors[$section][$key] );
|
||||
}
|
||||
}
|
||||
|
||||
if ( empty( $this->errors[$section] ) ) {
|
||||
unset( $this->errors[$section] );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The main validation runner.
|
||||
*
|
||||
* @return bool True if there is no error detected.
|
||||
*/
|
||||
public function validate() {
|
||||
$this->validate_form();
|
||||
$this->validate_mail( 'mail' );
|
||||
$this->validate_mail( 'mail_2' );
|
||||
$this->validate_messages();
|
||||
$this->validate_additional_settings();
|
||||
|
||||
do_action( 'wpcf7_config_validator_validate', $this );
|
||||
|
||||
return $this->is_valid();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Saves detected errors as a post meta data.
|
||||
*/
|
||||
public function save() {
|
||||
if ( $this->contact_form->initial() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
delete_post_meta( $this->contact_form->id(), '_config_validation' );
|
||||
|
||||
if ( $this->errors ) {
|
||||
update_post_meta(
|
||||
$this->contact_form->id(), '_config_validation', $this->errors
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Restore errors from the database.
|
||||
*/
|
||||
public function restore() {
|
||||
$config_errors = get_post_meta(
|
||||
$this->contact_form->id(), '_config_validation', true
|
||||
);
|
||||
|
||||
foreach ( (array) $config_errors as $section => $errors ) {
|
||||
if ( empty( $errors ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ( (array) $errors as $error ) {
|
||||
if ( ! empty( $error['code'] ) ) {
|
||||
$code = $error['code'];
|
||||
$args = isset( $error['args'] ) ? $error['args'] : '';
|
||||
$this->add_error( $section, $code, $args );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,476 @@
|
||||
<?php
|
||||
/**
|
||||
* Contact form helper functions
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Wrapper function of WPCF7_ContactForm::get_instance().
|
||||
*
|
||||
* @param WPCF7_ContactForm|WP_Post|int $post Object or post ID.
|
||||
* @return WPCF7_ContactForm|null Contact form object. Null if unset.
|
||||
*/
|
||||
function wpcf7_contact_form( $post ) {
|
||||
return WPCF7_ContactForm::get_instance( $post );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Searches for a contact form by an old unit ID.
|
||||
*
|
||||
* @param int $old_id Old unit ID.
|
||||
* @return WPCF7_ContactForm Contact form object.
|
||||
*/
|
||||
function wpcf7_get_contact_form_by_old_id( $old_id ) {
|
||||
$contact_forms = WPCF7_ContactForm::find( array(
|
||||
'meta_query' => array(
|
||||
array(
|
||||
'key' => '_old_cf7_unit_id',
|
||||
'type' => 'DECIMAL',
|
||||
'value' => $old_id,
|
||||
),
|
||||
),
|
||||
'posts_per_page' => 1,
|
||||
) );
|
||||
|
||||
if ( $contact_forms ) {
|
||||
return wpcf7_contact_form( $contact_forms[0] );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Searches for a contact form by a hash string.
|
||||
*
|
||||
* @param string $hash Part of a hash string.
|
||||
* @return WPCF7_ContactForm Contact form object.
|
||||
*/
|
||||
function wpcf7_get_contact_form_by_hash( $hash ) {
|
||||
if ( ! preg_match( '/^[0-9a-f]{7,}$/', $hash ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$contact_forms = WPCF7_ContactForm::find( array(
|
||||
'meta_query' => array(
|
||||
array(
|
||||
'key' => '_hash',
|
||||
'compare' => 'REGEXP',
|
||||
'value' => '^' . $hash,
|
||||
),
|
||||
),
|
||||
'posts_per_page' => 1,
|
||||
) );
|
||||
|
||||
if ( $contact_forms ) {
|
||||
return wpcf7_contact_form( $contact_forms[0] );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Searches for a contact form by title.
|
||||
*
|
||||
* @param string $title Title of contact form.
|
||||
* @return WPCF7_ContactForm|null Contact form object if found, null otherwise.
|
||||
*/
|
||||
function wpcf7_get_contact_form_by_title( $title ) {
|
||||
if ( ! is_string( $title ) or '' === $title ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$contact_forms = WPCF7_ContactForm::find( array(
|
||||
'title' => $title,
|
||||
'posts_per_page' => 1,
|
||||
) );
|
||||
|
||||
if ( $contact_forms ) {
|
||||
return wpcf7_contact_form( $contact_forms[0] );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Wrapper function of WPCF7_ContactForm::get_current().
|
||||
*
|
||||
* @return WPCF7_ContactForm Contact form object.
|
||||
*/
|
||||
function wpcf7_get_current_contact_form() {
|
||||
if ( $current = WPCF7_ContactForm::get_current() ) {
|
||||
return $current;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if it is in the state that a non-Ajax submission is accepted.
|
||||
*/
|
||||
function wpcf7_is_posted() {
|
||||
if ( ! $contact_form = wpcf7_get_current_contact_form() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $contact_form->is_posted();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the user input value through a non-Ajax submission.
|
||||
*
|
||||
* @param string $name Name of form control.
|
||||
* @param string $default_value Optional default value.
|
||||
* @return string The user input value through the form-control.
|
||||
*/
|
||||
function wpcf7_get_hangover( $name, $default_value = null ) {
|
||||
if ( ! wpcf7_is_posted() ) {
|
||||
return $default_value;
|
||||
}
|
||||
|
||||
$submission = WPCF7_Submission::get_instance();
|
||||
|
||||
if ( ! $submission or $submission->is( 'mail_sent' ) ) {
|
||||
return $default_value;
|
||||
}
|
||||
|
||||
return wpcf7_superglobal_post( $name, $default_value );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves an HTML snippet of validation error on the given form control.
|
||||
*
|
||||
* @param string $name Name of form control.
|
||||
* @return string Validation error message in a form of HTML snippet.
|
||||
*/
|
||||
function wpcf7_get_validation_error( $name ) {
|
||||
if ( ! $contact_form = wpcf7_get_current_contact_form() ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $contact_form->validation_error( $name );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a reference key to a validation error message.
|
||||
*
|
||||
* @param string $name Name of form control.
|
||||
* @param string $unit_tag Optional. Unit tag of the contact form.
|
||||
* @return string Reference key code.
|
||||
*/
|
||||
function wpcf7_get_validation_error_reference( $name, $unit_tag = '' ) {
|
||||
if ( '' === $unit_tag ) {
|
||||
$contact_form = wpcf7_get_current_contact_form();
|
||||
|
||||
if ( $contact_form and $contact_form->validation_error( $name ) ) {
|
||||
$unit_tag = $contact_form->unit_tag();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return preg_replace( '/[^0-9a-z_-]+/i', '',
|
||||
sprintf(
|
||||
'%1$s-ve-%2$s',
|
||||
$unit_tag,
|
||||
$name
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves a message for the given status.
|
||||
*/
|
||||
function wpcf7_get_message( $status ) {
|
||||
if ( ! $contact_form = wpcf7_get_current_contact_form() ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $contact_form->message( $status );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a class names list for a form-tag of the specified type.
|
||||
*
|
||||
* @param string $type Form-tag type.
|
||||
* @param string $default_classes Optional default classes.
|
||||
* @return string Whitespace-separated list of class names.
|
||||
*/
|
||||
function wpcf7_form_controls_class( $type, $default_classes = '' ) {
|
||||
$type = trim( $type );
|
||||
|
||||
if ( is_string( $default_classes ) ) {
|
||||
$default_classes = explode( ' ', $default_classes );
|
||||
}
|
||||
|
||||
$classes = array(
|
||||
'wpcf7-form-control',
|
||||
sprintf( 'wpcf7-%s', rtrim( $type, '*' ) ),
|
||||
);
|
||||
|
||||
if ( str_ends_with( $type, '*' ) ) {
|
||||
$classes[] = 'wpcf7-validates-as-required';
|
||||
}
|
||||
|
||||
$classes = array_merge( $classes, $default_classes );
|
||||
$classes = array_filter( array_unique( $classes ) );
|
||||
|
||||
return implode( ' ', $classes );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Callback function for the contact-form-7 shortcode.
|
||||
*/
|
||||
function wpcf7_contact_form_tag_func( $atts, $content = null, $code = '' ) {
|
||||
if ( is_feed() ) {
|
||||
return '[contact-form-7]';
|
||||
}
|
||||
|
||||
if ( 'contact-form-7' === $code ) {
|
||||
$atts = shortcode_atts(
|
||||
array(
|
||||
'id' => '',
|
||||
'title' => '',
|
||||
'html_id' => '',
|
||||
'html_name' => '',
|
||||
'html_title' => '',
|
||||
'html_class' => '',
|
||||
'output' => 'form',
|
||||
),
|
||||
$atts, 'wpcf7'
|
||||
);
|
||||
|
||||
$id = trim( $atts['id'] );
|
||||
$title = trim( $atts['title'] );
|
||||
|
||||
$contact_form = wpcf7_get_contact_form_by_hash( $id );
|
||||
|
||||
if ( ! $contact_form ) {
|
||||
$contact_form = wpcf7_contact_form( $id );
|
||||
}
|
||||
|
||||
if ( ! $contact_form ) {
|
||||
$contact_form = wpcf7_get_contact_form_by_title( $title );
|
||||
}
|
||||
|
||||
} else {
|
||||
if ( is_string( $atts ) ) {
|
||||
$atts = explode( ' ', $atts, 2 );
|
||||
}
|
||||
|
||||
$id = (int) array_shift( $atts );
|
||||
$contact_form = wpcf7_get_contact_form_by_old_id( $id );
|
||||
}
|
||||
|
||||
if ( ! $contact_form ) {
|
||||
return sprintf(
|
||||
'<p class="wpcf7-contact-form-not-found"><strong>%1$s</strong> %2$s</p>',
|
||||
esc_html( __( 'Error:', 'contact-form-7' ) ),
|
||||
esc_html( __( "Contact form not found.", 'contact-form-7' ) )
|
||||
);
|
||||
}
|
||||
|
||||
$callback = static function ( $contact_form, $atts ) {
|
||||
return $contact_form->form_html( $atts );
|
||||
};
|
||||
|
||||
$output = wpcf7_switch_locale(
|
||||
$contact_form->locale(),
|
||||
$callback,
|
||||
$contact_form, $atts
|
||||
);
|
||||
|
||||
do_action( 'wpcf7_shortcode_callback', $contact_form, $atts );
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Saves the contact form data.
|
||||
*/
|
||||
function wpcf7_save_contact_form( $data = '', $context = 'save' ) {
|
||||
$data = wp_parse_args( $data, array(
|
||||
'id' => -1,
|
||||
'title' => null,
|
||||
'locale' => null,
|
||||
'form' => null,
|
||||
'mail' => null,
|
||||
'mail_2' => null,
|
||||
'messages' => null,
|
||||
'additional_settings' => null,
|
||||
) );
|
||||
|
||||
$data['id'] = (int) $data['id'];
|
||||
|
||||
if ( -1 === $data['id'] ) {
|
||||
$contact_form = WPCF7_ContactForm::get_template();
|
||||
} else {
|
||||
$contact_form = wpcf7_contact_form( $data['id'] );
|
||||
}
|
||||
|
||||
if ( empty( $contact_form ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( null !== $data['title'] ) {
|
||||
$contact_form->set_title( $data['title'] );
|
||||
}
|
||||
|
||||
if ( null !== $data['locale'] ) {
|
||||
$contact_form->set_locale( $data['locale'] );
|
||||
}
|
||||
|
||||
$properties = array();
|
||||
|
||||
if ( null !== $data['form'] ) {
|
||||
$properties['form'] = wpcf7_sanitize_form( $data['form'] );
|
||||
}
|
||||
|
||||
if ( null !== $data['mail'] ) {
|
||||
$properties['mail'] = wpcf7_sanitize_mail( $data['mail'] );
|
||||
$properties['mail']['active'] = true;
|
||||
}
|
||||
|
||||
if ( null !== $data['mail_2'] ) {
|
||||
$properties['mail_2'] = wpcf7_sanitize_mail( $data['mail_2'] );
|
||||
}
|
||||
|
||||
if ( null !== $data['messages'] ) {
|
||||
$properties['messages'] = wpcf7_sanitize_messages( $data['messages'] );
|
||||
}
|
||||
|
||||
if ( null !== $data['additional_settings'] ) {
|
||||
$properties['additional_settings'] = wpcf7_sanitize_additional_settings(
|
||||
$data['additional_settings']
|
||||
);
|
||||
}
|
||||
|
||||
$contact_form->set_properties( $properties );
|
||||
|
||||
do_action( 'wpcf7_save_contact_form', $contact_form, $data, $context );
|
||||
|
||||
if ( 'save' === $context ) {
|
||||
$contact_form->save();
|
||||
}
|
||||
|
||||
return $contact_form;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sanitizes the form property data.
|
||||
*/
|
||||
function wpcf7_sanitize_form( $input, $default_template = '' ) {
|
||||
if ( null === $input ) {
|
||||
return $default_template;
|
||||
}
|
||||
|
||||
$output = trim( $input );
|
||||
|
||||
if ( ! current_user_can( 'unfiltered_html' ) ) {
|
||||
$output = wpcf7_kses( $output, 'form' );
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sanitizes the mail property data.
|
||||
*/
|
||||
function wpcf7_sanitize_mail( $input, $defaults = array() ) {
|
||||
$input = wp_parse_args( $input, array(
|
||||
'active' => false,
|
||||
'subject' => '',
|
||||
'sender' => '',
|
||||
'recipient' => '',
|
||||
'body' => '',
|
||||
'additional_headers' => '',
|
||||
'attachments' => '',
|
||||
'use_html' => false,
|
||||
'exclude_blank' => false,
|
||||
) );
|
||||
|
||||
$input = wp_parse_args( $input, $defaults );
|
||||
|
||||
$output = array();
|
||||
$output['active'] = (bool) $input['active'];
|
||||
$output['subject'] = trim( $input['subject'] );
|
||||
$output['sender'] = trim( $input['sender'] );
|
||||
$output['recipient'] = trim( $input['recipient'] );
|
||||
$output['body'] = trim( $input['body'] );
|
||||
|
||||
if ( ! current_user_can( 'unfiltered_html' ) ) {
|
||||
$output['body'] = wpcf7_kses( $output['body'], 'mail' );
|
||||
}
|
||||
|
||||
$output['additional_headers'] = '';
|
||||
|
||||
$headers = str_replace( "\r\n", "\n", $input['additional_headers'] );
|
||||
$headers = explode( "\n", $headers );
|
||||
|
||||
foreach ( $headers as $header ) {
|
||||
$header = trim( $header );
|
||||
|
||||
if ( '' !== $header ) {
|
||||
$output['additional_headers'] .= $header . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
$output['additional_headers'] = trim( $output['additional_headers'] );
|
||||
$output['attachments'] = trim( $input['attachments'] );
|
||||
$output['use_html'] = (bool) $input['use_html'];
|
||||
$output['exclude_blank'] = (bool) $input['exclude_blank'];
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sanitizes the messages property data.
|
||||
*/
|
||||
function wpcf7_sanitize_messages( $input, $defaults = array() ) {
|
||||
$output = array();
|
||||
|
||||
foreach ( wpcf7_messages() as $key => $val ) {
|
||||
if ( isset( $input[$key] ) ) {
|
||||
$output[$key] = trim( $input[$key] );
|
||||
} elseif ( isset( $defaults[$key] ) ) {
|
||||
$output[$key] = $defaults[$key];
|
||||
}
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sanitizes the additional settings property data.
|
||||
*/
|
||||
function wpcf7_sanitize_additional_settings( $input, $default_template = '' ) {
|
||||
if ( null === $input ) {
|
||||
return $default_template;
|
||||
}
|
||||
|
||||
$output = trim( $input );
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates a random hash string for a contact form.
|
||||
*
|
||||
* @param int $post_id Post ID.
|
||||
* @return string SHA-1 hash.
|
||||
*/
|
||||
function wpcf7_generate_contact_form_hash( $post_id ) {
|
||||
return hash( 'sha256', implode( '|', array(
|
||||
get_current_user_id(),
|
||||
$post_id,
|
||||
time(),
|
||||
home_url(),
|
||||
) ) );
|
||||
}
|
||||
@@ -0,0 +1,204 @@
|
||||
<?php
|
||||
|
||||
class WPCF7_ContactFormTemplate {
|
||||
|
||||
public static function get_default( $prop = 'form' ) {
|
||||
if ( 'form' === $prop ) {
|
||||
$template = self::form();
|
||||
} elseif ( 'mail' === $prop ) {
|
||||
$template = self::mail();
|
||||
} elseif ( 'mail_2' === $prop ) {
|
||||
$template = self::mail_2();
|
||||
} elseif ( 'messages' === $prop ) {
|
||||
$template = self::messages();
|
||||
} else {
|
||||
$template = null;
|
||||
}
|
||||
|
||||
return apply_filters( 'wpcf7_default_template', $template, $prop );
|
||||
}
|
||||
|
||||
public static function form() {
|
||||
$template = sprintf(
|
||||
'
|
||||
<label> %2$s
|
||||
[text* your-name autocomplete:name] </label>
|
||||
|
||||
<label> %3$s
|
||||
[email* your-email autocomplete:email] </label>
|
||||
|
||||
<label> %4$s
|
||||
[text* your-subject] </label>
|
||||
|
||||
<label> %5$s %1$s
|
||||
[textarea your-message] </label>
|
||||
|
||||
[submit "%6$s"]',
|
||||
__( '(optional)', 'contact-form-7' ),
|
||||
__( 'Your name', 'contact-form-7' ),
|
||||
__( 'Your email', 'contact-form-7' ),
|
||||
__( 'Subject', 'contact-form-7' ),
|
||||
__( 'Your message', 'contact-form-7' ),
|
||||
__( 'Submit', 'contact-form-7' )
|
||||
);
|
||||
|
||||
return trim( $template );
|
||||
}
|
||||
|
||||
public static function mail() {
|
||||
$template = array(
|
||||
'subject' => sprintf(
|
||||
/* translators: 1: blog name, 2: [your-subject] */
|
||||
_x( '%1$s "%2$s"', 'mail subject', 'contact-form-7' ),
|
||||
'[_site_title]',
|
||||
'[your-subject]'
|
||||
),
|
||||
'sender' => sprintf(
|
||||
'%s <%s>',
|
||||
'[_site_title]',
|
||||
self::from_email()
|
||||
),
|
||||
'body' =>
|
||||
sprintf(
|
||||
/* translators: %s: [your-name] [your-email] */
|
||||
__( 'From: %s', 'contact-form-7' ),
|
||||
'[your-name] [your-email]'
|
||||
) . "\n"
|
||||
. sprintf(
|
||||
/* translators: %s: [your-subject] */
|
||||
__( 'Subject: %s', 'contact-form-7' ),
|
||||
'[your-subject]'
|
||||
) . "\n\n"
|
||||
. __( 'Message Body:', 'contact-form-7' )
|
||||
. "\n" . '[your-message]' . "\n\n"
|
||||
. '-- ' . "\n"
|
||||
. sprintf(
|
||||
/* translators: 1: blog name, 2: blog URL */
|
||||
__( 'This is a notification that a contact form was submitted on your website (%1$s %2$s).', 'contact-form-7' ),
|
||||
'[_site_title]',
|
||||
'[_site_url]'
|
||||
),
|
||||
'recipient' => '[_site_admin_email]',
|
||||
'additional_headers' => 'Reply-To: [your-email]',
|
||||
'attachments' => '',
|
||||
'use_html' => 0,
|
||||
'exclude_blank' => 0,
|
||||
);
|
||||
|
||||
return $template;
|
||||
}
|
||||
|
||||
public static function mail_2() {
|
||||
$template = array(
|
||||
'active' => false,
|
||||
'subject' => sprintf(
|
||||
/* translators: 1: blog name, 2: [your-subject] */
|
||||
_x( '%1$s "%2$s"', 'mail subject', 'contact-form-7' ),
|
||||
'[_site_title]',
|
||||
'[your-subject]'
|
||||
),
|
||||
'sender' => sprintf(
|
||||
'%s <%s>',
|
||||
'[_site_title]',
|
||||
self::from_email()
|
||||
),
|
||||
'body' =>
|
||||
__( 'Message Body:', 'contact-form-7' )
|
||||
. "\n" . '[your-message]' . "\n\n"
|
||||
. '-- ' . "\n"
|
||||
. sprintf(
|
||||
/* translators: 1: blog name, 2: blog URL */
|
||||
__( 'This email is a receipt for your contact form submission on our website (%1$s %2$s) in which your email address was used. If that was not you, please ignore this message.', 'contact-form-7' ),
|
||||
'[_site_title]',
|
||||
'[_site_url]'
|
||||
),
|
||||
'recipient' => '[your-email]',
|
||||
'additional_headers' => sprintf(
|
||||
'Reply-To: %s',
|
||||
'[_site_admin_email]'
|
||||
),
|
||||
'attachments' => '',
|
||||
'use_html' => 0,
|
||||
'exclude_blank' => 0,
|
||||
);
|
||||
|
||||
return $template;
|
||||
}
|
||||
|
||||
public static function from_email() {
|
||||
$admin_email = get_option( 'admin_email' );
|
||||
|
||||
if ( wpcf7_is_localhost() ) {
|
||||
return $admin_email;
|
||||
}
|
||||
|
||||
$sitename = wp_parse_url( network_home_url(), PHP_URL_HOST );
|
||||
$sitename = strtolower( $sitename );
|
||||
|
||||
if ( 'www.' === substr( $sitename, 0, 4 ) ) {
|
||||
$sitename = substr( $sitename, 4 );
|
||||
}
|
||||
|
||||
if ( strpbrk( $admin_email, '@' ) === '@' . $sitename ) {
|
||||
return $admin_email;
|
||||
}
|
||||
|
||||
return 'wordpress@' . $sitename;
|
||||
}
|
||||
|
||||
public static function messages() {
|
||||
$messages = array();
|
||||
|
||||
foreach ( wpcf7_messages() as $key => $arr ) {
|
||||
$messages[$key] = $arr['default'];
|
||||
}
|
||||
|
||||
return $messages;
|
||||
}
|
||||
}
|
||||
|
||||
function wpcf7_messages() {
|
||||
$messages = array(
|
||||
'mail_sent_ok' => array(
|
||||
'description' => __( 'Sender’s message was sent successfully', 'contact-form-7' ),
|
||||
'default' => __( 'Thank you for your message. It has been sent.', 'contact-form-7' ),
|
||||
),
|
||||
|
||||
'mail_sent_ng' => array(
|
||||
'description' => __( 'Sender’s message failed to send', 'contact-form-7' ),
|
||||
'default' => __( 'There was an error trying to send your message. Please try again later.', 'contact-form-7' ),
|
||||
),
|
||||
|
||||
'validation_error' => array(
|
||||
'description' => __( 'Validation errors occurred', 'contact-form-7' ),
|
||||
'default' => __( 'One or more fields have an error. Please check and try again.', 'contact-form-7' ),
|
||||
),
|
||||
|
||||
'spam' => array(
|
||||
'description' => __( 'Submission was referred to as spam', 'contact-form-7' ),
|
||||
'default' => __( 'There was an error trying to send your message. Please try again later.', 'contact-form-7' ),
|
||||
),
|
||||
|
||||
'accept_terms' => array(
|
||||
'description' => __( 'There are terms that the sender must accept', 'contact-form-7' ),
|
||||
'default' => __( 'You must accept the terms and conditions before sending your message.', 'contact-form-7' ),
|
||||
),
|
||||
|
||||
'invalid_required' => array(
|
||||
'description' => __( 'There is a field that the sender must fill in', 'contact-form-7' ),
|
||||
'default' => __( 'Please fill out this field.', 'contact-form-7' ),
|
||||
),
|
||||
|
||||
'invalid_too_long' => array(
|
||||
'description' => __( 'There is a field with input that is longer than the maximum allowed length', 'contact-form-7' ),
|
||||
'default' => __( 'This field has a too long input.', 'contact-form-7' ),
|
||||
),
|
||||
|
||||
'invalid_too_short' => array(
|
||||
'description' => __( 'There is a field with input that is shorter than the minimum allowed length', 'contact-form-7' ),
|
||||
'default' => __( 'This field has a too short input.', 'contact-form-7' ),
|
||||
),
|
||||
);
|
||||
|
||||
return apply_filters( 'wpcf7_messages', $messages );
|
||||
}
|
||||
1379
wp-content/plugins/contact-form-7/includes/contact-form.php
Normal file
184
wp-content/plugins/contact-form-7/includes/controller.php
Normal file
@@ -0,0 +1,184 @@
|
||||
<?php
|
||||
/**
|
||||
* Controller for front-end requests, scripts, and styles
|
||||
*/
|
||||
|
||||
|
||||
add_action(
|
||||
'parse_request',
|
||||
'wpcf7_control_init',
|
||||
20, 0
|
||||
);
|
||||
|
||||
/**
|
||||
* Handles a submission in non-Ajax mode.
|
||||
*/
|
||||
function wpcf7_control_init() {
|
||||
if ( WPCF7_Submission::is_restful() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
$id = (int) wpcf7_superglobal_post( '_wpcf7' ) and
|
||||
$contact_form = wpcf7_contact_form( $id )
|
||||
) {
|
||||
$contact_form->submit();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Registers main scripts and styles.
|
||||
*/
|
||||
add_action(
|
||||
'wp_enqueue_scripts',
|
||||
static function () {
|
||||
$assets = include wpcf7_plugin_path( 'includes/js/index.asset.php' );
|
||||
|
||||
$assets = wp_parse_args( $assets, array(
|
||||
'dependencies' => array(),
|
||||
'version' => WPCF7_VERSION,
|
||||
) );
|
||||
|
||||
wp_register_script(
|
||||
'contact-form-7',
|
||||
wpcf7_plugin_url( 'includes/js/index.js' ),
|
||||
array_merge(
|
||||
$assets['dependencies'],
|
||||
array( 'swv' )
|
||||
),
|
||||
$assets['version'],
|
||||
array( 'in_footer' => true )
|
||||
);
|
||||
|
||||
wp_set_script_translations( 'contact-form-7', 'contact-form-7' );
|
||||
|
||||
wp_register_script(
|
||||
'contact-form-7-html5-fallback',
|
||||
wpcf7_plugin_url( 'includes/js/html5-fallback.js' ),
|
||||
array( 'jquery-ui-datepicker' ),
|
||||
WPCF7_VERSION,
|
||||
array( 'in_footer' => true )
|
||||
);
|
||||
|
||||
if ( wpcf7_load_js() ) {
|
||||
wpcf7_enqueue_scripts();
|
||||
}
|
||||
|
||||
wp_register_style(
|
||||
'contact-form-7',
|
||||
wpcf7_plugin_url( 'includes/css/styles.css' ),
|
||||
array(),
|
||||
WPCF7_VERSION,
|
||||
'all'
|
||||
);
|
||||
|
||||
wp_register_style(
|
||||
'contact-form-7-rtl',
|
||||
wpcf7_plugin_url( 'includes/css/styles-rtl.css' ),
|
||||
array( 'contact-form-7' ),
|
||||
WPCF7_VERSION,
|
||||
'all'
|
||||
);
|
||||
|
||||
wp_register_style(
|
||||
'jquery-ui-smoothness',
|
||||
wpcf7_plugin_url(
|
||||
'includes/js/jquery-ui/themes/smoothness/jquery-ui.min.css'
|
||||
),
|
||||
array(),
|
||||
'1.12.1',
|
||||
'screen'
|
||||
);
|
||||
|
||||
if ( wpcf7_load_css() ) {
|
||||
wpcf7_enqueue_styles();
|
||||
}
|
||||
},
|
||||
10, 0
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Enqueues scripts.
|
||||
*/
|
||||
function wpcf7_enqueue_scripts() {
|
||||
wp_enqueue_script( 'contact-form-7' );
|
||||
|
||||
$wpcf7_obj = array(
|
||||
'api' => array(
|
||||
'root' => sanitize_url( get_rest_url() ),
|
||||
'namespace' => 'contact-form-7/v1',
|
||||
),
|
||||
);
|
||||
|
||||
if ( defined( 'WP_CACHE' ) and WP_CACHE ) {
|
||||
$wpcf7_obj = array_merge( $wpcf7_obj, array(
|
||||
'cached' => 1,
|
||||
) );
|
||||
}
|
||||
|
||||
wp_add_inline_script( 'contact-form-7',
|
||||
sprintf(
|
||||
'var wpcf7 = %s;',
|
||||
wp_json_encode( $wpcf7_obj, JSON_PRETTY_PRINT )
|
||||
),
|
||||
'before'
|
||||
);
|
||||
|
||||
do_action( 'wpcf7_enqueue_scripts' );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the main script is enqueued.
|
||||
*/
|
||||
function wpcf7_script_is() {
|
||||
return wp_script_is( 'contact-form-7' );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Enqueues styles.
|
||||
*/
|
||||
function wpcf7_enqueue_styles() {
|
||||
wp_enqueue_style( 'contact-form-7' );
|
||||
|
||||
if ( wpcf7_is_rtl() ) {
|
||||
wp_enqueue_style( 'contact-form-7-rtl' );
|
||||
}
|
||||
|
||||
do_action( 'wpcf7_enqueue_styles' );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the main stylesheet is enqueued.
|
||||
*/
|
||||
function wpcf7_style_is() {
|
||||
return wp_style_is( 'contact-form-7' );
|
||||
}
|
||||
|
||||
|
||||
add_action(
|
||||
'wp_enqueue_scripts',
|
||||
'wpcf7_html5_fallback',
|
||||
20, 0
|
||||
);
|
||||
|
||||
/**
|
||||
* Enqueues scripts and styles for the HTML5 fallback.
|
||||
*/
|
||||
function wpcf7_html5_fallback() {
|
||||
if ( ! wpcf7_support_html5_fallback() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( wpcf7_script_is() ) {
|
||||
wp_enqueue_script( 'contact-form-7-html5-fallback' );
|
||||
}
|
||||
|
||||
if ( wpcf7_style_is() ) {
|
||||
wp_enqueue_style( 'jquery-ui-smoothness' );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
.wpcf7-not-valid-tip {
|
||||
direction: rtl;
|
||||
}
|
||||
|
||||
.use-floating-validation-tip .wpcf7-not-valid-tip {
|
||||
right: 1em;
|
||||
}
|
||||
|
||||
.wpcf7-list-item {
|
||||
margin: 0 1em 0 0;
|
||||
}
|
||||
176
wp-content/plugins/contact-form-7/includes/css/styles.css
Normal file
@@ -0,0 +1,176 @@
|
||||
.wpcf7 .screen-reader-response {
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
clip: rect(1px, 1px, 1px, 1px);
|
||||
clip-path: inset(50%);
|
||||
height: 1px;
|
||||
width: 1px;
|
||||
margin: -1px;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
word-wrap: normal !important;
|
||||
}
|
||||
|
||||
.wpcf7 .hidden-fields-container {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.wpcf7 form .wpcf7-response-output {
|
||||
margin: 2em 0.5em 1em;
|
||||
padding: 0.2em 1em;
|
||||
border: 2px solid #00a0d2; /* Blue */
|
||||
}
|
||||
|
||||
.wpcf7 form.init .wpcf7-response-output,
|
||||
.wpcf7 form.resetting .wpcf7-response-output,
|
||||
.wpcf7 form.submitting .wpcf7-response-output {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.wpcf7 form.sent .wpcf7-response-output {
|
||||
border-color: #46b450; /* Green */
|
||||
}
|
||||
|
||||
.wpcf7 form.failed .wpcf7-response-output,
|
||||
.wpcf7 form.aborted .wpcf7-response-output {
|
||||
border-color: #dc3232; /* Red */
|
||||
}
|
||||
|
||||
.wpcf7 form.spam .wpcf7-response-output {
|
||||
border-color: #f56e28; /* Orange */
|
||||
}
|
||||
|
||||
.wpcf7 form.invalid .wpcf7-response-output,
|
||||
.wpcf7 form.unaccepted .wpcf7-response-output,
|
||||
.wpcf7 form.payment-required .wpcf7-response-output {
|
||||
border-color: #ffb900; /* Yellow */
|
||||
}
|
||||
|
||||
.wpcf7-form-control-wrap {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.wpcf7-not-valid-tip {
|
||||
color: #dc3232; /* Red */
|
||||
font-size: 1em;
|
||||
font-weight: normal;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.use-floating-validation-tip .wpcf7-not-valid-tip {
|
||||
position: relative;
|
||||
top: -2ex;
|
||||
left: 1em;
|
||||
z-index: 100;
|
||||
border: 1px solid #dc3232;
|
||||
background: #fff;
|
||||
padding: .2em .8em;
|
||||
width: 24em;
|
||||
}
|
||||
|
||||
.wpcf7-list-item {
|
||||
display: inline-block;
|
||||
margin: 0 0 0 1em;
|
||||
}
|
||||
|
||||
.wpcf7-list-item-label::before,
|
||||
.wpcf7-list-item-label::after {
|
||||
content: " ";
|
||||
}
|
||||
|
||||
.wpcf7-spinner {
|
||||
visibility: hidden;
|
||||
display: inline-block;
|
||||
background-color: #23282d; /* Dark Gray 800 */
|
||||
opacity: 0.75;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border: none;
|
||||
border-radius: 100%;
|
||||
padding: 0;
|
||||
margin: 0 24px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
form.submitting .wpcf7-spinner {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.wpcf7-spinner::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
background-color: #fbfbfc; /* Light Gray 100 */
|
||||
top: 4px;
|
||||
left: 4px;
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border: none;
|
||||
border-radius: 100%;
|
||||
transform-origin: 8px 8px;
|
||||
animation-name: spin;
|
||||
animation-duration: 1000ms;
|
||||
animation-timing-function: linear;
|
||||
animation-iteration-count: infinite;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.wpcf7-spinner::before {
|
||||
animation-name: blink;
|
||||
animation-duration: 2000ms;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes blink {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
50% {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.wpcf7 [inert] {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.wpcf7 input[type="file"] {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.wpcf7 input[type="file"]:disabled {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.wpcf7 .wpcf7-submit:disabled {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.wpcf7 input[type="url"],
|
||||
.wpcf7 input[type="email"],
|
||||
.wpcf7 input[type="tel"] {
|
||||
direction: ltr;
|
||||
}
|
||||
|
||||
.wpcf7-reflection > output {
|
||||
display: list-item;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.wpcf7-reflection > output[hidden] {
|
||||
display: none;
|
||||
}
|
||||
440
wp-content/plugins/contact-form-7/includes/file.php
Normal file
@@ -0,0 +1,440 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Validates uploaded files and moves them to the temporary directory.
|
||||
*
|
||||
* @param array $file An item of `$_FILES`.
|
||||
* @param string|array $options Optional. Options to control behavior.
|
||||
* @return array|WP_Error Array of file paths, or WP_Error if validation fails.
|
||||
*/
|
||||
function wpcf7_unship_uploaded_file( $file, $options = '' ) {
|
||||
$filesystem = WPCF7_Filesystem::get_instance();
|
||||
|
||||
$options = wp_parse_args( $options, array(
|
||||
'required' => false,
|
||||
'filetypes' => '',
|
||||
'limit' => MB_IN_BYTES,
|
||||
) );
|
||||
|
||||
foreach ( array( 'name', 'size', 'tmp_name', 'error' ) as $key ) {
|
||||
if ( ! isset( $file[$key] ) ) {
|
||||
$file[$key] = array();
|
||||
}
|
||||
}
|
||||
|
||||
$names = wpcf7_array_flatten( $file['name'] );
|
||||
$sizes = wpcf7_array_flatten( $file['size'] );
|
||||
$tmp_names = wpcf7_array_flatten( $file['tmp_name'] );
|
||||
$errors = wpcf7_array_flatten( $file['error'] );
|
||||
|
||||
foreach ( $errors as $error ) {
|
||||
if ( ! empty( $error ) and UPLOAD_ERR_NO_FILE !== $error ) {
|
||||
return new WP_Error( 'wpcf7_upload_failed_php_error',
|
||||
wpcf7_get_message( 'upload_failed_php_error' )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if ( isset( $options['schema'] ) and isset( $options['name'] ) ) {
|
||||
$context = array(
|
||||
'file' => true,
|
||||
'field' => $options['name'],
|
||||
);
|
||||
|
||||
foreach ( $options['schema']->validate( $context ) as $result ) {
|
||||
if ( is_wp_error( $result ) ) {
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Move uploaded file to tmp dir
|
||||
$uploads_dir = wpcf7_upload_tmp_dir();
|
||||
$uploads_dir = wpcf7_maybe_add_random_dir( $uploads_dir );
|
||||
|
||||
$uploaded_files = array();
|
||||
|
||||
foreach ( $names as $key => $name ) {
|
||||
$tmp_name = $tmp_names[$key];
|
||||
|
||||
if ( empty( $tmp_name ) or ! is_uploaded_file( $tmp_name ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$filename = $name;
|
||||
$filename = wpcf7_canonicalize( $filename, array( 'strto' => 'as-is' ) );
|
||||
$filename = wpcf7_antiscript_file_name( $filename );
|
||||
|
||||
$filename = apply_filters( 'wpcf7_upload_file_name',
|
||||
$filename, $name, $options
|
||||
);
|
||||
|
||||
$filename = wp_unique_filename( $uploads_dir, $filename );
|
||||
$new_file = path_join( $uploads_dir, $filename );
|
||||
|
||||
// phpcs:ignore Generic.PHP.ForbiddenFunctions.Found
|
||||
if ( false === @move_uploaded_file( $tmp_name, $new_file ) ) {
|
||||
return new WP_Error( 'wpcf7_upload_failed',
|
||||
wpcf7_get_message( 'upload_failed' )
|
||||
);
|
||||
}
|
||||
|
||||
// Make sure the uploaded file is only readable for the owner process.
|
||||
$filesystem->chmod( $new_file, 0400 );
|
||||
|
||||
$uploaded_files[] = $new_file;
|
||||
}
|
||||
|
||||
return $uploaded_files;
|
||||
}
|
||||
|
||||
|
||||
add_filter(
|
||||
'wpcf7_messages',
|
||||
'wpcf7_file_messages',
|
||||
10, 1
|
||||
);
|
||||
|
||||
/**
|
||||
* A wpcf7_messages filter callback that adds messages for
|
||||
* file-uploading fields.
|
||||
*/
|
||||
function wpcf7_file_messages( $messages ) {
|
||||
return array_merge( $messages, array(
|
||||
'upload_failed' => array(
|
||||
'description' => __( 'Uploading a file fails for any reason', 'contact-form-7' ),
|
||||
'default' => __( 'There was an unknown error uploading the file.', 'contact-form-7' ),
|
||||
),
|
||||
|
||||
'upload_file_type_invalid' => array(
|
||||
'description' => __( 'Uploaded file is not allowed for file type', 'contact-form-7' ),
|
||||
'default' => __( 'You are not allowed to upload files of this type.', 'contact-form-7' ),
|
||||
),
|
||||
|
||||
'upload_file_too_large' => array(
|
||||
'description' => __( 'Uploaded file is too large', 'contact-form-7' ),
|
||||
'default' => __( 'The uploaded file is too large.', 'contact-form-7' ),
|
||||
),
|
||||
|
||||
'upload_failed_php_error' => array(
|
||||
'description' => __( 'Uploading a file fails for PHP error', 'contact-form-7' ),
|
||||
'default' => __( 'There was an error uploading the file.', 'contact-form-7' ),
|
||||
),
|
||||
) );
|
||||
}
|
||||
|
||||
|
||||
add_filter(
|
||||
'wpcf7_form_enctype',
|
||||
'wpcf7_file_form_enctype_filter',
|
||||
10, 1
|
||||
);
|
||||
|
||||
/**
|
||||
* A wpcf7_form_enctype filter callback that sets the enctype attribute
|
||||
* to multipart/form-data if the form has file-uploading fields.
|
||||
*/
|
||||
function wpcf7_file_form_enctype_filter( $enctype ) {
|
||||
$multipart = (bool) wpcf7_scan_form_tags( array(
|
||||
'feature' => 'file-uploading',
|
||||
) );
|
||||
|
||||
if ( $multipart ) {
|
||||
$enctype = 'multipart/form-data';
|
||||
}
|
||||
|
||||
return $enctype;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Converts a MIME type string to an array of corresponding file extensions.
|
||||
*
|
||||
* @param string $mime MIME type.
|
||||
* Wildcard (*) is available for the subtype part.
|
||||
* @return array Corresponding file extensions.
|
||||
*/
|
||||
function wpcf7_convert_mime_to_ext( $mime ) {
|
||||
static $mime_types = array();
|
||||
|
||||
$mime_types = wp_get_mime_types();
|
||||
|
||||
$results = array();
|
||||
|
||||
if ( preg_match( '%^([a-z]+)/([*]|[a-z0-9.+-]+)$%i', $mime, $matches ) ) {
|
||||
foreach ( $mime_types as $key => $val ) {
|
||||
if (
|
||||
'*' === $matches[2] and str_starts_with( $val, $matches[1] . '/' ) or
|
||||
$val === $matches[0]
|
||||
) {
|
||||
$results = array_merge( $results, explode( '|', $key ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$results = array_unique( $results );
|
||||
$results = array_filter( $results );
|
||||
$results = array_values( $results );
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a formatted list of acceptable filetypes.
|
||||
*
|
||||
* @param string|array $types Optional. Array of filetypes.
|
||||
* @param string $format Optional. Pre-defined format designator.
|
||||
* @return string Formatted list of acceptable filetypes.
|
||||
*/
|
||||
function wpcf7_acceptable_filetypes( $types = 'default', $format = 'regex' ) {
|
||||
if ( 'default' === $types or empty( $types ) ) {
|
||||
$types = array(
|
||||
'audio/*',
|
||||
'video/*',
|
||||
'image/*',
|
||||
);
|
||||
} else {
|
||||
$types = array_map(
|
||||
static function ( $type ) {
|
||||
if ( is_string( $type ) ) {
|
||||
return preg_split( '/[\s|,]+/', strtolower( $type ) );
|
||||
}
|
||||
},
|
||||
(array) $types
|
||||
);
|
||||
|
||||
$types = wpcf7_array_flatten( $types );
|
||||
$types = array_filter( array_unique( $types ) );
|
||||
}
|
||||
|
||||
if ( 'attr' === $format or 'attribute' === $format ) {
|
||||
$types = array_map(
|
||||
static function ( $type ) {
|
||||
if ( false === strpos( $type, '/' ) ) {
|
||||
return sprintf( '.%s', trim( $type, '.' ) );
|
||||
} elseif ( preg_match( '%^([a-z]+)/[*]$%i', $type, $matches ) ) {
|
||||
if (
|
||||
in_array( $matches[1], array( 'audio', 'video', 'image' ), true )
|
||||
) {
|
||||
return $type;
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
} elseif ( wpcf7_convert_mime_to_ext( $type ) ) {
|
||||
return $type;
|
||||
}
|
||||
},
|
||||
$types
|
||||
);
|
||||
|
||||
$types = array_filter( $types );
|
||||
|
||||
return implode( ',', $types );
|
||||
|
||||
} elseif ( 'regex' === $format ) {
|
||||
$types = array_map(
|
||||
static function ( $type ) {
|
||||
if ( false === strpos( $type, '/' ) ) {
|
||||
return preg_quote( trim( $type, '.' ) );
|
||||
} elseif ( $type = wpcf7_convert_mime_to_ext( $type ) ) {
|
||||
return $type;
|
||||
}
|
||||
},
|
||||
$types
|
||||
);
|
||||
|
||||
$types = wpcf7_array_flatten( $types );
|
||||
$types = array_filter( array_unique( $types ) );
|
||||
|
||||
return implode( '|', $types );
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
add_action(
|
||||
'wpcf7_init',
|
||||
'wpcf7_init_uploads',
|
||||
10, 0
|
||||
);
|
||||
|
||||
/**
|
||||
* Initializes the temporary directory for uploaded files.
|
||||
*/
|
||||
function wpcf7_init_uploads() {
|
||||
$dir = wpcf7_upload_tmp_dir();
|
||||
|
||||
if ( ! is_dir( $dir ) or ! wp_is_writable( $dir ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$htaccess_file = path_join( $dir, '.htaccess' );
|
||||
|
||||
if ( file_exists( $htaccess_file ) ) {
|
||||
list( $first_line_comment ) = (array) file(
|
||||
$htaccess_file,
|
||||
FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES
|
||||
);
|
||||
|
||||
if ( '# Apache 2.4+' === $first_line_comment ) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$filesystem = WPCF7_Filesystem::get_instance();
|
||||
|
||||
$htaccess_body = '
|
||||
# Apache 2.4+
|
||||
<IfModule authz_core_module>
|
||||
Require all denied
|
||||
</IfModule>
|
||||
|
||||
# Apache 2.2
|
||||
<IfModule !authz_core_module>
|
||||
Deny from all
|
||||
</IfModule>
|
||||
';
|
||||
|
||||
$filesystem->put_contents( $htaccess_file, ltrim( $htaccess_body ) );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a child directory with a randomly generated name.
|
||||
*
|
||||
* @param string $dir The parent directory path.
|
||||
* @return string The child directory path if created, otherwise the parent.
|
||||
*/
|
||||
function wpcf7_maybe_add_random_dir( $dir ) {
|
||||
do {
|
||||
$dir_new = path_join( $dir, zeroise( wp_rand(), 10 ) );
|
||||
} while ( file_exists( $dir_new ) );
|
||||
|
||||
if ( wp_mkdir_p( $dir_new ) ) {
|
||||
return $dir_new;
|
||||
}
|
||||
|
||||
return $dir;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the directory path for uploaded files.
|
||||
*
|
||||
* @return string Directory path.
|
||||
*/
|
||||
function wpcf7_upload_tmp_dir() {
|
||||
static $output = '';
|
||||
|
||||
if ( $output ) {
|
||||
return $output;
|
||||
}
|
||||
|
||||
if ( defined( 'WPCF7_UPLOADS_TMP_DIR' ) ) {
|
||||
$dir = path_join( WP_CONTENT_DIR, WPCF7_UPLOADS_TMP_DIR );
|
||||
wp_mkdir_p( $dir );
|
||||
|
||||
if ( wpcf7_is_file_path_in_content_dir( $dir ) ) {
|
||||
return $output = $dir;
|
||||
}
|
||||
}
|
||||
|
||||
$dir = path_join( wpcf7_upload_dir( 'dir' ), 'wpcf7_uploads' );
|
||||
wp_mkdir_p( $dir );
|
||||
|
||||
return $output = $dir;
|
||||
}
|
||||
|
||||
|
||||
add_action(
|
||||
'shutdown',
|
||||
'wpcf7_cleanup_upload_files',
|
||||
20, 0
|
||||
);
|
||||
|
||||
/**
|
||||
* Cleans up files in the temporary directory for uploaded files.
|
||||
*
|
||||
* @param int $seconds Files older than this are removed. Default 60.
|
||||
* @param int $max Maximum number of files to be removed in a function call.
|
||||
* Default 100.
|
||||
*/
|
||||
function wpcf7_cleanup_upload_files( $seconds = 60, $max = 100 ) {
|
||||
$dir = trailingslashit( wpcf7_upload_tmp_dir() );
|
||||
|
||||
if (
|
||||
! is_dir( $dir ) or
|
||||
! is_readable( $dir ) or
|
||||
! wp_is_writable( $dir )
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
$seconds = absint( $seconds );
|
||||
$max = absint( $max );
|
||||
$count = 0;
|
||||
|
||||
if ( $handle = opendir( $dir ) ) {
|
||||
while ( false !== ( $file = readdir( $handle ) ) ) {
|
||||
if ( '.' === $file or '..' === $file or '.htaccess' === $file ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$mtime = @filemtime( path_join( $dir, $file ) );
|
||||
|
||||
if ( $mtime and time() < $mtime + $seconds ) { // less than $seconds old
|
||||
continue;
|
||||
}
|
||||
|
||||
wpcf7_rmdir_p( path_join( $dir, $file ) );
|
||||
$count += 1;
|
||||
|
||||
if ( $max <= $count ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
closedir( $handle );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
add_action(
|
||||
'wpcf7_admin_warnings',
|
||||
'wpcf7_file_display_warning_message',
|
||||
10, 3
|
||||
);
|
||||
|
||||
/**
|
||||
* Displays warning messages about file-uploading fields.
|
||||
*/
|
||||
function wpcf7_file_display_warning_message( $page, $action, $object ) {
|
||||
if ( $object instanceof WPCF7_ContactForm ) {
|
||||
$contact_form = $object;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
$has_tags = (bool) $contact_form->scan_form_tags( array(
|
||||
'feature' => 'file-uploading',
|
||||
) );
|
||||
|
||||
if ( ! $has_tags ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$uploads_dir = wpcf7_upload_tmp_dir();
|
||||
|
||||
if ( ! is_dir( $uploads_dir ) or ! wp_is_writable( $uploads_dir ) ) {
|
||||
wp_admin_notice(
|
||||
sprintf(
|
||||
/* translators: %s: the path of the temporary folder */
|
||||
__( 'This contact form has file uploading fields, but the temporary folder for the files (%s) does not exist or is not writable. You can create the folder or change its permission manually.', 'contact-form-7' ),
|
||||
$uploads_dir
|
||||
),
|
||||
array( 'type' => 'warning' )
|
||||
);
|
||||
}
|
||||
}
|
||||
127
wp-content/plugins/contact-form-7/includes/filesystem.php
Normal file
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Class for filesystem operations.
|
||||
*/
|
||||
class WPCF7_Filesystem {
|
||||
|
||||
/**
|
||||
* The singleton instance.
|
||||
*
|
||||
* @var WPCF7_Filesystem
|
||||
*/
|
||||
private static $instance;
|
||||
|
||||
/**
|
||||
* Filesystem object.
|
||||
*
|
||||
* @var WP_Filesystem_Base
|
||||
*/
|
||||
private $filesystem;
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the singleton instance.
|
||||
*/
|
||||
public static function get_instance() {
|
||||
if ( empty( self::$instance ) ) {
|
||||
self::$instance = new self();
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
private function __construct() {
|
||||
$this->connect();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Connects to the filesystem.
|
||||
*
|
||||
* @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
|
||||
*/
|
||||
private function connect() {
|
||||
global $wp_filesystem;
|
||||
|
||||
if ( $this->filesystem ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
require_once ABSPATH . 'wp-admin/includes/file.php';
|
||||
require_once ABSPATH . 'wp-admin/includes/class-wp-filesystem-base.php';
|
||||
require_once ABSPATH . 'wp-admin/includes/class-wp-filesystem-direct.php';
|
||||
|
||||
ob_start();
|
||||
$credentials = request_filesystem_credentials( '' );
|
||||
ob_end_clean();
|
||||
|
||||
if ( false === $credentials or ! WP_Filesystem( $credentials ) ) {
|
||||
wp_trigger_error(
|
||||
__FUNCTION__,
|
||||
__( 'Could not access filesystem.', 'contact-form-7' )
|
||||
);
|
||||
}
|
||||
|
||||
if ( $wp_filesystem instanceof WP_Filesystem_Base ) {
|
||||
$this->filesystem = $wp_filesystem;
|
||||
} else {
|
||||
$this->filesystem = new WP_Filesystem_Direct( 1 );
|
||||
}
|
||||
|
||||
if ( ! defined( 'FS_CHMOD_DIR' ) ) {
|
||||
define( 'FS_CHMOD_DIR', fileperms( ABSPATH ) & 0777 | 0755 );
|
||||
}
|
||||
|
||||
if ( ! defined( 'FS_CHMOD_FILE' ) ) {
|
||||
define( 'FS_CHMOD_FILE', fileperms( ABSPATH . 'index.php' ) & 0777 | 0644 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Changes filesystem permissions.
|
||||
*
|
||||
* @param string $file Path to the file.
|
||||
* @param int|false $mode Optional. The permissions as octal number.
|
||||
* @param bool $recursive Optional. If set to true,
|
||||
* changes file permissions recursively. Default false.
|
||||
* @return bool True on success, false on failure.
|
||||
*/
|
||||
public function chmod( $file, $mode = false, $recursive = false ) {
|
||||
return $this->filesystem->chmod( $file, $mode, $recursive );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deletes a file or directory.
|
||||
*
|
||||
* @param string $file Path to the file or directory.
|
||||
* @param bool $recursive Optional. If set to true, deletes
|
||||
* files and folders recursively. Default false.
|
||||
* @param string|false $type Type of resource.
|
||||
* 'f' for file, 'd' for directory. Default false.
|
||||
* @return bool True on success, false on failure.
|
||||
*/
|
||||
public function delete( $file, $recursive = false, $type = false ) {
|
||||
return $this->filesystem->delete( $file, $recursive, $type );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Writes a string to a file.
|
||||
*
|
||||
* @param string $file Path to the file where to write the data.
|
||||
* @param string $contents The data to write.
|
||||
* @param int $mode The file permissions as octal number.
|
||||
* @return bool True on success, false on failure.
|
||||
*/
|
||||
public function put_contents( $file, $contents, $mode = false ) {
|
||||
return $this->filesystem->put_contents( $file, $contents, $mode );
|
||||
}
|
||||
|
||||
}
|
||||
618
wp-content/plugins/contact-form-7/includes/form-tag.php
Normal file
@@ -0,0 +1,618 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* A form-tag.
|
||||
*
|
||||
* @link https://contactform7.com/tag-syntax/#form_tag
|
||||
*/
|
||||
class WPCF7_FormTag implements ArrayAccess {
|
||||
|
||||
public $type;
|
||||
public $basetype;
|
||||
public $raw_name = '';
|
||||
public $name = '';
|
||||
public $options = array();
|
||||
public $raw_values = array();
|
||||
public $values = array();
|
||||
public $pipes;
|
||||
public $labels = array();
|
||||
public $attr = '';
|
||||
public $content = '';
|
||||
|
||||
public function __construct( $tag = array() ) {
|
||||
if ( is_array( $tag ) or $tag instanceof self ) {
|
||||
foreach ( $tag as $key => $value ) {
|
||||
if ( property_exists( __CLASS__, $key ) ) {
|
||||
$this->{$key} = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the type has a trailing asterisk.
|
||||
*/
|
||||
public function is_required() {
|
||||
return str_ends_with( $this->type, '*' );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the form-tag has a specified option.
|
||||
*/
|
||||
public function has_option( $option_name ) {
|
||||
$pattern = sprintf( '/^%s(:.+)?$/i', preg_quote( $option_name, '/' ) );
|
||||
return (bool) preg_grep( $pattern, $this->options );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves option values with the specified option name.
|
||||
*
|
||||
* @param string $option_name Option name.
|
||||
* @param string $pattern Optional. A regular expression pattern or one of
|
||||
* the keys of preset patterns. If specified, only options
|
||||
* whose value part matches this pattern will be returned.
|
||||
* @param bool $single Optional. If true, only the first matching option
|
||||
* will be returned. Default false.
|
||||
* @return string|array|bool The option value or an array of option values.
|
||||
* False if there is no option matches the pattern.
|
||||
*/
|
||||
public function get_option( $option_name, $pattern = '', $single = false ) {
|
||||
$preset_patterns = array(
|
||||
'date' => '[0-9]{4}-[0-9]{2}-[0-9]{2}',
|
||||
'int' => '[0-9]+',
|
||||
'signed_int' => '[-]?[0-9]+',
|
||||
'num' => '(?:[0-9]+|(?:[0-9]+)?[.][0-9]+)',
|
||||
'signed_num' => '[-]?(?:[0-9]+|(?:[0-9]+)?[.][0-9]+)',
|
||||
'class' => '[-0-9a-zA-Z_]+',
|
||||
'id' => '[-0-9a-zA-Z_]+',
|
||||
);
|
||||
|
||||
if ( isset( $preset_patterns[$pattern] ) ) {
|
||||
$pattern = $preset_patterns[$pattern];
|
||||
}
|
||||
|
||||
if ( '' === $pattern ) {
|
||||
$pattern = '.+';
|
||||
}
|
||||
|
||||
$pattern = sprintf(
|
||||
'/^%s:%s$/i',
|
||||
preg_quote( $option_name, '/' ),
|
||||
$pattern
|
||||
);
|
||||
|
||||
if ( $single ) {
|
||||
$matches = $this->get_first_match_option( $pattern );
|
||||
|
||||
if ( ! $matches ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return substr( $matches[0], strlen( $option_name ) + 1 );
|
||||
} else {
|
||||
$matches_a = $this->get_all_match_options( $pattern );
|
||||
|
||||
if ( ! $matches_a ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$results = array();
|
||||
|
||||
foreach ( $matches_a as $matches ) {
|
||||
$results[] = substr( $matches[0], strlen( $option_name ) + 1 );
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the id option value from the form-tag.
|
||||
*/
|
||||
public function get_id_option() {
|
||||
static $used = array();
|
||||
|
||||
$option = $this->get_option( 'id', 'id', true );
|
||||
|
||||
if (
|
||||
! $option or
|
||||
str_starts_with( $option, 'wpcf7' ) or
|
||||
in_array( $option, $used, true )
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$used[] = $option;
|
||||
|
||||
return $option;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the class option value from the form-tag.
|
||||
*
|
||||
* @param string|array $default_classes Optional. Preset classes as an array
|
||||
* or a whitespace-separated list. Default empty string.
|
||||
* @return string|bool A whitespace-separated list of classes.
|
||||
* False if there is no class to return.
|
||||
*/
|
||||
public function get_class_option( $default_classes = '' ) {
|
||||
if ( is_string( $default_classes ) ) {
|
||||
$default_classes = explode( ' ', $default_classes );
|
||||
}
|
||||
|
||||
$options = array_merge(
|
||||
(array) $default_classes,
|
||||
(array) $this->get_option( 'class' )
|
||||
);
|
||||
|
||||
$options = array_map( 'sanitize_html_class', $options );
|
||||
$options = array_filter( array_unique( $options ) );
|
||||
|
||||
if ( empty( $options ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return implode( ' ', $options );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the autocomplete option value from the form-tag.
|
||||
*
|
||||
* @return string|bool A whitespace-separated list of tokens.
|
||||
* False if there is no token to return.
|
||||
*/
|
||||
public function get_autocomplete_option() {
|
||||
$options = (array) $this->get_option( 'autocomplete', '[-0-9a-zA-Z|]+' );
|
||||
|
||||
$options = array_reduce( $options, static function ( $carry, $item ) {
|
||||
return array_merge( $carry,
|
||||
array_map( 'strtolower', explode( '|', $item ) )
|
||||
);
|
||||
}, array() );
|
||||
|
||||
$options = array_filter( $options, static function ( $item ) {
|
||||
return preg_match( '/^[a-z]+(?:-[0-9a-z]+)*$/', $item );
|
||||
} );
|
||||
|
||||
$options = array_unique( $options );
|
||||
|
||||
if ( empty( $options ) ) {
|
||||
return false;
|
||||
} elseif ( in_array( 'off', $options, true ) ) {
|
||||
return 'off';
|
||||
} elseif ( in_array( 'on', $options, true ) ) {
|
||||
return 'on';
|
||||
} else {
|
||||
return implode( ' ', $options );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the size option value from the form-tag.
|
||||
*
|
||||
* @param string $default_value Optional default value.
|
||||
* @return string The option value.
|
||||
*/
|
||||
public function get_size_option( $default_value = false ) {
|
||||
$option = $this->get_option( 'size', 'int', true );
|
||||
|
||||
if ( $option ) {
|
||||
return $option;
|
||||
}
|
||||
|
||||
$matches_a = $this->get_all_match_options( '%^([0-9]*)/[0-9]*$%' );
|
||||
|
||||
foreach ( $matches_a as $matches ) {
|
||||
if ( isset( $matches[1] ) and '' !== $matches[1] ) {
|
||||
return $matches[1];
|
||||
}
|
||||
}
|
||||
|
||||
return $default_value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the maxlength option value from the form-tag.
|
||||
*
|
||||
* @param string $default_value Optional default value.
|
||||
* @return string The option value.
|
||||
*/
|
||||
public function get_maxlength_option( $default_value = false ) {
|
||||
$option = $this->get_option( 'maxlength', 'int', true );
|
||||
|
||||
if ( $option ) {
|
||||
return $option;
|
||||
}
|
||||
|
||||
$matches_a = $this->get_all_match_options(
|
||||
'%^(?:[0-9]*x?[0-9]*)?/([0-9]+)$%'
|
||||
);
|
||||
|
||||
foreach ( $matches_a as $matches ) {
|
||||
if ( isset( $matches[1] ) and '' !== $matches[1] ) {
|
||||
return $matches[1];
|
||||
}
|
||||
}
|
||||
|
||||
return $default_value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the minlength option value from the form-tag.
|
||||
*
|
||||
* @param string $default_value Optional default value.
|
||||
* @return string The option value.
|
||||
*/
|
||||
public function get_minlength_option( $default_value = false ) {
|
||||
$option = $this->get_option( 'minlength', 'int', true );
|
||||
|
||||
if ( $option ) {
|
||||
return $option;
|
||||
} else {
|
||||
return $default_value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the cols option value from the form-tag.
|
||||
*
|
||||
* @param string $default_value Optional default value.
|
||||
* @return string The option value.
|
||||
*/
|
||||
public function get_cols_option( $default_value = false ) {
|
||||
$option = $this->get_option( 'cols', 'int', true );
|
||||
|
||||
if ( $option ) {
|
||||
return $option;
|
||||
}
|
||||
|
||||
$matches_a = $this->get_all_match_options(
|
||||
'%^([0-9]*)x([0-9]*)(?:/[0-9]+)?$%'
|
||||
);
|
||||
|
||||
foreach ( $matches_a as $matches ) {
|
||||
if ( isset( $matches[1] ) and '' !== $matches[1] ) {
|
||||
return $matches[1];
|
||||
}
|
||||
}
|
||||
|
||||
return $default_value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the rows option value from the form-tag.
|
||||
*
|
||||
* @param string $default_value Optional default value.
|
||||
* @return string The option value.
|
||||
*/
|
||||
public function get_rows_option( $default_value = false ) {
|
||||
$option = $this->get_option( 'rows', 'int', true );
|
||||
|
||||
if ( $option ) {
|
||||
return $option;
|
||||
}
|
||||
|
||||
$matches_a = $this->get_all_match_options(
|
||||
'%^([0-9]*)x([0-9]*)(?:/[0-9]+)?$%'
|
||||
);
|
||||
|
||||
foreach ( $matches_a as $matches ) {
|
||||
if ( isset( $matches[2] ) and '' !== $matches[2] ) {
|
||||
return $matches[2];
|
||||
}
|
||||
}
|
||||
|
||||
return $default_value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves a date-type option value from the form-tag.
|
||||
*
|
||||
* @param string $option_name A date-type option name, such as 'min' or 'max'.
|
||||
* @return string|bool The option value in YYYY-MM-DD format. False if the
|
||||
* option does not exist or the date value is invalid.
|
||||
*/
|
||||
public function get_date_option( $option_name ) {
|
||||
$option_value = $this->get_option( $option_name, '', true );
|
||||
|
||||
if ( empty( $option_value ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$date = apply_filters( 'wpcf7_form_tag_date_option',
|
||||
null,
|
||||
array( $option_name => $option_value )
|
||||
);
|
||||
|
||||
if ( $date ) {
|
||||
$date_pattern = '/^([0-9]{4})-([0-9]{2})-([0-9]{2})$/';
|
||||
|
||||
if (
|
||||
preg_match( $date_pattern, $date, $matches ) and
|
||||
checkdate( $matches[2], $matches[3], $matches[1] )
|
||||
) {
|
||||
return $date;
|
||||
}
|
||||
} else {
|
||||
$datetime_obj = date_create_immutable(
|
||||
preg_replace( '/[_]+/', ' ', $option_value ),
|
||||
wp_timezone()
|
||||
);
|
||||
|
||||
if ( $datetime_obj ) {
|
||||
return $datetime_obj->format( 'Y-m-d' );
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the default option value from the form-tag.
|
||||
*
|
||||
* @param string|array $default_value Optional default value.
|
||||
* @param string|array $args Optional options for the option value retrieval.
|
||||
* @return string|array The option value. If the multiple option is enabled,
|
||||
* an array of option values.
|
||||
*/
|
||||
public function get_default_option( $default_value = '', $args = '' ) {
|
||||
$args = wp_parse_args( $args, array(
|
||||
'multiple' => false,
|
||||
'shifted' => false,
|
||||
) );
|
||||
|
||||
$options = (array) $this->get_option( 'default' );
|
||||
$values = array();
|
||||
|
||||
if ( empty( $options ) ) {
|
||||
return $args['multiple'] ? $values : $default_value;
|
||||
}
|
||||
|
||||
foreach ( $options as $opt ) {
|
||||
$opt = sanitize_key( $opt );
|
||||
|
||||
if ( 'user_' === substr( $opt, 0, 5 ) and is_user_logged_in() ) {
|
||||
$primary_props = array( 'user_login', 'user_email', 'user_url' );
|
||||
$opt = in_array( $opt, $primary_props, true ) ? $opt : substr( $opt, 5 );
|
||||
|
||||
$user = wp_get_current_user();
|
||||
$user_prop = $user->get( $opt );
|
||||
|
||||
if ( ! empty( $user_prop ) ) {
|
||||
if ( $args['multiple'] ) {
|
||||
$values[] = $user_prop;
|
||||
} else {
|
||||
return $user_prop;
|
||||
}
|
||||
}
|
||||
|
||||
} elseif ( 'post_meta' === $opt and in_the_loop() ) {
|
||||
if ( $args['multiple'] ) {
|
||||
$values = array_merge( $values,
|
||||
get_post_meta( get_the_ID(), $this->name )
|
||||
);
|
||||
} else {
|
||||
$val = (string) get_post_meta( get_the_ID(), $this->name, true );
|
||||
|
||||
if ( strlen( $val ) ) {
|
||||
return $val;
|
||||
}
|
||||
}
|
||||
|
||||
} elseif (
|
||||
'get' === $opt and
|
||||
$vals = wpcf7_superglobal_get( $this->name )
|
||||
) {
|
||||
$vals = array_map( 'wpcf7_sanitize_query_var', (array) $vals );
|
||||
|
||||
if ( $args['multiple'] ) {
|
||||
$values = array_merge( $values, $vals );
|
||||
} else {
|
||||
$val = isset( $vals[0] ) ? (string) $vals[0] : '';
|
||||
|
||||
if ( strlen( $val ) ) {
|
||||
return $val;
|
||||
}
|
||||
}
|
||||
|
||||
} elseif (
|
||||
'post' === $opt and
|
||||
$vals = wpcf7_superglobal_post( $this->name )
|
||||
) {
|
||||
$vals = array_map( 'wpcf7_sanitize_query_var', (array) $vals );
|
||||
|
||||
if ( $args['multiple'] ) {
|
||||
$values = array_merge( $values, $vals );
|
||||
} else {
|
||||
$val = isset( $vals[0] ) ? (string) $vals[0] : '';
|
||||
|
||||
if ( strlen( $val ) ) {
|
||||
return $val;
|
||||
}
|
||||
}
|
||||
|
||||
} elseif ( 'shortcode_attr' === $opt ) {
|
||||
if ( $contact_form = WPCF7_ContactForm::get_current() ) {
|
||||
$val = $contact_form->shortcode_attr( $this->name );
|
||||
|
||||
if ( isset( $val ) and strlen( $val ) ) {
|
||||
if ( $args['multiple'] ) {
|
||||
$values[] = $val;
|
||||
} else {
|
||||
return $val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} elseif ( preg_match( '/^[0-9_]+$/', $opt ) ) {
|
||||
$nums = explode( '_', $opt );
|
||||
|
||||
foreach ( $nums as $num ) {
|
||||
$num = absint( $num );
|
||||
$num = $args['shifted'] ? $num : $num - 1;
|
||||
|
||||
if ( isset( $this->values[$num] ) ) {
|
||||
if ( $args['multiple'] ) {
|
||||
$values[] = $this->values[$num];
|
||||
} else {
|
||||
return $this->values[$num];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( $args['multiple'] ) {
|
||||
$values = array_unique( $values );
|
||||
return $values;
|
||||
} else {
|
||||
return $default_value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the data option value from the form-tag.
|
||||
*
|
||||
* @param string|array $args Optional options for the option value retrieval.
|
||||
* @return mixed The option value.
|
||||
*/
|
||||
public function get_data_option( $args = '' ) {
|
||||
$options = (array) $this->get_option( 'data' );
|
||||
|
||||
return apply_filters( 'wpcf7_form_tag_data_option', null, $options, $args );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the limit option value from the form-tag.
|
||||
*
|
||||
* @param int $default_value Optional default value. Default 1048576.
|
||||
* @return int The option value.
|
||||
*/
|
||||
public function get_limit_option( $default_value = MB_IN_BYTES ) {
|
||||
$pattern = '/^limit:([1-9][0-9]*)([kKmM]?[bB])?$/';
|
||||
|
||||
$matches = $this->get_first_match_option( $pattern );
|
||||
|
||||
if ( $matches ) {
|
||||
$size = (int) $matches[1];
|
||||
|
||||
if ( ! empty( $matches[2] ) ) {
|
||||
$kbmb = strtolower( $matches[2] );
|
||||
|
||||
if ( 'kb' === $kbmb ) {
|
||||
$size *= KB_IN_BYTES;
|
||||
} elseif ( 'mb' === $kbmb ) {
|
||||
$size *= MB_IN_BYTES;
|
||||
}
|
||||
}
|
||||
|
||||
return $size;
|
||||
}
|
||||
|
||||
return (int) $default_value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the value of the first option matches the given
|
||||
* regular expression pattern.
|
||||
*
|
||||
* @param string $pattern Regular expression pattern.
|
||||
* @return array|bool Option value as an array of matched strings.
|
||||
* False if there is no option matches the pattern.
|
||||
*/
|
||||
public function get_first_match_option( $pattern ) {
|
||||
foreach ( (array) $this->options as $option ) {
|
||||
if ( preg_match( $pattern, $option, $matches ) ) {
|
||||
return $matches;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves values of options that match the given
|
||||
* regular expression pattern.
|
||||
*
|
||||
* @param string $pattern Regular expression pattern.
|
||||
* @return array Array of arrays of strings that match the pattern.
|
||||
*/
|
||||
public function get_all_match_options( $pattern ) {
|
||||
$result = array();
|
||||
|
||||
foreach ( (array) $this->options as $option ) {
|
||||
if ( preg_match( $pattern, $option, $matches ) ) {
|
||||
$result[] = $matches;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Assigns a value to the specified offset.
|
||||
*
|
||||
* @link https://www.php.net/manual/en/arrayaccess.offsetset.php
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetSet( $offset, $value ) {
|
||||
if ( property_exists( __CLASS__, $offset ) ) {
|
||||
$this->{$offset} = $value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the value at specified offset.
|
||||
*
|
||||
* @link https://www.php.net/manual/en/arrayaccess.offsetget.php
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetGet( $offset ) {
|
||||
if ( property_exists( __CLASS__, $offset ) ) {
|
||||
return $this->{$offset};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the specified offset exists.
|
||||
*
|
||||
* @link https://www.php.net/manual/en/arrayaccess.offsetexists.php
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetExists( $offset ) {
|
||||
return property_exists( __CLASS__, $offset );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Unsets an offset.
|
||||
*
|
||||
* @link https://www.php.net/manual/en/arrayaccess.offsetunset.php
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetUnset( $offset ) {
|
||||
}
|
||||
|
||||
}
|
||||
615
wp-content/plugins/contact-form-7/includes/form-tags-manager.php
Normal file
@@ -0,0 +1,615 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Wrapper function of WPCF7_FormTagsManager::add().
|
||||
*/
|
||||
function wpcf7_add_form_tag( $tag_types, $callback, $features = '' ) {
|
||||
$manager = WPCF7_FormTagsManager::get_instance();
|
||||
|
||||
return $manager->add( $tag_types, $callback, $features );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Wrapper function of WPCF7_FormTagsManager::remove().
|
||||
*/
|
||||
function wpcf7_remove_form_tag( $tag_type ) {
|
||||
$manager = WPCF7_FormTagsManager::get_instance();
|
||||
|
||||
return $manager->remove( $tag_type );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Wrapper function of WPCF7_FormTagsManager::replace_all().
|
||||
*/
|
||||
function wpcf7_replace_all_form_tags( $content ) {
|
||||
$manager = WPCF7_FormTagsManager::get_instance();
|
||||
|
||||
return $manager->replace_all( $content );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Wrapper function of WPCF7_ContactForm::scan_form_tags().
|
||||
*/
|
||||
function wpcf7_scan_form_tags( $cond = null ) {
|
||||
$contact_form = WPCF7_ContactForm::get_current();
|
||||
|
||||
if ( $contact_form ) {
|
||||
return $contact_form->scan_form_tags( $cond );
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Wrapper function of WPCF7_FormTagsManager::tag_type_supports().
|
||||
*/
|
||||
function wpcf7_form_tag_supports( $tag_type, $feature ) {
|
||||
$manager = WPCF7_FormTagsManager::get_instance();
|
||||
|
||||
return $manager->tag_type_supports( $tag_type, $feature );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The singleton instance of this class manages the collection of form-tags.
|
||||
*/
|
||||
class WPCF7_FormTagsManager {
|
||||
|
||||
private static $instance;
|
||||
|
||||
private $tag_types = array();
|
||||
private $scanned_tags = null; // Tags scanned at the last time of scan()
|
||||
private $placeholders = array();
|
||||
|
||||
private function __construct() {}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the singleton instance.
|
||||
*
|
||||
* @return WPCF7_FormTagsManager The singleton manager.
|
||||
*/
|
||||
public static function get_instance() {
|
||||
if ( empty( self::$instance ) ) {
|
||||
self::$instance = new self();
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns scanned form-tags.
|
||||
*
|
||||
* @return array Array of WPCF7_FormTag objects.
|
||||
*/
|
||||
public function get_scanned_tags() {
|
||||
return $this->scanned_tags;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Registers form-tag types to the manager.
|
||||
*
|
||||
* @param string|array $tag_types The name of the form-tag type or
|
||||
* an array of the names.
|
||||
* @param callable $callback The callback to generates a form control HTML
|
||||
* for a form-tag in this type.
|
||||
* @param string|array $features Optional. Features a form-tag
|
||||
* in this type supports.
|
||||
*/
|
||||
public function add( $tag_types, $callback, $features = '' ) {
|
||||
if ( ! is_callable( $callback ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( true === $features ) { // for back-compat
|
||||
$features = array( 'name-attr' => true );
|
||||
}
|
||||
|
||||
$features = wp_parse_args( $features, array() );
|
||||
|
||||
$tag_types = array_filter( array_unique( (array) $tag_types ) );
|
||||
|
||||
foreach ( $tag_types as $tag_type ) {
|
||||
$tag_type = $this->sanitize_tag_type( $tag_type );
|
||||
|
||||
if ( ! $this->tag_type_exists( $tag_type ) ) {
|
||||
$this->tag_types[$tag_type] = array(
|
||||
'function' => $callback,
|
||||
'features' => $features,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the given tag type exists.
|
||||
*/
|
||||
public function tag_type_exists( $tag_type ) {
|
||||
return isset( $this->tag_types[$tag_type] );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the tag type supports the features.
|
||||
*
|
||||
* @param string $tag_type The name of the form-tag type.
|
||||
* @param array|string $features The feature to check or an array of features.
|
||||
* @return bool True if the form-tag type supports at least one of
|
||||
* the given features, false otherwise.
|
||||
*/
|
||||
public function tag_type_supports( $tag_type, $features ) {
|
||||
$features = array_filter( (array) $features );
|
||||
|
||||
if ( isset( $this->tag_types[$tag_type]['features'] ) ) {
|
||||
return (bool) array_intersect(
|
||||
array_keys( array_filter( $this->tag_types[$tag_type]['features'] ) ),
|
||||
$features
|
||||
);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns form-tag types that support the given features.
|
||||
*
|
||||
* @param array|string $features Optional. The feature to check or
|
||||
* an array of features. Default empty array.
|
||||
* @param bool $invert Optional. If this value is true, returns form-tag
|
||||
* types that do not support the given features. Default false.
|
||||
* @return array An array of form-tag types. If the $features param is empty,
|
||||
* returns all form-tag types that have been registered.
|
||||
*/
|
||||
public function collect_tag_types( $features = array(), $invert = false ) {
|
||||
$tag_types = array_keys( $this->tag_types );
|
||||
|
||||
if ( empty( $features ) ) {
|
||||
return $tag_types;
|
||||
}
|
||||
|
||||
$output = array();
|
||||
|
||||
foreach ( $tag_types as $tag_type ) {
|
||||
if (
|
||||
! $invert and $this->tag_type_supports( $tag_type, $features ) or
|
||||
$invert and ! $this->tag_type_supports( $tag_type, $features )
|
||||
) {
|
||||
$output[] = $tag_type;
|
||||
}
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sanitizes the form-tag type name.
|
||||
*/
|
||||
private function sanitize_tag_type( $tag_type ) {
|
||||
$tag_type = preg_replace( '/[^a-zA-Z0-9_*]+/', '_', $tag_type );
|
||||
$tag_type = rtrim( $tag_type, '_' );
|
||||
$tag_type = strtolower( $tag_type );
|
||||
return $tag_type;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deregisters the form-tag type.
|
||||
*/
|
||||
public function remove( $tag_type ) {
|
||||
unset( $this->tag_types[$tag_type] );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Normalizes the text content that includes form-tags.
|
||||
*/
|
||||
public function normalize( $content ) {
|
||||
if ( empty( $this->tag_types ) ) {
|
||||
return $content;
|
||||
}
|
||||
|
||||
$content = preg_replace_callback(
|
||||
'/' . $this->tag_regex() . '/su',
|
||||
array( $this, 'normalize_callback' ),
|
||||
$content
|
||||
);
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The callback function used within normalize().
|
||||
*/
|
||||
private function normalize_callback( $matches ) {
|
||||
// allow [[foo]] syntax for escaping a tag
|
||||
if ( '[' === $matches[1] and ']' === $matches[6] ) {
|
||||
return $matches[0];
|
||||
}
|
||||
|
||||
$tag = $matches[2];
|
||||
|
||||
$attr = trim( preg_replace( '/[\r\n\t ]+/', ' ', $matches[3] ) );
|
||||
$attr = strtr( $attr, array( '<' => '<', '>' => '>' ) );
|
||||
|
||||
$content = trim( $matches[5] );
|
||||
$content = str_replace( "\n", '<WPPreserveNewline />', $content );
|
||||
|
||||
$result = $matches[1] . '[' . $tag
|
||||
. ( $attr ? ' ' . $attr : '' )
|
||||
. ( $matches[4] ? ' ' . $matches[4] : '' )
|
||||
. ']'
|
||||
. ( $content ? $content . '[/' . $tag . ']' : '' )
|
||||
. $matches[6];
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Replace all form-tags in the given text with placeholders.
|
||||
*/
|
||||
public function replace_with_placeholders( $content ) {
|
||||
if ( empty( $this->tag_types ) ) {
|
||||
return $content;
|
||||
}
|
||||
|
||||
$this->placeholders = array();
|
||||
|
||||
$callback = function ( $matches ) {
|
||||
// Allow [[foo]] syntax for escaping a tag.
|
||||
if ( '[' === $matches[1] and ']' === $matches[6] ) {
|
||||
return $matches[0];
|
||||
}
|
||||
|
||||
$tag = $matches[0];
|
||||
$tag_type = $matches[2];
|
||||
|
||||
$block_or_hidden = $this->tag_type_supports(
|
||||
$tag_type,
|
||||
array( 'display-block', 'display-hidden' )
|
||||
);
|
||||
|
||||
if ( $block_or_hidden ) {
|
||||
$placeholder_tag_name = WPCF7_HTMLFormatter::placeholder_block;
|
||||
} else {
|
||||
$placeholder_tag_name = WPCF7_HTMLFormatter::placeholder_inline;
|
||||
}
|
||||
|
||||
$placeholder = sprintf(
|
||||
'<%1$s id="%2$s" />',
|
||||
$placeholder_tag_name,
|
||||
hash( 'sha256', $tag )
|
||||
);
|
||||
|
||||
list( $placeholder ) =
|
||||
WPCF7_HTMLFormatter::normalize_start_tag( $placeholder );
|
||||
|
||||
$this->placeholders[$placeholder] = $tag;
|
||||
|
||||
return $placeholder;
|
||||
};
|
||||
|
||||
return preg_replace_callback(
|
||||
'/' . $this->tag_regex() . '/su',
|
||||
$callback,
|
||||
$content
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Replace placeholders in the given text with original form-tags.
|
||||
*/
|
||||
public function restore_from_placeholders( $content ) {
|
||||
return str_replace(
|
||||
array_keys( $this->placeholders ),
|
||||
array_values( $this->placeholders ),
|
||||
$content
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Replaces all form-tags in the text content.
|
||||
*
|
||||
* @param string $content The text content including form-tags.
|
||||
* @return string The result of replacements.
|
||||
*/
|
||||
public function replace_all( $content ) {
|
||||
return $this->scan( $content, true );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Scans form-tags in the text content.
|
||||
*
|
||||
* @param string $content The text content including form-tags.
|
||||
* @param bool $replace Optional. Whether scanned form-tags will be
|
||||
* replaced. Default false.
|
||||
* @return array|string An array of scanned form-tags if $replace is false.
|
||||
* Otherwise text that scanned form-tags are replaced.
|
||||
*/
|
||||
public function scan( $content, $replace = false ) {
|
||||
$this->scanned_tags = array();
|
||||
|
||||
if ( empty( $this->tag_types ) ) {
|
||||
if ( $replace ) {
|
||||
return $content;
|
||||
} else {
|
||||
return $this->scanned_tags;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $replace ) {
|
||||
$content = preg_replace_callback(
|
||||
'/' . $this->tag_regex() . '/su',
|
||||
array( $this, 'replace_callback' ),
|
||||
$content
|
||||
);
|
||||
|
||||
return $content;
|
||||
} else {
|
||||
preg_replace_callback(
|
||||
'/' . $this->tag_regex() . '/su',
|
||||
array( $this, 'scan_callback' ),
|
||||
$content
|
||||
);
|
||||
|
||||
return $this->scanned_tags;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Filters form-tags based on a condition array argument.
|
||||
*
|
||||
* @param array|string $input The original form-tags collection.
|
||||
* If it is a string, scans form-tags from it.
|
||||
* @param array $cond The conditions that filtering will be based on.
|
||||
* @return array The filtered form-tags collection.
|
||||
*/
|
||||
public function filter( $input, $cond ) {
|
||||
if ( is_array( $input ) ) {
|
||||
$tags = $input;
|
||||
} elseif ( is_string( $input ) ) {
|
||||
$tags = $this->scan( $input );
|
||||
} else {
|
||||
$tags = $this->scanned_tags;
|
||||
}
|
||||
|
||||
$cond = wp_parse_args( $cond, array(
|
||||
'type' => array(),
|
||||
'basetype' => array(),
|
||||
'name' => array(),
|
||||
'feature' => array(),
|
||||
) );
|
||||
|
||||
$cond = array_map( static function ( $c ) {
|
||||
return array_filter( array_map( 'trim', (array) $c ) );
|
||||
}, $cond );
|
||||
|
||||
$tags = array_filter(
|
||||
(array) $tags,
|
||||
function ( $tag ) use ( $cond ) {
|
||||
$tag = new WPCF7_FormTag( $tag );
|
||||
|
||||
if (
|
||||
$cond['type'] and
|
||||
! in_array( $tag->type, $cond['type'], true )
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
$cond['basetype'] and
|
||||
! in_array( $tag->basetype, $cond['basetype'], true )
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
$cond['name'] and
|
||||
! in_array( $tag->name, $cond['name'], true )
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ( $cond['feature'] as $feature ) {
|
||||
if ( str_starts_with( $feature, '!' ) ) { // Negation
|
||||
$feature = trim( substr( $feature, 1 ) );
|
||||
|
||||
if ( $this->tag_type_supports( $tag->type, $feature ) ) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if ( ! $this->tag_type_supports( $tag->type, $feature ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
return array_values( $tags );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the regular expression for a form-tag.
|
||||
*/
|
||||
private function tag_regex() {
|
||||
$tag_types = implode( '|',
|
||||
array_map( 'preg_quote', array_keys( $this->tag_types ) )
|
||||
);
|
||||
|
||||
$whitespaces = wpcf7_get_unicode_whitespaces();
|
||||
|
||||
return '(\[?)'
|
||||
. '\[(' . $tag_types . ')'
|
||||
. '(?:[' . $whitespaces . ']+(.*?))?'
|
||||
. '(?:[' . $whitespaces . ']+(\/))?\]'
|
||||
. '(?:([^[]*?)\[\/\2\])?'
|
||||
. '(\]?)';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The callback function for the form-tag replacement.
|
||||
*/
|
||||
private function replace_callback( $matches ) {
|
||||
return $this->scan_callback( $matches, true );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The callback function for the form-tag scanning.
|
||||
*/
|
||||
private function scan_callback( $matches, $replace = false ) {
|
||||
// allow [[foo]] syntax for escaping a tag
|
||||
if ( '[' === $matches[1] and ']' === $matches[6] ) {
|
||||
return substr( $matches[0], 1, -1 );
|
||||
}
|
||||
|
||||
$tag_type = $matches[2];
|
||||
$tag_basetype = trim( $tag_type, '*' );
|
||||
$attr = $this->parse_atts( $matches[3] );
|
||||
|
||||
$scanned_tag = array(
|
||||
'type' => $tag_type,
|
||||
'basetype' => $tag_basetype,
|
||||
'raw_name' => '',
|
||||
'name' => '',
|
||||
'options' => array(),
|
||||
'raw_values' => array(),
|
||||
'values' => array(),
|
||||
'pipes' => null,
|
||||
'labels' => array(),
|
||||
'attr' => '',
|
||||
'content' => '',
|
||||
);
|
||||
|
||||
if ( $this->tag_type_supports( $tag_type, 'singular' ) ) {
|
||||
$tags_in_same_basetype = $this->filter(
|
||||
$this->scanned_tags,
|
||||
array( 'basetype' => $tag_basetype )
|
||||
);
|
||||
|
||||
if ( $tags_in_same_basetype ) {
|
||||
// Another tag in the same base type already exists. Ignore this one.
|
||||
return $matches[0];
|
||||
}
|
||||
}
|
||||
|
||||
if ( $this->tag_type_supports( $tag_type, 'name-attr' ) ) {
|
||||
if ( ! is_array( $attr ) ) {
|
||||
return $matches[0]; // Invalid form-tag.
|
||||
}
|
||||
|
||||
$scanned_tag['raw_name'] = (string) array_shift( $attr['options'] );
|
||||
|
||||
if ( ! wpcf7_is_name( $scanned_tag['raw_name'] ) ) {
|
||||
return $matches[0]; // Invalid name is used. Ignore this tag.
|
||||
}
|
||||
|
||||
$scanned_tag['name'] = strtr( $scanned_tag['raw_name'], '.', '_' );
|
||||
}
|
||||
|
||||
if ( is_array( $attr ) ) {
|
||||
$scanned_tag['options'] = (array) $attr['options'];
|
||||
$scanned_tag['raw_values'] = (array) $attr['values'];
|
||||
|
||||
if ( WPCF7_USE_PIPE ) {
|
||||
$pipes = new WPCF7_Pipes( $scanned_tag['raw_values'] );
|
||||
$scanned_tag['values'] = $pipes->collect_befores();
|
||||
$scanned_tag['pipes'] = $pipes;
|
||||
} else {
|
||||
$scanned_tag['values'] = $scanned_tag['raw_values'];
|
||||
}
|
||||
|
||||
$scanned_tag['labels'] = $scanned_tag['values'];
|
||||
|
||||
} else {
|
||||
$scanned_tag['attr'] = $attr;
|
||||
}
|
||||
|
||||
$scanned_tag['values'] = array_map( 'trim', $scanned_tag['values'] );
|
||||
$scanned_tag['labels'] = array_map( 'trim', $scanned_tag['labels'] );
|
||||
|
||||
$content = trim( $matches[5] );
|
||||
$content = preg_replace( "/<br[\r\n\t ]*\/?>$/m", '', $content );
|
||||
$scanned_tag['content'] = $content;
|
||||
|
||||
$scanned_tag = apply_filters( 'wpcf7_form_tag', $scanned_tag, $replace );
|
||||
|
||||
$scanned_tag = new WPCF7_FormTag( $scanned_tag );
|
||||
|
||||
$this->scanned_tags[] = $scanned_tag;
|
||||
|
||||
if ( $replace ) {
|
||||
$callback = $this->tag_types[$tag_type]['function'];
|
||||
return $matches[1] . call_user_func( $callback, $scanned_tag ) . $matches[6];
|
||||
} else {
|
||||
return $matches[0];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parses the attributes of a form-tag to extract the name,
|
||||
* options, and values.
|
||||
*
|
||||
* @param string $text Attributes of a form-tag.
|
||||
* @return array|string An associative array of the options and values
|
||||
* if the input is in the correct syntax,
|
||||
* otherwise the input text itself.
|
||||
*/
|
||||
private function parse_atts( $text ) {
|
||||
$atts = array(
|
||||
'options' => array(),
|
||||
'values' => array(),
|
||||
);
|
||||
|
||||
$whitespaces = wpcf7_get_unicode_whitespaces();
|
||||
|
||||
$text = preg_replace( '/[\x{00a0}\x{200b}]+/u', ' ', $text );
|
||||
$text = wpcf7_strip_whitespaces( $text );
|
||||
|
||||
$pattern = '%^([-+*=0-9a-zA-Z:.!?#$&@_/|\%' . $whitespaces . ']*?)'
|
||||
. '((?:'
|
||||
. '[' . $whitespaces . ']*"[^"]*"'
|
||||
. '|'
|
||||
. '[' . $whitespaces . ']*\'[^\']*\''
|
||||
. ')*)$%u';
|
||||
|
||||
if ( preg_match( $pattern, $text, $matches ) ) {
|
||||
if ( ! empty( $matches[1] ) ) {
|
||||
$atts['options'] = preg_split(
|
||||
sprintf( '/[%s]+/u', $whitespaces ),
|
||||
wpcf7_strip_whitespaces( $matches[1] )
|
||||
);
|
||||
}
|
||||
|
||||
if ( ! empty( $matches[2] ) ) {
|
||||
preg_match_all( '/"[^"]*"|\'[^\']*\'/', $matches[2], $matched_values );
|
||||
$atts['values'] = wpcf7_strip_quote_deep( $matched_values[0] );
|
||||
}
|
||||
} else {
|
||||
$atts = $text;
|
||||
}
|
||||
|
||||
return $atts;
|
||||
}
|
||||
|
||||
}
|
||||
653
wp-content/plugins/contact-form-7/includes/formatting.php
Normal file
@@ -0,0 +1,653 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Replaces double line breaks with paragraph elements.
|
||||
*
|
||||
* @param string $input The text which has to be formatted.
|
||||
* @param bool $br Optional. If set, this will convert all remaining
|
||||
* line breaks after paragraphing. Default true.
|
||||
* @return string Text which has been converted into correct paragraph tags.
|
||||
*/
|
||||
function wpcf7_autop( $input, $br = true ) {
|
||||
$placeholders = array();
|
||||
|
||||
// Replace non-HTML embedded elements with placeholders.
|
||||
$input = preg_replace_callback(
|
||||
'/<(math|svg).*?<\/\1>/is',
|
||||
static function ( $matches ) use ( &$placeholders ) {
|
||||
$placeholder = sprintf(
|
||||
'<%1$s id="%2$s" />',
|
||||
WPCF7_HTMLFormatter::placeholder_inline,
|
||||
hash( 'sha256', $matches[0] )
|
||||
);
|
||||
|
||||
list( $placeholder ) =
|
||||
WPCF7_HTMLFormatter::normalize_start_tag( $placeholder );
|
||||
|
||||
$placeholders[$placeholder] = $matches[0];
|
||||
|
||||
return $placeholder;
|
||||
},
|
||||
$input
|
||||
);
|
||||
|
||||
$formatter = new WPCF7_HTMLFormatter( array(
|
||||
'auto_br' => $br,
|
||||
'allowed_html' => null,
|
||||
) );
|
||||
|
||||
$chunks = $formatter->separate_into_chunks( $input );
|
||||
|
||||
$output = $formatter->format( $chunks );
|
||||
|
||||
// Restore from placeholders.
|
||||
$output = str_replace(
|
||||
array_keys( $placeholders ),
|
||||
array_values( $placeholders ),
|
||||
$output
|
||||
);
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Newline preservation help function for wpcf7_autop().
|
||||
*
|
||||
* @deprecated 5.7 Unnecessary to use any more.
|
||||
*
|
||||
* @param array $matches preg_replace_callback() matches array.
|
||||
* @return string Text including newline placeholders.
|
||||
*/
|
||||
function wpcf7_autop_preserve_newline_callback( $matches ) {
|
||||
return str_replace( "\n", '<WPPreserveNewline />', $matches[0] );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sanitizes the query variables.
|
||||
*
|
||||
* @param string $text Query variable.
|
||||
* @return string Text sanitized.
|
||||
*/
|
||||
function wpcf7_sanitize_query_var( $text ) {
|
||||
$text = wp_unslash( $text );
|
||||
$text = wp_check_invalid_utf8( $text );
|
||||
|
||||
if ( false !== strpos( $text, '<' ) ) {
|
||||
$text = wp_pre_kses_less_than( $text );
|
||||
$text = wp_strip_all_tags( $text );
|
||||
}
|
||||
|
||||
$text = preg_replace( '/%[a-f0-9]{2}/i', '', $text );
|
||||
$text = preg_replace( '/ +/', ' ', $text );
|
||||
$text = trim( $text, ' ' );
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Strips quote characters surrounding the input.
|
||||
*
|
||||
* @param string $text Input text.
|
||||
* @return string Processed output.
|
||||
*/
|
||||
function wpcf7_strip_quote( $text ) {
|
||||
$text = wpcf7_strip_whitespaces( $text );
|
||||
|
||||
if ( preg_match( '/^"(.*)"$/s', $text, $matches ) ) {
|
||||
$text = $matches[1];
|
||||
} elseif ( preg_match( "/^'(.*)'$/s", $text, $matches ) ) {
|
||||
$text = $matches[1];
|
||||
}
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Navigates through an array, object, or scalar, and
|
||||
* strips quote characters surrounding the each value.
|
||||
*
|
||||
* @param mixed $input The array or string to be processed.
|
||||
* @return mixed Processed value.
|
||||
*/
|
||||
function wpcf7_strip_quote_deep( $input ) {
|
||||
if ( is_string( $input ) ) {
|
||||
return wpcf7_strip_quote( $input );
|
||||
}
|
||||
|
||||
if ( is_array( $input ) ) {
|
||||
$result = array();
|
||||
|
||||
foreach ( $input as $key => $text ) {
|
||||
$result[$key] = wpcf7_strip_quote_deep( $text );
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Normalizes newline characters.
|
||||
*
|
||||
* @param string $text Input text.
|
||||
* @param string $to Optional. The newline character that is used in the output.
|
||||
* @return string Normalized text.
|
||||
*/
|
||||
function wpcf7_normalize_newline( $text, $to = "\n" ) {
|
||||
if ( ! is_string( $text ) ) {
|
||||
return $text;
|
||||
}
|
||||
|
||||
$nls = array( "\r\n", "\r", "\n" );
|
||||
|
||||
if ( ! in_array( $to, $nls, true ) ) {
|
||||
return $text;
|
||||
}
|
||||
|
||||
return str_replace( $nls, $to, $text );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Navigates through an array, object, or scalar, and
|
||||
* normalizes newline characters in the each value.
|
||||
*
|
||||
* @param mixed $input The array or string to be processed.
|
||||
* @param string $to Optional. The newline character that is used in the output.
|
||||
* @return mixed Processed value.
|
||||
*/
|
||||
function wpcf7_normalize_newline_deep( $input, $to = "\n" ) {
|
||||
if ( is_array( $input ) ) {
|
||||
$result = array();
|
||||
|
||||
foreach ( $input as $key => $text ) {
|
||||
$result[$key] = wpcf7_normalize_newline_deep( $text, $to );
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
return wpcf7_normalize_newline( $input, $to );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Strips newline characters.
|
||||
*
|
||||
* @param string $text Input text.
|
||||
* @return string Processed one-line text.
|
||||
*/
|
||||
function wpcf7_strip_newline( $text ) {
|
||||
$text = (string) $text;
|
||||
$text = str_replace( array( "\r", "\n" ), '', $text );
|
||||
return wpcf7_strip_whitespaces( $text );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Canonicalizes text.
|
||||
*
|
||||
* @param string $text Input text.
|
||||
* @param string|array|object $options Options.
|
||||
* @return string Canonicalized text.
|
||||
*/
|
||||
function wpcf7_canonicalize( $text, $options = '' ) {
|
||||
// for back-compat
|
||||
if (
|
||||
is_string( $options ) and
|
||||
'' !== $options and
|
||||
! str_contains( $options, '=' )
|
||||
) {
|
||||
$options = array(
|
||||
'strto' => $options,
|
||||
);
|
||||
}
|
||||
|
||||
$options = wp_parse_args( $options, array(
|
||||
'strto' => 'lower',
|
||||
'strip_separators' => false,
|
||||
) );
|
||||
|
||||
static $charset = null;
|
||||
|
||||
if ( ! isset( $charset ) ) {
|
||||
$charset = get_option( 'blog_charset' );
|
||||
|
||||
$is_utf8 = in_array(
|
||||
$charset,
|
||||
array( 'utf8', 'utf-8', 'UTF8', 'UTF-8' ),
|
||||
true
|
||||
);
|
||||
|
||||
if ( $is_utf8 ) {
|
||||
$charset = 'UTF-8';
|
||||
}
|
||||
}
|
||||
|
||||
$text = html_entity_decode( $text, ENT_QUOTES | ENT_HTML5, $charset );
|
||||
|
||||
if ( function_exists( 'mb_convert_kana' ) ) {
|
||||
$text = mb_convert_kana( $text, 'asKV', $charset );
|
||||
}
|
||||
|
||||
if ( $options['strip_separators'] ) {
|
||||
$text = preg_replace( '/[\r\n\t ]+/', '', $text );
|
||||
} else {
|
||||
$text = preg_replace( '/[\r\n\t ]+/', ' ', $text );
|
||||
}
|
||||
|
||||
if ( 'lower' === $options['strto'] ) {
|
||||
if ( function_exists( 'mb_strtolower' ) ) {
|
||||
$text = mb_strtolower( $text, $charset );
|
||||
} else {
|
||||
$text = strtolower( $text );
|
||||
}
|
||||
} elseif ( 'upper' === $options['strto'] ) {
|
||||
if ( function_exists( 'mb_strtoupper' ) ) {
|
||||
$text = mb_strtoupper( $text, $charset );
|
||||
} else {
|
||||
$text = strtoupper( $text );
|
||||
}
|
||||
}
|
||||
|
||||
return wpcf7_strip_whitespaces( $text );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a canonical keyword usable for a name or an ID purposes.
|
||||
*/
|
||||
function wpcf7_canonicalize_name( $text ) {
|
||||
return preg_replace( '/[^0-9a-z]+/i', '-', $text );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sanitizes Contact Form 7's form unit-tag.
|
||||
*
|
||||
* @param string $tag Unit-tag.
|
||||
* @return string Sanitized unit-tag.
|
||||
*/
|
||||
function wpcf7_sanitize_unit_tag( $tag ) {
|
||||
$tag = preg_replace( '/[^A-Za-z0-9_-]/', '', (string) $tag );
|
||||
return $tag;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Converts a file name to one that is not executable as a script.
|
||||
*
|
||||
* @param string $filename File name.
|
||||
* @return string Converted file name.
|
||||
*/
|
||||
function wpcf7_antiscript_file_name( $filename ) {
|
||||
$filename = wp_basename( $filename );
|
||||
|
||||
// Apply part of protection logic from sanitize_file_name().
|
||||
$filename = str_replace(
|
||||
array(
|
||||
'?', '[', ']', '/', '\\', '=', '<', '>', ':', ';', ',', "'", '"',
|
||||
'&', '$', '#', '*', '(', ')', '|', '~', '`', '!', '{', '}',
|
||||
'%', '+', '’', '«', '»', '”', '“', chr( 0 )
|
||||
),
|
||||
'',
|
||||
$filename
|
||||
);
|
||||
|
||||
$filename = preg_replace( '/[\r\n\t -]+/', '-', $filename );
|
||||
$filename = preg_replace( '/[\pC\pZ]+/iu', '', $filename );
|
||||
|
||||
$parts = explode( '.', $filename );
|
||||
|
||||
if ( count( $parts ) < 2 ) {
|
||||
return $filename;
|
||||
}
|
||||
|
||||
$script_pattern = '/^(php|phtml|pl|py|rb|cgi|asp|aspx)\d?$/i';
|
||||
|
||||
$filename = array_shift( $parts );
|
||||
$extension = array_pop( $parts );
|
||||
|
||||
foreach ( $parts as $part ) {
|
||||
if ( preg_match( $script_pattern, $part ) ) {
|
||||
$filename .= '.' . $part . '_';
|
||||
} else {
|
||||
$filename .= '.' . $part;
|
||||
}
|
||||
}
|
||||
|
||||
if ( preg_match( $script_pattern, $extension ) ) {
|
||||
$filename .= '.' . $extension . '_.txt';
|
||||
} else {
|
||||
$filename .= '.' . $extension;
|
||||
}
|
||||
|
||||
return $filename;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Masks a password with asterisks (*).
|
||||
*
|
||||
* @param int $right Length of right-hand unmasked text. Default 0.
|
||||
* @param int $left Length of left-hand unmasked text. Default 0.
|
||||
* @return string Text of masked password.
|
||||
*/
|
||||
function wpcf7_mask_password( $text, $right = 0, $left = 0 ) {
|
||||
$length = strlen( $text );
|
||||
|
||||
$right = absint( $right );
|
||||
$left = absint( $left );
|
||||
|
||||
if ( $length < $right + $left ) {
|
||||
$right = $left = 0;
|
||||
}
|
||||
|
||||
if ( $length <= 48 ) {
|
||||
$masked = str_repeat( '*', $length - ( $right + $left ) );
|
||||
} elseif ( $right + $left < 48 ) {
|
||||
$masked = str_repeat( '*', 48 - ( $right + $left ) );
|
||||
} else {
|
||||
$masked = '****';
|
||||
}
|
||||
|
||||
$left_unmasked = $left ? substr( $text, 0, $left ) : '';
|
||||
$right_unmasked = $right ? substr( $text, -1 * $right ) : '';
|
||||
|
||||
$text = $left_unmasked . $masked . $right_unmasked;
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an array of allowed HTML tags and attributes for a given context.
|
||||
*
|
||||
* @param string $context Context used to decide allowed tags and attributes.
|
||||
* @return array Array of allowed HTML tags and their allowed attributes.
|
||||
*/
|
||||
function wpcf7_kses_allowed_html( $context = 'form' ) {
|
||||
static $allowed_tags = array();
|
||||
|
||||
if ( isset( $allowed_tags[$context] ) ) {
|
||||
return apply_filters(
|
||||
'wpcf7_kses_allowed_html',
|
||||
$allowed_tags[$context],
|
||||
$context
|
||||
);
|
||||
}
|
||||
|
||||
$allowed_tags[$context] = wp_kses_allowed_html( 'post' );
|
||||
|
||||
if ( 'form' === $context ) {
|
||||
$additional_tags_for_form = array(
|
||||
'button' => array(
|
||||
'disabled' => true,
|
||||
'name' => true,
|
||||
'type' => true,
|
||||
'value' => true,
|
||||
),
|
||||
'datalist' => array(),
|
||||
'fieldset' => array(
|
||||
'disabled' => true,
|
||||
'name' => true,
|
||||
),
|
||||
'input' => array(
|
||||
'accept' => true,
|
||||
'alt' => true,
|
||||
'autocomplete' => true,
|
||||
'capture' => true,
|
||||
'checked' => true,
|
||||
'disabled' => true,
|
||||
'list' => true,
|
||||
'max' => true,
|
||||
'maxlength' => true,
|
||||
'min' => true,
|
||||
'minlength' => true,
|
||||
'multiple' => true,
|
||||
'name' => true,
|
||||
'pattern' => true,
|
||||
'placeholder' => true,
|
||||
'readonly' => true,
|
||||
'required' => true,
|
||||
'size' => true,
|
||||
'step' => true,
|
||||
'type' => true,
|
||||
'value' => true,
|
||||
),
|
||||
'label' => array(
|
||||
'for' => true,
|
||||
),
|
||||
'legend' => array(),
|
||||
'meter' => array(
|
||||
'value' => true,
|
||||
'min' => true,
|
||||
'max' => true,
|
||||
'low' => true,
|
||||
'high' => true,
|
||||
'optimum' => true,
|
||||
),
|
||||
'optgroup' => array(
|
||||
'disabled' => true,
|
||||
'label' => true,
|
||||
),
|
||||
'option' => array(
|
||||
'disabled' => true,
|
||||
'label' => true,
|
||||
'selected' => true,
|
||||
'value' => true,
|
||||
),
|
||||
'output' => array(
|
||||
'for' => true,
|
||||
'name' => true,
|
||||
),
|
||||
'progress' => array(
|
||||
'max' => true,
|
||||
'value' => true,
|
||||
),
|
||||
'select' => array(
|
||||
'autocomplete' => true,
|
||||
'disabled' => true,
|
||||
'multiple' => true,
|
||||
'name' => true,
|
||||
'required' => true,
|
||||
'size' => true,
|
||||
),
|
||||
'textarea' => array(
|
||||
'autocomplete' => true,
|
||||
'cols' => true,
|
||||
'disabled' => true,
|
||||
'maxlength' => true,
|
||||
'minlength' => true,
|
||||
'name' => true,
|
||||
'placeholder' => true,
|
||||
'readonly' => true,
|
||||
'required' => true,
|
||||
'rows' => true,
|
||||
'wrap' => true,
|
||||
),
|
||||
);
|
||||
|
||||
$allowed_tags[$context] = array_merge(
|
||||
$allowed_tags[$context],
|
||||
$additional_tags_for_form
|
||||
);
|
||||
|
||||
$allowed_tags[$context] = array_map(
|
||||
static function ( $elm ) {
|
||||
$global_attributes = array(
|
||||
'aria-atomic' => true,
|
||||
'aria-checked' => true,
|
||||
'aria-controls' => true,
|
||||
'aria-current' => true,
|
||||
'aria-describedby' => true,
|
||||
'aria-details' => true,
|
||||
'aria-disabled' => true,
|
||||
'aria-expanded' => true,
|
||||
'aria-hidden' => true,
|
||||
'aria-invalid' => true,
|
||||
'aria-label' => true,
|
||||
'aria-labelledby' => true,
|
||||
'aria-live' => true,
|
||||
'aria-relevant' => true,
|
||||
'aria-required' => true,
|
||||
'aria-selected' => true,
|
||||
'class' => true,
|
||||
'data-*' => true,
|
||||
'dir' => true,
|
||||
'hidden' => true,
|
||||
'id' => true,
|
||||
'inputmode' => true,
|
||||
'lang' => true,
|
||||
'role' => true,
|
||||
'spellcheck' => true,
|
||||
'style' => true,
|
||||
'tabindex' => true,
|
||||
'title' => true,
|
||||
'xml:lang' => true,
|
||||
);
|
||||
|
||||
return array_merge( $global_attributes, (array) $elm );
|
||||
},
|
||||
$allowed_tags[$context]
|
||||
);
|
||||
}
|
||||
|
||||
return apply_filters(
|
||||
'wpcf7_kses_allowed_html',
|
||||
$allowed_tags[$context],
|
||||
$context
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sanitizes content for allowed HTML tags for the specified context.
|
||||
*
|
||||
* @param string $input Content to filter.
|
||||
* @param string $context Context used to decide allowed tags and attributes.
|
||||
* @return string Filtered text with allowed HTML tags and attributes intact.
|
||||
*/
|
||||
function wpcf7_kses( $input, $context = 'form' ) {
|
||||
$output = wp_kses(
|
||||
$input,
|
||||
wpcf7_kses_allowed_html( $context )
|
||||
);
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a formatted string of HTML attributes.
|
||||
*
|
||||
* @param array $atts Associative array of attribute name and value pairs.
|
||||
* @return string Formatted HTML attributes.
|
||||
*/
|
||||
function wpcf7_format_atts( $atts ) {
|
||||
$atts_filtered = array();
|
||||
|
||||
foreach ( $atts as $name => $value ) {
|
||||
$name = strtolower( trim( $name ) );
|
||||
|
||||
if ( ! preg_match( '/^[a-z_:][a-z_:.0-9-]*$/', $name ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
static $boolean_attributes = array(
|
||||
'checked',
|
||||
'disabled',
|
||||
'inert',
|
||||
'multiple',
|
||||
'readonly',
|
||||
'required',
|
||||
'selected',
|
||||
);
|
||||
|
||||
if ( in_array( $name, $boolean_attributes, true ) and '' === $value ) {
|
||||
$value = false;
|
||||
}
|
||||
|
||||
if ( is_numeric( $value ) ) {
|
||||
$value = (string) $value;
|
||||
}
|
||||
|
||||
if ( null === $value or false === $value ) {
|
||||
unset( $atts_filtered[$name] );
|
||||
} elseif ( true === $value ) {
|
||||
$atts_filtered[$name] = $name; // boolean attribute
|
||||
} elseif ( is_string( $value ) ) {
|
||||
$atts_filtered[$name] = trim( $value );
|
||||
}
|
||||
}
|
||||
|
||||
$output = '';
|
||||
|
||||
foreach ( $atts_filtered as $name => $value ) {
|
||||
$output .= sprintf( ' %1$s="%2$s"', $name, esc_attr( $value ) );
|
||||
}
|
||||
|
||||
return trim( $output );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the regular expression pattern that represents
|
||||
* whitespace characters Unicode defines.
|
||||
*
|
||||
* @link https://www.unicode.org/Public/UCD/latest/ucd/PropList.txt
|
||||
*
|
||||
* @return string Regular expression pattern.
|
||||
*/
|
||||
function wpcf7_get_unicode_whitespaces() {
|
||||
return '\x09-\x0D\x20\x85\xA0\x{1680}\x{2000}-\x{200A}\x{2028}\x{2029}\x{202F}\x{205F}\x{3000}';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Strips surrounding whitespaces.
|
||||
*
|
||||
* @link https://contactform7.com/2024/07/13/consistent-handling-policy-of-surrounding-whitespaces/
|
||||
*
|
||||
* @param string|array $input Input text.
|
||||
* @param string $side The side from which whitespaces are stripped.
|
||||
* 'start', 'end', or 'both' (default).
|
||||
* @return string|array Output text.
|
||||
*/
|
||||
function wpcf7_strip_whitespaces( $input, $side = 'both' ) {
|
||||
if ( is_array( $input ) ) {
|
||||
return array_map(
|
||||
static function ( $i ) use ( $side ) {
|
||||
return wpcf7_strip_whitespaces( $i, $side );
|
||||
},
|
||||
$input
|
||||
);
|
||||
}
|
||||
|
||||
// https://tc39.es/ecma262/multipage/ecmascript-language-lexical-grammar.html
|
||||
$whitespaces = wpcf7_get_unicode_whitespaces() . '\x{FEFF}';
|
||||
|
||||
if ( 'end' !== $side ) {
|
||||
// Strip leading whitespaces
|
||||
$input = preg_replace(
|
||||
sprintf( '/^[%s]+/u', $whitespaces ),
|
||||
'',
|
||||
$input
|
||||
);
|
||||
}
|
||||
|
||||
if ( 'start' !== $side ) {
|
||||
// Strip trailing whitespaces
|
||||
$input = preg_replace(
|
||||
sprintf( '/[%s]+$/u', $whitespaces ),
|
||||
'',
|
||||
$input
|
||||
);
|
||||
}
|
||||
|
||||
return $input;
|
||||
}
|
||||
749
wp-content/plugins/contact-form-7/includes/functions.php
Normal file
@@ -0,0 +1,749 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Returns path to a plugin file.
|
||||
*
|
||||
* @param string $path File path relative to the plugin root directory.
|
||||
* @return string Absolute file path.
|
||||
*/
|
||||
function wpcf7_plugin_path( $path = '' ) {
|
||||
return path_join( WPCF7_PLUGIN_DIR, trim( $path, '/' ) );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the URL to a plugin file.
|
||||
*
|
||||
* @param string $path File path relative to the plugin root directory.
|
||||
* @return string URL.
|
||||
*/
|
||||
function wpcf7_plugin_url( $path = '' ) {
|
||||
$url = plugins_url( $path, WPCF7_PLUGIN );
|
||||
|
||||
if ( is_ssl() and 'http:' === substr( $url, 0, 5 ) ) {
|
||||
$url = 'https:' . substr( $url, 5 );
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Include a file under WPCF7_PLUGIN_MODULES_DIR.
|
||||
*
|
||||
* @param string $path File path relative to the module dir.
|
||||
* @return bool True on success, false on failure.
|
||||
*/
|
||||
function wpcf7_include_module_file( $path ) {
|
||||
$dir = WPCF7_PLUGIN_MODULES_DIR;
|
||||
|
||||
if ( empty( $dir ) or ! is_dir( $dir ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$path = path_join( $dir, ltrim( $path, '/' ) );
|
||||
|
||||
if ( file_exists( $path ) ) {
|
||||
include_once $path;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves uploads directory information.
|
||||
*
|
||||
* @param string|bool $type Optional. Type of output. Default false.
|
||||
* @return array|string Information about the upload directory.
|
||||
*/
|
||||
function wpcf7_upload_dir( $type = false ) {
|
||||
$uploads = wp_get_upload_dir();
|
||||
|
||||
$uploads = apply_filters( 'wpcf7_upload_dir', array(
|
||||
'dir' => $uploads['basedir'],
|
||||
'url' => $uploads['baseurl'],
|
||||
) );
|
||||
|
||||
if ( 'dir' === $type ) {
|
||||
return $uploads['dir'];
|
||||
} if ( 'url' === $type ) {
|
||||
return $uploads['url'];
|
||||
}
|
||||
|
||||
return $uploads;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Verifies that a correct security nonce was used with time limit.
|
||||
*
|
||||
* @param string $nonce Nonce value that was used for verification.
|
||||
* @param string $action Optional. Context to what is taking place.
|
||||
* Default 'wp_rest'.
|
||||
* @return int|bool 1 if the nonce is generated between 0-12 hours ago,
|
||||
* 2 if the nonce is generated between 12-24 hours ago.
|
||||
* False if the nonce is invalid.
|
||||
*/
|
||||
function wpcf7_verify_nonce( $nonce, $action = 'wp_rest' ) {
|
||||
return wp_verify_nonce( $nonce, $action );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a cryptographic token tied to a specific action, user, user session,
|
||||
* and window of time.
|
||||
*
|
||||
* @param string $action Optional. Context to what is taking place.
|
||||
* Default 'wp_rest'.
|
||||
* @return string The token.
|
||||
*/
|
||||
function wpcf7_create_nonce( $action = 'wp_rest' ) {
|
||||
return wp_create_nonce( $action );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Converts multi-dimensional array to a flat array.
|
||||
*
|
||||
* @param mixed $input Array or item of array.
|
||||
* @return array Flatten array.
|
||||
*/
|
||||
function wpcf7_array_flatten( $input ) {
|
||||
if ( ! is_array( $input ) ) {
|
||||
return array( $input );
|
||||
}
|
||||
|
||||
$output = array();
|
||||
|
||||
foreach ( $input as $value ) {
|
||||
$output = array_merge( $output, wpcf7_array_flatten( $value ) );
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Excludes unset or blank text values from the given array.
|
||||
*
|
||||
* @param array $input The array.
|
||||
* @return array Array without blank text values.
|
||||
*/
|
||||
function wpcf7_exclude_blank( $input ) {
|
||||
$output = array_filter( $input,
|
||||
static function ( $i ) {
|
||||
return isset( $i ) && '' !== $i;
|
||||
}
|
||||
);
|
||||
|
||||
return array_values( $output );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a comma-separated list from a multi-dimensional array.
|
||||
*
|
||||
* @param mixed $input Array or item of array.
|
||||
* @param string|array $options Optional. Output options.
|
||||
* @return string Comma-separated list.
|
||||
*/
|
||||
function wpcf7_flat_join( $input, $options = '' ) {
|
||||
$options = wp_parse_args( $options, array(
|
||||
'separator' => ', ',
|
||||
) );
|
||||
|
||||
$input = wpcf7_array_flatten( $input );
|
||||
$output = array();
|
||||
|
||||
foreach ( $input as $value ) {
|
||||
if ( is_scalar( $value ) ) {
|
||||
$output[] = trim( (string) $value );
|
||||
}
|
||||
}
|
||||
|
||||
return implode( $options['separator'], $output );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if HTML5 is supported.
|
||||
*/
|
||||
function wpcf7_support_html5() {
|
||||
return (bool) wpcf7_apply_filters_deprecated(
|
||||
'wpcf7_support_html5',
|
||||
array( true ),
|
||||
'5.6',
|
||||
''
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if HTML5 fallback is active.
|
||||
*/
|
||||
function wpcf7_support_html5_fallback() {
|
||||
return (bool) apply_filters( 'wpcf7_support_html5_fallback', false );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the Really Simple CAPTCHA plugin is used for contact forms.
|
||||
*/
|
||||
function wpcf7_use_really_simple_captcha() {
|
||||
return apply_filters( 'wpcf7_use_really_simple_captcha',
|
||||
WPCF7_USE_REALLY_SIMPLE_CAPTCHA
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if config validation is active.
|
||||
*/
|
||||
function wpcf7_validate_configuration() {
|
||||
return apply_filters( 'wpcf7_validate_configuration',
|
||||
WPCF7_VALIDATE_CONFIGURATION
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if wpcf7_autop() is applied.
|
||||
*/
|
||||
function wpcf7_autop_or_not( $options = '' ) {
|
||||
$options = wp_parse_args( $options, array(
|
||||
'for' => 'form',
|
||||
) );
|
||||
|
||||
return (bool) apply_filters( 'wpcf7_autop_or_not', WPCF7_AUTOP, $options );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if JavaScript for this plugin is loaded.
|
||||
*/
|
||||
function wpcf7_load_js() {
|
||||
return apply_filters( 'wpcf7_load_js', WPCF7_LOAD_JS );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if CSS for this plugin is loaded.
|
||||
*/
|
||||
function wpcf7_load_css() {
|
||||
return apply_filters( 'wpcf7_load_css', WPCF7_LOAD_CSS );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Builds an HTML anchor element.
|
||||
*
|
||||
* @param string $url Link URL.
|
||||
* @param string $anchor_text Anchor label text.
|
||||
* @param string|array $atts Optional. HTML attributes.
|
||||
* @return string Formatted anchor element.
|
||||
*/
|
||||
function wpcf7_link( $url, $anchor_text, $atts = '' ) {
|
||||
$atts = wp_parse_args( $atts, array(
|
||||
'id' => null,
|
||||
'class' => null,
|
||||
) );
|
||||
|
||||
$atts = array_merge( $atts, array(
|
||||
'href' => esc_url( $url ),
|
||||
) );
|
||||
|
||||
return sprintf(
|
||||
'<a %1$s>%2$s</a>',
|
||||
wpcf7_format_atts( $atts ),
|
||||
esc_html( $anchor_text )
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the current request URL.
|
||||
*/
|
||||
function wpcf7_get_request_uri() {
|
||||
static $request_uri = '';
|
||||
|
||||
if ( empty( $request_uri ) ) {
|
||||
$request_uri = add_query_arg( array() );
|
||||
$request_uri = '/' . ltrim( $request_uri, '/' );
|
||||
}
|
||||
|
||||
return sanitize_url( $request_uri );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Registers post types used for this plugin.
|
||||
*/
|
||||
function wpcf7_register_post_types() {
|
||||
if ( class_exists( 'WPCF7_ContactForm' ) ) {
|
||||
WPCF7_ContactForm::register_post_type();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the version string of this plugin.
|
||||
*
|
||||
* @param string|array $options Optional. Output options.
|
||||
* @return string Version string.
|
||||
*/
|
||||
function wpcf7_version( $options = '' ) {
|
||||
$options = wp_parse_args( $options, array(
|
||||
'limit' => -1,
|
||||
'only_major' => false,
|
||||
) );
|
||||
|
||||
if ( $options['only_major'] ) {
|
||||
$options['limit'] = 2;
|
||||
}
|
||||
|
||||
$options['limit'] = (int) $options['limit'];
|
||||
|
||||
$ver = WPCF7_VERSION;
|
||||
$ver = strtr( $ver, '_-+', '...' );
|
||||
$ver = preg_replace( '/[^0-9.]+/', '.$0.', $ver );
|
||||
$ver = preg_replace( '/[.]+/', '.', $ver );
|
||||
$ver = trim( $ver, '.' );
|
||||
$ver = explode( '.', $ver );
|
||||
|
||||
if ( -1 < $options['limit'] ) {
|
||||
$ver = array_slice( $ver, 0, $options['limit'] );
|
||||
}
|
||||
|
||||
$ver = implode( '.', $ver );
|
||||
|
||||
return $ver;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns array entries that match the given version.
|
||||
*
|
||||
* @param string $version The version to search for.
|
||||
* @param array $input Search target array.
|
||||
* @return array|bool Array of matched entries. False on failure.
|
||||
*/
|
||||
function wpcf7_version_grep( $version, array $input ) {
|
||||
$pattern = '/^' . preg_quote( (string) $version, '/' ) . '(?:\.|$)/';
|
||||
|
||||
return preg_grep( $pattern, $input );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an enctype attribute value.
|
||||
*
|
||||
* @param string $enctype Enctype value.
|
||||
* @return string Enctype value. Empty if not a valid enctype.
|
||||
*/
|
||||
function wpcf7_enctype_value( $enctype ) {
|
||||
$enctype = trim( $enctype );
|
||||
|
||||
if ( empty( $enctype ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$valid_enctypes = array(
|
||||
'application/x-www-form-urlencoded',
|
||||
'multipart/form-data',
|
||||
'text/plain',
|
||||
);
|
||||
|
||||
if ( in_array( $enctype, $valid_enctypes, true ) ) {
|
||||
return $enctype;
|
||||
}
|
||||
|
||||
$pattern = '%^enctype="(' . implode( '|', $valid_enctypes ) . ')"$%';
|
||||
|
||||
if ( preg_match( $pattern, $enctype, $matches ) ) {
|
||||
return $matches[1]; // for back-compat
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Removes directory recursively.
|
||||
*
|
||||
* @param string $dir Directory path.
|
||||
* @return bool True on success, false on failure.
|
||||
*/
|
||||
function wpcf7_rmdir_p( $dir ) {
|
||||
$filesystem = WPCF7_Filesystem::get_instance();
|
||||
|
||||
return $filesystem->delete( $dir, true );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Builds a URL-encoded query string.
|
||||
*
|
||||
* @link https://developer.wordpress.org/reference/functions/_http_build_query/
|
||||
*
|
||||
* @param array $data URL query parameters.
|
||||
* @param string $key Optional. If specified, used to prefix key name.
|
||||
* @return string Query string.
|
||||
*/
|
||||
function wpcf7_build_query( $data, $key = '' ) {
|
||||
$sep = '&';
|
||||
$ret = array();
|
||||
|
||||
foreach ( (array) $data as $k => $v ) {
|
||||
$k = urlencode( $k );
|
||||
|
||||
if ( ! empty( $key ) ) {
|
||||
$k = $key . '%5B' . $k . '%5D';
|
||||
}
|
||||
|
||||
if ( null === $v ) {
|
||||
continue;
|
||||
} elseif ( false === $v ) {
|
||||
$v = '0';
|
||||
}
|
||||
|
||||
if ( is_array( $v ) or is_object( $v ) ) {
|
||||
array_push( $ret, wpcf7_build_query( $v, $k ) );
|
||||
} else {
|
||||
array_push( $ret, $k . '=' . urlencode( $v ) );
|
||||
}
|
||||
}
|
||||
|
||||
return implode( $sep, $ret );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of code units in a string.
|
||||
*
|
||||
* @link http://www.w3.org/TR/html5/infrastructure.html#code-unit-length
|
||||
*
|
||||
* @param string $text Input string.
|
||||
* @return int|false The number of code units, or false if
|
||||
* mb_convert_encoding is not available.
|
||||
*/
|
||||
function wpcf7_count_code_units( $text ) {
|
||||
static $use_mb = null;
|
||||
|
||||
if ( is_null( $use_mb ) ) {
|
||||
$use_mb = function_exists( 'mb_convert_encoding' );
|
||||
}
|
||||
|
||||
if ( ! $use_mb ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$text = (string) $text;
|
||||
|
||||
if ( '' === $text ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$text = str_replace( "\r\n", "\n", $text );
|
||||
|
||||
$text = mb_convert_encoding(
|
||||
$text,
|
||||
'UTF-16',
|
||||
mb_detect_encoding( $text, mb_detect_order(), true ) ?: 'UTF-8'
|
||||
);
|
||||
|
||||
return intdiv( mb_strlen( $text, '8bit' ), 2 );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if WordPress is running on the localhost.
|
||||
*/
|
||||
function wpcf7_is_localhost() {
|
||||
$sitename = wp_parse_url( network_home_url(), PHP_URL_HOST );
|
||||
|
||||
return in_array(
|
||||
strtolower( $sitename ),
|
||||
array( 'localhost', '127.0.0.1' ),
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Marks a function as deprecated and informs when it has been used.
|
||||
*
|
||||
* @param string $function_name The function that was called.
|
||||
* @param string $version The version of Contact Form 7 that deprecated
|
||||
* the function.
|
||||
* @param string $replacement The function that should have been called.
|
||||
*/
|
||||
function wpcf7_deprecated_function( $function_name, $version, $replacement ) {
|
||||
|
||||
if ( ! WP_DEBUG ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( function_exists( '__' ) ) {
|
||||
/* translators: 1: PHP function name, 2: version number, 3: alternative function name */
|
||||
$message = __( 'Function %1$s is <strong>deprecated</strong> since Contact Form 7 version %2$s! Use %3$s instead.', 'contact-form-7' );
|
||||
} else {
|
||||
$message = 'Function %1$s is <strong>deprecated</strong> since Contact Form 7 version %2$s! Use %3$s instead.';
|
||||
}
|
||||
|
||||
$message = sprintf( $message, $function_name, $version, $replacement );
|
||||
|
||||
wp_trigger_error( '', $message, E_USER_DEPRECATED );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fires functions attached to a deprecated filter hook.
|
||||
*
|
||||
* @param string $hook_name The name of the filter hook.
|
||||
* @param array $args Array of additional function arguments to be
|
||||
* passed to apply_filters().
|
||||
* @param string $version The version of Contact Form 7 that deprecated
|
||||
* the hook.
|
||||
* @param string $replacement The hook that should have been used.
|
||||
*/
|
||||
function wpcf7_apply_filters_deprecated( $hook_name, $args, $version, $replacement = '' ) {
|
||||
if ( ! has_filter( $hook_name ) ) {
|
||||
return $args[0];
|
||||
}
|
||||
|
||||
if ( WP_DEBUG and apply_filters( 'deprecated_hook_trigger_error', true ) ) {
|
||||
if ( $replacement ) {
|
||||
wp_trigger_error(
|
||||
'',
|
||||
sprintf(
|
||||
/* translators: 1: WordPress hook name, 2: version number, 3: alternative hook name */
|
||||
__( 'Hook %1$s is <strong>deprecated</strong> since Contact Form 7 version %2$s! Use %3$s instead.', 'contact-form-7' ),
|
||||
$hook_name,
|
||||
$version,
|
||||
$replacement
|
||||
),
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
} else {
|
||||
wp_trigger_error(
|
||||
'',
|
||||
sprintf(
|
||||
/* translators: 1: WordPress hook name, 2: version number */
|
||||
__( 'Hook %1$s is <strong>deprecated</strong> since Contact Form 7 version %2$s with no alternative available.', 'contact-form-7' ),
|
||||
$hook_name,
|
||||
$version
|
||||
),
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return apply_filters_ref_array( $hook_name, $args );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Marks something as being incorrectly called.
|
||||
*
|
||||
* @param string $function_name The function that was called.
|
||||
* @param string $message A message explaining what has been done incorrectly.
|
||||
* @param string $version The version of Contact Form 7 where the message
|
||||
* was added.
|
||||
*/
|
||||
function wpcf7_doing_it_wrong( $function_name, $message, $version ) {
|
||||
|
||||
if ( ! WP_DEBUG ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( function_exists( '__' ) ) {
|
||||
if ( $version ) {
|
||||
$version = sprintf(
|
||||
/* translators: %s: Contact Form 7 version number. */
|
||||
__( '(This message was added in Contact Form 7 version %s.)', 'contact-form-7' ),
|
||||
$version
|
||||
);
|
||||
}
|
||||
|
||||
wp_trigger_error(
|
||||
'',
|
||||
sprintf(
|
||||
/* translators: Developer debugging message. 1: PHP function name, 2: Explanatory message, 3: Contact Form 7 version number. */
|
||||
__( 'Function %1$s was called incorrectly. %2$s %3$s', 'contact-form-7' ),
|
||||
$function_name,
|
||||
$message,
|
||||
$version
|
||||
),
|
||||
E_USER_NOTICE
|
||||
);
|
||||
} else {
|
||||
if ( $version ) {
|
||||
$version = sprintf(
|
||||
'(This message was added in Contact Form 7 version %s.)',
|
||||
$version
|
||||
);
|
||||
}
|
||||
|
||||
wp_trigger_error(
|
||||
'',
|
||||
sprintf(
|
||||
'Function %1$s was called incorrectly. %2$s %3$s',
|
||||
$function_name,
|
||||
$message,
|
||||
$version
|
||||
),
|
||||
E_USER_NOTICE
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Triggers an error about a remote HTTP request and response.
|
||||
*
|
||||
* @param string $url The resource URL.
|
||||
* @param array $request Request arguments.
|
||||
* @param array|WP_Error $response The response or WP_Error on failure.
|
||||
*/
|
||||
function wpcf7_log_remote_request( $url, $request, $response ) {
|
||||
|
||||
if ( ! WP_DEBUG ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$log = sprintf(
|
||||
/* translators: 1: response code, 2: message, 3: body, 4: URL */
|
||||
__( 'HTTP Response: %1$s %2$s %3$s from %4$s', 'contact-form-7' ),
|
||||
(int) wp_remote_retrieve_response_code( $response ),
|
||||
wp_remote_retrieve_response_message( $response ),
|
||||
wp_remote_retrieve_body( $response ),
|
||||
$url
|
||||
);
|
||||
|
||||
$log = apply_filters( 'wpcf7_log_remote_request',
|
||||
$log, $url, $request, $response
|
||||
);
|
||||
|
||||
if ( $log ) {
|
||||
wp_trigger_error( '', $log, E_USER_NOTICE );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Anonymizes an IP address by masking local part.
|
||||
*
|
||||
* @param string $ip_addr The original IP address.
|
||||
* @return string|bool Anonymized IP address, or false on failure.
|
||||
*/
|
||||
function wpcf7_anonymize_ip_addr( $ip_addr ) {
|
||||
if (
|
||||
! function_exists( 'inet_ntop' ) or
|
||||
! function_exists( 'inet_pton' )
|
||||
) {
|
||||
return $ip_addr;
|
||||
}
|
||||
|
||||
$packed = inet_pton( $ip_addr );
|
||||
|
||||
if ( false === $packed ) {
|
||||
return $ip_addr;
|
||||
}
|
||||
|
||||
if ( 4 === strlen( $packed ) ) { // IPv4
|
||||
$mask = '255.255.255.0';
|
||||
} elseif ( 16 === strlen( $packed ) ) { // IPv6
|
||||
$mask = 'ffff:ffff:ffff:0000:0000:0000:0000:0000';
|
||||
} else {
|
||||
return $ip_addr;
|
||||
}
|
||||
|
||||
return inet_ntop( $packed & inet_pton( $mask ) );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves a sanitized value from the $_GET superglobal.
|
||||
*
|
||||
* @param string $key Array key.
|
||||
* @param mixed $default The default value returned when
|
||||
* the specified superglobal is not set.
|
||||
* @return mixed Sanitized value.
|
||||
*/
|
||||
function wpcf7_superglobal_get( $key, $default = '' ) {
|
||||
return wpcf7_superglobal( 'get', $key ) ?? $default;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves a sanitized value from the $_POST superglobal.
|
||||
*
|
||||
* @param string $key Array key.
|
||||
* @param mixed $default The default value returned when
|
||||
* the specified superglobal is not set.
|
||||
* @return mixed Sanitized value.
|
||||
*/
|
||||
function wpcf7_superglobal_post( $key, $default = '' ) {
|
||||
return wpcf7_superglobal( 'post', $key ) ?? $default;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves a sanitized value from the $_REQUEST superglobal.
|
||||
*
|
||||
* @param string $key Array key.
|
||||
* @param mixed $default The default value returned when
|
||||
* the specified superglobal is not set.
|
||||
* @return mixed Sanitized value.
|
||||
*/
|
||||
function wpcf7_superglobal_request( $key, $default = '' ) {
|
||||
return wpcf7_superglobal( 'request', $key ) ?? $default;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves a sanitized value from the $_SERVER superglobal.
|
||||
*
|
||||
* @param string $key Array key.
|
||||
* @param mixed $default The default value returned when
|
||||
* the specified superglobal is not set.
|
||||
* @return mixed Sanitized value.
|
||||
*/
|
||||
function wpcf7_superglobal_server( $key, $default = '' ) {
|
||||
return wpcf7_superglobal( 'server', $key ) ?? $default;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves a sanitized value from the specified superglobal.
|
||||
*
|
||||
* @param string $superglobal A superglobal type.
|
||||
* @param string $key Array key.
|
||||
* @return string|array|null Sanitized value.
|
||||
*/
|
||||
function wpcf7_superglobal( $superglobal, $key ) {
|
||||
$superglobals = array(
|
||||
'get' => $_GET,
|
||||
'post' => $_POST,
|
||||
'request' => $_REQUEST,
|
||||
'server' => $_SERVER,
|
||||
);
|
||||
|
||||
if ( isset( $superglobals[$superglobal][$key] ) ) {
|
||||
return map_deep(
|
||||
$superglobals[$superglobal][$key],
|
||||
static function ( $val ) {
|
||||
$val = wp_unslash( $val );
|
||||
$val = wp_check_invalid_utf8( $val );
|
||||
$val = wp_kses_no_null( $val );
|
||||
$val = wpcf7_strip_whitespaces( $val );
|
||||
return $val;
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
868
wp-content/plugins/contact-form-7/includes/html-formatter.php
Normal file
@@ -0,0 +1,868 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Contact Form 7's class used for formatting HTML fragments.
|
||||
*/
|
||||
class WPCF7_HTMLFormatter {
|
||||
|
||||
// HTML component types.
|
||||
const text = 0;
|
||||
const start_tag = 1;
|
||||
const end_tag = 2;
|
||||
const comment = 3;
|
||||
|
||||
/**
|
||||
* Tag name reserved for a custom HTML element used as a block placeholder.
|
||||
*/
|
||||
const placeholder_block = 'placeholder:block';
|
||||
|
||||
/**
|
||||
* Tag name reserved for a custom HTML element used as an inline placeholder.
|
||||
*/
|
||||
const placeholder_inline = 'placeholder:inline';
|
||||
|
||||
/**
|
||||
* The void elements in HTML.
|
||||
*
|
||||
* @link https://developer.mozilla.org/en-US/docs/Glossary/Void_element
|
||||
*/
|
||||
const void_elements = array(
|
||||
'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input',
|
||||
'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr',
|
||||
self::placeholder_block, self::placeholder_inline,
|
||||
);
|
||||
|
||||
/**
|
||||
* HTML elements that can be a direct child of the same element.
|
||||
*/
|
||||
const nestable_elements = array(
|
||||
'article', 'aside', 'blockquote', 'div', 'fieldset', 'section', 'span',
|
||||
);
|
||||
|
||||
/**
|
||||
* HTML elements that can contain flow content.
|
||||
*/
|
||||
const p_parent_elements = array(
|
||||
'address', 'article', 'aside', 'blockquote', 'body', 'caption',
|
||||
'dd', 'details', 'dialog', 'div', 'dt', 'fieldset', 'figcaption',
|
||||
'figure', 'footer', 'form', 'header', 'li', 'main', 'nav',
|
||||
'section', 'td', 'th',
|
||||
);
|
||||
|
||||
/**
|
||||
* HTML elements that can be neither the parent nor a child of
|
||||
* a paragraph element.
|
||||
*/
|
||||
const p_nonparent_elements = array(
|
||||
'colgroup', 'dl', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head',
|
||||
'hgroup', 'html', 'legend', 'menu', 'ol', 'pre', 'style', 'summary',
|
||||
'table', 'tbody', 'template', 'tfoot', 'thead', 'title', 'tr', 'ul',
|
||||
);
|
||||
|
||||
/**
|
||||
* HTML elements in the phrasing content category, plus non-phrasing
|
||||
* content elements that can be grandchildren of a paragraph element.
|
||||
*/
|
||||
const p_child_elements = array(
|
||||
'a', 'abbr', 'area', 'audio', 'b', 'bdi', 'bdo', 'br', 'button',
|
||||
'canvas', 'cite', 'code', 'data', 'datalist', 'del', 'dfn',
|
||||
'em', 'embed', 'i', 'iframe', 'img', 'input', 'ins', 'kbd',
|
||||
'keygen', 'label', 'link', 'map', 'mark', 'meta',
|
||||
'meter', 'noscript', 'object', 'output', 'picture', 'progress',
|
||||
'q', 'ruby', 's', 'samp', 'script', 'select', 'slot', 'small',
|
||||
'span', 'strong', 'sub', 'sup', 'textarea',
|
||||
'time', 'u', 'var', 'video', 'wbr',
|
||||
'optgroup', 'option', 'rp', 'rt', // non-phrasing grandchildren
|
||||
self::placeholder_inline,
|
||||
);
|
||||
|
||||
/**
|
||||
* HTML elements that can contain phrasing content.
|
||||
*/
|
||||
const br_parent_elements = array(
|
||||
'a', 'abbr', 'address', 'article', 'aside', 'audio', 'b', 'bdi',
|
||||
'bdo', 'blockquote', 'button', 'canvas', 'caption', 'cite', 'code',
|
||||
'data', 'datalist', 'dd', 'del', 'details', 'dfn', 'dialog', 'div',
|
||||
'dt', 'em', 'fieldset', 'figcaption', 'figure', 'footer', 'form',
|
||||
'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'i', 'ins', 'kbd',
|
||||
'label', 'legend', 'li', 'main', 'map', 'mark', 'meter', 'nav',
|
||||
'noscript', 'object', 'output', 'p', 'progress', 'q', 'rt',
|
||||
'ruby', 's', 'samp', 'section', 'slot', 'small', 'span', 'strong',
|
||||
'sub', 'summary', 'sup', 'td', 'th', 'time', 'u', 'var',
|
||||
'video',
|
||||
);
|
||||
|
||||
|
||||
// Properties.
|
||||
private $options = array();
|
||||
private $stacked_elements = array();
|
||||
private $output = '';
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct( $options = '' ) {
|
||||
$this->options = wp_parse_args( $options, array(
|
||||
'auto_br' => true,
|
||||
'auto_indent' => true,
|
||||
'allowed_html' => wpcf7_kses_allowed_html(),
|
||||
) );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Separates the given text into chunks of HTML. Each chunk must be an
|
||||
* associative array that includes 'position', 'type', and 'content' keys.
|
||||
*
|
||||
* @param string $input Text to be separated into chunks.
|
||||
* @return iterable Iterable of chunks.
|
||||
*/
|
||||
public function separate_into_chunks( $input ) {
|
||||
$input_bytelength = strlen( $input );
|
||||
$position = 0;
|
||||
|
||||
while ( $position < $input_bytelength ) {
|
||||
$next_tag = preg_match(
|
||||
'/(?:<!--.*?-->|<(?:\/?)[a-z].*?>)/is',
|
||||
$input,
|
||||
$matches,
|
||||
PREG_OFFSET_CAPTURE,
|
||||
$position
|
||||
);
|
||||
|
||||
if ( ! $next_tag ) {
|
||||
yield array(
|
||||
'position' => $position,
|
||||
'type' => self::text,
|
||||
'content' => substr( $input, $position ),
|
||||
);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
$next_tag = $matches[0][0];
|
||||
$next_tag_position = $matches[0][1];
|
||||
|
||||
if ( $position < $next_tag_position ) {
|
||||
yield array(
|
||||
'position' => $position,
|
||||
'type' => self::text,
|
||||
'content' => substr(
|
||||
$input,
|
||||
$position,
|
||||
$next_tag_position - $position
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
if ( '<!' === substr( $next_tag, 0, 2 ) ) {
|
||||
$next_tag_type = self::comment;
|
||||
} elseif ( '</' === substr( $next_tag, 0, 2 ) ) {
|
||||
$next_tag_type = self::end_tag;
|
||||
} else {
|
||||
$next_tag_type = self::start_tag;
|
||||
}
|
||||
|
||||
yield array(
|
||||
'position' => $next_tag_position,
|
||||
'type' => $next_tag_type,
|
||||
'content' => substr(
|
||||
$input,
|
||||
$next_tag_position,
|
||||
strlen( $next_tag )
|
||||
),
|
||||
);
|
||||
|
||||
$position = $next_tag_position + strlen( $next_tag );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Normalizes content in each chunk. This may change the type and position
|
||||
* of the chunk.
|
||||
*
|
||||
* @param iterable $chunks The original chunks.
|
||||
* @return iterable Normalized chunks.
|
||||
*/
|
||||
public function pre_format( $chunks ) {
|
||||
$position = 0;
|
||||
|
||||
foreach ( $chunks as $chunk ) {
|
||||
$chunk['position'] = $position;
|
||||
|
||||
// Standardize newline characters to "\n".
|
||||
$chunk['content'] = str_replace(
|
||||
array( "\r\n", "\r" ), "\n", $chunk['content']
|
||||
);
|
||||
|
||||
if ( self::start_tag === $chunk['type'] ) {
|
||||
list( $chunk['content'] ) =
|
||||
self::normalize_start_tag( $chunk['content'] );
|
||||
|
||||
// Replace <br /> by a line break.
|
||||
if (
|
||||
$this->options['auto_br'] and
|
||||
preg_match( '/^<br\s*\/?>$/i', $chunk['content'] )
|
||||
) {
|
||||
$chunk['type'] = self::text;
|
||||
$chunk['content'] = "\n";
|
||||
}
|
||||
}
|
||||
|
||||
yield $chunk;
|
||||
$position = self::calc_next_position( $chunk );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Concatenates neighboring text chunks to create a single chunk.
|
||||
*
|
||||
* @param iterable $chunks The original chunks.
|
||||
* @return iterable Processed chunks.
|
||||
*/
|
||||
public function concatenate_texts( $chunks ) {
|
||||
$position = 0;
|
||||
$text_left = null;
|
||||
|
||||
foreach ( $chunks as $chunk ) {
|
||||
$chunk['position'] = $position;
|
||||
|
||||
if ( self::text === $chunk['type'] ) {
|
||||
if ( isset( $text_left ) ) {
|
||||
$text_left['content'] .= $chunk['content'];
|
||||
} else {
|
||||
$text_left = $chunk;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( isset( $text_left ) ) {
|
||||
yield $text_left;
|
||||
$chunk['position'] = self::calc_next_position( $text_left );
|
||||
$text_left = null;
|
||||
}
|
||||
|
||||
yield $chunk;
|
||||
$position = self::calc_next_position( $chunk );
|
||||
}
|
||||
|
||||
if ( isset( $text_left ) ) {
|
||||
yield $text_left;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Outputs formatted HTML based on the given chunks.
|
||||
*
|
||||
* @param iterable $chunks The original chunks.
|
||||
* @return string Formatted HTML.
|
||||
*/
|
||||
public function format( $chunks ) {
|
||||
$chunks = $this->pre_format( $chunks );
|
||||
$chunks = $this->concatenate_texts( $chunks );
|
||||
|
||||
$this->output = '';
|
||||
$this->stacked_elements = array();
|
||||
|
||||
foreach ( $chunks as $chunk ) {
|
||||
|
||||
if ( self::text === $chunk['type'] ) {
|
||||
$this->append_text( $chunk['content'] );
|
||||
}
|
||||
|
||||
if ( self::start_tag === $chunk['type'] ) {
|
||||
$this->start_tag( $chunk['content'] );
|
||||
}
|
||||
|
||||
if ( self::end_tag === $chunk['type'] ) {
|
||||
$this->end_tag( $chunk['content'] );
|
||||
}
|
||||
|
||||
if ( self::comment === $chunk['type'] ) {
|
||||
$this->append_comment( $chunk['content'] );
|
||||
}
|
||||
}
|
||||
|
||||
return $this->output();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Appends preformatted text to the output property.
|
||||
*/
|
||||
public function append_preformatted( $content ) {
|
||||
$this->output .= $content;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Appends whitespace to the output property.
|
||||
*/
|
||||
public function append_whitespace() {
|
||||
$this->append_preformatted( ' ' );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Appends a text node content to the output property.
|
||||
*
|
||||
* @param string $content Text node content.
|
||||
*/
|
||||
public function append_text( $content ) {
|
||||
if ( $this->is_inside( array( 'pre', 'template' ) ) ) {
|
||||
$this->append_preformatted( $content );
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
empty( $this->stacked_elements ) or
|
||||
$this->has_parent( 'p' ) or
|
||||
$this->has_parent( self::p_parent_elements )
|
||||
) {
|
||||
// Close <p> if the content starts with multiple line breaks.
|
||||
if ( preg_match( '/^\s*\n\s*\n\s*/', $content ) ) {
|
||||
$this->end_tag( 'p' );
|
||||
}
|
||||
|
||||
// Split up the contents into paragraphs, separated by double line breaks.
|
||||
$paragraphs = preg_split( '/\s*\n\s*\n\s*/', $content );
|
||||
|
||||
$paragraphs = array_filter( $paragraphs, static function ( $paragraph ) {
|
||||
return '' !== wpcf7_strip_whitespaces( $paragraph );
|
||||
} );
|
||||
|
||||
$paragraphs = array_values( $paragraphs );
|
||||
|
||||
if ( $paragraphs ) {
|
||||
if ( $this->is_inside( 'p' ) ) {
|
||||
$paragraph = array_shift( $paragraphs );
|
||||
|
||||
$paragraph = self::normalize_paragraph(
|
||||
$paragraph,
|
||||
$this->options['auto_br']
|
||||
);
|
||||
|
||||
$this->append_preformatted( $paragraph );
|
||||
}
|
||||
|
||||
foreach ( $paragraphs as $paragraph ) {
|
||||
$this->start_tag( 'p' );
|
||||
|
||||
$paragraph = wpcf7_strip_whitespaces( $paragraph, 'start' );
|
||||
|
||||
$paragraph = self::normalize_paragraph(
|
||||
$paragraph,
|
||||
$this->options['auto_br']
|
||||
);
|
||||
|
||||
$this->append_preformatted( $paragraph );
|
||||
}
|
||||
}
|
||||
|
||||
// Close <p> if the content ends with multiple line breaks.
|
||||
if ( preg_match( '/\s*\n\s*\n\s*$/', $content ) ) {
|
||||
$this->end_tag( 'p' );
|
||||
}
|
||||
|
||||
// Cases where the content is a single line break.
|
||||
if ( preg_match( '/^\s*\n\s*$/', $content ) ) {
|
||||
$auto_br = $this->options['auto_br'] && $this->is_inside( 'p' );
|
||||
|
||||
$content = self::normalize_paragraph( $content, $auto_br );
|
||||
|
||||
$this->append_preformatted( $content );
|
||||
}
|
||||
} else {
|
||||
$auto_br = $this->options['auto_br'] &&
|
||||
$this->has_parent( self::br_parent_elements );
|
||||
|
||||
$content = self::normalize_paragraph( $content, $auto_br );
|
||||
|
||||
$this->append_preformatted( $content );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Appends a start tag to the output property.
|
||||
*
|
||||
* @param string $tag A start tag.
|
||||
*/
|
||||
public function start_tag( $tag ) {
|
||||
list( $tag, $tag_name ) = self::normalize_start_tag( $tag );
|
||||
|
||||
if (
|
||||
in_array( $tag_name, self::p_child_elements, true ) and
|
||||
! $this->is_inside( 'p' ) and
|
||||
! $this->is_inside( self::p_child_elements ) and
|
||||
! $this->has_parent( self::p_nonparent_elements )
|
||||
) {
|
||||
// Open <p> if it does not exist.
|
||||
$this->start_tag( 'p' );
|
||||
}
|
||||
|
||||
$this->append_start_tag( $tag_name, array(), $tag );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Appends a start tag to the output property.
|
||||
*
|
||||
* @param string $tag_name Tag name.
|
||||
* @param array $atts Associative array of attribute name and value pairs.
|
||||
* @param string $tag A start tag.
|
||||
*/
|
||||
public function append_start_tag( $tag_name, $atts = array(), $tag = '' ) {
|
||||
if ( ! self::validate_tag_name( $tag_name ) ) {
|
||||
wp_trigger_error(
|
||||
__METHOD__,
|
||||
sprintf(
|
||||
/* translators: %s: Invalid HTML tag name */
|
||||
__( 'Invalid tag name (%s) is specified.', 'contact-form-7' ),
|
||||
$tag_name
|
||||
),
|
||||
E_USER_WARNING
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( WP_DEBUG and ! empty( $this->options['allowed_html'] ) ) {
|
||||
$html_disallowance = array();
|
||||
|
||||
if ( ! isset( $this->options['allowed_html'][$tag_name] ) ) {
|
||||
$html_disallowance = array(
|
||||
'element' => $tag_name,
|
||||
);
|
||||
} else {
|
||||
$atts_allowed = $this->options['allowed_html'][$tag_name];
|
||||
|
||||
$atts_disallowed = array_diff_ukey( $atts, $atts_allowed,
|
||||
static function ( $key_1, $key_2 ) use ( $atts_allowed ) {
|
||||
if (
|
||||
str_starts_with( $key_1, 'data-' ) and
|
||||
! empty( $atts_allowed['data-*'] ) and
|
||||
preg_match( '/^data-[a-z0-9_-]+$/', $key_1 )
|
||||
) {
|
||||
return 0;
|
||||
} else {
|
||||
return $key_1 === $key_2 ? 0 : 1;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
if ( ! empty( $atts_disallowed ) ) {
|
||||
$html_disallowance = array(
|
||||
'element' => $tag_name,
|
||||
'attributes' => array_keys( $atts_disallowed ),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if ( $html_disallowance ) {
|
||||
$notice = sprintf(
|
||||
/* translators: %s: JSON-formatted array of disallowed HTML */
|
||||
__( 'HTML Disallowance: %s', 'contact-form-7' ),
|
||||
wp_json_encode( $html_disallowance, JSON_PRETTY_PRINT )
|
||||
);
|
||||
|
||||
wp_trigger_error( __METHOD__, $notice, E_USER_NOTICE );
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
'p' === $tag_name or
|
||||
in_array( $tag_name, self::p_parent_elements, true ) or
|
||||
in_array( $tag_name, self::p_nonparent_elements, true )
|
||||
) {
|
||||
// Close <p> if it exists.
|
||||
$this->end_tag( 'p' );
|
||||
}
|
||||
|
||||
if ( 'dd' === $tag_name or 'dt' === $tag_name ) {
|
||||
// Close <dd> and <dt> if closing tag is omitted.
|
||||
$this->end_tag( 'dd' );
|
||||
$this->end_tag( 'dt' );
|
||||
}
|
||||
|
||||
if ( 'li' === $tag_name ) {
|
||||
// Close <li> if closing tag is omitted.
|
||||
$this->end_tag( 'li' );
|
||||
}
|
||||
|
||||
if ( 'optgroup' === $tag_name ) {
|
||||
// Close <option> and <optgroup> if closing tag is omitted.
|
||||
$this->end_tag( 'option' );
|
||||
$this->end_tag( 'optgroup' );
|
||||
}
|
||||
|
||||
if ( 'option' === $tag_name ) {
|
||||
// Close <option> if closing tag is omitted.
|
||||
$this->end_tag( 'option' );
|
||||
}
|
||||
|
||||
if ( 'rp' === $tag_name or 'rt' === $tag_name ) {
|
||||
// Close <rp> and <rt> if closing tag is omitted.
|
||||
$this->end_tag( 'rp' );
|
||||
$this->end_tag( 'rt' );
|
||||
}
|
||||
|
||||
if ( 'td' === $tag_name or 'th' === $tag_name ) {
|
||||
// Close <td> and <th> if closing tag is omitted.
|
||||
$this->end_tag( 'td' );
|
||||
$this->end_tag( 'th' );
|
||||
}
|
||||
|
||||
if ( 'tr' === $tag_name ) {
|
||||
// Close <tr> if closing tag is omitted.
|
||||
$this->end_tag( 'tr' );
|
||||
}
|
||||
|
||||
if ( 'tbody' === $tag_name or 'tfoot' === $tag_name ) {
|
||||
// Close <thead> if closing tag is omitted.
|
||||
$this->end_tag( 'thead' );
|
||||
}
|
||||
|
||||
if ( 'tfoot' === $tag_name ) {
|
||||
// Close <tbody> if closing tag is omitted.
|
||||
$this->end_tag( 'tbody' );
|
||||
}
|
||||
|
||||
if (
|
||||
$this->has_parent( $tag_name ) and
|
||||
! in_array( $tag_name, self::nestable_elements, true )
|
||||
) {
|
||||
$this->end_tag( $tag_name );
|
||||
}
|
||||
|
||||
if ( ! in_array( $tag_name, self::void_elements, true ) ) {
|
||||
array_unshift( $this->stacked_elements, $tag_name );
|
||||
}
|
||||
|
||||
if ( ! in_array( $tag_name, self::p_child_elements, true ) ) {
|
||||
if ( '' !== $this->output ) {
|
||||
$this->output = wpcf7_strip_whitespaces( $this->output, 'end' ) . "\n";
|
||||
}
|
||||
|
||||
if ( $this->options['auto_indent'] ) {
|
||||
$this->append_preformatted(
|
||||
self::indent( count( $this->stacked_elements ) - 1 )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if ( $tag ) {
|
||||
$this->append_preformatted( $tag );
|
||||
} elseif ( $atts ) {
|
||||
if ( in_array( $tag_name, self::void_elements, true ) ) {
|
||||
$this->append_preformatted(
|
||||
sprintf(
|
||||
'<%1$s %2$s />',
|
||||
$tag_name,
|
||||
wpcf7_format_atts( $atts )
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$this->append_preformatted(
|
||||
sprintf(
|
||||
'<%1$s %2$s>',
|
||||
$tag_name,
|
||||
wpcf7_format_atts( $atts )
|
||||
)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if ( in_array( $tag_name, self::void_elements, true ) ) {
|
||||
$this->append_preformatted(
|
||||
sprintf(
|
||||
'<%s />',
|
||||
$tag_name
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$this->append_preformatted(
|
||||
sprintf(
|
||||
'<%s>',
|
||||
$tag_name
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Closes an element and its open descendants at a time.
|
||||
*
|
||||
* @param string $tag An end tag.
|
||||
*/
|
||||
public function end_tag( $tag ) {
|
||||
if ( preg_match( '/<\/(.+?)(?:\s|>)/', $tag, $matches ) ) {
|
||||
$tag_name = strtolower( $matches[1] );
|
||||
} else {
|
||||
$tag_name = strtolower( $tag );
|
||||
}
|
||||
|
||||
$stacked_elements = array_values( $this->stacked_elements );
|
||||
|
||||
$tag_position = array_search( $tag_name, $stacked_elements, true );
|
||||
|
||||
if ( false === $tag_position ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Element groups that make up an indirect nesting structure.
|
||||
// Descendant can contain ancestors.
|
||||
static $nesting_families = array(
|
||||
array(
|
||||
'ancestors' => array( 'dl' ),
|
||||
'descendants' => array( 'dd', 'dt' ),
|
||||
),
|
||||
array(
|
||||
'ancestors' => array( 'ol', 'ul', 'menu' ),
|
||||
'descendants' => array( 'li' ),
|
||||
),
|
||||
array(
|
||||
'ancestors' => array( 'table' ),
|
||||
'descendants' => array( 'td', 'th', 'tr', 'thead', 'tbody', 'tfoot' ),
|
||||
),
|
||||
);
|
||||
|
||||
foreach ( $nesting_families as $family ) {
|
||||
$ancestors = (array) $family['ancestors'];
|
||||
$descendants = (array) $family['descendants'];
|
||||
|
||||
if ( in_array( $tag_name, $descendants, true ) ) {
|
||||
$intersect = array_intersect(
|
||||
$ancestors,
|
||||
array_slice( $stacked_elements, 0, $tag_position )
|
||||
);
|
||||
|
||||
if ( $intersect ) { // Ancestor appears after descendant.
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while ( $element = array_shift( $this->stacked_elements ) ) {
|
||||
$this->append_end_tag( $element );
|
||||
|
||||
if ( $element === $tag_name ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Appends an end tag to the output property.
|
||||
*
|
||||
* @param string $tag_name Tag name.
|
||||
*/
|
||||
public function append_end_tag( $tag_name ) {
|
||||
if ( ! in_array( $tag_name, self::p_child_elements, true ) ) {
|
||||
// Remove unnecessary <br />.
|
||||
$this->output = preg_replace( '/\s*<br \/>\s*$/', '', $this->output );
|
||||
|
||||
$this->output = wpcf7_strip_whitespaces( $this->output, 'end' ) . "\n";
|
||||
|
||||
if ( $this->options['auto_indent'] ) {
|
||||
$this->append_preformatted(
|
||||
self::indent( count( $this->stacked_elements ) )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$this->append_preformatted(
|
||||
sprintf( '</%s>', $tag_name )
|
||||
);
|
||||
|
||||
// Remove trailing <p></p>.
|
||||
$this->output = preg_replace( '/<p>\s*<\/p>$/', '', $this->output );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Closes all open tags.
|
||||
*/
|
||||
public function close_all_tags() {
|
||||
while ( $element = array_shift( $this->stacked_elements ) ) {
|
||||
$this->append_end_tag( $element );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Appends an HTML comment to the output property.
|
||||
*
|
||||
* @param string $tag An HTML comment.
|
||||
*/
|
||||
public function append_comment( $tag ) {
|
||||
$this->append_preformatted( $tag );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if it is currently inside one of HTML elements specified
|
||||
* by tag names.
|
||||
*
|
||||
* @param string|array $tag_names A tag name or an array of tag names.
|
||||
*/
|
||||
public function is_inside( $tag_names ) {
|
||||
$tag_names = (array) $tag_names;
|
||||
|
||||
foreach ( $this->stacked_elements as $element ) {
|
||||
if ( in_array( $element, $tag_names, true ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the parent node is one of HTML elements specified
|
||||
* by tag names.
|
||||
*
|
||||
* @param string|array $tag_names A tag name or an array of tag names.
|
||||
*/
|
||||
public function has_parent( $tag_names ) {
|
||||
$tag_names = (array) $tag_names;
|
||||
|
||||
$parent = reset( $this->stacked_elements );
|
||||
|
||||
if ( false === $parent ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return in_array( $parent, $tag_names, true );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calls the callback given by the first parameter. The buffered output
|
||||
* will be appended to the output property.
|
||||
*/
|
||||
public function call_user_func( $callback, ...$args ) {
|
||||
ob_start();
|
||||
$result = call_user_func( $callback, ...$args );
|
||||
$output = ob_get_clean();
|
||||
|
||||
if ( false !== $output ) {
|
||||
$this->append_preformatted( "\n" . $output . "\n" );
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Closes all remaining tags, returns and resets the output.
|
||||
*/
|
||||
public function output() {
|
||||
$this->close_all_tags();
|
||||
|
||||
$output = $this->output;
|
||||
$this->output = '';
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Prints the output. Returns false if the allowed_html option is empty.
|
||||
*/
|
||||
public function print() {
|
||||
if ( empty( $this->options['allowed_html'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
echo wp_kses( $this->output(), $this->options['allowed_html'] );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calculates the position of the next chunk based on the position and
|
||||
* length of the current chunk.
|
||||
*
|
||||
* @param array $chunk An associative array of the current chunk.
|
||||
* @return int The position of the next chunk.
|
||||
*/
|
||||
public static function calc_next_position( $chunk ) {
|
||||
return $chunk['position'] + strlen( $chunk['content'] );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Outputs a set of tabs to indent.
|
||||
*
|
||||
* @param int $level Indentation level.
|
||||
* @return string A series of tabs.
|
||||
*/
|
||||
public static function indent( $level ) {
|
||||
$level = (int) $level;
|
||||
|
||||
if ( 0 < $level ) {
|
||||
return str_repeat( "\t", $level );
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Normalizes a start tag.
|
||||
*
|
||||
* @param string $tag A start tag or a tag name.
|
||||
* @return array An array includes the normalized start tag and tag name.
|
||||
*/
|
||||
public static function normalize_start_tag( $tag ) {
|
||||
if ( preg_match( '/<(.+?)[\s\/>]/', $tag, $matches ) ) {
|
||||
$tag_name = strtolower( $matches[1] );
|
||||
} else {
|
||||
$tag_name = strtolower( $tag );
|
||||
$tag = sprintf( '<%s>', $tag_name );
|
||||
}
|
||||
|
||||
if ( in_array( $tag_name, self::void_elements, true ) ) {
|
||||
// Normalize void element.
|
||||
$tag = preg_replace( '/\s*\/?>/', ' />', $tag );
|
||||
}
|
||||
|
||||
return array( $tag, $tag_name );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Normalizes a paragraph of text.
|
||||
*
|
||||
* @param string $paragraph A paragraph of text.
|
||||
* @param bool $auto_br Optional. If true, line breaks will be replaced
|
||||
* by a br element.
|
||||
* @return string The normalized paragraph.
|
||||
*/
|
||||
public static function normalize_paragraph( $paragraph, $auto_br = false ) {
|
||||
if ( $auto_br ) {
|
||||
$paragraph = preg_replace( '/\s*\n\s*/', "<br />\n", $paragraph );
|
||||
}
|
||||
|
||||
$paragraph = preg_replace( '/[ ]+/', ' ', $paragraph );
|
||||
|
||||
return $paragraph;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the specified tag name is valid.
|
||||
*/
|
||||
public static function validate_tag_name( $tag_name ) {
|
||||
return preg_match( '/^[a-z][0-9a-z]*(?:[:][a-z][0-9a-z]*)?$/', $tag_name );
|
||||
}
|
||||
|
||||
}
|
||||
430
wp-content/plugins/contact-form-7/includes/integration.php
Normal file
@@ -0,0 +1,430 @@
|
||||
<?php
|
||||
/**
|
||||
* Integration API
|
||||
*
|
||||
* @link https://contactform7.com/integration-with-external-apis/
|
||||
*/
|
||||
|
||||
class WPCF7_Integration {
|
||||
|
||||
private static $instance;
|
||||
|
||||
private $services = array();
|
||||
private $categories = array();
|
||||
|
||||
private function __construct() {}
|
||||
|
||||
|
||||
/**
|
||||
* Returns initially supported service categories.
|
||||
*
|
||||
* @return array Service categories.
|
||||
*/
|
||||
public static function get_builtin_categories() {
|
||||
return array(
|
||||
'spam_protection' => __( 'Spam protection', 'contact-form-7' ),
|
||||
'email_marketing' => __( 'Email marketing', 'contact-form-7' ),
|
||||
'payments' => __( 'Payments', 'contact-form-7' ),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the singleton instance of this class.
|
||||
*
|
||||
* @return WPCF7_Integration The instance.
|
||||
*/
|
||||
public static function get_instance() {
|
||||
if ( empty( self::$instance ) ) {
|
||||
self::$instance = new self();
|
||||
self::$instance->categories = self::get_builtin_categories();
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a service to the services list.
|
||||
*/
|
||||
public function add_service( $name, WPCF7_Service $service ) {
|
||||
$name = sanitize_key( $name );
|
||||
|
||||
if ( empty( $name ) or isset( $this->services[$name] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->services[$name] = $service;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a service category to the categories list.
|
||||
*/
|
||||
public function add_category( $name, $title ) {
|
||||
$name = sanitize_key( $name );
|
||||
|
||||
if ( empty( $name ) or isset( $this->categories[$name] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->categories[$name] = $title;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if a service with the name exists in the services list.
|
||||
*
|
||||
* @param string $name The name of service to search.
|
||||
*/
|
||||
public function service_exists( $name = '' ) {
|
||||
if ( '' === $name ) {
|
||||
return (bool) count( $this->services );
|
||||
} else {
|
||||
return isset( $this->services[$name] );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a service object with the name.
|
||||
*
|
||||
* @param string $name The name of service.
|
||||
* @return WPCF7_Service|bool The service object if it exists,
|
||||
* false otherwise.
|
||||
*/
|
||||
public function get_service( $name ) {
|
||||
if ( $this->service_exists( $name ) ) {
|
||||
return $this->services[$name];
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Prints services list.
|
||||
*/
|
||||
public function list_services( $args = '' ) {
|
||||
$args = wp_parse_args( $args, array(
|
||||
'include' => array(),
|
||||
) );
|
||||
|
||||
$singular = false;
|
||||
$services = (array) $this->services;
|
||||
|
||||
if ( ! empty( $args['include'] ) ) {
|
||||
$services = array_intersect_key( $services,
|
||||
array_flip( (array) $args['include'] )
|
||||
);
|
||||
|
||||
if ( 1 === count( $services ) ) {
|
||||
$singular = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( empty( $services ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$action = wpcf7_current_action();
|
||||
|
||||
foreach ( $services as $name => $service ) {
|
||||
$cats = array_intersect_key( $this->categories,
|
||||
array_flip( $service->get_categories() )
|
||||
);
|
||||
?>
|
||||
<div class="card<?php echo $service->is_active() ? ' active' : ''; ?>" id="<?php echo esc_attr( $name ); ?>">
|
||||
<?php $service->icon(); ?>
|
||||
<h2 class="title"><?php echo esc_html( $service->get_title() ); ?></h2>
|
||||
<div class="infobox">
|
||||
<?php echo esc_html( implode( ', ', $cats ) ); ?>
|
||||
<br />
|
||||
<?php $service->link(); ?>
|
||||
</div>
|
||||
<br class="clear" />
|
||||
|
||||
<div class="inside">
|
||||
<?php
|
||||
if ( $singular ) {
|
||||
$service->display( $action );
|
||||
} else {
|
||||
$service->display();
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Abstract class for services.
|
||||
*
|
||||
* Only instances of this class's subclasses are allowed to be
|
||||
* listed on the Integration page.
|
||||
*/
|
||||
abstract class WPCF7_Service {
|
||||
|
||||
abstract public function get_title();
|
||||
abstract public function is_active();
|
||||
|
||||
|
||||
public function get_categories() {
|
||||
return array();
|
||||
}
|
||||
|
||||
|
||||
public function icon() {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
public function link() {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
public function load( $action = '' ) {
|
||||
}
|
||||
|
||||
|
||||
public function display( $action = '' ) {
|
||||
}
|
||||
|
||||
|
||||
public function admin_notice( $message = '' ) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Class for services that use OAuth.
|
||||
*
|
||||
* While this is not an abstract class, subclassing this class for
|
||||
* your aim is advised.
|
||||
*/
|
||||
class WPCF7_Service_OAuth2 extends WPCF7_Service {
|
||||
|
||||
protected $client_id = '';
|
||||
protected $client_secret = '';
|
||||
protected $access_token = '';
|
||||
protected $refresh_token = '';
|
||||
protected $authorization_endpoint = 'https://example.com/authorization';
|
||||
protected $token_endpoint = 'https://example.com/token';
|
||||
|
||||
|
||||
public function get_title() {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
public function is_active() {
|
||||
return ! empty( $this->refresh_token );
|
||||
}
|
||||
|
||||
|
||||
protected function save_data() {
|
||||
}
|
||||
|
||||
|
||||
protected function reset_data() {
|
||||
}
|
||||
|
||||
|
||||
protected function get_redirect_uri() {
|
||||
return admin_url();
|
||||
}
|
||||
|
||||
|
||||
protected function menu_page_url( $args = '' ) {
|
||||
return menu_page_url( 'wpcf7-integration', false );
|
||||
}
|
||||
|
||||
|
||||
public function load( $action = '' ) {
|
||||
if ( 'auth_redirect' === $action ) {
|
||||
$code = wpcf7_superglobal_get( 'code' );
|
||||
|
||||
if ( $code ) {
|
||||
$this->request_token( $code );
|
||||
}
|
||||
|
||||
if ( ! empty( $this->access_token ) ) {
|
||||
$message = 'success';
|
||||
} else {
|
||||
$message = 'failed';
|
||||
}
|
||||
|
||||
wp_safe_redirect( $this->menu_page_url(
|
||||
array(
|
||||
'action' => 'setup',
|
||||
'message' => $message,
|
||||
)
|
||||
) );
|
||||
|
||||
exit();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected function authorize( $scope = '' ) {
|
||||
$endpoint = add_query_arg(
|
||||
array(
|
||||
'response_type' => 'code',
|
||||
'client_id' => $this->client_id,
|
||||
'redirect_uri' => urlencode( $this->get_redirect_uri() ),
|
||||
'scope' => $scope,
|
||||
),
|
||||
$this->authorization_endpoint
|
||||
);
|
||||
|
||||
if ( wp_redirect( sanitize_url( $endpoint ) ) ) {
|
||||
exit();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected function get_http_authorization_header( $scheme = 'basic' ) {
|
||||
$scheme = strtolower( trim( $scheme ) );
|
||||
|
||||
switch ( $scheme ) {
|
||||
case 'bearer':
|
||||
return sprintf( 'Bearer %s', $this->access_token );
|
||||
case 'basic':
|
||||
default:
|
||||
return sprintf( 'Basic %s',
|
||||
base64_encode( $this->client_id . ':' . $this->client_secret )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected function request_token( $authorization_code ) {
|
||||
$endpoint = add_query_arg(
|
||||
array(
|
||||
'code' => $authorization_code,
|
||||
'redirect_uri' => urlencode( $this->get_redirect_uri() ),
|
||||
'grant_type' => 'authorization_code',
|
||||
),
|
||||
$this->token_endpoint
|
||||
);
|
||||
|
||||
$request = array(
|
||||
'headers' => array(
|
||||
'Authorization' => $this->get_http_authorization_header( 'basic' ),
|
||||
),
|
||||
);
|
||||
|
||||
$response = wp_remote_post( sanitize_url( $endpoint ), $request );
|
||||
$response_code = (int) wp_remote_retrieve_response_code( $response );
|
||||
$response_body = wp_remote_retrieve_body( $response );
|
||||
$response_body = json_decode( $response_body, true );
|
||||
|
||||
if ( WP_DEBUG and 400 <= $response_code ) {
|
||||
$this->log( $endpoint, $request, $response );
|
||||
}
|
||||
|
||||
if ( 401 === $response_code ) { // Unauthorized
|
||||
$this->access_token = null;
|
||||
$this->refresh_token = null;
|
||||
} else {
|
||||
if ( isset( $response_body['access_token'] ) ) {
|
||||
$this->access_token = $response_body['access_token'];
|
||||
} else {
|
||||
$this->access_token = null;
|
||||
}
|
||||
|
||||
if ( isset( $response_body['refresh_token'] ) ) {
|
||||
$this->refresh_token = $response_body['refresh_token'];
|
||||
} else {
|
||||
$this->refresh_token = null;
|
||||
}
|
||||
}
|
||||
|
||||
$this->save_data();
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
|
||||
protected function refresh_token() {
|
||||
$endpoint = add_query_arg(
|
||||
array(
|
||||
'refresh_token' => $this->refresh_token,
|
||||
'grant_type' => 'refresh_token',
|
||||
),
|
||||
$this->token_endpoint
|
||||
);
|
||||
|
||||
$request = array(
|
||||
'headers' => array(
|
||||
'Authorization' => $this->get_http_authorization_header( 'basic' ),
|
||||
),
|
||||
);
|
||||
|
||||
$response = wp_remote_post( sanitize_url( $endpoint ), $request );
|
||||
$response_code = (int) wp_remote_retrieve_response_code( $response );
|
||||
$response_body = wp_remote_retrieve_body( $response );
|
||||
$response_body = json_decode( $response_body, true );
|
||||
|
||||
if ( WP_DEBUG and 400 <= $response_code ) {
|
||||
$this->log( $endpoint, $request, $response );
|
||||
}
|
||||
|
||||
if ( 401 === $response_code ) { // Unauthorized
|
||||
$this->access_token = null;
|
||||
$this->refresh_token = null;
|
||||
} else {
|
||||
if ( isset( $response_body['access_token'] ) ) {
|
||||
$this->access_token = $response_body['access_token'];
|
||||
} else {
|
||||
$this->access_token = null;
|
||||
}
|
||||
|
||||
if ( isset( $response_body['refresh_token'] ) ) {
|
||||
$this->refresh_token = $response_body['refresh_token'];
|
||||
}
|
||||
}
|
||||
|
||||
$this->save_data();
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
|
||||
protected function remote_request( $url, $request = array() ) {
|
||||
static $refreshed = false;
|
||||
|
||||
$request = wp_parse_args( $request, array() );
|
||||
|
||||
$request['headers'] = array_merge(
|
||||
$request['headers'],
|
||||
array(
|
||||
'Authorization' => $this->get_http_authorization_header( 'bearer' ),
|
||||
)
|
||||
);
|
||||
|
||||
$response = wp_remote_request( sanitize_url( $url ), $request );
|
||||
|
||||
if ( 401 === wp_remote_retrieve_response_code( $response )
|
||||
and ! $refreshed ) {
|
||||
$this->refresh_token();
|
||||
$refreshed = true;
|
||||
|
||||
$response = $this->remote_request( $url, $request );
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
|
||||
protected function log( $url, $request, $response ) {
|
||||
wpcf7_log_remote_request( $url, $request, $response );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
( function( $ ) {
|
||||
$( function() {
|
||||
var supportHtml5 = ( function() {
|
||||
var features = {};
|
||||
var input = document.createElement( 'input' );
|
||||
var inputTypes = [ 'date' ];
|
||||
|
||||
$.each( inputTypes, function( index, value ) {
|
||||
input.setAttribute( 'type', value );
|
||||
features[ value ] = input.type !== 'text';
|
||||
} );
|
||||
|
||||
return features;
|
||||
} )();
|
||||
|
||||
if ( ! supportHtml5.date ) {
|
||||
$( 'input.wpcf7-date[type="date"]' ).each( function() {
|
||||
$( this ).datepicker( {
|
||||
dateFormat: 'yy-mm-dd',
|
||||
minDate: new Date( $( this ).attr( 'min' ) ),
|
||||
maxDate: new Date( $( this ).attr( 'max' ) )
|
||||
} );
|
||||
} );
|
||||
}
|
||||
} );
|
||||
} )( jQuery );
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'dependencies' => array(
|
||||
'wp-i18n',
|
||||
),
|
||||
'version' => WPCF7_VERSION,
|
||||
);
|
||||
1
wp-content/plugins/contact-form-7/includes/js/index.js
Normal file
|
After Width: | Height: | Size: 393 B |
|
After Width: | Height: | Size: 265 B |
|
After Width: | Height: | Size: 323 B |
|
After Width: | Height: | Size: 324 B |
|
After Width: | Height: | Size: 390 B |
|
After Width: | Height: | Size: 325 B |
|
After Width: | Height: | Size: 6.9 KiB |
|
After Width: | Height: | Size: 4.6 KiB |
|
After Width: | Height: | Size: 6.9 KiB |
|
After Width: | Height: | Size: 6.9 KiB |
|
After Width: | Height: | Size: 4.6 KiB |
1311
wp-content/plugins/contact-form-7/includes/js/jquery-ui/themes/smoothness/jquery-ui.css
vendored
Normal file
7
wp-content/plugins/contact-form-7/includes/js/jquery-ui/themes/smoothness/jquery-ui.min.css
vendored
Normal file
@@ -0,0 +1,443 @@
|
||||
/*!
|
||||
* jQuery UI CSS Framework 1.12.1
|
||||
* http://jqueryui.com
|
||||
*
|
||||
* Copyright jQuery Foundation and other contributors
|
||||
* Released under the MIT license.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* http://api.jqueryui.com/category/theming/
|
||||
*
|
||||
* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana%2CArial%2Csans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=highlight_soft&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=flat&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=glass&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=glass&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=glass&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=glass&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=glass&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
|
||||
*/
|
||||
|
||||
|
||||
/* Component containers
|
||||
----------------------------------*/
|
||||
.ui-widget {
|
||||
font-family: Verdana,Arial,sans-serif;
|
||||
font-size: 1.1em;
|
||||
}
|
||||
.ui-widget .ui-widget {
|
||||
font-size: 1em;
|
||||
}
|
||||
.ui-widget input,
|
||||
.ui-widget select,
|
||||
.ui-widget textarea,
|
||||
.ui-widget button {
|
||||
font-family: Verdana,Arial,sans-serif;
|
||||
font-size: 1em;
|
||||
}
|
||||
.ui-widget.ui-widget-content {
|
||||
border: 1px solid #d3d3d3;
|
||||
}
|
||||
.ui-widget-content {
|
||||
border: 1px solid #aaaaaa;
|
||||
background: #ffffff;
|
||||
color: #222222;
|
||||
}
|
||||
.ui-widget-content a {
|
||||
color: #222222;
|
||||
}
|
||||
.ui-widget-header {
|
||||
border: 1px solid #aaaaaa;
|
||||
background: #cccccc url("images/ui-bg_highlight-soft_75_cccccc_1x100.png") 50% 50% repeat-x;
|
||||
color: #222222;
|
||||
font-weight: bold;
|
||||
}
|
||||
.ui-widget-header a {
|
||||
color: #222222;
|
||||
}
|
||||
|
||||
/* Interaction states
|
||||
----------------------------------*/
|
||||
.ui-state-default,
|
||||
.ui-widget-content .ui-state-default,
|
||||
.ui-widget-header .ui-state-default,
|
||||
.ui-button,
|
||||
|
||||
/* We use html here because we need a greater specificity to make sure disabled
|
||||
works properly when clicked or hovered */
|
||||
html .ui-button.ui-state-disabled:hover,
|
||||
html .ui-button.ui-state-disabled:active {
|
||||
border: 1px solid #d3d3d3;
|
||||
background: #e6e6e6 url("images/ui-bg_glass_75_e6e6e6_1x400.png") 50% 50% repeat-x;
|
||||
font-weight: normal;
|
||||
color: #555555;
|
||||
}
|
||||
.ui-state-default a,
|
||||
.ui-state-default a:link,
|
||||
.ui-state-default a:visited,
|
||||
a.ui-button,
|
||||
a:link.ui-button,
|
||||
a:visited.ui-button,
|
||||
.ui-button {
|
||||
color: #555555;
|
||||
text-decoration: none;
|
||||
}
|
||||
.ui-state-hover,
|
||||
.ui-widget-content .ui-state-hover,
|
||||
.ui-widget-header .ui-state-hover,
|
||||
.ui-state-focus,
|
||||
.ui-widget-content .ui-state-focus,
|
||||
.ui-widget-header .ui-state-focus,
|
||||
.ui-button:hover,
|
||||
.ui-button:focus {
|
||||
border: 1px solid #999999;
|
||||
background: #dadada url("images/ui-bg_glass_75_dadada_1x400.png") 50% 50% repeat-x;
|
||||
font-weight: normal;
|
||||
color: #212121;
|
||||
}
|
||||
.ui-state-hover a,
|
||||
.ui-state-hover a:hover,
|
||||
.ui-state-hover a:link,
|
||||
.ui-state-hover a:visited,
|
||||
.ui-state-focus a,
|
||||
.ui-state-focus a:hover,
|
||||
.ui-state-focus a:link,
|
||||
.ui-state-focus a:visited,
|
||||
a.ui-button:hover,
|
||||
a.ui-button:focus {
|
||||
color: #212121;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.ui-visual-focus {
|
||||
box-shadow: 0 0 3px 1px rgb(94, 158, 214);
|
||||
}
|
||||
.ui-state-active,
|
||||
.ui-widget-content .ui-state-active,
|
||||
.ui-widget-header .ui-state-active,
|
||||
a.ui-button:active,
|
||||
.ui-button:active,
|
||||
.ui-button.ui-state-active:hover {
|
||||
border: 1px solid #aaaaaa;
|
||||
background: #ffffff url("images/ui-bg_glass_65_ffffff_1x400.png") 50% 50% repeat-x;
|
||||
font-weight: normal;
|
||||
color: #212121;
|
||||
}
|
||||
.ui-icon-background,
|
||||
.ui-state-active .ui-icon-background {
|
||||
border: #aaaaaa;
|
||||
background-color: #212121;
|
||||
}
|
||||
.ui-state-active a,
|
||||
.ui-state-active a:link,
|
||||
.ui-state-active a:visited {
|
||||
color: #212121;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* Interaction Cues
|
||||
----------------------------------*/
|
||||
.ui-state-highlight,
|
||||
.ui-widget-content .ui-state-highlight,
|
||||
.ui-widget-header .ui-state-highlight {
|
||||
border: 1px solid #fcefa1;
|
||||
background: #fbf9ee url("images/ui-bg_glass_55_fbf9ee_1x400.png") 50% 50% repeat-x;
|
||||
color: #363636;
|
||||
}
|
||||
.ui-state-checked {
|
||||
border: 1px solid #fcefa1;
|
||||
background: #fbf9ee;
|
||||
}
|
||||
.ui-state-highlight a,
|
||||
.ui-widget-content .ui-state-highlight a,
|
||||
.ui-widget-header .ui-state-highlight a {
|
||||
color: #363636;
|
||||
}
|
||||
.ui-state-error,
|
||||
.ui-widget-content .ui-state-error,
|
||||
.ui-widget-header .ui-state-error {
|
||||
border: 1px solid #cd0a0a;
|
||||
background: #fef1ec url("images/ui-bg_glass_95_fef1ec_1x400.png") 50% 50% repeat-x;
|
||||
color: #cd0a0a;
|
||||
}
|
||||
.ui-state-error a,
|
||||
.ui-widget-content .ui-state-error a,
|
||||
.ui-widget-header .ui-state-error a {
|
||||
color: #cd0a0a;
|
||||
}
|
||||
.ui-state-error-text,
|
||||
.ui-widget-content .ui-state-error-text,
|
||||
.ui-widget-header .ui-state-error-text {
|
||||
color: #cd0a0a;
|
||||
}
|
||||
.ui-priority-primary,
|
||||
.ui-widget-content .ui-priority-primary,
|
||||
.ui-widget-header .ui-priority-primary {
|
||||
font-weight: bold;
|
||||
}
|
||||
.ui-priority-secondary,
|
||||
.ui-widget-content .ui-priority-secondary,
|
||||
.ui-widget-header .ui-priority-secondary {
|
||||
opacity: .7;
|
||||
filter:Alpha(Opacity=70); /* support: IE8 */
|
||||
font-weight: normal;
|
||||
}
|
||||
.ui-state-disabled,
|
||||
.ui-widget-content .ui-state-disabled,
|
||||
.ui-widget-header .ui-state-disabled {
|
||||
opacity: .35;
|
||||
filter:Alpha(Opacity=35); /* support: IE8 */
|
||||
background-image: none;
|
||||
}
|
||||
.ui-state-disabled .ui-icon {
|
||||
filter:Alpha(Opacity=35); /* support: IE8 - See #6059 */
|
||||
}
|
||||
|
||||
/* Icons
|
||||
----------------------------------*/
|
||||
|
||||
/* states and images */
|
||||
.ui-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
.ui-icon,
|
||||
.ui-widget-content .ui-icon {
|
||||
background-image: url("images/ui-icons_222222_256x240.png");
|
||||
}
|
||||
.ui-widget-header .ui-icon {
|
||||
background-image: url("images/ui-icons_222222_256x240.png");
|
||||
}
|
||||
.ui-state-hover .ui-icon,
|
||||
.ui-state-focus .ui-icon,
|
||||
.ui-button:hover .ui-icon,
|
||||
.ui-button:focus .ui-icon {
|
||||
background-image: url("images/ui-icons_454545_256x240.png");
|
||||
}
|
||||
.ui-state-active .ui-icon,
|
||||
.ui-button:active .ui-icon {
|
||||
background-image: url("images/ui-icons_454545_256x240.png");
|
||||
}
|
||||
.ui-state-highlight .ui-icon,
|
||||
.ui-button .ui-state-highlight.ui-icon {
|
||||
background-image: url("images/ui-icons_2e83ff_256x240.png");
|
||||
}
|
||||
.ui-state-error .ui-icon,
|
||||
.ui-state-error-text .ui-icon {
|
||||
background-image: url("images/ui-icons_cd0a0a_256x240.png");
|
||||
}
|
||||
.ui-button .ui-icon {
|
||||
background-image: url("images/ui-icons_888888_256x240.png");
|
||||
}
|
||||
|
||||
/* positioning */
|
||||
.ui-icon-blank { background-position: 16px 16px; }
|
||||
.ui-icon-caret-1-n { background-position: 0 0; }
|
||||
.ui-icon-caret-1-ne { background-position: -16px 0; }
|
||||
.ui-icon-caret-1-e { background-position: -32px 0; }
|
||||
.ui-icon-caret-1-se { background-position: -48px 0; }
|
||||
.ui-icon-caret-1-s { background-position: -65px 0; }
|
||||
.ui-icon-caret-1-sw { background-position: -80px 0; }
|
||||
.ui-icon-caret-1-w { background-position: -96px 0; }
|
||||
.ui-icon-caret-1-nw { background-position: -112px 0; }
|
||||
.ui-icon-caret-2-n-s { background-position: -128px 0; }
|
||||
.ui-icon-caret-2-e-w { background-position: -144px 0; }
|
||||
.ui-icon-triangle-1-n { background-position: 0 -16px; }
|
||||
.ui-icon-triangle-1-ne { background-position: -16px -16px; }
|
||||
.ui-icon-triangle-1-e { background-position: -32px -16px; }
|
||||
.ui-icon-triangle-1-se { background-position: -48px -16px; }
|
||||
.ui-icon-triangle-1-s { background-position: -65px -16px; }
|
||||
.ui-icon-triangle-1-sw { background-position: -80px -16px; }
|
||||
.ui-icon-triangle-1-w { background-position: -96px -16px; }
|
||||
.ui-icon-triangle-1-nw { background-position: -112px -16px; }
|
||||
.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
|
||||
.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
|
||||
.ui-icon-arrow-1-n { background-position: 0 -32px; }
|
||||
.ui-icon-arrow-1-ne { background-position: -16px -32px; }
|
||||
.ui-icon-arrow-1-e { background-position: -32px -32px; }
|
||||
.ui-icon-arrow-1-se { background-position: -48px -32px; }
|
||||
.ui-icon-arrow-1-s { background-position: -65px -32px; }
|
||||
.ui-icon-arrow-1-sw { background-position: -80px -32px; }
|
||||
.ui-icon-arrow-1-w { background-position: -96px -32px; }
|
||||
.ui-icon-arrow-1-nw { background-position: -112px -32px; }
|
||||
.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
|
||||
.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
|
||||
.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
|
||||
.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
|
||||
.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
|
||||
.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
|
||||
.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
|
||||
.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
|
||||
.ui-icon-arrowthick-1-n { background-position: 1px -48px; }
|
||||
.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
|
||||
.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
|
||||
.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
|
||||
.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
|
||||
.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
|
||||
.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
|
||||
.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
|
||||
.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
|
||||
.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
|
||||
.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
|
||||
.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
|
||||
.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
|
||||
.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
|
||||
.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
|
||||
.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
|
||||
.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
|
||||
.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
|
||||
.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
|
||||
.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
|
||||
.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
|
||||
.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
|
||||
.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
|
||||
.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
|
||||
.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
|
||||
.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
|
||||
.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
|
||||
.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
|
||||
.ui-icon-arrow-4 { background-position: 0 -80px; }
|
||||
.ui-icon-arrow-4-diag { background-position: -16px -80px; }
|
||||
.ui-icon-extlink { background-position: -32px -80px; }
|
||||
.ui-icon-newwin { background-position: -48px -80px; }
|
||||
.ui-icon-refresh { background-position: -64px -80px; }
|
||||
.ui-icon-shuffle { background-position: -80px -80px; }
|
||||
.ui-icon-transfer-e-w { background-position: -96px -80px; }
|
||||
.ui-icon-transferthick-e-w { background-position: -112px -80px; }
|
||||
.ui-icon-folder-collapsed { background-position: 0 -96px; }
|
||||
.ui-icon-folder-open { background-position: -16px -96px; }
|
||||
.ui-icon-document { background-position: -32px -96px; }
|
||||
.ui-icon-document-b { background-position: -48px -96px; }
|
||||
.ui-icon-note { background-position: -64px -96px; }
|
||||
.ui-icon-mail-closed { background-position: -80px -96px; }
|
||||
.ui-icon-mail-open { background-position: -96px -96px; }
|
||||
.ui-icon-suitcase { background-position: -112px -96px; }
|
||||
.ui-icon-comment { background-position: -128px -96px; }
|
||||
.ui-icon-person { background-position: -144px -96px; }
|
||||
.ui-icon-print { background-position: -160px -96px; }
|
||||
.ui-icon-trash { background-position: -176px -96px; }
|
||||
.ui-icon-locked { background-position: -192px -96px; }
|
||||
.ui-icon-unlocked { background-position: -208px -96px; }
|
||||
.ui-icon-bookmark { background-position: -224px -96px; }
|
||||
.ui-icon-tag { background-position: -240px -96px; }
|
||||
.ui-icon-home { background-position: 0 -112px; }
|
||||
.ui-icon-flag { background-position: -16px -112px; }
|
||||
.ui-icon-calendar { background-position: -32px -112px; }
|
||||
.ui-icon-cart { background-position: -48px -112px; }
|
||||
.ui-icon-pencil { background-position: -64px -112px; }
|
||||
.ui-icon-clock { background-position: -80px -112px; }
|
||||
.ui-icon-disk { background-position: -96px -112px; }
|
||||
.ui-icon-calculator { background-position: -112px -112px; }
|
||||
.ui-icon-zoomin { background-position: -128px -112px; }
|
||||
.ui-icon-zoomout { background-position: -144px -112px; }
|
||||
.ui-icon-search { background-position: -160px -112px; }
|
||||
.ui-icon-wrench { background-position: -176px -112px; }
|
||||
.ui-icon-gear { background-position: -192px -112px; }
|
||||
.ui-icon-heart { background-position: -208px -112px; }
|
||||
.ui-icon-star { background-position: -224px -112px; }
|
||||
.ui-icon-link { background-position: -240px -112px; }
|
||||
.ui-icon-cancel { background-position: 0 -128px; }
|
||||
.ui-icon-plus { background-position: -16px -128px; }
|
||||
.ui-icon-plusthick { background-position: -32px -128px; }
|
||||
.ui-icon-minus { background-position: -48px -128px; }
|
||||
.ui-icon-minusthick { background-position: -64px -128px; }
|
||||
.ui-icon-close { background-position: -80px -128px; }
|
||||
.ui-icon-closethick { background-position: -96px -128px; }
|
||||
.ui-icon-key { background-position: -112px -128px; }
|
||||
.ui-icon-lightbulb { background-position: -128px -128px; }
|
||||
.ui-icon-scissors { background-position: -144px -128px; }
|
||||
.ui-icon-clipboard { background-position: -160px -128px; }
|
||||
.ui-icon-copy { background-position: -176px -128px; }
|
||||
.ui-icon-contact { background-position: -192px -128px; }
|
||||
.ui-icon-image { background-position: -208px -128px; }
|
||||
.ui-icon-video { background-position: -224px -128px; }
|
||||
.ui-icon-script { background-position: -240px -128px; }
|
||||
.ui-icon-alert { background-position: 0 -144px; }
|
||||
.ui-icon-info { background-position: -16px -144px; }
|
||||
.ui-icon-notice { background-position: -32px -144px; }
|
||||
.ui-icon-help { background-position: -48px -144px; }
|
||||
.ui-icon-check { background-position: -64px -144px; }
|
||||
.ui-icon-bullet { background-position: -80px -144px; }
|
||||
.ui-icon-radio-on { background-position: -96px -144px; }
|
||||
.ui-icon-radio-off { background-position: -112px -144px; }
|
||||
.ui-icon-pin-w { background-position: -128px -144px; }
|
||||
.ui-icon-pin-s { background-position: -144px -144px; }
|
||||
.ui-icon-play { background-position: 0 -160px; }
|
||||
.ui-icon-pause { background-position: -16px -160px; }
|
||||
.ui-icon-seek-next { background-position: -32px -160px; }
|
||||
.ui-icon-seek-prev { background-position: -48px -160px; }
|
||||
.ui-icon-seek-end { background-position: -64px -160px; }
|
||||
.ui-icon-seek-start { background-position: -80px -160px; }
|
||||
/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
|
||||
.ui-icon-seek-first { background-position: -80px -160px; }
|
||||
.ui-icon-stop { background-position: -96px -160px; }
|
||||
.ui-icon-eject { background-position: -112px -160px; }
|
||||
.ui-icon-volume-off { background-position: -128px -160px; }
|
||||
.ui-icon-volume-on { background-position: -144px -160px; }
|
||||
.ui-icon-power { background-position: 0 -176px; }
|
||||
.ui-icon-signal-diag { background-position: -16px -176px; }
|
||||
.ui-icon-signal { background-position: -32px -176px; }
|
||||
.ui-icon-battery-0 { background-position: -48px -176px; }
|
||||
.ui-icon-battery-1 { background-position: -64px -176px; }
|
||||
.ui-icon-battery-2 { background-position: -80px -176px; }
|
||||
.ui-icon-battery-3 { background-position: -96px -176px; }
|
||||
.ui-icon-circle-plus { background-position: 0 -192px; }
|
||||
.ui-icon-circle-minus { background-position: -16px -192px; }
|
||||
.ui-icon-circle-close { background-position: -32px -192px; }
|
||||
.ui-icon-circle-triangle-e { background-position: -48px -192px; }
|
||||
.ui-icon-circle-triangle-s { background-position: -64px -192px; }
|
||||
.ui-icon-circle-triangle-w { background-position: -80px -192px; }
|
||||
.ui-icon-circle-triangle-n { background-position: -96px -192px; }
|
||||
.ui-icon-circle-arrow-e { background-position: -112px -192px; }
|
||||
.ui-icon-circle-arrow-s { background-position: -128px -192px; }
|
||||
.ui-icon-circle-arrow-w { background-position: -144px -192px; }
|
||||
.ui-icon-circle-arrow-n { background-position: -160px -192px; }
|
||||
.ui-icon-circle-zoomin { background-position: -176px -192px; }
|
||||
.ui-icon-circle-zoomout { background-position: -192px -192px; }
|
||||
.ui-icon-circle-check { background-position: -208px -192px; }
|
||||
.ui-icon-circlesmall-plus { background-position: 0 -208px; }
|
||||
.ui-icon-circlesmall-minus { background-position: -16px -208px; }
|
||||
.ui-icon-circlesmall-close { background-position: -32px -208px; }
|
||||
.ui-icon-squaresmall-plus { background-position: -48px -208px; }
|
||||
.ui-icon-squaresmall-minus { background-position: -64px -208px; }
|
||||
.ui-icon-squaresmall-close { background-position: -80px -208px; }
|
||||
.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
|
||||
.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
|
||||
.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
|
||||
.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
|
||||
.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
|
||||
.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
|
||||
|
||||
|
||||
/* Misc visuals
|
||||
----------------------------------*/
|
||||
|
||||
/* Corner radius */
|
||||
.ui-corner-all,
|
||||
.ui-corner-top,
|
||||
.ui-corner-left,
|
||||
.ui-corner-tl {
|
||||
border-top-left-radius: 4px;
|
||||
}
|
||||
.ui-corner-all,
|
||||
.ui-corner-top,
|
||||
.ui-corner-right,
|
||||
.ui-corner-tr {
|
||||
border-top-right-radius: 4px;
|
||||
}
|
||||
.ui-corner-all,
|
||||
.ui-corner-bottom,
|
||||
.ui-corner-left,
|
||||
.ui-corner-bl {
|
||||
border-bottom-left-radius: 4px;
|
||||
}
|
||||
.ui-corner-all,
|
||||
.ui-corner-bottom,
|
||||
.ui-corner-right,
|
||||
.ui-corner-br {
|
||||
border-bottom-right-radius: 4px;
|
||||
}
|
||||
|
||||
/* Overlays */
|
||||
.ui-widget-overlay {
|
||||
background: #aaaaaa;
|
||||
opacity: .3;
|
||||
filter: Alpha(Opacity=30); /* support: IE8 */
|
||||
}
|
||||
.ui-widget-shadow {
|
||||
-webkit-box-shadow: -8px -8px 8px #aaaaaa;
|
||||
box-shadow: -8px -8px 8px #aaaaaa;
|
||||
}
|
||||
156
wp-content/plugins/contact-form-7/includes/l10n.php
Normal file
@@ -0,0 +1,156 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Retrieves an associative array of languages to which
|
||||
* this plugin is translated.
|
||||
*
|
||||
* @return array Array of languages.
|
||||
*/
|
||||
function wpcf7_l10n() {
|
||||
static $l10n = array();
|
||||
|
||||
if ( ! empty( $l10n ) ) {
|
||||
return $l10n;
|
||||
}
|
||||
|
||||
if ( ! is_admin() ) {
|
||||
return $l10n;
|
||||
}
|
||||
|
||||
require_once ABSPATH . 'wp-admin/includes/translation-install.php';
|
||||
|
||||
$api = translations_api( 'plugins', array(
|
||||
'slug' => 'contact-form-7',
|
||||
'version' => WPCF7_VERSION,
|
||||
) );
|
||||
|
||||
if ( is_wp_error( $api ) or empty( $api['translations'] ) ) {
|
||||
return $l10n;
|
||||
}
|
||||
|
||||
foreach ( (array) $api['translations'] as $translation ) {
|
||||
if (
|
||||
! empty( $translation['language'] ) and
|
||||
! empty( $translation['english_name'] )
|
||||
) {
|
||||
$l10n[$translation['language']] = $translation['english_name'];
|
||||
}
|
||||
}
|
||||
|
||||
return $l10n;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the given locale code looks valid.
|
||||
*
|
||||
* @param string $locale Locale code.
|
||||
*/
|
||||
function wpcf7_is_valid_locale( $locale ) {
|
||||
if ( ! is_string( $locale ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$pattern = '/^[a-z]{2,3}(?:_[a-zA-Z_]{2,})?$/';
|
||||
return (bool) preg_match( $pattern, $locale );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the given locale is an RTL language.
|
||||
*/
|
||||
function wpcf7_is_rtl( $locale = '' ) {
|
||||
static $rtl_locales = array(
|
||||
'ar' => 'Arabic',
|
||||
'ary' => 'Moroccan Arabic',
|
||||
'azb' => 'South Azerbaijani',
|
||||
'fa_IR' => 'Persian',
|
||||
'haz' => 'Hazaragi',
|
||||
'he_IL' => 'Hebrew',
|
||||
'ps' => 'Pashto',
|
||||
'ug_CN' => 'Uighur',
|
||||
);
|
||||
|
||||
if ( empty( $locale ) and function_exists( 'is_rtl' ) ) {
|
||||
return is_rtl();
|
||||
}
|
||||
|
||||
if ( empty( $locale ) ) {
|
||||
$locale = determine_locale();
|
||||
}
|
||||
|
||||
return isset( $rtl_locales[$locale] );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Loads a translation file into the plugin's text domain.
|
||||
*
|
||||
* @param string $locale Locale code.
|
||||
* @return bool True on success, false on failure.
|
||||
*/
|
||||
function wpcf7_load_textdomain( $locale = '' ) {
|
||||
$mofile = path_join(
|
||||
WP_LANG_DIR . '/plugins/',
|
||||
sprintf( '%s-%s.mo', WPCF7_TEXT_DOMAIN, $locale )
|
||||
);
|
||||
|
||||
return load_textdomain( WPCF7_TEXT_DOMAIN, $mofile, $locale );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Unloads translations for the plugin's text domain.
|
||||
*
|
||||
* @param bool $reloadable Whether the text domain can be loaded
|
||||
* just-in-time again.
|
||||
* @return bool True on success, false on failure.
|
||||
*/
|
||||
function wpcf7_unload_textdomain( $reloadable = false ) {
|
||||
return unload_textdomain( WPCF7_TEXT_DOMAIN, $reloadable );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Switches translation locale, calls the callback, then switches back
|
||||
* to the original locale.
|
||||
*
|
||||
* @param string $locale Locale code.
|
||||
* @param callable $callback The callable to be called.
|
||||
* @param mixed $args Parameters to be passed to the callback.
|
||||
* @return mixed The return value of the callback.
|
||||
*/
|
||||
function wpcf7_switch_locale( $locale, callable $callback, ...$args ) {
|
||||
static $available_locales = null;
|
||||
|
||||
if ( ! isset( $available_locales ) ) {
|
||||
$available_locales = array_merge(
|
||||
array( 'en_US' ),
|
||||
get_available_languages()
|
||||
);
|
||||
}
|
||||
|
||||
$previous_locale = determine_locale();
|
||||
|
||||
$do_switch_locale = (
|
||||
$locale !== $previous_locale &&
|
||||
in_array( $locale, $available_locales, true ) &&
|
||||
in_array( $previous_locale, $available_locales, true )
|
||||
);
|
||||
|
||||
if ( $do_switch_locale ) {
|
||||
wpcf7_unload_textdomain();
|
||||
switch_to_locale( $locale );
|
||||
wpcf7_load_textdomain( $locale );
|
||||
}
|
||||
|
||||
$result = call_user_func( $callback, ...$args );
|
||||
|
||||
if ( $do_switch_locale ) {
|
||||
wpcf7_unload_textdomain( true );
|
||||
restore_previous_locale();
|
||||
wpcf7_load_textdomain( $previous_locale );
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
198
wp-content/plugins/contact-form-7/includes/mail-tag.php
Normal file
@@ -0,0 +1,198 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Class that represents a mail-tag.
|
||||
*/
|
||||
class WPCF7_MailTag {
|
||||
|
||||
private $tag;
|
||||
private $tagname = '';
|
||||
private $name = '';
|
||||
private $options = array();
|
||||
private $values = array();
|
||||
private $form_tag = null;
|
||||
|
||||
|
||||
/**
|
||||
* The constructor method.
|
||||
*/
|
||||
public function __construct( $tag, $tagname, $values ) {
|
||||
$this->tag = $tag;
|
||||
$this->name = $this->tagname = $tagname;
|
||||
|
||||
$this->options = array(
|
||||
'do_not_heat' => false,
|
||||
'format' => '',
|
||||
);
|
||||
|
||||
if ( ! empty( $values ) ) {
|
||||
preg_match_all( '/"[^"]*"|\'[^\']*\'/', $values, $matches );
|
||||
$this->values = wpcf7_strip_quote_deep( $matches[0] );
|
||||
}
|
||||
|
||||
if ( preg_match( '/^_raw_(.+)$/', $tagname, $matches ) ) {
|
||||
$this->name = trim( $matches[1] );
|
||||
$this->options['do_not_heat'] = true;
|
||||
}
|
||||
|
||||
if ( preg_match( '/^_format_(.+)$/', $tagname, $matches ) ) {
|
||||
$this->name = trim( $matches[1] );
|
||||
$this->options['format'] = $this->values[0];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the name part of this mail-tag.
|
||||
*/
|
||||
public function tag_name() {
|
||||
return $this->tagname;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the form field name corresponding to this mail-tag.
|
||||
*/
|
||||
public function field_name() {
|
||||
return strtr( $this->name, '.', '_' );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the value of the specified option.
|
||||
*/
|
||||
public function get_option( $option ) {
|
||||
return $this->options[$option];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the values part of this mail-tag.
|
||||
*/
|
||||
public function values() {
|
||||
return $this->values;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the WPCF7_FormTag object that corresponds to this mail-tag.
|
||||
*/
|
||||
public function corresponding_form_tag() {
|
||||
if ( $this->form_tag instanceof WPCF7_FormTag ) {
|
||||
return $this->form_tag;
|
||||
}
|
||||
|
||||
if ( $submission = WPCF7_Submission::get_instance() ) {
|
||||
$contact_form = $submission->get_contact_form();
|
||||
|
||||
$tags = $contact_form->scan_form_tags( array(
|
||||
'name' => $this->field_name(),
|
||||
'feature' => '! zero-controls-container',
|
||||
) );
|
||||
|
||||
if ( $tags ) {
|
||||
$this->form_tag = $tags[0];
|
||||
}
|
||||
}
|
||||
|
||||
return $this->form_tag;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
use Contactable\SWV;
|
||||
|
||||
/**
|
||||
* Mail-tag output calculator.
|
||||
*/
|
||||
class WPCF7_MailTag_OutputCalculator {
|
||||
|
||||
const email = 0b100;
|
||||
const text = 0b010;
|
||||
const blank = 0b001;
|
||||
|
||||
private $contact_form;
|
||||
|
||||
public function __construct( WPCF7_ContactForm $contact_form ) {
|
||||
$this->contact_form = $contact_form;
|
||||
}
|
||||
|
||||
public function calc_output( WPCF7_MailTag $mail_tag ) {
|
||||
return $this->calc_swv_result(
|
||||
$mail_tag,
|
||||
$this->contact_form->get_schema()
|
||||
);
|
||||
}
|
||||
|
||||
private function calc_swv_result( WPCF7_MailTag $mail_tag, SWV\Rule $rule ) {
|
||||
|
||||
if ( $rule instanceof SWV\AnyRule ) {
|
||||
$result = 0b000;
|
||||
|
||||
foreach ( $rule->rules() as $child_rule ) {
|
||||
$result |= $this->calc_swv_result( $mail_tag, $child_rule );
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
if ( $rule instanceof SWV\CompositeRule ) {
|
||||
$result = 0b111;
|
||||
|
||||
foreach ( $rule->rules() as $child_rule ) {
|
||||
$result &= $this->calc_swv_result( $mail_tag, $child_rule );
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
$field_prop = $rule->get_property( 'field' );
|
||||
|
||||
if ( empty( $field_prop ) or $field_prop !== $mail_tag->field_name() ) {
|
||||
return self::email | self::text | self::blank;
|
||||
}
|
||||
|
||||
if ( $rule instanceof SWV\RequiredRule ) {
|
||||
return ~ self::blank;
|
||||
}
|
||||
|
||||
if ( $rule instanceof SWV\EmailRule ) {
|
||||
return self::email | self::blank;
|
||||
}
|
||||
|
||||
if ( $rule instanceof SWV\EnumRule ) {
|
||||
$acceptable_values = (array) $rule->get_property( 'accept' );
|
||||
$acceptable_values = array_map( 'strval', $acceptable_values );
|
||||
$acceptable_values = array_filter( $acceptable_values );
|
||||
$acceptable_values = array_unique( $acceptable_values );
|
||||
|
||||
if ( ! $mail_tag->get_option( 'do_not_heat' ) ) {
|
||||
$pipes = $this->contact_form->get_pipes(
|
||||
$mail_tag->field_name()
|
||||
);
|
||||
|
||||
$acceptable_values = array_map(
|
||||
static function ( $val ) use ( $pipes ) {
|
||||
return $pipes->do_pipe( $val );
|
||||
},
|
||||
$acceptable_values
|
||||
);
|
||||
}
|
||||
|
||||
$email_values = array_filter(
|
||||
$acceptable_values,
|
||||
'wpcf7_is_mailbox_list'
|
||||
);
|
||||
|
||||
if ( count( $email_values ) === count( $acceptable_values ) ) {
|
||||
return self::email | self::blank;
|
||||
} else {
|
||||
return self::email | self::text | self::blank;
|
||||
}
|
||||
}
|
||||
|
||||
return self::email | self::text | self::blank;
|
||||
}
|
||||
|
||||
}
|
||||
632
wp-content/plugins/contact-form-7/includes/mail.php
Normal file
@@ -0,0 +1,632 @@
|
||||
<?php
|
||||
|
||||
add_filter( 'wpcf7_mail_html_body', 'wpcf7_mail_html_body_autop', 10, 1 );
|
||||
|
||||
/**
|
||||
* Filter callback that applies auto-p to HTML email message body.
|
||||
*/
|
||||
function wpcf7_mail_html_body_autop( $body ) {
|
||||
if ( wpcf7_autop_or_not( array( 'for' => 'mail' ) ) ) {
|
||||
$body = wpcf7_autop( $body );
|
||||
}
|
||||
|
||||
return $body;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Class that represents an attempt to compose and send email.
|
||||
*/
|
||||
class WPCF7_Mail {
|
||||
|
||||
private static $current = null;
|
||||
|
||||
private $name = '';
|
||||
private $locale = '';
|
||||
private $template = array();
|
||||
private $component = '';
|
||||
private $use_html = false;
|
||||
private $exclude_blank = false;
|
||||
|
||||
|
||||
/**
|
||||
* Returns the singleton instance of this class.
|
||||
*/
|
||||
public static function get_current() {
|
||||
return self::$current;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the name of the email template currently processed.
|
||||
*
|
||||
* Expected output: 'mail' or 'mail_2'
|
||||
*/
|
||||
public static function get_current_template_name() {
|
||||
$current = self::get_current();
|
||||
|
||||
if ( $current instanceof self ) {
|
||||
return $current->get_template_name();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the name of the email template component currently processed.
|
||||
*
|
||||
* Expected output: 'recipient', 'sender', 'subject',
|
||||
* 'additional_headers', 'body', or 'attachments'
|
||||
*/
|
||||
public static function get_current_component_name() {
|
||||
$current = self::get_current();
|
||||
|
||||
if ( $current instanceof self ) {
|
||||
return $current->get_component_name();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Composes and sends email based on the specified template.
|
||||
*
|
||||
* @param array $template Array of email template.
|
||||
* @param string $name Optional name of the template, such as
|
||||
* 'mail' or 'mail_2'. Default empty string.
|
||||
* @return bool Whether the email was sent successfully.
|
||||
*/
|
||||
public static function send( $template, $name = '' ) {
|
||||
self::$current = new self( $name, $template );
|
||||
return self::$current->compose();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The constructor method.
|
||||
*
|
||||
* @param string $name The name of the email template.
|
||||
* Such as 'mail' or 'mail_2'.
|
||||
* @param array $template Array of email template.
|
||||
*/
|
||||
private function __construct( $name, $template ) {
|
||||
$this->name = trim( $name );
|
||||
$this->use_html = ! empty( $template['use_html'] );
|
||||
$this->exclude_blank = ! empty( $template['exclude_blank'] );
|
||||
|
||||
$this->template = wp_parse_args( $template, array(
|
||||
'subject' => '',
|
||||
'sender' => '',
|
||||
'body' => '',
|
||||
'recipient' => '',
|
||||
'additional_headers' => '',
|
||||
'attachments' => '',
|
||||
) );
|
||||
|
||||
if ( $submission = WPCF7_Submission::get_instance() ) {
|
||||
$contact_form = $submission->get_contact_form();
|
||||
$this->locale = $contact_form->locale();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the name of the email template.
|
||||
*/
|
||||
public function name() {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the name of the email template. A wrapper method of name().
|
||||
*/
|
||||
public function get_template_name() {
|
||||
return $this->name();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the name of the email template component currently processed.
|
||||
*/
|
||||
public function get_component_name() {
|
||||
return $this->component;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves a component from the email template.
|
||||
*
|
||||
* @param string $component The name of the component.
|
||||
* @param bool $replace_tags Whether to replace mail-tags
|
||||
* within the component.
|
||||
* @return string The text representation of the email component.
|
||||
*/
|
||||
public function get( $component, $replace_tags = false ) {
|
||||
$this->component = $component;
|
||||
|
||||
$use_html = ( $this->use_html && 'body' === $component );
|
||||
$exclude_blank = ( $this->exclude_blank && 'body' === $component );
|
||||
|
||||
$template = $this->template;
|
||||
$component = isset( $template[$component] ) ? $template[$component] : '';
|
||||
|
||||
if ( $replace_tags ) {
|
||||
$component = $this->replace_tags( $component, array(
|
||||
'html' => $use_html,
|
||||
'exclude_blank' => $exclude_blank,
|
||||
) );
|
||||
|
||||
if ( $use_html ) {
|
||||
// Convert <example@example.com> to <example@example.com>.
|
||||
$component = preg_replace_callback(
|
||||
'/<(.*?)>/',
|
||||
static function ( $matches ) {
|
||||
if ( is_email( $matches[1] ) ) {
|
||||
return sprintf( '<%s>', $matches[1] );
|
||||
} else {
|
||||
return $matches[0];
|
||||
}
|
||||
},
|
||||
$component
|
||||
);
|
||||
|
||||
if ( ! preg_match( '%<html[>\s].*</html>%is', $component ) ) {
|
||||
$component = $this->htmlize( $component );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->component = '';
|
||||
|
||||
return $component;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates HTML message body by adding the header and footer.
|
||||
*
|
||||
* @param string $body The body part of HTML.
|
||||
* @return string Formatted HTML.
|
||||
*/
|
||||
private function htmlize( $body ) {
|
||||
if ( $this->locale ) {
|
||||
$lang_atts = sprintf( ' %s',
|
||||
wpcf7_format_atts( array(
|
||||
'dir' => wpcf7_is_rtl( $this->locale ) ? 'rtl' : 'ltr',
|
||||
'lang' => str_replace( '_', '-', $this->locale ),
|
||||
) )
|
||||
);
|
||||
} else {
|
||||
$lang_atts = '';
|
||||
}
|
||||
|
||||
$header = apply_filters( 'wpcf7_mail_html_header',
|
||||
'<!doctype html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"' . $lang_atts . '>
|
||||
<head>
|
||||
<title>' . esc_html( $this->get( 'subject', true ) ) . '</title>
|
||||
</head>
|
||||
<body>
|
||||
',
|
||||
$this
|
||||
);
|
||||
|
||||
$body = apply_filters( 'wpcf7_mail_html_body', $body, $this );
|
||||
|
||||
$footer = apply_filters( 'wpcf7_mail_html_footer',
|
||||
'</body>
|
||||
</html>',
|
||||
$this
|
||||
);
|
||||
|
||||
return $header . $body . $footer;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Composes an email message and attempts to send it.
|
||||
*
|
||||
* @param bool $send Whether to attempt to send email. Default true.
|
||||
*/
|
||||
private function compose( $send = true ) {
|
||||
$components = array(
|
||||
'subject' => $this->get( 'subject', true ),
|
||||
'sender' => $this->get( 'sender', true ),
|
||||
'body' => $this->get( 'body', true ),
|
||||
'recipient' => $this->get( 'recipient', true ),
|
||||
'additional_headers' => $this->get( 'additional_headers', true ),
|
||||
'attachments' => $this->attachments(),
|
||||
);
|
||||
|
||||
$components = apply_filters( 'wpcf7_mail_components',
|
||||
$components, wpcf7_get_current_contact_form(), $this
|
||||
);
|
||||
|
||||
if ( ! $send ) {
|
||||
return $components;
|
||||
}
|
||||
|
||||
$subject = wpcf7_strip_newline( $components['subject'] );
|
||||
$sender = wpcf7_strip_newline( $components['sender'] );
|
||||
$recipient = wpcf7_strip_newline( $components['recipient'] );
|
||||
$body = $components['body'];
|
||||
$additional_headers = trim( $components['additional_headers'] );
|
||||
|
||||
$headers = "From: $sender\n";
|
||||
|
||||
if ( $this->use_html ) {
|
||||
$headers .= "Content-Type: text/html\n";
|
||||
$headers .= "X-WPCF7-Content-Type: text/html\n";
|
||||
} else {
|
||||
$headers .= "X-WPCF7-Content-Type: text/plain\n";
|
||||
}
|
||||
|
||||
if ( $additional_headers ) {
|
||||
$headers .= $additional_headers . "\n";
|
||||
}
|
||||
|
||||
$attachments = array_filter(
|
||||
(array) $components['attachments'],
|
||||
function ( $attachment ) {
|
||||
$path = path_join( WP_CONTENT_DIR, $attachment );
|
||||
|
||||
if ( ! wpcf7_is_file_path_in_content_dir( $path ) ) {
|
||||
wp_trigger_error(
|
||||
'',
|
||||
sprintf(
|
||||
/* translators: %s: Attachment file path. */
|
||||
__( 'Failed to attach a file. %s is not in the allowed directory.', 'contact-form-7' ),
|
||||
$path
|
||||
),
|
||||
E_USER_NOTICE
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! is_readable( $path ) or ! is_file( $path ) ) {
|
||||
wp_trigger_error(
|
||||
'',
|
||||
sprintf(
|
||||
/* translators: %s: Attachment file path. */
|
||||
__( 'Failed to attach a file. %s is not a readable file.', 'contact-form-7' ),
|
||||
$path
|
||||
),
|
||||
E_USER_NOTICE
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static $total_size = array();
|
||||
|
||||
if ( ! isset( $total_size[$this->name] ) ) {
|
||||
$total_size[$this->name] = 0;
|
||||
}
|
||||
|
||||
$file_size = (int) @filesize( $path );
|
||||
|
||||
if ( 25 * MB_IN_BYTES < $total_size[$this->name] + $file_size ) {
|
||||
wp_trigger_error(
|
||||
'',
|
||||
__( 'Failed to attach a file. The total file size exceeds the limit of 25 megabytes.', 'contact-form-7' ),
|
||||
E_USER_NOTICE
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$total_size[$this->name] += $file_size;
|
||||
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
return wp_mail( $recipient, $subject, $body, $headers, $attachments );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Replaces mail-tags within the given text.
|
||||
*/
|
||||
public function replace_tags( $content, $options = '' ) {
|
||||
if ( true === $options ) {
|
||||
$options = array( 'html' => true );
|
||||
}
|
||||
|
||||
$options = wp_parse_args( $options, array(
|
||||
'html' => false,
|
||||
'exclude_blank' => false,
|
||||
) );
|
||||
|
||||
return wpcf7_mail_replace_tags( $content, $options );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates an array of attachments based on uploaded files and local files.
|
||||
*/
|
||||
private function attachments( $template = null ) {
|
||||
if ( ! $template ) {
|
||||
$template = $this->get( 'attachments' );
|
||||
}
|
||||
|
||||
$attachments = array();
|
||||
|
||||
if ( $submission = WPCF7_Submission::get_instance() ) {
|
||||
$uploaded_files = $submission->uploaded_files();
|
||||
|
||||
foreach ( (array) $uploaded_files as $name => $paths ) {
|
||||
if ( false !== strpos( $template, "[{$name}]" ) ) {
|
||||
$attachments = array_merge( $attachments, (array) $paths );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ( explode( "\n", $template ) as $line ) {
|
||||
$line = trim( $line );
|
||||
|
||||
if ( '' === $line or '[' === substr( $line, 0, 1 ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$attachments[] = path_join( WP_CONTENT_DIR, $line );
|
||||
}
|
||||
|
||||
if ( $submission = WPCF7_Submission::get_instance() ) {
|
||||
$attachments = array_merge(
|
||||
$attachments,
|
||||
(array) $submission->extra_attachments( $this->name )
|
||||
);
|
||||
}
|
||||
|
||||
return $attachments;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Replaces all mail-tags within the given text content.
|
||||
*
|
||||
* @param string $content Text including mail-tags.
|
||||
* @param string|array $options Optional. Output options.
|
||||
* @return string Result of replacement.
|
||||
*/
|
||||
function wpcf7_mail_replace_tags( $content, $options = '' ) {
|
||||
$options = wp_parse_args( $options, array(
|
||||
'html' => false,
|
||||
'exclude_blank' => false,
|
||||
) );
|
||||
|
||||
if ( is_array( $content ) ) {
|
||||
foreach ( $content as $key => $value ) {
|
||||
$content[$key] = wpcf7_mail_replace_tags( $value, $options );
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
$content = explode( "\n", $content );
|
||||
|
||||
foreach ( $content as $num => $line ) {
|
||||
$line = new WPCF7_MailTaggedText( $line, $options );
|
||||
$replaced = $line->replace_tags();
|
||||
|
||||
if ( $options['exclude_blank'] ) {
|
||||
$replaced_tags = $line->get_replaced_tags();
|
||||
|
||||
if (
|
||||
empty( $replaced_tags ) or
|
||||
array_filter( $replaced_tags, 'strlen' )
|
||||
) {
|
||||
$content[$num] = $replaced;
|
||||
} else {
|
||||
unset( $content[$num] ); // Remove a line.
|
||||
}
|
||||
} else {
|
||||
$content[$num] = $replaced;
|
||||
}
|
||||
}
|
||||
|
||||
$content = implode( "\n", $content );
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
|
||||
add_action( 'phpmailer_init', 'wpcf7_phpmailer_init', 10, 1 );
|
||||
|
||||
/**
|
||||
* Adds custom properties to the PHPMailer object.
|
||||
*/
|
||||
function wpcf7_phpmailer_init( $phpmailer ) {
|
||||
$custom_headers = $phpmailer->getCustomHeaders();
|
||||
$phpmailer->clearCustomHeaders();
|
||||
$wpcf7_content_type = false;
|
||||
|
||||
foreach ( (array) $custom_headers as $custom_header ) {
|
||||
$name = $custom_header[0];
|
||||
$value = $custom_header[1];
|
||||
|
||||
if ( 'X-WPCF7-Content-Type' === $name ) {
|
||||
$wpcf7_content_type = trim( $value );
|
||||
} else {
|
||||
$phpmailer->addCustomHeader( $name, $value );
|
||||
}
|
||||
}
|
||||
|
||||
if ( 'text/html' === $wpcf7_content_type ) {
|
||||
$phpmailer->msgHTML( $phpmailer->Body );
|
||||
} elseif ( 'text/plain' === $wpcf7_content_type ) {
|
||||
$phpmailer->AltBody = '';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Class that represents a single-line text including mail-tags.
|
||||
*/
|
||||
class WPCF7_MailTaggedText {
|
||||
|
||||
private $html = false;
|
||||
private $callback = null;
|
||||
private $content = '';
|
||||
private $replaced_tags = array();
|
||||
|
||||
|
||||
/**
|
||||
* The constructor method.
|
||||
*/
|
||||
public function __construct( $content, $options = '' ) {
|
||||
$options = wp_parse_args( $options, array(
|
||||
'html' => false,
|
||||
'callback' => null,
|
||||
) );
|
||||
|
||||
$this->html = (bool) $options['html'];
|
||||
|
||||
if (
|
||||
null !== $options['callback'] and
|
||||
is_callable( $options['callback'] )
|
||||
) {
|
||||
$this->callback = $options['callback'];
|
||||
} elseif ( $this->html ) {
|
||||
$this->callback = array( $this, 'replace_tags_callback_html' );
|
||||
} else {
|
||||
$this->callback = array( $this, 'replace_tags_callback' );
|
||||
}
|
||||
|
||||
$this->content = $content;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves mail-tags that have been replaced by this instance.
|
||||
*
|
||||
* @return array List of mail-tags replaced.
|
||||
*/
|
||||
public function get_replaced_tags() {
|
||||
return $this->replaced_tags;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Replaces mail-tags based on regexp.
|
||||
*/
|
||||
public function replace_tags() {
|
||||
$regex = '/(\[?)\[[\t ]*'
|
||||
. '([a-zA-Z_][0-9a-zA-Z:._-]*)' // [2] = name
|
||||
. '((?:[\t ]+"[^"]*"|[\t ]+\'[^\']*\')*)' // [3] = values
|
||||
. '[\t ]*\](\]?)/';
|
||||
|
||||
return preg_replace_callback( $regex, $this->callback, $this->content );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Callback function for replacement. For HTML message body.
|
||||
*/
|
||||
private function replace_tags_callback_html( $matches ) {
|
||||
return $this->replace_tags_callback( $matches, true );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Callback function for replacement.
|
||||
*/
|
||||
private function replace_tags_callback( $matches, $html = false ) {
|
||||
// allow [[foo]] syntax for escaping a tag
|
||||
if ( '[' === $matches[1] and ']' === $matches[4] ) {
|
||||
return substr( $matches[0], 1, -1 );
|
||||
}
|
||||
|
||||
$tag = $matches[0];
|
||||
$tagname = $matches[2];
|
||||
$values = $matches[3];
|
||||
|
||||
$mail_tag = new WPCF7_MailTag( $tag, $tagname, $values );
|
||||
$field_name = $mail_tag->field_name();
|
||||
|
||||
$submission = WPCF7_Submission::get_instance();
|
||||
$submitted = $submission
|
||||
? $submission->get_posted_data( $field_name )
|
||||
: null;
|
||||
|
||||
if ( $mail_tag->get_option( 'do_not_heat' ) ) {
|
||||
$submitted = wpcf7_superglobal_post( $field_name );
|
||||
}
|
||||
|
||||
$replaced = $submitted;
|
||||
|
||||
if ( null !== $replaced ) {
|
||||
if ( $format = $mail_tag->get_option( 'format' ) ) {
|
||||
$replaced = $this->format( $replaced, $format );
|
||||
}
|
||||
|
||||
$separator = ( 'body' === WPCF7_Mail::get_current_component_name() )
|
||||
? wp_get_list_item_separator()
|
||||
: ', ';
|
||||
|
||||
$replaced = wpcf7_flat_join( $replaced, array(
|
||||
'separator' => $separator,
|
||||
) );
|
||||
|
||||
if ( $html ) {
|
||||
$replaced = esc_html( $replaced );
|
||||
$replaced = wptexturize( $replaced );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $form_tag = $mail_tag->corresponding_form_tag() ) {
|
||||
$type = $form_tag->type;
|
||||
|
||||
$replaced = apply_filters(
|
||||
"wpcf7_mail_tag_replaced_{$type}", $replaced,
|
||||
$submitted, $html, $mail_tag
|
||||
);
|
||||
}
|
||||
|
||||
$replaced = apply_filters(
|
||||
'wpcf7_mail_tag_replaced', $replaced,
|
||||
$submitted, $html, $mail_tag
|
||||
);
|
||||
|
||||
if ( null !== $replaced ) {
|
||||
$replaced = trim( $replaced );
|
||||
|
||||
$this->replaced_tags[$tag] = $replaced;
|
||||
return $replaced;
|
||||
}
|
||||
|
||||
$special = apply_filters( 'wpcf7_special_mail_tags', null,
|
||||
$mail_tag->tag_name(), $html, $mail_tag
|
||||
);
|
||||
|
||||
if ( null !== $special ) {
|
||||
$this->replaced_tags[$tag] = $special;
|
||||
return $special;
|
||||
}
|
||||
|
||||
return $tag;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Formats string based on the formatting option in the form-tag.
|
||||
*/
|
||||
public function format( $original, $format ) {
|
||||
$original = (array) $original;
|
||||
|
||||
foreach ( $original as $key => $value ) {
|
||||
if ( preg_match( '/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/', $value ) ) {
|
||||
$datetime = date_create( $value, wp_timezone() );
|
||||
|
||||
if ( false !== $datetime ) {
|
||||
$original[$key] = wp_date( $format, $datetime->getTimestamp() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $original;
|
||||
}
|
||||
|
||||
}
|
||||