Download all files FTP
This commit is contained in:
25
wp-content/plugins/stops-core-theme-and-plugin-updates/vendor/autoload.php
vendored
Normal file
25
wp-content/plugins/stops-core-theme-and-plugin-updates/vendor/autoload.php
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
// autoload.php @generated by Composer
|
||||
|
||||
if (PHP_VERSION_ID < 50600) {
|
||||
if (!headers_sent()) {
|
||||
header('HTTP/1.1 500 Internal Server Error');
|
||||
}
|
||||
$err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
|
||||
if (!ini_get('display_errors')) {
|
||||
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
|
||||
fwrite(STDERR, $err);
|
||||
} elseif (!headers_sent()) {
|
||||
echo $err;
|
||||
}
|
||||
}
|
||||
trigger_error(
|
||||
$err,
|
||||
E_USER_ERROR
|
||||
);
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/composer/autoload_real.php';
|
||||
|
||||
return ComposerAutoloaderInita423c23c686d92ae4c71ddde2e05a1ea::getLoader();
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2016-2019 Denis Brumann
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
153
wp-content/plugins/stops-core-theme-and-plugin-updates/vendor/brumann/polyfill-unserialize/README.md
vendored
Normal file
153
wp-content/plugins/stops-core-theme-and-plugin-updates/vendor/brumann/polyfill-unserialize/README.md
vendored
Normal file
@@ -0,0 +1,153 @@
|
||||
Polyfill unserialize [](https://travis-ci.org/dbrumann/polyfill-unserialize)
|
||||
===
|
||||
|
||||
Backports unserialize options introduced in PHP 7.0 to older PHP versions.
|
||||
This was originally designed as a Proof of Concept for Symfony Issue
|
||||
[#21090](https://github.com/symfony/symfony/pull/21090).
|
||||
|
||||
You can use this package in projects that rely on PHP versions older than
|
||||
PHP 7.0. In case you are using PHP 7.0+ the original `unserialize()` will be
|
||||
used instead.
|
||||
|
||||
From the [documentation](https://secure.php.net/manual/en/function.unserialize.php):
|
||||
|
||||
> **Warning**
|
||||
>
|
||||
> Do not pass untrusted user input to unserialize() regardless of the options
|
||||
> value of allowed_classes. Unserialization can result in code being loaded and
|
||||
> executed due to object instantiation and autoloading, and a malicious user
|
||||
> may be able to exploit this. Use a safe, standard data interchange format
|
||||
> such as JSON (via json_decode() and json_encode()) if you need to pass
|
||||
> serialized data to the user.
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
- PHP 5.3+
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
You can install this package via composer:
|
||||
|
||||
```bash
|
||||
composer require brumann/polyfill-unserialize "^2.0"
|
||||
```
|
||||
|
||||
Older versions
|
||||
--------------
|
||||
|
||||
You can find the most recent 1.x versions in the branch with the same name:
|
||||
|
||||
* [dbrumann/polyfill-unserialize/tree/1.x](https://github.com/dbrumann/polyfill-unserialize/tree/1.x)
|
||||
|
||||
Upgrading
|
||||
---------
|
||||
|
||||
Upgrading from 1.x to 2.0 should be seamless and require no changes to code
|
||||
using the library. There are no changes to the public API, i.e. the names for
|
||||
classes, methods and arguments as well as argument order and types remain the
|
||||
same. Version 2.x uses a completely different approach for substituting
|
||||
disallowed classes, which is why we chose to use a new major release to prevent
|
||||
issues from unknown side effects in existing installations.
|
||||
|
||||
Known Issues
|
||||
------------
|
||||
|
||||
There is a mismatch in behavior when `allowed_classes` in `$options` is not
|
||||
of the correct type (array or boolean). PHP 7.0 will not issue a warning that
|
||||
an invalid type was provided. This library will trigger a warning, similar to
|
||||
the one PHP 7.1+ will raise and then continue, assuming `false` to make sure
|
||||
no classes are deserialized by accident.
|
||||
|
||||
Tests
|
||||
-----
|
||||
|
||||
You can run the test suite using PHPUnit. It is intentionally not bundled as
|
||||
dev dependency to make sure this package has the lowest restrictions on the
|
||||
implementing system as possible.
|
||||
|
||||
Please read the [PHPUnit Manual](https://phpunit.de/manual/current/en/installation.html)
|
||||
for information how to install it on your system.
|
||||
|
||||
Please make sure to pick a compatible version. If you use PHP 5.6 you should
|
||||
use PHPUnit 5.7.27 and for older PHP versions you should use PHPUnit 4.8.36.
|
||||
Older versions of PHPUnit might not support namespaces, meaning they will not
|
||||
work with the tests. Newer versions only support PHP 7.0+, where this library
|
||||
is not needed anymore.
|
||||
|
||||
You can run the test suite as follows:
|
||||
|
||||
```bash
|
||||
phpunit -c phpunit.xml.dist tests/
|
||||
```
|
||||
|
||||
Contributing
|
||||
------------
|
||||
|
||||
This package is considered feature complete. As such I will likely not update
|
||||
it unless there are security issues.
|
||||
|
||||
Should you find any bugs or have questions, feel free to submit an Issue or a
|
||||
Pull Request on GitHub.
|
||||
|
||||
Development setup
|
||||
-----------------
|
||||
|
||||
This library contains a docker setup for development purposes. This allows
|
||||
running the code on an older PHP version without having to install it locally.
|
||||
|
||||
You can use the setup as follows:
|
||||
|
||||
1. Go into the project directory
|
||||
|
||||
1. Build the docker image
|
||||
|
||||
```
|
||||
docker build -t polyfill-unserialize .
|
||||
```
|
||||
|
||||
This will download a debian/jessie container with PHP 5.6 installed. Then
|
||||
it will download an appropriate version of phpunit for this PHP version.
|
||||
It will also download composer. It will set the working directory to `/opt/app`.
|
||||
The resulting image is tagged as `polyfill-unserialize`, which is the name
|
||||
we will refer to, when running the container.
|
||||
|
||||
1. You can then run a container based on the image, which will run your tests
|
||||
|
||||
```
|
||||
docker run -it --rm --name polyfill-unserialize-dev -v "$PWD":/opt/app polyfill-unserialize
|
||||
```
|
||||
|
||||
This will run a docker container based on our previously built image.
|
||||
The container will automatically be removed after phpunit finishes.
|
||||
We name the image `polyfill-unserialize-dev`. This makes sure only one
|
||||
instance is running and that we can easily identify a running container by
|
||||
its name, e.g. in order to remove it manually.
|
||||
We mount our current directory into the container's working directory.
|
||||
This ensures that tests run on our current project's state.
|
||||
|
||||
You can repeat the final step as often as you like in order to run the tests.
|
||||
The output should look something like this:
|
||||
|
||||
```bash
|
||||
dbr:polyfill-unserialize/ (improvement/dev_setup*) $ docker run -it --rm --name polyfill-unserialize-dev -v "$PWD":/opt/app polyfill-unserialize
|
||||
Loading composer repositories with package information
|
||||
Installing dependencies (including require-dev) from lock file
|
||||
Nothing to install or update
|
||||
Generating autoload files
|
||||
PHPUnit 5.7.27 by Sebastian Bergmann and contributors.
|
||||
|
||||
...................... 22 / 22 (100%)
|
||||
|
||||
Time: 167 ms, Memory: 13.25MB
|
||||
|
||||
OK (22 tests, 31 assertions)
|
||||
```
|
||||
|
||||
When you are done working on the project you can free up disk space by removing
|
||||
the initially built image:
|
||||
|
||||
```
|
||||
docker image rm polyfill-unserialize
|
||||
```
|
||||
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "brumann/polyfill-unserialize",
|
||||
"description": "Backports unserialize options introduced in PHP 7.0 to older PHP versions.",
|
||||
"type": "library",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Denis Brumann",
|
||||
"email": "denis.brumann@sensiolabs.de"
|
||||
}
|
||||
],
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Brumann\\Polyfill\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Tests\\Brumann\\Polyfill\\": "tests/"
|
||||
}
|
||||
},
|
||||
"minimum-stability": "stable",
|
||||
"require": {
|
||||
"php": "^5.3|^7.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
<?php
|
||||
namespace Brumann\Polyfill;
|
||||
|
||||
/**
|
||||
* Worker implementation for identifying and skipping false-positives
|
||||
* not to be substituted - like nested serializations in string literals.
|
||||
*
|
||||
* @internal This class should only be used by \Brumann\Polyfill\Unserialize
|
||||
*/
|
||||
final class DisallowedClassesSubstitutor
|
||||
{
|
||||
const PATTERN_STRING = '#s:(\d+):(")#';
|
||||
const PATTERN_OBJECT = '#(^|;)O:\d+:"([^"]*)":(\d+):\{#';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $serialized;
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
private $allowedClasses;
|
||||
|
||||
/**
|
||||
* Each array item consists of `[<offset-start>, <offset-end>]` and
|
||||
* marks start and end positions of items to be ignored.
|
||||
*
|
||||
* @var array[]
|
||||
*/
|
||||
private $ignoreItems = array();
|
||||
|
||||
/**
|
||||
* @param string $serialized
|
||||
* @param string[] $allowedClasses
|
||||
*/
|
||||
public function __construct($serialized, array $allowedClasses)
|
||||
{
|
||||
$this->serialized = $serialized;
|
||||
$this->allowedClasses = $allowedClasses;
|
||||
|
||||
$this->buildIgnoreItems();
|
||||
$this->substituteObjects();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getSubstitutedSerialized()
|
||||
{
|
||||
return $this->serialized;
|
||||
}
|
||||
|
||||
/**
|
||||
* Identifies items to be ignored - like nested serializations in string literals.
|
||||
*/
|
||||
private function buildIgnoreItems()
|
||||
{
|
||||
$offset = 0;
|
||||
while (preg_match(self::PATTERN_STRING, $this->serialized, $matches, PREG_OFFSET_CAPTURE, $offset)) {
|
||||
$length = (int)$matches[1][0]; // given length in serialized data (e.g. `s:123:"` --> 123)
|
||||
$start = $matches[2][1]; // offset position of quote character
|
||||
$end = $start + $length + 1;
|
||||
$offset = $end + 1;
|
||||
|
||||
// serialized string nested in outer serialized string
|
||||
if ($this->ignore($start, $end)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->ignoreItems[] = array($start, $end);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Substitutes disallowed object class names and respects items to be ignored.
|
||||
*/
|
||||
private function substituteObjects()
|
||||
{
|
||||
$offset = 0;
|
||||
while (preg_match(self::PATTERN_OBJECT, $this->serialized, $matches, PREG_OFFSET_CAPTURE, $offset)) {
|
||||
$completeMatch = (string)$matches[0][0];
|
||||
$completeLength = strlen($completeMatch);
|
||||
$start = $matches[0][1];
|
||||
$end = $start + $completeLength;
|
||||
$leftBorder = (string)$matches[1][0];
|
||||
$className = (string)$matches[2][0];
|
||||
$objectSize = (int)$matches[3][0];
|
||||
$offset = $end + 1;
|
||||
|
||||
// class name is actually allowed - skip this item
|
||||
if (in_array($className, $this->allowedClasses, true)) {
|
||||
continue;
|
||||
}
|
||||
// serialized object nested in outer serialized string
|
||||
if ($this->ignore($start, $end)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$incompleteItem = $this->sanitizeItem($className, $leftBorder, $objectSize);
|
||||
$incompleteItemLength = strlen($incompleteItem);
|
||||
$offset = $start + $incompleteItemLength + 1;
|
||||
|
||||
$this->replace($incompleteItem, $start, $end);
|
||||
$this->shift($end, $incompleteItemLength - $completeLength);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces sanitized object class names in serialized data.
|
||||
*
|
||||
* @param string $replacement Sanitized object data
|
||||
* @param int $start Start offset in serialized data
|
||||
* @param int $end End offset in serialized data
|
||||
*/
|
||||
private function replace($replacement, $start, $end)
|
||||
{
|
||||
$this->serialized = substr($this->serialized, 0, $start)
|
||||
. $replacement . substr($this->serialized, $end);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether given offset positions should be ignored.
|
||||
*
|
||||
* @param int $start
|
||||
* @param int $end
|
||||
* @return bool
|
||||
*/
|
||||
private function ignore($start, $end)
|
||||
{
|
||||
foreach ($this->ignoreItems as $ignoreItem) {
|
||||
if ($ignoreItem[0] <= $start && $ignoreItem[1] >= $end) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shifts offset positions of ignore items by `$size`.
|
||||
* This is necessary whenever object class names have been
|
||||
* substituted which have a different length than before.
|
||||
*
|
||||
* @param int $offset
|
||||
* @param int $size
|
||||
*/
|
||||
private function shift($offset, $size)
|
||||
{
|
||||
foreach ($this->ignoreItems as &$ignoreItem) {
|
||||
// only focus on items starting after given offset
|
||||
if ($ignoreItem[0] < $offset) {
|
||||
continue;
|
||||
}
|
||||
$ignoreItem[0] += $size;
|
||||
$ignoreItem[1] += $size;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitizes object class item.
|
||||
*
|
||||
* @param string $className
|
||||
* @param int $leftBorder
|
||||
* @param int $objectSize
|
||||
* @return string
|
||||
*/
|
||||
private function sanitizeItem($className, $leftBorder, $objectSize)
|
||||
{
|
||||
return sprintf(
|
||||
'%sO:22:"__PHP_Incomplete_Class":%d:{s:27:"__PHP_Incomplete_Class_Name";%s',
|
||||
$leftBorder,
|
||||
$objectSize + 1, // size of object + 1 for added string
|
||||
\serialize($className)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace Brumann\Polyfill;
|
||||
|
||||
final class Unserialize
|
||||
{
|
||||
/**
|
||||
* @see https://secure.php.net/manual/en/function.unserialize.php
|
||||
*
|
||||
* @param string $serialized Serialized data
|
||||
* @param array $options Associative array containing options
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public static function unserialize($serialized, array $options = array())
|
||||
{
|
||||
if (PHP_VERSION_ID >= 70000) {
|
||||
return \unserialize($serialized, $options);
|
||||
}
|
||||
if (!array_key_exists('allowed_classes', $options) || true === $options['allowed_classes']) {
|
||||
return \unserialize($serialized);
|
||||
}
|
||||
$allowedClasses = $options['allowed_classes'];
|
||||
if (false === $allowedClasses) {
|
||||
$allowedClasses = array();
|
||||
}
|
||||
if (!is_array($allowedClasses)) {
|
||||
$allowedClasses = array();
|
||||
trigger_error(
|
||||
'unserialize(): allowed_classes option should be array or boolean',
|
||||
E_USER_WARNING
|
||||
);
|
||||
}
|
||||
|
||||
$worker = new DisallowedClassesSubstitutor($serialized, $allowedClasses);
|
||||
|
||||
return \unserialize($worker->getSubstitutedSerialized());
|
||||
}
|
||||
}
|
||||
579
wp-content/plugins/stops-core-theme-and-plugin-updates/vendor/composer/ClassLoader.php
vendored
Normal file
579
wp-content/plugins/stops-core-theme-and-plugin-updates/vendor/composer/ClassLoader.php
vendored
Normal file
@@ -0,0 +1,579 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer\Autoload;
|
||||
|
||||
/**
|
||||
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
|
||||
*
|
||||
* $loader = new \Composer\Autoload\ClassLoader();
|
||||
*
|
||||
* // register classes with namespaces
|
||||
* $loader->add('Symfony\Component', __DIR__.'/component');
|
||||
* $loader->add('Symfony', __DIR__.'/framework');
|
||||
*
|
||||
* // activate the autoloader
|
||||
* $loader->register();
|
||||
*
|
||||
* // to enable searching the include path (eg. for PEAR packages)
|
||||
* $loader->setUseIncludePath(true);
|
||||
*
|
||||
* In this example, if you try to use a class in the Symfony\Component
|
||||
* namespace or one of its children (Symfony\Component\Console for instance),
|
||||
* the autoloader will first look for the class under the component/
|
||||
* directory, and it will then fallback to the framework/ directory if not
|
||||
* found before giving up.
|
||||
*
|
||||
* This class is loosely based on the Symfony UniversalClassLoader.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
* @see https://www.php-fig.org/psr/psr-0/
|
||||
* @see https://www.php-fig.org/psr/psr-4/
|
||||
*/
|
||||
class ClassLoader
|
||||
{
|
||||
/** @var \Closure(string):void */
|
||||
private static $includeFile;
|
||||
|
||||
/** @var string|null */
|
||||
private $vendorDir;
|
||||
|
||||
// PSR-4
|
||||
/**
|
||||
* @var array<string, array<string, int>>
|
||||
*/
|
||||
private $prefixLengthsPsr4 = array();
|
||||
/**
|
||||
* @var array<string, list<string>>
|
||||
*/
|
||||
private $prefixDirsPsr4 = array();
|
||||
/**
|
||||
* @var list<string>
|
||||
*/
|
||||
private $fallbackDirsPsr4 = array();
|
||||
|
||||
// PSR-0
|
||||
/**
|
||||
* List of PSR-0 prefixes
|
||||
*
|
||||
* Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2')))
|
||||
*
|
||||
* @var array<string, array<string, list<string>>>
|
||||
*/
|
||||
private $prefixesPsr0 = array();
|
||||
/**
|
||||
* @var list<string>
|
||||
*/
|
||||
private $fallbackDirsPsr0 = array();
|
||||
|
||||
/** @var bool */
|
||||
private $useIncludePath = false;
|
||||
|
||||
/**
|
||||
* @var array<string, string>
|
||||
*/
|
||||
private $classMap = array();
|
||||
|
||||
/** @var bool */
|
||||
private $classMapAuthoritative = false;
|
||||
|
||||
/**
|
||||
* @var array<string, bool>
|
||||
*/
|
||||
private $missingClasses = array();
|
||||
|
||||
/** @var string|null */
|
||||
private $apcuPrefix;
|
||||
|
||||
/**
|
||||
* @var array<string, self>
|
||||
*/
|
||||
private static $registeredLoaders = array();
|
||||
|
||||
/**
|
||||
* @param string|null $vendorDir
|
||||
*/
|
||||
public function __construct($vendorDir = null)
|
||||
{
|
||||
$this->vendorDir = $vendorDir;
|
||||
self::initializeIncludeClosure();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, list<string>>
|
||||
*/
|
||||
public function getPrefixes()
|
||||
{
|
||||
if (!empty($this->prefixesPsr0)) {
|
||||
return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, list<string>>
|
||||
*/
|
||||
public function getPrefixesPsr4()
|
||||
{
|
||||
return $this->prefixDirsPsr4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<string>
|
||||
*/
|
||||
public function getFallbackDirs()
|
||||
{
|
||||
return $this->fallbackDirsPsr0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<string>
|
||||
*/
|
||||
public function getFallbackDirsPsr4()
|
||||
{
|
||||
return $this->fallbackDirsPsr4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, string> Array of classname => path
|
||||
*/
|
||||
public function getClassMap()
|
||||
{
|
||||
return $this->classMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, string> $classMap Class to filename map
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addClassMap(array $classMap)
|
||||
{
|
||||
if ($this->classMap) {
|
||||
$this->classMap = array_merge($this->classMap, $classMap);
|
||||
} else {
|
||||
$this->classMap = $classMap;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-0 directories for a given prefix, either
|
||||
* appending or prepending to the ones previously set for this prefix.
|
||||
*
|
||||
* @param string $prefix The prefix
|
||||
* @param list<string>|string $paths The PSR-0 root directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add($prefix, $paths, $prepend = false)
|
||||
{
|
||||
$paths = (array) $paths;
|
||||
if (!$prefix) {
|
||||
if ($prepend) {
|
||||
$this->fallbackDirsPsr0 = array_merge(
|
||||
$paths,
|
||||
$this->fallbackDirsPsr0
|
||||
);
|
||||
} else {
|
||||
$this->fallbackDirsPsr0 = array_merge(
|
||||
$this->fallbackDirsPsr0,
|
||||
$paths
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$first = $prefix[0];
|
||||
if (!isset($this->prefixesPsr0[$first][$prefix])) {
|
||||
$this->prefixesPsr0[$first][$prefix] = $paths;
|
||||
|
||||
return;
|
||||
}
|
||||
if ($prepend) {
|
||||
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||
$paths,
|
||||
$this->prefixesPsr0[$first][$prefix]
|
||||
);
|
||||
} else {
|
||||
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||
$this->prefixesPsr0[$first][$prefix],
|
||||
$paths
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-4 directories for a given namespace, either
|
||||
* appending or prepending to the ones previously set for this namespace.
|
||||
*
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param list<string>|string $paths The PSR-4 base directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addPsr4($prefix, $paths, $prepend = false)
|
||||
{
|
||||
$paths = (array) $paths;
|
||||
if (!$prefix) {
|
||||
// Register directories for the root namespace.
|
||||
if ($prepend) {
|
||||
$this->fallbackDirsPsr4 = array_merge(
|
||||
$paths,
|
||||
$this->fallbackDirsPsr4
|
||||
);
|
||||
} else {
|
||||
$this->fallbackDirsPsr4 = array_merge(
|
||||
$this->fallbackDirsPsr4,
|
||||
$paths
|
||||
);
|
||||
}
|
||||
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
|
||||
// Register directories for a new namespace.
|
||||
$length = strlen($prefix);
|
||||
if ('\\' !== $prefix[$length - 1]) {
|
||||
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||
}
|
||||
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||
$this->prefixDirsPsr4[$prefix] = $paths;
|
||||
} elseif ($prepend) {
|
||||
// Prepend directories for an already registered namespace.
|
||||
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||
$paths,
|
||||
$this->prefixDirsPsr4[$prefix]
|
||||
);
|
||||
} else {
|
||||
// Append directories for an already registered namespace.
|
||||
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||
$this->prefixDirsPsr4[$prefix],
|
||||
$paths
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-0 directories for a given prefix,
|
||||
* replacing any others previously set for this prefix.
|
||||
*
|
||||
* @param string $prefix The prefix
|
||||
* @param list<string>|string $paths The PSR-0 base directories
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function set($prefix, $paths)
|
||||
{
|
||||
if (!$prefix) {
|
||||
$this->fallbackDirsPsr0 = (array) $paths;
|
||||
} else {
|
||||
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-4 directories for a given namespace,
|
||||
* replacing any others previously set for this namespace.
|
||||
*
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param list<string>|string $paths The PSR-4 base directories
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setPsr4($prefix, $paths)
|
||||
{
|
||||
if (!$prefix) {
|
||||
$this->fallbackDirsPsr4 = (array) $paths;
|
||||
} else {
|
||||
$length = strlen($prefix);
|
||||
if ('\\' !== $prefix[$length - 1]) {
|
||||
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||
}
|
||||
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||
$this->prefixDirsPsr4[$prefix] = (array) $paths;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns on searching the include path for class files.
|
||||
*
|
||||
* @param bool $useIncludePath
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setUseIncludePath($useIncludePath)
|
||||
{
|
||||
$this->useIncludePath = $useIncludePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Can be used to check if the autoloader uses the include path to check
|
||||
* for classes.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getUseIncludePath()
|
||||
{
|
||||
return $this->useIncludePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns off searching the prefix and fallback directories for classes
|
||||
* that have not been registered with the class map.
|
||||
*
|
||||
* @param bool $classMapAuthoritative
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setClassMapAuthoritative($classMapAuthoritative)
|
||||
{
|
||||
$this->classMapAuthoritative = $classMapAuthoritative;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should class lookup fail if not found in the current class map?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isClassMapAuthoritative()
|
||||
{
|
||||
return $this->classMapAuthoritative;
|
||||
}
|
||||
|
||||
/**
|
||||
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
|
||||
*
|
||||
* @param string|null $apcuPrefix
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setApcuPrefix($apcuPrefix)
|
||||
{
|
||||
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The APCu prefix in use, or null if APCu caching is not enabled.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getApcuPrefix()
|
||||
{
|
||||
return $this->apcuPrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers this instance as an autoloader.
|
||||
*
|
||||
* @param bool $prepend Whether to prepend the autoloader or not
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register($prepend = false)
|
||||
{
|
||||
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
|
||||
|
||||
if (null === $this->vendorDir) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($prepend) {
|
||||
self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
|
||||
} else {
|
||||
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||
self::$registeredLoaders[$this->vendorDir] = $this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters this instance as an autoloader.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function unregister()
|
||||
{
|
||||
spl_autoload_unregister(array($this, 'loadClass'));
|
||||
|
||||
if (null !== $this->vendorDir) {
|
||||
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the given class or interface.
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
* @return true|null True if loaded, null otherwise
|
||||
*/
|
||||
public function loadClass($class)
|
||||
{
|
||||
if ($file = $this->findFile($class)) {
|
||||
$includeFile = self::$includeFile;
|
||||
$includeFile($file);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the path to the file where the class is defined.
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
*
|
||||
* @return string|false The path if found, false otherwise
|
||||
*/
|
||||
public function findFile($class)
|
||||
{
|
||||
// class map lookup
|
||||
if (isset($this->classMap[$class])) {
|
||||
return $this->classMap[$class];
|
||||
}
|
||||
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
|
||||
return false;
|
||||
}
|
||||
if (null !== $this->apcuPrefix) {
|
||||
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
|
||||
if ($hit) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
$file = $this->findFileWithExtension($class, '.php');
|
||||
|
||||
// Search for Hack files if we are running on HHVM
|
||||
if (false === $file && defined('HHVM_VERSION')) {
|
||||
$file = $this->findFileWithExtension($class, '.hh');
|
||||
}
|
||||
|
||||
if (null !== $this->apcuPrefix) {
|
||||
apcu_add($this->apcuPrefix.$class, $file);
|
||||
}
|
||||
|
||||
if (false === $file) {
|
||||
// Remember that this class does not exist.
|
||||
$this->missingClasses[$class] = true;
|
||||
}
|
||||
|
||||
return $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently registered loaders keyed by their corresponding vendor directories.
|
||||
*
|
||||
* @return array<string, self>
|
||||
*/
|
||||
public static function getRegisteredLoaders()
|
||||
{
|
||||
return self::$registeredLoaders;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $class
|
||||
* @param string $ext
|
||||
* @return string|false
|
||||
*/
|
||||
private function findFileWithExtension($class, $ext)
|
||||
{
|
||||
// PSR-4 lookup
|
||||
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
|
||||
|
||||
$first = $class[0];
|
||||
if (isset($this->prefixLengthsPsr4[$first])) {
|
||||
$subPath = $class;
|
||||
while (false !== $lastPos = strrpos($subPath, '\\')) {
|
||||
$subPath = substr($subPath, 0, $lastPos);
|
||||
$search = $subPath . '\\';
|
||||
if (isset($this->prefixDirsPsr4[$search])) {
|
||||
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
|
||||
foreach ($this->prefixDirsPsr4[$search] as $dir) {
|
||||
if (file_exists($file = $dir . $pathEnd)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-4 fallback dirs
|
||||
foreach ($this->fallbackDirsPsr4 as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 lookup
|
||||
if (false !== $pos = strrpos($class, '\\')) {
|
||||
// namespaced class name
|
||||
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
|
||||
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
|
||||
} else {
|
||||
// PEAR-like class name
|
||||
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
|
||||
}
|
||||
|
||||
if (isset($this->prefixesPsr0[$first])) {
|
||||
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
|
||||
if (0 === strpos($class, $prefix)) {
|
||||
foreach ($dirs as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 fallback dirs
|
||||
foreach ($this->fallbackDirsPsr0 as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 include paths.
|
||||
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
private static function initializeIncludeClosure()
|
||||
{
|
||||
if (self::$includeFile !== null) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope isolated include.
|
||||
*
|
||||
* Prevents access to $this/self from included files.
|
||||
*
|
||||
* @param string $file
|
||||
* @return void
|
||||
*/
|
||||
self::$includeFile = \Closure::bind(static function($file) {
|
||||
include $file;
|
||||
}, null, null);
|
||||
}
|
||||
}
|
||||
359
wp-content/plugins/stops-core-theme-and-plugin-updates/vendor/composer/InstalledVersions.php
vendored
Normal file
359
wp-content/plugins/stops-core-theme-and-plugin-updates/vendor/composer/InstalledVersions.php
vendored
Normal file
@@ -0,0 +1,359 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer;
|
||||
|
||||
use Composer\Autoload\ClassLoader;
|
||||
use Composer\Semver\VersionParser;
|
||||
|
||||
/**
|
||||
* This class is copied in every Composer installed project and available to all
|
||||
*
|
||||
* See also https://getcomposer.org/doc/07-runtime.md#installed-versions
|
||||
*
|
||||
* To require its presence, you can require `composer-runtime-api ^2.0`
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class InstalledVersions
|
||||
{
|
||||
/**
|
||||
* @var mixed[]|null
|
||||
* @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
|
||||
*/
|
||||
private static $installed;
|
||||
|
||||
/**
|
||||
* @var bool|null
|
||||
*/
|
||||
private static $canGetVendors;
|
||||
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||
*/
|
||||
private static $installedByVendor = array();
|
||||
|
||||
/**
|
||||
* Returns a list of all package names which are present, either by being installed, replaced or provided
|
||||
*
|
||||
* @return string[]
|
||||
* @psalm-return list<string>
|
||||
*/
|
||||
public static function getInstalledPackages()
|
||||
{
|
||||
$packages = array();
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
$packages[] = array_keys($installed['versions']);
|
||||
}
|
||||
|
||||
if (1 === \count($packages)) {
|
||||
return $packages[0];
|
||||
}
|
||||
|
||||
return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all package names with a specific type e.g. 'library'
|
||||
*
|
||||
* @param string $type
|
||||
* @return string[]
|
||||
* @psalm-return list<string>
|
||||
*/
|
||||
public static function getInstalledPackagesByType($type)
|
||||
{
|
||||
$packagesByType = array();
|
||||
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
foreach ($installed['versions'] as $name => $package) {
|
||||
if (isset($package['type']) && $package['type'] === $type) {
|
||||
$packagesByType[] = $name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $packagesByType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given package is installed
|
||||
*
|
||||
* This also returns true if the package name is provided or replaced by another package
|
||||
*
|
||||
* @param string $packageName
|
||||
* @param bool $includeDevRequirements
|
||||
* @return bool
|
||||
*/
|
||||
public static function isInstalled($packageName, $includeDevRequirements = true)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (isset($installed['versions'][$packageName])) {
|
||||
return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given package satisfies a version constraint
|
||||
*
|
||||
* e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
|
||||
*
|
||||
* Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
|
||||
*
|
||||
* @param VersionParser $parser Install composer/semver to have access to this class and functionality
|
||||
* @param string $packageName
|
||||
* @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
|
||||
* @return bool
|
||||
*/
|
||||
public static function satisfies(VersionParser $parser, $packageName, $constraint)
|
||||
{
|
||||
$constraint = $parser->parseConstraints((string) $constraint);
|
||||
$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
|
||||
|
||||
return $provided->matches($constraint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a version constraint representing all the range(s) which are installed for a given package
|
||||
*
|
||||
* It is easier to use this via isInstalled() with the $constraint argument if you need to check
|
||||
* whether a given version of a package is installed, and not just whether it exists
|
||||
*
|
||||
* @param string $packageName
|
||||
* @return string Version constraint usable with composer/semver
|
||||
*/
|
||||
public static function getVersionRanges($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$ranges = array();
|
||||
if (isset($installed['versions'][$packageName]['pretty_version'])) {
|
||||
$ranges[] = $installed['versions'][$packageName]['pretty_version'];
|
||||
}
|
||||
if (array_key_exists('aliases', $installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
|
||||
}
|
||||
if (array_key_exists('replaced', $installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
|
||||
}
|
||||
if (array_key_exists('provided', $installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
|
||||
}
|
||||
|
||||
return implode(' || ', $ranges);
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
|
||||
*/
|
||||
public static function getVersion($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($installed['versions'][$packageName]['version'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $installed['versions'][$packageName]['version'];
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
|
||||
*/
|
||||
public static function getPrettyVersion($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($installed['versions'][$packageName]['pretty_version'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $installed['versions'][$packageName]['pretty_version'];
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
|
||||
*/
|
||||
public static function getReference($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($installed['versions'][$packageName]['reference'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $installed['versions'][$packageName]['reference'];
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
|
||||
*/
|
||||
public static function getInstallPath($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
|
||||
*/
|
||||
public static function getRootPackage()
|
||||
{
|
||||
$installed = self::getInstalled();
|
||||
|
||||
return $installed[0]['root'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw installed.php data for custom implementations
|
||||
*
|
||||
* @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
|
||||
* @return array[]
|
||||
* @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}
|
||||
*/
|
||||
public static function getRawData()
|
||||
{
|
||||
@trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
|
||||
|
||||
if (null === self::$installed) {
|
||||
// only require the installed.php file if this file is loaded from its dumped location,
|
||||
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
|
||||
if (substr(__DIR__, -8, 1) !== 'C') {
|
||||
self::$installed = include __DIR__ . '/installed.php';
|
||||
} else {
|
||||
self::$installed = array();
|
||||
}
|
||||
}
|
||||
|
||||
return self::$installed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw data of all installed.php which are currently loaded for custom implementations
|
||||
*
|
||||
* @return array[]
|
||||
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||
*/
|
||||
public static function getAllRawData()
|
||||
{
|
||||
return self::getInstalled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Lets you reload the static array from another file
|
||||
*
|
||||
* This is only useful for complex integrations in which a project needs to use
|
||||
* this class but then also needs to execute another project's autoloader in process,
|
||||
* and wants to ensure both projects have access to their version of installed.php.
|
||||
*
|
||||
* A typical case would be PHPUnit, where it would need to make sure it reads all
|
||||
* the data it needs from this class, then call reload() with
|
||||
* `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
|
||||
* the project in which it runs can then also use this class safely, without
|
||||
* interference between PHPUnit's dependencies and the project's dependencies.
|
||||
*
|
||||
* @param array[] $data A vendor/composer/installed.php data set
|
||||
* @return void
|
||||
*
|
||||
* @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $data
|
||||
*/
|
||||
public static function reload($data)
|
||||
{
|
||||
self::$installed = $data;
|
||||
self::$installedByVendor = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||
*/
|
||||
private static function getInstalled()
|
||||
{
|
||||
if (null === self::$canGetVendors) {
|
||||
self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
|
||||
}
|
||||
|
||||
$installed = array();
|
||||
|
||||
if (self::$canGetVendors) {
|
||||
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
|
||||
if (isset(self::$installedByVendor[$vendorDir])) {
|
||||
$installed[] = self::$installedByVendor[$vendorDir];
|
||||
} elseif (is_file($vendorDir.'/composer/installed.php')) {
|
||||
/** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
|
||||
$required = require $vendorDir.'/composer/installed.php';
|
||||
$installed[] = self::$installedByVendor[$vendorDir] = $required;
|
||||
if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
|
||||
self::$installed = $installed[count($installed) - 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (null === self::$installed) {
|
||||
// only require the installed.php file if this file is loaded from its dumped location,
|
||||
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
|
||||
if (substr(__DIR__, -8, 1) !== 'C') {
|
||||
/** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
|
||||
$required = require __DIR__ . '/installed.php';
|
||||
self::$installed = $required;
|
||||
} else {
|
||||
self::$installed = array();
|
||||
}
|
||||
}
|
||||
|
||||
if (self::$installed !== array()) {
|
||||
$installed[] = self::$installed;
|
||||
}
|
||||
|
||||
return $installed;
|
||||
}
|
||||
}
|
||||
21
wp-content/plugins/stops-core-theme-and-plugin-updates/vendor/composer/LICENSE
vendored
Normal file
21
wp-content/plugins/stops-core-theme-and-plugin-updates/vendor/composer/LICENSE
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
|
||||
Copyright (c) Nils Adermann, Jordi Boggiano
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
10
wp-content/plugins/stops-core-theme-and-plugin-updates/vendor/composer/autoload_classmap.php
vendored
Normal file
10
wp-content/plugins/stops-core-theme-and-plugin-updates/vendor/composer/autoload_classmap.php
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
// autoload_classmap.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
|
||||
);
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
// autoload_namespaces.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
);
|
||||
10
wp-content/plugins/stops-core-theme-and-plugin-updates/vendor/composer/autoload_psr4.php
vendored
Normal file
10
wp-content/plugins/stops-core-theme-and-plugin-updates/vendor/composer/autoload_psr4.php
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
// autoload_psr4.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'Brumann\\Polyfill\\' => array($vendorDir . '/brumann/polyfill-unserialize/src'),
|
||||
);
|
||||
36
wp-content/plugins/stops-core-theme-and-plugin-updates/vendor/composer/autoload_real.php
vendored
Normal file
36
wp-content/plugins/stops-core-theme-and-plugin-updates/vendor/composer/autoload_real.php
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
// autoload_real.php @generated by Composer
|
||||
|
||||
class ComposerAutoloaderInita423c23c686d92ae4c71ddde2e05a1ea
|
||||
{
|
||||
private static $loader;
|
||||
|
||||
public static function loadClassLoader($class)
|
||||
{
|
||||
if ('Composer\Autoload\ClassLoader' === $class) {
|
||||
require __DIR__ . '/ClassLoader.php';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Composer\Autoload\ClassLoader
|
||||
*/
|
||||
public static function getLoader()
|
||||
{
|
||||
if (null !== self::$loader) {
|
||||
return self::$loader;
|
||||
}
|
||||
|
||||
spl_autoload_register(array('ComposerAutoloaderInita423c23c686d92ae4c71ddde2e05a1ea', 'loadClassLoader'), true, true);
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInita423c23c686d92ae4c71ddde2e05a1ea', 'loadClassLoader'));
|
||||
|
||||
require __DIR__ . '/autoload_static.php';
|
||||
call_user_func(\Composer\Autoload\ComposerStaticInita423c23c686d92ae4c71ddde2e05a1ea::getInitializer($loader));
|
||||
|
||||
$loader->register(true);
|
||||
|
||||
return $loader;
|
||||
}
|
||||
}
|
||||
36
wp-content/plugins/stops-core-theme-and-plugin-updates/vendor/composer/autoload_static.php
vendored
Normal file
36
wp-content/plugins/stops-core-theme-and-plugin-updates/vendor/composer/autoload_static.php
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
// autoload_static.php @generated by Composer
|
||||
|
||||
namespace Composer\Autoload;
|
||||
|
||||
class ComposerStaticInita423c23c686d92ae4c71ddde2e05a1ea
|
||||
{
|
||||
public static $prefixLengthsPsr4 = array (
|
||||
'B' =>
|
||||
array (
|
||||
'Brumann\\Polyfill\\' => 17,
|
||||
),
|
||||
);
|
||||
|
||||
public static $prefixDirsPsr4 = array (
|
||||
'Brumann\\Polyfill\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/brumann/polyfill-unserialize/src',
|
||||
),
|
||||
);
|
||||
|
||||
public static $classMap = array (
|
||||
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
|
||||
);
|
||||
|
||||
public static function getInitializer(ClassLoader $loader)
|
||||
{
|
||||
return \Closure::bind(function () use ($loader) {
|
||||
$loader->prefixLengthsPsr4 = ComposerStaticInita423c23c686d92ae4c71ddde2e05a1ea::$prefixLengthsPsr4;
|
||||
$loader->prefixDirsPsr4 = ComposerStaticInita423c23c686d92ae4c71ddde2e05a1ea::$prefixDirsPsr4;
|
||||
$loader->classMap = ComposerStaticInita423c23c686d92ae4c71ddde2e05a1ea::$classMap;
|
||||
|
||||
}, null, ClassLoader::class);
|
||||
}
|
||||
}
|
||||
85
wp-content/plugins/stops-core-theme-and-plugin-updates/vendor/composer/installed.json
vendored
Normal file
85
wp-content/plugins/stops-core-theme-and-plugin-updates/vendor/composer/installed.json
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
{
|
||||
"packages": [
|
||||
{
|
||||
"name": "brumann/polyfill-unserialize",
|
||||
"version": "v2.0.0",
|
||||
"version_normalized": "2.0.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/dbrumann/polyfill-unserialize.git",
|
||||
"reference": "46e5c18ee87d8a9b5765ef95468c1ac27bd107bf"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/dbrumann/polyfill-unserialize/zipball/46e5c18ee87d8a9b5765ef95468c1ac27bd107bf",
|
||||
"reference": "46e5c18ee87d8a9b5765ef95468c1ac27bd107bf",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^5.3|^7.0"
|
||||
},
|
||||
"time": "2020-07-24T10:16:53+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Brumann\\Polyfill\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Denis Brumann",
|
||||
"email": "denis.brumann@sensiolabs.de"
|
||||
}
|
||||
],
|
||||
"description": "Backports unserialize options introduced in PHP 7.0 to older PHP versions.",
|
||||
"support": {
|
||||
"issues": "https://github.com/dbrumann/polyfill-unserialize/issues",
|
||||
"source": "https://github.com/dbrumann/polyfill-unserialize/tree/v2.0.0"
|
||||
},
|
||||
"install-path": "../brumann/polyfill-unserialize"
|
||||
},
|
||||
{
|
||||
"name": "team-updraft/common-libs",
|
||||
"version": "3.0.3",
|
||||
"version_normalized": "3.0.3.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "ssh://git@source.updraftplus.com:20022/team-updraft/common-libs.git",
|
||||
"reference": "cd30bf3b65e2cadcea1cca01deb32f5cd21a0b63"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://source.updraftplus.com/api/v4/projects/28/packages/composer/archives/team-updraft/common-libs.zip?sha=cd30bf3b65e2cadcea1cca01deb32f5cd21a0b63",
|
||||
"reference": "cd30bf3b65e2cadcea1cca01deb32f5cd21a0b63",
|
||||
"shasum": ""
|
||||
},
|
||||
"require-dev": {
|
||||
"dealerdirect/phpcodesniffer-composer-installer": "0.7.*",
|
||||
"phpcompatibility/php-compatibility": "9.3.*",
|
||||
"sirbrillig/phpcs-variable-analysis": "2.11.*",
|
||||
"squizlabs/php_codesniffer": "3.6.*",
|
||||
"wp-coding-standards/wpcs": "2.3.*"
|
||||
},
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"license": [
|
||||
"GPL-3.0-only"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Team Updraft",
|
||||
"email": "team.updraft@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "These are the common libs used across all of our projects",
|
||||
"install-path": "../team-updraft/common-libs"
|
||||
}
|
||||
],
|
||||
"dev": false,
|
||||
"dev-package-names": []
|
||||
}
|
||||
41
wp-content/plugins/stops-core-theme-and-plugin-updates/vendor/composer/installed.php
vendored
Normal file
41
wp-content/plugins/stops-core-theme-and-plugin-updates/vendor/composer/installed.php
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php return array(
|
||||
'root' => array(
|
||||
'name' => 'updraftplus/stops-core-theme-and-plugin-updates',
|
||||
'pretty_version' => 'dev-master',
|
||||
'version' => 'dev-master',
|
||||
'reference' => 'f29aa5298f5401b5aea9b10e11fc3f0e749444ed',
|
||||
'type' => 'project',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
'dev' => false,
|
||||
),
|
||||
'versions' => array(
|
||||
'brumann/polyfill-unserialize' => array(
|
||||
'pretty_version' => 'v2.0.0',
|
||||
'version' => '2.0.0.0',
|
||||
'reference' => '46e5c18ee87d8a9b5765ef95468c1ac27bd107bf',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../brumann/polyfill-unserialize',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'team-updraft/common-libs' => array(
|
||||
'pretty_version' => '3.0.3',
|
||||
'version' => '3.0.3.0',
|
||||
'reference' => 'cd30bf3b65e2cadcea1cca01deb32f5cd21a0b63',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../team-updraft/common-libs',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'updraftplus/stops-core-theme-and-plugin-updates' => array(
|
||||
'pretty_version' => 'dev-master',
|
||||
'version' => 'dev-master',
|
||||
'reference' => 'f29aa5298f5401b5aea9b10e11fc3f0e749444ed',
|
||||
'type' => 'project',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0"?>
|
||||
<ruleset name="UpdraftPlus">
|
||||
<!-- How to run on Commandline: vendor/bin/phpcs -p -s -d memory_limit=150M \-\-standard=CI/php-compatibility.xml src/ \-\-report-full \-\-extensions=php -->
|
||||
<description>UpdraftPlus PHP Compatibility Check</description>
|
||||
<!-- Set Memory Limit -->
|
||||
<ini name="memory_limit" value="150M"/>
|
||||
<!-- CI Cache -->
|
||||
<arg name="cache" value="../CI/phpcs-cache-compatibility"/>
|
||||
<!-- Check up to 4 files simultanously. -->
|
||||
<arg name="parallel" value="4"/>
|
||||
<!-- Only Test for PHP 5.2+ -->
|
||||
<config name="testVersion" value="5.2-"/>
|
||||
<!-- Ignoring Folders As they are part of Vendor packages -->
|
||||
<!-- <exclude-pattern>src/tools/customer-tools/vendor</exclude-pattern> -->
|
||||
<!-- PHPCompatibility -->
|
||||
<rule ref="PHPCompatibility"/>
|
||||
</ruleset>
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0"?>
|
||||
<ruleset name="UpdraftPlus">
|
||||
<description>UpdraftPlus PHP Syntax Check</description>
|
||||
<!-- Set Memory Limit -->
|
||||
<ini name="memory_limit" value="150M"/>
|
||||
<!-- CI Cache -->
|
||||
<arg name="cache" value="../CI/phpcs-cache-syntax-check"/>
|
||||
<!-- Check up to 4 files simultanously. -->
|
||||
<arg name="parallel" value="4"/>
|
||||
<!-- Check for PHP syntax errors -->
|
||||
<rule ref="Generic.PHP.Syntax"/>
|
||||
</ruleset>
|
||||
10
wp-content/plugins/stops-core-theme-and-plugin-updates/vendor/team-updraft/common-libs/README.md
vendored
Normal file
10
wp-content/plugins/stops-core-theme-and-plugin-updates/vendor/team-updraft/common-libs/README.md
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
# Common Libraries
|
||||
|
||||
This project contains many useful libraries that are currently used and can be reused across our projects. They are kept here for easy maintenance and also so that consumers get a uniform interface and things dont break across versions or on updates.
|
||||
|
||||
CHANGELOG
|
||||
* TWEAK: Port from previous semaphore classes to Updraft_Semaphore_3_0 in updraft-tasks
|
||||
* FIX: Wrong query value in `delete_task_meta` method
|
||||
* TWEAK: Make the logging format uniform
|
||||
* FIX: Wrong DB Schema reference
|
||||
* TWEAK: Logging on the semaphore
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "team-updraft/common-libs",
|
||||
"description": "These are the common libs used across all of our projects",
|
||||
"type": "library",
|
||||
"license": "GPL-3.0-only",
|
||||
"authors": [{
|
||||
"name": "Team Updraft",
|
||||
"email": "team.updraft@gmail.com"
|
||||
}],
|
||||
"config": {
|
||||
"platform-check": false
|
||||
},
|
||||
"require-dev": {
|
||||
"squizlabs/php_codesniffer": "3.6.*",
|
||||
"phpcompatibility/php-compatibility": "9.3.*",
|
||||
"wp-coding-standards/wpcs": "2.3.*",
|
||||
"sirbrillig/phpcs-variable-analysis": "2.11.*",
|
||||
"dealerdirect/phpcodesniffer-composer-installer": "0.7.*"
|
||||
},
|
||||
"prefer-stable" : true
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
<?php
|
||||
|
||||
if (!defined('ABSPATH')) die('No direct access allowed');
|
||||
|
||||
abstract class Updraft_Notices_1_2 {
|
||||
|
||||
protected $notices_content;
|
||||
|
||||
// These variables are just short-hands to be used in advert content.
|
||||
protected $dashboard_top = array('top');
|
||||
|
||||
protected $dashboard_top_or_report = array('top', 'report', 'report-plain');
|
||||
|
||||
protected $dashboard_bottom_or_report = array('bottom', 'report', 'report-plain');
|
||||
|
||||
protected $anywhere = array('top', 'bottom', 'report', 'report-plain');
|
||||
|
||||
protected $autobackup = array('autobackup');
|
||||
|
||||
protected $autobackup_bottom_or_report = array('autobackup', 'bottom', 'report', 'report-plain');
|
||||
|
||||
/**
|
||||
* Global adverts that appear in all products will be returned to the child to display
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function populate_notices_content() {
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this method to setup the notices.
|
||||
*/
|
||||
abstract protected function notices_init();
|
||||
|
||||
/**
|
||||
* Checks if the plugin is installed and checks status if needed.
|
||||
*
|
||||
* @param null $product - Plugin to check
|
||||
* @param boolean $also_require_active - bool to indicate if active status is required or not
|
||||
*
|
||||
* @return boolean Returns true, if plugin is installed otherwise false
|
||||
*/
|
||||
protected function is_plugin_installed($product = null, $also_require_active = false) {
|
||||
if ($also_require_active) return class_exists($product);
|
||||
if (!function_exists('get_plugins')) include_once(ABSPATH.'wp-admin/includes/plugin.php');
|
||||
$plugins = get_plugins();
|
||||
foreach ($plugins as $value) {
|
||||
if ($value['TextDomain'] == $product) {
|
||||
// We have found the plugin so return false so that we do not display this advert.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if translation is needed or not
|
||||
*
|
||||
* @param string $plugin_base_dir - Base directory of plugin
|
||||
* @param string $product_name - Plugin name
|
||||
*
|
||||
* @return boolean Returns true if translation is needed, otherwise false
|
||||
*/
|
||||
protected function translation_needed($plugin_base_dir, $product_name) {
|
||||
$wplang = get_locale();
|
||||
if (strlen($wplang) < 1 || 'en_US' == $wplang || 'en_GB' == $wplang) return false;
|
||||
if (defined('WP_LANG_DIR') && is_file(WP_LANG_DIR.'/plugins/'.$product_name.'-'.$wplang.'.mo')) return false;
|
||||
if (is_file($plugin_base_dir.'/languages/'.$product_name.'-'.$wplang.'.mo')) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the start of a HTML URL
|
||||
*
|
||||
* @param boolean $html_allowed - indicates if HTML is allowed or not
|
||||
* @param string $url - the URL
|
||||
* @param boolean $https - the protocol to use
|
||||
* @param string $website_home - the product website name
|
||||
*
|
||||
* @return string returns a partial HTML URL
|
||||
*/
|
||||
protected function url_start($html_allowed, $url, $https = false, $website_home = null) {
|
||||
$proto = ($https) ? 'https' : 'http';
|
||||
if (strpos($url, $website_home) !== false) {
|
||||
return $html_allowed ? "<a href=".apply_filters(str_replace('.', '_', $website_home).'_link', $proto.'://'.$url).'>' : '';
|
||||
} else {
|
||||
return $html_allowed ? '<a href="'.$proto.'://'.$url.'">' : '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the end of a HTML URL
|
||||
*
|
||||
* @param boolean $html_allowed - indicates if HTML is allowed or not
|
||||
* @param string $url - the URL
|
||||
* @param boolean $https - the protocol to use
|
||||
*
|
||||
* @return string returns a partial HTML URL
|
||||
*/
|
||||
protected function url_end($html_allowed, $url, $https = false) {
|
||||
$proto = $https ? 'https' : 'http';
|
||||
return $html_allowed ? '</a>' : ' ('.$proto.'://'.$url.')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders notice
|
||||
*
|
||||
* @param mixed $notice - a specific notice to render or false
|
||||
* @param string $position - position of the notice
|
||||
* @param boolean $return_instead_of_echo - indicates if we should echo notice or return as string
|
||||
*
|
||||
* @return mixed Returns string or echos notice
|
||||
*/
|
||||
public function do_notice($notice = false, $position = 'top', $return_instead_of_echo = false) {
|
||||
|
||||
$this->notices_init();
|
||||
|
||||
if (false === $notice) $notice = apply_filters('updraft_notices_force_id', false, $this);
|
||||
|
||||
$notice_content = $this->get_notice_data($notice, $position);
|
||||
|
||||
if (false != $notice_content) {
|
||||
return $this->render_specified_notice($notice_content, $return_instead_of_echo, $position);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will return a notice ready for display.
|
||||
*
|
||||
* @param boolean $notice - a specific notice to render or false
|
||||
* @param string $position - position of the notice
|
||||
*
|
||||
* @return array returns notice data
|
||||
*/
|
||||
protected function get_notice_data($notice = false, $position = 'top') {
|
||||
|
||||
// If a specific notice has been passed to this method then return that notice.
|
||||
if ($notice) {
|
||||
if (!isset($this->notices_content[$notice])) return false;
|
||||
|
||||
// Does the notice support the position specified?
|
||||
if (isset($this->notices_content[$notice]['supported_positions']) && !in_array($position, $this->notices_content[$notice]['supported_positions'])) return false;
|
||||
|
||||
// First check if the advert passed can be displayed and hasn't been dismissed, we do this by checking what dismissed value we should be checking.
|
||||
$dismiss_time = $this->notices_content[$notice]['dismiss_time'];
|
||||
|
||||
$dismiss = $this->check_notice_dismissed($dismiss_time);
|
||||
|
||||
if ($dismiss) return false;
|
||||
|
||||
// If the advert has a validity function, then require the advert to be valid
|
||||
if (!empty($this->notices_content[$notice]['validity_function']) && !call_user_func(array($this, $this->notices_content[$notice]['validity_function']))) return false;
|
||||
|
||||
return $this->notices_content[$notice];
|
||||
}
|
||||
|
||||
// Create an array to add non-seasonal adverts to so that if a seasonal advert can't be returned we can choose a random advert from this array.
|
||||
$available_notices = array();
|
||||
|
||||
// If Advert wasn't passed then next we should check to see if a seasonal advert can be returned.
|
||||
foreach ($this->notices_content as $notice_id => $notice_data) {
|
||||
// Does the notice support the position specified?
|
||||
if (isset($this->notices_content[$notice_id]['supported_positions']) && !in_array($position, $this->notices_content[$notice_id]['supported_positions'])) continue;
|
||||
|
||||
// If the advert has a validity function, then require the advert to be valid.
|
||||
if (!empty($notice_data['validity_function']) && !call_user_func(array($this, $notice_data['validity_function']))) continue;
|
||||
|
||||
|
||||
if (isset($notice_data['valid_from']) && isset($notice_data['valid_to'])) {
|
||||
if ($this->skip_seasonal_notices($notice_data)) return $notice_data;
|
||||
} else {
|
||||
$dismiss_time = $this->notices_content[$notice_id]['dismiss_time'];
|
||||
$dismiss = $this->check_notice_dismissed($dismiss_time);
|
||||
|
||||
if (!$dismiss) $available_notices[$notice_id] = $notice_data;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($available_notices)) return false;
|
||||
|
||||
// If a seasonal advert can't be returned then we will return a random advert.
|
||||
|
||||
// Here we give a 25% chance for the rate advert to be returned before selecting a random advert from the entire collection which also includes the rate advert
|
||||
if (0 == rand(0, 3) && isset($available_notices['rate'])) return $available_notices['rate'];
|
||||
|
||||
// Using shuffle here as something like rand which produces a random number and uses that as the array index fails, this is because in future an advert may not be numbered and could have a string as its key which will then cause errors.
|
||||
shuffle($available_notices);
|
||||
return $available_notices[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Skip seasonal notices
|
||||
*
|
||||
* @param array $notice_data - an array of data for the chosen notice
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
protected function skip_seasonal_notices($notice_data) {// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns affiliate ID
|
||||
*
|
||||
* @return mixed Returns affiliate ID
|
||||
*/
|
||||
public function get_affiliate_id() {
|
||||
return $this->self_affiliate_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the notice has been dismissed
|
||||
*
|
||||
* @param string $dismiss_time - dismiss time
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
abstract protected function check_notice_dismissed($dismiss_time);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,213 @@
|
||||
<?php
|
||||
|
||||
if (!defined('ABSPATH')) die('No direct access.');
|
||||
|
||||
/**
|
||||
* Class Updraft_Semaphore_3_0
|
||||
*
|
||||
* This class is much simpler to use than the the previous series, as it has dropped support for complicated cases that were not being used. It also now only uses a single row in the options database, and takes care of creating it itself internally.
|
||||
*
|
||||
* Logging, though, may be noisier, unless your loggers are taking note of the log level and only registering what is required.
|
||||
*
|
||||
* Example of use (a lock that will expire if not released within 300 seconds)
|
||||
*
|
||||
* See test.php for a longer example (including logging).
|
||||
*
|
||||
* $my_lock = new Updraft_Semaphore_3_0('my_lock_name', 300);
|
||||
* // If getting the lock does not succeed first time, try again up to twice
|
||||
* if ($my_lock->lock(2)) {
|
||||
* try {
|
||||
* // do stuff ...
|
||||
* } catch (Exception $e) {
|
||||
* // We are making sure we release the lock in case of an error
|
||||
* } catch (Error $e) {
|
||||
* // We are making sure we release the lock in case of an error
|
||||
* }
|
||||
* $my_lock->release();
|
||||
* } else {
|
||||
* error_log("Sorry, could not get the lock");
|
||||
* }
|
||||
*/
|
||||
class Updraft_Semaphore_3_0 {
|
||||
|
||||
// Time after which the lock will expire (in seconds)
|
||||
protected $locked_for;
|
||||
|
||||
// Name for the lock in the WP options table
|
||||
protected $option_name;
|
||||
|
||||
// Lock status - a boolean
|
||||
protected $acquired = false;
|
||||
|
||||
// An array of loggers
|
||||
protected $loggers = array();
|
||||
|
||||
/**
|
||||
* Constructor. Instantiating does not lock anything, but sets up the details for future operations.
|
||||
*
|
||||
* @param String $name - a unique (across the WP site) name for the lock. Should be no more than 51 characters in length (because of the use of the WP options table, with some further characters used internally)
|
||||
* @param Integer $locked_for - time (in seconds) after which the lock will expire if not released. This needs to be positive if you don't want bad things to happen.
|
||||
* @param Array $loggers - an array of loggers
|
||||
*/
|
||||
public function __construct($name, $locked_for = 300, $loggers = array()) {
|
||||
$this->option_name = 'updraft_lock_'.$name;
|
||||
$this->locked_for = $locked_for;
|
||||
$this->loggers = $loggers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal function to make sure that the lock is set up in the database
|
||||
*
|
||||
* @return Integer - 0 means 'failed' (which could include that someone else concurrently created it); 1 means 'already existed'; 2 means 'exists, because we created it). The intention is that non-zero results mean that the lock exists.
|
||||
*/
|
||||
private function ensure_database_initialised() {
|
||||
|
||||
global $wpdb;
|
||||
|
||||
$sql = $wpdb->prepare("SELECT COUNT(*) FROM {$wpdb->options} WHERE option_name = %s", $this->option_name);
|
||||
|
||||
if (1 === (int) $wpdb->get_var($sql)) {
|
||||
$this->log('Lock option ('.$this->option_name.', '.$wpdb->options.') already existed in the database', 'debug');
|
||||
return 1;
|
||||
}
|
||||
|
||||
$sql = $wpdb->prepare("INSERT INTO {$wpdb->options} (option_name, option_value, autoload) VALUES(%s, '0', 'no');", $this->option_name);
|
||||
|
||||
$rows_affected = $wpdb->query($sql);
|
||||
|
||||
if ($rows_affected > 0) {
|
||||
$this->log('Lock option ('.$this->option_name.', '.$wpdb->options.') was created in the database', 'debug');
|
||||
} else {
|
||||
$this->log('Lock option ('.$this->option_name.', '.$wpdb->options.') failed to be created in the database (could already exist)', 'notice');
|
||||
}
|
||||
|
||||
return ($rows_affected > 0) ? 2 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to acquire the lock. If it was already acquired, then nothing extra will be done (the method will be a no-op).
|
||||
*
|
||||
* @param Integer $retries - how many times to retry (after a 1 second sleep each time)
|
||||
*
|
||||
* @return Boolean - whether the lock was successfully acquired or not
|
||||
*/
|
||||
public function lock($retries = 0) {
|
||||
|
||||
if ($this->acquired) return true;
|
||||
|
||||
global $wpdb;
|
||||
|
||||
$time_now = time();
|
||||
$acquire_until = $time_now + $this->locked_for;
|
||||
|
||||
$sql = $wpdb->prepare("UPDATE {$wpdb->options} SET option_value = %s WHERE option_name = %s AND option_value < %d", $acquire_until, $this->option_name, $time_now);
|
||||
|
||||
if (1 === $wpdb->query($sql)) {
|
||||
$this->log('Lock ('.$this->option_name.', '.$wpdb->options.') acquired', 'info');
|
||||
$this->acquired = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// See if the failure was caused by the row not existing (we check this only after failure, because it should only occur once on the site)
|
||||
if (!$this->ensure_database_initialised()) return false;
|
||||
|
||||
do {
|
||||
// Now that the row has been created, try again
|
||||
if (1 === $wpdb->query($sql)) {
|
||||
$this->log('Lock ('.$this->option_name.', '.$wpdb->options.') acquired after initialising the database', 'info');
|
||||
$this->acquired = true;
|
||||
return true;
|
||||
}
|
||||
$retries--;
|
||||
if ($retries >=0) {
|
||||
$this->log('Lock ('.$this->option_name.', '.$wpdb->options.') not yet acquired; sleeping', 'debug');
|
||||
sleep(1);
|
||||
// As a second has passed, update the time we are aiming for
|
||||
$time_now = time();
|
||||
$acquire_until = $time_now + $this->locked_for;
|
||||
$sql = $wpdb->prepare("UPDATE {$wpdb->options} SET option_value = %s WHERE option_name = %s AND option_value < %d", $acquire_until, $this->option_name, $time_now);
|
||||
}
|
||||
} while ($retries >= 0);
|
||||
|
||||
$this->log('Lock ('.$this->option_name.', '.$wpdb->options.') could not be acquired (it is locked)', 'info');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Release the lock
|
||||
*
|
||||
* N.B. We don't attempt to unlock it unless we locked it. i.e. Lost locks are left to expire rather than being forced. (If we want to force them, we'll need to introduce a new parameter).
|
||||
*
|
||||
* @return Boolean - if it returns false, then the lock was apparently not locked by us (and the caller will most likely therefore ignore the result, whatever it is).
|
||||
*/
|
||||
public function release() {
|
||||
if (!$this->acquired) return false;
|
||||
global $wpdb;
|
||||
$sql = $wpdb->prepare("UPDATE {$wpdb->options} SET option_value = '0' WHERE option_name = %s", $this->option_name);
|
||||
|
||||
$this->log('Lock option ('.$this->option_name.', '.$wpdb->options.') released', 'info');
|
||||
|
||||
$result = (int) $wpdb->query($sql) === 1;
|
||||
|
||||
$this->acquired = false;
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans up the DB of any residual data. This should not be used as part of ordinary unlocking; only as part of deinstalling, or if you otherwise know that the lock will not be used again. If calling this, it's redundant to first unlock (and a no-op to attempt to do so afterwards).
|
||||
*/
|
||||
public function delete() {
|
||||
$this->acquired = false;
|
||||
|
||||
global $wpdb;
|
||||
$wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->options} WHERE option_name = %s", $this->option_name));
|
||||
|
||||
$this->log('Lock option ('.$this->option_name.', '.$wpdb->options.') was deleted from the database');
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures and logs any given messages
|
||||
*
|
||||
* @param String $message - the error message
|
||||
* @param String $level - the message level (debug, notice, info, warning, error)
|
||||
*/
|
||||
public function log($message, $level = 'info') {
|
||||
if (isset($this->loggers)) {
|
||||
foreach ($this->loggers as $logger) {
|
||||
$logger->log($message, $level);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the list of loggers for this instance (removing any others).
|
||||
*
|
||||
* @param Array $loggers - the loggers for this task
|
||||
*/
|
||||
public function set_loggers($loggers) {
|
||||
$this->loggers = array();
|
||||
foreach ($loggers as $logger) {
|
||||
$this->add_logger($logger);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a logger to loggers list
|
||||
*
|
||||
* @param Callable $logger - a logger (a method with a callable function 'log', taking string parameters $level $message)
|
||||
*/
|
||||
public function add_logger($logger) {
|
||||
$this->loggers[] = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current list of loggers
|
||||
*
|
||||
* @return Array
|
||||
*/
|
||||
public function get_loggers() {
|
||||
return $this->loggers;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
Example usage:
|
||||
|
||||
php -a
|
||||
require 'wp-load.php';
|
||||
define('I_AM_TESTING', true);
|
||||
require 'test.php';
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) die('No direct access.');
|
||||
|
||||
if (!defined('I_AM_TESTING') || !I_AM_TESTING) die('Please define I_AM_TESTING.');
|
||||
|
||||
require_once(dirname(__FILE__).'/class-updraft-semaphore.php');
|
||||
|
||||
class Test_Logger_1 {
|
||||
function log($message, $level) {
|
||||
echo "Test_Logger_1::log(level=$level, message=$message)\n";
|
||||
}
|
||||
}
|
||||
|
||||
class Test_Logger_2 {
|
||||
function log($message, $level) {
|
||||
echo "Test_Logger_2::log(level=$level, message=$message)\n";
|
||||
}
|
||||
}
|
||||
|
||||
$my_lock = new Updraft_Semaphore_3_0('my_test_lock_name', 4, array(new Test_Logger_1()));
|
||||
|
||||
if ($my_lock->lock()) {
|
||||
try {
|
||||
// do stuff ...
|
||||
$my_lock_again = new Updraft_Semaphore_3_0('my_test_lock_name', 4, array(new Test_Logger_2()));
|
||||
$time_now = microtime(true);
|
||||
if ($my_lock_again->lock(6)) {
|
||||
echo "Eventually got it after ".round(microtime(true) - $time_now, 3)." seconds\n";
|
||||
$my_lock_again->release();
|
||||
} else {
|
||||
echo("Sorry, could not get the second lock\n");
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
var_dump($e);
|
||||
// We are making sure we release the lock in case of an error
|
||||
} catch (Error $e) { // phpcs:ignore PHPCompatibility.Classes.NewClasses.errorFound
|
||||
var_dump($e);
|
||||
// We are making sure we release the lock in case of an error
|
||||
}
|
||||
|
||||
$my_lock->release();
|
||||
|
||||
} else {
|
||||
echo("Sorry, could not get the first lock\n");
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
<?php
|
||||
/**
|
||||
* The AJAX Commands manager class
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) die('Access denied.');
|
||||
|
||||
if (!defined('Updraft_Task_Manager_Commands_1_0')) :
|
||||
|
||||
class Updraft_Task_Manager_Commands_1_0 {
|
||||
|
||||
protected $task_manager;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param Updraft_Task_Manager_1_3 $task_manager The task manager instance
|
||||
*/
|
||||
public function __construct($task_manager) {
|
||||
$this->task_manager = $task_manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* A list of allowed commands via AJAX
|
||||
*
|
||||
* @return array - List of allowed commands
|
||||
*/
|
||||
public static function get_allowed_ajax_commands() {
|
||||
|
||||
$commands = array(
|
||||
'process_task',
|
||||
'get_task_status',
|
||||
'end_task',
|
||||
'process_queue',
|
||||
'get_active_tasks',
|
||||
'clean_up_old_tasks',
|
||||
);
|
||||
|
||||
return apply_filters('updraft_task_manager_allowed_ajax_commands', $commands);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a single task in the queue
|
||||
*
|
||||
* @param array $data data passed via AJAX
|
||||
* @return void|WP_Error status of the operation
|
||||
*/
|
||||
public function process_task($data) {
|
||||
|
||||
if (!isset($data['task_id']))
|
||||
return new WP_Error('id_missing', 'Task ID is missing or invalid');
|
||||
|
||||
$task_id = (int) $data['task_id'];
|
||||
|
||||
$response = apply_filters('updraft_task_manager_process_task_response', "Processing task: {$task_id}", $task_id);
|
||||
$this->close_browser_connection($response);
|
||||
$this->task_manager->process_task($task_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a single task in the queue
|
||||
*
|
||||
* @param array $data data passed via AJAX
|
||||
* @return String - status of task or false if none found
|
||||
*/
|
||||
public function get_task_status($data) {
|
||||
|
||||
if (!isset($data['task_id']))
|
||||
return new WP_Error('id_missing', 'Task ID is missing or invalid');
|
||||
|
||||
$task_id = (int) $data['task_id'];
|
||||
|
||||
return $this->task_manager->get_task_status($task_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends a given task
|
||||
*
|
||||
* @param array $data data passed via AJAX
|
||||
* @return boolean - Status of the operation.
|
||||
*/
|
||||
public function end_task($data) {
|
||||
|
||||
if (!isset($data['task_id']))
|
||||
return new WP_Error('id_missing', 'Task ID is missing or invalid');
|
||||
|
||||
$task_id = (int) $data['task_id'];
|
||||
|
||||
$status = $this->task_manager->end_task($task_id);
|
||||
|
||||
if (!$status) return new WP_Error('end_task_failed', 'Task is already ended');
|
||||
|
||||
$response = apply_filters('updraft_task_manager_end_task_response', "Successfully ended task with id : {$task_id}", $task_id);
|
||||
$this->close_browser_connection($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a list of all active tasks
|
||||
*
|
||||
* @param array $data data passed via AJAX
|
||||
* @return Mixed - array of UpdraftPlus_Task ojects or NULL if none found
|
||||
*/
|
||||
public function get_active_tasks($data) {
|
||||
|
||||
if (!isset($data['type']))
|
||||
return new WP_Error('type_missing', 'Task type is missing or invalid');
|
||||
|
||||
$type = $data['type'];
|
||||
$tasks = $this->task_manager->get_active_tasks($type);
|
||||
|
||||
$ids = array();
|
||||
|
||||
if ($tasks) {
|
||||
foreach ($tasks as $task) {
|
||||
array_push($ids, $task->get_id());
|
||||
}
|
||||
}
|
||||
|
||||
$response = apply_filters('updraft_task_manager_get_active_tasks_response', $ids, $type);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans out all complete tasks from the DB.
|
||||
*
|
||||
* @param array $data data passed via AJAX
|
||||
* @return void|WP_Error status of the operation
|
||||
*/
|
||||
public function clean_up_old_tasks($data) {
|
||||
|
||||
if (!isset($data['type']))
|
||||
return new WP_Error('type_missing', 'Task type is missing or invalid');
|
||||
|
||||
$type = $data['type'];
|
||||
$status = $this->task_manager->clean_up_old_tasks($type);
|
||||
|
||||
if (!$status) return new WP_Error('clean_up_failed', 'Queue is already empty or the task type invalid');
|
||||
|
||||
$response = apply_filters('updraft_task_manager_clean_up_old_tasks_response', "Cleaned up old tasks of type : $type", $type);
|
||||
$this->close_browser_connection($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a queue of a specific type of task
|
||||
*
|
||||
* @param array $data data passed via AJAX
|
||||
* @return void|WP_Error status of the operation
|
||||
*/
|
||||
public function process_queue($data) {
|
||||
if (!isset($data['type']))
|
||||
return new WP_Error('type_missing', 'Task type is missing or invalid');
|
||||
|
||||
$type = $data['type'];
|
||||
|
||||
$response = apply_filters('updraft_task_manager_process_queue_response', "Processing queue of type {$type}", $type);
|
||||
|
||||
$this->close_browser_connection(json_encode($response));
|
||||
$status = $this->task_manager->process_queue($type);
|
||||
|
||||
if (!$status)
|
||||
return new WP_Error('process_queue_operation_failed', 'Failed to process the queue');
|
||||
}
|
||||
|
||||
/**
|
||||
* Close browser connection so that it can resume AJAX polling
|
||||
*
|
||||
* @param array $txt Response to browser
|
||||
* @return void
|
||||
*/
|
||||
public function close_browser_connection($txt = '') {
|
||||
header('Content-Length: '.((!empty($txt)) ? 5+strlen($txt) : '0'));
|
||||
header('Connection: close');
|
||||
header('Content-Encoding: none');
|
||||
if (session_id()) session_write_close();
|
||||
echo "\r\n\r\n";
|
||||
echo $txt;
|
||||
|
||||
$levels = ob_get_level();
|
||||
|
||||
for ($i = 0; $i < $levels; $i++) {
|
||||
ob_end_flush();
|
||||
}
|
||||
|
||||
flush();
|
||||
}
|
||||
}
|
||||
|
||||
endif;
|
||||
@@ -0,0 +1,387 @@
|
||||
<?php
|
||||
/**
|
||||
* A task manager that locks and processes the task queue
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) die('Access denied.');
|
||||
|
||||
if (!class_exists('Updraft_Task_Manager_1_3')) :
|
||||
|
||||
abstract class Updraft_Task_Manager_1_3 {
|
||||
|
||||
protected $loggers;
|
||||
|
||||
public $commands;
|
||||
|
||||
private $queue_semaphore;
|
||||
|
||||
/**
|
||||
* Set this to the number of seconds for the lock timeout, or 0 to not use a lock
|
||||
*/
|
||||
protected $use_per_task_lock = 0;
|
||||
|
||||
/**
|
||||
* The Task Manager constructor
|
||||
*/
|
||||
public function __construct() {
|
||||
|
||||
if (!class_exists('Updraft_Task_1_2')) require_once('class-updraft-task.php');
|
||||
if (!class_exists('Updraft_Task_Manager_Commands_1_0')) require_once('class-updraft-task-manager-commands.php');
|
||||
if (!class_exists('Updraft_Semaphore_3_0')) require_once(dirname(__FILE__).'/../updraft-semaphore/class-updraft-semaphore.php');
|
||||
if (!class_exists('Updraft_Tasks_Activation')) require_once(dirname(__FILE__).'/class-updraft-tasks-activation.php');
|
||||
|
||||
$this->commands = new Updraft_Task_Manager_Commands_1_0($this);
|
||||
|
||||
add_action('wp_ajax_updraft_taskmanager_ajax', array($this, 'updraft_taskmanager_ajax'));
|
||||
|
||||
do_action('updraft_task_manager_loaded', $this);
|
||||
}
|
||||
|
||||
/**
|
||||
* The Task Manager AJAX handler
|
||||
*/
|
||||
public function updraft_taskmanager_ajax() {
|
||||
|
||||
$nonce = empty($_REQUEST['nonce']) ? '' : $_REQUEST['nonce'];
|
||||
|
||||
if (!wp_verify_nonce($nonce, 'updraft-task-manager-ajax-nonce') || empty($_REQUEST['subaction']))
|
||||
die('Security check failed');
|
||||
|
||||
$subaction = $_REQUEST['subaction'];
|
||||
|
||||
$allowed_commands = Updraft_Task_Manager_Commands_1_0::get_allowed_ajax_commands();
|
||||
|
||||
if (in_array($subaction, $allowed_commands)) {
|
||||
|
||||
if (isset($_REQUEST['action_data']))
|
||||
$data = $_REQUEST['action_data'];
|
||||
|
||||
$results = call_user_func(array($this->commands, $subaction), $data);
|
||||
|
||||
if (is_wp_error($results)) {
|
||||
$results = array(
|
||||
'result' => false,
|
||||
'error_code' => $results->get_error_code(),
|
||||
'error_message' => $results->get_error_message(),
|
||||
'error_data' => $results->get_error_data(),
|
||||
);
|
||||
}
|
||||
|
||||
echo json_encode($results);
|
||||
} else {
|
||||
echo json_encode("{'error' : 'No such command found'}");
|
||||
}
|
||||
die;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a single task in the queue
|
||||
*
|
||||
* @param int|Updraft_Task - $task Task ID or Updraft_Task object.
|
||||
* @return boolean|WP_Error - status of task or error if task not found
|
||||
*/
|
||||
public function process_task($task) {
|
||||
|
||||
if (!is_a($task, 'Updraft_Task_1_2')) {
|
||||
$task_id = (int) $task;
|
||||
$task = $this->get_task_instance($task_id);
|
||||
}
|
||||
|
||||
if (!$task) return new WP_Error('id_invalid', 'Task not found or ID is invalid');
|
||||
|
||||
return $task->attempt(apply_filters('updraft_task_lock_for', $this->use_per_task_lock, $this));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of all tasks that matches the $status flag
|
||||
*
|
||||
* @param int|Updraft_Task - $task Task ID or Updraft_Task object.
|
||||
* @return String|WP_Error - status of task or error if task not found.
|
||||
*/
|
||||
public function get_task_status($task) {
|
||||
|
||||
if (!($task instanceof Updraft_Task_1_2)) {
|
||||
$task_id = (int) $task;
|
||||
$task = $this->get_task_instance($task_id);
|
||||
}
|
||||
|
||||
if (!$task) return new WP_Error('id_invalid', 'Task not found or ID is invalid');
|
||||
|
||||
return $task->get_status();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends a given task
|
||||
*
|
||||
* @param int|Updraft_Task - $task Task ID or Updraft_Task object.
|
||||
* @return boolean|WP_Error - Status of the operation or error if task not found.
|
||||
*/
|
||||
public function end_task($task) {
|
||||
|
||||
if (!($task instanceof Updraft_Task_1_2)) {
|
||||
$task_id = (int) $task;
|
||||
$task = $this->get_task_instance($task_id);
|
||||
}
|
||||
|
||||
if (!$task) return new WP_Error('id_invalid', 'Task not found or ID is invalid');
|
||||
|
||||
return $task->complete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a the queue of a specifed task type
|
||||
*
|
||||
* @param string $type queue type to process
|
||||
* @return bool true on success, false otherwise
|
||||
*/
|
||||
public function process_queue($type) {
|
||||
|
||||
$task_list = $this->get_active_tasks($type);
|
||||
$total = is_array($task_list) ? count($task_list) : 0;
|
||||
|
||||
if (1 > $total) {
|
||||
$this->log(sprintf('The queue for tasks of type "%s" is empty. Aborting!', $type));
|
||||
return true;
|
||||
} else {
|
||||
$this->log(sprintf('A total of %d tasks of type %s found and will be processed in this iteration', $total, $type));
|
||||
}
|
||||
|
||||
$this->queue_semaphore = new Updraft_Semaphore_3_0($type);
|
||||
|
||||
// Prevent PHP warning which trigger from semaphore class set_loggers method if $this->loggers is empty
|
||||
if (!empty($this->loggers)) {
|
||||
$this->queue_semaphore->set_loggers($this->loggers);
|
||||
}
|
||||
|
||||
if (!$this->queue_semaphore->lock()) {
|
||||
|
||||
$this->log(sprintf('Failed to gain semaphore lock (%s) - another process is already processing the queue - aborting (if this is wrong - i.e. if the other process crashed without removing the lock, then another can be started after 1 minute', $type));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$done = 0;
|
||||
foreach ($task_list as $task) {
|
||||
$this->process_task($task);
|
||||
$done++;
|
||||
/**
|
||||
* Filters if the queue should be interrupted. Used after processing each task.
|
||||
*
|
||||
* @param boolean $interrupt_queue - If the queue should be interrupted. Default to FALSE
|
||||
* @param object $task - The current task object
|
||||
* @param object $task_manager - The task manager instance
|
||||
*/
|
||||
if (apply_filters('updraft_interrupt_tasks_queue_'.$type, false, $task, $this)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$this->queue_semaphore->release();
|
||||
$this->log(sprintf('Successfully processed the queue (%s). %d tasks were processed out of %d.', $type, $done, $total));
|
||||
$this->queue_semaphore->delete();
|
||||
|
||||
return $done == $total;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans out all complete tasks from the DB.
|
||||
*
|
||||
* @param String $type type of the task
|
||||
*/
|
||||
public function clean_up_old_tasks($type) {
|
||||
$completed_tasks = $this->get_completed_tasks($type);
|
||||
|
||||
if (!$completed_tasks) return false;
|
||||
|
||||
$this->log(sprintf('Cleaning up tasks of type (%s). A total of %d tasks will be deleted.', $type, count($completed_tasks)));
|
||||
|
||||
foreach ($completed_tasks as $task) {
|
||||
$task->delete_meta();
|
||||
$task->delete();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all tasks from queue.
|
||||
*
|
||||
* @param string $type
|
||||
*
|
||||
* @return boolean|integer Number of rows deleted, or (boolean)false upon error
|
||||
*/
|
||||
public function delete_tasks($task_type) {
|
||||
global $wpdb;
|
||||
|
||||
$sql = "DELETE t, tm FROM `{$wpdb->base_prefix}tm_tasks` t LEFT JOIN `{$wpdb->base_prefix}tm_taskmeta` tm ON t.id = tm.task_id WHERE t.type = '{$task_type}'";
|
||||
|
||||
return $wpdb->query($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get count of completed and all tasks.
|
||||
*
|
||||
* @return array - [ ['complete_tasks' => , 'all_tasks' => ] ]
|
||||
*/
|
||||
public function get_status($task_type) {
|
||||
global $wpdb;
|
||||
|
||||
$query = $wpdb->prepare(
|
||||
"SELECT complete_tasks, all_tasks FROM (SELECT COUNT(*) AS complete_tasks FROM {$wpdb->base_prefix}tm_tasks WHERE `type` = %s AND `status` = %s) a, (SELECT COUNT(*) AS all_tasks FROM {$wpdb->base_prefix}tm_tasks WHERE `type` = %s) b",
|
||||
array(
|
||||
$task_type,
|
||||
'complete',
|
||||
$task_type,
|
||||
)
|
||||
);
|
||||
|
||||
$status = $wpdb->get_row($query, ARRAY_A);
|
||||
|
||||
if (empty($status)) {
|
||||
$status = array(
|
||||
'complete_tasks' => 0,
|
||||
'all_tasks' => 0,
|
||||
);
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a list of all active tasks
|
||||
*
|
||||
* @param String $type type of the task
|
||||
* @return Mixed - array of Task ojects or NULL if none found
|
||||
*/
|
||||
public function get_active_tasks($type) {
|
||||
return $this->get_tasks('active', $type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of all completed tasks
|
||||
*
|
||||
* @param String $type type of the task
|
||||
* @return Mixed - array of Task ojects or NULL if none found
|
||||
*/
|
||||
public function get_completed_tasks($type) {
|
||||
return $this->get_tasks('complete', $type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of all tasks that matches the $status flag
|
||||
*
|
||||
* @param String $status - status of tasks to return, defaults to all tasks
|
||||
* @param String $type - type of task
|
||||
*
|
||||
* @return Mixed - array of Task objects or NULL if none found
|
||||
*/
|
||||
public function get_tasks($status, $type) {
|
||||
global $wpdb;
|
||||
|
||||
$tasks = array();
|
||||
|
||||
if (array_key_exists($status, Updraft_Task_1_2::get_allowed_statuses())) {
|
||||
$sql = $wpdb->prepare("SELECT * FROM {$wpdb->base_prefix}tm_tasks WHERE status = %s AND type = %s", $status, $type);
|
||||
} else {
|
||||
$sql = $wpdb->prepare("SELECT * FROM {$wpdb->base_prefix}tm_tasks WHERE type = %s", $type);
|
||||
}
|
||||
|
||||
$_tasks = $wpdb->get_results($sql);
|
||||
|
||||
if (!$_tasks) {
|
||||
// if we got an error then check if task manager tables are in the database
|
||||
// and recreate them if needed.
|
||||
if ($wpdb->last_error) {
|
||||
Updraft_Tasks_Activation::reinstall_if_needed();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
foreach ($_tasks as $_task) {
|
||||
$task = $this->get_task_instance($_task->id);
|
||||
if ($task) array_push($tasks, $task);
|
||||
}
|
||||
|
||||
return $tasks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the task instance using its ID
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @global wpdb $wpdb WordPress database abstraction object.
|
||||
*
|
||||
* @param int $task_id Task ID.
|
||||
* @return Task|Boolean Task object, false otherwise.
|
||||
*/
|
||||
public function get_task_instance($task_id) {
|
||||
global $wpdb;
|
||||
|
||||
$task_id = (int) $task_id;
|
||||
if (!$task_id) return false;
|
||||
|
||||
$sql = $wpdb->prepare("SELECT * FROM {$wpdb->base_prefix}tm_tasks WHERE id = %d LIMIT 1", $task_id);
|
||||
$_task = $wpdb->get_row($sql);
|
||||
|
||||
if (!$_task)
|
||||
return false;
|
||||
|
||||
$class_identifier = $_task->class_identifier;
|
||||
|
||||
if (class_exists($class_identifier))
|
||||
$task_instance = new $class_identifier($_task);
|
||||
$task_instance->set_loggers($this->loggers);
|
||||
return $task_instance;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the logger for this instance.
|
||||
*
|
||||
* @param array $loggers - the loggers for this task
|
||||
*/
|
||||
public function set_loggers($loggers) {
|
||||
foreach ($loggers as $logger) {
|
||||
$this->add_logger($logger);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a logger to loggers list
|
||||
*
|
||||
* @param Object $logger - a logger for the instance
|
||||
*/
|
||||
public function add_logger($logger) {
|
||||
$this->loggers[] = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return list of loggers
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_loggers() {
|
||||
return $this->loggers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures and logs any interesting messages
|
||||
*
|
||||
* @param String $message - the error message
|
||||
* @param String $error_type - the error type
|
||||
*/
|
||||
public function log($message, $error_type = 'info') {
|
||||
if (isset($this->loggers)) {
|
||||
foreach ($this->loggers as $logger) {
|
||||
$logger->log($message, $error_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
endif;
|
||||
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
/**
|
||||
* The DB handle class for the options framework
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) die('Access denied.');
|
||||
|
||||
if (!class_exists('Updraft_Task_Meta')) :
|
||||
|
||||
class Updraft_Task_Meta {
|
||||
|
||||
/**
|
||||
* This method gets data from the task meta table in the WordPress database
|
||||
*
|
||||
* @param int $id the instance id of the task
|
||||
* @param String $key the key to get
|
||||
*
|
||||
* @return Mixed The option from the database
|
||||
*/
|
||||
public static function get_task_meta($id, $key) {
|
||||
global $wpdb;
|
||||
|
||||
$id = (int) $id;
|
||||
if (!$id) return false;
|
||||
|
||||
$sql = $wpdb->prepare("SELECT meta_value FROM {$wpdb->base_prefix}tm_taskmeta WHERE task_id = %d AND meta_key = %s LIMIT 1", $id, $key);
|
||||
|
||||
$meta = $wpdb->get_var($sql);
|
||||
|
||||
if ($meta)
|
||||
return maybe_unserialize($meta);
|
||||
else return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method is used to update data stored in the WordPress database
|
||||
*
|
||||
* @param int $id the instance id of the task
|
||||
* @param String $key the key of the data to update
|
||||
* @param Mixed $value the value to save to the option
|
||||
*
|
||||
* @return Mixed the status of the update operation
|
||||
*/
|
||||
public static function update_task_meta($id, $key, $value) {
|
||||
global $wpdb;
|
||||
|
||||
$id = (int) $id;
|
||||
if (!$id) return false;
|
||||
|
||||
$value = maybe_serialize($value);
|
||||
|
||||
if (false !== self::get_task_meta($id, $key)) {
|
||||
$sql = $wpdb->prepare("UPDATE {$wpdb->base_prefix}tm_taskmeta SET meta_value = %s WHERE meta_key = %s AND task_id = %d", $value, $key, $id);
|
||||
} else {
|
||||
$sql = $wpdb->prepare("INSERT INTO {$wpdb->base_prefix}tm_taskmeta (task_id, meta_key, meta_value) VALUES (%d, %s, %s)", $id, $key, $value);
|
||||
}
|
||||
|
||||
return $wpdb->query($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is used to delete task data stored in the WordPress database
|
||||
*
|
||||
* @param int $id the instance id of the task
|
||||
* @param String $key the key to delete
|
||||
*
|
||||
* @return Mixed the status of the delete operation
|
||||
*/
|
||||
public static function delete_task_meta($id, $key) {
|
||||
global $wpdb;
|
||||
|
||||
$id = (int) $id;
|
||||
if (!$id) return false;
|
||||
|
||||
$sql = $wpdb->prepare("DELETE FROM {$wpdb->base_prefix}tm_taskmeta WHERE task_id = %d AND meta_key = %s LIMIT 1", $id, $key);
|
||||
return $wpdb->query($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bulk delete task
|
||||
*
|
||||
* @param int $id the instance id of the task
|
||||
*/
|
||||
public static function bulk_delete_task_meta($id) {
|
||||
global $wpdb;
|
||||
|
||||
$id = (int) $id;
|
||||
if (!$id) return false;
|
||||
|
||||
$sql = $wpdb->prepare("DELETE FROM {$wpdb->base_prefix}tm_taskmeta WHERE task_id = %d", $id);
|
||||
return $wpdb->query($sql);
|
||||
}
|
||||
}
|
||||
|
||||
endif;
|
||||
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
/**
|
||||
* The options framework for tasks
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) die('Access denied.');
|
||||
|
||||
if (!class_exists('Updraft_Task_Options')) :
|
||||
|
||||
class Updraft_Task_Options {
|
||||
|
||||
/**
|
||||
* This method gets an option from the task meta table in the WordPress database
|
||||
*
|
||||
* @param int $instance_id the instance id of the task
|
||||
* @param String $option the name of the option to get
|
||||
* @param Mixed $default a value to return if the option is not currently set
|
||||
*
|
||||
* @return Mixed The option from the database
|
||||
*/
|
||||
public static function get_task_option($instance_id, $option, $default = null) {
|
||||
|
||||
$tmp = Updraft_Task_Meta::get_task_meta($instance_id, 'task_options');
|
||||
|
||||
if (isset($tmp[$option])) {
|
||||
$value = $tmp[$option];
|
||||
} else {
|
||||
$value = $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the value of an existing option.
|
||||
*
|
||||
* The dynamic portion of the hook name, `$option`, refers to the option name.
|
||||
*/
|
||||
return apply_filters("ud_task_option_{$option}", maybe_unserialize($value), $option, $default, $instance_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is used to update a task option stored in the WordPress database
|
||||
*
|
||||
* @param int $instance_id the instance id of the task
|
||||
* @param String $option the name of the option to update
|
||||
* @param Mixed $value the value to save to the option
|
||||
*
|
||||
* @return Mixed the status of the update operation
|
||||
*/
|
||||
public static function update_task_option($instance_id, $option, $value) {
|
||||
|
||||
$option = trim($option);
|
||||
|
||||
if (empty($option)) return false;
|
||||
|
||||
$old_value = self::get_task_option($instance_id, $option);
|
||||
|
||||
/**
|
||||
* Filters a specific option before its value is (maybe) serialized and updated.
|
||||
*/
|
||||
$value = apply_filters("ud_pre_update_task_option_{$option}", $value, $old_value, $option, $instance_id);
|
||||
|
||||
$tmp = Updraft_Task_Meta::get_task_meta($instance_id, 'task_options');
|
||||
|
||||
if (!is_array($tmp)) $tmp = array();
|
||||
$tmp[$option] = maybe_serialize($value);
|
||||
|
||||
$result = Updraft_Task_Meta::update_task_meta($instance_id, 'task_options', $tmp);
|
||||
|
||||
if ($result) {
|
||||
|
||||
/**
|
||||
* Fires after the value of a specific option has been successfully updated.
|
||||
*/
|
||||
do_action("ud_update_task_option_{$option}", $value, $old_value, $option, $instance_id);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is used to delete a task option stored in the WordPress database
|
||||
*
|
||||
* @param int $instance_id the instance id of the task
|
||||
* @param String $option the option to delete
|
||||
*/
|
||||
public static function delete_task_option($instance_id, $option) {
|
||||
|
||||
/**
|
||||
* Fires immediately before an option is deleted.
|
||||
*/
|
||||
do_action("ud_before_delete_task_option", $option, $instance_id);
|
||||
|
||||
$tmp = Updraft_Task_Meta::get_task_meta($instance_id, 'task_options');
|
||||
|
||||
if (is_array($tmp)) {
|
||||
if (isset($tmp[$option])) unset($tmp[$option]);
|
||||
} else {
|
||||
$tmp = array();
|
||||
}
|
||||
|
||||
$result = Updraft_Task_Meta::update_task_meta($instance_id, 'task_options', $tmp);
|
||||
|
||||
if ($result) {
|
||||
|
||||
/**
|
||||
* Fires after a specific option has been successfully deleted.
|
||||
*/
|
||||
do_action("ud_delete_task_option_{$option}", $option);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method gets all options assoicated with a task
|
||||
*
|
||||
* @param int $instance_id the instance id of the task
|
||||
*
|
||||
* @return Mixed The options from the database
|
||||
*/
|
||||
public static function get_all_task_options($instance_id) {
|
||||
|
||||
$value = Updraft_Task_Meta::get_task_meta($instance_id, 'task_options');
|
||||
return apply_filters("ud_all_task_options", maybe_unserialize($value), $instance_id);
|
||||
}
|
||||
}
|
||||
|
||||
endif;
|
||||
@@ -0,0 +1,693 @@
|
||||
<?php
|
||||
/**
|
||||
* The base class which must be extended to use the tasks library
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) die('Access denied.');
|
||||
|
||||
if (!class_exists('Updraft_Task_1_2')) :
|
||||
|
||||
if (!class_exists('Updraft_Task_Options')) require_once('class-updraft-task-options.php');
|
||||
if (!class_exists('Updraft_Task_Meta')) require_once('class-updraft-task-meta.php');
|
||||
|
||||
abstract class Updraft_Task_1_2 {
|
||||
|
||||
/**
|
||||
* A unique ID for the specific task
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* The user id of the creator of this task
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $user_id;
|
||||
|
||||
/**
|
||||
* A text description for the task
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $description;
|
||||
|
||||
/**
|
||||
* A type for the task
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $type;
|
||||
|
||||
/**
|
||||
* A timestamp indicating the time the task was created
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $time_created;
|
||||
|
||||
/**
|
||||
* The number of times this task was attempted
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $attempts;
|
||||
|
||||
/**
|
||||
* A text description describing the status of the task
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $status;
|
||||
|
||||
/**
|
||||
* An identifier indicating which child class created this instance
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $class_identifier;
|
||||
|
||||
/**
|
||||
* A logger object that can be used to capture interesting events / messages
|
||||
*
|
||||
* @var Object
|
||||
*/
|
||||
protected $_loggers;
|
||||
|
||||
/**
|
||||
* The Task constructor
|
||||
*
|
||||
* @param UpdraftPlus_Task|object $task UpdraftPlus_Task object.
|
||||
*/
|
||||
public function __construct($task) {
|
||||
foreach (get_object_vars($task) as $key => $value)
|
||||
$this->$key = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the instance ID.
|
||||
*
|
||||
* @param String $instance_id - the instance ID
|
||||
*/
|
||||
public function set_id($instance_id) {
|
||||
$this->id = $instance_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the instance ID.
|
||||
*
|
||||
* @return String the instance ID
|
||||
*/
|
||||
public function get_id() {
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the description.
|
||||
*
|
||||
* @param String $description - the description of the task
|
||||
*/
|
||||
public function set_description($description) {
|
||||
$this->description = $description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the task description
|
||||
*
|
||||
* @return String $description - the description of the task
|
||||
*/
|
||||
public function get_description() {
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the type.
|
||||
*
|
||||
* @param String $type - the type of the task
|
||||
*/
|
||||
public function set_type($type) {
|
||||
$this->type = $type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of times this task was attempted
|
||||
*
|
||||
* @return int $attempts - the count
|
||||
*/
|
||||
public function get_attempts() {
|
||||
return $this->attempts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the number of times this task was attempted
|
||||
*
|
||||
* @param String $attempts - the count
|
||||
*/
|
||||
public function set_attempts($attempts) {
|
||||
if (is_numeric($attempts))
|
||||
$this->attempts = $attempts;
|
||||
else return false;
|
||||
|
||||
return $this->update_attempts($this->id, $this->attempts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the task type
|
||||
*
|
||||
* @return String $type - the type of the task
|
||||
*/
|
||||
public function get_type() {
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the task status.
|
||||
*
|
||||
* @param String $status - the status of the task
|
||||
*
|
||||
* @return Boolean - the result of the status update
|
||||
*/
|
||||
public function set_status($status) {
|
||||
|
||||
if (array_key_exists($status, self::get_allowed_statuses()))
|
||||
$this->status = $status;
|
||||
else return false;
|
||||
|
||||
return $this->update_status($this->id, $this->status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the task status
|
||||
*
|
||||
* @return String $status - the status of the task
|
||||
*/
|
||||
public function get_status() {
|
||||
return $this->status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the logger for this task.
|
||||
*
|
||||
* @param array $loggers - the loggers for this task
|
||||
*/
|
||||
public function set_loggers($loggers) {
|
||||
if (is_array($loggers)) {
|
||||
foreach ($loggers as $logger) {
|
||||
$this->add_logger($logger);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a logger to loggers list
|
||||
*
|
||||
* @param Object $logger - a logger for the task
|
||||
*/
|
||||
public function add_logger($logger) {
|
||||
$this->_loggers[] = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return list of loggers
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_loggers() {
|
||||
return $this->_loggers;
|
||||
}
|
||||
|
||||
/**
|
||||
* The initialisation function that accepts and processes any parameters needed before the task starts
|
||||
*
|
||||
* @param Array $options - array of options
|
||||
*
|
||||
* @uses update_option
|
||||
*/
|
||||
public function initialise($options = array()) {
|
||||
|
||||
do_action('ud_task_before_initialise', $this, $options);
|
||||
|
||||
/**
|
||||
* Parse incoming $options into an array and merge it with defaults
|
||||
*/
|
||||
$defaults = $this->get_default_options();
|
||||
$options = wp_parse_args($options, $defaults);
|
||||
|
||||
foreach ($options as $option => $value) {
|
||||
$this->update_option($option, $value);
|
||||
}
|
||||
|
||||
do_action('ud_task_initialise_complete', $this, $options);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to perform the task
|
||||
*
|
||||
* @param integer $lock_for - if greater than zero, then lock the task, and don't break until this number of seconds has passed
|
||||
*
|
||||
* @return boolean Status of the attempt
|
||||
*/
|
||||
public function attempt($lock_for = 0) {
|
||||
|
||||
$_task = $this->get_task_from_db($this->get_id());
|
||||
|
||||
if (!$_task) {
|
||||
$this->log("The task with id : {$this->get_id()}, and type '{$this->get_type()}' seems to have been deleted from the database.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if ('complete' == $this->get_status()) {
|
||||
$this->log("Attempting already complete task with ID : {$this->get_id()}, and type '{$this->get_type()}'. Aborting !");
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($lock_for) {
|
||||
$try = 1;
|
||||
$locked = false;
|
||||
while ($try < 4) {
|
||||
if ($locked = $this->lock($this->get_id(), true, $lock_for)) break;
|
||||
$try ++;
|
||||
sleep(1);
|
||||
}
|
||||
if (!$locked) {
|
||||
$this->fail('could_not_lock', 'The task could not be locked');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$attempts = $this->get_attempts();
|
||||
|
||||
if ($attempts >= $this->get_max_attempts()) {
|
||||
$this->fail("max_attempts_exceeded", "Maximum attempts ($attempts) exceeded for task");
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->log("Processing task with ID : {$this->get_id()}, and type '{$this->get_type()}'");
|
||||
$this->set_attempts(++$attempts);
|
||||
$status = $this->run();
|
||||
|
||||
if ($status) {
|
||||
$this->complete();
|
||||
$this->log("Completed processing task with ID : {$this->get_id()}, and type '{$this->get_type()}'");
|
||||
}
|
||||
|
||||
if ($lock_for) $this->lock($this->get_id(), false);
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lock or unlock a task
|
||||
*
|
||||
* @param Integer - $task_id - task identifier
|
||||
* @param Boolean - $lock - whether to lock or unlock
|
||||
* @param Integer - $lock_for - if already locked, how long after which to break the lock
|
||||
*
|
||||
* @return Boolean - whether the operation was successful
|
||||
*/
|
||||
public function lock($task_id, $lock = true, $lock_for = 60) {
|
||||
|
||||
global $wpdb;
|
||||
|
||||
if (!$lock) {
|
||||
return $wpdb->update($wpdb->base_prefix.'tm_tasks', array('last_locked_at' => 0), array('id' => $task_id)) ? true : false;
|
||||
}
|
||||
|
||||
// Mode: lock. Attempt to set the lock
|
||||
$affected = $wpdb->update($wpdb->base_prefix.'tm_tasks', array('last_locked_at' => time()), array('id' => $task_id, 'last_locked_at' => 0));
|
||||
|
||||
// Success.
|
||||
if (1 == $affected) return true;
|
||||
|
||||
// Failed - something else already had it locked. Grab the lock if it had expired.
|
||||
$affected = $wpdb->update($wpdb->base_prefix.'tm_tasks', array('last_locked_at' => time()), array('id' => $task_id, 'last_locked_at' => 0));
|
||||
|
||||
$expires_at = time() - $lock_for;
|
||||
|
||||
$affected = $wpdb->query($wpdb->prepare("
|
||||
UPDATE {$wpdb->base_prefix}tm_tasks
|
||||
SET last_locked_at = %d
|
||||
WHERE id = %d
|
||||
AND last_locked_at <= %s
|
||||
", time(), $task_id, $expires_at));
|
||||
|
||||
return $affected ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is called to allow for the task to perform a small chunk of work.
|
||||
* It should be written in a way that anticipates it being killed off at any time.
|
||||
*/
|
||||
abstract public function run();
|
||||
|
||||
/**
|
||||
* Any clean up code goes here.
|
||||
*/
|
||||
public function complete() {
|
||||
|
||||
do_action('ud_task_before_complete', $this);
|
||||
|
||||
$this->set_status('complete');
|
||||
|
||||
do_action('ud_task_completed', $this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fires if the task fails, any clean up code and logging should go here
|
||||
*
|
||||
* @param String $error_code - A code for the failure
|
||||
* @param String $error_message - A description for the failure
|
||||
*/
|
||||
public function fail($error_code = "Unknown", $error_message = "Unknown") {
|
||||
|
||||
do_action('ud_task_before_failed', $this);
|
||||
|
||||
$this->set_status('failed');
|
||||
$this->log(sprintf("Task with ID %d and type (%s) failed with error code %s - %s", $this->id, $this->type, $error_code, $error_message));
|
||||
|
||||
$this->update_option("error_code", $error_code);
|
||||
$this->update_option("error_message", $error_message);
|
||||
|
||||
do_action('ud_task_failed', $this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints any information about the task that the UI can use on the front end for debugging
|
||||
* @param String $title the header to use in the report
|
||||
*
|
||||
* @return String The task report HTML
|
||||
*/
|
||||
public function print_task_report_widget($title = 'Task Summary') {
|
||||
|
||||
$ret = "";
|
||||
|
||||
$status = $this->get_status();
|
||||
$stage = $this->get_option('stage') ? $this->get_option('stage') : 'Unknown';
|
||||
$description = $this->get_status_description($status);
|
||||
|
||||
|
||||
$ret .= "<div class='task task-report task-{$this->type}' id='task-id-{$this->id}'>";
|
||||
$ret .= "<h4>Task Summary</h4>";
|
||||
$ret .= "<ul class='properties-list task-{$this->type}'>";
|
||||
|
||||
foreach ($this as $key => $value) {
|
||||
$ret .= sprintf("<li> %s : %s </li>", $key, $value);
|
||||
}
|
||||
$ret .='</ul>';
|
||||
|
||||
$ret .= "<h4> $title </h4>";
|
||||
$ret .= "<ul class='data-list task-{$this->type}'>";
|
||||
|
||||
foreach ($this->get_all_options() as $key => $value) {
|
||||
if (is_array(maybe_unserialize($value))) {
|
||||
$ret .= sprintf("<li> %s</li>", $key);
|
||||
$ret .= "<ul class='sub-list'>";
|
||||
foreach (maybe_unserialize($value) as $k => $v) {
|
||||
$ret .= sprintf("<li> %s => %s </li>", $k, $v);
|
||||
}
|
||||
$ret .= "</ul>";
|
||||
} else {
|
||||
$ret .= sprintf("<li> %s : %s </li>", $key, $value);
|
||||
}
|
||||
}
|
||||
$ret .='</ul>';
|
||||
$ret .='</div>';
|
||||
|
||||
return apply_filters('ud_print_task_report_widget', $ret, $this);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method gets an option from the task options in the WordPress database if available,
|
||||
* otherwise returns the default for this task type
|
||||
*
|
||||
* @param String $option the name of the option to get
|
||||
* @param Mixed $default a value to return if the option is not currently set
|
||||
*
|
||||
* @return Mixed The option from the database
|
||||
*/
|
||||
public function get_option($option = null, $default = null) {
|
||||
return Updraft_Task_Options::get_task_option($this->id, $option, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is used to add a task option stored in the WordPress database
|
||||
*
|
||||
* @param String $option the name of the option to update
|
||||
* @param Mixed $value the value to save to the option
|
||||
*
|
||||
* @return Mixed the status of the add operation
|
||||
*/
|
||||
public function add_option($option, $value) {
|
||||
return Updraft_Task_Options::update_task_option($this->id, $option, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is used to update a task option stored in the WordPress database
|
||||
*
|
||||
* @param String $option the name of the option to update
|
||||
* @param Mixed $value the value to save to the option
|
||||
*
|
||||
* @return Mixed the status of the update operation
|
||||
*/
|
||||
public function update_option($option, $value) {
|
||||
return Updraft_Task_Options::update_task_option($this->id, $option, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is used to delete a task option stored in the WordPress database
|
||||
*
|
||||
* @param String $option the option to delete
|
||||
*
|
||||
* @return Boolean the result of the delete operation
|
||||
*/
|
||||
public function delete_option($option) {
|
||||
return Updraft_Task_Options::delete_task_option($this->id, $option);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method gets all options assoicated with a task
|
||||
*/
|
||||
public function get_all_options() {
|
||||
return Updraft_Task_Options::get_all_task_options($this->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve default options for this task.
|
||||
* This method should normally be over-ridden by the child.
|
||||
*
|
||||
* @return Array - an array of options
|
||||
*/
|
||||
public function get_default_options() {
|
||||
|
||||
$this->log(sprintf('The get_default_options() method was not over-ridden for the class : %s', $this->get_description()));
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a unique label for this instance that can be used as an identifier
|
||||
*
|
||||
* @return String - a unique label for this instance
|
||||
*/
|
||||
protected function get_unique_label() {
|
||||
return apply_filters('ud_task_unique_label', $this->id."-".$this->type, $this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the status of the given task in the DB
|
||||
*
|
||||
* @param String $id - the id of the task
|
||||
* @param String $status - the status of the task
|
||||
*
|
||||
* @return Boolean - the stauts of the update operation
|
||||
*/
|
||||
public function update_status($id, $status) {
|
||||
|
||||
if (!array_key_exists($status, self::get_allowed_statuses()))
|
||||
return false;
|
||||
|
||||
global $wpdb;
|
||||
$sql = $wpdb->prepare("UPDATE {$wpdb->base_prefix}tm_tasks SET status = %s WHERE id = %d", $status, $id);
|
||||
|
||||
return $wpdb->query($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the number of attempts made for the given task in the DB
|
||||
*
|
||||
* @param String $id - the id of the task
|
||||
* @param int $attempts - the status of the task
|
||||
*
|
||||
* @return Boolean - the stauts of the update operation
|
||||
*/
|
||||
public function update_attempts($id, $attempts) {
|
||||
|
||||
if (!is_numeric($attempts))
|
||||
return false;
|
||||
|
||||
global $wpdb;
|
||||
$sql = $wpdb->prepare("UPDATE {$wpdb->base_prefix}tm_tasks SET attempts = %s WHERE id = %d", $attempts, $id);
|
||||
|
||||
return $wpdb->query($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans out the given task from the DB
|
||||
*
|
||||
* @return Boolean - the status of the delete operation
|
||||
*/
|
||||
public function delete() {
|
||||
global $wpdb;
|
||||
|
||||
$sql = $wpdb->prepare("DELETE FROM {$wpdb->base_prefix}tm_tasks WHERE id = %d", $this->id);
|
||||
return $wpdb->query($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans out the given task meta from the DB
|
||||
*
|
||||
* @return Boolean - the status of the delete operation
|
||||
*/
|
||||
public function delete_meta() {
|
||||
return Updraft_Task_Meta::bulk_delete_task_meta($this->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to convert object to array.
|
||||
*
|
||||
* @return array Object as array.
|
||||
*/
|
||||
public function to_array() {
|
||||
$task = get_object_vars($this);
|
||||
|
||||
foreach (array( 'task_options', 'task_data', 'task_logs', 'task_extras' ) as $key) {
|
||||
if ($this->__isset($key))
|
||||
$task[$key] = $this->__get($key);
|
||||
}
|
||||
|
||||
return $task;
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures and logs any interesting messages
|
||||
*
|
||||
* @param String $message - the error message
|
||||
* @param String $error_type - the error type
|
||||
*/
|
||||
public function log($message, $error_type = 'info') {
|
||||
|
||||
if (isset($this->_loggers)) {
|
||||
foreach ($this->_loggers as $logger) {
|
||||
$logger->log($message, $error_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve all the supported task statuses.
|
||||
*
|
||||
* Tasks should have a limited set of valid status values, this method provides a
|
||||
* list of values and descriptions.
|
||||
*
|
||||
* @return array List of task statuses.
|
||||
*/
|
||||
public static function get_allowed_statuses() {
|
||||
$status = array(
|
||||
'initialised' => __('Initialised'),
|
||||
'active' => __('Active'),
|
||||
'paused' => __('Paused'),
|
||||
'complete' => __('Completed'),
|
||||
'failed' => __('Failed')
|
||||
);
|
||||
|
||||
return apply_filters('ud_allowed_task_statuses', $status);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve the max attempts permitted for task type
|
||||
*
|
||||
* @return int Max attempts permitted for task type
|
||||
*/
|
||||
private function get_max_attempts() {
|
||||
return apply_filters('ud_max_attempts', 5, $this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the text description of the task status.
|
||||
*
|
||||
* @param String $status - The task status
|
||||
*
|
||||
* @return String Description of the task status.
|
||||
*/
|
||||
public static function get_status_description($status) {
|
||||
$list = self::get_allowed_statuses();
|
||||
|
||||
if (!array_key_exists($status, self::get_allowed_statuses()))
|
||||
return __('Unknown');
|
||||
|
||||
return apply_filters("ud_task_status_description_{$status}", $list[$status], $status, $list);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new task instance and returns it
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @global wpdb $wpdb WordPress database abstraction object.
|
||||
*
|
||||
* @param String $type A identifier for the task
|
||||
* @param String $description A description of the task
|
||||
* @param Mixed $options A list of options to initialise the task
|
||||
* @param String $task_class Class name of task; only needed/used on PHP 5.2 (due to lack of late static binding)
|
||||
*
|
||||
* @return Updraft_Task|false Task object, false otherwise.
|
||||
*/
|
||||
public static function create_task($type, $description, $options = array(), $task_class = '') {
|
||||
global $wpdb;
|
||||
|
||||
$user_id = get_current_user_id();
|
||||
$class_identifier = function_exists('get_called_class') ? get_called_class() : $task_class;// phpcs:ignore PHPCompatibility.FunctionUse.NewFunctions.get_called_classFound
|
||||
|
||||
$is_anonymous_user_allowed = isset($options['anonymous_user_allowed']) && $options['anonymous_user_allowed'];
|
||||
if (!$user_id && !$is_anonymous_user_allowed) return false;
|
||||
|
||||
$sql = $wpdb->prepare("INSERT INTO {$wpdb->base_prefix}tm_tasks (type, user_id, description, class_identifier, status) VALUES (%s, %d, %s, %s, %s)", $type, $user_id, $description, $class_identifier, 'active');
|
||||
|
||||
$wpdb->query($sql);
|
||||
|
||||
$task_id = $wpdb->insert_id;
|
||||
|
||||
if (!$task_id) return false;
|
||||
|
||||
$_task = $wpdb->get_row("SELECT * FROM {$wpdb->base_prefix}tm_tasks WHERE id = {$task_id} LIMIT 1");
|
||||
|
||||
$task = new $class_identifier($_task);
|
||||
|
||||
if (!$task) return false;
|
||||
|
||||
$task->initialise($options);
|
||||
|
||||
return $task;
|
||||
}
|
||||
|
||||
/**
|
||||
* Select the current task from the database
|
||||
*
|
||||
* @param int $task_id - The task ID
|
||||
* @return object|false
|
||||
*/
|
||||
private function get_task_from_db($task_id) {
|
||||
global $wpdb;
|
||||
return $wpdb->get_row("SELECT * FROM {$wpdb->base_prefix}tm_tasks WHERE id = {$task_id} LIMIT 1");
|
||||
}
|
||||
}
|
||||
endif;
|
||||
@@ -0,0 +1,207 @@
|
||||
<?php
|
||||
/**
|
||||
* Initialise the tasks module and create the needed DB tables
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) die('Access denied.');
|
||||
|
||||
if (!class_exists('Updraft_Tasks_Activation')) :
|
||||
|
||||
class Updraft_Tasks_Activation {
|
||||
|
||||
private static $table_prefix;
|
||||
|
||||
/**
|
||||
* Format: key=<version>, value=array of method names to call
|
||||
* Example Usage:
|
||||
* private static $db_updates = array(
|
||||
* '1.0.1' => array(
|
||||
* 'update_101_add_new_column',
|
||||
* ),
|
||||
* );
|
||||
*
|
||||
* @var Mixed
|
||||
*/
|
||||
private static $db_updates = array(
|
||||
'0.0.1' => array('create_tables'),
|
||||
'1.0.1' => array('add_attempts_and_class_identifier'),
|
||||
'1.1' => array('add_lock_column'),
|
||||
);
|
||||
|
||||
|
||||
const UPDRAFT_TASKS_DB_VERSION = '1.1';
|
||||
|
||||
/**
|
||||
* Initialise this class
|
||||
*/
|
||||
public static function init_db() {
|
||||
self::$table_prefix = defined('UPDRAFT_TASKS_TABLE_PREFIX') ? UPDRAFT_TASKS_TABLE_PREFIX : 'tm_';
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the class entry point
|
||||
*/
|
||||
public static function install() {
|
||||
self::init_db();
|
||||
self::create_tables();
|
||||
// we need walk through all updates when install at first.
|
||||
self::check_updates();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check needed tables in data base and if one of them doesn't exist force reinstall.
|
||||
*/
|
||||
public static function reinstall_if_needed() {
|
||||
static $done = false;
|
||||
|
||||
if ($done) return;
|
||||
|
||||
if (!self::check_if_tables_exist()) self::reinstall();
|
||||
|
||||
$done = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop database version variable from option from database and run install again.
|
||||
*/
|
||||
public static function reinstall() {
|
||||
if (is_multisite()) {
|
||||
delete_site_option('updraft_task_manager_dbversion');
|
||||
} else {
|
||||
delete_option('updraft_task_manager_dbversion');
|
||||
}
|
||||
self::install();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if needed task manager tables exist.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function check_if_tables_exist() {
|
||||
global $wpdb;
|
||||
self::init_db();
|
||||
$our_prefix = $wpdb->base_prefix.self::$table_prefix;
|
||||
$tables = array($our_prefix.'tasks', $our_prefix.'taskmeta');
|
||||
|
||||
foreach ($tables as $table) {
|
||||
$query = "SHOW TABLES LIKE '{$table}'";
|
||||
$tables = $wpdb->get_results($query, ARRAY_A);
|
||||
if (!is_array($tables) || 0 == count($tables)) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* See if any database schema updates are needed, and perform them if so.
|
||||
* Example Usage:
|
||||
* public static function update_101_add_new_column() {
|
||||
* $wpdb = $GLOBALS['wpdb'];
|
||||
* $wpdb->query('ALTER TABLE tm_tasks ADD task_expiry varchar(300) AFTER id');
|
||||
* }
|
||||
*/
|
||||
public static function check_updates() {
|
||||
self::init_db();
|
||||
$our_version = self::get_version();
|
||||
if (is_multisite()) {
|
||||
$db_version = get_site_option('updraft_task_manager_dbversion');
|
||||
} else {
|
||||
$db_version = get_option('updraft_task_manager_dbversion');
|
||||
}
|
||||
if (!$db_version || version_compare($our_version, $db_version, '>')) {
|
||||
foreach (self::$db_updates as $version => $updates) {
|
||||
if (version_compare($version, $db_version, '>')) {
|
||||
foreach ($updates as $update) {
|
||||
call_user_func(array(__CLASS__, $update));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (is_multisite()) {
|
||||
update_site_option('updraft_task_manager_dbversion', self::get_version());
|
||||
} else {
|
||||
update_option('updraft_task_manager_dbversion', self::get_version());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current version of the plugin
|
||||
*/
|
||||
public static function get_version() {
|
||||
return self::UPDRAFT_TASKS_DB_VERSION;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the database tables
|
||||
*/
|
||||
public static function create_tables() {
|
||||
|
||||
$wpdb = $GLOBALS['wpdb'];
|
||||
|
||||
$our_prefix = $wpdb->base_prefix.self::$table_prefix;
|
||||
$collate = '';
|
||||
|
||||
if ($wpdb->has_cap('collation')) {
|
||||
if (!empty($wpdb->charset)) {
|
||||
$collate .= "DEFAULT CHARACTER SET $wpdb->charset";
|
||||
}
|
||||
if (!empty($wpdb->collate)) {
|
||||
$collate .= " COLLATE $wpdb->collate";
|
||||
}
|
||||
}
|
||||
|
||||
include_once ABSPATH.'wp-admin/includes/upgrade.php';
|
||||
|
||||
// Important: obey the magical/arbitrary rules for formatting this stuff: https://codex.wordpress.org/Creating_Tables_with_Plugins
|
||||
// Otherwise, you get SQL errors and unwanted header output warnings when activating
|
||||
|
||||
$create_tables = 'CREATE TABLE '.$our_prefix."tasks (
|
||||
task_id bigint(20) NOT NULL auto_increment,
|
||||
user_id bigint(20) NOT NULL,
|
||||
type varchar(300) NOT NULL,
|
||||
description varchar(300),
|
||||
PRIMARY KEY (task_id),
|
||||
KEY user_id (user_id),
|
||||
time_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||
status varchar(300)
|
||||
) $collate;
|
||||
";
|
||||
// KEY attribute_name (attribute_name)
|
||||
dbDelta($create_tables);
|
||||
|
||||
$max_index_length = 191;
|
||||
|
||||
$create_tables = 'CREATE TABLE '.$our_prefix."taskmeta (
|
||||
meta_id bigint(20) NOT NULL auto_increment,
|
||||
task_id bigint(20) NOT NULL default '0',
|
||||
meta_key varchar(255) DEFAULT NULL,
|
||||
meta_value longtext,
|
||||
PRIMARY KEY (meta_id),
|
||||
KEY meta_key (meta_key($max_index_length)),
|
||||
KEY task_id (task_id)
|
||||
) $collate;
|
||||
";
|
||||
|
||||
dbDelta($create_tables);
|
||||
}
|
||||
|
||||
public static function add_attempts_and_class_identifier() {
|
||||
$wpdb = $GLOBALS['wpdb'];
|
||||
$our_prefix = $wpdb->base_prefix.self::$table_prefix;
|
||||
|
||||
$wpdb->query("ALTER TABLE ".$our_prefix."tasks CHANGE COLUMN `task_id` `id` INT NOT NULL");
|
||||
$wpdb->query("ALTER TABLE ".$our_prefix."tasks MODIFY COLUMN `id` INT auto_increment");
|
||||
$wpdb->query("ALTER TABLE ".$our_prefix."tasks ADD attempts INT DEFAULT 0 AFTER type");
|
||||
$wpdb->query("ALTER TABLE ".$our_prefix."tasks ADD class_identifier varchar(300) DEFAULT 0 AFTER type");
|
||||
}
|
||||
|
||||
public static function add_lock_column() {
|
||||
$wpdb = $GLOBALS['wpdb'];
|
||||
$our_prefix = $wpdb->base_prefix.self::$table_prefix;
|
||||
$wpdb->query('ALTER TABLE '.$our_prefix.'tasks ADD last_locked_at BIGINT DEFAULT 0 AFTER time_created');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
endif;
|
||||
Reference in New Issue
Block a user