├── .gitignore
├── .travis.yml
├── Gruntfile.js
├── LICENSE
├── README.md
├── bin
└── install-wp-tests.sh
├── composer.json
├── composer.lock
├── lightweight-term-count-update.php
├── multisite.xml
├── package.json
├── phpcs.ruleset.xml
├── phpunit.xml.dist
├── readme.txt
└── tests
├── bootstrap.php
└── test-term-counting.php
/.gitignore:
--------------------------------------------------------------------------------
1 | /vendor/
2 | /.phpunit.result.cache
3 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: false
2 |
3 | language: php
4 |
5 | notifications:
6 | email:
7 | on_success: never
8 | on_failure: change
9 |
10 | branches:
11 | only:
12 | - master
13 | - develop
14 |
15 | matrix:
16 | include:
17 | - php: 5.6
18 | env: WP_VERSION=latest PHP_LINT=1
19 | - php: 7.0
20 | env: WP_VERSION=latest PHP_LINT=1
21 | - php: 7.1
22 | env: WP_VERSION=latest PHP_LINT=1
23 | - php: 7.2
24 | env: WP_VERSION=latest PHP_LINT=1 WP_PHPCS=1
25 | - php: 7.2
26 | env: WP_VERSION=nightly WP_TEST_OBJECT_CACHE=1
27 | - php: 7.3
28 | env: WP_VERSION=nightly PHP_LINT=1
29 | fast_finish: true
30 |
31 | cache:
32 | - composer
33 | - $HOME/.composer/cache
34 |
35 | before_script:
36 | - |
37 | if [[ ! -z "$WP_VERSION" ]] ; then
38 | bash bin/install-wp-tests.sh wordpress_test root '' localhost $WP_VERSION
39 | fi
40 | - |
41 | if [[ "$WP_TEST_OBJECT_CACHE" == "1" ]]; then
42 | WP_CORE_DIR=${WP_CORE_DIR-/tmp/wordpress/}
43 | curl https://raw.githubusercontent.com/tollmanz/wordpress-pecl-memcached-object-cache/584392b56dc4adbe52bd2c7b86f875e23a3e5f75/object-cache.php > $WP_CORE_DIR/wp-content/object-cache.php
44 | ls -la $WP_CORE_DIR/wp-content/
45 | echo "extension = memcached.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
46 | fi
47 | - export PATH="$HOME/.composer/vendor/bin:$PATH"
48 | - |
49 | if [[ ${TRAVIS_PHP_VERSION:0:2} == "7." ]]; then
50 | composer global require "phpunit/phpunit=5.7.*"
51 | else
52 | composer global require "phpunit/phpunit=4.8.*"
53 | fi
54 | - |
55 | if [[ "$WP_PHPCS" == "1" ]]; then
56 | composer global require wp-coding-standards/wpcs
57 | phpcs --config-set installed_paths $HOME/.composer/vendor/wp-coding-standards/wpcs
58 | fi
59 | - phpunit --version
60 |
61 | script:
62 | - if [[ "$PHP_LINT" == "1" ]]; then find . -type "f" -iname "*.php" | xargs -L "1" php -l; fi
63 | - if [[ "$WP_PHPCS" == "1" ]]; then phpcs -n --standard=phpcs.ruleset.xml lightweight-term-count-update.php; fi
64 | - phpunit
65 | - phpunit -c multisite.xml
66 |
--------------------------------------------------------------------------------
/Gruntfile.js:
--------------------------------------------------------------------------------
1 | module.exports = function( grunt ) {
2 |
3 | 'use strict';
4 | var banner = '/**\n * <%= pkg.homepage %>\n * Copyright (c) <%= grunt.template.today("yyyy") %>\n * This file is generated automatically. Do not edit.\n */\n';
5 | // Project configuration
6 | grunt.initConfig( {
7 |
8 | pkg: grunt.file.readJSON( 'package.json' ),
9 |
10 | addtextdomain: {
11 | options: {
12 | textdomain: 'lightweight-term-count-update',
13 | },
14 | target: {
15 | files: {
16 | src: [ '*.php', '**/*.php', '!node_modules/**', '!php-tests/**', '!bin/**' ]
17 | }
18 | }
19 | },
20 |
21 | wp_readme_to_markdown: {
22 | your_target: {
23 | files: {
24 | 'README.md': 'readme.txt'
25 | }
26 | },
27 | },
28 |
29 | makepot: {
30 | target: {
31 | options: {
32 | domainPath: '/languages',
33 | mainFile: 'lightweight-term-count-update.php',
34 | potFilename: 'lightweight-term-count-update.pot',
35 | potHeaders: {
36 | poedit: true,
37 | 'x-poedit-keywordslist': true
38 | },
39 | type: 'wp-plugin',
40 | updateTimestamp: true
41 | }
42 | }
43 | },
44 | } );
45 |
46 | grunt.loadNpmTasks( 'grunt-wp-i18n' );
47 | grunt.loadNpmTasks( 'grunt-wp-readme-to-markdown' );
48 | grunt.registerTask( 'i18n', ['addtextdomain', 'makepot'] );
49 | grunt.registerTask( 'readme', ['wp_readme_to_markdown'] );
50 |
51 | grunt.util.linefeed = '\n';
52 |
53 | };
54 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 2, June 1991
3 |
4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6 | Everyone is permitted to copy and distribute verbatim copies
7 | of this license document, but changing it is not allowed.
8 |
9 | Preamble
10 |
11 | The licenses for most software are designed to take away your
12 | freedom to share and change it. By contrast, the GNU General Public
13 | License is intended to guarantee your freedom to share and change free
14 | software--to make sure the software is free for all its users. This
15 | General Public License applies to most of the Free Software
16 | Foundation's software and to any other program whose authors commit to
17 | using it. (Some other Free Software Foundation software is covered by
18 | the GNU Lesser General Public License instead.) You can apply it to
19 | your programs, too.
20 |
21 | When we speak of free software, we are referring to freedom, not
22 | price. Our General Public Licenses are designed to make sure that you
23 | have the freedom to distribute copies of free software (and charge for
24 | this service if you wish), that you receive source code or can get it
25 | if you want it, that you can change the software or use pieces of it
26 | in new free programs; and that you know you can do these things.
27 |
28 | To protect your rights, we need to make restrictions that forbid
29 | anyone to deny you these rights or to ask you to surrender the rights.
30 | These restrictions translate to certain responsibilities for you if you
31 | distribute copies of the software, or if you modify it.
32 |
33 | For example, if you distribute copies of such a program, whether
34 | gratis or for a fee, you must give the recipients all the rights that
35 | you have. You must make sure that they, too, receive or can get the
36 | source code. And you must show them these terms so they know their
37 | rights.
38 |
39 | We protect your rights with two steps: (1) copyright the software, and
40 | (2) offer you this license which gives you legal permission to copy,
41 | distribute and/or modify the software.
42 |
43 | Also, for each author's protection and ours, we want to make certain
44 | that everyone understands that there is no warranty for this free
45 | software. If the software is modified by someone else and passed on, we
46 | want its recipients to know that what they have is not the original, so
47 | that any problems introduced by others will not reflect on the original
48 | authors' reputations.
49 |
50 | Finally, any free program is threatened constantly by software
51 | patents. We wish to avoid the danger that redistributors of a free
52 | program will individually obtain patent licenses, in effect making the
53 | program proprietary. To prevent this, we have made it clear that any
54 | patent must be licensed for everyone's free use or not licensed at all.
55 |
56 | The precise terms and conditions for copying, distribution and
57 | modification follow.
58 |
59 | GNU GENERAL PUBLIC LICENSE
60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61 |
62 | 0. This License applies to any program or other work which contains
63 | a notice placed by the copyright holder saying it may be distributed
64 | under the terms of this General Public License. The "Program", below,
65 | refers to any such program or work, and a "work based on the Program"
66 | means either the Program or any derivative work under copyright law:
67 | that is to say, a work containing the Program or a portion of it,
68 | either verbatim or with modifications and/or translated into another
69 | language. (Hereinafter, translation is included without limitation in
70 | the term "modification".) Each licensee is addressed as "you".
71 |
72 | Activities other than copying, distribution and modification are not
73 | covered by this License; they are outside its scope. The act of
74 | running the Program is not restricted, and the output from the Program
75 | is covered only if its contents constitute a work based on the
76 | Program (independent of having been made by running the Program).
77 | Whether that is true depends on what the Program does.
78 |
79 | 1. You may copy and distribute verbatim copies of the Program's
80 | source code as you receive it, in any medium, provided that you
81 | conspicuously and appropriately publish on each copy an appropriate
82 | copyright notice and disclaimer of warranty; keep intact all the
83 | notices that refer to this License and to the absence of any warranty;
84 | and give any other recipients of the Program a copy of this License
85 | along with the Program.
86 |
87 | You may charge a fee for the physical act of transferring a copy, and
88 | you may at your option offer warranty protection in exchange for a fee.
89 |
90 | 2. You may modify your copy or copies of the Program or any portion
91 | of it, thus forming a work based on the Program, and copy and
92 | distribute such modifications or work under the terms of Section 1
93 | above, provided that you also meet all of these conditions:
94 |
95 | a) You must cause the modified files to carry prominent notices
96 | stating that you changed the files and the date of any change.
97 |
98 | b) You must cause any work that you distribute or publish, that in
99 | whole or in part contains or is derived from the Program or any
100 | part thereof, to be licensed as a whole at no charge to all third
101 | parties under the terms of this License.
102 |
103 | c) If the modified program normally reads commands interactively
104 | when run, you must cause it, when started running for such
105 | interactive use in the most ordinary way, to print or display an
106 | announcement including an appropriate copyright notice and a
107 | notice that there is no warranty (or else, saying that you provide
108 | a warranty) and that users may redistribute the program under
109 | these conditions, and telling the user how to view a copy of this
110 | License. (Exception: if the Program itself is interactive but
111 | does not normally print such an announcement, your work based on
112 | the Program is not required to print an announcement.)
113 |
114 | These requirements apply to the modified work as a whole. If
115 | identifiable sections of that work are not derived from the Program,
116 | and can be reasonably considered independent and separate works in
117 | themselves, then this License, and its terms, do not apply to those
118 | sections when you distribute them as separate works. But when you
119 | distribute the same sections as part of a whole which is a work based
120 | on the Program, the distribution of the whole must be on the terms of
121 | this License, whose permissions for other licensees extend to the
122 | entire whole, and thus to each and every part regardless of who wrote it.
123 |
124 | Thus, it is not the intent of this section to claim rights or contest
125 | your rights to work written entirely by you; rather, the intent is to
126 | exercise the right to control the distribution of derivative or
127 | collective works based on the Program.
128 |
129 | In addition, mere aggregation of another work not based on the Program
130 | with the Program (or with a work based on the Program) on a volume of
131 | a storage or distribution medium does not bring the other work under
132 | the scope of this License.
133 |
134 | 3. You may copy and distribute the Program (or a work based on it,
135 | under Section 2) in object code or executable form under the terms of
136 | Sections 1 and 2 above provided that you also do one of the following:
137 |
138 | a) Accompany it with the complete corresponding machine-readable
139 | source code, which must be distributed under the terms of Sections
140 | 1 and 2 above on a medium customarily used for software interchange; or,
141 |
142 | b) Accompany it with a written offer, valid for at least three
143 | years, to give any third party, for a charge no more than your
144 | cost of physically performing source distribution, a complete
145 | machine-readable copy of the corresponding source code, to be
146 | distributed under the terms of Sections 1 and 2 above on a medium
147 | customarily used for software interchange; or,
148 |
149 | c) Accompany it with the information you received as to the offer
150 | to distribute corresponding source code. (This alternative is
151 | allowed only for noncommercial distribution and only if you
152 | received the program in object code or executable form with such
153 | an offer, in accord with Subsection b above.)
154 |
155 | The source code for a work means the preferred form of the work for
156 | making modifications to it. For an executable work, complete source
157 | code means all the source code for all modules it contains, plus any
158 | associated interface definition files, plus the scripts used to
159 | control compilation and installation of the executable. However, as a
160 | special exception, the source code distributed need not include
161 | anything that is normally distributed (in either source or binary
162 | form) with the major components (compiler, kernel, and so on) of the
163 | operating system on which the executable runs, unless that component
164 | itself accompanies the executable.
165 |
166 | If distribution of executable or object code is made by offering
167 | access to copy from a designated place, then offering equivalent
168 | access to copy the source code from the same place counts as
169 | distribution of the source code, even though third parties are not
170 | compelled to copy the source along with the object code.
171 |
172 | 4. You may not copy, modify, sublicense, or distribute the Program
173 | except as expressly provided under this License. Any attempt
174 | otherwise to copy, modify, sublicense or distribute the Program is
175 | void, and will automatically terminate your rights under this License.
176 | However, parties who have received copies, or rights, from you under
177 | this License will not have their licenses terminated so long as such
178 | parties remain in full compliance.
179 |
180 | 5. You are not required to accept this License, since you have not
181 | signed it. However, nothing else grants you permission to modify or
182 | distribute the Program or its derivative works. These actions are
183 | prohibited by law if you do not accept this License. Therefore, by
184 | modifying or distributing the Program (or any work based on the
185 | Program), you indicate your acceptance of this License to do so, and
186 | all its terms and conditions for copying, distributing or modifying
187 | the Program or works based on it.
188 |
189 | 6. Each time you redistribute the Program (or any work based on the
190 | Program), the recipient automatically receives a license from the
191 | original licensor to copy, distribute or modify the Program subject to
192 | these terms and conditions. You may not impose any further
193 | restrictions on the recipients' exercise of the rights granted herein.
194 | You are not responsible for enforcing compliance by third parties to
195 | this License.
196 |
197 | 7. If, as a consequence of a court judgment or allegation of patent
198 | infringement or for any other reason (not limited to patent issues),
199 | conditions are imposed on you (whether by court order, agreement or
200 | otherwise) that contradict the conditions of this License, they do not
201 | excuse you from the conditions of this License. If you cannot
202 | distribute so as to satisfy simultaneously your obligations under this
203 | License and any other pertinent obligations, then as a consequence you
204 | may not distribute the Program at all. For example, if a patent
205 | license would not permit royalty-free redistribution of the Program by
206 | all those who receive copies directly or indirectly through you, then
207 | the only way you could satisfy both it and this License would be to
208 | refrain entirely from distribution of the Program.
209 |
210 | If any portion of this section is held invalid or unenforceable under
211 | any particular circumstance, the balance of the section is intended to
212 | apply and the section as a whole is intended to apply in other
213 | circumstances.
214 |
215 | It is not the purpose of this section to induce you to infringe any
216 | patents or other property right claims or to contest validity of any
217 | such claims; this section has the sole purpose of protecting the
218 | integrity of the free software distribution system, which is
219 | implemented by public license practices. Many people have made
220 | generous contributions to the wide range of software distributed
221 | through that system in reliance on consistent application of that
222 | system; it is up to the author/donor to decide if he or she is willing
223 | to distribute software through any other system and a licensee cannot
224 | impose that choice.
225 |
226 | This section is intended to make thoroughly clear what is believed to
227 | be a consequence of the rest of this License.
228 |
229 | 8. If the distribution and/or use of the Program is restricted in
230 | certain countries either by patents or by copyrighted interfaces, the
231 | original copyright holder who places the Program under this License
232 | may add an explicit geographical distribution limitation excluding
233 | those countries, so that distribution is permitted only in or among
234 | countries not thus excluded. In such case, this License incorporates
235 | the limitation as if written in the body of this License.
236 |
237 | 9. The Free Software Foundation may publish revised and/or new versions
238 | of the General Public License from time to time. Such new versions will
239 | be similar in spirit to the present version, but may differ in detail to
240 | address new problems or concerns.
241 |
242 | Each version is given a distinguishing version number. If the Program
243 | specifies a version number of this License which applies to it and "any
244 | later version", you have the option of following the terms and conditions
245 | either of that version or of any later version published by the Free
246 | Software Foundation. If the Program does not specify a version number of
247 | this License, you may choose any version ever published by the Free Software
248 | Foundation.
249 |
250 | 10. If you wish to incorporate parts of the Program into other free
251 | programs whose distribution conditions are different, write to the author
252 | to ask for permission. For software which is copyrighted by the Free
253 | Software Foundation, write to the Free Software Foundation; we sometimes
254 | make exceptions for this. Our decision will be guided by the two goals
255 | of preserving the free status of all derivatives of our free software and
256 | of promoting the sharing and reuse of software generally.
257 |
258 | NO WARRANTY
259 |
260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268 | REPAIR OR CORRECTION.
269 |
270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278 | POSSIBILITY OF SUCH DAMAGES.
279 |
280 | END OF TERMS AND CONDITIONS
281 |
282 | How to Apply These Terms to Your New Programs
283 |
284 | If you develop a new program, and you want it to be of the greatest
285 | possible use to the public, the best way to achieve this is to make it
286 | free software which everyone can redistribute and change under these terms.
287 |
288 | To do so, attach the following notices to the program. It is safest
289 | to attach them to the start of each source file to most effectively
290 | convey the exclusion of warranty; and each file should have at least
291 | the "copyright" line and a pointer to where the full notice is found.
292 |
293 | {description}
294 | Copyright (C) {year} {fullname}
295 |
296 | This program is free software; you can redistribute it and/or modify
297 | it under the terms of the GNU General Public License as published by
298 | the Free Software Foundation; either version 2 of the License, or
299 | (at your option) any later version.
300 |
301 | This program is distributed in the hope that it will be useful,
302 | but WITHOUT ANY WARRANTY; without even the implied warranty of
303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304 | GNU General Public License for more details.
305 |
306 | You should have received a copy of the GNU General Public License along
307 | with this program; if not, write to the Free Software Foundation, Inc.,
308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
309 |
310 | Also add information on how to contact you by electronic and paper mail.
311 |
312 | If the program is interactive, make it output a short notice like this
313 | when it starts in an interactive mode:
314 |
315 | Gnomovision version 69, Copyright (C) year name of author
316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317 | This is free software, and you are welcome to redistribute it
318 | under certain conditions; type `show c' for details.
319 |
320 | The hypothetical commands `show w' and `show c' should show the appropriate
321 | parts of the General Public License. Of course, the commands you use may
322 | be called something other than `show w' and `show c'; they could even be
323 | mouse-clicks or menu items--whatever suits your program.
324 |
325 | You should also get your employer (if you work as a programmer) or your
326 | school, if any, to sign a "copyright disclaimer" for the program, if
327 | necessary. Here is a sample; alter the names:
328 |
329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330 | `Gnomovision' (which makes passes at compilers) written by James Hacker.
331 |
332 | {signature of Ty Coon}, 1 April 1989
333 | Ty Coon, President of Vice
334 |
335 | This General Public License does not permit incorporating your program into
336 | proprietary programs. If your program is a subroutine library, you may
337 | consider it more useful to permit linking proprietary applications with the
338 | library. If this is what you want to do, use the GNU Lesser General
339 | Public License instead of this License.
340 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Lightweight Term Count Update
2 |
3 | This plugin prevents WordPress from running term count queries.
4 |
5 | Rather, it will instead perform a simple increment/decrement on the post count that does not require a recalculation.
--------------------------------------------------------------------------------
/bin/install-wp-tests.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | if [ $# -lt 3 ]; then
4 | echo "usage: $0 [db-host] [wp-version] [skip-database-creation]"
5 | exit 1
6 | fi
7 |
8 | DB_NAME=$1
9 | DB_USER=$2
10 | DB_PASS=$3
11 | DB_HOST=${4-localhost}
12 | WP_VERSION=${5-latest}
13 | SKIP_DB_CREATE=${6-false}
14 |
15 | WP_TESTS_DIR=${WP_TESTS_DIR-/tmp/wordpress-tests-lib}
16 | WP_CORE_DIR=${WP_CORE_DIR-/tmp/wordpress/}
17 |
18 | download() {
19 | if [ `which curl` ]; then
20 | curl -s "$1" > "$2";
21 | elif [ `which wget` ]; then
22 | wget -nv -O "$2" "$1"
23 | fi
24 | }
25 |
26 | if [[ $WP_VERSION =~ [0-9]+\.[0-9]+(\.[0-9]+)? ]]; then
27 | WP_TESTS_TAG="tags/$WP_VERSION"
28 | elif [[ $WP_VERSION == 'nightly' || $WP_VERSION == 'trunk' ]]; then
29 | WP_TESTS_TAG="trunk"
30 | else
31 | # http serves a single offer, whereas https serves multiple. we only want one
32 | download http://api.wordpress.org/core/version-check/1.7/ /tmp/wp-latest.json
33 | grep '[0-9]+\.[0-9]+(\.[0-9]+)?' /tmp/wp-latest.json
34 | LATEST_VERSION=$(grep -o '"version":"[^"]*' /tmp/wp-latest.json | sed 's/"version":"//')
35 | if [[ -z "$LATEST_VERSION" ]]; then
36 | echo "Latest WordPress version could not be found"
37 | exit 1
38 | fi
39 | WP_TESTS_TAG="tags/$LATEST_VERSION"
40 | fi
41 |
42 | set -ex
43 |
44 | install_wp() {
45 |
46 | if [ -d $WP_CORE_DIR ]; then
47 | return;
48 | fi
49 |
50 | mkdir -p $WP_CORE_DIR
51 |
52 | if [[ $WP_VERSION == 'nightly' || $WP_VERSION == 'trunk' ]]; then
53 | mkdir -p /tmp/wordpress-nightly
54 | download https://wordpress.org/nightly-builds/wordpress-latest.zip /tmp/wordpress-nightly/wordpress-nightly.zip
55 | unzip -q /tmp/wordpress-nightly/wordpress-nightly.zip -d /tmp/wordpress-nightly/
56 | mv /tmp/wordpress-nightly/wordpress/* $WP_CORE_DIR
57 | else
58 | if [ $WP_VERSION == 'latest' ]; then
59 | local ARCHIVE_NAME='latest'
60 | else
61 | local ARCHIVE_NAME="wordpress-$WP_VERSION"
62 | fi
63 | download https://wordpress.org/${ARCHIVE_NAME}.tar.gz /tmp/wordpress.tar.gz
64 | tar --strip-components=1 -zxmf /tmp/wordpress.tar.gz -C $WP_CORE_DIR
65 | fi
66 |
67 | download https://raw.github.com/markoheijnen/wp-mysqli/master/db.php $WP_CORE_DIR/wp-content/db.php
68 | }
69 |
70 | install_test_suite() {
71 | # portable in-place argument for both GNU sed and Mac OSX sed
72 | if [[ $(uname -s) == 'Darwin' ]]; then
73 | local ioption='-i .bak'
74 | else
75 | local ioption='-i'
76 | fi
77 |
78 | # set up testing suite if it doesn't yet exist
79 | if [ ! -d $WP_TESTS_DIR ]; then
80 | # set up testing suite
81 | mkdir -p $WP_TESTS_DIR
82 | svn co --quiet https://develop.svn.wordpress.org/${WP_TESTS_TAG}/tests/phpunit/includes/ $WP_TESTS_DIR/includes
83 | svn co --quiet https://develop.svn.wordpress.org/${WP_TESTS_TAG}/tests/phpunit/data/ $WP_TESTS_DIR/data
84 | fi
85 |
86 | if [ ! -f wp-tests-config.php ]; then
87 | download https://develop.svn.wordpress.org/${WP_TESTS_TAG}/wp-tests-config-sample.php "$WP_TESTS_DIR"/wp-tests-config.php
88 | # remove all forward slashes in the end
89 | WP_CORE_DIR=$(echo $WP_CORE_DIR | sed "s:/\+$::")
90 | sed $ioption "s:dirname( __FILE__ ) . '/src/':'$WP_CORE_DIR/':" "$WP_TESTS_DIR"/wp-tests-config.php
91 | sed $ioption "s/youremptytestdbnamehere/$DB_NAME/" "$WP_TESTS_DIR"/wp-tests-config.php
92 | sed $ioption "s/yourusernamehere/$DB_USER/" "$WP_TESTS_DIR"/wp-tests-config.php
93 | sed $ioption "s/yourpasswordhere/$DB_PASS/" "$WP_TESTS_DIR"/wp-tests-config.php
94 | sed $ioption "s|localhost|${DB_HOST}|" "$WP_TESTS_DIR"/wp-tests-config.php
95 | fi
96 |
97 | }
98 |
99 | install_db() {
100 |
101 | if [ ${SKIP_DB_CREATE} = "true" ]; then
102 | return 0
103 | fi
104 |
105 | # parse DB_HOST for port or socket references
106 | local PARTS=(${DB_HOST//\:/ })
107 | local DB_HOSTNAME=${PARTS[0]};
108 | local DB_SOCK_OR_PORT=${PARTS[1]};
109 | local EXTRA=""
110 |
111 | if ! [ -z $DB_HOSTNAME ] ; then
112 | if [ $(echo $DB_SOCK_OR_PORT | grep -e '^[0-9]\{1,\}$') ]; then
113 | EXTRA=" --host=$DB_HOSTNAME --port=$DB_SOCK_OR_PORT --protocol=tcp"
114 | elif ! [ -z $DB_SOCK_OR_PORT ] ; then
115 | EXTRA=" --socket=$DB_SOCK_OR_PORT"
116 | elif ! [ -z $DB_HOSTNAME ] ; then
117 | EXTRA=" --host=$DB_HOSTNAME --protocol=tcp"
118 | fi
119 | fi
120 |
121 | # create database
122 | mysqladmin create $DB_NAME --user="$DB_USER" --password="$DB_PASS"$EXTRA
123 | }
124 |
125 | install_wp
126 | install_test_suite
127 | install_db
128 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "automattic/lightweight-term-count-update",
3 | "description": "This plugin prevents WordPress from running term count queries, instead performing a simple increment/decrement on the post count.",
4 | "type": "wordpress-plugin",
5 | "license": "GPL-2.0-or-later",
6 | "require-dev": {
7 | "phpunit/phpunit": "^5.7.21 || ^7.5",
8 | "yoast/phpunit-polyfills": "^1.0"
9 | },
10 | "scripts": {
11 | "phpunit": "vendor/bin/phpunit"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/composer.lock:
--------------------------------------------------------------------------------
1 | {
2 | "_readme": [
3 | "This file locks the dependencies of your project to a known state",
4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
5 | "This file is @generated automatically"
6 | ],
7 | "content-hash": "ffabef1e39af78b54aeb044e9df073b3",
8 | "packages": [],
9 | "packages-dev": [
10 | {
11 | "name": "doctrine/instantiator",
12 | "version": "1.4.1",
13 | "source": {
14 | "type": "git",
15 | "url": "https://github.com/doctrine/instantiator.git",
16 | "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc"
17 | },
18 | "dist": {
19 | "type": "zip",
20 | "url": "https://api.github.com/repos/doctrine/instantiator/zipball/10dcfce151b967d20fde1b34ae6640712c3891bc",
21 | "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc",
22 | "shasum": ""
23 | },
24 | "require": {
25 | "php": "^7.1 || ^8.0"
26 | },
27 | "require-dev": {
28 | "doctrine/coding-standard": "^9",
29 | "ext-pdo": "*",
30 | "ext-phar": "*",
31 | "phpbench/phpbench": "^0.16 || ^1",
32 | "phpstan/phpstan": "^1.4",
33 | "phpstan/phpstan-phpunit": "^1",
34 | "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
35 | "vimeo/psalm": "^4.22"
36 | },
37 | "type": "library",
38 | "autoload": {
39 | "psr-4": {
40 | "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
41 | }
42 | },
43 | "notification-url": "https://packagist.org/downloads/",
44 | "license": [
45 | "MIT"
46 | ],
47 | "authors": [
48 | {
49 | "name": "Marco Pivetta",
50 | "email": "ocramius@gmail.com",
51 | "homepage": "https://ocramius.github.io/"
52 | }
53 | ],
54 | "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
55 | "homepage": "https://www.doctrine-project.org/projects/instantiator.html",
56 | "keywords": [
57 | "constructor",
58 | "instantiate"
59 | ],
60 | "support": {
61 | "issues": "https://github.com/doctrine/instantiator/issues",
62 | "source": "https://github.com/doctrine/instantiator/tree/1.4.1"
63 | },
64 | "funding": [
65 | {
66 | "url": "https://www.doctrine-project.org/sponsorship.html",
67 | "type": "custom"
68 | },
69 | {
70 | "url": "https://www.patreon.com/phpdoctrine",
71 | "type": "patreon"
72 | },
73 | {
74 | "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator",
75 | "type": "tidelift"
76 | }
77 | ],
78 | "time": "2022-03-03T08:28:38+00:00"
79 | },
80 | {
81 | "name": "myclabs/deep-copy",
82 | "version": "1.11.0",
83 | "source": {
84 | "type": "git",
85 | "url": "https://github.com/myclabs/DeepCopy.git",
86 | "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614"
87 | },
88 | "dist": {
89 | "type": "zip",
90 | "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/14daed4296fae74d9e3201d2c4925d1acb7aa614",
91 | "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614",
92 | "shasum": ""
93 | },
94 | "require": {
95 | "php": "^7.1 || ^8.0"
96 | },
97 | "conflict": {
98 | "doctrine/collections": "<1.6.8",
99 | "doctrine/common": "<2.13.3 || >=3,<3.2.2"
100 | },
101 | "require-dev": {
102 | "doctrine/collections": "^1.6.8",
103 | "doctrine/common": "^2.13.3 || ^3.2.2",
104 | "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13"
105 | },
106 | "type": "library",
107 | "autoload": {
108 | "files": [
109 | "src/DeepCopy/deep_copy.php"
110 | ],
111 | "psr-4": {
112 | "DeepCopy\\": "src/DeepCopy/"
113 | }
114 | },
115 | "notification-url": "https://packagist.org/downloads/",
116 | "license": [
117 | "MIT"
118 | ],
119 | "description": "Create deep copies (clones) of your objects",
120 | "keywords": [
121 | "clone",
122 | "copy",
123 | "duplicate",
124 | "object",
125 | "object graph"
126 | ],
127 | "support": {
128 | "issues": "https://github.com/myclabs/DeepCopy/issues",
129 | "source": "https://github.com/myclabs/DeepCopy/tree/1.11.0"
130 | },
131 | "funding": [
132 | {
133 | "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy",
134 | "type": "tidelift"
135 | }
136 | ],
137 | "time": "2022-03-03T13:19:32+00:00"
138 | },
139 | {
140 | "name": "nikic/php-parser",
141 | "version": "v4.15.2",
142 | "source": {
143 | "type": "git",
144 | "url": "https://github.com/nikic/PHP-Parser.git",
145 | "reference": "f59bbe44bf7d96f24f3e2b4ddc21cd52c1d2adbc"
146 | },
147 | "dist": {
148 | "type": "zip",
149 | "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/f59bbe44bf7d96f24f3e2b4ddc21cd52c1d2adbc",
150 | "reference": "f59bbe44bf7d96f24f3e2b4ddc21cd52c1d2adbc",
151 | "shasum": ""
152 | },
153 | "require": {
154 | "ext-tokenizer": "*",
155 | "php": ">=7.0"
156 | },
157 | "require-dev": {
158 | "ircmaxell/php-yacc": "^0.0.7",
159 | "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0"
160 | },
161 | "bin": [
162 | "bin/php-parse"
163 | ],
164 | "type": "library",
165 | "extra": {
166 | "branch-alias": {
167 | "dev-master": "4.9-dev"
168 | }
169 | },
170 | "autoload": {
171 | "psr-4": {
172 | "PhpParser\\": "lib/PhpParser"
173 | }
174 | },
175 | "notification-url": "https://packagist.org/downloads/",
176 | "license": [
177 | "BSD-3-Clause"
178 | ],
179 | "authors": [
180 | {
181 | "name": "Nikita Popov"
182 | }
183 | ],
184 | "description": "A PHP parser written in PHP",
185 | "keywords": [
186 | "parser",
187 | "php"
188 | ],
189 | "support": {
190 | "issues": "https://github.com/nikic/PHP-Parser/issues",
191 | "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.2"
192 | },
193 | "time": "2022-11-12T15:38:23+00:00"
194 | },
195 | {
196 | "name": "phar-io/manifest",
197 | "version": "2.0.3",
198 | "source": {
199 | "type": "git",
200 | "url": "https://github.com/phar-io/manifest.git",
201 | "reference": "97803eca37d319dfa7826cc2437fc020857acb53"
202 | },
203 | "dist": {
204 | "type": "zip",
205 | "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53",
206 | "reference": "97803eca37d319dfa7826cc2437fc020857acb53",
207 | "shasum": ""
208 | },
209 | "require": {
210 | "ext-dom": "*",
211 | "ext-phar": "*",
212 | "ext-xmlwriter": "*",
213 | "phar-io/version": "^3.0.1",
214 | "php": "^7.2 || ^8.0"
215 | },
216 | "type": "library",
217 | "extra": {
218 | "branch-alias": {
219 | "dev-master": "2.0.x-dev"
220 | }
221 | },
222 | "autoload": {
223 | "classmap": [
224 | "src/"
225 | ]
226 | },
227 | "notification-url": "https://packagist.org/downloads/",
228 | "license": [
229 | "BSD-3-Clause"
230 | ],
231 | "authors": [
232 | {
233 | "name": "Arne Blankerts",
234 | "email": "arne@blankerts.de",
235 | "role": "Developer"
236 | },
237 | {
238 | "name": "Sebastian Heuer",
239 | "email": "sebastian@phpeople.de",
240 | "role": "Developer"
241 | },
242 | {
243 | "name": "Sebastian Bergmann",
244 | "email": "sebastian@phpunit.de",
245 | "role": "Developer"
246 | }
247 | ],
248 | "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
249 | "support": {
250 | "issues": "https://github.com/phar-io/manifest/issues",
251 | "source": "https://github.com/phar-io/manifest/tree/2.0.3"
252 | },
253 | "time": "2021-07-20T11:28:43+00:00"
254 | },
255 | {
256 | "name": "phar-io/version",
257 | "version": "3.2.1",
258 | "source": {
259 | "type": "git",
260 | "url": "https://github.com/phar-io/version.git",
261 | "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74"
262 | },
263 | "dist": {
264 | "type": "zip",
265 | "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
266 | "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
267 | "shasum": ""
268 | },
269 | "require": {
270 | "php": "^7.2 || ^8.0"
271 | },
272 | "type": "library",
273 | "autoload": {
274 | "classmap": [
275 | "src/"
276 | ]
277 | },
278 | "notification-url": "https://packagist.org/downloads/",
279 | "license": [
280 | "BSD-3-Clause"
281 | ],
282 | "authors": [
283 | {
284 | "name": "Arne Blankerts",
285 | "email": "arne@blankerts.de",
286 | "role": "Developer"
287 | },
288 | {
289 | "name": "Sebastian Heuer",
290 | "email": "sebastian@phpeople.de",
291 | "role": "Developer"
292 | },
293 | {
294 | "name": "Sebastian Bergmann",
295 | "email": "sebastian@phpunit.de",
296 | "role": "Developer"
297 | }
298 | ],
299 | "description": "Library for handling version information and constraints",
300 | "support": {
301 | "issues": "https://github.com/phar-io/version/issues",
302 | "source": "https://github.com/phar-io/version/tree/3.2.1"
303 | },
304 | "time": "2022-02-21T01:04:05+00:00"
305 | },
306 | {
307 | "name": "phpunit/php-code-coverage",
308 | "version": "9.2.19",
309 | "source": {
310 | "type": "git",
311 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
312 | "reference": "c77b56b63e3d2031bd8997fcec43c1925ae46559"
313 | },
314 | "dist": {
315 | "type": "zip",
316 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/c77b56b63e3d2031bd8997fcec43c1925ae46559",
317 | "reference": "c77b56b63e3d2031bd8997fcec43c1925ae46559",
318 | "shasum": ""
319 | },
320 | "require": {
321 | "ext-dom": "*",
322 | "ext-libxml": "*",
323 | "ext-xmlwriter": "*",
324 | "nikic/php-parser": "^4.14",
325 | "php": ">=7.3",
326 | "phpunit/php-file-iterator": "^3.0.3",
327 | "phpunit/php-text-template": "^2.0.2",
328 | "sebastian/code-unit-reverse-lookup": "^2.0.2",
329 | "sebastian/complexity": "^2.0",
330 | "sebastian/environment": "^5.1.2",
331 | "sebastian/lines-of-code": "^1.0.3",
332 | "sebastian/version": "^3.0.1",
333 | "theseer/tokenizer": "^1.2.0"
334 | },
335 | "require-dev": {
336 | "phpunit/phpunit": "^9.3"
337 | },
338 | "suggest": {
339 | "ext-pcov": "*",
340 | "ext-xdebug": "*"
341 | },
342 | "type": "library",
343 | "extra": {
344 | "branch-alias": {
345 | "dev-master": "9.2-dev"
346 | }
347 | },
348 | "autoload": {
349 | "classmap": [
350 | "src/"
351 | ]
352 | },
353 | "notification-url": "https://packagist.org/downloads/",
354 | "license": [
355 | "BSD-3-Clause"
356 | ],
357 | "authors": [
358 | {
359 | "name": "Sebastian Bergmann",
360 | "email": "sebastian@phpunit.de",
361 | "role": "lead"
362 | }
363 | ],
364 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
365 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
366 | "keywords": [
367 | "coverage",
368 | "testing",
369 | "xunit"
370 | ],
371 | "support": {
372 | "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
373 | "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.19"
374 | },
375 | "funding": [
376 | {
377 | "url": "https://github.com/sebastianbergmann",
378 | "type": "github"
379 | }
380 | ],
381 | "time": "2022-11-18T07:47:47+00:00"
382 | },
383 | {
384 | "name": "phpunit/php-file-iterator",
385 | "version": "3.0.6",
386 | "source": {
387 | "type": "git",
388 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
389 | "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf"
390 | },
391 | "dist": {
392 | "type": "zip",
393 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf",
394 | "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf",
395 | "shasum": ""
396 | },
397 | "require": {
398 | "php": ">=7.3"
399 | },
400 | "require-dev": {
401 | "phpunit/phpunit": "^9.3"
402 | },
403 | "type": "library",
404 | "extra": {
405 | "branch-alias": {
406 | "dev-master": "3.0-dev"
407 | }
408 | },
409 | "autoload": {
410 | "classmap": [
411 | "src/"
412 | ]
413 | },
414 | "notification-url": "https://packagist.org/downloads/",
415 | "license": [
416 | "BSD-3-Clause"
417 | ],
418 | "authors": [
419 | {
420 | "name": "Sebastian Bergmann",
421 | "email": "sebastian@phpunit.de",
422 | "role": "lead"
423 | }
424 | ],
425 | "description": "FilterIterator implementation that filters files based on a list of suffixes.",
426 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
427 | "keywords": [
428 | "filesystem",
429 | "iterator"
430 | ],
431 | "support": {
432 | "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues",
433 | "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6"
434 | },
435 | "funding": [
436 | {
437 | "url": "https://github.com/sebastianbergmann",
438 | "type": "github"
439 | }
440 | ],
441 | "time": "2021-12-02T12:48:52+00:00"
442 | },
443 | {
444 | "name": "phpunit/php-invoker",
445 | "version": "3.1.1",
446 | "source": {
447 | "type": "git",
448 | "url": "https://github.com/sebastianbergmann/php-invoker.git",
449 | "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67"
450 | },
451 | "dist": {
452 | "type": "zip",
453 | "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67",
454 | "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67",
455 | "shasum": ""
456 | },
457 | "require": {
458 | "php": ">=7.3"
459 | },
460 | "require-dev": {
461 | "ext-pcntl": "*",
462 | "phpunit/phpunit": "^9.3"
463 | },
464 | "suggest": {
465 | "ext-pcntl": "*"
466 | },
467 | "type": "library",
468 | "extra": {
469 | "branch-alias": {
470 | "dev-master": "3.1-dev"
471 | }
472 | },
473 | "autoload": {
474 | "classmap": [
475 | "src/"
476 | ]
477 | },
478 | "notification-url": "https://packagist.org/downloads/",
479 | "license": [
480 | "BSD-3-Clause"
481 | ],
482 | "authors": [
483 | {
484 | "name": "Sebastian Bergmann",
485 | "email": "sebastian@phpunit.de",
486 | "role": "lead"
487 | }
488 | ],
489 | "description": "Invoke callables with a timeout",
490 | "homepage": "https://github.com/sebastianbergmann/php-invoker/",
491 | "keywords": [
492 | "process"
493 | ],
494 | "support": {
495 | "issues": "https://github.com/sebastianbergmann/php-invoker/issues",
496 | "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1"
497 | },
498 | "funding": [
499 | {
500 | "url": "https://github.com/sebastianbergmann",
501 | "type": "github"
502 | }
503 | ],
504 | "time": "2020-09-28T05:58:55+00:00"
505 | },
506 | {
507 | "name": "phpunit/php-text-template",
508 | "version": "2.0.4",
509 | "source": {
510 | "type": "git",
511 | "url": "https://github.com/sebastianbergmann/php-text-template.git",
512 | "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28"
513 | },
514 | "dist": {
515 | "type": "zip",
516 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28",
517 | "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28",
518 | "shasum": ""
519 | },
520 | "require": {
521 | "php": ">=7.3"
522 | },
523 | "require-dev": {
524 | "phpunit/phpunit": "^9.3"
525 | },
526 | "type": "library",
527 | "extra": {
528 | "branch-alias": {
529 | "dev-master": "2.0-dev"
530 | }
531 | },
532 | "autoload": {
533 | "classmap": [
534 | "src/"
535 | ]
536 | },
537 | "notification-url": "https://packagist.org/downloads/",
538 | "license": [
539 | "BSD-3-Clause"
540 | ],
541 | "authors": [
542 | {
543 | "name": "Sebastian Bergmann",
544 | "email": "sebastian@phpunit.de",
545 | "role": "lead"
546 | }
547 | ],
548 | "description": "Simple template engine.",
549 | "homepage": "https://github.com/sebastianbergmann/php-text-template/",
550 | "keywords": [
551 | "template"
552 | ],
553 | "support": {
554 | "issues": "https://github.com/sebastianbergmann/php-text-template/issues",
555 | "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4"
556 | },
557 | "funding": [
558 | {
559 | "url": "https://github.com/sebastianbergmann",
560 | "type": "github"
561 | }
562 | ],
563 | "time": "2020-10-26T05:33:50+00:00"
564 | },
565 | {
566 | "name": "phpunit/php-timer",
567 | "version": "5.0.3",
568 | "source": {
569 | "type": "git",
570 | "url": "https://github.com/sebastianbergmann/php-timer.git",
571 | "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2"
572 | },
573 | "dist": {
574 | "type": "zip",
575 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2",
576 | "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2",
577 | "shasum": ""
578 | },
579 | "require": {
580 | "php": ">=7.3"
581 | },
582 | "require-dev": {
583 | "phpunit/phpunit": "^9.3"
584 | },
585 | "type": "library",
586 | "extra": {
587 | "branch-alias": {
588 | "dev-master": "5.0-dev"
589 | }
590 | },
591 | "autoload": {
592 | "classmap": [
593 | "src/"
594 | ]
595 | },
596 | "notification-url": "https://packagist.org/downloads/",
597 | "license": [
598 | "BSD-3-Clause"
599 | ],
600 | "authors": [
601 | {
602 | "name": "Sebastian Bergmann",
603 | "email": "sebastian@phpunit.de",
604 | "role": "lead"
605 | }
606 | ],
607 | "description": "Utility class for timing",
608 | "homepage": "https://github.com/sebastianbergmann/php-timer/",
609 | "keywords": [
610 | "timer"
611 | ],
612 | "support": {
613 | "issues": "https://github.com/sebastianbergmann/php-timer/issues",
614 | "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3"
615 | },
616 | "funding": [
617 | {
618 | "url": "https://github.com/sebastianbergmann",
619 | "type": "github"
620 | }
621 | ],
622 | "time": "2020-10-26T13:16:10+00:00"
623 | },
624 | {
625 | "name": "phpunit/phpunit",
626 | "version": "9.5.26",
627 | "source": {
628 | "type": "git",
629 | "url": "https://github.com/sebastianbergmann/phpunit.git",
630 | "reference": "851867efcbb6a1b992ec515c71cdcf20d895e9d2"
631 | },
632 | "dist": {
633 | "type": "zip",
634 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/851867efcbb6a1b992ec515c71cdcf20d895e9d2",
635 | "reference": "851867efcbb6a1b992ec515c71cdcf20d895e9d2",
636 | "shasum": ""
637 | },
638 | "require": {
639 | "doctrine/instantiator": "^1.3.1",
640 | "ext-dom": "*",
641 | "ext-json": "*",
642 | "ext-libxml": "*",
643 | "ext-mbstring": "*",
644 | "ext-xml": "*",
645 | "ext-xmlwriter": "*",
646 | "myclabs/deep-copy": "^1.10.1",
647 | "phar-io/manifest": "^2.0.3",
648 | "phar-io/version": "^3.0.2",
649 | "php": ">=7.3",
650 | "phpunit/php-code-coverage": "^9.2.13",
651 | "phpunit/php-file-iterator": "^3.0.5",
652 | "phpunit/php-invoker": "^3.1.1",
653 | "phpunit/php-text-template": "^2.0.3",
654 | "phpunit/php-timer": "^5.0.2",
655 | "sebastian/cli-parser": "^1.0.1",
656 | "sebastian/code-unit": "^1.0.6",
657 | "sebastian/comparator": "^4.0.8",
658 | "sebastian/diff": "^4.0.3",
659 | "sebastian/environment": "^5.1.3",
660 | "sebastian/exporter": "^4.0.5",
661 | "sebastian/global-state": "^5.0.1",
662 | "sebastian/object-enumerator": "^4.0.3",
663 | "sebastian/resource-operations": "^3.0.3",
664 | "sebastian/type": "^3.2",
665 | "sebastian/version": "^3.0.2"
666 | },
667 | "suggest": {
668 | "ext-soap": "*",
669 | "ext-xdebug": "*"
670 | },
671 | "bin": [
672 | "phpunit"
673 | ],
674 | "type": "library",
675 | "extra": {
676 | "branch-alias": {
677 | "dev-master": "9.5-dev"
678 | }
679 | },
680 | "autoload": {
681 | "files": [
682 | "src/Framework/Assert/Functions.php"
683 | ],
684 | "classmap": [
685 | "src/"
686 | ]
687 | },
688 | "notification-url": "https://packagist.org/downloads/",
689 | "license": [
690 | "BSD-3-Clause"
691 | ],
692 | "authors": [
693 | {
694 | "name": "Sebastian Bergmann",
695 | "email": "sebastian@phpunit.de",
696 | "role": "lead"
697 | }
698 | ],
699 | "description": "The PHP Unit Testing framework.",
700 | "homepage": "https://phpunit.de/",
701 | "keywords": [
702 | "phpunit",
703 | "testing",
704 | "xunit"
705 | ],
706 | "support": {
707 | "issues": "https://github.com/sebastianbergmann/phpunit/issues",
708 | "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.26"
709 | },
710 | "funding": [
711 | {
712 | "url": "https://phpunit.de/sponsors.html",
713 | "type": "custom"
714 | },
715 | {
716 | "url": "https://github.com/sebastianbergmann",
717 | "type": "github"
718 | },
719 | {
720 | "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit",
721 | "type": "tidelift"
722 | }
723 | ],
724 | "time": "2022-10-28T06:00:21+00:00"
725 | },
726 | {
727 | "name": "sebastian/cli-parser",
728 | "version": "1.0.1",
729 | "source": {
730 | "type": "git",
731 | "url": "https://github.com/sebastianbergmann/cli-parser.git",
732 | "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2"
733 | },
734 | "dist": {
735 | "type": "zip",
736 | "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2",
737 | "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2",
738 | "shasum": ""
739 | },
740 | "require": {
741 | "php": ">=7.3"
742 | },
743 | "require-dev": {
744 | "phpunit/phpunit": "^9.3"
745 | },
746 | "type": "library",
747 | "extra": {
748 | "branch-alias": {
749 | "dev-master": "1.0-dev"
750 | }
751 | },
752 | "autoload": {
753 | "classmap": [
754 | "src/"
755 | ]
756 | },
757 | "notification-url": "https://packagist.org/downloads/",
758 | "license": [
759 | "BSD-3-Clause"
760 | ],
761 | "authors": [
762 | {
763 | "name": "Sebastian Bergmann",
764 | "email": "sebastian@phpunit.de",
765 | "role": "lead"
766 | }
767 | ],
768 | "description": "Library for parsing CLI options",
769 | "homepage": "https://github.com/sebastianbergmann/cli-parser",
770 | "support": {
771 | "issues": "https://github.com/sebastianbergmann/cli-parser/issues",
772 | "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1"
773 | },
774 | "funding": [
775 | {
776 | "url": "https://github.com/sebastianbergmann",
777 | "type": "github"
778 | }
779 | ],
780 | "time": "2020-09-28T06:08:49+00:00"
781 | },
782 | {
783 | "name": "sebastian/code-unit",
784 | "version": "1.0.8",
785 | "source": {
786 | "type": "git",
787 | "url": "https://github.com/sebastianbergmann/code-unit.git",
788 | "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120"
789 | },
790 | "dist": {
791 | "type": "zip",
792 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120",
793 | "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120",
794 | "shasum": ""
795 | },
796 | "require": {
797 | "php": ">=7.3"
798 | },
799 | "require-dev": {
800 | "phpunit/phpunit": "^9.3"
801 | },
802 | "type": "library",
803 | "extra": {
804 | "branch-alias": {
805 | "dev-master": "1.0-dev"
806 | }
807 | },
808 | "autoload": {
809 | "classmap": [
810 | "src/"
811 | ]
812 | },
813 | "notification-url": "https://packagist.org/downloads/",
814 | "license": [
815 | "BSD-3-Clause"
816 | ],
817 | "authors": [
818 | {
819 | "name": "Sebastian Bergmann",
820 | "email": "sebastian@phpunit.de",
821 | "role": "lead"
822 | }
823 | ],
824 | "description": "Collection of value objects that represent the PHP code units",
825 | "homepage": "https://github.com/sebastianbergmann/code-unit",
826 | "support": {
827 | "issues": "https://github.com/sebastianbergmann/code-unit/issues",
828 | "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8"
829 | },
830 | "funding": [
831 | {
832 | "url": "https://github.com/sebastianbergmann",
833 | "type": "github"
834 | }
835 | ],
836 | "time": "2020-10-26T13:08:54+00:00"
837 | },
838 | {
839 | "name": "sebastian/code-unit-reverse-lookup",
840 | "version": "2.0.3",
841 | "source": {
842 | "type": "git",
843 | "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git",
844 | "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5"
845 | },
846 | "dist": {
847 | "type": "zip",
848 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5",
849 | "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5",
850 | "shasum": ""
851 | },
852 | "require": {
853 | "php": ">=7.3"
854 | },
855 | "require-dev": {
856 | "phpunit/phpunit": "^9.3"
857 | },
858 | "type": "library",
859 | "extra": {
860 | "branch-alias": {
861 | "dev-master": "2.0-dev"
862 | }
863 | },
864 | "autoload": {
865 | "classmap": [
866 | "src/"
867 | ]
868 | },
869 | "notification-url": "https://packagist.org/downloads/",
870 | "license": [
871 | "BSD-3-Clause"
872 | ],
873 | "authors": [
874 | {
875 | "name": "Sebastian Bergmann",
876 | "email": "sebastian@phpunit.de"
877 | }
878 | ],
879 | "description": "Looks up which function or method a line of code belongs to",
880 | "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
881 | "support": {
882 | "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues",
883 | "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3"
884 | },
885 | "funding": [
886 | {
887 | "url": "https://github.com/sebastianbergmann",
888 | "type": "github"
889 | }
890 | ],
891 | "time": "2020-09-28T05:30:19+00:00"
892 | },
893 | {
894 | "name": "sebastian/comparator",
895 | "version": "4.0.8",
896 | "source": {
897 | "type": "git",
898 | "url": "https://github.com/sebastianbergmann/comparator.git",
899 | "reference": "fa0f136dd2334583309d32b62544682ee972b51a"
900 | },
901 | "dist": {
902 | "type": "zip",
903 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a",
904 | "reference": "fa0f136dd2334583309d32b62544682ee972b51a",
905 | "shasum": ""
906 | },
907 | "require": {
908 | "php": ">=7.3",
909 | "sebastian/diff": "^4.0",
910 | "sebastian/exporter": "^4.0"
911 | },
912 | "require-dev": {
913 | "phpunit/phpunit": "^9.3"
914 | },
915 | "type": "library",
916 | "extra": {
917 | "branch-alias": {
918 | "dev-master": "4.0-dev"
919 | }
920 | },
921 | "autoload": {
922 | "classmap": [
923 | "src/"
924 | ]
925 | },
926 | "notification-url": "https://packagist.org/downloads/",
927 | "license": [
928 | "BSD-3-Clause"
929 | ],
930 | "authors": [
931 | {
932 | "name": "Sebastian Bergmann",
933 | "email": "sebastian@phpunit.de"
934 | },
935 | {
936 | "name": "Jeff Welch",
937 | "email": "whatthejeff@gmail.com"
938 | },
939 | {
940 | "name": "Volker Dusch",
941 | "email": "github@wallbash.com"
942 | },
943 | {
944 | "name": "Bernhard Schussek",
945 | "email": "bschussek@2bepublished.at"
946 | }
947 | ],
948 | "description": "Provides the functionality to compare PHP values for equality",
949 | "homepage": "https://github.com/sebastianbergmann/comparator",
950 | "keywords": [
951 | "comparator",
952 | "compare",
953 | "equality"
954 | ],
955 | "support": {
956 | "issues": "https://github.com/sebastianbergmann/comparator/issues",
957 | "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8"
958 | },
959 | "funding": [
960 | {
961 | "url": "https://github.com/sebastianbergmann",
962 | "type": "github"
963 | }
964 | ],
965 | "time": "2022-09-14T12:41:17+00:00"
966 | },
967 | {
968 | "name": "sebastian/complexity",
969 | "version": "2.0.2",
970 | "source": {
971 | "type": "git",
972 | "url": "https://github.com/sebastianbergmann/complexity.git",
973 | "reference": "739b35e53379900cc9ac327b2147867b8b6efd88"
974 | },
975 | "dist": {
976 | "type": "zip",
977 | "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88",
978 | "reference": "739b35e53379900cc9ac327b2147867b8b6efd88",
979 | "shasum": ""
980 | },
981 | "require": {
982 | "nikic/php-parser": "^4.7",
983 | "php": ">=7.3"
984 | },
985 | "require-dev": {
986 | "phpunit/phpunit": "^9.3"
987 | },
988 | "type": "library",
989 | "extra": {
990 | "branch-alias": {
991 | "dev-master": "2.0-dev"
992 | }
993 | },
994 | "autoload": {
995 | "classmap": [
996 | "src/"
997 | ]
998 | },
999 | "notification-url": "https://packagist.org/downloads/",
1000 | "license": [
1001 | "BSD-3-Clause"
1002 | ],
1003 | "authors": [
1004 | {
1005 | "name": "Sebastian Bergmann",
1006 | "email": "sebastian@phpunit.de",
1007 | "role": "lead"
1008 | }
1009 | ],
1010 | "description": "Library for calculating the complexity of PHP code units",
1011 | "homepage": "https://github.com/sebastianbergmann/complexity",
1012 | "support": {
1013 | "issues": "https://github.com/sebastianbergmann/complexity/issues",
1014 | "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2"
1015 | },
1016 | "funding": [
1017 | {
1018 | "url": "https://github.com/sebastianbergmann",
1019 | "type": "github"
1020 | }
1021 | ],
1022 | "time": "2020-10-26T15:52:27+00:00"
1023 | },
1024 | {
1025 | "name": "sebastian/diff",
1026 | "version": "4.0.4",
1027 | "source": {
1028 | "type": "git",
1029 | "url": "https://github.com/sebastianbergmann/diff.git",
1030 | "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d"
1031 | },
1032 | "dist": {
1033 | "type": "zip",
1034 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d",
1035 | "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d",
1036 | "shasum": ""
1037 | },
1038 | "require": {
1039 | "php": ">=7.3"
1040 | },
1041 | "require-dev": {
1042 | "phpunit/phpunit": "^9.3",
1043 | "symfony/process": "^4.2 || ^5"
1044 | },
1045 | "type": "library",
1046 | "extra": {
1047 | "branch-alias": {
1048 | "dev-master": "4.0-dev"
1049 | }
1050 | },
1051 | "autoload": {
1052 | "classmap": [
1053 | "src/"
1054 | ]
1055 | },
1056 | "notification-url": "https://packagist.org/downloads/",
1057 | "license": [
1058 | "BSD-3-Clause"
1059 | ],
1060 | "authors": [
1061 | {
1062 | "name": "Sebastian Bergmann",
1063 | "email": "sebastian@phpunit.de"
1064 | },
1065 | {
1066 | "name": "Kore Nordmann",
1067 | "email": "mail@kore-nordmann.de"
1068 | }
1069 | ],
1070 | "description": "Diff implementation",
1071 | "homepage": "https://github.com/sebastianbergmann/diff",
1072 | "keywords": [
1073 | "diff",
1074 | "udiff",
1075 | "unidiff",
1076 | "unified diff"
1077 | ],
1078 | "support": {
1079 | "issues": "https://github.com/sebastianbergmann/diff/issues",
1080 | "source": "https://github.com/sebastianbergmann/diff/tree/4.0.4"
1081 | },
1082 | "funding": [
1083 | {
1084 | "url": "https://github.com/sebastianbergmann",
1085 | "type": "github"
1086 | }
1087 | ],
1088 | "time": "2020-10-26T13:10:38+00:00"
1089 | },
1090 | {
1091 | "name": "sebastian/environment",
1092 | "version": "5.1.4",
1093 | "source": {
1094 | "type": "git",
1095 | "url": "https://github.com/sebastianbergmann/environment.git",
1096 | "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7"
1097 | },
1098 | "dist": {
1099 | "type": "zip",
1100 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/1b5dff7bb151a4db11d49d90e5408e4e938270f7",
1101 | "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7",
1102 | "shasum": ""
1103 | },
1104 | "require": {
1105 | "php": ">=7.3"
1106 | },
1107 | "require-dev": {
1108 | "phpunit/phpunit": "^9.3"
1109 | },
1110 | "suggest": {
1111 | "ext-posix": "*"
1112 | },
1113 | "type": "library",
1114 | "extra": {
1115 | "branch-alias": {
1116 | "dev-master": "5.1-dev"
1117 | }
1118 | },
1119 | "autoload": {
1120 | "classmap": [
1121 | "src/"
1122 | ]
1123 | },
1124 | "notification-url": "https://packagist.org/downloads/",
1125 | "license": [
1126 | "BSD-3-Clause"
1127 | ],
1128 | "authors": [
1129 | {
1130 | "name": "Sebastian Bergmann",
1131 | "email": "sebastian@phpunit.de"
1132 | }
1133 | ],
1134 | "description": "Provides functionality to handle HHVM/PHP environments",
1135 | "homepage": "http://www.github.com/sebastianbergmann/environment",
1136 | "keywords": [
1137 | "Xdebug",
1138 | "environment",
1139 | "hhvm"
1140 | ],
1141 | "support": {
1142 | "issues": "https://github.com/sebastianbergmann/environment/issues",
1143 | "source": "https://github.com/sebastianbergmann/environment/tree/5.1.4"
1144 | },
1145 | "funding": [
1146 | {
1147 | "url": "https://github.com/sebastianbergmann",
1148 | "type": "github"
1149 | }
1150 | ],
1151 | "time": "2022-04-03T09:37:03+00:00"
1152 | },
1153 | {
1154 | "name": "sebastian/exporter",
1155 | "version": "4.0.5",
1156 | "source": {
1157 | "type": "git",
1158 | "url": "https://github.com/sebastianbergmann/exporter.git",
1159 | "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d"
1160 | },
1161 | "dist": {
1162 | "type": "zip",
1163 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d",
1164 | "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d",
1165 | "shasum": ""
1166 | },
1167 | "require": {
1168 | "php": ">=7.3",
1169 | "sebastian/recursion-context": "^4.0"
1170 | },
1171 | "require-dev": {
1172 | "ext-mbstring": "*",
1173 | "phpunit/phpunit": "^9.3"
1174 | },
1175 | "type": "library",
1176 | "extra": {
1177 | "branch-alias": {
1178 | "dev-master": "4.0-dev"
1179 | }
1180 | },
1181 | "autoload": {
1182 | "classmap": [
1183 | "src/"
1184 | ]
1185 | },
1186 | "notification-url": "https://packagist.org/downloads/",
1187 | "license": [
1188 | "BSD-3-Clause"
1189 | ],
1190 | "authors": [
1191 | {
1192 | "name": "Sebastian Bergmann",
1193 | "email": "sebastian@phpunit.de"
1194 | },
1195 | {
1196 | "name": "Jeff Welch",
1197 | "email": "whatthejeff@gmail.com"
1198 | },
1199 | {
1200 | "name": "Volker Dusch",
1201 | "email": "github@wallbash.com"
1202 | },
1203 | {
1204 | "name": "Adam Harvey",
1205 | "email": "aharvey@php.net"
1206 | },
1207 | {
1208 | "name": "Bernhard Schussek",
1209 | "email": "bschussek@gmail.com"
1210 | }
1211 | ],
1212 | "description": "Provides the functionality to export PHP variables for visualization",
1213 | "homepage": "https://www.github.com/sebastianbergmann/exporter",
1214 | "keywords": [
1215 | "export",
1216 | "exporter"
1217 | ],
1218 | "support": {
1219 | "issues": "https://github.com/sebastianbergmann/exporter/issues",
1220 | "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5"
1221 | },
1222 | "funding": [
1223 | {
1224 | "url": "https://github.com/sebastianbergmann",
1225 | "type": "github"
1226 | }
1227 | ],
1228 | "time": "2022-09-14T06:03:37+00:00"
1229 | },
1230 | {
1231 | "name": "sebastian/global-state",
1232 | "version": "5.0.5",
1233 | "source": {
1234 | "type": "git",
1235 | "url": "https://github.com/sebastianbergmann/global-state.git",
1236 | "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2"
1237 | },
1238 | "dist": {
1239 | "type": "zip",
1240 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2",
1241 | "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2",
1242 | "shasum": ""
1243 | },
1244 | "require": {
1245 | "php": ">=7.3",
1246 | "sebastian/object-reflector": "^2.0",
1247 | "sebastian/recursion-context": "^4.0"
1248 | },
1249 | "require-dev": {
1250 | "ext-dom": "*",
1251 | "phpunit/phpunit": "^9.3"
1252 | },
1253 | "suggest": {
1254 | "ext-uopz": "*"
1255 | },
1256 | "type": "library",
1257 | "extra": {
1258 | "branch-alias": {
1259 | "dev-master": "5.0-dev"
1260 | }
1261 | },
1262 | "autoload": {
1263 | "classmap": [
1264 | "src/"
1265 | ]
1266 | },
1267 | "notification-url": "https://packagist.org/downloads/",
1268 | "license": [
1269 | "BSD-3-Clause"
1270 | ],
1271 | "authors": [
1272 | {
1273 | "name": "Sebastian Bergmann",
1274 | "email": "sebastian@phpunit.de"
1275 | }
1276 | ],
1277 | "description": "Snapshotting of global state",
1278 | "homepage": "http://www.github.com/sebastianbergmann/global-state",
1279 | "keywords": [
1280 | "global state"
1281 | ],
1282 | "support": {
1283 | "issues": "https://github.com/sebastianbergmann/global-state/issues",
1284 | "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5"
1285 | },
1286 | "funding": [
1287 | {
1288 | "url": "https://github.com/sebastianbergmann",
1289 | "type": "github"
1290 | }
1291 | ],
1292 | "time": "2022-02-14T08:28:10+00:00"
1293 | },
1294 | {
1295 | "name": "sebastian/lines-of-code",
1296 | "version": "1.0.3",
1297 | "source": {
1298 | "type": "git",
1299 | "url": "https://github.com/sebastianbergmann/lines-of-code.git",
1300 | "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc"
1301 | },
1302 | "dist": {
1303 | "type": "zip",
1304 | "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc",
1305 | "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc",
1306 | "shasum": ""
1307 | },
1308 | "require": {
1309 | "nikic/php-parser": "^4.6",
1310 | "php": ">=7.3"
1311 | },
1312 | "require-dev": {
1313 | "phpunit/phpunit": "^9.3"
1314 | },
1315 | "type": "library",
1316 | "extra": {
1317 | "branch-alias": {
1318 | "dev-master": "1.0-dev"
1319 | }
1320 | },
1321 | "autoload": {
1322 | "classmap": [
1323 | "src/"
1324 | ]
1325 | },
1326 | "notification-url": "https://packagist.org/downloads/",
1327 | "license": [
1328 | "BSD-3-Clause"
1329 | ],
1330 | "authors": [
1331 | {
1332 | "name": "Sebastian Bergmann",
1333 | "email": "sebastian@phpunit.de",
1334 | "role": "lead"
1335 | }
1336 | ],
1337 | "description": "Library for counting the lines of code in PHP source code",
1338 | "homepage": "https://github.com/sebastianbergmann/lines-of-code",
1339 | "support": {
1340 | "issues": "https://github.com/sebastianbergmann/lines-of-code/issues",
1341 | "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3"
1342 | },
1343 | "funding": [
1344 | {
1345 | "url": "https://github.com/sebastianbergmann",
1346 | "type": "github"
1347 | }
1348 | ],
1349 | "time": "2020-11-28T06:42:11+00:00"
1350 | },
1351 | {
1352 | "name": "sebastian/object-enumerator",
1353 | "version": "4.0.4",
1354 | "source": {
1355 | "type": "git",
1356 | "url": "https://github.com/sebastianbergmann/object-enumerator.git",
1357 | "reference": "5c9eeac41b290a3712d88851518825ad78f45c71"
1358 | },
1359 | "dist": {
1360 | "type": "zip",
1361 | "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71",
1362 | "reference": "5c9eeac41b290a3712d88851518825ad78f45c71",
1363 | "shasum": ""
1364 | },
1365 | "require": {
1366 | "php": ">=7.3",
1367 | "sebastian/object-reflector": "^2.0",
1368 | "sebastian/recursion-context": "^4.0"
1369 | },
1370 | "require-dev": {
1371 | "phpunit/phpunit": "^9.3"
1372 | },
1373 | "type": "library",
1374 | "extra": {
1375 | "branch-alias": {
1376 | "dev-master": "4.0-dev"
1377 | }
1378 | },
1379 | "autoload": {
1380 | "classmap": [
1381 | "src/"
1382 | ]
1383 | },
1384 | "notification-url": "https://packagist.org/downloads/",
1385 | "license": [
1386 | "BSD-3-Clause"
1387 | ],
1388 | "authors": [
1389 | {
1390 | "name": "Sebastian Bergmann",
1391 | "email": "sebastian@phpunit.de"
1392 | }
1393 | ],
1394 | "description": "Traverses array structures and object graphs to enumerate all referenced objects",
1395 | "homepage": "https://github.com/sebastianbergmann/object-enumerator/",
1396 | "support": {
1397 | "issues": "https://github.com/sebastianbergmann/object-enumerator/issues",
1398 | "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4"
1399 | },
1400 | "funding": [
1401 | {
1402 | "url": "https://github.com/sebastianbergmann",
1403 | "type": "github"
1404 | }
1405 | ],
1406 | "time": "2020-10-26T13:12:34+00:00"
1407 | },
1408 | {
1409 | "name": "sebastian/object-reflector",
1410 | "version": "2.0.4",
1411 | "source": {
1412 | "type": "git",
1413 | "url": "https://github.com/sebastianbergmann/object-reflector.git",
1414 | "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7"
1415 | },
1416 | "dist": {
1417 | "type": "zip",
1418 | "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7",
1419 | "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7",
1420 | "shasum": ""
1421 | },
1422 | "require": {
1423 | "php": ">=7.3"
1424 | },
1425 | "require-dev": {
1426 | "phpunit/phpunit": "^9.3"
1427 | },
1428 | "type": "library",
1429 | "extra": {
1430 | "branch-alias": {
1431 | "dev-master": "2.0-dev"
1432 | }
1433 | },
1434 | "autoload": {
1435 | "classmap": [
1436 | "src/"
1437 | ]
1438 | },
1439 | "notification-url": "https://packagist.org/downloads/",
1440 | "license": [
1441 | "BSD-3-Clause"
1442 | ],
1443 | "authors": [
1444 | {
1445 | "name": "Sebastian Bergmann",
1446 | "email": "sebastian@phpunit.de"
1447 | }
1448 | ],
1449 | "description": "Allows reflection of object attributes, including inherited and non-public ones",
1450 | "homepage": "https://github.com/sebastianbergmann/object-reflector/",
1451 | "support": {
1452 | "issues": "https://github.com/sebastianbergmann/object-reflector/issues",
1453 | "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4"
1454 | },
1455 | "funding": [
1456 | {
1457 | "url": "https://github.com/sebastianbergmann",
1458 | "type": "github"
1459 | }
1460 | ],
1461 | "time": "2020-10-26T13:14:26+00:00"
1462 | },
1463 | {
1464 | "name": "sebastian/recursion-context",
1465 | "version": "4.0.4",
1466 | "source": {
1467 | "type": "git",
1468 | "url": "https://github.com/sebastianbergmann/recursion-context.git",
1469 | "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172"
1470 | },
1471 | "dist": {
1472 | "type": "zip",
1473 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172",
1474 | "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172",
1475 | "shasum": ""
1476 | },
1477 | "require": {
1478 | "php": ">=7.3"
1479 | },
1480 | "require-dev": {
1481 | "phpunit/phpunit": "^9.3"
1482 | },
1483 | "type": "library",
1484 | "extra": {
1485 | "branch-alias": {
1486 | "dev-master": "4.0-dev"
1487 | }
1488 | },
1489 | "autoload": {
1490 | "classmap": [
1491 | "src/"
1492 | ]
1493 | },
1494 | "notification-url": "https://packagist.org/downloads/",
1495 | "license": [
1496 | "BSD-3-Clause"
1497 | ],
1498 | "authors": [
1499 | {
1500 | "name": "Sebastian Bergmann",
1501 | "email": "sebastian@phpunit.de"
1502 | },
1503 | {
1504 | "name": "Jeff Welch",
1505 | "email": "whatthejeff@gmail.com"
1506 | },
1507 | {
1508 | "name": "Adam Harvey",
1509 | "email": "aharvey@php.net"
1510 | }
1511 | ],
1512 | "description": "Provides functionality to recursively process PHP variables",
1513 | "homepage": "http://www.github.com/sebastianbergmann/recursion-context",
1514 | "support": {
1515 | "issues": "https://github.com/sebastianbergmann/recursion-context/issues",
1516 | "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.4"
1517 | },
1518 | "funding": [
1519 | {
1520 | "url": "https://github.com/sebastianbergmann",
1521 | "type": "github"
1522 | }
1523 | ],
1524 | "time": "2020-10-26T13:17:30+00:00"
1525 | },
1526 | {
1527 | "name": "sebastian/resource-operations",
1528 | "version": "3.0.3",
1529 | "source": {
1530 | "type": "git",
1531 | "url": "https://github.com/sebastianbergmann/resource-operations.git",
1532 | "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8"
1533 | },
1534 | "dist": {
1535 | "type": "zip",
1536 | "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8",
1537 | "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8",
1538 | "shasum": ""
1539 | },
1540 | "require": {
1541 | "php": ">=7.3"
1542 | },
1543 | "require-dev": {
1544 | "phpunit/phpunit": "^9.0"
1545 | },
1546 | "type": "library",
1547 | "extra": {
1548 | "branch-alias": {
1549 | "dev-master": "3.0-dev"
1550 | }
1551 | },
1552 | "autoload": {
1553 | "classmap": [
1554 | "src/"
1555 | ]
1556 | },
1557 | "notification-url": "https://packagist.org/downloads/",
1558 | "license": [
1559 | "BSD-3-Clause"
1560 | ],
1561 | "authors": [
1562 | {
1563 | "name": "Sebastian Bergmann",
1564 | "email": "sebastian@phpunit.de"
1565 | }
1566 | ],
1567 | "description": "Provides a list of PHP built-in functions that operate on resources",
1568 | "homepage": "https://www.github.com/sebastianbergmann/resource-operations",
1569 | "support": {
1570 | "issues": "https://github.com/sebastianbergmann/resource-operations/issues",
1571 | "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3"
1572 | },
1573 | "funding": [
1574 | {
1575 | "url": "https://github.com/sebastianbergmann",
1576 | "type": "github"
1577 | }
1578 | ],
1579 | "time": "2020-09-28T06:45:17+00:00"
1580 | },
1581 | {
1582 | "name": "sebastian/type",
1583 | "version": "3.2.0",
1584 | "source": {
1585 | "type": "git",
1586 | "url": "https://github.com/sebastianbergmann/type.git",
1587 | "reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e"
1588 | },
1589 | "dist": {
1590 | "type": "zip",
1591 | "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e",
1592 | "reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e",
1593 | "shasum": ""
1594 | },
1595 | "require": {
1596 | "php": ">=7.3"
1597 | },
1598 | "require-dev": {
1599 | "phpunit/phpunit": "^9.5"
1600 | },
1601 | "type": "library",
1602 | "extra": {
1603 | "branch-alias": {
1604 | "dev-master": "3.2-dev"
1605 | }
1606 | },
1607 | "autoload": {
1608 | "classmap": [
1609 | "src/"
1610 | ]
1611 | },
1612 | "notification-url": "https://packagist.org/downloads/",
1613 | "license": [
1614 | "BSD-3-Clause"
1615 | ],
1616 | "authors": [
1617 | {
1618 | "name": "Sebastian Bergmann",
1619 | "email": "sebastian@phpunit.de",
1620 | "role": "lead"
1621 | }
1622 | ],
1623 | "description": "Collection of value objects that represent the types of the PHP type system",
1624 | "homepage": "https://github.com/sebastianbergmann/type",
1625 | "support": {
1626 | "issues": "https://github.com/sebastianbergmann/type/issues",
1627 | "source": "https://github.com/sebastianbergmann/type/tree/3.2.0"
1628 | },
1629 | "funding": [
1630 | {
1631 | "url": "https://github.com/sebastianbergmann",
1632 | "type": "github"
1633 | }
1634 | ],
1635 | "time": "2022-09-12T14:47:03+00:00"
1636 | },
1637 | {
1638 | "name": "sebastian/version",
1639 | "version": "3.0.2",
1640 | "source": {
1641 | "type": "git",
1642 | "url": "https://github.com/sebastianbergmann/version.git",
1643 | "reference": "c6c1022351a901512170118436c764e473f6de8c"
1644 | },
1645 | "dist": {
1646 | "type": "zip",
1647 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c",
1648 | "reference": "c6c1022351a901512170118436c764e473f6de8c",
1649 | "shasum": ""
1650 | },
1651 | "require": {
1652 | "php": ">=7.3"
1653 | },
1654 | "type": "library",
1655 | "extra": {
1656 | "branch-alias": {
1657 | "dev-master": "3.0-dev"
1658 | }
1659 | },
1660 | "autoload": {
1661 | "classmap": [
1662 | "src/"
1663 | ]
1664 | },
1665 | "notification-url": "https://packagist.org/downloads/",
1666 | "license": [
1667 | "BSD-3-Clause"
1668 | ],
1669 | "authors": [
1670 | {
1671 | "name": "Sebastian Bergmann",
1672 | "email": "sebastian@phpunit.de",
1673 | "role": "lead"
1674 | }
1675 | ],
1676 | "description": "Library that helps with managing the version number of Git-hosted PHP projects",
1677 | "homepage": "https://github.com/sebastianbergmann/version",
1678 | "support": {
1679 | "issues": "https://github.com/sebastianbergmann/version/issues",
1680 | "source": "https://github.com/sebastianbergmann/version/tree/3.0.2"
1681 | },
1682 | "funding": [
1683 | {
1684 | "url": "https://github.com/sebastianbergmann",
1685 | "type": "github"
1686 | }
1687 | ],
1688 | "time": "2020-09-28T06:39:44+00:00"
1689 | },
1690 | {
1691 | "name": "theseer/tokenizer",
1692 | "version": "1.2.1",
1693 | "source": {
1694 | "type": "git",
1695 | "url": "https://github.com/theseer/tokenizer.git",
1696 | "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e"
1697 | },
1698 | "dist": {
1699 | "type": "zip",
1700 | "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e",
1701 | "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e",
1702 | "shasum": ""
1703 | },
1704 | "require": {
1705 | "ext-dom": "*",
1706 | "ext-tokenizer": "*",
1707 | "ext-xmlwriter": "*",
1708 | "php": "^7.2 || ^8.0"
1709 | },
1710 | "type": "library",
1711 | "autoload": {
1712 | "classmap": [
1713 | "src/"
1714 | ]
1715 | },
1716 | "notification-url": "https://packagist.org/downloads/",
1717 | "license": [
1718 | "BSD-3-Clause"
1719 | ],
1720 | "authors": [
1721 | {
1722 | "name": "Arne Blankerts",
1723 | "email": "arne@blankerts.de",
1724 | "role": "Developer"
1725 | }
1726 | ],
1727 | "description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
1728 | "support": {
1729 | "issues": "https://github.com/theseer/tokenizer/issues",
1730 | "source": "https://github.com/theseer/tokenizer/tree/1.2.1"
1731 | },
1732 | "funding": [
1733 | {
1734 | "url": "https://github.com/theseer",
1735 | "type": "github"
1736 | }
1737 | ],
1738 | "time": "2021-07-28T10:34:58+00:00"
1739 | },
1740 | {
1741 | "name": "yoast/phpunit-polyfills",
1742 | "version": "1.0.4",
1743 | "source": {
1744 | "type": "git",
1745 | "url": "https://github.com/Yoast/PHPUnit-Polyfills.git",
1746 | "reference": "3c621ff5429d2b1ff96dc5808ad6cde99d31ea4c"
1747 | },
1748 | "dist": {
1749 | "type": "zip",
1750 | "url": "https://api.github.com/repos/Yoast/PHPUnit-Polyfills/zipball/3c621ff5429d2b1ff96dc5808ad6cde99d31ea4c",
1751 | "reference": "3c621ff5429d2b1ff96dc5808ad6cde99d31ea4c",
1752 | "shasum": ""
1753 | },
1754 | "require": {
1755 | "php": ">=5.4",
1756 | "phpunit/phpunit": "^4.8.36 || ^5.7.21 || ^6.0 || ^7.0 || ^8.0 || ^9.0"
1757 | },
1758 | "require-dev": {
1759 | "yoast/yoastcs": "^2.2.1"
1760 | },
1761 | "type": "library",
1762 | "extra": {
1763 | "branch-alias": {
1764 | "dev-main": "1.x-dev",
1765 | "dev-develop": "1.x-dev"
1766 | }
1767 | },
1768 | "autoload": {
1769 | "files": [
1770 | "phpunitpolyfills-autoload.php"
1771 | ]
1772 | },
1773 | "notification-url": "https://packagist.org/downloads/",
1774 | "license": [
1775 | "BSD-3-Clause"
1776 | ],
1777 | "authors": [
1778 | {
1779 | "name": "Team Yoast",
1780 | "email": "support@yoast.com",
1781 | "homepage": "https://yoast.com"
1782 | },
1783 | {
1784 | "name": "Contributors",
1785 | "homepage": "https://github.com/Yoast/PHPUnit-Polyfills/graphs/contributors"
1786 | }
1787 | ],
1788 | "description": "Set of polyfills for changed PHPUnit functionality to allow for creating PHPUnit cross-version compatible tests",
1789 | "homepage": "https://github.com/Yoast/PHPUnit-Polyfills",
1790 | "keywords": [
1791 | "phpunit",
1792 | "polyfill",
1793 | "testing"
1794 | ],
1795 | "support": {
1796 | "issues": "https://github.com/Yoast/PHPUnit-Polyfills/issues",
1797 | "source": "https://github.com/Yoast/PHPUnit-Polyfills"
1798 | },
1799 | "time": "2022-11-16T09:07:52+00:00"
1800 | }
1801 | ],
1802 | "aliases": [],
1803 | "minimum-stability": "stable",
1804 | "stability-flags": [],
1805 | "prefer-stable": false,
1806 | "prefer-lowest": false,
1807 | "platform": [],
1808 | "platform-dev": [],
1809 | "plugin-api-version": "2.1.0"
1810 | }
1811 |
--------------------------------------------------------------------------------
/lightweight-term-count-update.php:
--------------------------------------------------------------------------------
1 | setup();
62 | }
63 | return self::$instance;
64 | }
65 |
66 | /**
67 | * Setup the singleton.
68 | */
69 | public function setup() {
70 | // Prevent core from counting terms.
71 | wp_defer_term_counting( true );
72 | remove_action( 'transition_post_status', '_update_term_count_on_transition_post_status' );
73 |
74 | /**
75 | * Filter the statuses that should be counted, to allow for custom post
76 | * statuses that are otherwise equivalent to 'publish'.
77 | *
78 | * @param array $counted_statuses The statuses that should be counted.
79 | * Defaults to ['publish'].
80 | */
81 | $this->counted_statuses = apply_filters( 'ltcu_counted_statuses', $this->counted_statuses );
82 | add_action( 'transition_post_status', array( $this, 'transition_post_status' ), 10, 3 );
83 | add_action( 'added_term_relationship', array( $this, 'added_term_relationship' ), 10, 3 );
84 | add_action( 'deleted_term_relationships', array( $this, 'deleted_term_relationships' ), 10, 3 );
85 |
86 | /**
87 | * Possibly recount posts for a term once it's been edited.
88 | */
89 | add_action( 'edit_term', array( $this, 'maybe_recount_posts_for_term' ), 10, 3 );
90 | }
91 |
92 | /**
93 | * When a term relationship is added, increment the term count.
94 | *
95 | * @see {LTCU_Plugin::handle_term_relationship_change()}
96 | *
97 | * @param int $object_id Object ID.
98 | * @param int $tt_id Single term taxonomy ID.
99 | * @param string $taxonomy Taxonomy slug.
100 | */
101 | public function added_term_relationship( $object_id, $tt_id, $taxonomy ) {
102 | $this->handle_term_relationship_change( $object_id, (array) $tt_id, $taxonomy, 'increment' );
103 | }
104 |
105 | /**
106 | * When a term relationship is deleted, decrement the term count.
107 | *
108 | * @see {LTCU_Plugin::handle_term_relationship_change()}
109 | *
110 | * @param int $object_id Object ID.
111 | * @param array $tt_ids Array of term taxonomy IDs.
112 | * @param string $taxonomy Taxonomy slug.
113 | */
114 | public function deleted_term_relationships( $object_id, $tt_ids, $taxonomy ) {
115 | $this->handle_term_relationship_change( $object_id, $tt_ids, $taxonomy, 'decrement' );
116 | }
117 |
118 | /**
119 | * Update term counts when term relationships are added or deleted.
120 | *
121 | * @see {LTCU_Plugin::added_term_relationship()}
122 | * @see {LTCU_Plugin::deleted_term_relationships()}
123 | *
124 | * @param int $object_id Object ID.
125 | * @param array $tt_ids Array of term taxonomy IDs.
126 | * @param string $taxonomy Taxonomy slug.
127 | * @param string $transition_type Transition type (increment or decrement).
128 | */
129 | protected function handle_term_relationship_change( $object_id, $tt_ids, $taxonomy, $transition_type ) {
130 | $post = get_post( $object_id );
131 |
132 | if ( ! $post || ! is_object_in_taxonomy( $post->post_type, $taxonomy ) ) {
133 | // If this object isn't a post, we can jump right into counting it.
134 | $this->quick_update_terms_count( $object_id, $tt_ids, $taxonomy, $transition_type );
135 | } elseif ( in_array( get_post_status( $post ), $this->counted_statuses, true ) ) {
136 | // If this is a post, we only count it if it's in a counted status.
137 | // If the status changed, that will be caught by
138 | // `LTCU_Plugin::transition_post_status()`. Also note that we used
139 | // `get_post_status()` above because that checks the parent status
140 | // if the status is inherit.
141 | $this->quick_update_terms_count( $object_id, $tt_ids, $taxonomy, $transition_type );
142 | } else {
143 | clean_term_cache( $tt_ids, '', false );
144 | }
145 | }
146 |
147 | /**
148 | * When a post transitions, increment or decrement term counts as
149 | * appropriate.
150 | *
151 | * @param string $new_status New post status.
152 | * @param string $old_status Old post status.
153 | * @param object $post {
154 | * Post being transitioned. This not always a \WP_Post.
155 | *
156 | * @type int $ID Post ID.
157 | * @type string $post_type Post type.
158 | * }
159 | */
160 | public function transition_post_status( $new_status, $old_status, $post ) {
161 | foreach ( (array) get_object_taxonomies( $post->post_type ) as $taxonomy ) {
162 | $tt_ids = wp_get_object_terms( $post->ID, $taxonomy, array(
163 | 'fields' => 'tt_ids',
164 | ) );
165 |
166 | if ( ! empty( $tt_ids ) && ! is_wp_error( $tt_ids ) ) {
167 | $this->quick_update_terms_count(
168 | $post->ID,
169 | $tt_ids,
170 | $taxonomy,
171 | $this->transition_type( $new_status, $old_status )
172 | );
173 | }
174 | }
175 |
176 | // For non-attachments, let's check if there are any attachment children
177 | // with inherited post status -- if so those will need to be re-counted.
178 | if ( 'attachment' !== $post->post_type ) {
179 | $attachments = new WP_Query( array(
180 | 'post_type' => 'attachment',
181 | 'post_parent' => $post->ID,
182 | 'post_status' => 'inherit',
183 | 'ignore_sticky_posts' => true,
184 | 'no_found_rows' => true,
185 | 'posts_per_page' => -1,
186 | 'fields' => 'ids',
187 | 'orderby' => 'ID',
188 | 'order' => 'ASC',
189 | ) );
190 |
191 | if ( $attachments->have_posts() ) {
192 | foreach ( $attachments->posts as $attachment_id ) {
193 | $this->transition_post_status( $new_status, $old_status, (object) array(
194 | 'ID' => $attachment_id,
195 | 'post_type' => 'attachment',
196 | ) );
197 | }
198 | }
199 | }
200 | }
201 |
202 | /**
203 | * Update term counts using a very light SQL query.
204 | *
205 | * @param int $object_id Object ID with the term relationship.
206 | * @param array $tt_ids Term taxonomy IDs.
207 | * @param string $taxonomy Taxonomy slug.
208 | * @param string $transition_type 'increment' or 'decrement'.
209 | */
210 | public function quick_update_terms_count( $object_id, $tt_ids, $taxonomy, $transition_type ) {
211 | global $wpdb;
212 |
213 | if ( ! $transition_type ) {
214 | return false;
215 | }
216 |
217 | $tax_obj = get_taxonomy( $taxonomy );
218 | if ( $tax_obj ) {
219 | $tt_ids = array_filter( array_map( 'intval', (array) $tt_ids ) );
220 |
221 | // Respect if a taxonomy has a callback override.
222 | if ( ! empty( $tax_obj->update_count_callback ) ) {
223 | call_user_func( $tax_obj->update_count_callback, $tt_ids, $tax_obj );
224 | } elseif ( ! empty( $tt_ids ) ) {
225 | if ( ! isset( $this->counted_terms[ $object_id ][ $taxonomy ][ $transition_type ] ) ) {
226 | $this->counted_terms[ $object_id ][ $taxonomy ][ $transition_type ] = array();
227 | }
228 |
229 | // Ensure that these terms haven't already been counted.
230 | $tt_ids = array_diff( $tt_ids, $this->counted_terms[ $object_id ][ $taxonomy ][ $transition_type ] );
231 |
232 | if ( empty( $tt_ids ) ) {
233 | // No term to process. So return.
234 | return;
235 | }
236 |
237 | $this->counted_terms[ $object_id ][ $taxonomy ][ $transition_type ] = array_merge(
238 | $this->counted_terms[ $object_id ][ $taxonomy ][ $transition_type ],
239 | $tt_ids
240 | );
241 |
242 | $tt_ids = array_map( 'absint', $tt_ids );
243 | $tt_ids_string = '(' . implode( ',', $tt_ids ) . ')';
244 |
245 | if ( 'increment' === $transition_type ) {
246 | // Incrementing.
247 | $update_query = "UPDATE {$wpdb->term_taxonomy} AS tt SET tt.count = tt.count + 1 WHERE tt.term_taxonomy_id IN $tt_ids_string";
248 | } else {
249 | // Decrementing.
250 | $update_query = "UPDATE {$wpdb->term_taxonomy} AS tt SET tt.count = tt.count - 1 WHERE tt.term_taxonomy_id IN $tt_ids_string AND tt.count > 0";
251 | }
252 |
253 | foreach ( $tt_ids as $tt_id ) {
254 | /** This action is documented in wp-includes/taxonomy.php */
255 | do_action( 'edit_term_taxonomy', $tt_id, $taxonomy );
256 | }
257 | $wpdb->query( $update_query ); // WPCS: unprepared SQL ok.
258 | foreach ( $tt_ids as $tt_id ) {
259 | /** This action is documented in wp-includes/taxonomy.php */
260 | do_action( 'edited_term_taxonomy', $tt_id, $taxonomy );
261 | }
262 | } // End if().
263 |
264 | clean_term_cache( $tt_ids, '', false );
265 | } // End if().
266 | }
267 |
268 | /**
269 | * Determine if a term count should be incremented or decremented.
270 | *
271 | * @param string $new New post status.
272 | * @param string $old Old post status.
273 | * @return string|bool 'increment', 'decrement', or false.
274 | */
275 | public function transition_type( $new, $old ) {
276 | if ( ! is_array( $this->counted_statuses ) || ! $this->counted_statuses ) {
277 | return false;
278 | }
279 |
280 | $new_is_counted = in_array( $new, $this->counted_statuses, true );
281 | $old_is_counted = in_array( $old, $this->counted_statuses, true );
282 |
283 | if ( $new_is_counted && ! $old_is_counted ) {
284 | return 'increment';
285 | } elseif ( $old_is_counted && ! $new_is_counted ) {
286 | return 'decrement';
287 | } else {
288 | return false;
289 | }
290 | }
291 |
292 | /**
293 | * Force-recount posts for a term. Do this only when the update originates from the edit term screen.
294 | *
295 | * @param int $term_id the term id.
296 | * @param int $tt_id the term taxonomy id.
297 | * @param string $taxonomy the taxonomy.
298 | *
299 | * @return bool false if the screen check fails, true otherwise
300 | */
301 | public function maybe_recount_posts_for_term( $term_id, $tt_id, $taxonomy ) {
302 | $screen = function_exists( 'get_current_screen' ) ? get_current_screen() : '';
303 | if ( ! ( $screen instanceof WP_Screen ) ) {
304 | return false;
305 | }
306 | if ( "edit-$taxonomy" === $screen->id ) {
307 | wp_update_term_count_now( array( $tt_id ), $taxonomy );
308 | }
309 | return true;
310 | }
311 | }
312 |
313 | // Only run this plugin if we're not running a cron task or wp-cli task.
314 | if (
315 | ! ( defined( 'DOING_CRON' ) && DOING_CRON )
316 | && ! ( defined( 'WP_CLI' ) && WP_CLI )
317 | && ! ( defined( 'WP_IMPORTING' ) && WP_IMPORTING )
318 | ) {
319 | add_action( 'init', array( 'LTCU_Plugin', 'instance' ) );
320 | }
321 |
--------------------------------------------------------------------------------
/multisite.xml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 | tests
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 |
2 | {
3 | "name": "lightweight-term-count-update",
4 | "version": "0.1.0",
5 | "main": "Gruntfile.js",
6 | "author": "YOUR NAME HERE",
7 | "devDependencies": {
8 | "grunt": "~0.4.5",
9 | "grunt-wp-i18n": "~0.5.0",
10 | "grunt-wp-readme-to-markdown": "~1.0.0"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/phpcs.ruleset.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Generally-applicable sniffs for WordPress plugins
4 |
5 |
6 |
7 | vendor/*
8 | node_modules/*
9 |
10 |
11 | warning
12 |
13 |
14 | warning
15 |
16 |
17 |
18 |
19 | warning
20 |
21 |
22 |
--------------------------------------------------------------------------------
/phpunit.xml.dist:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 | ./tests/
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/readme.txt:
--------------------------------------------------------------------------------
1 | === Cronify Term Count Update ===
2 | Contributors: Automattic, alleyinteractive
3 | Tags: performance, post-save
4 | Requires at least: 4.7
5 | Tested up to: 4.7.3
6 | Stable tag: 0.1.0
7 | License: GPLv2 or later
8 | License URI: http://www.gnu.org/licenses/gpl-2.0.html
9 |
10 | This plugin deferres the _update_term_count_on_transition_post_status action to cron
11 |
12 | == Description ==
13 |
14 | Sometimes the term count update hooked to the transition_post_status action may slow down the post_save action. This plugin offloads the action to cron, so it does no block the post_save action.
15 |
16 | == Installation ==
17 |
18 | 1. Upload this plugin to the `/wp-content/plugins/` directory
19 | 1. Activate the plugin through the 'Plugins' menu in WordPress
20 |
21 | == Changelog ==
22 |
23 | = 0.1.0 =
24 | Initial version
25 |
--------------------------------------------------------------------------------
/tests/bootstrap.php:
--------------------------------------------------------------------------------
1 | counted_terms = array();
18 | }
19 |
20 | /**
21 | * Create and return a test category.
22 | *
23 | * @return \WP_Term
24 | */
25 | protected function make_category() {
26 | return self::factory()->category->create_and_get(
27 | array(
28 | 'slug' => 'mytestcat',
29 | 'name' => 'My Test Category 1',
30 | )
31 | );
32 | }
33 |
34 | /**
35 | * Test a single post publish action with a single category
36 | */
37 | function test_single_post_publish_with_a_single_category() {
38 |
39 | // Create Test Category.
40 | $testcat = $this->make_category();
41 |
42 | $post_id = self::factory()->post->create( array(
43 | 'post_type' => 'post',
44 | 'post_title' => 'Test post 1',
45 | 'post_status' => 'publish',
46 | 'post_category' => array( $testcat->term_id ),
47 | ) );
48 |
49 | $category = get_term( $testcat->term_id, 'category' );
50 |
51 | $this->assertEquals( $testcat->count + 1, $category->count );
52 | }
53 |
54 | /**
55 | * Test multiple posts counting
56 | */
57 | function test_multiple_posts_counting() {
58 | // Create a test category.
59 | $testcat = $this->make_category();
60 |
61 | self::factory()->post->create_many( 3, array(
62 | 'post_type' => 'post',
63 | 'post_status' => 'publish',
64 | 'post_category' => array( $testcat->term_id ),
65 | ) );
66 |
67 | $category = get_term( $testcat->term_id, 'category' );
68 |
69 | $this->assertEquals( $testcat->count + 3, $category->count );
70 | }
71 |
72 | /**
73 | * Test post unpublish action
74 | */
75 | function test_post_unpublish() {
76 | $testcat = $this->make_category();
77 |
78 | $post_id = self::factory()->post->create( array(
79 | 'post_type' => 'post',
80 | 'post_status' => 'publish',
81 | 'post_category' => array( $testcat->term_id ),
82 | ) );
83 |
84 | wp_update_post( array( 'ID' => $post_id, 'post_status' => 'draft' ) );
85 |
86 | $category = get_term( $testcat->term_id, 'category' );
87 |
88 | $this->assertEquals( $testcat->count, $category->count );
89 | }
90 |
91 | function test_set_object_terms() {
92 | // Create a test category.
93 | $testcat = $this->make_category();
94 |
95 | $post_ids = self::factory()->post->create_many( 3, array(
96 | 'post_type' => 'post',
97 | 'post_status' => 'publish',
98 | ) );
99 |
100 | wp_set_object_terms( $post_ids[0], $testcat->term_id, 'category' );
101 |
102 | $category = get_term( $testcat->term_id, 'category' );
103 |
104 | $this->assertEquals( $testcat->count + 1, $category->count );
105 | }
106 |
107 | function test_remove_object_terms() {
108 | // Create a test category.
109 | $testcat = $this->make_category();
110 |
111 | $post_ids = self::factory()->post->create_many( 3, array(
112 | 'post_type' => 'post',
113 | 'post_status' => 'publish',
114 | 'post_category' => array( $testcat->term_id ),
115 | ) );
116 |
117 | wp_remove_object_terms( $post_ids[0], $testcat->term_id, 'category' );
118 |
119 | $category = get_term( $testcat->term_id, 'category' );
120 |
121 | $this->assertEquals( $testcat->count + 2, $category->count );
122 | }
123 |
124 | /**
125 | * Data provider to test status changes.
126 | *
127 | * @return array
128 | */
129 | public function term_counts_data() {
130 | return array(
131 | array( 'publish', 'publish' ),
132 | array( 'draft', 'publish' ),
133 | array( 'publish', 'draft' ),
134 | array( 'draft', 'draft' ),
135 | );
136 | }
137 |
138 | /**
139 | * @dataProvider term_counts_data
140 | * @param string $old_status Post status to transition from.
141 | * @param string $new_status Post status to transition to.
142 | */
143 | function test_set_object_terms_with_status_changes( $old_status, $new_status ) {
144 | // Create a test category.
145 | $testcat = $this->make_category();
146 |
147 | $post_ids = self::factory()->post->create_many( 3, array(
148 | 'post_type' => 'post',
149 | 'post_status' => $old_status,
150 | ) );
151 |
152 | // Reset the counted terms cache to mimic pre-existing posts.
153 | LTCU_Plugin::instance()->counted_terms = array();
154 |
155 | wp_update_post( array(
156 | 'ID' => $post_ids[0],
157 | 'post_status' => $new_status,
158 | ) );
159 | wp_set_object_terms( $post_ids[0], $testcat->term_id, 'category' );
160 |
161 | $category = get_term( $testcat->term_id, 'category' );
162 |
163 | $change = ( 'publish' === $new_status ) ? 1 : 0;
164 | $this->assertEquals( $testcat->count + $change, $category->count );
165 | }
166 |
167 | /**
168 | * @dataProvider term_counts_data
169 | * @param string $old_status Post status to transition from.
170 | * @param string $new_status Post status to transition to.
171 | */
172 | function test_remove_object_terms_with_status_changes( $old_status, $new_status ) {
173 | // Create a test category.
174 | $testcat = $this->make_category();
175 |
176 | $post_ids = self::factory()->post->create_many( 3, array(
177 | 'post_type' => 'post',
178 | 'post_status' => $old_status,
179 | 'post_category' => array( $testcat->term_id ),
180 | ) );
181 |
182 | // Reset the counted terms cache to mimic pre-existing posts.
183 | LTCU_Plugin::instance()->counted_terms = array();
184 |
185 | wp_update_post( array(
186 | 'ID' => $post_ids[0],
187 | 'post_status' => $new_status,
188 | 'post_date' => '2017-01-01 12:34:56',
189 | ) );
190 | wp_remove_object_terms( $post_ids[0], $testcat->term_id, 'category' );
191 |
192 | $category = get_term( $testcat->term_id, 'category' );
193 |
194 | $change = ( 'draft' === $old_status ) ? 0 : 2;
195 | $this->assertEquals( $testcat->count + $change, $category->count );
196 | }
197 |
198 | function test_post_update_removing_categories() {
199 | // Create a test category.
200 | $testcat = $this->make_category();
201 |
202 | $post_id = self::factory()->post->create( array(
203 | 'post_type' => 'post',
204 | 'post_status' => 'publish',
205 | 'post_category' => array( $testcat->term_id ),
206 | ) );
207 |
208 | // Reset the counted terms cache to mimic pre-existing posts.
209 | LTCU_Plugin::instance()->counted_terms = array();
210 |
211 | $testcat2 = self::factory()->category->create_and_get();
212 |
213 | wp_update_post( array(
214 | 'ID' => $post_id,
215 | 'post_category' => array( $testcat2->term_id ),
216 | ) );
217 |
218 | $category = get_term( $testcat->term_id, 'category' );
219 |
220 | $this->assertEquals( 0, $category->count );
221 |
222 | $category2 = get_term( $testcat2->term_id, 'category' );
223 |
224 | $this->assertEquals( $testcat2->count + 1, $category2->count );
225 | }
226 |
227 | /**
228 | * Categories with a parent are being reflected in category count
229 | * in case the parent post has publish post status
230 | */
231 | function test_attachments_with_inherit_post_status_categories() {
232 | // Create a test category.
233 | $testcat = $this->make_category();
234 |
235 | register_taxonomy_for_object_type( 'category', 'attachment' );
236 |
237 | $post_id = self::factory()->post->create( array(
238 | 'post_type' => 'post',
239 | 'post_status' => 'publish',
240 | ) );
241 |
242 | $attachment_id = self::factory()->attachment->create( array(
243 | 'post_parent' => $post_id,
244 | ) );
245 |
246 | // Reset the counted terms cache to mimic pre-existing posts.
247 | LTCU_Plugin::instance()->counted_terms = array();
248 |
249 | wp_update_post( array(
250 | 'ID' => $attachment_id,
251 | 'post_category' => array( $testcat->term_id ),
252 | ) );
253 |
254 | $category = get_term( $testcat->term_id, 'category' );
255 |
256 | $this->assertEquals( $testcat->count + 1, $category->count );
257 | }
258 |
259 | /**
260 | * Categories w/o parent have, by default, post_status set by inherit
261 | * and WordPress does not currently reflect them in category counts
262 | * {@see https://core.trac.wordpress.org/ticket/22558} and
263 | * {@see https://core.trac.wordpress.org/ticket/23530}. However, they should
264 | * be included and so this plugin does count them. If this behavior is left
265 | * as a "won't fix" in core, this plugin might change how it works to remain
266 | * inline with core.
267 | */
268 | function test_non_attached_attachments_categories() {
269 | // Create a test category.
270 | $testcat = $this->make_category();
271 |
272 | register_taxonomy_for_object_type( 'category', 'attachment' );
273 |
274 | $attachment_id = self::factory()->attachment->create( array() );
275 |
276 | // Reset the counted terms cache to mimic pre-existing posts.
277 | LTCU_Plugin::instance()->counted_terms = array();
278 |
279 | wp_update_post( array(
280 | 'ID' => $attachment_id,
281 | 'post_category' => array( $testcat->term_id ),
282 | ) );
283 |
284 | $category = get_term( $testcat->term_id, 'category' );
285 |
286 | $this->assertEquals( $testcat->count + 1, $category->count );
287 | }
288 |
289 | /**
290 | * Attachments with post_status inherit should be counted in the category
291 | * count in case their parent is published
292 | */
293 | function test_post_publish_of_post_with_attachments() {
294 | // Create a test category.
295 | $testcat = $this->make_category();
296 |
297 | register_taxonomy_for_object_type( 'category', 'attachment' );
298 |
299 | $post_id = self::factory()->post->create( array(
300 | 'post_type' => 'post',
301 | 'post_status' => 'draft',
302 | 'post_category' => array( $testcat->term_id ),
303 | ) );
304 |
305 | self::factory()->attachment->create_many( 11, array(
306 | 'post_parent' => $post_id,
307 | 'post_category' => array( $testcat->term_id ),
308 | ) );
309 |
310 | // Reset the counted terms cache to mimic pre-existing posts.
311 | LTCU_Plugin::instance()->counted_terms = array();
312 |
313 | wp_update_post( array(
314 | 'ID' => $post_id,
315 | 'post_status' => 'publish',
316 | ) );
317 |
318 | $category = get_term( $testcat->term_id, 'category' );
319 |
320 | $this->assertEquals( $testcat->count + 12, $category->count );
321 | }
322 |
323 | /**
324 | * Test non-post taxonomy
325 | * @see: http://justintadlock.com/archives/2011/10/20/custom-user-taxonomies-in-wordpress
326 | */
327 | function test_non_post_taxonomy() {
328 | register_taxonomy(
329 | 'profession',
330 | 'user',
331 | array(
332 | 'public' => true,
333 | )
334 | );
335 | $testterm_array = wp_create_term( 'Developer', 'profession' );
336 |
337 | $testterm = get_term( $testterm_array['term_id'], 'profession' );
338 |
339 | $user_id = self::factory()->user->create();
340 |
341 | wp_set_object_terms( $user_id, $testterm->term_id, 'profession' );
342 |
343 | $term = get_term( $testterm->term_id, 'profession' );
344 |
345 | $this->assertEquals( $testterm->count + 1, $term->count );
346 | }
347 |
348 | /**
349 | * Test custom count callback of a custom taxonomy
350 | */
351 | function test_custom_count_callback() {
352 | register_taxonomy(
353 | 'test-taxonomy',
354 | 'post',
355 | array(
356 | 'public' => true,
357 | 'update_count_callback' => function( $terms, $taxonomy ) {
358 | global $wpdb;
359 |
360 | //confirm parameters are as expected
361 | $this->assertTrue( is_int($terms) || is_array( $terms ) );
362 | $this->assertInstanceOf( 'WP_Taxonomy', $taxonomy );
363 |
364 | foreach ( (array) $terms as $term ) {
365 |
366 | $count = 10;
367 |
368 | do_action( 'edit_term_taxonomy', $term, $taxonomy );
369 | $wpdb->update( $wpdb->term_taxonomy, compact( 'count' ), array( 'term_taxonomy_id' => $term ) );
370 | do_action( 'edited_term_taxonomy', $term, $taxonomy );
371 | }
372 | },
373 | )
374 | );
375 | $testterm_array = wp_create_term( 'Test term', 'test-taxonomy' );
376 |
377 | $testterm = get_term( $testterm_array['term_id'], 'test-taxonomy' );
378 |
379 | $post_id = self::factory()->post->create( array(
380 | 'post_type' => 'post',
381 | 'post_status' => 'publish',
382 | ) );
383 |
384 | // Reset the counted terms cache to mimic pre-existing posts.
385 | LTCU_Plugin::instance()->counted_terms = array();
386 |
387 | wp_set_object_terms( $post_id, $testterm->term_id, 'test-taxonomy' );
388 |
389 | $term = get_term( $testterm->term_id, 'test-taxonomy' );
390 |
391 | $this->assertEquals( 10, $term->count );
392 | }
393 |
394 |
395 | /**
396 | * Data provider to test actions fired on update.
397 | *
398 | * @return array
399 | */
400 | public function actions_data() {
401 | return array(
402 | array( 'edit_term_taxonomy' ),
403 | array( 'edited_term_taxonomy' ),
404 | );
405 | }
406 |
407 | /**
408 | * @dataProvider actions_data
409 | * @param string $action Action to be fired.
410 | */
411 | function test_actins_being_fired( $action ) {
412 | // Create a test category.
413 | $testcats = self::factory()->category->create_many( 3 );
414 |
415 | // Reset the counted terms cache to mimic pre-existing posts.
416 | LTCU_Plugin::instance()->counted_terms = array();
417 |
418 | // Hook test action.
419 | $GLOBALS['ltcu_fired_action_tt_ids'] = array();
420 | $GLOBALS['ltcu_fired_action_taxonomy'] = '';
421 | add_action( $action, function( $tt_id, $taxonomy ) {
422 | $GLOBALS['ltcu_fired_action_tt_ids'][] = $tt_id;
423 | $GLOBALS['ltcu_fired_action_taxonomy'] = $taxonomy;
424 | }, 10, 2 );
425 |
426 | $post_id = self::factory()->post->create( array(
427 | 'post_type' => 'post',
428 | 'post_status' => 'publish',
429 | 'post_category' => $testcats,
430 | ) );
431 |
432 | wp_set_object_terms( $post_id, $testcats, 'category' );
433 |
434 | // Prepare the comparison.
435 | $tt_ids = array();
436 | foreach ( $testcats as $term_id ) {
437 | $term = get_term( $term_id, 'category' );
438 | $tt_ids[] = $term->term_taxonomy_id;
439 | }
440 |
441 | $this->assertEquals( sort( $GLOBALS['ltcu_fired_action_tt_ids'] ) , sort( $tt_ids ) );
442 | $this->assertEquals( 'category', $GLOBALS['ltcu_fired_action_taxonomy'] );
443 | }
444 |
445 | /**
446 | * Test that the first draft of a post gets terms set properly and the term
447 | * cache is cleared.
448 | *
449 | * {@see https://github.com/Automattic/lightweight-term-count-update/pull/8}
450 | */
451 | function test_first_draft_save() {
452 | // Create Test Category.
453 | $testcat = $this->make_category();
454 |
455 | // Create the blank post object to mimic the "Write" screen.
456 | $post = get_default_post_to_edit( 'post', true );
457 | $post_id = $post->ID;
458 |
459 | // Save a draft of the post.
460 | wp_update_post( array(
461 | 'ID' => $post_id,
462 | 'post_status' => 'draft',
463 | 'post_title' => 'some-post',
464 | 'post_type' => 'post',
465 | 'post_content' => 'some_content',
466 | 'post_category' => array( $testcat->term_id ),
467 | ) );
468 |
469 | // Ensure that caches were cleared.
470 | $terms = get_the_terms( $post_id, 'category' );
471 |
472 | $this->assertTrue( is_array( $terms ) );
473 | $this->assertSame( array( $testcat->term_id ), wp_list_pluck( $terms, 'term_id' ) );
474 | }
475 | }
476 |
--------------------------------------------------------------------------------