<?php
/**
 * Singleton trait which implements Singleton pattern in any class in which this trait is used.
 *
 * Using the singleton pattern in WordPress is an easy way to protect against
 * mistakes caused by creating multiple objects or multiple initialization
 * of classes which need to be initialized only once.
 *
 * If you're planning on using a global variable, then you should implement
 * this trait. Singletons are a way to safely use globals; they let you
 * access and set the global from anywhere, without risk of collision.
 *
 * If any method in a class needs to be aware of "state", then you should
 * implement this trait in that class.
 *
 * If any method in the class need to "talk" to another or be aware of what
 * another method has done, then you should implement this trait in that class.
 *
 * If you specifically need multiple objects, then use a normal class.
 *
 * @see https://github.com/rtCamp/blank-theme/tree/master/inc/traits
 */

namespace EasyWhiteLabel\Traits;

trait Singleton
{
    /**
     * Protected class constructor to prevent direct object creation.
     *
     * This is meant to be overridden in the classes which implement
     * this trait. This is ideal for doing stuff that you only want to
     * do once, such as hooking into actions and filters, etc.
     */
    protected function __construct()
    {
    }

    /**
     * Prevent object cloning.
     */
    final protected function __clone()
    {
    }

    /**
     * This method returns new or existing Singleton instance
     * of the class for which it is called. This method is set
     * as final intentionally, it is not meant to be overridden.
     *
     * @return object Singleton instance of the class.
     */
    final public static function init(): object
    {
        /**
         * Collection of instance.
         *
         * @var array
         */
        static $instance = [];

        /**
         * If this trait is implemented in a class which has multiple
         * sub-classes then static::$_instance will be overwritten with the most recent
         * sub-class instance. Thanks to late static binding
         * we use get_called_class() to grab the called class name, and store
         * a key=>value pair for each `classname => instance` in self::$_instance
         * for each sub-class.
         */
        $called_class = static::class;

        if ( ! isset( $instance[ $called_class ] ) ) {
            $instance[ $called_class ] = new $called_class();
        }

        return $instance[ $called_class ];
    }
}
