- Refactored fallback submission logic in `class-event-handler.php` to remove `wp_die`/`exit` calls and use redirects for error handling, enabling proper unit testing. - Implemented meta-data saving (dates, venue, organizer) in the fallback logic using `update_post_meta`. - Updated unit tests (`test-event-management.php`) to remove `markTestIncomplete` calls related to handler errors and uncommented meta assertions. Unit tests for fallback logic now pass. - Added Instructions section and Return to Dashboard button to the event form shortcode (`display_event_form_shortcode`). - Applied basic theme styling classes (`ast-container`, `notice`, `ast-button`) to the event form. - Updated `docs/implementation_plan.md` to reflect completion of tasks 4.1-4.5 and set focus to Task 5. Refs: Task 4.1, 4.2, 4.3, 4.4, 4.5
388 lines
9.3 KiB
PHP
388 lines
9.3 KiB
PHP
<?php
|
|
|
|
/**
|
|
* @link http://patchwork2.org/
|
|
* @author Ignas Rudaitis <ignas.rudaitis@gmail.com>
|
|
* @copyright 2010-2018 Ignas Rudaitis
|
|
* @license http://www.opensource.org/licenses/mit-license.html
|
|
*/
|
|
namespace Patchwork\Utils;
|
|
|
|
use Patchwork\Config;
|
|
use Patchwork\CallRerouting;
|
|
use Patchwork\CodeManipulation;
|
|
|
|
const ALIASING_CODE = '
|
|
namespace %s;
|
|
function %s() {
|
|
return call_user_func_array("%s", func_get_args());
|
|
}
|
|
';
|
|
|
|
function clearOpcodeCaches()
|
|
{
|
|
if (function_exists('opcache_reset')) {
|
|
opcache_reset();
|
|
}
|
|
if (ini_get('wincache.ocenabled')) {
|
|
wincache_refresh_if_changed();
|
|
}
|
|
if (ini_get('apc.enabled') && function_exists('apc_clear_cache')) {
|
|
apc_clear_cache();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @deprecated 2.2.0
|
|
*/
|
|
function generatorsSupported()
|
|
{
|
|
return version_compare(PHP_VERSION, "5.5", ">=");
|
|
}
|
|
|
|
/**
|
|
* @deprecated 2.2.0
|
|
*/
|
|
function runningOnHHVM()
|
|
{
|
|
return defined("HHVM_VERSION");
|
|
}
|
|
|
|
function condense($string)
|
|
{
|
|
return preg_replace('/\s+/', ' ', $string);
|
|
}
|
|
|
|
function indexOfFirstGreaterThan(array $array, $value)
|
|
{
|
|
$low = 0;
|
|
$high = count($array) - 1;
|
|
if (empty($array) || $array[$high] <= $value) {
|
|
return -1;
|
|
}
|
|
while ($low < $high) {
|
|
$mid = (int)(($low + $high) / 2);
|
|
if ($array[$mid] <= $value) {
|
|
$low = $mid + 1;
|
|
} else {
|
|
$high = $mid;
|
|
}
|
|
}
|
|
return $low;
|
|
}
|
|
|
|
function indexOfLastNotGreaterThan(array $array, $value)
|
|
{
|
|
if (empty($array)) {
|
|
return -1;
|
|
}
|
|
$result = indexOfFirstGreaterThan($array, $value);
|
|
if ($result === -1) {
|
|
$result = count($array) - 1;
|
|
}
|
|
while ($array[$result] > $value) {
|
|
$result--;
|
|
}
|
|
return $result;
|
|
}
|
|
|
|
function firstGreaterThan(array $array, $value, $default = INF)
|
|
{
|
|
$index = indexOfFirstGreaterThan($array, $value);
|
|
return ($index !== -1) ? $array[$index] : $default;
|
|
}
|
|
|
|
function lastNotGreaterThan(array $array, $value, $default = INF)
|
|
{
|
|
$index = indexOfLastNotGreaterThan($array, $value);
|
|
return ($index !== -1) ? $array[$index] : $default;
|
|
}
|
|
|
|
function allWithinRange(array $array, $low, $high)
|
|
{
|
|
$low--;
|
|
$high++;
|
|
$index = indexOfFirstGreaterThan($array, $low);
|
|
if ($index === -1) {
|
|
return [];
|
|
}
|
|
$result = [];
|
|
while ($index < count($array) && $array[$index] < $high) {
|
|
$result[] = $array[$index];
|
|
$index++;
|
|
}
|
|
return $result;
|
|
}
|
|
|
|
function interpretCallable($callback)
|
|
{
|
|
if (is_object($callback)) {
|
|
return interpretCallable([$callback, "__invoke"]);
|
|
}
|
|
if (is_array($callback)) {
|
|
list($class, $method) = $callback;
|
|
$instance = null;
|
|
if (is_object($class)) {
|
|
$instance = $class;
|
|
$class = get_class($class);
|
|
}
|
|
$class = isset($class) ? ltrim($class, "\\") : '';
|
|
return [$class, $method, $instance];
|
|
}
|
|
if (substr($callback, 0, 4) === 'new ') {
|
|
return [ltrim(substr($callback, 4)), 'new', null];
|
|
}
|
|
$callback = ltrim($callback, "\\");
|
|
if (strpos($callback, "::")) {
|
|
list($class, $method) = explode("::", $callback);
|
|
return [$class, $method, null];
|
|
}
|
|
return [null, $callback, null];
|
|
}
|
|
|
|
function callableDefined($callable, $shouldAutoload = false)
|
|
{
|
|
list($class, $method, $instance) = interpretCallable($callable);
|
|
if ($instance !== null) {
|
|
return true;
|
|
}
|
|
if (isset($class)) {
|
|
return classOrTraitExists($class, $shouldAutoload) &&
|
|
(method_exists($class, $method) || $method === 'new');
|
|
}
|
|
return function_exists($method);
|
|
}
|
|
|
|
function classOrTraitExists($classOrTrait, $shouldAutoload = true)
|
|
{
|
|
return class_exists($classOrTrait, $shouldAutoload)
|
|
|| trait_exists($classOrTrait, $shouldAutoload);
|
|
}
|
|
|
|
function append(&$array, $value)
|
|
{
|
|
$array[] = $value;
|
|
end($array);
|
|
return key($array);
|
|
}
|
|
|
|
function appendUnder(&$array, $path, $value)
|
|
{
|
|
foreach ((array) $path as $key) {
|
|
if (!isset($array[$key])) {
|
|
$array[$key] = [];
|
|
}
|
|
$array = &$array[$key];
|
|
}
|
|
return append($array, $value);
|
|
}
|
|
|
|
function access($array, $path, $default = null)
|
|
{
|
|
foreach ((array) $path as $key) {
|
|
if (!isset($array[$key])) {
|
|
return $default;
|
|
}
|
|
$array = $array[$key];
|
|
}
|
|
return $array;
|
|
}
|
|
|
|
function normalizePath($path)
|
|
{
|
|
return rtrim(strtr($path, "\\", "/"), "/");
|
|
}
|
|
|
|
function reflectCallable($callback)
|
|
{
|
|
if ($callback instanceof \Closure) {
|
|
return new \ReflectionFunction($callback);
|
|
}
|
|
list($class, $method) = interpretCallable($callback);
|
|
if (isset($class)) {
|
|
return new \ReflectionMethod($class, $method);
|
|
}
|
|
return new \ReflectionFunction($method);
|
|
}
|
|
|
|
function callableToString($callback)
|
|
{
|
|
list($class, $method) = interpretCallable($callback);
|
|
if (isset($class)) {
|
|
return $class . "::" . $method;
|
|
}
|
|
return $method;
|
|
}
|
|
|
|
function alias($namespace, array $mapping)
|
|
{
|
|
foreach ($mapping as $original => $aliases) {
|
|
$original = ltrim(str_replace('\\', '\\\\', $namespace) . '\\\\' . $original, '\\');
|
|
foreach ((array) $aliases as $alias) {
|
|
eval(sprintf(ALIASING_CODE, $namespace, $alias, $original));
|
|
}
|
|
}
|
|
}
|
|
|
|
function getUserDefinedCallables()
|
|
{
|
|
return array_merge(get_defined_functions()['user'], getUserDefinedMethods());
|
|
}
|
|
|
|
function getRedefinableCallables()
|
|
{
|
|
return array_merge(getUserDefinedCallables(), Config\getRedefinableInternals());
|
|
}
|
|
|
|
function getUserDefinedMethods()
|
|
{
|
|
static $result = [];
|
|
static $classCount = 0;
|
|
static $traitCount = 0;
|
|
$classes = getUserDefinedClasses();
|
|
$traits = getUserDefinedTraits();
|
|
$newClasses = array_slice($classes, $classCount);
|
|
$newTraits = array_slice($traits, $traitCount);
|
|
foreach (array_merge($newClasses, $newTraits) as $newClass) {
|
|
foreach (get_class_methods($newClass) as $method) {
|
|
$result[] = $newClass . '::' . $method;
|
|
}
|
|
}
|
|
$classCount = count($classes);
|
|
$traitCount = count($traits);
|
|
return $result;
|
|
}
|
|
|
|
function getUserDefinedClasses()
|
|
{
|
|
static $classCutoff;
|
|
$classes = get_declared_classes();
|
|
if (!isset($classCutoff)) {
|
|
$classCutoff = count($classes);
|
|
for ($i = 0; $i < count($classes); $i++) {
|
|
if ((new \ReflectionClass($classes[$i]))->isUserDefined()) {
|
|
$classCutoff = $i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return array_slice($classes, $classCutoff);
|
|
}
|
|
|
|
function getUserDefinedTraits()
|
|
{
|
|
static $traitCutoff;
|
|
$traits = get_declared_traits();
|
|
if (!isset($traitCutoff)) {
|
|
$traitCutoff = count($traits);
|
|
for ($i = 0; $i < count($traits); $i++) {
|
|
$methods = get_class_methods($traits[$i]);
|
|
if (empty($methods)) {
|
|
continue;
|
|
}
|
|
list($first) = $methods;
|
|
if ((new \ReflectionMethod($traits[$i], $first))->isUserDefined()) {
|
|
$traitCutoff = $i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return array_slice($traits, $traitCutoff);
|
|
}
|
|
|
|
function matchWildcard($wildcard, array $subjects)
|
|
{
|
|
$table = ['*' => '.*', '{' => '(', '}' => ')', ' ' => '', '\\' => '\\\\'];
|
|
$pattern = '/' . strtr($wildcard, $table) . '/i';
|
|
return preg_grep($pattern, $subjects);
|
|
}
|
|
|
|
function wildcardMatches($wildcard, $subject)
|
|
{
|
|
return matchWildcard($wildcard, [$subject]) == [$subject];
|
|
}
|
|
|
|
function isOwnName($name)
|
|
{
|
|
return stripos((string) $name, 'Patchwork\\') === 0
|
|
&& stripos((string) $name, CallRerouting\INTERNAL_REDEFINITION_NAMESPACE . '\\') !== 0;
|
|
}
|
|
|
|
function isForeignName($name)
|
|
{
|
|
return !isOwnName($name);
|
|
}
|
|
|
|
function markMissedCallables()
|
|
{
|
|
State::$missedCallables = array_map('strtolower', getUserDefinedCallables());
|
|
}
|
|
|
|
function getMissedCallables()
|
|
{
|
|
return State::$missedCallables;
|
|
}
|
|
|
|
function callableWasMissed($name)
|
|
{
|
|
return in_array(strtolower($name), getMissedCallables());
|
|
}
|
|
|
|
function endsWith($haystack, $needle)
|
|
{
|
|
if (strlen($haystack) === strlen($needle)) {
|
|
return $haystack === $needle;
|
|
}
|
|
if (strlen($haystack) < strlen($needle)) {
|
|
return false;
|
|
}
|
|
return substr($haystack, -strlen($needle)) === $needle;
|
|
}
|
|
|
|
function wasRunAsConsoleApp()
|
|
{
|
|
global $argv;
|
|
return isset($argv) && (
|
|
endsWith($argv[0], 'patchwork.phar') || endsWith($argv[0], 'Patchwork.php')
|
|
);
|
|
}
|
|
|
|
function getParameterAndArgumentLists(?\ReflectionMethod $reflection = null)
|
|
{
|
|
$parameters = [];
|
|
$arguments = [];
|
|
if ($reflection) {
|
|
foreach ($reflection->getParameters() as $p) {
|
|
$parameter = '$' . $p->name;
|
|
if ($p->isOptional()) {
|
|
try {
|
|
$value = var_export($p->getDefaultValue(), true);
|
|
} catch (\ReflectionException $e) {
|
|
$value = var_export(CallRerouting\INSTANTIATOR_DEFAULT_ARGUMENT, true);
|
|
}
|
|
$parameter .= ' = ' . $value;
|
|
}
|
|
$parameters[] = $parameter;
|
|
$arguments[] = '$' . $p->name;
|
|
}
|
|
}
|
|
return [join(', ' , $parameters), join(', ', $arguments)];
|
|
}
|
|
|
|
function args()
|
|
{
|
|
return func_get_args();
|
|
}
|
|
|
|
function tokenize($string)
|
|
{
|
|
if (defined('TOKEN_PARSE')) {
|
|
return token_get_all($string, TOKEN_PARSE);
|
|
}
|
|
return token_get_all($string);
|
|
}
|
|
|
|
class State
|
|
{
|
|
static $missedCallables = [];
|
|
}
|