from(Database::get_table(Terms::TABLE_NAME)) ->where([Terms::NAME->value => $name]) ->limit(1) ->select(Terms::TERM_ID->value); return $query->num_rows === 1 ? new static($query->fetch_assoc()[Terms::TERM_ID->value]) : null; } /** * Returns an array of all Terms associated with a Post * * @param Post $post * @return array */ public static function from_post(Post $post): array { $query = Database::current() ->from(Database::get_table(TermRelationships::TABLE_NAME)) ->where([TermRelationships::OBJECT_ID->value => $post->id]) ->select(TermRelationships::TERM_TAXONOMY_ID->value); return array_map(fn(array $post_meta): static => new static($post_meta[TermRelationships::TERM_TAXONOMY_ID->value]), $query->fetch_all(MYSQLI_ASSOC)); } /** * Create a new post meta field for a given post * * @param string $title Post title * @param string $type Post type * @return static */ public static function new(string $name, ?string $slug = null): static { // Current auto increment value will be the id for this entity $id = Database::current()->latest(Terms::TABLE_NAME); $values = [ Terms::TERM_ID->value => null, Terms::NAME->value => $name, Terms::SLUG->value => $slug ? $slug : slugify($name), Terms::TERM_GROUP->value => 0 ]; if (!parent::create(Database::get_table(Terms::TABLE_NAME), $values)) { throw new Exception("Failed to create database entity"); } return new static($id); } public function __construct(public readonly int $id) { parent::__construct( Database::get_table(Terms::TABLE_NAME), Terms::values(), [Terms::TERM_ID->value => $id] ); } public string $name { get => $this->get(Terms::NAME->value); set (string $name) => $this->set(Terms::NAME->value, $name); } public string $slug { get => $this->get(Terms::SLUG->value); set (string $slug) => $this->set(Terms::SLUG->value, $slug); } public int $term_group { get => $this->get(Terms::TERM_GROUP->value); set (int $term_group) => $this->set(Terms::TERM_GROUP->value, $term_group); } /** * Returns an array of Taxonomies that implement this Term * * @return array */ public function taxonomies(): array { return Taxonomy::from_term($this); } /** * Add this Term to a target Post * * @param Post $post * @return void */ public function add_to_post(Post $post): void { // Bail out if this term has already been added to the target Post if ($this->post_has_term($post)) { return; } $query = Database::current() ->from(Database::get_table(TermRelationships::TABLE_NAME)) ->insert([ TermRelationships::OBJECT_ID->value => $post->id, TermRelationships::TERM_TAXONOMY_ID->value => $this->id, TermRelationships::TERM_ORDER->value => 0 ]); if ($query === false) { throw new Exception("Failed to create database entity"); } // Increase the post count for each Taxonomy implementing this Term foreach ($this->taxonomies() as $taxonomy) { $taxonomy->count++; } } /** * Remove this Term from a target Post * * @param Post $post * @return void */ public function remove_from_post(Post $post): void { // Bail out if this Term is not set on the target Post if (!$this->post_has_term($post)) { return; } $query = Database::current() ->from(Database::get_table(TermRelationships::TABLE_NAME)) ->delete([ TermRelationships::OBJECT_ID->value => $post->id, TermRelationships::TERM_TAXONOMY_ID->value => $this->id ]); if ($query === false) { throw new Exception("Failed to create database entity"); } // Decrease the post count for each Taxonomy implementing this Term foreach ($this->taxonomies() as $taxonomy) { $taxonomy->count--; } } /** * Returns true if a given Post has this Term * * @param Post $post * @return bool */ private function post_has_term(Post $post): bool { return in_array($this->id, array_column(self::from_post($post), "id")); } }