<?php
namespace SabaiApps\Directories\Component\WordPressContent;

use SabaiApps\Directories\Component\AbstractComponent;
use SabaiApps\Directories\Application;
use SabaiApps\Directories\Context;
use SabaiApps\Directories\Component\Field;
use SabaiApps\Directories\Component\Entity\ITypes;
use SabaiApps\Directories\Component\System;
use SabaiApps\Directories\Component\Display;
use SabaiApps\Directories\Component\CSV;
use SabaiApps\Directories\Component\Entity\Model\Bundle;
use SabaiApps\Directories\Component\Entity\Type\Query as EntityQuery;
use SabaiApps\Directories\Request;

class WordPressContentComponent extends AbstractComponent implements
	ITypes,
	System\IMainRouter,
	System\IAdminRouter,
	Field\ITypes,
	Field\IWidgets,
	Field\IRenderers,
	Field\IFilters,
	Display\IElements,
	Display\IStatistics,
	System\ITools,
	CSV\IExporters,
	CSV\IImporters {

	const VERSION = '2.0.6', PACKAGE = 'directories-pro', DB_VERSION = '20260111.6';

	private $_postTypes = array(), $_taxonomies = array();

	public static function description() {
		return 'Provides functions and features to manage WordPress pages, permissions (capabilities), and notifications.';
	}

	public static function events() {
		return array(
			'CorePlatformWordPressInit'      => 1, // run early so that others can access post types and taxonomies
			'EntityCreateBundlesCommitted'   => 99,
			'EntityUpdateBundlesCommitted'   => 99,
			'EntityDeleteBundlesCommitted'   => 99,
			'EntityFieldConditionRuleFilter' => 99, // must be run after any component                                       6
		);
	}

	public static function interfaces() {
		return array( 'FrontendSubmit\IRestrictors', 'Location\IGeolocationApis', 'Captcha\IApis', 'Notification\IEvents' );
	}

	public function install() {
		parent::install();
		$this->setDatabaseVersion();
		return $this;
	}

	public function getDatabaseVersion() {
		return $this->_application->getPlatform()->getOption( 'wp_update_database_version' );
	}

	public function setDatabaseVersion( $version = null ) {
		$this->_application->getPlatform()->setOption( 'wp_update_database_version', $version ?? self::DB_VERSION );
	}

	public function databaseNeedsUpdate() {
		if ( $this->getDatabaseVersion() >= self::DB_VERSION ) {
			return false;
		}

		if ( ! $component_model = $this->_application->getModel( 'Component', 'System' )->fetchById( $this->_name ) ) {
			return false;
		}
		return version_compare( $component_model->version, '2.0.0-dev.0', '>=' );
	}

	public function onEntityPermalinkUrlFilter( &$url, $entity, $fragment, $lang ) {
		if ( ! get_option( 'permalink_structure' ) ) {
			switch ( $entity->getType() ) {
				case 'post':
					$url = get_permalink( (int) $entity->getId() );
					break;
				case 'term':
					if ( ! $term = $entity->term() ) {
						$this->_application->logError( 'Failed fetching term for entity: ' . $entity->getId() );
						$url = $this->_application->getPlatform()->getSiteUrl();
					} else {
						$url = get_term_link( $term );
					}
					break;
				default:
					return;
			}
		}

		switch ( $this->_application->getPlatform()->getI18n() ) {
			case 'wpml':
				if ( isset( $lang ) ) {
					$url = apply_filters( 'wpml_permalink', $url, $lang );
				}
				break;
			// case 'polylang':
			// break;
			default:
				break;
		}
		if ( isset( $fragment ) && strlen( $fragment ) && strpos( $url, '#' ) === false ) {
			$url .= '#' . $fragment;
		}
	}

	public function systemMainRoutes( $lang = null ) {
		return array(
			'/_drts/wp/posts' => array(
				'controller'     => 'QueryPosts',
				'type'           => Application::ROUTE_CALLBACK,
				'access_control' => true,
				'callback_path'  => 'query_posts',
			),
		);
	}

	public function systemOnAccessMainRoute( Context $context, $path, $accessType, array &$route ) {
		switch ( $path ) {
			case 'query_posts':
				return ! $this->getUser()->isAnonymous();
		}
	}

	public function systemMainRouteTitle( Context $context, $path, $titleType, array $route ) {}

	public function systemAdminRoutes() {
		return array(
			'/directories/:directory_name/permissions' => array(
				'controller'      => 'DirectoryPermissions',
				'title_callback'  => true,
				'access_callback' => true,
				'callback_path'   => 'directory_permissions',
				'type'            => Application::ROUTE_TAB,
				'weight'          => 89,
			),
		);
	}

	public function systemOnAccessAdminRoute( Context $context, $path, $accessType, array &$route ) {
		switch ( $path ) {
			case 'directory_permissions':
				foreach ( $this->_application->Entity_Bundles( null, $context->directory->name ) as $bundle ) {
					if ( $this->_application->Entity_BundleTypeInfo( $bundle, 'entity_permissions' ) !== false ) {
						return true;
					}
				}
				return false;
		}
	}

	public function systemAdminRouteTitle( Context $context, $path, $titleType, array $route ) {
		switch ( $path ) {
			case 'directory_permissions':
				return __( 'Permissions', 'directories-pro' );
		}
	}

	public function fieldGetTypeNames() {
		return array(
			'wp_post_status',
			'wp_post_parent',
			'wp_post_content',
			'wp_term_description',
			'wp_file',
			'wp_image',
			'wp_post_reference',
			'wp_shortcode',
		);
	}

	public function fieldGetType( $name ) {
		switch ( $name ) {
			case 'wp_file':
				return new FieldType\FileFieldType( $this->_application, $name );
			case 'wp_image':
				return new FieldType\ImageFieldType( $this->_application, $name );
			case 'wp_post_parent':
				return new FieldType\PostParentFieldType( $this->_application, $name );
			case 'wp_post_content':
				return new FieldType\PostContentFieldType( $this->_application, $name );
			case 'wp_post_status':
				return new FieldType\PostStatusFieldType( $this->_application, $name );
			case 'wp_term_description':
				return new FieldType\TermDescriptionFieldType( $this->_application, $name );
			case 'wp_post_reference':
				return new FieldType\PostReferenceFieldType( $this->_application, $name );
			case 'wp_shortcode':
				return new FieldType\ShortcodeFieldType( $this->_application, $name );
		}
	}

	public function fieldGetWidgetNames() {
		return array( 'wp_post_content', 'wp_file', 'wp_image', 'wp_editor', 'wp_post_reference', 'wp_shortcode' );
	}

	public function fieldGetWidget( $name ) {
		switch ( $name ) {
			case 'wp_file':
				return new FieldWidget\FileFieldWidget( $this->_application, $name );
			case 'wp_image':
				return new FieldWidget\ImageFieldWidget( $this->_application, $name );
			case 'wp_post_content':
				return new FieldWidget\PostContentFieldWidget( $this->_application, $name );
			case 'wp_editor':
				return new FieldWidget\EditorFieldWidget( $this->_application, $name );
			case 'wp_post_reference':
				return new FieldWidget\PostReferenceFieldWidget( $this->_application, $name );
			case 'wp_shortcode':
				return new FieldWidget\ShortcodeFieldWidget( $this->_application, $name );
		}
	}

	public function fieldGetRendererNames() {
		return array( 'wp_post_content', 'wp_term_description', 'wp_file', 'wp_gallery', 'wp_post_reference', 'wp_shortcode' );
	}

	public function fieldGetRenderer( $name ) {
		switch ( $name ) {
			case 'wp_post_content':
				return new FieldRenderer\PostContentFieldRenderer( $this->_application, $name );
			case 'wp_term_description':
				return new FieldRenderer\TermDescriptionFieldRenderer( $this->_application, $name );
			case 'wp_file':
				return new FieldRenderer\FileFieldRenderer( $this->_application, $name );
			case 'wp_gallery':
				return new FieldRenderer\GalleryFieldRenderer( $this->_application, $name );
			case 'text':
				return new FieldRenderer\TextFieldRenderer( $this->_application, $name );
			case 'wp_post_reference':
				return new FieldRenderer\PostReferenceFieldRenderer( $this->_application, $name );
			case 'wp_shortcode':
				return new FieldRenderer\ShortcodeFieldRenderer( $this->_application, $name );
		}
	}

	public function fieldGetFilterNames() {
		return array( 'wp_image', 'wp_file' );
	}

	public function fieldGetFilter( $name ) {
		switch ( $name ) {
			case 'wp_file':
				return new FieldFilter\FileFieldFilter( $this->_application, $name );
			case 'wp_image':
				return new FieldFilter\ImageFieldFilter( $this->_application, $name );
		}
	}

	public function onFieldRenderersFilter( &$renderers ) {
		$renderers['text'] = $this->_name;
	}

	public function onCorePlatformWordPressInit() {
		$this->_registerContentTypes();

		// Post/Term hooks
		add_filter( 'post_type_link', array( $this, 'postTypeLinkFilter' ), 30, 4 );
		add_filter( 'term_link', array( $this, 'termLinkFilter' ), 10, 3 );
		add_action( 'trashed_post', array( $this, 'trashedPostAction' ) );
		add_action( 'untrashed_post', array( $this, 'untrashedPostAction' ) );

		// Enable fetching custom field values through get_xxx_meta() functions
		add_filter( 'get_post_metadata', array( $this->_application, 'WordPressContent_Metadata_post' ), 10, 4 );
		add_filter( 'get_term_metadata', array( $this->_application, 'WordPressContent_Metadata_term' ), 10, 4 );
		add_filter( 'update_post_metadata', array( $this->_application, 'WordPressContent_Metadata_updatePost' ), 10, 5 );
		add_filter( 'update_term_metadata', array( $this->_application, 'WordPressContent_Metadata_updateTerm' ), 10, 5 );

		// Enable querying posts by custom fields through WP_Query
		new Query( $this->_application );

		// Hide comments related functions for drts post types
		add_filter( 'comments_open', array( $this, 'commentsOpenFilter' ), 10, 2 );
		add_filter( 'comments_template', array( $this, 'commentsTemplateFilter' ) );
		add_action( 'comment_post', array( $this, 'commentPostAction' ), 10, 2 );
		add_action( 'comment_unapproved_to_approved', array( $this, 'commentUnapprovedToApprovedAction' ) );

		// Add image size
		add_image_size( 'drts_icon', 32, 32, true );
		add_image_size( 'drts_icon_lg', 48, 48, true );
		add_image_size( 'drts_icon_xl', 80, 80, true );
		add_image_size( 'drts_thumbnail', 240, 180, true );
		add_image_size( 'drts_thumbnail_scaled', 240, 180, false );

		// Init Rest API
		add_action( 'rest_api_init', array( $this->_application, 'WordPressContent_RestApi_init' ) );

		// Add field values to Relevanssi index
		add_filter( 'relevanssi_content_to_index', array( $this, 'relevanssiContentToIndex' ), 10, 2 );

		// AMP
		add_filter( 'amp_skip_post', array( $this, 'ampSkipPostFilter' ), 10, 3 );

		// BNFW
		$this->_application->WordPressContent_Bnfw();

		// Body tag classes
		add_filter( 'body_class', array( $this, 'onBodyClassFilter' ) );

		if ( ! function_exists( 'is_plugin_active' ) ) {
			require ABSPATH . 'wp-admin/includes/plugin.php';
		}

		if ( is_admin() ) {
			if ( ! Request::isAjax() ) {
				// Add pending post counts in sidebar
				if ( apply_filters( 'drts_wordpress_show_pending_post_counts', true ) ) {
					add_filter( 'add_menu_classes', array( $this->_application, 'WordPressContent_AddPendingCountsToMenu' ) );
				}
			}
		} else {
			add_shortcode( 'drts-entity', array( $this->_application, 'WordPressContent_DoShortcode' ) );
			add_filter( 'pre_handle_404', array( $this, 'preHandle404Filter' ), 10, 2 );

			// WordPress SEO
			add_filter(
				'wpseo_json_ld_output',
				function ( $data ) {
					if ( isset( $GLOBALS['drts_entity'] )
					&& ( $bundle = $this->_application->Entity_Bundle( $GLOBALS['drts_entity'] ) )
					&& ! empty( $bundle->info['entity_schemaorg']['type'] )
					) {
						return array();
					}
					return $data;
				}
			);
		}

		// WP All Import
		if ( is_admin()
			|| php_sapi_name() === 'cli'
			|| isset( $_GET['import_key'] )
		) {
			if ( is_plugin_active( 'wp-all-import/plugin.php' )
				|| is_plugin_active( 'wp-all-import-pro/wp-all-import-pro.php' )
			) {
				new CSV\WPAllImport\Importer( $this->_application, $this->getPostTypeNames() );
			}
		}

		// Load theme specific CSS file if any
		$theme = $this->_application->getPlatform()->getThemeSlug();
		if ( $theme === 'divi' ) {
			// Fixes issue with "Grab the first post image" option in Divi
			add_action(
				'drts_wordpress_wp_action',
				function () {
					add_filter( 'et_grab_image_setting', '__return_false' );
				}
			);
		}

		// Category Order and Taxonomy Terms Order plugin
		if ( is_plugin_active( 'taxonomy-terms-order/taxonomy-terms-order.php' ) ) {
			add_filter(
				'drts_entity_terms_sort',
				function ( $sort, $bundle ) {
					if ( ! empty( $bundle->info['is_hierarchical'] ) ) {
						$sort['field']     = array( __CLASS__, 'ttoEntityTermsSortFilter' );
						$sort['is_custom'] = true;
					}
					return $sort;
				},
				10,
				2
			);
			add_action(
				'tto/update-order',
				function () {
					$this->_application->Entity_TaxonomyTerms_clearCache();
				}
			);
			add_filter(
				'drts_entity_sorts',
				function ( $sorts, $bundleName ) {
					if ( ( $bundle = $this->_application->Entity_Bundle( $bundleName ) )
					&& ! empty( $bundle->info['is_hierarchical'] )
					) {
						$sorts['tto_order'] = array(
							'label'    => apply_filters( 'drts_wordpress_tto_order_label', __( 'Custom', 'directories-pro' ), array( $bundleName ) ),
							'callback' => array( __CLASS__, 'ttoEntityTermsSortFilter' ),
						);
					}
					return $sorts;
				},
				10,
				2
			);
		}

		// Register Elementor Pro dynamic tags
		if ( is_plugin_active( 'elementor-pro/elementor-pro.php' ) ) {
			add_action(
				'elementor/dynamic_tags/register_tags',
				function ( $dynamic_tags ) {
					\Elementor\Plugin::$instance->dynamic_tags->register_group(
						'drts',
						array(
							'title' => 'Directories',
						)
					);
					$namespace = __NAMESPACE__ . '\Elementor';
					foreach ( array( 'Date', 'File', 'Gallery', 'Image', 'Number', 'Text', 'Url' ) as $name ) {
						$dynamic_tags->register_tag( $namespace . '\\' . $name . 'DynamicTag' );
					}
				}
			);
		}

		// The SEO Framework
		if ( is_plugin_active( 'autodescription/autodescription.php' ) ) {
			add_filter(
				'the_seo_framework_post_meta',
				function ( $meta, $postId ) {
					remove_filter( 'get_post_metadata', array( $this->_application, 'WordPressContent_Metadata_post' ), 10 );
					foreach ( get_post_meta( $postId ) as $key => $value ) {
						$meta[ $key ] = $value[0];
					}
					add_filter( 'get_post_metadata', array( $this->_application, 'WordPressContent_Metadata_post' ), 10, 4 );
					return $meta;
				},
				10,
				2
			);
		}

		// Prevent redirection loop with Members plugin
		if ( is_plugin_active( 'members/members.php' ) ) {
			add_filter(
				'members_is_private_page',
				function ( $ret ) {
					if ( $ret
					&& $this->_application->isComponentLoaded( 'FrontendSubmit' )
					&& ( $slug = $this->_application->getComponent( 'FrontendSubmit' )->hasCustomLoginRegistrationPage() )
					&& $slug === get_post_field( 'post_name' )
					) {
						$ret = false;
					}
					return $ret;
				}
			);
		}

		// Enable ACF field shortcode in block themes
		add_filter( 'acf/shortcode/allow_in_block_themes_outside_content', '__return_true' );

		// Yoast Duplicate Post plugin
		if ( is_plugin_active( 'duplicate-post/duplicate-post.php' ) ) {
			add_action(
				'dp_duplicate_post',
				function ( $new_post_id, $post, $status ) {
					if ( in_array( $post->post_type, $this->getPostTypeNames() )
					&& ( $new_entity = $this->_application->Entity_Entity( 'post', $new_post_id ) )
					&& ( $old_entity = $this->_application->Entity_Entity( 'post', $post->ID ) )
					) {
						$this->_application->Entity_Save( $new_entity, $old_entity->getFieldValues() );
					}
				},
				10,
				3
			);
		}
	}

	public function preHandle404Filter( $stop, $wp_query ) {
		if ( ! $wp_query->posts
			&& ( $post_type = @$wp_query->query_vars['post_type'] )
			&& is_string( $post_type )
			&& isset( $this->_postTypes[ $post_type ] )
			&& isset( $wp_query->query_vars['name'] )
			&& strlen( $wp_query->query_vars['name'] )
			&& ( $bundle = $this->_application->Entity_Bundle( $post_type ) )
			&& ! empty( $bundle->info['taxonomies'] )
		) {
			// See if taxonomy term exists
			foreach ( $bundle->info['taxonomies'] as $taxonomy_bundle_name ) {
				if ( $taxonomy_bundle = $this->_application->Entity_Bundle( $taxonomy_bundle_name ) ) {
					query_posts( array( $taxonomy_bundle->name => $wp_query->query_vars['name'] ) );
					$GLOBALS['wp_the_query'] = $GLOBALS['wp_query'];
					if ( get_queried_object() ) {
						// Taxonomy term exists, do not return 404
						$stop = true;
						break;
					}
				}
			}
		}
		return $stop;
	}

	public static function ttoEntityTermsSortFilter( $order, $tableName ) {
		return $tableName . '.term_order ' . $order;
	}

	public function entityGetTypeNames() {
		return array( 'post', 'term' );
	}

	public function entityGetType( $name ) {
		switch ( $name ) {
			case 'post':
				return new EntityType\PostEntityType( $this->_application, $name );
			case 'term':
				return new EntityType\TermEntityType( $this->_application, $name );
		}
	}

	public function onDirectoryAdminSettingsFormFilter( &$form ) {
		// Moved from Directory to System component
		$this->onSystemAdminSettingsFormFilter( $form );
	}

	public function onSystemAdminSettingsFormFilter( &$form ) {
		if ( $slugs = $this->_application->System_Slugs( null, 'Directory' ) ) {
			$_slugs = array();
			foreach ( array_keys( $slugs ) as $component_name ) {
				$_slugs += $slugs[ $component_name ];
			}
			$form['tabs'][ $this->_name ]   = array(
				'#title'  => __( 'Pages', 'directories-pro' ),
				'#weight' => 95,
			);
			$form['fields'][ $this->_name ] = array(
				'#tab'   => $this->_name,
				'#title' => __( 'Page Settings', 'directories-pro' ),
			) + $this->_application->WordPress_PageSettingsForm( $_slugs, array( 'wordpress_pages' ) );
		}
	}

	protected function _registerContentTypes( $force = false ) {
		$content_types     = $this->_application->WordPressContent_ContentTypes_register( $force );
		$this->_postTypes  = $content_types['post_types'];
		$this->_taxonomies = $content_types['taxonomies'];

		if ( $this->_application->getPlatform()->isFullSiteEditorEnabled() ) {
			$this->_application->WordPressContent_ContentTypes_registerTemplates();
		}
	}

	public function getPostTypeNames() {
		return array_keys( $this->_postTypes );
	}

	public function getTaxonomyNames() {
		return array_keys( $this->_taxonomies );
	}

	public function hasPostType( $postType ) {
		return isset( $this->_postTypes[ $postType ] ) ? $this->_postTypes[ $postType ] : false;
	}

	public function hasTaxonomy( $taxonomy ) {
		return isset( $this->_taxonomies[ $taxonomy ] ) ? $this->_taxonomies[ $taxonomy ] : false;
	}

	public function commentsOpenFilter( $open, $postId ) {
		if ( $open ) {
			// Allow comments if wpDiscuz is active
			if ( class_exists( '\WpdiscuzCore', false )
				&& ( ! isset( $GLOBALS['drts_entity'] ) // this may not be set when WpdiscuzHelper::isLoadWpdiscuz() called
					|| $GLOBALS['drts_entity']->getId() === $postId
				)
			) {
				return $open;
			}

			if ( ! is_admin()
				&& ! isset( $_POST['comment'] ) // make sure not submitting a comment
				&& ! isset( $_POST['wc_comment'] ) // make sure not submitting a comment through wpDiscuz
				&& ! isset( $_POST['drts'] ) // make sure not submitting content
				&& ( $post_type = get_post_type( $postId ) )
				&& $this->hasPostType( $post_type )
				&& ! Display\Helper\RenderHelper::isRendering( $post_type )
			) {
				$open = false;
			}
		}

		return $open;
	}

	public function commentsTemplateFilter( $file ) {
		// Disable comments if not currently rendering a display for the post
		if ( isset( $GLOBALS['post'] )
			&& $this->hasPostType( $GLOBALS['post']->post_type )
			&& ! Display\Helper\RenderHelper::isRendering( $GLOBALS['post']->post_type )
		) {
			$file = __DIR__ . '/comments_template.php';
			remove_all_filters( 'comments_template' );
		}
		return $file;
	}

	public function commentPostAction( $commentId, $commentApproved ) {
		if ( $commentApproved
			&& ( $comment = get_comment( $commentId ) )
			&& ( $post = get_post( $comment->comment_post_ID ) )
			&& $this->hasPostType( $post->post_type )
			&& ( $entity = $this->_application->Entity_Entity( 'post', $post->ID ) )
		) {
			$this->_application->Action( 'wordpresscontent_comment_published', array( $comment, $entity ) );
		}
	}

	public function commentUnapprovedToApprovedAction( $comment ) {
		if ( ( $post = get_post( $comment->comment_post_ID ) )
			&& $this->hasPostType( $post->post_type )
			&& ( $entity = $this->_application->Entity_Entity( 'post', $post->ID ) )
		) {
			$this->_application->Action( 'wordpresscontent_comment_published', array( $comment, $entity ) );
		}
	}

	public function onCorePlatformWordPressAdminInit() {
		new AdminContent( $this->_application, $this->_postTypes, $this->_taxonomies );
		// BNFW plugin
		add_action( 'bnfw_after_notification_options', array( $this->_application, 'WordPressContent_Bnfw_afterNotificationOptions' ), 10, 3 );
		// Personal data exporter/eraser
		add_filter( 'wp_privacy_personal_data_exporters', array( $this, 'wpPrivacyPersonalDataExportersFilter' ) );
		add_filter( 'wp_privacy_personal_data_erasers', array( $this, 'wpPrivacyPersonalDataErasersFilter' ) );
	}

	public function postTypeLinkFilter( $url, $post, $leavename, $sample ) {
		if ( ! get_option( 'permalink_structure' ) ) {
			return $url;
		}

		$post_type = get_post_type( $post );
		if ( $this->hasPostType( $post_type )
			&& ( $entity = $this->_application->Entity_Entity( 'post', $post->ID ) )
		) {
			$url = $this->_application->Entity_PermalinkUrl( $entity );
		}
		return $url;
	}

	public function termLinkFilter( $url, $term, $taxonomy ) {
		if ( ! get_option( 'permalink_structure' )
			|| ! $this->hasTaxonomy( $taxonomy )
			|| ( ! $entity = $this->_application->Entity_Entity( 'term', $term->term_id ) )
		) {
			return $url;
		}

		$alt_bundle = null;
		if ( is_admin()
			&& ! empty( $_REQUEST['post_type'] )
			&& $this->hasPostType( $_REQUEST['post_type'] )
			&& ( $real_taxonomy_bundle = $this->_application->Entity_Bundle_isTaxonomyAliased( $taxonomy, $_REQUEST['post_type'] ) )
		) {
			$alt_bundle = $real_taxonomy_bundle;
		}
		return $this->_application->Entity_PermalinkUrl( $entity, '', null, array(), $alt_bundle );
	}

	public function onEntityCreateBundlesCommitted( $bundles, $bundlesInfo ) {
		// Add default perms to all roles
		$default_caps = $all_caps = $default_guest_caps = $role_caps = array();
		foreach ( $bundles as $bundle ) {
			if ( ! $perms = $this->_application->Entity_Permissions( $bundle ) ) {
				continue;
			}

			foreach ( $perms as $perm => $perm_info ) {
				$cap              = 'drts_' . $perm . '_' . $bundle->name;
				$all_caps[ $cap ] = 1;
				if ( ! empty( $perm_info['default'] ) ) {
					$default_caps[ $cap ] = 1;
					if ( ! empty( $perm_info['guest_allowed'] ) ) {
						$default_guest_caps[ $cap ] = 1;
					}
				}
			}
			if ( isset( $bundlesInfo[ $bundle->type ]['permissions'] ) ) {
				foreach ( array_keys( $bundlesInfo[ $bundle->type ]['permissions'] ) as $role_name ) {
					if ( ! isset( $role_caps[ $role_name ] ) ) {
						$role_caps[ $role_name ] = array();
					}
					foreach ( $bundlesInfo[ $bundle->type ]['permissions'][ $role_name ] as $perm ) {
						$cap                             = 'drts_' . $perm . '_' . $bundle->name;
						$role_caps[ $role_name ][ $cap ] = 1;
					}
				}
				if ( isset( $role_caps['_guest_'] ) ) {
					if ( ! isset( $guest_caps ) ) {
						$guest_caps = array();
					}
					$guest_caps += $role_caps['_guest_'];
					unset( $role_caps['_guest_'] );
				}
			}
		}
		if ( ! empty( $all_caps ) ) {
			foreach ( array_keys( $this->_application->getPlatform()->getRoles() ) as $role_name ) {
				$role = get_role( $role_name );
				if ( $role->has_cap( DRTS_WORDPRESS_ADMIN_CAPABILITY )
					|| $role->has_cap( 'manage_directories' )
				) {
					$caps = array_keys( $all_caps );
				} elseif ( isset( $role_caps[ $role_name ] ) ) {
					$caps = array_keys( $role_caps[ $role_name ] );
				} else {
					$caps = array_keys( $default_caps );
				}
				foreach ( $caps as $cap ) {
					$role->add_cap( $cap );
				}
			}
			if ( ! isset( $guest_caps ) ) {
				$guest_caps = $default_guest_caps;
			}
			if ( ! empty( $guest_caps ) ) {
				// Update guest perms
				$current_guest_caps = $this->_application->getPlatform()->getOption( 'guest_permissions', array() );
				$this->_application->getPlatform()->setOption( 'guest_permissions', $guest_caps + $current_guest_caps );
			}
		}

		$this->_application->WordPressContent_ContentTypes_clearCache();
	}

	public function onEntityUpdateBundlesCommitted( $bundles ) {
		$this->_application->WordPressContent_ContentTypes_clearCache();
	}

	public function onEntityAfterCreatePostEntity( $bundle, $entity, $values, $extraArgs ) {
		$this->_maybeSetTerms( $bundle, $entity, $values, $extraArgs );
		$this->_maybeAssociateEntityImage( $bundle, $entity, $values, true );
	}

	public function onEntityAfterUpdatePostEntity( $bundle, $entity, $oldEntity, $values, $extraArgs ) {
		$this->_maybeSetTerms( $bundle, $entity, $values, $extraArgs );
		$this->_maybeAssociateEntityImage( $bundle, $entity, $values );
	}

	public function onEntityFieldValuesCopied( $bundle, $entity, $values, $isNew ) {
		$this->_maybeSetTerms( $bundle, $entity, $values );
		$this->_maybeAssociateEntityImage( $bundle, $entity, $values, $isNew );
	}

	protected function _isPostTypeAdmin( $bundle ) {
		return is_admin()
			&& $this->hasPostType( $bundle->name )
			&& isset( $GLOBALS['pagenow'] )
			&& $GLOBALS['pagenow'] === 'post.php';
	}

	/**
	 * Sync taxonomy terms selected with that of WordPress
	 */
	protected function _maybeSetTerms( $bundle, $entity, $values, array $extraArgs = array() ) {
		if ( ! empty( $extraArgs['wordpress_skip_set_terms'] ) ) {
			return;
		}

		if ( empty( $bundle->info['taxonomies'] ) ) {
			return;
		}

		if ( $this->_application->getPlatform()->isAdmin() ) {
			$current_screen = get_current_screen();
			// Return if not on directories backend page
			if ( strpos( $current_screen->id, 'toplevel_page_drts/directories' ) !== 0 ) {
				return;
			}
		}

		foreach ( $bundle->info['taxonomies'] as $taxonomy_bundle_type => $taxonomy ) {
			if ( ! isset( $values[ $taxonomy_bundle_type ] ) ) {
				continue;
			}

			$term_ids = array();
			foreach ( $values[ $taxonomy_bundle_type ] as $value ) {
				if ( ! empty( $value['auto'] ) ) {
					continue;
				}

				$term_ids[] = (int) $value['value']; // must be int otherwise numeric terms are created
			}
			wp_set_object_terms( $entity->getId(), $term_ids, $taxonomy );
		}
	}

	protected function _maybeAssociateEntityImage( $bundle, $entity, $values, $isNew = false ) {
		foreach ( $this->_application->Entity_Field( $bundle ) as $field ) {
			if ( ! in_array( $field->getFieldType(), array( 'wp_file', 'wp_image' ) )
				|| ! isset( $values[ $field->getFieldName() ] )
			) {
				continue;
			}

			if ( ! $isNew ) {
				$posts = get_posts(
					array(
						'post_type'  => 'attachment',
						'meta_query' => array(
							'relation' => 'AND',
							array(
								'key'   => '_drts_entity_id',
								'value' => $entity->getId(),
							),
							array(
								'key'   => '_drts_entity_type',
								'value' => $entity->getType(),
							),
							array(
								'key'   => '_drts_field',
								'value' => $field->getFieldName(),
							),
						),
					)
				);
				foreach ( $posts as $post ) {
					// Unattach currently attached
					wp_update_post(
						array(
							'ID'          => $post->ID,
							'post_parent' => 0,
						)
					);
					delete_post_meta( $post->ID, '_drts_entity_id' );
					delete_post_meta( $post->ID, '_drts_entity_type' );
					delete_post_meta( $post->ID, '_drts_field' );
				}
			}

			foreach ( $values[ $field->getFieldName() ] as $value ) {
				if ( $entity->getType() === 'post' ) {
					wp_update_post(
						array(
							'ID'          => $value['attachment_id'],
							'post_parent' => $entity->getId(),
						)
					);
				}
				update_post_meta( $value['attachment_id'], '_drts_entity_type', $entity->getType() );
				update_post_meta( $value['attachment_id'], '_drts_entity_id', $entity->getId() );
				update_post_meta( $value['attachment_id'], '_drts_field', $field->getFieldName() );
			}
		}

		/*
		if ($bundle->entitytype_name !== 'post'
			|| empty($bundle->info['entity_image'])
		) return;

		$image_field = $bundle->info['entity_image'];
		if (!isset($values[$image_field])) return;

		$meta_key = '_entity_id_' . $image_field;

		if (!$isNew) {
			$posts = get_posts([
				'post_type' => 'attachment',
				'meta_key' => $meta_key,
				'meta_value' => $entity->getId(),
			]);
			foreach ($posts as $post) {
				// Unattach currently attached
				wp_update_post([
					'ID' => $post->ID,
					'post_parent' => 0,
				]);
				delete_post_meta($post->ID, $meta_key);
			}
		}

		// Attach
		foreach ($values[$image_field] as $value) {
			wp_update_post([
				'ID' => $value['attachment_id'],
				'post_parent' => $entity->getId(),
			]);
			update_post_meta($value['attachment_id'], $meta_key, $entity->getId());
		}
		*/
	}

	public function trashedPostAction( $postId ) {
		$this->_trashPost( $postId );
	}

	public function untrashedPostAction( $postId ) {
		$this->_trashPost( $postId, false );
	}

	protected function _trashPost( $postId, $trash = true ) {
		static $processing = array();

		if ( ( ! $post = get_post( $postId ) )
			|| ( ! $post_type = $this->hasPostType( $post->post_type ) )
		) {
			return;
		}

		$processing[ $postId ] = true;

		if ( ! empty( $post_type['children'] ) ) {
			if ( $trash ) {
				$func              = 'wp_trash_post';
				$child_post_status = 'any';
			} else {
				$func              = 'wp_untrash_post';
				$child_post_status = 'trash';
			}
			foreach ( $post_type['children'] as $child_post_type ) {
				foreach ( get_children(
					array(
						'post_parent' => $post->ID,
						'post_type'   => $child_post_type,
						'post_status' => $child_post_status,
					)
				) as $child_post ) {
					$func( $child_post->ID );
				}
			}
			// Invoke entity updated events with new status and then update own status
			if ( $entity = $this->_maybeInvokeEntityUpdatedEvents( $post ) ) {
				$this->_application->getComponent( 'Entity' )->updateParentPostStats( $entity, true, true, true );
			}
		} elseif ( ! empty( $post_type['parent'] ) ) {
			// Invoke entity updated events with new status
			if ( $entity = $this->_maybeInvokeEntityUpdatedEvents( $post ) ) {
				// Update parent post status
				if ( ( $parent_id = $entity->getParentId() )
					&& empty( $processing[ $parent_id ] ) // do not update if trashing/untrashing parent
					&& ( $parent_entity = $this->_application->Entity_Entity( 'post', $parent_id ) )
				) {
					// Update parent stats
					$this->_application->getComponent( 'Entity' )->updateParentPostStats( $parent_entity, true, true, true );
				}
			}
		}
	}

	protected function _maybeInvokeEntityUpdatedEvents( $post ) {
		if ( ( ! $entity = $this->_application->Entity_Entity( 'post', $post->ID, false ) )
			|| ( ! $bundle = $this->_application->Entity_Bundle( $entity ) )
		) {
			return;
		}

		$this->_application->Entity_Field_load( $entity, null, true );
		// Create old entity with old status
		$old_entity = clone $entity;
		$old_entity->setStatus( $post->post_status === 'trash' ? 'publish' : 'trash' ); // @todo get real previous status
		// Notify that the status of entity has changed
		$this->_application->Entity_Save_invokeEvents(
			'post',
			$entity->getBundleType(),
			array( $bundle, $entity, $old_entity, array( 'status' => $post->post_status ), array() ),
			'update',
			'success'
		);
		return $entity;
	}

	public function onEntityFormTaxonomySelectorFilter( &$selector, $bundle, $taxonomyBundleType ) {
		if ( $bundle->entitytype_name === 'post' ) {
			// Add selector for admin add page
			$selector .= ',input[name="tax_input[' . $bundle->info['taxonomies'][ $taxonomyBundleType ] . '][]"]';
		}
	}

	public function onEntityFormTaxonomyValuesFilter( &$values, $bundle, $taxonomyBundleType ) {
		if ( $bundle->entitytype_name === 'post'
			&& isset( $bundle->info['taxonomies'][ $taxonomyBundleType ] )
			&& $this->_isPostTypeAdmin( $bundle )
		) {
			$taxonomy_name = $bundle->info['taxonomies'][ $taxonomyBundleType ];
			$values        = empty( $_POST['tax_input'][ $taxonomy_name ] ) ? array() : $_POST['tax_input'][ $taxonomy_name ];
		}
	}

	public function onEntityStorageQueryFilter( &$parsed, $entityType, $fieldQuery, $lang ) {
		if ( ( $entityType !== 'post' && $entityType !== 'term' )
			|| ( ! $i18n = $this->_application->getPlatform()->getI18n() )
			|| ( ! $bundle_name = $fieldQuery->getQueriedBundleName() )
		) {
			return;
		}

		if ( is_array( $bundle_name )
			&& count( $bundle_name ) === 1
		) {
			$bundle_name = $bundle_name[0];
		}

		if ( ! is_array( $bundle_name ) ) {
			if ( ! $this->_application->getPlatform()->isTranslatable( $entityType, $bundle_name ) ) {
				return;
			}
		} else {
			// @todo Figure out how to handle multiple bundles with both translatable and non-translatable
		}

		$db = $this->_application->getDB();

		switch ( $i18n ) {
			case 'wpml':
				$parsed['table_joins'] .= sprintf(
					' LEFT JOIN %sicl_translations icl_t ON icl_t.element_id = %s',
					$db->getConnection()->getWpdb()->prefix,
					$entityType === 'term' ? 'tt.term_taxonomy_id' : $parsed['table_id_column']
				);
				if ( is_array( $bundle_name ) ) {
					$parsed['criteria'] .= ' AND icl_t.element_type LIKE ' . $db->escapeString( $entityType === 'term' ? 'tax_%' : 'post_%' );
				} else {
					$parsed['criteria'] .= ' AND icl_t.element_type = ' . $db->escapeString( ( $entityType === 'term' ? 'tax_' : 'post_' ) . $bundle_name );
				}
				if ( isset( $lang ) ) {
					$parsed['criteria'] .= ' AND icl_t.language_code = ' . $db->escapeString( $lang );
				} else {
					$parsed['criteria'] .= ' AND (icl_t.language_code = ' . $db->escapeString( $this->_application->getPlatform()->getCurrentLanguage() ) . ' OR icl_t.language_code IS NULL)';
				}
				break;
			case 'polylang':
				if ( $entityType === 'post' ) {
					$parsed['table_joins'] .= sprintf(
						' INNER JOIN %1$sterm_relationships pll_tr ON pll_tr.object_id = %2$s INNER JOIN %1$sterm_taxonomy pll_tt ON pll_tt.term_taxonomy_id = pll_tr.term_taxonomy_id INNER JOIN %1$sterms pll_t ON pll_t.term_id = pll_tt.term_id',
						$db->getConnection()->getWpdb()->prefix,
						$parsed['table_id_column']
					);
					$parsed['criteria']    .= ' AND pll_tt.taxonomy = ' . $db->escapeString( 'language' ) . ' AND pll_t.slug = ' . $db->escapeString( isset( $lang ) ? $lang : $this->_application->getPlatform()->getCurrentLanguage() );
				} else {
					$parsed['table_joins'] .= sprintf(
						' INNER JOIN %1$sterm_relationships pll_tr ON pll_tr.object_id = %2$s INNER JOIN %1$sterm_taxonomy pll_tt ON pll_tt.term_taxonomy_id = pll_tr.term_taxonomy_id INNER JOIN %1$sterms pll_t ON pll_t.term_id = pll_tt.term_id',
						$db->getConnection()->getWpdb()->prefix,
						'tt.term_taxonomy_id'
					);
					$parsed['criteria']    .= ' AND pll_tt.taxonomy = ' . $db->escapeString( 'term_language' ) . ' AND pll_t.slug = ' . $db->escapeString( 'pll_' . ( isset( $lang ) ? $lang : $this->_application->getPlatform()->getCurrentLanguage() ) );
				}
				break;
		}
	}

	public function displayGetElementNames( Bundle $bundle ) {
		return empty( $bundle->info['public'] ) || $bundle->entitytype_name !== 'post' ? array() : array( 'wp_comments', 'wp_acf' );
	}

	public function displayGetElement( $name ) {
		switch ( $name ) {
			case 'wp_comments':
				return new DisplayElement\CommentsDisplayElement( $this->_application, $name );
			case 'wp_acf':
				return new DisplayElement\AcfDisplayElement( $this->_application, $name );
		}
	}

	public function displayGetStatisticNames( Bundle $bundle ) {
		if ( empty( $bundle->info['public'] ) || $bundle->entitytype_name !== 'post' ) {
			return array();
		}

		$ret = array( 'wp_comments' );
		if ( DisplayStatistic\PostViewsDisplayStatistic::getSources() ) {
			$ret[] = 'wp_post_views';
		}

		return $ret;
	}

	public function displayGetStatistic( $name ) {
		switch ( $name ) {
			case 'wp_comments':
				return new DisplayStatistic\CommentsDisplayStatistic( $this->_application, $name );
			case 'wp_post_views':
				return new DisplayStatistic\PostViewsDisplayStatistic( $this->_application, $name );
		}
	}

	public function onEntityCreatePostEntitySuccess( $bundle, $entity, $values, $extraArgs ) {
		if ( ! is_admin() ) {
			$this->_application->WordPressContent_Util_maybeSetPostThumbnail( $bundle, $entity );
		}
	}

	public function onEntityUpdatePostEntitySuccess( $bundle, $entity, $oldEntity, $values, $extraArgs ) {
		if ( ! is_admin() ) {
			$this->_application->WordPressContent_Util_maybeSetPostThumbnail( $bundle, $entity );
		}
	}

	public function onEntityCreateTermEntitySuccess( $bundle, $entity, $values, $extraArgs ) {
		$this->_application->WordPressContent_Util_maybeSetTermThumbnail( $bundle, $entity );
	}

	public function onEntityUpdateTermEntitySuccess( $bundle, $entity, $oldEntity, $values, $extraArgs ) {
		$this->_application->WordPressContent_Util_maybeSetTermThumbnail( $bundle, $entity );
	}

	public function ampSkipPostFilter( $skip, $postId, $post ) {
		return $this->hasPostType( $post->post_type );
	}

	public function onEntityAdminBundleSettingsSaved( $bundle, $oldBundleInfo ) {
		$this->_application->WordPressContent_ContentTypes_clearCache();

		if ( $oldBundleInfo['slug'] !== $bundle->info['slug'] ) {
			$this->_application->WordPress_PageSettingsForm_reload();
		}

		$flush_rewrite_rules = false;
		if ( $oldBundleInfo['slug'] !== $bundle->info['slug']
			|| $oldBundleInfo['permalink_path'] !== $bundle->info['permalink_path']
			|| ! isset( $oldBundleInfo['permalink_type'] )
			|| $oldBundleInfo['permalink_type'] !== $bundle->info['permalink_type']
			|| $oldBundleInfo['wordpress_page'] !== $bundle->info['wordpress_page']
		) {
			$flush_rewrite_rules = true;
		}
		if ( $bundle->info['permalink_type'] === '114compat' ) {
			if ( ! isset( $oldBundleInfo['permalink_slug_114'] )
				|| $oldBundleInfo['permalink_slug_114'] !== $bundle->info['permalink_slug_114']
			) {
				$flush_rewrite_rules = true;
			}
		}
		if ( $flush_rewrite_rules ) {
			$this->_application->getPlatform()->flushRewriteRules();
		}
	}

	public function onFakerAdminGenerateTitleFilter( $title, $context, $bundle, $titleType ) {
		$this->_filterAdminTitle( $context, $bundle, $titleType );
	}

	public function onCsvAdminImportTitleFilter( $title, $context, $bundle, $titleType ) {
		$this->_filterAdminTitle( $context, $bundle, $titleType );
	}

	public function onCsvAdminExportTitleFilter( $title, $context, $bundle, $titleType ) {
		$this->_filterAdminTitle( $context, $bundle, $titleType );
	}

	public function onDirectoryAdminDirectorySendEmailTitleFilter( $title, $context, $bundle, $titleType ) {
		$this->_filterAdminTitle( $context, $bundle, $titleType );
	}

	public function onCalendarAdminOccurrencesTitleFilter( $title, $context, $bundle, $titleType ) {
		$this->_filterAdminTitle( $context, $bundle, $titleType );
	}

	protected function _filterAdminTitle( $context, $bundle, $titleType ) {
		if ( $titleType !== Application::ROUTE_TITLE_INFO ) {
			return;
		}

		switch ( $bundle->entitytype_name ) {
			case 'post':
				$url   = admin_url( 'edit.php?post_type=' . $bundle->name );
				$label = get_post_type_object( $bundle->name )->labels->name;
				break;
			case 'term':
				if ( ! $taxonomy = get_taxonomy( $bundle->name ) ) {
					return;
				}
				$url   = admin_url( 'edit-tags.php?taxonomy=' . $bundle->name . '&post_type=' . $taxonomy->object_type[0] );
				$label = get_taxonomy( $bundle->name )->labels->name;
				break;
			default:
				return;
		}
		$context->clearTabs()->clearMenus()->clearInfo()->setInfo( $label, $url );
	}

	public function onWordPressContentINotificationsInstallSuccess( AbstractComponent $component ) {
		$this->_createNotifications( $component );
	}

	public function onWordPressContentINotificationsUpgradeSuccess( AbstractComponent $component ) {
		$this->_createNotifications( $component );
	}

	protected function _createNotifications( $component ) {
		foreach ( $component->wpGetNotificationNames() as $name ) {
			$this->_application->WordPressContent_Notifications_create( $name );
		}
	}

	public function onCsvExportQueryFilter( EntityQuery $query, Bundle $bundle ) {
		if ( $bundle->entitytype_name !== 'post' ) {
			return;
		}

		$query->fieldIsIn( 'status', array( 'publish', 'pending', 'draft', 'future', 'private', 'trash', 'inherit' ) );
	}

	public function onFormBuildDirectoryAdminContentTypes( &$form ) {
		$this->_addContentColumn( $form['content'], $form['#primary_bundle_name'] );
	}

	protected function _addContentColumn( &$form, $primaryBundleName ) {
		$form['#header']['content'] = array(
			'order' => 25,
			'label' => __( 'Content', 'directories-pro' ),
		);
		foreach ( array_keys( $form['#options'] ) as $bundle_name ) {
			if ( ! $bundle = $this->_application->Entity_Bundle( $bundle_name ) ) {
				continue;
			}

			switch ( $bundle->entitytype_name ) {
				case 'post':
					$url    = admin_url( 'edit.php?post_type=' . $bundle->name );
					$counts = wp_count_posts( $bundle->name, 'readable' );
					$count  = $counts->publish + $counts->pending + $counts->draft + $counts->future + $counts->private;
					break;
				case 'term':
					if ( $_bundle = $bundle->isAlias() ) {
						$bundle = $_bundle;
					}
					$url   = admin_url( 'edit-tags.php?taxonomy=' . $bundle->name . '&post_type=' . $primaryBundleName );
					$count = wp_count_terms( $bundle->name, array( 'hide_empty' => false ) );
					break;
				case 'user':
					$url   = admin_url( 'users.php' );
					$count = count_users()['total_users'];
					break;
				default:
					continue 2;
			}
			$form['#options'][ $bundle_name ]['content'] = $this->_application->LinkTo( $count, $url );
		}
	}

	public function onDirectoryAdminDirectoryLinksFilter( &$links, $directory ) {
		$has_permission = false;
		foreach ( $this->_application->Entity_Bundles( null, $directory->name ) as $bundle ) {
			if ( $this->_application->Entity_BundleTypeInfo( $bundle, 'entity_permissions' ) !== false ) {
				$has_permission = true;
				break;
			}
		}
		if ( $has_permission ) {
			$links['settings']['link'][89] = $this->_application->LinkTo(
				__( 'Permissions', 'directories-pro' ),
				$this->_application->Url( '/directories/' . $directory->name . '/permissions' )
			);
		}
	}

	public function onEntityAdminBundleSettingsFormFilter( &$form, $bundle, $submitValues ) {
		if ( empty( $bundle->info['public'] ) ) {
			return;
		}

		if ( ! $this->_application->getPlatform()->isFullSiteEditorEnabled() ) {
			$form['seo']['single']['wordpress_page'] = array(
				'#type'                  => 'item',
				'#title'                 => __( 'Assign page template', 'directories-pro' ),
				'#markup'                => wp_dropdown_pages(
					array(
						'depth'            => 2,
						'echo'             => 0,
						'show_option_none' => __( '— Select page —', 'directories-pro' ),
						'name'             => 'wordpress_page',
						'selected'         => $this->_application->getComponent( 'WordPressContent' )->getBundleSingleItemPageId( $bundle ),
					)
				),
				'#horizontal'            => true,
				'#description'           => sprintf(
					$this->_application->H( __( 'Shortcode %s can be used to customize the content of the page.', 'directories-pro' ) ),
					'<code class="' . DRTS_BS_PREFIX . 'user-select-all">[drts-entity]</code>'
				),
				'#description_no_escape' => true,
				'#weight'                => 20,
				'#js_ready'              => array( '$("#__FORM_ID__ select").toggleClass("' . DRTS_BS_PREFIX . 'form-select", true);' ),
			);
		}

		if ( isset( $form['general']['image'] ) ) {
			$featured_image_desc = sprintf(
				__( 'Enable a featured image for this content type (mainly used by your WordPress theme). You can also use the %s tool to bulk-assign a featured image to existing content items.', 'directories-pro' ),
				$this->_application->LinkTo(
					__( 'Assign featured images', 'directories-pro' ),
					$this->_application->Url( '/directories/system', array( '_drts_form_current_tab' => 'tools' ), 'drts-system-admin-tool-wp_assign_featured_images' )
				)
			);
			if ( $bundle->entitytype_name === 'post' ) {
				$form['general']['image'] += array(
					'wp_post_thumbnail'      => array(
						'#type'          => 'checkbox',
						'#title'         => __( 'Enable featured image', 'directories-pro' ),
						'#horizontal'    => true,
						'#default_value' => ! empty( $bundle->info['wp_post_thumbnail'] ),
						'#description'   => $featured_image_desc,
					),
					'wp_post_thumbnail_auto' => array(
						'#type'          => 'checkbox',
						'#title'         => __( 'Automatically generate featured image', 'directories-pro' ),
						'#horizontal'    => true,
						'#default_value' => ! empty( $bundle->info['wp_post_thumbnail_auto'] ),
						'#states'        => array(
							'visible' => array(
								'[name="entity_image"]' => array(
									'type'  => '!value',
									'value' => '',
								),
								'[name="wp_post_thumbnail"]' => array( 'value' => true ),
							),
						),
						'#description'   => __( 'Check this option to automatically generate a featured image using the first image when submitted from the frontend.', 'directories-pro' ),
					),
				);
			} elseif ( $bundle->entitytype_name === 'term' ) {
				$form['general']['image'] += array(
					'wp_term_thumbnail' => array(
						'#type'          => 'checkbox',
						'#title'         => __( 'Enable featured image', 'directories-pro' ),
						'#horizontal'    => true,
						'#default_value' => ! empty( $bundle->info['wp_term_thumbnail'] ),
						'#description'   => $featured_image_desc,
					),
				);
			}
		}
	}

	public function onDirectoryAdminDirectoryExportSettingsFilter( &$export, $directory ) {
		// Retrieve all caps
		$caps = array();
		foreach ( array_keys( $export['bundles'] ) as $bundle_type ) {
			if ( ( ! $bundle = $this->_application->Entity_Bundle( $bundle_type, $directory->name ) )
				|| ( ! $perms = $this->_application->Entity_Permissions( $bundle ) )
			) {
				continue;
			}

			foreach ( array_keys( $perms ) as $perm ) {
				$caps[ $bundle_type ][ $perm ] = 'drts_' . $perm . '_' . $bundle->name;
			}
		}
		if ( empty( $caps ) ) {
			return;
		}

		// Export role permissions by bundle
		foreach ( array_keys( $this->_application->getPlatform()->getRoles() ) as $role_name ) {
			$role = get_role( $role_name );
			foreach ( array_keys( $caps ) as $bundle_type ) {
				if ( $role->has_cap( DRTS_WORDPRESS_ADMIN_CAPABILITY )
					|| $role->has_cap( 'manage_directories' )
				) {
					$role_perms = array_keys( $caps[ $bundle_type ] );
				} else {
					$role_perms = array();
					foreach ( $caps[ $bundle_type ] as $perm => $cap ) {
						if ( $role->has_cap( $cap ) ) {
							$role_perms[] = $perm;
						}
					}
				}
				$export['bundles'][ $bundle_type ]['permissions'][ $role_name ] = $role_perms;
			}
		}

		// Export guest permissions
		$platform   = $this->_application->getPlatform();
		$prefix_len = strlen( 'drts_' );
		foreach ( array_keys( $caps ) as $bundle_type ) {
			$guest_perms = array();
			foreach ( $caps[ $bundle_type ] as $perm => $cap ) {
				if ( $platform->guestHasPermission( substr( $cap, $prefix_len ) ) ) {
					$guest_perms[] = $perm;
				}
			}
			$export['bundles'][ $bundle_type ]['permissions']['_guest_'] = $guest_perms;
		}
	}

	public function onSearchFieldSettingsFilter( &$form, $bundle, $fieldName, $settings ) {
		// Search taxonomies?
		if ( $fieldName !== 'search_keyword'
			|| empty( $bundle->info['taxonomies'] )
		) {
			return;
		}

		$taxonomy_options = array();
		foreach ( array_keys( $bundle->info['taxonomies'] ) as $taxonomy_bundle_type ) {
			$taxonomy_options[ $taxonomy_bundle_type ] = $this->_application->Entity_BundleTypeInfo( $taxonomy_bundle_type, 'label_singular' );
		}
		$form['taxonomies'] = array(
			'#type'          => 'checkboxes',
			'#title'         => __( 'Search taxonomy term names', 'directories-pro' ),
			'#default_value' => $settings['taxonomies'],
			'#options'       => $taxonomy_options,
			'#weight'        => 6,
			'#horizontal'    => true,
		);
	}

	public function onCoreUninstall( $removeData = false ) {
		// make sure post type and taxonomy names are fetched
		$this->_registerContentTypes( true );
	}

	public function uninstall( $removeData = false ) {
		if ( ! $removeData ) {
			return;
		}

		$this->_deleteContent( $this->getPostTypeNames(), $this->getTaxonomyNames() );
	}

	protected function _deleteContent( array $postTypes, array $taxonomies ) {
		global $wpdb;

		// Delete posts
		if ( ! empty( $postTypes ) ) {
			$post_types = array_map(
				function ( $v ) {
					return "'" . esc_sql( $v ) . "'";
				},
				$postTypes
			);
			$wpdb->query( 'DELETE FROM ' . $wpdb->posts . ' WHERE post_type IN (' . implode( ',', $post_types ) . ');' );
			$wpdb->query( 'DELETE meta FROM ' . $wpdb->postmeta . ' meta LEFT JOIN ' . $wpdb->posts . ' posts ON posts.ID = meta.post_id WHERE posts.ID IS NULL;' );
		}

		// Delete terms
		if ( ! empty( $taxonomies ) ) {
			foreach ( $taxonomies as $taxonomy ) {
				$wpdb->delete( $wpdb->term_taxonomy, array( 'taxonomy' => $taxonomy ) );
				$wpdb->query( 'DELETE tr FROM ' . $wpdb->term_relationships . ' tr LEFT JOIN ' . $wpdb->posts . ' posts ON posts.ID = tr.object_id WHERE posts.ID IS NULL;' );
				$wpdb->query( 'DELETE t FROM ' . $wpdb->terms . ' t LEFT JOIN ' . $wpdb->term_taxonomy . ' tt ON t.term_id = tt.term_id WHERE tt.term_id IS NULL;' );
				$wpdb->query( 'DELETE tm FROM ' . $wpdb->termmeta . ' tm LEFT JOIN ' . $wpdb->term_taxonomy . ' tt ON tm.term_id = tt.term_id WHERE tt.term_id IS NULL;' );
			}
		}
	}

	public function onEntityDeleteBundlesCommitted( array $bundles, $deleteContent ) {
		$this->_application->WordPressContent_ContentTypes_clearCache();

		if ( empty( $deleteContent ) ) {
			return;
		}

		$post_types = $taxonomies = array();
		foreach ( array_keys( $bundles ) as $i ) {
			$bundle_name = $bundles[ $i ]->name;
			if ( ! empty( $bundles[ $i ]->info['is_taxonomy'] ) ) {
				if ( $this->hasTaxonomy( $bundle_name ) ) {
					$taxonomies[] = $bundle_name;
				}
			} elseif ( $this->hasPostType( $bundle_name ) ) {
					$post_types[] = $bundle_name;
			}
		}
		$this->_deleteContent( $post_types, $taxonomies );
	}

	public function relevanssiContentToIndex( $content, $post ) {
		if ( $this->hasPostType( $post->post_type ) ) {
			foreach ( $this->_application->Entity_Field( $post->post_type ) as $field ) {
				if ( ( ! $field_type = $this->_application->Field_Type( $field->getFieldType(), true ) )
					|| ! $field_type instanceof Field\Type\IHumanReadable
					|| ( ! $entity = $this->_application->Entity_Entity( 'post', $post->ID ) )
				) {
					continue;
				}

				$content .= $field_type->fieldHumanReadableText( $field, $entity );
			}
		}
		return $content;
	}

	public function onDirectoryValidateNameFilter( &$true, $name ) {
		if ( ! $true ) {
			return;
		}

		$true = ! post_type_exists( $name . '_dir_ltg' )
			&& ! taxonomy_exists( $name . '_dir_cat' )
			&& ! taxonomy_exists( $name . '_dir_tag' );
	}

	public function onEntityFieldConditionRuleFilter( &$rule, $field, $compare, $value, $name, $type ) {
		switch ( $field->getFieldType() ) {
			case 'entity_terms':
				if ( ! in_array( $rule['type'], array( 'value', '!value', 'one' ) )
					|| ( ( ! $is_admin = is_admin() ) && $type === 'js' )
					|| ( ! $taxonomy_bundle = $this->_application->Entity_Bundle( $field->getFieldName(), $field->Bundle->group ) )
				) {
					return;
				}

				$rule['value'] = (array) $rule['value'];
				if ( $is_admin
					&& $type === 'js'
				) {
					$rule['target'] = '[name="tax_input[' . $taxonomy_bundle->name . '][]"],[id^="in-popular-' . $taxonomy_bundle->name . '-"]';
				}

				// Convert slugs to IDs since terms can be referenced by an ID only
				$slug_keys = array();
				foreach ( array_keys( $rule['value'] ) as $i ) {
					$slug_keys[ $rule['value'][ $i ] ] = $i;
				}
				if ( ! empty( $slug_keys ) ) {
					$terms = get_terms(
						$taxonomy_bundle->name,
						array(
							'hide_empty' => false,
							'slug'       => array_keys( $slug_keys ),
							'fields'     => 'id=>slug',
						)
					);
					if ( ! is_wp_error( $terms ) ) {
						foreach ( $terms as $id => $slug ) {
							if ( isset( $slug_keys[ $slug ] ) ) {
								$value_key                   = $slug_keys[ $slug ];
								$rule['value'][ $value_key ] = (string) $id;
							}
						}
					}
				}
				break;
		}
	}

	public function wpPrivacyPersonalDataExportersFilter( $exporters ) {
		$exporters += $this->_application->WordPressContent_PersonalData_exporters();
		return $exporters;
	}

	public function wpPrivacyPersonalDataErasersFilter( $erasers ) {
		$erasers += $this->_application->WordPressContent_PersonalData_erasers();
		return $erasers;
	}

	public static function getTermTaxonomy( $id ) {
		if ( ! empty( $id )
			&& ( $term = get_term( $id ) )
			&& ! is_wp_error( $term )
		) {
			return $term->taxonomy;
		}
	}

	public function onEntityBundleInfoKeysFilter( &$keys ) {
		$keys[] = 'wp_post_thumbnail';
		$keys[] = 'wp_post_thumbnail_auto';
		$keys[] = 'wp_term_thumbnail';
	}

	public function onBodyClassFilter( $classes ) {
		if ( isset( $GLOBALS['drts_entity'] ) ) {
			$classes = array_merge( $classes, $this->_application->Entity_HtmlClass( $GLOBALS['drts_entity'], true ) );
		}
		return $classes;
	}

	public function onEntityFormFilter( &$form, $bundle, $entity, &$options ) {
		if ( class_exists( '\ACF', false ) ) {
			$form['#submit'][9][] = array( __NAMESPACE__ . '\DisplayElement\AcfDisplayElement', 'validateFormCallback' );
			// Another callback is required to fetch entity submitted
			$form['#submit'][11][] = array( __NAMESPACE__ . '\DisplayElement\AcfDisplayElement', 'submitFormCallback' );
		}
	}

	public function getBundleSingleItemPageId( $bundle ) {
		if ( ( ! $bundle = $this->_application->Entity_Bundle( $bundle ) )
			|| empty( $bundle->info['public'] )
			|| $this->_application->getPlatform()->isFullSiteEditorEnabled()
		) {
			return;
		}

		if ( isset( $bundle->info['wordpress_page'] ) ) {
			return $bundle->info['wordpress_page'];
		}

		// Code below is for compat with <1.4.0
		$page_slugs   = $this->_application->getPlatform()->getPageSlugs();
		$current_slug = null;
		if ( empty( $bundle->info['parent'] ) ) {
			$slug_name = $bundle->group . '-' . $bundle->info['slug'];
			if ( ! isset( $page_slugs[1][ $bundle->component ][ $slug_name ] ) ) {
				return;
			}

			$current_slug = $page_slugs[1][ $bundle->component ][ $slug_name ];
		} else {
			if ( ! $parent_bundle = $this->_application->Entity_Bundle( $bundle->info['parent'] ) ) {
				return;
			}

			// Need to fetch parent slug and then prepend it to get the current slug
			$parent_slug_name = $bundle->group . '-' . $parent_bundle->info['slug'];
			if ( ! isset( $page_slugs[1][ $bundle->component ][ $parent_slug_name ] ) ) {
				return;
			}

			$current_slug = $page_slugs[1][ $bundle->component ][ $parent_slug_name ] . '/' . $bundle->info['slug'];
		}
		if ( ! isset( $page_slugs[2][ $current_slug ] ) ) {
			return;
		}

		return $page_slugs[2][ $current_slug ];
	}

	public function frontendsubmitGetRestrictorNames() {
		return array( 'wp_role', 'wp_woocommerce_memberships', 'wp_memberpress' );
	}

	public function frontendsubmitGetRestrictor( $name ) {
		switch ( $name ) {
			case 'wp_role':
				return new FrontendSubmitRestrictor\RoleFrontendSubmitRestrictor( $this->_application, $name );
			case 'wp_woocommerce_memberships':
				return new FrontendSubmitRestrictor\WooCommerceMembershipsFrontendSubmitRestrictor( $this->_application, $name );
			case 'wp_memberpress':
				return new FrontendSubmitRestrictor\MemberPressFrontendSubmitRestrictor( $this->_application, $name );
		}
	}

	public function systemGetToolNames() {
		return array( 'wp_sync_terms', 'wp_update_database', 'wp_clean_unattached_media_files', 'wp_assign_featured_images' );
	}

	public function systemGetTool( $name ) {
		switch ( $name ) {
			case 'wp_sync_terms':
				return new SystemTool\SyncTermsSystemTool( $this->_application, $name );
			case 'wp_clean_unattached_media_files':
				return new SystemTool\CleanUnattachedMediaFilesSystemTool( $this->_application, $name );
			case 'wp_update_database':
				return new SystemTool\UpdateDatabaseSystemTool( $this->_application, $name );
			case 'wp_assign_featured_images':
				return new SystemTool\AssignFeaturedImagesSystemTool( $this->_application, $name );
		}
	}

	public function onFormBuildViewAdminViews( &$form ) {
		$form['views']['#header']['wp_shortcode'] = array(
			'order' => 35,
			'label' => __( 'Shortcode', 'directories-pro' ),
		);
		foreach ( array_keys( $form['views']['#options'] ) as $view_id ) {
			$form['views']['#options'][ $view_id ]['wp_shortcode'] = '<code class="' . DRTS_BS_PREFIX . 'user-select-all">' . sprintf(
				'[drts-directory-view directory="%1$s"%2$s%3$s]',
				$this->_application->H( $form['#bundle']->group ),
				empty( $form['#bundle']->info['is_primary'] ) ? ' type="' . $this->_application->H( $form['#bundle']->type ) . '"' : '',
				$form['#views'][ $view_id ]->default ? '' : ' name="' . $this->_application->H( $form['#views'][ $view_id ]->name ) . '"'
			) . '</code>';
		}
	}

	public function onEntityTitleFilter( &$title, $entity ) {
		if ( $entity->getType() !== 'post' ) {
			return;
		}

		// Remove unwanted filters
		$filters = array(
			'wptexturize'   => 10,
			'convert_chars' => 10,
		);
		foreach ( $filters as $filter => $priority ) {
			if ( has_filter( 'the_title', $filter ) ) {
				remove_filter( 'the_title', $filter, $priority );
			} else {
				unset( $filters[ $filter ] );
			}
		}

		$title = apply_filters( 'the_title', $title, $entity->getId() );

		// Add back removed filters if any
		foreach ( $filters as $filter => $priority ) {
			add_filter( 'the_title', $filter, $priority );
		}
	}

	/* Start code for setting visibility by user role */

	protected function _hasRole( array $roles, array $current ) {
		if ( ! empty( $roles )
			&& ! empty( $current )
		) {
			foreach ( $current as $current_role ) {
				if ( in_array( $current_role, $roles ) ) {
					return true;
				}
			}
		}

		return false;
	}

	public function onFieldFieldDataFilter( &$fieldData, $bundle, &$data ) {
		if ( ! empty( $data['visibility']['wp_check_role'] )
			&& ! empty( $data['visibility']['wp_roles'] )
		) {
			// Custom field data must start with underscore
			$fieldData['data']['_wp_roles'] = $data['visibility']['wp_roles'];
		} else {
			$fieldData['data']['_wp_roles'] = null;
		}
	}

	public function onEntityFieldWidgetFilter( &$ele, $entity, $field ) {
		if ( $wp_roles = $field->getFieldData( '_wp_roles' ) ) {
			if ( ! $this->_hasRole( $wp_roles, $this->_application->getRoles() ) ) {
				$ele = null;
			}
		}
	}

	public function onDisplayElementRenderFilter( &$results, $bundle, array $element, $var ) {
		if ( empty( $element['visibility']['wp_check_role'] ) ) {
			return;
		}

		$current_user_roles = $this->_application->getUser()->isAnonymous() ? array( '_guest_' ) : (array) wp_get_current_user()->roles;
		$results[]          = $this->_hasRole( $element['visibility']['wp_roles'], $current_user_roles );
	}
	/*
		public function onDisplayDisplayFilter(&$display, $bundle, $displayType, $displayName)
		{
			// Check role to view the display?
			if (empty($display['wp_check_roles'])
				|| empty($display['elements'])
				|| is_admin()
			) return;

			$this->_checkDisplayElementRole($display['elements'], $this->_application->getRoles());
		}

		protected function _checkDisplayElementRole(array &$elements, array $currentUserRoles)
		{
			foreach (array_keys($elements) as $element_id) {
				if (!empty($elements[$element_id]['visibility']['wp_check_role'])
					&& !$this->_hasRole($elements[$element_id]['visibility']['wp_roles'], $currentUserRoles)
				) {
					unset($elements[$element_id]);
				} else {
					if (!empty($elements[$element_id]['wp_check_children_roles'])) {
						$this->_checkDisplayElementRole($elements[$element_id]['children'], $currentUserRoles);
					}
				}
			}
		}

		public function onDisplayCacheDisplayFilter(&$display, $bundle, $displayType, $displayName)
		{
			// Cache if display/row/column/element require role check so that we do not need to process those do not required at runtime
			foreach (array_keys($display['elements']) as $element_id) { // elements
				$this->_checkDisplayElementVisibilitySettings($display, $display['elements'][$element_id]);
			}
		}

		protected function _checkDisplayElementVisibilitySettings(&$display, &$element)
		{
			$ret = false;
			if (!empty($element['visibility']['wp_check_role'])) {
				$display['wp_check_roles'] = $ret = true;
			}
			if (!empty($element['children'])) {
				foreach (array_keys($element['children']) as $element_id) { // elements
					if ($this->_checkDisplayElementVisibilitySettings($display, $element['children'][$element_id])) {
						$element['wp_check_children_roles'] = $ret = true;
					}
				}
			}

			return $ret;
		}
	*/

	public function onDisplayElementSettingsFormFilter( &$form, $bundle, $display, $element, $elementData ) {
		if ( $display->type === 'form' ) {
			$display_element_type = (string) $element;
			if ( ( strpos( $display_element_type, 'entity_form_entity_' ) === 0 && ! in_array( $display_element_type, array( 'entity_form_entity_terms', 'entity_form_entity_reference' ) ) )
				|| in_array( $display_element_type, array( 'entity_form_wp_post_parent', 'entity_form_wordpressuser_role', 'entity_form_frontendsubmit_guest' ) )
			) {
				return;
			}
		}

		$roles                               = $this->_application->getPlatform()->getRoles();
		$roles['_guest_']                    = __( 'Guest', 'directories-pro' );
		$form['visibility']['wp_check_role'] = array(
			'#type'          => 'checkbox',
			'#title'         => __( 'Visible to selected roles only', 'directories-pro' ),
			'#default_value' => ! empty( $elementData['visibility']['wp_check_role'] ),
			'#horizontal'    => true,
			'#weight'        => 30,
		);
		$form['visibility']['wp_roles']      = array(
			'#type'          => 'checkboxes',
			'#columns'       => 3,
			'#options'       => $roles,
			'#default_value' => empty( $elementData['visibility']['wp_roles'] ) ? null : $elementData['visibility']['wp_roles'],
			'#horizontal'    => true,
			'#states'        => array(
				'visible' => array(
					'input[name="visibility[wp_check_role]"]' => array(
						'type'  => 'checked',
						'value' => true,
					),
				),
			),
			'#weight'        => 30,
		);
	}

	/* End code for setting visibility by user role */

	public function onFrontendsubmitRegisterFormFilter( &$form ) {
		$form['#attributes']['name'] = 'registerform'; // some plugins require this
	}

	public function onFieldCurrentEntityFilter( &$entity, $type = null ) {
		if ( is_single() ) {
			if ( ( ! isset( $type ) || $type === 'post' )
				&& ( $post = get_post() )
				&& ( $post_entity = $this->_application->Entity_Entity( 'post', $post->ID ) )
			) {
				$entity = $post_entity;
			}
		} elseif ( is_tax() ) {
			if ( ( ! isset( $type ) || $type === 'term' )
				&& ( $term_id = get_queried_object()->term_id )
				&& ( $term_entity = $this->_application->Entity_Entity( 'term', $term_id ) )
			) {
				$entity = $term_entity;
			}
		}
	}

	public function onDisplayElementReadableInfoFilter( &$info, $bundle, $element ) {
		if ( $element->Display->type !== 'entity'
			|| $element->Display->name !== 'detailed'
			|| ! $element->element_id
		) {
			return;
		}

		$info['code'] = array(
			'label' => __( 'Code', 'directories-pro' ),
			'value' => array(
				'class' => array(
					'label'   => __( 'Shortcode', 'directories-pro' ),
					'value'   => '<code class="' . DRTS_BS_PREFIX . 'user-select-all">[drts-entity display_element="' . $element->name . '-' . $element->element_id . '"]</code>',
					'is_html' => true,
				),
			),
		);
	}

	public function onEntityFormLoadAssets( $bundle, $assets ) {
		wp_enqueue_media();
		wp_enqueue_editor();
	}

	public function onMapGooglemapsApiLoaded( $handle ) {
		add_action(
			is_admin() ? 'admin_enqueue_scripts' : 'wp_enqueue_scripts',
			function () {
				wp_dequeue_script( 'evcal_gmaps' ); // EventOn plugin
				wp_dequeue_script( 'google_map_api' );
				wp_dequeue_script( 'google-maps' );
			},
			99999
		);
	}

	public function locationGetGeolocationApiNames() {
		$ret = array();
		if ( defined( 'GEOIP_DETECT_VERSION' ) ) {
			$ret[] = 'wordpress_geoip';
		}
		return $ret;
	}

	public function locationGetGeolocationApi( $name ) {
		switch ( $name ) {
			case 'wordpress_geoip':
				return new LocationApi\GeoIpGeolocationApi( $this->_application, $name );
		}
	}

	public function onCorePlatformWordpressRewriteRulesFilter( &$rules, $lang ) {
		$rules = $this->_application->WordPressContent_RewriteRules( $lang ) + $rules;
	}

	public function onEntityBundleInfoUserKeysFilter( &$keys ) {
		$keys[] = 'wordpress_page';
	}

	public function captchaGetApiNames() {
		return array( 'wordpress_really_simple_captcha' );
	}

	public function captchaGetApi( $name ) {
		return new CaptchaApi\ReallySimpleCaptchaApi( $this->_application, $name );
	}

	public function hasVarDir() {
		return true;
	}

	public function onEntityPrimaryTermFilter( &$term, $postId, $taxonomy, $terms ) {
		if ( class_exists( '\WPSEO_Primary_Term', false ) ) {
			$wpseo_primary_term = new \WPSEO_Primary_Term( $taxonomy, $postId );
			if ( $primary_term_id = $wpseo_primary_term->get_primary_term() ) {
				foreach ( array_keys( $terms ) as $k ) {
					if ( $terms[ $k ]->getId() == $primary_term_id ) {
						$term = $terms[ $k ];
						return;
					}
				}
			}
		}
	}

	public function csvGetExporterNames() {
		return array( 'wp_image', 'wp_file', 'wp_post_content', 'wp_term_description', 'wp_post_status', 'wp_post_parent' );
	}

	public function csvGetExporter( $name ) {
		return new CSVExporter\WPCSVExporter( $this->_application, $name );
	}

	public function csvGetImporterNames() {
		return array( 'wp_image', 'wp_file', 'wp_post_content', 'wp_term_description', 'wp_post_status', 'wp_post_parent' );
	}

	public function csvGetImporter( $name ) {
		return new CSVImporter\WPCSVImporter( $this->_application, $name );
	}

	public function onViewInit( $context ) {
		// Redirect to main page if no page exists for the taxonomy/child entities page
		if ( isset( $context->bundle )
			&& ! $context->isEmbed()
			&& ( isset( $context->taxonomy_bundle ) || isset( $context->child_bundle ) )
		) {
			$current_route = trim( (string) $context->getRoute(), '/' );
			$bundle        = $context->taxonomy_bundle ?? $context->child_bundle;
			if ( $current_route === trim( $bundle->getPath( false ), '/' )
				&& ! get_page_by_path( $current_route )
			) {
				$context->setRedirect( $context->bundle->getPath( false ) );
			}
		}
	}

	public function onWordPressContentSubpageRewriteRulesFilter( &$rules, $lang ) {
		foreach ( array_keys( $rules ) as $bundle_name ) {
			foreach ( array( 'search', 'filter', 'compare' ) as $slug ) {
				$rules[ $bundle_name ][ $slug ] = array( 'type' => 'system' );
			}
		}
	}

	public function notificationGetEventNames() {
		return array( 'wordpresscontent_comment_published' );
	}

	public function notificationGetEvent( $name ) {
		switch ( $name ) {
			case 'wordpresscontent_comment_published':
				return new NotificationEvent\CommentPublishedNotificationEvent( $this->_application, $name );
		}
	}
}
