<?php
/*
 * Copyright (c) 2023. RTM Business
 */

namespace WordpressModels\ORM;

use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\Event\LoadClassMetadataEventArgs;
use Doctrine\ORM\Events;
use WordpressModels\ORM\Entity\Post;
use WordpressModels\ORM\Entity\PostType\Attachment;
use WordpressModels\ORM\Entity\PostType\Page;

/**
 * Doctrine EventSubscriber to register post-types as MappedSuperclass Subclasses of the Post class.
 */
class PostTypeClassMetadataListener implements EventSubscriber
{

    public function __construct()
    {
        add_filter('doctrine_post_type_discriminator_map', $this->addDefaultPostTypeDiscriminators(...));
    }

    /**
     * Register the default post types
     */
    public function addDefaultPostTypeDiscriminators(array $classMap)
    {
        return $classMap + [
                'post' => Post::class,
                'page' => Page::class,
                'attachment' => Attachment::class
            ];
    }

    public function getSubscribedEvents()
    {
        return [
            Events::loadClassMetadata
        ];
    }

    /**
     * Event listener for the LoadClassMetadata event to register discriminator mappings for post types.
     *
     * Fires a hook 'doctrine_post_type_discriminator_map', which accepts the original discriminator mapping for
     * Post::class (post => Post::class, page => Page::class, attachment => Attachment::class).
     *
     * To register extra entities for the discriminator, check the 'doctrine_entity_directories' hook.
     *
     * @param LoadClassMetadataEventArgs $eventArgs
     * @return void
     * @throws \Doctrine\ORM\Mapping\MappingException If any invalid entity is given.
     */
    public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs)
    {
        $classMetadata = $eventArgs->getClassMetadata();
        if ($classMetadata->getName() === Post::class) {
            $discriminatorMap = array_filter(
                apply_filters('doctrine_post_type_discriminator_map', $classMetadata->discriminatorMap),
                fn(string $value) => $value !== Post::class
            );
            foreach ($discriminatorMap as $columnValue => $entityClass) {
                $classMetadata->addDiscriminatorMapClass($columnValue, $entityClass);
            }
        }
    }

}
