diff --git a/composer.json b/composer.json index bc7ee94..dd10383 100644 --- a/composer.json +++ b/composer.json @@ -4,7 +4,7 @@ "description": "A plugin for WordPress that makes post types easier to manage", "minimum-stability": "stable", "license": "GPL-3.0", - "version": "2.1.0", + "version": "2.1.1", "autoload": { "psr-4": { "Outlandish\\Wordpress\\Oowp\\": "src/" diff --git a/src/PostTypeManager.php b/src/PostTypeManager.php index af7b4b2..070ce27 100644 --- a/src/PostTypeManager.php +++ b/src/PostTypeManager.php @@ -50,7 +50,6 @@ protected function registerPostType($className) } $this->postTypes[$className] = $postType; - $this->connections[$postType] = array(); do_action('oowp/post_type_registered', $postType, $className); } @@ -135,45 +134,45 @@ public function getPostTypes() return array_values($this->postTypes); } - /** - * Registers a new connection between two post types - * @param string $postType - * @param string $targetPostType - * @param array $parameters - * @return bool|object - */ - public function registerConnection($postType, $targetPostType, $parameters) + /** + * Registers a new connection between two post types + * @param string $postType + * @param string $targetPostType + * @param array $parameters + * @param string $connectionName + * @return bool|object + */ + public function registerConnection($postType, $targetPostType, $parameters, $connectionName = null) { if (!function_exists('p2p_register_connection_type')) { return null; } - if(!array_key_exists($postType, $this->connections)) { - $this->connections[$postType] = array(); - } - if(!array_key_exists($targetPostType, $this->connections)) { - $this->connections[$targetPostType] = array(); - } - if(in_array($targetPostType, $this->connections[$postType]) || in_array($postType, $this->connections[$targetPostType])) { - return false; //this connection has already been registered - } - $this->connections[$targetPostType][] = $postType; - $this->connections[$postType][] = $targetPostType; + if (!$connectionName) { + $connectionName = $this->generateConnectionName($postType, $targetPostType); + } - $types = array($targetPostType, $postType); - sort($types); + if (array_key_exists($connectionName, $this->connections)) { + return $this->connections[$connectionName]->connection; + } - $connection_name = $this->generateConnectionName($postType, $targetPostType); $defaults = array( - 'name' => $connection_name, - 'from' => $types[0], - 'to' => $types[1], + 'name' => $connectionName, + 'from' => $postType, + 'to' => $targetPostType, 'cardinality' => 'many-to-many', 'reciprocal' => true ); $parameters = wp_parse_args($parameters, $defaults); - return p2p_register_connection_type($parameters); + $connection = p2p_register_connection_type($parameters); + + $this->connections[$connectionName] = (object) [ + 'parameters' => $parameters, + 'connection' => $connection + ]; + + return $connection; } /** @@ -195,8 +194,45 @@ public function generateConnectionName($postType, $targetType) * @param string $postType * @return string[] */ - public function getConnections($postType) + public function getConnectedPostTypes($postType) { - return array_key_exists($postType, $this->connections) ? $this->connections[$postType] : array(); + $types = []; + foreach ($this->connections as $connection) { + if ($connection->parameters['from'] === $postType) { + $types[] = $connection->parameters['to']; + } + if ($connection->parameters['to'] === $postType) { + $types[] = $connection->parameters['from']; + } + } + return array_unique($types); } + + /** + * Gets all of the connection names that go between (one of) $postTypeA and (one of) $postTypeB + * @param string|string[] $postTypeA + * @param string|string[] $postTypeB + * @return string[] + */ + public function getConnectionNames($postTypeA, $postTypeB) + { + $connectionNames = []; + if ($postTypeA && $postTypeB) { + if (!is_array($postTypeB)) { + $postTypeB = [$postTypeB]; + } + if (!is_array($postTypeA)) { + $postTypeA = [$postTypeA]; + } + foreach ($this->connections as $name => $connection) { + if (in_array($connection->parameters['from'], $postTypeA) && in_array($connection->parameters['to'], $postTypeB)) { + $connectionNames[] = $name; + } + if (in_array($connection->parameters['from'], $postTypeB) && in_array($connection->parameters['to'], $postTypeA)) { + $connectionNames[] = $name; + } + } + } + return array_unique($connectionNames); + } } \ No newline at end of file diff --git a/src/PostTypes/WordpressPost.php b/src/PostTypes/WordpressPost.php index 3a6f501..3f5acb1 100644 --- a/src/PostTypes/WordpressPost.php +++ b/src/PostTypes/WordpressPost.php @@ -208,14 +208,17 @@ public function connectAll($posts) { } } - /** - * @param $post int|object|WordpressPost - * @param array $meta - */ - public function connect($post, $meta = array()) { + /** + * @param $post int|object|WordpressPost + * @param array $meta + * @param string $connectionName + */ + public function connect($post, $meta = array(), $connectionName = null) { $post = WordpressPost::createWordpressPost($post); if ($post) { - $connectionName = PostTypeManager::get()->generateConnectionName(self::postType(), $post->post_type); + if (!$connectionName) { + $connectionName = PostTypeManager::get()->generateConnectionName(self::postType(), $post->post_type); + } /** @var \P2P_Directed_Connection_Type $connectionType */ $connectionType = p2p_type($connectionName); if ($connectionType) { @@ -227,14 +230,15 @@ public function connect($post, $meta = array()) { } } - /** - * @param $targetPostType string e.g. post, event - the type of post you want to connect to - * @param bool $single - just return the first/only post? - * @param array $queryArgs - augment or overwrite the default parameters for the WP_Query - * @param bool $hierarchical - if this is true the the function will return any post that is connected to this post *or any of its descendants* - * @return null|WordpressPost|OowpQuery - */ - public function connected($targetPostType, $single = false, $queryArgs = array(), $hierarchical = false) + /** + * @param string|string[] $targetPostType e.g. post, event - the type of connected post(s) you want + * @param bool $single - just return the first/only post? + * @param array $queryArgs - augment or overwrite the default parameters for the WP_Query + * @param bool $hierarchical - if this is true the the function will return any post that is connected to this post *or any of its descendants* + * @param string|string[] $connectionName If specified, only this connection name is used to find the connected posts (defaults to any/all connections to $targetPostType) + * @return null|OowpQuery|WordpressPost + */ + public function connected($targetPostType, $single = false, $queryArgs = array(), $hierarchical = false, $connectionName = null) { $toReturn = null; if (function_exists('p2p_register_connection_type')) { @@ -243,17 +247,23 @@ public function connected($targetPostType, $single = false, $queryArgs = array() } $manager = PostTypeManager::get(); $postType = self::postType(); - $connection_name = array(); - foreach ($targetPostType as $targetType) { - $connection_name[] = $manager->generateConnectionName($postType, $targetType); - } + + if (!$connectionName) { + $connectionName = $manager->getConnectionNames($postType, $targetPostType); + } else if (!is_array($connectionName)) { + $connectionName = [$connectionName]; + } $defaults = array( - 'connected_type' => $connection_name, - 'post_type' => $targetPostType, + 'connected_type' => $connectionName, + 'post_type' => $targetPostType, ); - #todo optimisation: check to see if this post type is hierarchical first + // ignore $hierarchical = true if this post type is not hierarchical + if ($hierarchical && !self::isHierarchical($postType)) { + $hierarchical = false; + } + if ($hierarchical) { $defaults['connected_items'] = array_merge($this->getDescendantIds(), array($this->ID)); } else { @@ -263,8 +273,8 @@ public function connected($targetPostType, $single = false, $queryArgs = array() // use the menu order if $hierarchical is true, or any of the target post types are hierarchical $useMenuOrder = $hierarchical; if (!$useMenuOrder) { - foreach ($targetPostType as $postType) { - if (self::isHierarchical($postType)) { + foreach ($targetPostType as $otherPostType) { + if (self::isHierarchical($otherPostType)) { $useMenuOrder = true; break; } @@ -558,7 +568,7 @@ public function childPostClassNames() */ public static function connectedPostTypes() { - return PostTypeManager::get()->getConnections(self::postType()); + return PostTypeManager::get()->getConnectedPostTypes(self::postType()); } /** @@ -867,15 +877,16 @@ static function getQueriedObject() { return $ooQueriedObject; } - /** - * @static Creates a p2p connection to another post type - * @param $targetPostType - the post_type of the post type you want to connect to - * @param array $parameters - these can overwrite the defaults. though if you change the name of the connection you'll need a custom getConnected aswell - * @return mixed - */ - static function registerConnection($targetPostType, $parameters = array()) + /** + * @static Creates a p2p connection to another post type + * @param string $targetPostType The post_type of the post type you want to connect to + * @param array $parameters These can overwrite the defaults. Do not specify connection_name, use $connectionName instead + * @param string $connectionName + * @return mixed + */ + static function registerConnection($targetPostType, $parameters = array(), $connectionName = null) { - return PostTypeManager::get()->registerConnection(self::postType(), $targetPostType, $parameters); + return PostTypeManager::get()->registerConnection(self::postType(), $targetPostType, $parameters, $connectionName); } /**