8889841cPost_Types/Base.php000064400000026522150437272350010257 0ustar00post = $post; return $instance; } /** * Returns the slug that will be prefixed to the cache key for the model. * * @since 4.9.18 * * @return string The slug that will be prefixed to the cache key for the model. */ abstract protected function get_cache_slug(); /** * Returns the cached model properties for the specified filter, if any. * * @since 4.9.18 * * @param string $filter Type of filter to apply, used here as the stored post values might change. * * @return array|false An array of model properties, or `false` if not found. */ protected function get_cached_properties( $filter ) { $cache_slug = $this->get_cache_slug(); if ( empty( $cache_slug ) ) { return false; } // Cache by post ID and filter. $cache_key = $this->get_properties_cache_key( $filter ); return ( new Cache() )->get( $cache_key, Cache_Listener::TRIGGER_SAVE_POST ); } /** * Builds and returns the properties for the model. * * In this method child classes should also implement any caching trigger mechanism, if any. * * @since 4.9.18 * * @param string $filter The type of filter to build the properties for. * * @return array An array of built properties. */ abstract protected function build_properties( $filter ); /** * Returns an array of the model properties. * * @since 4.9.18 * * @param string $filter The type of filter to get the properties for. * @param bool $force Whether to force a rebuild of the properties or not. * * @return array The model properties. This value might be cached. */ protected function get_properties( $filter, bool $force = false ) { $cached = ! $force ? $this->get_cached_properties( $filter ) : false; if ( false !== $cached ) { // Un-serialize the pre-serialized properties now, when classes will be most likely defined. $pre_serialized_properties = $cached[ self::PRE_SERIALIZED_PROPERTY ] ?? []; foreach ( $pre_serialized_properties as $key => $value ) { try { $cached[ $key ] = unserialize( $value, [ 'allowed_classes' => true ] ); } catch ( \Throwable $t ) { /* * Deal with the case where plugin A, B, C were active when the cache was built, * but B and C are now inactive. In this case the un-serialization will fail for * any pre-serialized value using classes from B and C: here we gracefully ignore * each one of those. */ } } try { // Allow models to apply further unserialization operations. $cached = $this->scalar_unserialize_properties( $cached ); /** * Allows filtering the properties of the post type model after they have been unserialized from the * cache.. * * @since 5.0.3 * * @param array $cached The key-value map of the properties of the post type model. * @param \WP_Post $post The post object of the post type model. */ $cached = apply_filters( "tec_model_{$this->get_cache_slug()}_read_cache_properties", $cached, $this->post ); // Remove the pre-serialized properties from the cached properties. unset( $cached[ self::PRE_SERIALIZED_PROPERTY ] ); return $cached; } catch ( \Throwable $t ) { // Rebuid the properties from cache failed, move on. } } $props = $this->build_properties( $filter ); $cache_slug = $this->get_cache_slug(); /** * Filters the array of properties that will be used to decorate the post object handled by the class. * * @since 4.9.18 * * @param array $props An associative array of all the properties that will be set on the "decorated" post * object. * @param \WP_Post $post The post object handled by the class. */ $props = apply_filters( "tribe_post_type_{$cache_slug}_properties", $props, $this->post ); return $props; } /** * Returns the WP_Post version of this model. * * @since 4.9.18 * @since 5.0.3 Added the `$force` parameter. * * @param string $output The required return type. One of OBJECT, ARRAY_A, or ARRAY_N, which correspond to a WP_Post * object,an associative array, or a numeric array, respectively. * @param string $filter Type of filter to apply. Accepts 'raw', 'edit', 'db', or 'display' and other formats * supported by the specific type implementation. * @param bool $force Whether to force the post to be reloaded from the database or not. * * @return \WP_Post|array|null The post object version of this post type model or `null` if the post is not valid. */ public function to_post( $output = OBJECT, $filter = 'raw', bool $force = false ) { $properties = $this->get_properties( $filter, $force ); switch ( $output ) { case ARRAY_A: return array_merge( (array) $this->post, $properties ); case ARRAY_N: return array_values( array_merge( (array) $this->post, $properties ) ); case OBJECT: default: // Clone the post to avoid side effects. $clone = clone $this->post; // And decorate the clone with the properties. foreach ( $properties as $key => $value ) { $clone->{$key} = $value; } return $clone; } } /** * Returns the closure that should be used to cache the post type model when, and if, caching it is required. * * @since 4.9.18 * * @param string $filter The kind of filter applied to the model. * @return callable The closure, or callable, that should be used to cache this model when, and if, required. */ protected function get_caching_callback( $filter ) { $cache_slug = $this->get_cache_slug(); if ( empty( $cache_slug ) ) { return '__return_true'; } $callback = null; if ( wp_using_ext_object_cache() ) { $callback = $this->get_object_cache_callback( $filter ); } return $callback; } /** * Further scalarizes the properties of the post type model. * * Extending classes should implement this method to handle * specific scalarization of the model properties. * * @since 5.0.3 * * @param array $properties A key-value map of the * properties of the post type model. * * @return array The scalarized properties key-value map. */ protected function scalar_serialize_properties( array $properties ): array { return $properties; } /** * Further un-scalarizes the properties of the post type model. * * Extending classes should implement this method to handle * specific un-scalarization of the model properties. * * @since 5.0.3 * * @param array $properties A key-value map of the * properties of the post type model. * * @return array The un-scalarized properties key-value map. */ protected function scalar_unserialize_properties( array $properties ): array { return $properties; } /** * Returns the callback function that should be used to cache the model using object caching. * * If any real caching is in place , then define a function to cache this event when, and if, one of the * lazy properties is loaded. * Cache by post ID and filter. * Cache could be pre-fetched: in that case only built-in PHP classes will be supported: for this reason * object properties will be "scalarized". * * @since 5.0.3 * * @param string $cache_slug The cache slug of the post type model. * @param string $filter The filter to cache the model for. * * @return \Closure The callback function that should be used to cache the model using object caching. */ protected function get_object_cache_callback( string $filter ): \Closure { $cache_key = $this->get_properties_cache_key( $filter ); $cache = new Cache(); return function () use ( $cache, $cache_key, $filter ) { $properties = $this->get_properties( $filter ); $pre_serialized_properties = []; try { // Pre-serialize each object property and store it in a separate cache entry. foreach ( $properties as $key => &$value ) { try { if ( is_object( $value ) && ! $value instanceof \stdClass ) { // We might end up pre-serializing other built-in objects here, but let's play it safe. $pre_serialized_properties[ $key ] = serialize( $value ); } } catch ( \Throwable $t ) { // Null the property: an object that cannot be serialized correctly is not cacheable. $value = null; } } unset( $value ); // Remove the pre-serialized properties from the main cache entry. $properties = array_diff_key( $properties, $pre_serialized_properties ); // Allow models to customize the pre-serialization further. $properties = $this->scalar_serialize_properties( $properties ); // Add the pre-serialized properties to the main cache entry. if ( count( $pre_serialized_properties ) ) { $properties[ self::PRE_SERIALIZED_PROPERTY ] = $pre_serialized_properties; } /** * Allows filtering the properties of the post type model before they are cached. * * @since 5.0.3 * * @param array $properties The key-value map of the properties of the post type model. * @param \WP_Post $post The post object of the post type model. */ $properties = apply_filters( "tec_model_{$this->get_cache_slug()}_put_cache_properties", $properties, $this->post ); } catch ( \Throwable $t ) { // If we can't serialize the properties, bail. return; } /* * Cache without expiration, but only until a post of the types managed by The Events Calendar is * updated or created. */ $cache->set( $cache_key, $properties, 0, Cache_Listener::TRIGGER_SAVE_POST ); }; } /** * Returns the cache key to be used to cache the model properties. * * @since 5.0.3 * * @param string $filter The filter to cache the model for. * * @return string The cache key to be used to cache the model properties. */ public function get_properties_cache_key( string $filter ): string { return $this->get_cache_slug() . '_' . $this->post->ID . '_' . $filter; } /** * Commits the model properties to cache immediately. * * @since 5.0.3 * * @param string $filter The filter to cache the model properties for. * * @return void The model properties are cached immediately. */ public function commit_to_cache( string $filter = 'raw' ): void { $caching_callback = $this->get_object_cache_callback( $filter ); $caching_callback(); } } Post_Types/Nothing.php000064400000001320150437272350011000 0ustar00