diff --git a/common/libs/floating-scroll/css/jquery.floatingscroll.css b/common/libs/floating-scroll/css/jquery.floatingscroll.css new file mode 100644 index 000000000..47cddfef8 --- /dev/null +++ b/common/libs/floating-scroll/css/jquery.floatingscroll.css @@ -0,0 +1 @@ +.fl-scrolls{overflow:auto;position:fixed}.fl-scrolls div{overflow:hidden;pointer-events:none}.fl-scrolls div::before{content:"\A0"}.fl-scrolls,.fl-scrolls div{font-size:1px;line-height:0;margin:0;padding:0}.fl-scrolls-hidden div::before{content:"\A0\A0"}.fl-scrolls-viewport{position:relative}.fl-scrolls-body{overflow:auto}.fl-scrolls-viewport .fl-scrolls{position:absolute}.fl-scrolls-hoverable .fl-scrolls{opacity:0;transition:opacity .5s .3s}.fl-scrolls-hoverable:hover .fl-scrolls{opacity:1}.fl-scrolls:not([data-orientation]),.fl-scrolls[data-orientation=horizontal]{bottom:0;min-height:17px}.fl-scrolls:not([data-orientation]) div,.fl-scrolls[data-orientation=horizontal] div{height:1px}.fl-scrolls-hidden.fl-scrolls:not([data-orientation]),.fl-scrolls-hidden.fl-scrolls[data-orientation=horizontal]{bottom:9999px}.fl-scrolls-viewport .fl-scrolls:not([data-orientation]),.fl-scrolls-viewport .fl-scrolls[data-orientation=horizontal]{left:0}.fl-scrolls[data-orientation=vertical]{right:0;min-width:17px}.fl-scrolls[data-orientation=vertical] div{width:1px}.fl-scrolls-hidden.fl-scrolls[data-orientation=vertical]{right:9999px}.fl-scrolls-viewport .fl-scrolls[data-orientation=vertical]{top:0} \ No newline at end of file diff --git a/common/libs/floating-scroll/js/jquery.floatingscroll.min.js b/common/libs/floating-scroll/js/jquery.floatingscroll.min.js new file mode 100644 index 000000000..ccfef61a5 --- /dev/null +++ b/common/libs/floating-scroll/js/jquery.floatingscroll.min.js @@ -0,0 +1,6 @@ +/*! +floating-scroll v3.2.0 +https://amphiluke.github.io/floating-scroll/ +(c) 2024 Amphiluke +*/ +!function(t,n){"object"==typeof exports&&"undefined"!=typeof module?n(require("jquery")):"function"==typeof define&&define.amd?define(["jquery"],n):n((t="undefined"!=typeof globalThis?globalThis:t||self).jQuery)}(this,(function(t){"use strict";var n="horizontal",i="vertical",e={init:function(t,i){var e=this;e.orientationProps=function(t){var i=t===n;return{ORIENTATION:t,SIZE:i?"width":"height",X_SIZE:i?"height":"width",OFFSET_SIZE:i?"offsetWidth":"offsetHeight",OFFSET_X_SIZE:i?"offsetHeight":"offsetWidth",CLIENT_SIZE:i?"clientWidth":"clientHeight",CLIENT_X_SIZE:i?"clientHeight":"clientWidth",INNER_X_SIZE:i?"innerHeight":"innerWidth",SCROLL_SIZE:i?"scrollWidth":"scrollHeight",SCROLL_POS:i?"scrollLeft":"scrollTop",START:i?"left":"top",X_START:i?"top":"left",X_END:i?"bottom":"right"}}(i);var o=t.closest(".fl-scrolls-body");o.length&&(e.scrollBody=o),e.container=t[0],e.visible=!0,e.initWidget(),e.updateAPI(),e.addEventHandlers(),e.skipSyncContainer=e.skipSyncWidget=!1},initWidget:function(){var n=this,i=n.orientationProps,e=i.ORIENTATION,o=i.SIZE,r=i.SCROLL_SIZE,c=n.widget=t('
');t("
").appendTo(c)[o](n.container[r]),c.appendTo(n.container)},addEventHandlers:function(){var n=this;(n.eventHandlers=[{$el:t(window),handlers:{"destroyDetached.fscroll":function(t){"fscroll"===t.namespace&&n.destroyDetachedAPI()}}},{$el:n.scrollBody||t(window),handlers:{scroll:function(){n.updateAPI()},resize:function(){n.updateAPI()}}},{$el:n.widget,handlers:{scroll:function(){n.visible&&!n.skipSyncContainer&&n.syncContainer(),n.skipSyncContainer=!1}}},{$el:t(n.container),handlers:{scroll:function(){n.skipSyncWidget||n.syncWidget(),n.skipSyncWidget=!1},focusin:function(){setTimeout((function(){n.widget&&n.syncWidget()}),0)},"update.fscroll":function(t){"fscroll"===t.namespace&&n.updateAPI()},"destroy.fscroll":function(t){"fscroll"===t.namespace&&n.destroyAPI()}}}]).forEach((function(t){var n=t.$el,i=t.handlers;return n.bind(i)}))},checkVisibility:function(){var t=this,n=t.widget,i=t.container,e=t.scrollBody,o=t.orientationProps,r=o.SCROLL_SIZE,c=o.OFFSET_SIZE,s=o.X_START,l=o.X_END,d=o.INNER_X_SIZE,a=o.CLIENT_X_SIZE,f=n[0][r]<=n[0][c];if(!f){var u=i.getBoundingClientRect(),h=e?e[0].getBoundingClientRect()[l]:window[d]||document.documentElement[a];f=u[l]<=h||u[s]>h}t.visible===f&&(t.visible=!f,n.toggleClass("fl-scrolls-hidden"))},syncContainer:function(){var t=this,n=t.orientationProps.SCROLL_POS,i=t.widget[0][n];t.container[n]!==i&&(t.skipSyncWidget=!0,t.container[n]=i)},syncWidget:function(){var t=this,n=t.orientationProps.SCROLL_POS,i=t.container[n];t.widget[0][n]!==i&&(t.skipSyncContainer=!0,t.widget[0][n]=i)},updateAPI:function(){var n=this,i=n.orientationProps,e=i.SIZE,o=i.X_SIZE,r=i.OFFSET_X_SIZE,c=i.CLIENT_SIZE,s=i.CLIENT_X_SIZE,l=i.SCROLL_SIZE,d=i.START,a=n.widget,f=n.container,u=n.scrollBody,h=f[c],S=f[l];a[e](h),u||a.css(d,f.getBoundingClientRect()[d]+"px"),t("div",a)[e](S),S>h&&a[o](a[0][r]-a[0][s]+1),n.syncWidget(),n.checkVisibility()},destroyAPI:function(){var t=this;t.eventHandlers.forEach((function(t){var n=t.$el,i=t.handlers;return n.unbind(i)})),t.widget.remove(),t.eventHandlers=t.widget=t.container=t.scrollBody=null},destroyDetachedAPI:function(){t.contains(document.body,this.container)||this.destroyAPI()}};t.fn.floatingScroll=function(o,r){if(void 0===o&&(o="init"),void 0===r&&(r={}),"init"===o){var c=r.orientation,s=void 0===c?n:c;if(s!==n&&s!==i)throw new Error("Scrollbar orientation should be either “"+n+"” or “"+i+"”");this.each((function(n,i){return Object.create(e).init(t(i),s)}))}else Object.prototype.hasOwnProperty.call(e,o+"API")&&this.trigger(o+".fscroll");return this},t((function(){t("body [data-fl-scrolls]").each((function(n,i){var e=t(i);e.floatingScroll("init",e.data("flScrolls")||{})}))}))})); diff --git a/common/php/class-module.php b/common/php/class-module.php index 76e1147b5..d853d4783 100644 --- a/common/php/class-module.php +++ b/common/php/class-module.php @@ -803,5 +803,45 @@ public static function isPublishPressModuleEnabled($module_slug) return isset($publishpress->{$module_slug}) && $publishpress->{$module_slug}->module->options->enabled === 'on'; } + + public function getUserAuthorizedPostStatusOptions($postType) + { + $postStatuses = $this->getPostStatusOptions(); + + foreach ($postStatuses as $index => $status) { + // Filter publishing posts if the post type is set + if (in_array($status['value'], ['publish', 'future', 'private'])) { + $postTypeObj = get_post_type_object($postType); + if (! current_user_can($postTypeObj->cap->publish_posts)) { + unset($postStatuses[$index]); + } + } + } + + return $postStatuses; + } + + public function getPostStatusOptions() + { + $postStatuses = []; + $post_statuses_terms = get_terms('post_status', ['hide_empty' => false]); + $post_statuses_terms_slugs = (!is_wp_error($post_statuses_terms)) ? array_column($post_statuses_terms, 'slug') : []; + foreach ($this->get_post_statuses() as $status) { + //add support for capabilities custom statuses + if (defined('PUBLISHPRESS_CAPS_PRO_VERSION') + && !empty(get_option('cme_custom_status_control')) + && in_array($status->slug, $post_statuses_terms_slugs) + && !current_user_can('status_change_' . $status->slug) + ) { + continue; + } + $postStatuses[] = [ + 'value' => esc_attr($status->slug), + 'text' => esc_html($status->label), + ]; + } + + return $postStatuses; + } } } diff --git a/common/php/util.php b/common/php/util.php index 2eda1e7fe..909382fe3 100644 --- a/common/php/util.php +++ b/common/php/util.php @@ -119,3 +119,41 @@ function pp_get_users_with_author_permissions() return apply_filters('pp_get_users_eligible_to_be_authors', $authors); } } + +if (!function_exists('pp_planner_admin_notice')) { + /** + * Show admin notices function for use with admin_notices hook. + * + * Constructs admin notice HTML. + * + * @param string $message Message to use in admin notice. Optional. Default empty string. + * @param bool $success Whether or not a success. Optional. Default true. + * @return mixed + */ + function pp_planner_admin_notice($message = '', $success = true) + { + + $class = []; + $class[] = $success ? 'updated' : 'error'; + $class[] = 'notice is-dismissible'; + + $messagewrapstart = '

'; + + $messagewrapend = '

'; + + $action = ''; + + /** + * Filters the custom admin notice for ppma. + * + * + * @param string $value Complete HTML output for notice. + * @param string $action Action whose message is being generated. + * @param string $message The message to be displayed. + * @param string $messagewrapstart Beginning wrap HTML. + * @param string $messagewrapend Ending wrap HTML. + */ + return apply_filters('ppch_admin_notice', $messagewrapstart . $message . $messagewrapend, $action, $message, + $messagewrapstart, $messagewrapend); + } +} diff --git a/composer.json b/composer.json index 10e897d37..216a0efc0 100644 --- a/composer.json +++ b/composer.json @@ -13,14 +13,6 @@ "minimum-stability": "dev", "prefer-stable": true, "repositories": [ - { - "type": "git", - "url": "https://github.com/publishpress/wp-browser" - }, - { - "type": "vcs", - "url": "https://github.com/publishpress/publishpress-phpcs-standards" - } ], "require": { "php": ">=7.2.5" @@ -29,7 +21,6 @@ "bartlett/php-compatinfo": "^5.2", "overtrue/phplint": "^2.1", "automattic/vipwpcs": "^2.2", - "publishpress/wp-browser": "2.6.5.2", "codeception/module-phpbrowser": "^1.0.0", "codeception/module-asserts": "^1.0.0", "codeception/module-webdriver": "^1.0", @@ -40,7 +31,6 @@ "mustache/mustache": "2.14.1", "squizlabs/php_codesniffer": "3.*", "dealerdirect/phpcodesniffer-composer-installer": "^0.7.2", - "publishpress/publishpress-phpcs-standards": "dev-main", "phpcompatibility/php-compatibility": "*" }, "config": { diff --git a/includes.php b/includes.php index c76a1a9b5..20c9966bd 100644 --- a/includes.php +++ b/includes.php @@ -34,7 +34,7 @@ if (! defined('PP_LOADED')) { if (! defined('PUBLISHPRESS_VERSION')) { // Define constants - define('PUBLISHPRESS_VERSION', '4.0.3'); + define('PUBLISHPRESS_VERSION', '4.0.4-beta.2'); define('PUBLISHPRESS_BASE_PATH', __DIR__); define('PUBLISHPRESS_VIEWS_PATH', __DIR__ . '/views'); define('PUBLISHPRESS_FILE_PATH', PUBLISHPRESS_BASE_PATH . '/publishpress.php'); diff --git a/lib/composer.lock b/lib/composer.lock index 98a46e545..e40733dad 100644 --- a/lib/composer.lock +++ b/lib/composer.lock @@ -457,5 +457,5 @@ "php": ">=7.2.5" }, "platform-dev": [], - "plugin-api-version": "2.2.0" + "plugin-api-version": "2.3.0" } diff --git a/lib/vendor/autoload.php b/lib/vendor/autoload.php index 5c19b399f..eee0ef9e8 100644 --- a/lib/vendor/autoload.php +++ b/lib/vendor/autoload.php @@ -2,6 +2,24 @@ // 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 ComposerAutoloaderInitPublishPressPlanner::getLoader(); diff --git a/lib/vendor/composer/ClassLoader.php b/lib/vendor/composer/ClassLoader.php index afef3fa2a..7824d8f7e 100644 --- a/lib/vendor/composer/ClassLoader.php +++ b/lib/vendor/composer/ClassLoader.php @@ -42,35 +42,37 @@ */ class ClassLoader { - /** @var ?string */ + /** @var \Closure(string):void */ + private static $includeFile; + + /** @var string|null */ private $vendorDir; // PSR-4 /** - * @var array[] - * @psalm-var array> + * @var array> */ private $prefixLengthsPsr4 = array(); /** - * @var array[] - * @psalm-var array> + * @var array> */ private $prefixDirsPsr4 = array(); /** - * @var array[] - * @psalm-var array + * @var list */ private $fallbackDirsPsr4 = array(); // PSR-0 /** - * @var array[] - * @psalm-var array> + * List of PSR-0 prefixes + * + * Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2'))) + * + * @var array>> */ private $prefixesPsr0 = array(); /** - * @var array[] - * @psalm-var array + * @var list */ private $fallbackDirsPsr0 = array(); @@ -78,8 +80,7 @@ class ClassLoader private $useIncludePath = false; /** - * @var string[] - * @psalm-var array + * @var array */ private $classMap = array(); @@ -87,29 +88,29 @@ class ClassLoader private $classMapAuthoritative = false; /** - * @var bool[] - * @psalm-var array + * @var array */ private $missingClasses = array(); - /** @var ?string */ + /** @var string|null */ private $apcuPrefix; /** - * @var self[] + * @var array */ private static $registeredLoaders = array(); /** - * @param ?string $vendorDir + * @param string|null $vendorDir */ public function __construct($vendorDir = null) { $this->vendorDir = $vendorDir; + self::initializeIncludeClosure(); } /** - * @return string[] + * @return array> */ public function getPrefixes() { @@ -121,8 +122,7 @@ public function getPrefixes() } /** - * @return array[] - * @psalm-return array> + * @return array> */ public function getPrefixesPsr4() { @@ -130,8 +130,7 @@ public function getPrefixesPsr4() } /** - * @return array[] - * @psalm-return array + * @return list */ public function getFallbackDirs() { @@ -139,8 +138,7 @@ public function getFallbackDirs() } /** - * @return array[] - * @psalm-return array + * @return list */ public function getFallbackDirsPsr4() { @@ -148,8 +146,7 @@ public function getFallbackDirsPsr4() } /** - * @return string[] Array of classname => path - * @psalm-return array + * @return array Array of classname => path */ public function getClassMap() { @@ -157,8 +154,7 @@ public function getClassMap() } /** - * @param string[] $classMap Class to filename map - * @psalm-param array $classMap + * @param array $classMap Class to filename map * * @return void */ @@ -175,24 +171,25 @@ public function addClassMap(array $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 string[]|string $paths The PSR-0 root directories - * @param bool $prepend Whether to prepend the directories + * @param string $prefix The prefix + * @param list|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( - (array) $paths, + $paths, $this->fallbackDirsPsr0 ); } else { $this->fallbackDirsPsr0 = array_merge( $this->fallbackDirsPsr0, - (array) $paths + $paths ); } @@ -201,19 +198,19 @@ public function add($prefix, $paths, $prepend = false) $first = $prefix[0]; if (!isset($this->prefixesPsr0[$first][$prefix])) { - $this->prefixesPsr0[$first][$prefix] = (array) $paths; + $this->prefixesPsr0[$first][$prefix] = $paths; return; } if ($prepend) { $this->prefixesPsr0[$first][$prefix] = array_merge( - (array) $paths, + $paths, $this->prefixesPsr0[$first][$prefix] ); } else { $this->prefixesPsr0[$first][$prefix] = array_merge( $this->prefixesPsr0[$first][$prefix], - (array) $paths + $paths ); } } @@ -222,9 +219,9 @@ public function add($prefix, $paths, $prepend = false) * 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 string[]|string $paths The PSR-4 base directories - * @param bool $prepend Whether to prepend the directories + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param list|string $paths The PSR-4 base directories + * @param bool $prepend Whether to prepend the directories * * @throws \InvalidArgumentException * @@ -232,17 +229,18 @@ public function add($prefix, $paths, $prepend = false) */ public function addPsr4($prefix, $paths, $prepend = false) { + $paths = (array) $paths; if (!$prefix) { // Register directories for the root namespace. if ($prepend) { $this->fallbackDirsPsr4 = array_merge( - (array) $paths, + $paths, $this->fallbackDirsPsr4 ); } else { $this->fallbackDirsPsr4 = array_merge( $this->fallbackDirsPsr4, - (array) $paths + $paths ); } } elseif (!isset($this->prefixDirsPsr4[$prefix])) { @@ -252,18 +250,18 @@ public function addPsr4($prefix, $paths, $prepend = false) 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; + $this->prefixDirsPsr4[$prefix] = $paths; } elseif ($prepend) { // Prepend directories for an already registered namespace. $this->prefixDirsPsr4[$prefix] = array_merge( - (array) $paths, + $paths, $this->prefixDirsPsr4[$prefix] ); } else { // Append directories for an already registered namespace. $this->prefixDirsPsr4[$prefix] = array_merge( $this->prefixDirsPsr4[$prefix], - (array) $paths + $paths ); } } @@ -272,8 +270,8 @@ public function addPsr4($prefix, $paths, $prepend = false) * 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 string[]|string $paths The PSR-0 base directories + * @param string $prefix The prefix + * @param list|string $paths The PSR-0 base directories * * @return void */ @@ -290,8 +288,8 @@ public function set($prefix, $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 string[]|string $paths The PSR-4 base directories + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param list|string $paths The PSR-4 base directories * * @throws \InvalidArgumentException * @@ -425,7 +423,8 @@ public function unregister() public function loadClass($class) { if ($file = $this->findFile($class)) { - includeFile($file); + $includeFile = self::$includeFile; + $includeFile($file); return true; } @@ -476,9 +475,9 @@ public function findFile($class) } /** - * Returns the currently registered loaders indexed by their corresponding vendor directories. + * Returns the currently registered loaders keyed by their corresponding vendor directories. * - * @return self[] + * @return array */ public static function getRegisteredLoaders() { @@ -555,18 +554,26 @@ private function findFileWithExtension($class, $ext) return false; } -} -/** - * Scope isolated include. - * - * Prevents access to $this/self from included files. - * - * @param string $file - * @return void - * @private - */ -function includeFile($file) -{ - include $file; + /** + * @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); + } } diff --git a/lib/vendor/composer/InstalledVersions.php b/lib/vendor/composer/InstalledVersions.php index 015819496..51e734a77 100644 --- a/lib/vendor/composer/InstalledVersions.php +++ b/lib/vendor/composer/InstalledVersions.php @@ -21,12 +21,14 @@ * 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, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array}|array{}|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}|array{}|null */ private static $installed; @@ -37,7 +39,7 @@ class InstalledVersions /** * @var array[] - * @psalm-var array}> + * @psalm-var array}> */ private static $installedByVendor = array(); @@ -96,7 +98,7 @@ public static function isInstalled($packageName, $includeDevRequirements = true) { foreach (self::getInstalled() as $installed) { if (isset($installed['versions'][$packageName])) { - return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']); + return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false; } } @@ -117,7 +119,7 @@ public static function isInstalled($packageName, $includeDevRequirements = true) */ public static function satisfies(VersionParser $parser, $packageName, $constraint) { - $constraint = $parser->parseConstraints($constraint); + $constraint = $parser->parseConstraints((string) $constraint); $provided = $parser->parseConstraints(self::getVersionRanges($packageName)); return $provided->matches($constraint); @@ -241,7 +243,7 @@ public static function getInstallPath($packageName) /** * @return array - * @psalm-return array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string} + * @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() { @@ -255,7 +257,7 @@ public static function getRootPackage() * * @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, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: 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} */ public static function getRawData() { @@ -278,7 +280,7 @@ public static function getRawData() * Returns the raw data of all installed.php which are currently loaded for custom implementations * * @return array[] - * @psalm-return list}> + * @psalm-return list}> */ public static function getAllRawData() { @@ -301,7 +303,7 @@ public static function getAllRawData() * @param array[] $data A vendor/composer/installed.php data set * @return void * - * @psalm-param array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array} $data + * @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} $data */ public static function reload($data) { @@ -311,7 +313,7 @@ public static function reload($data) /** * @return array[] - * @psalm-return list}> + * @psalm-return list}> */ private static function getInstalled() { diff --git a/lib/vendor/composer/LICENSE b/lib/vendor/composer/LICENSE index 62ecfd8d0..f27399a04 100644 --- a/lib/vendor/composer/LICENSE +++ b/lib/vendor/composer/LICENSE @@ -1,3 +1,4 @@ + Copyright (c) Nils Adermann, Jordi Boggiano Permission is hereby granted, free of charge, to any person obtaining a copy @@ -17,3 +18,4 @@ 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. + diff --git a/lib/vendor/composer/autoload_classmap.php b/lib/vendor/composer/autoload_classmap.php index b26f1b13b..0fb0a2c19 100644 --- a/lib/vendor/composer/autoload_classmap.php +++ b/lib/vendor/composer/autoload_classmap.php @@ -2,7 +2,7 @@ // autoload_classmap.php @generated by Composer -$vendorDir = dirname(dirname(__FILE__)); +$vendorDir = dirname(__DIR__); $baseDir = dirname($vendorDir); return array( diff --git a/lib/vendor/composer/autoload_files.php b/lib/vendor/composer/autoload_files.php index 84462ead4..2fd444363 100644 --- a/lib/vendor/composer/autoload_files.php +++ b/lib/vendor/composer/autoload_files.php @@ -2,7 +2,7 @@ // autoload_files.php @generated by Composer -$vendorDir = dirname(dirname(__FILE__)); +$vendorDir = dirname(__DIR__); $baseDir = dirname($vendorDir); return array( diff --git a/lib/vendor/composer/autoload_namespaces.php b/lib/vendor/composer/autoload_namespaces.php index b7fc0125d..15a2ff3ad 100644 --- a/lib/vendor/composer/autoload_namespaces.php +++ b/lib/vendor/composer/autoload_namespaces.php @@ -2,7 +2,7 @@ // autoload_namespaces.php @generated by Composer -$vendorDir = dirname(dirname(__FILE__)); +$vendorDir = dirname(__DIR__); $baseDir = dirname($vendorDir); return array( diff --git a/lib/vendor/composer/autoload_psr4.php b/lib/vendor/composer/autoload_psr4.php index cfe379c75..9dde0db04 100644 --- a/lib/vendor/composer/autoload_psr4.php +++ b/lib/vendor/composer/autoload_psr4.php @@ -2,7 +2,7 @@ // autoload_psr4.php @generated by Composer -$vendorDir = dirname(dirname(__FILE__)); +$vendorDir = dirname(__DIR__); $baseDir = dirname($vendorDir); return array( diff --git a/lib/vendor/composer/autoload_real.php b/lib/vendor/composer/autoload_real.php index acb4e1bc3..d220f05e5 100644 --- a/lib/vendor/composer/autoload_real.php +++ b/lib/vendor/composer/autoload_real.php @@ -23,56 +23,26 @@ public static function getLoader() } spl_autoload_register(array('ComposerAutoloaderInitPublishPressPlanner', 'loadClassLoader'), true, true); - self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__))); + self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__)); spl_autoload_unregister(array('ComposerAutoloaderInitPublishPressPlanner', 'loadClassLoader')); - $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); - if ($useStaticLoader) { - require __DIR__ . '/autoload_static.php'; + require __DIR__ . '/autoload_static.php'; + call_user_func(\Composer\Autoload\ComposerStaticInitPublishPressPlanner::getInitializer($loader)); - call_user_func(\Composer\Autoload\ComposerStaticInitPublishPressPlanner::getInitializer($loader)); - } else { - $map = require __DIR__ . '/autoload_namespaces.php'; - foreach ($map as $namespace => $path) { - $loader->set($namespace, $path); - } + $loader->register(true); - $map = require __DIR__ . '/autoload_psr4.php'; - foreach ($map as $namespace => $path) { - $loader->setPsr4($namespace, $path); - } + $filesToLoad = \Composer\Autoload\ComposerStaticInitPublishPressPlanner::$files; + $requireFile = \Closure::bind(static function ($fileIdentifier, $file) { + if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { + $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; - $classMap = require __DIR__ . '/autoload_classmap.php'; - if ($classMap) { - $loader->addClassMap($classMap); + require $file; } - } - - $loader->register(true); - - if ($useStaticLoader) { - $includeFiles = Composer\Autoload\ComposerStaticInitPublishPressPlanner::$files; - } else { - $includeFiles = require __DIR__ . '/autoload_files.php'; - } - foreach ($includeFiles as $fileIdentifier => $file) { - composerRequirePublishPressPlanner($fileIdentifier, $file); + }, null, null); + foreach ($filesToLoad as $fileIdentifier => $file) { + $requireFile($fileIdentifier, $file); } return $loader; } } - -/** - * @param string $fileIdentifier - * @param string $file - * @return void - */ -function composerRequirePublishPressPlanner($fileIdentifier, $file) -{ - if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { - $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; - - require $file; - } -} diff --git a/lib/vendor/composer/installed.php b/lib/vendor/composer/installed.php index c77c03f00..df2d82528 100644 --- a/lib/vendor/composer/installed.php +++ b/lib/vendor/composer/installed.php @@ -1,76 +1,76 @@ array( - 'pretty_version' => 'dev-master', - 'version' => 'dev-master', + 'name' => '__root__', + 'pretty_version' => '1.0.0+no-version-set', + 'version' => '1.0.0.0', + 'reference' => NULL, 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), - 'reference' => '1fac247139326a1f736aec441a1650d7b4127992', - 'name' => '__root__', 'dev' => true, ), 'versions' => array( '__root__' => array( - 'pretty_version' => 'dev-master', - 'version' => 'dev-master', + 'pretty_version' => '1.0.0+no-version-set', + 'version' => '1.0.0.0', + 'reference' => NULL, 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), - 'reference' => '1fac247139326a1f736aec441a1650d7b4127992', 'dev_requirement' => false, ), 'publishpress/instance-protection' => array( 'pretty_version' => '2.0.1', 'version' => '2.0.1.0', + 'reference' => '4193f84a8a680bf4c0d40cc64976ddcadd92158a', 'type' => 'library', 'install_path' => __DIR__ . '/../publishpress/instance-protection', 'aliases' => array(), - 'reference' => '4193f84a8a680bf4c0d40cc64976ddcadd92158a', 'dev_requirement' => false, ), 'publishpress/pimple-pimple' => array( 'pretty_version' => '3.5.0.10', 'version' => '3.5.0.10', + 'reference' => 'f2784f4b1ccaf195b373a46a74cf3742e7c9f826', 'type' => 'library', 'install_path' => __DIR__ . '/../publishpress/pimple-pimple', 'aliases' => array(), - 'reference' => 'f2784f4b1ccaf195b373a46a74cf3742e7c9f826', 'dev_requirement' => false, ), 'publishpress/psr-container' => array( 'pretty_version' => '2.0.1.10', 'version' => '2.0.1.10', + 'reference' => '4ccd2cb058e7b93e96186791ca25870a02e35c5d', 'type' => 'library', 'install_path' => __DIR__ . '/../publishpress/psr-container', 'aliases' => array(), - 'reference' => '4ccd2cb058e7b93e96186791ca25870a02e35c5d', 'dev_requirement' => false, ), 'publishpress/wordpress-reviews' => array( 'pretty_version' => 'v1.1.20', 'version' => '1.1.20.0', + 'reference' => '6d0b687a66439721b0432ef1320fd818cd56309f', 'type' => 'library', 'install_path' => __DIR__ . '/../publishpress/wordpress-reviews', 'aliases' => array(), - 'reference' => '6d0b687a66439721b0432ef1320fd818cd56309f', 'dev_requirement' => false, ), 'publishpress/wordpress-version-notices' => array( 'pretty_version' => '2.1.3', 'version' => '2.1.3.0', + 'reference' => '8e54558d2427a0f93174ccbc1d02c1ba7e2abc8d', 'type' => 'library', 'install_path' => __DIR__ . '/../publishpress/wordpress-version-notices', 'aliases' => array(), - 'reference' => '8e54558d2427a0f93174ccbc1d02c1ba7e2abc8d', 'dev_requirement' => false, ), 'sabre/vobject' => array( 'pretty_version' => '3.5.3', 'version' => '3.5.3.0', + 'reference' => '129d80533a9ec0d9cacfb50b51180c34edb6874c', 'type' => 'library', 'install_path' => __DIR__ . '/../sabre/vobject', 'aliases' => array(), - 'reference' => '129d80533a9ec0d9cacfb50b51180c34edb6874c', 'dev_requirement' => false, ), ), diff --git a/modules/calendar/calendar.php b/modules/calendar/calendar.php index 4064e6990..8a0c4fc6b 100644 --- a/modules/calendar/calendar.php +++ b/modules/calendar/calendar.php @@ -529,46 +529,6 @@ private function currentUserCanViewCalendar() return current_user_can($this->getViewCapability()); } - protected function getPostStatusOptions() - { - $postStatuses = []; - $post_statuses_terms = get_terms('post_status', ['hide_empty' => false]); - $post_statuses_terms_slugs = (!is_wp_error($post_statuses_terms)) ? array_column($post_statuses_terms, 'slug') : []; - foreach ($this->get_post_statuses() as $status) { - //add support for capabilities custom statuses - if (defined('PUBLISHPRESS_CAPS_PRO_VERSION') - && !empty(get_option('cme_custom_status_control')) - && in_array($status->slug, $post_statuses_terms_slugs) - && !current_user_can('status_change_' . $status->slug) - ) { - continue; - } - $postStatuses[] = [ - 'value' => esc_attr($status->slug), - 'text' => esc_html($status->label), - ]; - } - - return $postStatuses; - } - - protected function getUserAuthorizedPostStatusOptions($postType) - { - $postStatuses = $this->getPostStatusOptions(); - - foreach ($postStatuses as $index => $status) { - // Filter publishing posts if the post type is set - if (in_array($status['value'], ['publish', 'future', 'private'])) { - $postTypeObj = get_post_type_object($postType); - if (! current_user_can($postTypeObj->cap->publish_posts)) { - unset($postStatuses[$index]); - } - } - } - - return $postStatuses; - } - /** * Add any necessary JS to the WordPress admin * diff --git a/modules/content-overview/content-overview.php b/modules/content-overview/content-overview.php index 0112e5efd..793f708cc 100644 --- a/modules/content-overview/content-overview.php +++ b/modules/content-overview/content-overview.php @@ -58,11 +58,6 @@ class PP_Content_Overview extends PP_Module */ const USERMETA_KEY_PREFIX = 'PP_Content_Overview_'; - /** - * Default number of columns - */ - const DEFAULT_NUM_COLUMNS = 1; - /** * @var string */ @@ -83,37 +78,41 @@ class PP_Content_Overview extends PP_Module public $module; /** - * [$num_columns description] + * [$no_matching_posts description] * - * @var integer + * @var boolean */ - public $num_columns = 0; + public $no_matching_posts = true; /** - * [$max_num_columns description] - * - * @var [type] + * @var array */ - public $max_num_columns; + public $columns; /** - * [$no_matching_posts description] - * - * @var boolean + * @var array */ - public $no_matching_posts = true; + public $filters; /** - * [$terms description] - * * @var array */ - public $terms = []; + public $form_columns = []; /** * @var array */ - public $columns; + public $form_filters = []; + + /** + * @var array + */ + public $form_column_lists = []; + + /** + * @var array + */ + public $form_filter_list = []; /** * [$user_filters description] @@ -129,6 +128,13 @@ class PP_Content_Overview extends PP_Module */ private $terms_options = []; + /** + * [$content_overview_datas description] + * + * @var [type] + */ + public $content_overview_datas; + /** * Register the module with PublishPress but don't do anything else */ @@ -146,13 +152,16 @@ public function __construct() 'slug' => 'content-overview', 'default_options' => [ 'enabled' => 'on', + // Leave default as non array to confirm if user save settings or not + 'content_overview_columns' => '', + 'content_overview_custom_columns' => '', + 'content_overview_filters' => '', + 'content_overview_custom_filters' => '', + 'post_types' => [ 'post' => 'on', 'page' => 'off', ], - 'taxonomies' => [ - 'category' => 'on' - ], ], 'configure_page_cb' => 'print_configure_view', 'options_page' => true, @@ -179,22 +188,17 @@ public function init() return; } - $this->num_columns = $this->get_num_columns(); - $this->max_num_columns = apply_filters('PP_Content_Overview_max_num_columns', 3); - // Filter to allow users to pick a taxonomy other than 'category' for sorting their posts $this->taxonomy_used = apply_filters('PP_Content_Overview_taxonomy_used', $this->taxonomy_used); add_action('admin_init', [$this, 'handle_form_date_range_change']); - add_action('admin_init', [$this, 'handle_screen_options']); // Register our settings add_action('admin_init', [$this, 'register_settings']); - add_action('admin_init', [$this, 'register_columns']); - add_action('wp_ajax_publishpress_content_overview_search_authors', [$this, 'sendJsonSearchAuthors']); add_action('wp_ajax_publishpress_content_overview_search_categories', [$this, 'sendJsonSearchCategories']); + add_action('wp_ajax_publishpress_content_overview_get_form_fields', [$this, 'getFormFieldAjaxHandler']); // Menu add_filter('publishpress_admin_menu_slug', [$this, 'filter_admin_menu_slug'], 20); @@ -227,56 +231,6 @@ public function setDefaultCapabilities() } } - /** - * Get the number of columns to show on the content overview - */ - public function get_num_columns() - { - if (empty($this->num_columns)) { - $current_user = wp_get_current_user(); - $this->num_columns = $this->get_user_meta( - $current_user->ID, - self::USERMETA_KEY_PREFIX . 'screen_columns', - true - ); - // If usermeta didn't have a value already, use a default value and insert into DB - if (empty($this->num_columns)) { - $this->num_columns = self::DEFAULT_NUM_COLUMNS; - $this->save_column_prefs([self::USERMETA_KEY_PREFIX . 'screen_columns' => $this->num_columns]); - } - } - - return $this->num_columns; - } - - /** - * Save the current user's preference for number of columns. - */ - public function save_column_prefs($posted_fields) - { - $key = self::USERMETA_KEY_PREFIX . 'screen_columns'; - $this->num_columns = (int)$posted_fields[$key]; - - $current_user = wp_get_current_user(); - $this->update_user_meta($current_user->ID, $key, $this->num_columns); - } - - public function handle_screen_options() - { - include_once PUBLISHPRESS_BASE_PATH . '/common/php/' . 'screen-options.php'; - - if (function_exists('add_screen_options_panel')) { - add_screen_options_panel( - self::USERMETA_KEY_PREFIX . 'screen_columns', - esc_html__('Screen Layout', 'publishpress'), - [$this, 'print_column_prefs'], - self::SCREEN_ID, - [$this, 'save_column_prefs'], - true - ); - } - } - /** * Register settings for notifications so we can partially use the Settings API * (We use the Settings API for form generation, but not saving) @@ -300,44 +254,6 @@ public function register_settings() $this->module->options_group_name, $this->module->options_group_name . '_general' ); - - add_settings_field( - 'taxonomies', - __('Taxonomies to show:', 'publishpress'), - [$this, 'settings_taxonomies_option'], - $this->module->options_group_name, - $this->module->options_group_name . '_general' - ); - } - - /** - * Choose the taxonomies - * - * @since 3.7.0 - */ - public function settings_taxonomies_option() - { - - $taxonomies = $this->get_all_taxonomies(); - - foreach ($taxonomies as $taxonomy) { - $value = $taxonomy->name; - $label = $taxonomy->label . ' (' . $value . ')';//some taxonomy can have same public name, so we should put unique name in bracket - - //let skip status from filter list since we already have it seperately - if (in_array($value, ['post_status', 'post_status_core_wp_pp', 'post_visibility_pp'])) { - continue; - } - - echo '
'; - } - } /** @@ -406,10 +322,6 @@ public function settings_validate($new_options) $this->module->post_type_support ); - if (!isset($new_options['taxonomies'])) { - $new_options['taxonomies'] = []; - } - return $new_options; } @@ -419,8 +331,7 @@ public function settings_validate($new_options) * @since 0.7 */ public function print_configure_view() - { - global $publishpress; ?> + { ?>
@@ -540,18 +451,14 @@ public function enqueue_admin_scripts() { global $pagenow; - // Only load calendar styles on the calendar page + // Only load content overview styles on the content overview page if ('admin.php' === $pagenow && isset($_GET['page']) && $_GET['page'] === 'pp-content-overview') { // phpcs:ignore WordPress.Security.NonceVerification.Recommended - $num_columns = $this->get_num_columns(); - echo ''; $this->enqueue_datepicker_resources(); wp_enqueue_script( 'publishpress-content_overview', $this->module_url . 'lib/content-overview.js', - ['publishpress-date_picker', 'publishpress-select2'], + ['jquery', 'publishpress-date_picker', 'publishpress-select2', 'jquery-ui-sortable'], PUBLISHPRESS_VERSION, true ); @@ -563,11 +470,20 @@ public function enqueue_admin_scripts() PUBLISHPRESS_VERSION ); + + wp_enqueue_script( + 'publishpress-floating-scroll', + PUBLISHPRESS_URL . 'common/libs/floating-scroll/js/jquery.floatingscroll.min.js', + ['jquery'], + PUBLISHPRESS_VERSION + ); + wp_localize_script( 'publishpress-content_overview', 'PPContentOverview', [ 'nonce' => wp_create_nonce('content_overview_filter_nonce'), + 'moduleUrl' => $this->module_url ] ); } @@ -611,147 +527,66 @@ public function action_enqueue_admin_styles() PUBLISHPRESS_VERSION, 'screen' ); + + wp_enqueue_style( + 'publishpress-floating-scroll', + PUBLISHPRESS_URL . 'common/libs/floating-scroll/css/jquery.floatingscroll.css', + false, + PUBLISHPRESS_VERSION, + 'screen' + ); } } /** - * Register the columns of information that appear for each term module. - * Modeled after how WP_List_Table works, but focused on hooks instead of OOP extending - * - * @since 0.7 + * Create the content overview view. This calls lots of other methods to do its work. This will + * output any messages, create the table navigation, then print the columns.. */ - public function register_columns() + public function render_admin_page() { + // phpcs:disable WordPress.Security.NonceVerification.Recommended + global $publishpress; + + // update content overview form action + $this->update_content_overview_form_action(); + + // Get content overview data + $this->content_overview_datas = $this->get_content_overview_datas(); + $columns = [ - 'post_title' => esc_html__('Title', 'publishpress'), - 'post_status' => esc_html__('Status', 'publishpress'), - 'post_type' => esc_html__('Post Type', 'publishpress'), - 'post_author' => esc_html__('Author', 'publishpress'), - 'post_date' => esc_html__('Post Date', 'publishpress'), - 'post_modified' => esc_html__('Last Modified', 'publishpress'), + 'post_title' => esc_html__('Title', 'publishpress') ]; - + $columns = array_merge($columns, $this->content_overview_datas['content_overview_columns']); /** * @param array $columns * * @return array - * @deprecated Use publishpress_content_overview_columns */ - $columns = apply_filters('PP_Content_Overview_term_columns', $columns); + $this->columns = apply_filters('publishpress_content_overview_columns', $columns); + + $filters = $this->content_overview_datas['content_overview_filters']; /** * @param array $columns * * @return array */ - $columns = apply_filters('publishpress_content_overview_columns', $columns); - - if (class_exists('PP_Editorial_Metadata')) { - $additional_terms = get_terms( - [ - 'taxonomy' => PP_Editorial_Metadata::metadata_taxonomy, - 'orderby' => 'name', - 'order' => 'asc', - 'hide_empty' => 0, - 'parent' => 0, - 'fields' => 'all', - ] - ); - - $additional_terms = apply_filters('PP_Content_Overview_filter_terms', $additional_terms); - foreach ($additional_terms as $term) { - if (! is_object($term) || $term->taxonomy !== PP_Editorial_Metadata::metadata_taxonomy) { - continue; - } - - $term_options = $this->get_unencoded_description($term->description); - - if (! isset($term_options['viewable']) || - (bool)$term_options['viewable'] === false || - isset($columns[$term->slug])) { - continue; - } - - $this->terms_options[$term->slug] = $term_options; - - $columns[$term->slug] = $term->name; - } - - $this->columns = $columns; - } - } - - /** - * Print column number preferences for screen options - */ - public function print_column_prefs() - { - $return_val = esc_html__('Number of Columns: ', 'publishpress'); - - for ($i = 1; $i <= $this->max_num_columns; ++$i) { - $return_val .= "\n"; - } - - return $return_val; - } + $this->filters = apply_filters('publishpress_content_overview_filters', $filters); - /** - * Create the content overview view. This calls lots of other methods to do its work. This will - * output any messages, create the table navigation, then print the columns based on - * get_num_columns(), which will in turn print the stories themselves. - */ - public function render_admin_page() - { - // phpcs:disable WordPress.Security.NonceVerification.Recommended - global $publishpress; + $this->form_columns = $this->get_content_overview_form_columns(); + $this->form_column_list = array_merge(...array_values(array_column($this->form_columns, 'columns'))); + $this->form_filters = $this->get_content_overview_form_filters(); + $this->form_filter_list = array_merge(...array_values(array_column($this->form_filters, 'filters'))); + // Update the current user's filters with the variables set in $_GET $this->user_filters = $this->update_user_filters(); - if (! empty($this->user_filters['cat'])) { - $terms = []; - $terms[] = get_term($this->user_filters['cat'], $this->taxonomy_used); - } else { - // Get all of the terms from the taxonomy, regardless whether there are published posts - $args = [ - 'orderby' => 'name', - 'order' => 'asc', - 'hide_empty' => 0, - 'parent' => 0, - ]; - $terms = get_terms($this->taxonomy_used, $args); - } - - if (class_exists('PP_Editorial_Metadata')) { - $this->terms = array_filter( - // allow for reordering or any other filtering of terms - apply_filters('PP_Content_Overview_filter_terms', $terms), - function ($term) { - if ($term->taxonomy !== PP_Editorial_Metadata::metadata_taxonomy) { - return true; - } - - $term_options = $this->get_unencoded_description($term->description); - - return isset($term_options['viewable']) && (bool)$term_options['viewable']; - } - ); - } else { - // allow for reordering or any other filtering of terms - $this->terms = apply_filters('PP_Content_Overview_filter_terms', $terms); - } - $description = sprintf( '
%s %s
%s', '', '', - $this->content_overview_search_box() + '' ); $publishpress->settings->print_default_header($publishpress->modules->content_overview, $description); ?> @@ -770,7 +605,7 @@ function ($term) { } echo '
'; - $this->printPostForPostType(null, $selectedPostTypes); + $this->printPostForPostType($selectedPostTypes); echo '
'; ?> @@ -797,23 +632,6 @@ public function get_selected_post_types() return $enabledPostTypes; } - /** - * Retrieve all metadata with filter option - */ - public function get_filterable_metadata() - { - global $publishpress; - - $filterable_metadata = []; - if (class_exists('PP_Editorial_Metadata')) { - $editorial_metadata_terms = $publishpress->editorial_metadata->get_editorial_metadata_terms(['show_in_filters' => true]); - foreach ($editorial_metadata_terms as $term) { - $filterable_metadata[$term->slug] = $term; - } - } - return $filterable_metadata; - } - /** * Update the current user's filters for content overview display with the filters in $_GET. The filters * in $_GET take precedence over the current users filters if they exist. @@ -823,33 +641,44 @@ public function update_user_filters() $current_user = wp_get_current_user(); $user_filters = [ - 'search_box' => $this->filter_get_param('s'), - 'post_status' => $this->filter_get_param('post_status'), - 'author' => $this->filter_get_param('author'), 'start_date' => $this->filter_get_param('start_date'), 'end_date' => $this->filter_get_param('end_date'), - 'ptype' => $this->filter_get_param('ptype'), + 'me_mode' => $this->filter_get_param('me_mode'), ]; - //add metadata to filter - foreach ($this->get_filterable_metadata() as $meta_key => $meta_term) { - if ($meta_term->type === 'checkbox') { - $user_filters[$meta_key] = !empty($this->filter_get_param($meta_key)) ? absint($this->filter_get_param($meta_key)) : ''; - } elseif ($meta_term->type === 'date') { - $user_filters[$meta_key] = $this->filter_get_param_text($meta_key); - $user_filters[$meta_key . '_start'] = $this->filter_get_param_text($meta_key . '_start'); - $user_filters[$meta_key . '_end'] = $this->filter_get_param_text($meta_key . '_end'); - $user_filters[$meta_key . '_start_hidden'] = $this->filter_get_param_text($meta_key . '_start_hidden'); - $user_filters[$meta_key . '_end_hidden'] = $this->filter_get_param_text($meta_key . '_end_hidden'); + $editorial_metadata = $this->terms_options; + + foreach ($this->filters as $filter_key => $filter_label) { + if (array_key_exists($filter_key, $editorial_metadata)) { + //add metadata to filter + $meta_term = $editorial_metadata[$filter_key]; + $meta_term_type = $meta_term['type']; + if ($meta_term_type === 'checkbox') { + if (! isset($_GET[$filter_key])) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended + $check_value = null; + } else { + $check_value = absint($this->filter_get_param($filter_key)); + } + $user_filters[$filter_key] = $check_value; + } elseif ($meta_term_type === 'date') { + $user_filters[$filter_key] = $this->filter_get_param_text($filter_key); + $user_filters[$filter_key . '_start'] = $this->filter_get_param_text($filter_key . '_start'); + $user_filters[$filter_key . '_end'] = $this->filter_get_param_text($filter_key . '_end'); + $user_filters[$filter_key . '_start_hidden'] = $this->filter_get_param_text($filter_key . '_start_hidden'); + $user_filters[$filter_key . '_end_hidden'] = $this->filter_get_param_text($filter_key . '_end_hidden'); + } elseif ($meta_term_type === 'user') { + if (empty($user_filters['me_mode'])) { + $user_filters[$filter_key] = $this->filter_get_param_text($filter_key); + } + } else { + $user_filters[$filter_key] = $this->filter_get_param_text($filter_key); + } } else { - $user_filters[$meta_key] = $this->filter_get_param_text($meta_key); - } - } - - //add taxonomies to filter - foreach ($this->module->options->taxonomies as $taxonomy => $status) { - if ($status == 'on') { - $user_filters[$taxonomy] = $this->filter_get_param($taxonomy); + // other filters + $user_filters[$filter_key] = $this->filter_get_param_text($filter_key); + if (in_array($filter_key, $this->content_overview_datas['meta_keys']) || in_array($filter_key, ['ppch_co_yoast_seo__yoast_wpseo_linkdex', 'ppch_co_yoast_seo__yoast_wpseo_content_score'])) { + $user_filters[$filter_key . '_operator'] = $this->filter_get_param_text($filter_key . '_operator'); + } } } @@ -858,7 +687,7 @@ public function update_user_filters() // If any of the $_GET vars are missing, then use the current user filter foreach ($user_filters as $key => $value) { - if (is_null($value) && ! empty($current_user_filters[$key])) { + if (is_null($value) && $value !== '0' && ! empty($current_user_filters[$key])) { $user_filters[$key] = $current_user_filters[$key]; } } @@ -871,6 +700,10 @@ public function update_user_filters() $user_filters['end_date'] = date('Y-m-d', strtotime($user_filters['start_date'] . ' +30 day')); } + if (!empty($user_filters['me_mode'])) { + $user_filters['author'] = $current_user->ID; + } + $user_filters = apply_filters('PP_Content_Overview_filter_values', $user_filters, $current_user_filters); $this->update_user_meta($current_user->ID, self::USERMETA_KEY_PREFIX . 'filters', $user_filters); @@ -930,7 +763,7 @@ public function handle_form_date_range_change() * * @param string $param The parameter to look for in $_GET * - * @return null if the parameter is not set in $_GET, empty string if the parameter is empty in $_GET, + * @return mixed null if the parameter is not set in $_GET, empty string if the parameter is empty in $_GET, * or a sanitized version of the parameter from $_GET if set and not empty */ public function filter_get_param($param) @@ -950,7 +783,7 @@ public function filter_get_param($param) * * @param string $param The parameter to look for in $_GET * - * @return null if the parameter is not set in $_GET, empty string if the parameter is empty in $_GET, + * @return mixed null if the parameter is not set in $_GET, empty string if the parameter is empty in $_GET, * or a sanitized version of the parameter from $_GET if set and not empty */ public function filter_get_param_text($param) @@ -978,16 +811,16 @@ public function content_overview_time_range() $filtered_end_date = $this->user_filters['end_date']; $filtered_end_date_timestamp = strtotime($filtered_end_date); - $output = ''; - $output .= ''; + $output = ''; return $output; } - /** - * Content overview search box - * - */ - public function content_overview_search_box() - { - ob_start(); - ?> - - -
-
- - -
- content_overview_filters(['default']) as $select_id => $select_name) { - $default_filter .= $this->content_overview_filter_options($select_id, $select_name, $this->user_filters); - } - $default_filter = preg_replace('~>\s+<~', '><', $default_filter);//remove whitespace - echo $default_filter; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped - ?> -
- -
- 'filter-submit']); ?> - -
- - -
- - - - - - - content_overview_filters() as $select_id => $select_name) { - echo ''; - } ?> - '; - $start_date_value .= ''; - - $end_date_value = ''; - $end_date_value .= ''; - - $nonce = wp_nonce_field('change-date', 'nonce', 'change-date-nonce', false); - - echo $start_date_value . $end_date_value . $nonce; - ?> - -
-
- - -
-
- module->options->taxonomies as $taxonomy => $status) { - if ($status == 'on') { - $select_filter_names[$taxonomy] = $taxonomy; - } - } - $select_filter_names['author'] = 'author'; - $select_filter_names['ptype'] = 'ptype'; - $select_filter_names['search_box'] = 'search_box'; - } - - if (in_array('metadata', $filter)) { - //metadata field - foreach ($this->get_filterable_metadata() as $meta_key => $meta_term) { - if ($meta_term->type === 'date') { - $select_filter_names[$meta_key . '_start'] = $meta_key . '_start'; - $select_filter_names[$meta_key . '_end'] = $meta_key . '_end'; - $select_filter_names[$meta_key . '_start_hidden'] = $meta_key . '_start_hidden'; - $select_filter_names[$meta_key . '_end_hidden'] = $meta_key . '_end_hidden'; + $publishpress->update_module_option($this->module->name, 'content_overview_columns', $content_overview_columns); + $publishpress->update_module_option($this->module->name, 'content_overview_custom_columns', $content_overview_custom_columns); + + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + echo pp_planner_admin_notice(esc_html__('Column updated successfully.', 'publishpress')); + } elseif (!empty($_POST['co_form_action']) && !empty($_POST['_nonce']) && $_POST['co_form_action'] == 'filter_form' && wp_verify_nonce(sanitize_key($_POST['_nonce']), 'content_overview_filter_form_nonce')) { + // Content overview filter form + $content_overview_filters = !empty($_POST['content_overview_filters']) ? array_map('sanitize_text_field', $_POST['content_overview_filters']) : []; + $content_overview_filters_order = !empty($_POST['content_overview_filters_order']) ? array_map('sanitize_text_field', $_POST['content_overview_filters_order']) : []; + $content_overview_custom_filters = !empty($_POST['content_overview_custom_filters']) ? map_deep($_POST['content_overview_custom_filters'], 'sanitize_text_field') : []; + + // make sure enabled filters are saved in organized order + $content_overview_filters = array_intersect($content_overview_filters_order, $content_overview_filters); + + $publishpress->update_module_option($this->module->name, 'content_overview_filters', $content_overview_filters); + $publishpress->update_module_option($this->module->name, 'content_overview_custom_filters', $content_overview_custom_filters); + + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + echo pp_planner_admin_notice(esc_html__('Filter updated successfully.', 'publishpress')); + } elseif (!empty($_POST['co_form_action']) && !empty($_POST['_nonce']) && !empty($_POST['ptype']) && $_POST['co_form_action'] == 'post_form' && wp_verify_nonce(sanitize_key($_POST['_nonce']), 'content_overview_post_form_nonce')) { + $postType = sanitize_text_field($_POST['ptype']); + $postTypeObject = get_post_type_object($postType); + if (current_user_can($postTypeObject->cap->edit_posts)) { + $status = isset($_POST['status']) ? sanitize_text_field($_POST['status']) : null; + $title = isset($_POST['title']) ? sanitize_text_field($_POST['title']) : ''; + // Sanitized by the wp_filter_post_kses function. + // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized + $content = isset($_POST['content']) ? wp_filter_post_kses($_POST['content']) : ''; + $authors = isset($_POST['authors']) ? (int) $_POST['authors'] : get_current_user_id(); + $categories = isset($_POST['category']) ? array_map('sanitize_text_field', $_POST['category']) : []; + $tags = isset($_POST['post_tag']) ? array_map('sanitize_text_field', $_POST['post_tag']) : []; + + $postArgs = [ + 'post_author' => $authors, + 'post_title' => $title, + 'post_content' => $content, + 'post_type' => $postType, + 'post_status' => $status + ]; + + $postId = wp_insert_post($postArgs); + + if ($postId) { + if (! empty($categories)) { + $categoriesIdList = []; + foreach ($categories as $categorySlug) { + $category = get_term_by('slug', $categorySlug, 'category'); + + if (! $category || is_wp_error($category)) { + $category = wp_create_category($categorySlug); + $category = get_term($category); + } + + if (! is_wp_error($category)) { + $categoriesIdList[] = $category->term_id; + } + } + wp_set_post_terms($postId, $categoriesIdList, 'category'); + } + + if (! empty($tags)) { + foreach ($tags as $tagSlug) { + $tag = get_term_by('slug', $tagSlug, 'post_tag'); + + if (! $tag || is_wp_error($tag)) { + wp_create_tag($tagSlug); + } + } + wp_set_post_terms($postId, $tags); + } + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + echo pp_planner_admin_notice(sprintf(__('%s created successfully. Edit %s', 'publishpress'), esc_html($postTypeObject->labels->singular_name), esc_url(get_edit_post_link($postId)), esc_html($postTypeObject->labels->singular_name))); + } else { + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + echo pp_planner_admin_notice(sprintf(esc_html__('%s could not be created', 'publishpress'), esc_html($postTypeObject->labels->singular_name)), false); } - $select_filter_names[$meta_key] = $meta_key; + + } else { + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + echo pp_planner_admin_notice(sprintf(esc_html__('You do not have permission to add new %s', 'publishpress'), esc_html($postTypeObject->labels->singular_name)), false); } } - return apply_filters('PP_Content_Overview_filter_names', $select_filter_names); } - public function content_overview_filter_options($select_id, $select_name, $filters) - { - - if (array_key_exists($select_id, $this->get_filterable_metadata())) { - $select_id = 'metadata_key'; - } - - if (array_key_exists($select_id, $this->module->options->taxonomies) && taxonomy_exists($select_id)) { + /** + * Get content overview data that's required on the + * content overview page + * + * @return array + */ + public function get_content_overview_datas() { + global $wpdb; + + if (is_array($this->content_overview_datas)) { + return $this->content_overview_datas; + } + + $datas = []; + + // add all meta keys + $datas['meta_keys'] = $wpdb->get_col("SELECT DISTINCT meta_key FROM $wpdb->postmeta WHERE 1=1 ORDER BY meta_key ASC"); + + // add editorial metadata + if (class_exists('PP_Editorial_Metadata')) { + $additional_terms = get_terms( + [ + 'taxonomy' => PP_Editorial_Metadata::metadata_taxonomy, + 'orderby' => 'name', + 'order' => 'asc', + 'hide_empty' => 0, + 'parent' => 0, + 'fields' => 'all', + ] + ); + + $metadatas = []; + foreach ($additional_terms as $term) { + if (! is_object($term) || $term->taxonomy !== PP_Editorial_Metadata::metadata_taxonomy) { + continue; + } + $metadatas[$term->slug] = $term->name; + + $term_options = $this->get_unencoded_description($term->description); + $term_options['name'] = $term->name; + $term_options['slug'] = $term->slug; + $this->terms_options[$term->slug] = $term_options; + } + + $datas['editorial_metadata'] = $metadatas; + } + + // add taxononomies + $taxonomies = $this->get_all_taxonomies(); + $all_taxonomies = []; + foreach ($taxonomies as $taxonomy) { + if (in_array($taxonomy->name, ['post_status', 'post_status_core_wp_pp', 'post_visibility_pp'])) { + continue; + } + $all_taxonomies[$taxonomy->name] = $taxonomy->label;// . ' (' . $taxonomy->name . ')'; + } + $datas['taxonomies'] = $all_taxonomies; + + // Add content overview columns content + $content_overview_columns = $this->module->options->content_overview_columns; + $content_overview_custom_columns = $this->module->options->content_overview_custom_columns; + + $datas['content_overview_columns'] = is_array($content_overview_columns) ? $content_overview_columns : + [ + 'post_status' => esc_html__('Status', 'publishpress'), + 'post_type' => esc_html__('Post Type', 'publishpress'), + 'post_author' => esc_html__('Author', 'publishpress'), + 'post_date' => esc_html__('Post Date', 'publishpress'), + 'post_modified' => esc_html__('Last Modified', 'publishpress'), + ]; + + $datas['content_overview_custom_columns'] = is_array($content_overview_custom_columns) ? $content_overview_custom_columns : []; + + // Add content overview filters content + $content_overview_filters = $this->module->options->content_overview_filters; + $content_overview_custom_filters = $this->module->options->content_overview_custom_filters; + + $datas['content_overview_filters'] = is_array($content_overview_filters) ? $content_overview_filters : [ + 'post_status' => esc_html__('Status', 'publishpress'), + 'category' => esc_html__('Categories', 'publishpress'), + 'author' => esc_html__('Author', 'publishpress'), + 'ptype' => esc_html__('Post Type', 'publishpress') + ]; + $datas['content_overview_custom_filters'] = is_array($content_overview_custom_filters) ? $content_overview_custom_filters : []; + + /** + * @param array $datas + * + * @return $datas + */ + $datas = apply_filters('publishpress_content_overview_datas', $datas); + + $this->content_overview_datas = $datas; + + return $datas; + } + + /** + * Get content overview form columns + * + * @return array + */ + public function get_content_overview_form_columns() { + + if (!empty($this->form_columns)) { + return $this->form_columns; + } + + $content_overview_datas = $this->content_overview_datas; + + $columns = []; + // custom columns + $columns['custom'] = [ + 'title' => esc_html__('Custom Columns', 'publishpress'), + 'message' => esc_html__('You do not have any custom column. Use this area to add new custom column', 'publishpress'), + 'columns' => is_array($content_overview_datas['content_overview_custom_columns']) ? $content_overview_datas['content_overview_custom_columns'] : [] + ]; + + // default columns + $columns['default'] = [ + 'title' => esc_html__('Inbuilt Columns', 'publishpress'), + 'columns' => [ + 'post_status' => esc_html__('Status', 'publishpress'), + 'post_type' => esc_html__('Post Type', 'publishpress'), + 'post_author' => esc_html__('Author', 'publishpress'), + 'post_date' => esc_html__('Post Date', 'publishpress'), + 'post_modified' => esc_html__('Last Modified', 'publishpress') + ] + ]; + + // editorial metadata columns + if (isset($content_overview_datas['editorial_metadata'])) { + $columns['editorial_metadata'] = [ + 'title' => esc_html__('Editorial Metadata', 'publishpress'), + 'message' => esc_html__('You do not have any editorial metadata enabled', 'publishpress'), + 'columns' => is_array($content_overview_datas['editorial_metadata']) ? $content_overview_datas['editorial_metadata'] : [] + ]; + } + + $columns['taxonomies'] = [ + 'title' => esc_html__('Taxonomies', 'publishpress'), + 'message' => esc_html__('You do not have any public taxonomies', 'publishpress'), + 'columns' => is_array($content_overview_datas['taxonomies']) ? $content_overview_datas['taxonomies'] : [] + ]; + + /** + * @param array $columns + * @param array $content_overview_datas + * + * @return array $columns + */ + $columns = apply_filters('publishpress_content_overview_form_columns', $columns, $content_overview_datas); + + $this->form_columns = $columns; + + return $columns; + } + + + /** + * Get content overview form filters + * + * @return array + */ + public function get_content_overview_form_filters() { + + if (!empty($this->form_filters)) { + return $this->form_filters; + } + + $content_overview_datas = $this->content_overview_datas; + + $filters = []; + // custom filters + $filters['custom'] = [ + 'title' => esc_html__('Custom filters', 'publishpress'), + 'message' => esc_html__('You do not have any custom filter. Use this area to add new custom filter', 'publishpress'), + 'filters' => $content_overview_datas['content_overview_custom_filters'] + ]; + + // default filters + $filters['default'] = [ + 'title' => esc_html__('Inbuilt filters', 'publishpress'), + 'filters' => [ + 'post_status' => esc_html__('Post Status', 'publishpress'), + 'author' => esc_html__('Author', 'publishpress'), + 'ptype' => esc_html__('Post Type', 'publishpress') + ] + ]; + + // editorial metadata filters + if (isset($content_overview_datas['editorial_metadata'])) { + $filters['editorial_metadata'] = [ + 'title' => esc_html__('Editorial Metadata', 'publishpress'), + 'message' => esc_html__('You do not have any editorial metadata enabled', 'publishpress'), + 'filters' => $content_overview_datas['editorial_metadata'] + ]; + } + + $filters['taxonomies'] = [ + 'title' => esc_html__('Taxonomies', 'publishpress'), + 'message' => esc_html__('You do not have any public taxonomies', 'publishpress'), + 'filters' => $content_overview_datas['taxonomies'] + ]; + + /** + * @param array $filters + * @param array $content_overview_datas + * + * @return $filters + */ + $filters = apply_filters('publishpress_content_overview_form_filters', $filters, $content_overview_datas); + + $this->form_filters = $filters; + + return $filters; + } + + public function content_overview_customize_column_form() { + + ob_start(); + + $content_overview_datas = $this->content_overview_datas; + $enabled_columns = array_keys($content_overview_datas['content_overview_columns']); + $columns = $this->form_columns; + $meta_keys = $content_overview_datas['meta_keys']; + + $all_columns = []; + + ?> +
+ + +
+
+
+
+
+
+
+

+
+
+ $column_datas) : + $column_index++; + ?> +
+
+ +
+ +
+ +
+ + + + +
+ + $column_label) : + $active_class = (in_array($column_name, $enabled_columns)) ? 'active-item' : ''; + $input_name = (in_array($column_name, $enabled_columns)) ? 'content_overview_columns['. $column_name .']' : ''; + + $all_columns[$column_name] = [ + 'column_label' => $column_label, + 'column_group' => $column_group + ]; + ?> +
+ + + + +
+ +
+
+ +
+
+
()
+
+ +
+ +
+ +
+ + + +
+
+ + +
+
+ content_overview_datas; + $enabled_filters = array_keys($content_overview_datas['content_overview_filters']); + $filters = $this->form_filters; + $meta_keys = $content_overview_datas['meta_keys']; + + $all_filters = []; + ?> +
+ + +
+
+
+
+
+
+
+

+
+
+ $filter_datas) : + $filter_index++; + ?> +
+
+ +
+ +
+ +
+ + + + +
+ + $filter_label) : + $active_class = (in_array($filter_name, $enabled_filters)) ? 'active-item' : ''; + $input_name = (in_array($filter_name, $enabled_filters)) ? 'content_overview_filters['. $filter_name .']' : ''; + + $all_filters[$filter_name] = [ + 'filter_label' => $filter_label, + 'filter_group' => $filter_group + ]; + ?> +
+ + + + +
+ +
+
+ +
+
+
()
+
+ +
+ +
+ +
+ + + +
+
+ + +
+
+ content_overview_get_post_form($post_type); + } + + wp_send_json($response); + } + + public function content_overview_get_post_form($post_type) { + + ob_start(); + + $postTypeObject = get_post_type_object($post_type); + $post_fields = $this->getPostTypeFields($post_type); + ?> +
+ + +
+ labels->singular_name)); ?> +
+
+
+
+
+ + + $field_options) : ?> + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+
+ +
+ + + + +
+ + [ + 'label' => __('Post Type', 'publishpress'), + 'value' => $postType, + 'type' => 'post_type', + 'options' => $this->get_editable_post_types(), + ], + 'title' => [ + 'label' => __('Title', 'publishpress'), + 'value' => null, + 'type' => 'text', + ], + 'status' => [ + 'label' => __('Post Status', 'publishpress'), + 'value' => 'draft', + 'type' => 'status', + 'options' => $this->getUserAuthorizedPostStatusOptions($postType) + ] + ]; + + if (current_user_can($postTypeObject->cap->edit_others_posts)) { + $fields['authors'] = [ + 'label' => __('Author', 'publishpress'), + 'value' => get_current_user_id(), + 'type' => 'authors', + ]; + } + + $taxonomies = get_object_taxonomies($postType); + + if (in_array('category', $taxonomies)) { + $fields['categories'] = [ + 'label' => __('Categories', 'publishpress'), + 'value' => null, + 'type' => 'taxonomy', + 'taxonomy' => 'category', + ]; + } + + if (in_array('post_tag', $taxonomies)) { + $fields['tags'] = [ + 'label' => __('Tags', 'publishpress'), + 'value' => null, + 'type' => 'taxonomy', + 'taxonomy' => 'post_tag', + ]; + } + + $fields['content'] = [ + 'label' => __('Content', 'publishpress'), + 'value' => null, + 'type' => 'html' + ]; + + if (class_exists('PP_Editorial_Metadata')) { + $editorial_metadata_class = new PP_Editorial_Metadata; + $editorial_metadata_terms = $publishpress->editorial_metadata->get_editorial_metadata_terms(['show_in_calendar_form' => true]); + foreach ($editorial_metadata_terms as $term) { + if (isset($term->post_types) && is_array($term->post_types) && in_array($postType, $term->post_types)) { + $term_options = $editorial_metadata_class->get_editorial_metadata_term_by('id', $term->term_id); + $postmeta_key = esc_attr($editorial_metadata_class->get_postmeta_key($term)); + $post_types = (isset($term->post_types) && is_array($term->post_types)) ? array_values($term->post_types) : []; + $post_types = join(" ", $post_types); + $term_data = [ + 'name' => $postmeta_key, + 'label' => $term->name, + 'description' => $term->description, + 'term_options' => $term_options, + ]; + $term_type = $term->type; + if ($term_type === 'user') { + $ajaxArgs = []; + if (isset($term->user_role)) { + $ajaxArgs['user_role'] = $term->user_role; + } + $fields[$term_data['name']] = [ + 'metadata' => true, + 'term' => $term, + 'label' => $term->name, + 'value' => '', + 'ajaxArgs' => $ajaxArgs, + 'post_types' => $post_types, + 'type' => 'authors', + 'multiple' => '' + ]; + } elseif ($term_type === 'paragraph') { + $fields[$term_data['name']] = [ + 'metadata' => true, + 'term' => $term, + 'label' => $term->name, + 'post_types' => $post_types, + 'value' => '', + 'type' => 'html' + ]; + } else { + $html = apply_filters("pp_editorial_metadata_{$term->type}_get_input_html", $term_data, ''); + $fields[$term_data['name']] = [ + 'metadata' => true, + 'post_types' => $post_types, + 'html' => (is_object($html) || is_array($html)) ? '' : '
' . $html . '
', + 'term' => $term, + 'label' => $term->name, + 'value' => '', + 'type' => 'metafield' + ]; + } + } + } + } + + $fields = apply_filters('publishpress_content_overview_get_post_type_fields', $fields, $postType); + + return $fields; + } + + /** + * Get post types user has capability to edit posts in + */ + public function get_editable_post_types() { + $editable_post_types = []; + $postTypes = $this->get_selected_post_types(); + foreach ($postTypes as $postType) { + $postTypeObject = get_post_type_object($postType); + if (!empty($postTypeObject->cap->edit_posts) && current_user_can($postTypeObject->cap->edit_posts)) { + $editable_post_types[$postTypeObject->name] = $postTypeObject->labels->singular_name; + } + } + + return $editable_post_types; + } + + /** + * Print the table navigation and filter controls, using the current user's filters if any are set. + */ + public function table_navigation() + { + // phpcs:disable WordPress.Security.NonceVerification.Recommended + + $editable_post_types = $this->get_editable_post_types(); + ?> +
+
+ user_filters['me_mode']; + $active_me_mode = !empty($me_mode) ? 'active-filter' : ''; + ?> +
+ +
+
+ +
+ + +
+ +
+ + +
+
+ + +
+ +
+ + +
+ +
+
+
+
+
+ + +
+ user_filters['start_date']; + $filtered_end_date = $this->user_filters['end_date']; + $selected_date = ': ' . date("F j, Y", strtotime($filtered_start_date)) . ' '. esc_html__('to', 'publishpress').' ' . date("F j, Y", strtotime($filtered_end_date)); + $modal_id++; + ?> + + + content_overview_filters() as $select_id => $select_name) { + $modal_id++; + $filter_data = $this->content_overview_filter_options($select_id, $select_name, $this->user_filters); + $active_class = !empty($filter_data['selected_value']) ? 'active-filter' : ''; + $button_label = $filter_data['filter_label']; + $button_label .= !empty($filter_data['selected_value']) ? ': ' . $filter_data['selected_value'] : ''; + ?> + + + + + + + + +
+
+ +
+ + + + + + + + content_overview_filters() as $select_id => $select_name) { + echo ''; + } ?> + '; + $start_date_value .= ''; + + $end_date_value = ''; + $end_date_value .= ''; + + $nonce = wp_nonce_field('change-date', 'nonce', 'change-date-nonce', false); + + echo $start_date_value . $end_date_value . $nonce; + ?> + +
+ terms_options; + + foreach ($this->filters as $filter_key => $filter_label) { + if (array_key_exists($filter_key, $editorial_metadata) && $editorial_metadata[$filter_key]['type'] === 'date') { + $select_filter_names[$filter_key . '_start'] = $filter_key . '_start'; + $select_filter_names[$filter_key . '_end'] = $filter_key . '_end'; + $select_filter_names[$filter_key . '_start_hidden'] = $filter_key . '_start_hidden'; + $select_filter_names[$filter_key . '_end_hidden'] = $filter_key . '_end_hidden'; + } + $select_filter_names[$filter_key] = $filter_key; + } + + return apply_filters('PP_Content_Overview_filter_names', $select_filter_names); + } + + private function meta_query_operator($operator = false) { + $operators = [ + 'equals' => '=', + 'not_equals' => '!=', + 'greater_than' => '>', + 'greater_than_or_equals' => '>=', + 'less_than' => '<', + 'less_than_or_equals' => '<=', + 'like' => 'LIKE', + 'not_like' => 'NOT LIKE', + 'not_exists' => 'NOT EXISTS' + ]; + + if ($operator) { + $return = array_key_exists($operator, $operators) ? $operators[$operator] : $operator; + } else { + $return = $operators; + } + + return $return; + } + + public function content_overview_filter_options($select_id, $select_name, $filters) + { + + if (array_key_exists($select_id, $this->terms_options)) { + $select_id = 'metadata_key'; + } + + if (array_key_exists($select_id, $this->content_overview_datas['taxonomies']) && taxonomy_exists($select_id)) { $select_id = 'taxonomy'; } + $filter_label = ''; + $selected_value = ''; + ob_start(); switch ($select_id) { case 'post_status': $post_statuses = $this->get_post_statuses(); + $filter_label = esc_html__('Post Status', 'publishpress'); ?> name; + echo ""; @@ -1296,6 +2111,7 @@ class="filter_taxonomy" case 'author': $authorId = isset($filters['author']) ? (int)$filters['author'] : 0; $selectedOptionAll = empty($authorId) ? 'selected="selected"' : ''; + $filter_label = esc_html__('Author', 'publishpress'); ?>