phplrt/phplrt

View on GitHub
libs/position/src/PositionFactoryTrait.php

Summary

Maintainability
A
0 mins
Test Coverage
<?php

declare(strict_types=1);

namespace Phplrt\Position;

use Phplrt\Contracts\Position\PositionFactoryInterface;
use Phplrt\Contracts\Position\PositionInterface;
use Phplrt\Contracts\Source\ReadableInterface;
use Phplrt\Contracts\Source\SourceExceptionInterface;
use Phplrt\Contracts\Source\SourceFactoryInterface;
use Phplrt\Source\SourceFactory;

trait PositionFactoryTrait
{
    private static ?PositionFactoryInterface $positionFactory = null;

    private static ?SourceFactoryInterface $sourceFactory = null;

    public static function setPositionFactory(PositionFactoryInterface $factory): void
    {
        self::$positionFactory = $factory;
    }

    public static function getPositionFactory(): PositionFactoryInterface
    {
        return self::$positionFactory ??= new PositionFactory();
    }

    public static function setSourceFactory(SourceFactoryInterface $factory): void
    {
        self::$sourceFactory = $factory;
    }

    public static function getSourceFactory(): SourceFactoryInterface
    {
        if (self::$sourceFactory !== null) {
            return self::$sourceFactory;
        }

        if (!\class_exists(SourceFactory::class)) {
            $message = 'Can not find and create instance of %s because the package'
                . ' "phplrt/source" is not available. Please indicate it explicitly'
                . ' using "%s::setSourceFactory()" method.';

            throw new \LogicException(\vsprintf($message, [
                SourceFactoryInterface::class,
                static::class,
            ]));
        }

        return self::$sourceFactory = new SourceFactory();
    }

    /**
     * An alternative factory function of the
     * {@see PositionFactoryInterface::createFromPosition()} method.
     *
     * @param int<1, max> $line Expected line value of the position in the
     *        passed source instance.
     * @param int<1, max> $column Expected column value of the position in the
     *        passed source instance.
     *
     * @throws SourceExceptionInterface In case of an error in creating the
     *         source object.
     */
    public static function fromPosition(
        $source,
        int $line = PositionInterface::MIN_LINE,
        int $column = PositionInterface::MIN_COLUMN
    ): PositionInterface {
        $factory = self::getPositionFactory();

        if (!$source instanceof ReadableInterface) {
            $sources = self::getSourceFactory();

            $source = $sources->create($source);
        }

        return $factory->createFromPosition($source, $line, $column);
    }

    /**
     * An alternative factory function of the
     * {@see PositionFactoryInterface::createAtStarting()} method.
     */
    public static function start(): PositionInterface
    {
        $factory = self::getPositionFactory();

        return $factory->createAtStarting();
    }

    /**
     * An alternative factory function of the
     * {@see PositionFactoryInterface::createAtEnding()} method.
     *
     * @throws SourceExceptionInterface In case of an error in creating the
     *         source object.
     */
    public static function end($source): PositionInterface
    {
        $factory = self::getPositionFactory();

        if (!$source instanceof ReadableInterface) {
            $sources = self::getSourceFactory();

            $source = $sources->create($source);
        }

        return $factory->createAtEnding($source);
    }

    /**
     * An alternative factory function of the
     * {@see PositionFactoryInterface::createFromOffset()} method.
     *
     * @param int<0, max> $offset Expected offset of the position in the passed
     *        source instance.
     *
     * @throws SourceExceptionInterface In case of an error in creating the
     *         source object.
     */
    public static function fromOffset(
        $source,
        int $offset = PositionInterface::MIN_OFFSET
    ): PositionInterface {
        $factory = self::getPositionFactory();

        if (!$source instanceof ReadableInterface) {
            $sources = self::getSourceFactory();

            $source = $sources->create($source);
        }

        return $factory->createFromOffset($source, $offset);
    }
}