installed plugin Jetpack Protect
version 1.0.2
This commit is contained in:
@ -0,0 +1,312 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [1.17.20] - 2022-07-26
|
||||
### Changed
|
||||
- Updated package dependencies. [#25158]
|
||||
|
||||
## [1.17.19] - 2022-07-12
|
||||
### Changed
|
||||
- Updated package dependencies.
|
||||
|
||||
## [1.17.18] - 2022-07-06
|
||||
### Changed
|
||||
- Updated package dependencies
|
||||
|
||||
## [1.17.17] - 2022-06-21
|
||||
### Changed
|
||||
- Renaming master to trunk.
|
||||
|
||||
## [1.17.16] - 2022-06-14
|
||||
|
||||
## [1.17.15] - 2022-06-08
|
||||
### Changed
|
||||
- Reorder JS imports for `import/order` eslint rule. [#24601]
|
||||
|
||||
## [1.17.14] - 2022-05-18
|
||||
### Changed
|
||||
- Updated package dependencies [#24372]
|
||||
|
||||
## [1.17.13] - 2022-05-10
|
||||
### Changed
|
||||
- Updated package dependencies. [#24302]
|
||||
|
||||
## [1.17.12] - 2022-05-04
|
||||
### Added
|
||||
- Add missing JavaScript dependencies, and fix a test. [#24096]
|
||||
|
||||
## [1.17.11] - 2022-04-26
|
||||
### Changed
|
||||
- Updated package dependencies.
|
||||
|
||||
## [1.17.10] - 2022-04-19
|
||||
### Fixed
|
||||
- Assets: Defer the enqueued script instead of its translations
|
||||
|
||||
## [1.17.9] - 2022-04-05
|
||||
### Changed
|
||||
- Updated package dependencies.
|
||||
|
||||
## [1.17.8] - 2022-03-29
|
||||
### Changed
|
||||
- Updated package dependencies.
|
||||
|
||||
## [1.17.7] - 2022-03-23
|
||||
### Changed
|
||||
- Updated package dependencies.
|
||||
|
||||
## [1.17.6] - 2022-03-02
|
||||
### Changed
|
||||
- Updated package dependencies.
|
||||
|
||||
## [1.17.5] - 2022-02-16
|
||||
### Changed
|
||||
- Updated package dependencies.
|
||||
|
||||
## [1.17.4] - 2022-02-09
|
||||
### Changed
|
||||
- Updated package dependencies.
|
||||
|
||||
## [1.17.3] - 2022-02-02
|
||||
### Fixed
|
||||
- Fixed minor coding standard violation.
|
||||
|
||||
## [1.17.2] - 2022-02-01
|
||||
### Changed
|
||||
- Build: remove unneeded files from production build.
|
||||
|
||||
## [1.17.1] - 2022-01-27
|
||||
### Changed
|
||||
- Updated package dependencies.
|
||||
|
||||
## [1.17.0] - 2022-01-25
|
||||
### Added
|
||||
- Accept package path prefixes from jetpack-composer-plugin and use them when lazy-loading JS translations.
|
||||
- Generate the `wp-jp-i18n-loader` module needed by the new i18n-loader-webpack-plugin.
|
||||
|
||||
### Deprecated
|
||||
- Deprecated the `wp-jp-i18n-state` module.
|
||||
|
||||
## [1.16.2] - 2022-01-18
|
||||
### Fixed
|
||||
- Handle the case where `WP_LANG_DIR` is in `WP_CONTENT_DIR`, but `WP_CONTENT_DIR` is not in `ABSPATH`.
|
||||
|
||||
## [1.16.1] - 2022-01-05
|
||||
### Fixed
|
||||
- Don't issue a "doing it wrong" warning for registering aliases during plugin activation.
|
||||
|
||||
## [1.16.0] - 2022-01-04
|
||||
### Added
|
||||
- Document use of jetpack-assets, jetpack-composer-plugin, and i18n-loader-webpack-plugin together.
|
||||
|
||||
### Changed
|
||||
- Switch to pcov for code coverage.
|
||||
- Updated package dependencies
|
||||
- Updated package textdomain from `jetpack` to `jetpack-assets`.
|
||||
|
||||
## [1.15.0] - 2021-12-20
|
||||
### Added
|
||||
- Add `alias_textdomain()`.
|
||||
|
||||
## [1.14.0] - 2021-12-14
|
||||
### Added
|
||||
- Generate `wp-jp-i18n-state` script.
|
||||
|
||||
## [1.13.1] - 2021-11-22
|
||||
### Fixed
|
||||
- Call `_doing_it_wrong` correctly.
|
||||
|
||||
## [1.13.0] - 2021-11-22
|
||||
### Added
|
||||
- Have `Assets::register_script()` accept a textdomain for `wp_set_script_translations` (and complain if no textdomain is passed when `wp-i18n` is depended on).
|
||||
|
||||
### Changed
|
||||
- Updated package dependencies
|
||||
|
||||
### Fixed
|
||||
- Added missing option doc for `Assets::register_script()`.
|
||||
|
||||
## [1.12.0] - 2021-11-15
|
||||
### Added
|
||||
- Add `Assets::register_script()` for easier loading of Webpack-built scripts.
|
||||
|
||||
## [1.11.10] - 2021-11-02
|
||||
### Changed
|
||||
- Set `convertDeprecationsToExceptions` true in PHPUnit config.
|
||||
- Update PHPUnit configs to include just what needs coverage rather than include everything then try to exclude stuff that doesn't.
|
||||
|
||||
## [1.11.9] - 2021-10-13
|
||||
### Changed
|
||||
- Updated package dependencies.
|
||||
|
||||
## [1.11.8] - 2021-10-06
|
||||
### Changed
|
||||
- Updated package dependencies
|
||||
|
||||
## [1.11.7] - 2021-09-28
|
||||
### Changed
|
||||
- Updated package dependencies.
|
||||
|
||||
## [1.11.6] - 2021-08-30
|
||||
### Changed
|
||||
- Run composer update on test-php command instead of phpunit
|
||||
- Tests: update PHPUnit polyfills dependency (yoast/phpunit-polyfills).
|
||||
- update annotations versions
|
||||
|
||||
## [1.11.5] - 2021-05-25
|
||||
### Changed
|
||||
- Updated package dependencies.
|
||||
|
||||
## [1.11.4] - 2021-04-08
|
||||
### Changed
|
||||
- Packaging and build changes, no change to the package itself.
|
||||
|
||||
## [1.11.3] - 2021-03-30
|
||||
### Added
|
||||
- Composer alias for dev-master, to improve dependencies
|
||||
|
||||
### Changed
|
||||
- Update package dependencies.
|
||||
|
||||
### Fixed
|
||||
- Use `composer update` rather than `install` in scripts, as composer.lock isn't checked in.
|
||||
|
||||
## [1.11.2] - 2021-02-23
|
||||
|
||||
- CI: Make tests more generic
|
||||
|
||||
## [1.11.1] - 2021-01-26
|
||||
|
||||
- Add mirror-repo information to all current composer packages
|
||||
- Monorepo: Reorganize all projects
|
||||
|
||||
## [1.11.0] - 2021-01-05
|
||||
|
||||
- Update dependency brain/monkey to v2.6.0
|
||||
|
||||
## [1.10.0] - 2020-12-08
|
||||
|
||||
- Assets: introduce new method to process static resources
|
||||
- Assets: Use defer for script tags
|
||||
- Pin dependencies
|
||||
- Packages: Update for PHP 8 testing
|
||||
|
||||
## [1.9.1] - 2020-11-24
|
||||
|
||||
- Update dependency brain/monkey to v2.5.0
|
||||
- Updated PHPCS: Packages and Debugger
|
||||
|
||||
## [1.9.0] - 2020-10-27
|
||||
|
||||
- Instagram oEmbed: Simplify
|
||||
|
||||
## [1.8.0] - 2020-09-29
|
||||
|
||||
- Consolidate the Lazy Images package to rely on the Assets package
|
||||
|
||||
## [1.7.0] - 2020-08-25
|
||||
|
||||
- Packages: Update filenames after #16810
|
||||
- CI: Try collect js coverage
|
||||
- Docker: Add package testing shortcut
|
||||
|
||||
## [1.6.0] - 2020-07-28
|
||||
|
||||
- Various: Use wp_resource_hints
|
||||
|
||||
## [1.5.0] - 2020-06-30
|
||||
|
||||
- PHPCS: Clean up the packages
|
||||
- WooCommerce Analytics: avoid 404 error when enqueuing script
|
||||
|
||||
## [1.4.0] - 2020-05-26
|
||||
|
||||
- Add Jetpack Scan threat notifications
|
||||
|
||||
## [1.3.0] - 2020-04-28
|
||||
|
||||
- Update dependencies to latest stable
|
||||
|
||||
## [1.2.0] - 2020-03-31
|
||||
|
||||
- Update dependencies to latest stable
|
||||
|
||||
## [1.1.1] - 2020-01-27
|
||||
|
||||
- Pin dependency brain/monkey to 2.4.0
|
||||
|
||||
## [1.1.0] - 2020-01-14
|
||||
|
||||
- Packages: Various improvements for wp.com or self-contained consumers
|
||||
|
||||
## [1.0.3] - 2019-11-08
|
||||
|
||||
- Packages: Use classmap instead of PSR-4
|
||||
|
||||
## [1.0.1] - 2019-10-28
|
||||
|
||||
- PHPCS: JITM and Assets packages
|
||||
- Packages: Add gitattributes files to all packages that need th…
|
||||
|
||||
## 1.0.0 - 2019-09-14
|
||||
|
||||
- Statically access asset tools
|
||||
|
||||
[1.17.20]: https://github.com/Automattic/jetpack-assets/compare/v1.17.19...v1.17.20
|
||||
[1.17.19]: https://github.com/Automattic/jetpack-assets/compare/v1.17.18...v1.17.19
|
||||
[1.17.18]: https://github.com/Automattic/jetpack-assets/compare/v1.17.17...v1.17.18
|
||||
[1.17.17]: https://github.com/Automattic/jetpack-assets/compare/v1.17.16...v1.17.17
|
||||
[1.17.16]: https://github.com/Automattic/jetpack-assets/compare/v1.17.15...v1.17.16
|
||||
[1.17.15]: https://github.com/Automattic/jetpack-assets/compare/v1.17.14...v1.17.15
|
||||
[1.17.14]: https://github.com/Automattic/jetpack-assets/compare/v1.17.13...v1.17.14
|
||||
[1.17.13]: https://github.com/Automattic/jetpack-assets/compare/v1.17.12...v1.17.13
|
||||
[1.17.12]: https://github.com/Automattic/jetpack-assets/compare/v1.17.11...v1.17.12
|
||||
[1.17.11]: https://github.com/Automattic/jetpack-assets/compare/v1.17.10...v1.17.11
|
||||
[1.17.10]: https://github.com/Automattic/jetpack-assets/compare/v1.17.9...v1.17.10
|
||||
[1.17.9]: https://github.com/Automattic/jetpack-assets/compare/v1.17.8...v1.17.9
|
||||
[1.17.8]: https://github.com/Automattic/jetpack-assets/compare/v1.17.7...v1.17.8
|
||||
[1.17.7]: https://github.com/Automattic/jetpack-assets/compare/v1.17.6...v1.17.7
|
||||
[1.17.6]: https://github.com/Automattic/jetpack-assets/compare/v1.17.5...v1.17.6
|
||||
[1.17.5]: https://github.com/Automattic/jetpack-assets/compare/v1.17.4...v1.17.5
|
||||
[1.17.4]: https://github.com/Automattic/jetpack-assets/compare/v1.17.3...v1.17.4
|
||||
[1.17.3]: https://github.com/Automattic/jetpack-assets/compare/v1.17.2...v1.17.3
|
||||
[1.17.2]: https://github.com/Automattic/jetpack-assets/compare/v1.17.1...v1.17.2
|
||||
[1.17.1]: https://github.com/Automattic/jetpack-assets/compare/v1.17.0...v1.17.1
|
||||
[1.17.0]: https://github.com/Automattic/jetpack-assets/compare/v1.16.2...v1.17.0
|
||||
[1.16.2]: https://github.com/Automattic/jetpack-assets/compare/v1.16.1...v1.16.2
|
||||
[1.16.1]: https://github.com/Automattic/jetpack-assets/compare/v1.16.0...v1.16.1
|
||||
[1.16.0]: https://github.com/Automattic/jetpack-assets/compare/v1.15.0...v1.16.0
|
||||
[1.15.0]: https://github.com/Automattic/jetpack-assets/compare/v1.14.0...v1.15.0
|
||||
[1.14.0]: https://github.com/Automattic/jetpack-assets/compare/v1.13.1...v1.14.0
|
||||
[1.13.1]: https://github.com/Automattic/jetpack-assets/compare/v1.13.0...v1.13.1
|
||||
[1.13.0]: https://github.com/Automattic/jetpack-assets/compare/v1.12.0...v1.13.0
|
||||
[1.12.0]: https://github.com/Automattic/jetpack-assets/compare/v1.11.10...v1.12.0
|
||||
[1.11.10]: https://github.com/Automattic/jetpack-assets/compare/v1.11.9...v1.11.10
|
||||
[1.11.9]: https://github.com/Automattic/jetpack-assets/compare/v1.11.8...v1.11.9
|
||||
[1.11.8]: https://github.com/Automattic/jetpack-assets/compare/v1.11.7...v1.11.8
|
||||
[1.11.7]: https://github.com/Automattic/jetpack-assets/compare/v1.11.6...v1.11.7
|
||||
[1.11.6]: https://github.com/Automattic/jetpack-assets/compare/v1.11.5...v1.11.6
|
||||
[1.11.5]: https://github.com/Automattic/jetpack-assets/compare/v1.11.4...v1.11.5
|
||||
[1.11.4]: https://github.com/Automattic/jetpack-assets/compare/v1.11.3...v1.11.4
|
||||
[1.11.3]: https://github.com/Automattic/jetpack-assets/compare/v1.11.2...v1.11.3
|
||||
[1.11.2]: https://github.com/Automattic/jetpack-assets/compare/v1.11.1...v1.11.2
|
||||
[1.11.1]: https://github.com/Automattic/jetpack-assets/compare/v1.11.0...v1.11.1
|
||||
[1.11.0]: https://github.com/Automattic/jetpack-assets/compare/v1.10.0...v1.11.0
|
||||
[1.10.0]: https://github.com/Automattic/jetpack-assets/compare/v1.9.1...v1.10.0
|
||||
[1.9.1]: https://github.com/Automattic/jetpack-assets/compare/v1.9.0...v1.9.1
|
||||
[1.9.0]: https://github.com/Automattic/jetpack-assets/compare/v1.8.0...v1.9.0
|
||||
[1.8.0]: https://github.com/Automattic/jetpack-assets/compare/v1.7.0...v1.8.0
|
||||
[1.7.0]: https://github.com/Automattic/jetpack-assets/compare/v1.6.0...v1.7.0
|
||||
[1.6.0]: https://github.com/Automattic/jetpack-assets/compare/v1.5.0...v1.6.0
|
||||
[1.5.0]: https://github.com/Automattic/jetpack-assets/compare/v1.4.0...v1.5.0
|
||||
[1.4.0]: https://github.com/Automattic/jetpack-assets/compare/v1.3.0...v1.4.0
|
||||
[1.3.0]: https://github.com/Automattic/jetpack-assets/compare/v1.2.0...v1.3.0
|
||||
[1.2.0]: https://github.com/Automattic/jetpack-assets/compare/v1.1.1...v1.2.0
|
||||
[1.1.1]: https://github.com/Automattic/jetpack-assets/compare/v1.1.0...v1.1.1
|
||||
[1.1.0]: https://github.com/Automattic/jetpack-assets/compare/v1.0.3...v1.1.0
|
||||
[1.0.3]: https://github.com/Automattic/jetpack-assets/compare/v1.0.1...v1.0.3
|
||||
[1.0.1]: https://github.com/Automattic/jetpack-assets/compare/v1.0.0...v1.0.1
|
@ -0,0 +1,357 @@
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
|
||||
===================================
|
||||
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
@ -0,0 +1,38 @@
|
||||
# Security Policy
|
||||
|
||||
Full details of the Automattic Security Policy can be found on [automattic.com](https://automattic.com/security/).
|
||||
|
||||
## Supported Versions
|
||||
|
||||
Generally, only the latest version of Jetpack has continued support. If a critical vulnerability is found in the current version of Jetpack, we may opt to backport any patches to previous versions.
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
[Jetpack](https://jetpack.com/) is an open-source plugin for WordPress. Our HackerOne program covers the plugin software, as well as a variety of related projects and infrastructure.
|
||||
|
||||
**For responsible disclosure of security issues and to be eligible for our bug bounty program, please submit your report via the [HackerOne](https://hackerone.com/automattic) portal.**
|
||||
|
||||
Our most critical targets are:
|
||||
|
||||
* Jetpack and the Jetpack composer packages (all within this repo)
|
||||
* Jetpack.com -- the primary marketing site.
|
||||
* cloud.jetpack.com -- a management site.
|
||||
* wordpress.com -- the shared management site for both Jetpack and WordPress.com sites.
|
||||
|
||||
For more targets, see the `In Scope` section on [HackerOne](https://hackerone.com/automattic).
|
||||
|
||||
_Please note that the **WordPress software is a separate entity** from Automattic. Please report vulnerabilities for WordPress through [the WordPress Foundation's HackerOne page](https://hackerone.com/wordpress)._
|
||||
|
||||
## Guidelines
|
||||
|
||||
We're committed to working with security researchers to resolve the vulnerabilities they discover. You can help us by following these guidelines:
|
||||
|
||||
* Follow [HackerOne's disclosure guidelines](https://www.hackerone.com/disclosure-guidelines).
|
||||
* Pen-testing Production:
|
||||
* Please **setup a local environment** instead whenever possible. Most of our code is open source (see above).
|
||||
* If that's not possible, **limit any data access/modification** to the bare minimum necessary to reproduce a PoC.
|
||||
* **_Don't_ automate form submissions!** That's very annoying for us, because it adds extra work for the volunteers who manage those systems, and reduces the signal/noise ratio in our communication channels.
|
||||
* To be eligible for a bounty, all of these guidelines must be followed.
|
||||
* Be Patient - Give us a reasonable time to correct the issue before you disclose the vulnerability.
|
||||
|
||||
We also expect you to comply with all applicable laws. You're responsible to pay any taxes associated with your bounties.
|
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
/**
|
||||
* Action Hooks for Jetpack Assets module.
|
||||
*
|
||||
* @package automattic/jetpack-assets
|
||||
*/
|
||||
|
||||
// If WordPress's plugin API is available already, use it. If not,
|
||||
// drop data into `$wp_filter` for `WP_Hook::build_preinitialized_hooks()`.
|
||||
if ( function_exists( 'add_action' ) ) {
|
||||
add_action( 'wp_default_scripts', array( Automattic\Jetpack\Assets::class, 'wp_default_scripts_hook' ) );
|
||||
} else {
|
||||
global $wp_filter;
|
||||
// phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
|
||||
$wp_filter['wp_default_scripts'][10][] = array(
|
||||
'accepted_args' => 1,
|
||||
'function' => array( Automattic\Jetpack\Assets::class, 'wp_default_scripts_hook' ),
|
||||
);
|
||||
}
|
@ -0,0 +1 @@
|
||||
<?php return array('dependencies' => array('wp-i18n'), 'version' => 'ee939953aa2115e2ca59');
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,57 @@
|
||||
{
|
||||
"name": "automattic/jetpack-assets",
|
||||
"description": "Asset management utilities for Jetpack ecosystem packages",
|
||||
"type": "jetpack-library",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"require": {
|
||||
"automattic/jetpack-constants": "^1.6"
|
||||
},
|
||||
"require-dev": {
|
||||
"brain/monkey": "2.6.1",
|
||||
"yoast/phpunit-polyfills": "1.0.3",
|
||||
"automattic/jetpack-changelogger": "^3.2",
|
||||
"wikimedia/testing-access-wrapper": "^1.0 || ^2.0"
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"actions.php"
|
||||
],
|
||||
"classmap": [
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
"build-development": [
|
||||
"pnpm run build"
|
||||
],
|
||||
"build-production": [
|
||||
"pnpm run build-production"
|
||||
],
|
||||
"phpunit": [
|
||||
"./vendor/phpunit/phpunit/phpunit --colors=always"
|
||||
],
|
||||
"test-coverage": [
|
||||
"php -dpcov.directory=. ./vendor/bin/phpunit --coverage-clover \"$COVERAGE_DIR/php/clover.xml\"",
|
||||
"pnpm run test-coverage"
|
||||
],
|
||||
"test-js": [
|
||||
"pnpm run test"
|
||||
],
|
||||
"test-php": [
|
||||
"@composer phpunit"
|
||||
]
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"prefer-stable": true,
|
||||
"extra": {
|
||||
"autotagger": true,
|
||||
"mirror-repo": "Automattic/jetpack-assets",
|
||||
"textdomain": "jetpack-assets",
|
||||
"changelogger": {
|
||||
"link-template": "https://github.com/Automattic/jetpack-assets/compare/v${old}...v${new}"
|
||||
},
|
||||
"branch-alias": {
|
||||
"dev-trunk": "1.17.x-dev"
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,738 @@
|
||||
<?php
|
||||
/**
|
||||
* Jetpack Assets package.
|
||||
*
|
||||
* @package automattic/jetpack-assets
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack;
|
||||
|
||||
use Automattic\Jetpack\Assets\Semver;
|
||||
use Automattic\Jetpack\Constants as Jetpack_Constants;
|
||||
use InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Class Assets
|
||||
*/
|
||||
class Assets {
|
||||
/**
|
||||
* Holds all the scripts handles that should be loaded in a deferred fashion.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $defer_script_handles = array();
|
||||
|
||||
/**
|
||||
* The singleton instance of this class.
|
||||
*
|
||||
* @var Assets
|
||||
*/
|
||||
protected static $instance;
|
||||
|
||||
/**
|
||||
* The registered textdomain mappings.
|
||||
*
|
||||
* @var array `array( mapped_domain => array( string target_domain, string target_type, string semver, string path_prefix ) )`.
|
||||
*/
|
||||
private static $domain_map = array();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* Static-only class, so nothing here.
|
||||
*/
|
||||
private function __construct() {}
|
||||
|
||||
// ////////////////////
|
||||
// region Async script loading
|
||||
|
||||
/**
|
||||
* Get the singleton instance of the class.
|
||||
*
|
||||
* @return Assets
|
||||
*/
|
||||
public static function instance() {
|
||||
if ( ! isset( self::$instance ) ) {
|
||||
self::$instance = new Assets();
|
||||
self::$instance->init_hooks();
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initalize the hooks as needed.
|
||||
*/
|
||||
private function init_hooks() {
|
||||
/*
|
||||
* Load some scripts asynchronously.
|
||||
*/
|
||||
add_filter( 'script_loader_tag', array( $this, 'script_add_async' ), 10, 2 );
|
||||
}
|
||||
|
||||
/**
|
||||
* A public method for adding the async script.
|
||||
*
|
||||
* @param string $script_handle Script handle.
|
||||
*/
|
||||
public function add_async_script( $script_handle ) {
|
||||
$this->defer_script_handles[] = $script_handle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an async attribute to scripts that can be loaded deferred.
|
||||
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script
|
||||
*
|
||||
* @param string $tag The <script> tag for the enqueued script.
|
||||
* @param string $handle The script's registered handle.
|
||||
*/
|
||||
public function script_add_async( $tag, $handle ) {
|
||||
if ( empty( $this->defer_script_handles ) ) {
|
||||
return $tag;
|
||||
}
|
||||
|
||||
if ( in_array( $handle, $this->defer_script_handles, true ) ) {
|
||||
// phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedScript
|
||||
return preg_replace( '/<script( [^>]*)? src=/i', '<script defer$1 src=', $tag );
|
||||
}
|
||||
|
||||
return $tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper function that lets you enqueue scripts in an async fashion.
|
||||
*
|
||||
* @param string $handle Name of the script. Should be unique.
|
||||
* @param string $min_path Minimized script path.
|
||||
* @param string $non_min_path Full Script path.
|
||||
* @param array $deps Array of script dependencies.
|
||||
* @param bool $ver The script version.
|
||||
* @param bool $in_footer Should the script be included in the footer.
|
||||
*/
|
||||
public static function enqueue_async_script( $handle, $min_path, $non_min_path, $deps = array(), $ver = false, $in_footer = true ) {
|
||||
$assets_instance = self::instance();
|
||||
$assets_instance->add_async_script( $handle );
|
||||
wp_enqueue_script( $handle, self::get_file_url_for_environment( $min_path, $non_min_path ), $deps, $ver, $in_footer );
|
||||
}
|
||||
|
||||
// endregion .
|
||||
|
||||
// ////////////////////
|
||||
// region Utils
|
||||
|
||||
/**
|
||||
* Given a minified path, and a non-minified path, will return
|
||||
* a minified or non-minified file URL based on whether SCRIPT_DEBUG is set and truthy.
|
||||
*
|
||||
* If $package_path is provided, then the minified or non-minified file URL will be generated
|
||||
* relative to the root package directory.
|
||||
*
|
||||
* Both `$min_base` and `$non_min_base` can be either full URLs, or are expected to be relative to the
|
||||
* root Jetpack directory.
|
||||
*
|
||||
* @param string $min_path minified path.
|
||||
* @param string $non_min_path non-minified path.
|
||||
* @param string $package_path Optional. A full path to a file inside a package directory
|
||||
* The URL will be relative to its directory. Default empty.
|
||||
* Typically this is done by passing __FILE__ as the argument.
|
||||
*
|
||||
* @return string The URL to the file
|
||||
* @since 1.0.3
|
||||
* @since-jetpack 5.6.0
|
||||
*/
|
||||
public static function get_file_url_for_environment( $min_path, $non_min_path, $package_path = '' ) {
|
||||
$path = ( Jetpack_Constants::is_defined( 'SCRIPT_DEBUG' ) && Jetpack_Constants::get_constant( 'SCRIPT_DEBUG' ) )
|
||||
? $non_min_path
|
||||
: $min_path;
|
||||
|
||||
/*
|
||||
* If the path is actually a full URL, keep that.
|
||||
* We look for a host value, since enqueues are sometimes without a scheme.
|
||||
*/
|
||||
$file_parts = wp_parse_url( $path );
|
||||
if ( ! empty( $file_parts['host'] ) ) {
|
||||
$url = $path;
|
||||
} else {
|
||||
$plugin_path = empty( $package_path ) ? Jetpack_Constants::get_constant( 'JETPACK__PLUGIN_FILE' ) : $package_path;
|
||||
|
||||
$url = plugins_url( $path, $plugin_path );
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the URL for a file passed through the get_file_url_for_environment function.
|
||||
*
|
||||
* @since 1.0.3
|
||||
*
|
||||
* @package assets
|
||||
*
|
||||
* @param string $url The URL to the file.
|
||||
* @param string $min_path The minified path.
|
||||
* @param string $non_min_path The non-minified path.
|
||||
*/
|
||||
return apply_filters( 'jetpack_get_file_for_environment', $url, $min_path, $non_min_path );
|
||||
}
|
||||
|
||||
/**
|
||||
* Passes an array of URLs to wp_resource_hints.
|
||||
*
|
||||
* @since 1.5.0
|
||||
*
|
||||
* @param string|array $urls URLs to hint.
|
||||
* @param string $type One of the supported resource types: dns-prefetch (default), preconnect, prefetch, or prerender.
|
||||
*/
|
||||
public static function add_resource_hint( $urls, $type = 'dns-prefetch' ) {
|
||||
add_filter(
|
||||
'wp_resource_hints',
|
||||
function ( $hints, $resource_type ) use ( $urls, $type ) {
|
||||
if ( $resource_type === $type ) {
|
||||
// Type casting to array required since the function accepts a single string.
|
||||
foreach ( (array) $urls as $url ) {
|
||||
$hints[] = $url;
|
||||
}
|
||||
}
|
||||
return $hints;
|
||||
},
|
||||
10,
|
||||
2
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Serve a WordPress.com static resource via a randomized wp.com subdomain.
|
||||
*
|
||||
* @since 1.9.0
|
||||
*
|
||||
* @param string $url WordPress.com static resource URL.
|
||||
*
|
||||
* @return string $url
|
||||
*/
|
||||
public static function staticize_subdomain( $url ) {
|
||||
// Extract hostname from URL.
|
||||
$host = wp_parse_url( $url, PHP_URL_HOST );
|
||||
|
||||
// Explode hostname on '.'.
|
||||
$exploded_host = explode( '.', $host );
|
||||
|
||||
// Retrieve the name and TLD.
|
||||
if ( count( $exploded_host ) > 1 ) {
|
||||
$name = $exploded_host[ count( $exploded_host ) - 2 ];
|
||||
$tld = $exploded_host[ count( $exploded_host ) - 1 ];
|
||||
// Rebuild domain excluding subdomains.
|
||||
$domain = $name . '.' . $tld;
|
||||
} else {
|
||||
$domain = $host;
|
||||
}
|
||||
// Array of Automattic domains.
|
||||
$domains_allowed = array( 'wordpress.com', 'wp.com' );
|
||||
|
||||
// Return $url if not an Automattic domain.
|
||||
if ( ! in_array( $domain, $domains_allowed, true ) ) {
|
||||
return $url;
|
||||
}
|
||||
|
||||
if ( \is_ssl() ) {
|
||||
return preg_replace( '|https?://[^/]++/|', 'https://s-ssl.wordpress.com/', $url );
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate a random subdomain id by taking the modulus of the crc32 value of the URL.
|
||||
* Valid values are 0, 1, and 2.
|
||||
*/
|
||||
$static_counter = abs( crc32( basename( $url ) ) % 3 );
|
||||
|
||||
return preg_replace( '|://[^/]+?/|', "://s$static_counter.wp.com/", $url );
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve '.' and '..' components in a path or URL.
|
||||
*
|
||||
* @since 1.12.0
|
||||
* @param string $path Path or URL.
|
||||
* @return string Normalized path or URL.
|
||||
*/
|
||||
public static function normalize_path( $path ) {
|
||||
$parts = wp_parse_url( $path );
|
||||
if ( ! isset( $parts['path'] ) ) {
|
||||
return $path;
|
||||
}
|
||||
|
||||
$ret = '';
|
||||
$ret .= isset( $parts['scheme'] ) ? $parts['scheme'] . '://' : '';
|
||||
if ( isset( $parts['user'] ) || isset( $parts['pass'] ) ) {
|
||||
$ret .= isset( $parts['user'] ) ? $parts['user'] : '';
|
||||
$ret .= isset( $parts['pass'] ) ? ':' . $parts['pass'] : '';
|
||||
$ret .= '@';
|
||||
}
|
||||
$ret .= isset( $parts['host'] ) ? $parts['host'] : '';
|
||||
$ret .= isset( $parts['port'] ) ? ':' . $parts['port'] : '';
|
||||
|
||||
$pp = explode( '/', $parts['path'] );
|
||||
if ( '' === $pp[0] ) {
|
||||
$ret .= '/';
|
||||
array_shift( $pp );
|
||||
}
|
||||
$i = 0;
|
||||
while ( $i < count( $pp ) ) { // phpcs:ignore Squiz.PHP.DisallowSizeFunctionsInLoops.Found
|
||||
if ( '' === $pp[ $i ] || '.' === $pp[ $i ] || 0 === $i && '..' === $pp[ $i ] ) {
|
||||
array_splice( $pp, $i, 1 );
|
||||
} elseif ( '..' === $pp[ $i ] ) {
|
||||
array_splice( $pp, --$i, 2 );
|
||||
} else {
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
$ret .= join( '/', $pp );
|
||||
|
||||
$ret .= isset( $parts['query'] ) ? '?' . $parts['query'] : '';
|
||||
$ret .= isset( $parts['fragment'] ) ? '#' . $parts['fragment'] : '';
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
// endregion .
|
||||
|
||||
// ////////////////////
|
||||
// region Webpack-built script registration
|
||||
|
||||
/**
|
||||
* Register a Webpack-built script.
|
||||
*
|
||||
* Our Webpack-built scripts tend to need a bunch of boilerplate:
|
||||
* - A call to `Assets::get_file_url_for_environment()` for possible debugging.
|
||||
* - A call to `wp_register_style()` for extracted CSS, possibly with detection of RTL.
|
||||
* - Loading of dependencies and version provided by `@wordpress/dependency-extraction-webpack-plugin`.
|
||||
* - Avoiding WPCom's broken minifier.
|
||||
*
|
||||
* This wrapper handles all of that.
|
||||
*
|
||||
* @since 1.12.0
|
||||
* @param string $handle Name of the script. Should be unique across both scripts and styles.
|
||||
* @param string $path Minimized script path.
|
||||
* @param string $relative_to File that `$path` is relative to. Pass `__FILE__`.
|
||||
* @param array $options Additional options:
|
||||
* - `asset_path`: (string|null) `.asset.php` to load. Default is to base it on `$path`.
|
||||
* - `async`: (bool) Set true to register the script as async, like `Assets::enqueue_async_script()`
|
||||
* - `css_dependencies`: (string[]) Additional style dependencies to queue.
|
||||
* - `css_path`: (string|null) `.css` to load. Default is to base it on `$path`.
|
||||
* - `dependencies`: (string[]) Additional script dependencies to queue.
|
||||
* - `enqueue`: (bool) Set true to enqueue the script immediately.
|
||||
* - `in_footer`: (bool) Set true to register script for the footer.
|
||||
* - `media`: (string) Media for the css file. Default 'all'.
|
||||
* - `minify`: (bool|null) Set true to pass `minify=true` in the query string, or `null` to suppress the normal `minify=false`.
|
||||
* - `nonmin_path`: (string) Non-minified script path.
|
||||
* - `textdomain`: (string) Text domain for the script. Required if the script depends on wp-i18n.
|
||||
* - `version`: (string) Override the version from the `asset_path` file.
|
||||
* @throws \InvalidArgumentException If arguments are invalid.
|
||||
*/
|
||||
public static function register_script( $handle, $path, $relative_to, array $options = array() ) {
|
||||
if ( substr( $path, -3 ) !== '.js' ) {
|
||||
throw new \InvalidArgumentException( '$path must end in ".js"' );
|
||||
}
|
||||
|
||||
$dir = dirname( $relative_to );
|
||||
$base = substr( $path, 0, -3 );
|
||||
$options += array(
|
||||
'asset_path' => "$base.asset.php",
|
||||
'async' => false,
|
||||
'css_dependencies' => array(),
|
||||
'css_path' => "$base.css",
|
||||
'dependencies' => array(),
|
||||
'enqueue' => false,
|
||||
'in_footer' => false,
|
||||
'media' => 'all',
|
||||
'minify' => false,
|
||||
'textdomain' => null,
|
||||
);
|
||||
|
||||
if ( $options['css_path'] && substr( $options['css_path'], -4 ) !== '.css' ) {
|
||||
throw new \InvalidArgumentException( '$options[\'css_path\'] must end in ".css"' );
|
||||
}
|
||||
|
||||
if ( isset( $options['nonmin_path'] ) ) {
|
||||
$url = self::get_file_url_for_environment( $path, $options['nonmin_path'], $relative_to );
|
||||
} else {
|
||||
$url = plugins_url( $path, $relative_to );
|
||||
}
|
||||
$url = self::normalize_path( $url );
|
||||
if ( null !== $options['minify'] ) {
|
||||
$url = add_query_arg( 'minify', $options['minify'] ? 'true' : 'false', $url );
|
||||
}
|
||||
|
||||
if ( $options['asset_path'] && file_exists( "$dir/{$options['asset_path']}" ) ) {
|
||||
$asset = require "$dir/{$options['asset_path']}"; // phpcs:ignore WordPressVIPMinimum.Files.IncludingFile.NotAbsolutePath
|
||||
$options['dependencies'] = array_merge( $asset['dependencies'], $options['dependencies'] );
|
||||
$options['css_dependencies'] = array_merge(
|
||||
array_filter(
|
||||
$asset['dependencies'],
|
||||
function ( $d ) {
|
||||
return wp_style_is( $d, 'registered' );
|
||||
}
|
||||
),
|
||||
$options['css_dependencies']
|
||||
);
|
||||
$ver = isset( $options['version'] ) ? $options['version'] : $asset['version'];
|
||||
} else {
|
||||
$ver = isset( $options['version'] ) ? $options['version'] : filemtime( "$dir/$path" );
|
||||
}
|
||||
|
||||
wp_register_script( $handle, $url, $options['dependencies'], $ver, $options['in_footer'] );
|
||||
if ( $options['async'] ) {
|
||||
self::instance()->add_async_script( $handle );
|
||||
}
|
||||
if ( $options['textdomain'] ) {
|
||||
// phpcs:ignore Jetpack.Functions.I18n.DomainNotLiteral
|
||||
wp_set_script_translations( $handle, $options['textdomain'] );
|
||||
} elseif ( in_array( 'wp-i18n', $options['dependencies'], true ) ) {
|
||||
_doing_it_wrong(
|
||||
__METHOD__,
|
||||
/* translators: %s is the script handle. */
|
||||
esc_html( sprintf( __( 'Script "%s" depends on wp-i18n but does not specify "textdomain"', 'jetpack-assets' ), $handle ) ),
|
||||
''
|
||||
);
|
||||
}
|
||||
|
||||
if ( $options['css_path'] && file_exists( "$dir/{$options['css_path']}" ) ) {
|
||||
$csspath = $options['css_path'];
|
||||
if ( is_rtl() ) {
|
||||
$rtlcsspath = substr( $csspath, 0, -4 ) . '.rtl.css';
|
||||
if ( file_exists( "$dir/$rtlcsspath" ) ) {
|
||||
$csspath = $rtlcsspath;
|
||||
}
|
||||
}
|
||||
|
||||
$url = self::normalize_path( plugins_url( $csspath, $relative_to ) );
|
||||
if ( null !== $options['minify'] ) {
|
||||
$url = add_query_arg( 'minify', $options['minify'] ? 'true' : 'false', $url );
|
||||
}
|
||||
wp_register_style( $handle, $url, $options['css_dependencies'], $ver, $options['media'] );
|
||||
wp_script_add_data( $handle, 'Jetpack::Assets::hascss', true );
|
||||
} else {
|
||||
wp_script_add_data( $handle, 'Jetpack::Assets::hascss', false );
|
||||
}
|
||||
|
||||
if ( $options['enqueue'] ) {
|
||||
self::enqueue_script( $handle );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue a script registered with `Assets::register_script`.
|
||||
*
|
||||
* @since 1.12.0
|
||||
* @param string $handle Name of the script. Should be unique across both scripts and styles.
|
||||
*/
|
||||
public static function enqueue_script( $handle ) {
|
||||
wp_enqueue_script( $handle );
|
||||
if ( wp_scripts()->get_data( $handle, 'Jetpack::Assets::hascss' ) ) {
|
||||
wp_enqueue_style( $handle );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 'wp_default_scripts' action handler.
|
||||
*
|
||||
* This registers the `wp-jp-i18n-loader` script for use by Webpack bundles built with
|
||||
* `@automattic/i18n-loader-webpack-plugin`.
|
||||
*
|
||||
* @since 1.14.0
|
||||
* @param \WP_Scripts $wp_scripts WP_Scripts instance.
|
||||
*/
|
||||
public static function wp_default_scripts_hook( $wp_scripts ) {
|
||||
$data = array(
|
||||
'baseUrl' => false,
|
||||
'locale' => determine_locale(),
|
||||
'domainMap' => array(),
|
||||
'domainPaths' => array(),
|
||||
);
|
||||
|
||||
$lang_dir = Jetpack_Constants::get_constant( 'WP_LANG_DIR' );
|
||||
$content_dir = Jetpack_Constants::get_constant( 'WP_CONTENT_DIR' );
|
||||
$abspath = Jetpack_Constants::get_constant( 'ABSPATH' );
|
||||
|
||||
if ( strpos( $lang_dir, $content_dir ) === 0 ) {
|
||||
$data['baseUrl'] = content_url( substr( trailingslashit( $lang_dir ), strlen( trailingslashit( $content_dir ) ) ) );
|
||||
} elseif ( strpos( $lang_dir, $abspath ) === 0 ) {
|
||||
$data['baseUrl'] = site_url( substr( trailingslashit( $lang_dir ), strlen( untrailingslashit( $abspath ) ) ) );
|
||||
}
|
||||
|
||||
foreach ( self::$domain_map as $from => list( $to, $type, , $path ) ) {
|
||||
$data['domainMap'][ $from ] = ( 'core' === $type ? '' : "{$type}/" ) . $to;
|
||||
if ( '' !== $path ) {
|
||||
$data['domainPaths'][ $from ] = trailingslashit( $path );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the i18n state data for use by Webpack bundles built with
|
||||
* `@automattic/i18n-loader-webpack-plugin`.
|
||||
*
|
||||
* @since 1.14.0
|
||||
* @package assets
|
||||
* @param array $data The state data to generate. Expected fields are:
|
||||
* - `baseUrl`: (string|false) The URL to the languages directory. False if no URL could be determined.
|
||||
* - `locale`: (string) The locale for the page.
|
||||
* - `domainMap`: (string[]) A mapping from Composer package textdomains to the corresponding
|
||||
* `plugins/textdomain` or `themes/textdomain` (or core `textdomain`, but that's unlikely).
|
||||
* - `domainPaths`: (string[]) A mapping from Composer package textdomains to the corresponding package
|
||||
* paths.
|
||||
*/
|
||||
$data = apply_filters( 'jetpack_i18n_state', $data );
|
||||
|
||||
// Can't use self::register_script(), this action is called too early.
|
||||
if ( file_exists( __DIR__ . '/../build/i18n-loader.asset.php' ) ) {
|
||||
$path = '../build/i18n-loader.js';
|
||||
$asset = require __DIR__ . '/../build/i18n-loader.asset.php';
|
||||
} else {
|
||||
$path = 'js/i18n-loader.js';
|
||||
$asset = array(
|
||||
'dependencies' => array( 'wp-i18n' ),
|
||||
'version' => filemtime( __DIR__ . "/$path" ),
|
||||
);
|
||||
}
|
||||
$url = self::normalize_path( plugins_url( $path, __FILE__ ) );
|
||||
$url = add_query_arg( 'minify', 'true', $url );
|
||||
$wp_scripts->add( 'wp-jp-i18n-loader', $url, $asset['dependencies'], $asset['version'] );
|
||||
if ( ! is_array( $data ) ||
|
||||
! isset( $data['baseUrl'] ) || ! ( is_string( $data['baseUrl'] ) || false === $data['baseUrl'] ) ||
|
||||
! isset( $data['locale'] ) || ! is_string( $data['locale'] ) ||
|
||||
! isset( $data['domainMap'] ) || ! is_array( $data['domainMap'] ) ||
|
||||
! isset( $data['domainPaths'] ) || ! is_array( $data['domainPaths'] )
|
||||
) {
|
||||
$wp_scripts->add_inline_script( 'wp-jp-i18n-loader', 'console.warn( "I18n state deleted by jetpack_i18n_state hook" );' );
|
||||
} elseif ( ! $data['baseUrl'] ) {
|
||||
$wp_scripts->add_inline_script( 'wp-jp-i18n-loader', 'console.warn( "Failed to determine languages base URL. Is WP_LANG_DIR in the WordPress root?" );' );
|
||||
} else {
|
||||
$data['domainMap'] = (object) $data['domainMap']; // Ensure it becomes a json object.
|
||||
$data['domainPaths'] = (object) $data['domainPaths']; // Ensure it becomes a json object.
|
||||
$wp_scripts->add_inline_script( 'wp-jp-i18n-loader', 'wp.jpI18nLoader.state = ' . wp_json_encode( $data, JSON_UNESCAPED_SLASHES ) . ';' );
|
||||
}
|
||||
|
||||
// Deprecated state module: Depend on wp-i18n to ensure global `wp` exists and because anything needing this will need that too.
|
||||
$wp_scripts->add( 'wp-jp-i18n-state', null, array( 'wp-deprecated', 'wp-jp-i18n-loader' ) );
|
||||
$wp_scripts->add_inline_script( 'wp-jp-i18n-state', 'wp.deprecated( "wp-jp-i18n-state", { alternative: "wp-jp-i18n-loader" } );' );
|
||||
$wp_scripts->add_inline_script( 'wp-jp-i18n-state', 'wp.jpI18nState = wp.jpI18nLoader.state;' );
|
||||
}
|
||||
|
||||
// endregion .
|
||||
|
||||
// ////////////////////
|
||||
// region Textdomain aliasing
|
||||
|
||||
/**
|
||||
* Register a textdomain alias.
|
||||
*
|
||||
* Composer packages included in plugins will likely not use the textdomain of the plugin, while
|
||||
* WordPress's i18n infrastructure will include the translations in the plugin's domain. This
|
||||
* allows for mapping the package's domain to the plugin's.
|
||||
*
|
||||
* Since multiple plugins may use the same package, we include the package's version here so
|
||||
* as to choose the most recent translations (which are most likely to match the package
|
||||
* selected by jetpack-autoloader).
|
||||
*
|
||||
* @since 1.15.0
|
||||
* @param string $from Domain to alias.
|
||||
* @param string $to Domain to alias it to.
|
||||
* @param string $totype What is the target of the alias: 'plugins', 'themes', or 'core'.
|
||||
* @param string $ver Version of the `$from` domain.
|
||||
* @param string $path Path to prepend when lazy-loading from JavaScript.
|
||||
* @throws InvalidArgumentException If arguments are invalid.
|
||||
*/
|
||||
public static function alias_textdomain( $from, $to, $totype, $ver, $path = '' ) {
|
||||
if ( ! in_array( $totype, array( 'plugins', 'themes', 'core' ), true ) ) {
|
||||
throw new InvalidArgumentException( 'Type must be "plugins", "themes", or "core"' );
|
||||
}
|
||||
|
||||
if (
|
||||
did_action( 'wp_default_scripts' ) &&
|
||||
// Don't complain during plugin activation.
|
||||
! defined( 'WP_SANDBOX_SCRAPING' )
|
||||
) {
|
||||
_doing_it_wrong(
|
||||
__METHOD__,
|
||||
sprintf(
|
||||
/* translators: 1: wp_default_scripts. 2: Name of the domain being aliased. */
|
||||
esc_html__( 'Textdomain aliases should be registered before the %1$s hook. This notice was triggered by the %2$s domain.', 'jetpack-assets' ),
|
||||
'<code>wp_default_scripts</code>',
|
||||
'<code>' . esc_html( $from ) . '</code>'
|
||||
),
|
||||
''
|
||||
);
|
||||
}
|
||||
|
||||
if ( empty( self::$domain_map[ $from ] ) ) {
|
||||
self::init_domain_map_hooks( $from, array() === self::$domain_map );
|
||||
self::$domain_map[ $from ] = array( $to, $totype, $ver, $path );
|
||||
} elseif ( Semver::compare( $ver, self::$domain_map[ $from ][2] ) > 0 ) {
|
||||
self::$domain_map[ $from ] = array( $to, $totype, $ver, $path );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register textdomain aliases from a mapping file.
|
||||
*
|
||||
* The mapping file is simply a PHP file that returns an array
|
||||
* with the following properties:
|
||||
* - 'domain': String, `$to`
|
||||
* - 'type': String, `$totype`
|
||||
* - 'packages': Array, mapping `$from` to `array( 'path' => $path, 'ver' => $ver )` (or to the string `$ver` for back compat).
|
||||
*
|
||||
* @since 1.15.0
|
||||
* @param string $file Mapping file.
|
||||
*/
|
||||
public static function alias_textdomains_from_file( $file ) {
|
||||
$data = require $file;
|
||||
foreach ( $data['packages'] as $from => $fromdata ) {
|
||||
if ( ! is_array( $fromdata ) ) {
|
||||
$fromdata = array(
|
||||
'path' => '',
|
||||
'ver' => $fromdata,
|
||||
);
|
||||
}
|
||||
self::alias_textdomain( $from, $data['domain'], $data['type'], $fromdata['ver'], $fromdata['path'] );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the hooks for textdomain aliasing.
|
||||
*
|
||||
* @param string $domain Domain to alias.
|
||||
* @param bool $firstcall If this is the first call.
|
||||
*/
|
||||
private static function init_domain_map_hooks( $domain, $firstcall ) {
|
||||
// If WordPress's plugin API is available already, use it. If not,
|
||||
// drop data into `$wp_filter` for `WP_Hook::build_preinitialized_hooks()`.
|
||||
if ( function_exists( 'add_filter' ) ) {
|
||||
$add_filter = 'add_filter';
|
||||
} else {
|
||||
$add_filter = function ( $hook_name, $callback, $priority = 10, $accepted_args = 1 ) {
|
||||
global $wp_filter;
|
||||
// phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
|
||||
$wp_filter[ $hook_name ][ $priority ][] = array(
|
||||
'accepted_args' => $accepted_args,
|
||||
'function' => $callback,
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
$add_filter( "gettext_{$domain}", array( self::class, 'filter_gettext' ), 10, 3 );
|
||||
$add_filter( "ngettext_{$domain}", array( self::class, 'filter_ngettext' ), 10, 5 );
|
||||
$add_filter( "gettext_with_context_{$domain}", array( self::class, 'filter_gettext_with_context' ), 10, 4 );
|
||||
$add_filter( "ngettext_with_context_{$domain}", array( self::class, 'filter_ngettext_with_context' ), 10, 6 );
|
||||
if ( $firstcall ) {
|
||||
$add_filter( 'load_script_translation_file', array( self::class, 'filter_load_script_translation_file' ), 10, 3 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter for `gettext`.
|
||||
*
|
||||
* @since 1.15.0
|
||||
* @param string $translation Translated text.
|
||||
* @param string $text Text to translate.
|
||||
* @param string $domain Text domain.
|
||||
* @return string Translated text.
|
||||
*/
|
||||
public static function filter_gettext( $translation, $text, $domain ) {
|
||||
if ( $translation === $text ) {
|
||||
// phpcs:ignore WordPress.WP.I18n
|
||||
$newtext = __( $text, self::$domain_map[ $domain ][0] );
|
||||
if ( $newtext !== $text ) {
|
||||
return $newtext;
|
||||
}
|
||||
}
|
||||
return $translation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter for `ngettext`.
|
||||
*
|
||||
* @since 1.15.0
|
||||
* @param string $translation Translated text.
|
||||
* @param string $single The text to be used if the number is singular.
|
||||
* @param string $plural The text to be used if the number is plural.
|
||||
* @param string $number The number to compare against to use either the singular or plural form.
|
||||
* @param string $domain Text domain.
|
||||
* @return string Translated text.
|
||||
*/
|
||||
public static function filter_ngettext( $translation, $single, $plural, $number, $domain ) {
|
||||
if ( $translation === $single || $translation === $plural ) {
|
||||
// phpcs:ignore WordPress.WP.I18n
|
||||
$translation = _n( $single, $plural, $number, self::$domain_map[ $domain ][0] );
|
||||
}
|
||||
return $translation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter for `gettext_with_context`.
|
||||
*
|
||||
* @since 1.15.0
|
||||
* @param string $translation Translated text.
|
||||
* @param string $text Text to translate.
|
||||
* @param string $context Context information for the translators.
|
||||
* @param string $domain Text domain.
|
||||
* @return string Translated text.
|
||||
*/
|
||||
public static function filter_gettext_with_context( $translation, $text, $context, $domain ) {
|
||||
if ( $translation === $text ) {
|
||||
// phpcs:ignore WordPress.WP.I18n
|
||||
$translation = _x( $text, $context, self::$domain_map[ $domain ][0] );
|
||||
}
|
||||
return $translation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter for `ngettext_with_context`.
|
||||
*
|
||||
* @since 1.15.0
|
||||
* @param string $translation Translated text.
|
||||
* @param string $single The text to be used if the number is singular.
|
||||
* @param string $plural The text to be used if the number is plural.
|
||||
* @param string $number The number to compare against to use either the singular or plural form.
|
||||
* @param string $context Context information for the translators.
|
||||
* @param string $domain Text domain.
|
||||
* @return string Translated text.
|
||||
*/
|
||||
public static function filter_ngettext_with_context( $translation, $single, $plural, $number, $context, $domain ) {
|
||||
if ( $translation === $single || $translation === $plural ) {
|
||||
// phpcs:ignore WordPress.WP.I18n
|
||||
$translation = _nx( $single, $plural, $number, $context, self::$domain_map[ $domain ][0] );
|
||||
}
|
||||
return $translation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter for `load_script_translation_file`.
|
||||
*
|
||||
* @since 1.15.0
|
||||
* @param string|false $file Path to the translation file to load. False if there isn't one.
|
||||
* @param string $handle Name of the script to register a translation domain to.
|
||||
* @param string $domain The text domain.
|
||||
*/
|
||||
public static function filter_load_script_translation_file( $file, $handle, $domain ) {
|
||||
if ( false !== $file && isset( self::$domain_map[ $domain ] ) && ! is_readable( $file ) ) {
|
||||
// Determine the part of the filename after the domain.
|
||||
$suffix = basename( $file );
|
||||
$l = strlen( $domain );
|
||||
if ( substr( $suffix, 0, $l ) !== $domain || '-' !== $suffix[ $l ] ) {
|
||||
return $file;
|
||||
}
|
||||
$suffix = substr( $suffix, $l );
|
||||
$lang_dir = Jetpack_Constants::get_constant( 'WP_LANG_DIR' );
|
||||
|
||||
// Look for replacement files.
|
||||
list( $newdomain, $type ) = self::$domain_map[ $domain ];
|
||||
$newfile = $lang_dir . ( 'core' === $type ? '/' : "/{$type}/" ) . $newdomain . $suffix;
|
||||
if ( is_readable( $newfile ) ) {
|
||||
return $newfile;
|
||||
}
|
||||
}
|
||||
return $file;
|
||||
}
|
||||
|
||||
// endregion .
|
||||
|
||||
}
|
||||
|
||||
// Enable section folding in vim:
|
||||
// vim: foldmarker=//\ region,//\ endregion foldmethod=marker
|
||||
// .
|
@ -0,0 +1,122 @@
|
||||
<?php
|
||||
/**
|
||||
* Simple semver version handling.
|
||||
*
|
||||
* We use this instead of something like `composer/semver` to avoid
|
||||
* plugins needing to include yet-another dependency package. The
|
||||
* amount of code we need here is pretty small.
|
||||
*
|
||||
* We use this instead of PHP's `version_compare()` because that doesn't
|
||||
* handle prerelease versions in the way anyone other than PHP devs would
|
||||
* expect, and silently breaks on various unexpected input.
|
||||
*
|
||||
* @package automattic/jetpack-assets
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Assets;
|
||||
|
||||
use InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Simple semver version handling.
|
||||
*/
|
||||
class Semver {
|
||||
/**
|
||||
* Parse a semver version.
|
||||
*
|
||||
* @param string $version Version.
|
||||
* @return array With components:
|
||||
* - major: (int) Major version.
|
||||
* - minor: (int) Minor version.
|
||||
* - patch: (int) Patch version.
|
||||
* - version: (string) Major.minor.patch.
|
||||
* - prerelease: (string|null) Pre-release string.
|
||||
* - buildinfo: (string|null) Build metadata string.
|
||||
* @throws InvalidArgumentException If the version number is not in a recognized format.
|
||||
*/
|
||||
public static function parse( $version ) {
|
||||
// This is slightly looser than the official version from semver.org, in that leading zeros are allowed.
|
||||
if ( ! preg_match( '/^(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(?:-(?P<prerelease>(?:[0-9a-zA-Z-]+)(?:\.(?:[0-9a-zA-Z-]+))*))?(?:\+(?P<buildinfo>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/', $version, $m ) ) {
|
||||
throw new InvalidArgumentException( "Version number \"$version\" is not in a recognized format." );
|
||||
}
|
||||
$info = array(
|
||||
'major' => (int) $m['major'],
|
||||
'minor' => (int) $m['minor'],
|
||||
'patch' => (int) $m['patch'],
|
||||
'version' => sprintf( '%d.%d.%d', $m['major'], $m['minor'], $m['patch'] ),
|
||||
'prerelease' => isset( $m['prerelease'] ) && '' !== $m['prerelease'] ? $m['prerelease'] : null,
|
||||
'buildinfo' => isset( $m['buildinfo'] ) && '' !== $m['buildinfo'] ? $m['buildinfo'] : null,
|
||||
);
|
||||
|
||||
if ( null !== $info['prerelease'] ) {
|
||||
$sep = '';
|
||||
$prerelease = '';
|
||||
foreach ( explode( '.', $info['prerelease'] ) as $part ) {
|
||||
if ( ctype_digit( $part ) ) {
|
||||
$part = (int) $part;
|
||||
}
|
||||
$prerelease .= $sep . $part;
|
||||
$sep = '.';
|
||||
}
|
||||
$info['prerelease'] = $prerelease;
|
||||
}
|
||||
|
||||
return $info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two version numbers.
|
||||
*
|
||||
* @param string $a First version.
|
||||
* @param string $b Second version.
|
||||
* @return int Less than, equal to, or greater than 0 depending on whether `$a` is less than, equal to, or greater than `$b`.
|
||||
* @throws InvalidArgumentException If the version numbers are not in a recognized format.
|
||||
*/
|
||||
public static function compare( $a, $b ) {
|
||||
$aa = self::parse( $a );
|
||||
$bb = self::parse( $b );
|
||||
if ( $aa['major'] !== $bb['major'] ) {
|
||||
return $aa['major'] - $bb['major'];
|
||||
}
|
||||
if ( $aa['minor'] !== $bb['minor'] ) {
|
||||
return $aa['minor'] - $bb['minor'];
|
||||
}
|
||||
if ( $aa['patch'] !== $bb['patch'] ) {
|
||||
return $aa['patch'] - $bb['patch'];
|
||||
}
|
||||
|
||||
if ( null === $aa['prerelease'] ) {
|
||||
return null === $bb['prerelease'] ? 0 : 1;
|
||||
}
|
||||
if ( null === $bb['prerelease'] ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
$aaa = explode( '.', $aa['prerelease'] );
|
||||
$bbb = explode( '.', $bb['prerelease'] );
|
||||
$al = count( $aaa );
|
||||
$bl = count( $bbb );
|
||||
for ( $i = 0; $i < $al && $i < $bl; $i++ ) {
|
||||
$a = $aaa[ $i ];
|
||||
$b = $bbb[ $i ];
|
||||
if ( ctype_digit( $a ) ) {
|
||||
if ( ctype_digit( $b ) ) {
|
||||
if ( (int) $a !== (int) $b ) {
|
||||
return $a - $b;
|
||||
}
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
} elseif ( ctype_digit( $b ) ) {
|
||||
return 1;
|
||||
} else {
|
||||
$tmp = strcmp( $a, $b );
|
||||
if ( 0 !== $tmp ) {
|
||||
return $tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $al - $bl;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
const i18n = require( '@wordpress/i18n' );
|
||||
const { default: md5 } = require( 'md5-es' );
|
||||
|
||||
const locationMap = {
|
||||
plugin: 'plugins/',
|
||||
theme: 'themes/',
|
||||
core: '',
|
||||
};
|
||||
|
||||
const hasOwn = ( obj, prop ) => Object.prototype.hasOwnProperty.call( obj, prop );
|
||||
|
||||
module.exports = {
|
||||
state: {
|
||||
baseUrl: null,
|
||||
locale: null,
|
||||
domainMap: {},
|
||||
domainPaths: {},
|
||||
},
|
||||
|
||||
/**
|
||||
* Download and register translations for a bundle.
|
||||
*
|
||||
* @param {string} path - Bundle path being fetched. May have a query part.
|
||||
* @param {string} domain - Text domain to register into.
|
||||
* @param {string} location - Location for the translation: 'plugin', 'theme', or 'core'.
|
||||
* @returns {Promise} Resolved when the translations are registered, or rejected with an `Error`.
|
||||
*/
|
||||
async downloadI18n( path, domain, location ) {
|
||||
const state = this.state;
|
||||
if ( ! state || typeof state.baseUrl !== 'string' ) {
|
||||
throw new Error( 'wp.jpI18nLoader.state is not set' );
|
||||
}
|
||||
|
||||
// "en_US" is the default, no translations are needed.
|
||||
if ( state.locale === 'en_US' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check that fetch is available.
|
||||
if ( typeof fetch === 'undefined' ) {
|
||||
throw new Error( 'Fetch API is not available.' );
|
||||
}
|
||||
|
||||
// Extract any query part and hash the script name like WordPress does.
|
||||
const pathPrefix = hasOwn( state.domainPaths, domain ) ? state.domainPaths[ domain ] : '';
|
||||
let hash, query;
|
||||
const i = path.indexOf( '?' );
|
||||
if ( i >= 0 ) {
|
||||
hash = md5.hash( pathPrefix + path.substring( 0, i ) );
|
||||
query = path.substring( i );
|
||||
} else {
|
||||
hash = md5.hash( pathPrefix + path );
|
||||
query = '';
|
||||
}
|
||||
|
||||
// Download.
|
||||
const locationAndDomain = hasOwn( state.domainMap, domain )
|
||||
? state.domainMap[ domain ]
|
||||
: locationMap[ location ] + domain;
|
||||
const res = await fetch(
|
||||
// prettier-ignore
|
||||
`${ state.baseUrl }${ locationAndDomain }-${ state.locale }-${ hash }.json${ query }`
|
||||
);
|
||||
if ( ! res.ok ) {
|
||||
throw new Error( `HTTP request failed: ${ res.status } ${ res.statusText }` );
|
||||
}
|
||||
const data = await res.json();
|
||||
|
||||
// Extract the messages from the file and register them.
|
||||
const localeData = hasOwn( data.locale_data, domain )
|
||||
? data.locale_data[ domain ]
|
||||
: data.locale_data.messages;
|
||||
localeData[ '' ].domain = domain;
|
||||
i18n.setLocaleData( localeData, domain );
|
||||
},
|
||||
};
|
Reference in New Issue
Block a user