src/Stdlib/TypeExtensions/Stdlib/DurationTypeExtension.php

Summary

Maintainability
C
7 hrs
Test Coverage
F
35%
<?php

namespace Smuuf\Primi\Stdlib\TypeExtensions\Stdlib;

use \Smuuf\Primi\Context;
use \Smuuf\Primi\Extensions\PrimiFunc;
use \Smuuf\Primi\Values\NumberValue;
use \Smuuf\Primi\Values\AbstractValue;
use \Smuuf\Primi\Values\InstanceValue;
use \Smuuf\Primi\Helpers\Func;
use \Smuuf\Primi\Helpers\Interned;
use \Smuuf\Primi\Extensions\TypeExtension;
use \Smuuf\Primi\Structures\CallArgs;

class DurationTypeExtension extends TypeExtension {

    /** @const string Total seconds attr name. */
    private const ATTR_TOTSEC = 'total_seconds';

    #[PrimiFunc(callConv: PrimiFunc::CONV_CALLARGS)]
    public static function __init__(
        CallArgs $args
    ): void {

        [$self, $totalSec] = $args->extractPositional(2);
        Func::allow_argument_types(2, $totalSec, NumberValue::class);

        $self->attrSet(self::ATTR_TOTSEC, $totalSec);

        $totalSecInt = $totalSec->getInternalValue();
        $self->attrSet(
            'days',
            Interned::number((string) floor((int) $totalSecInt / 86400))
        );

        $self->attrSet(
            'seconds',
            Interned::number((string) ((int) $totalSecInt % 86400))
        );

    }

    #[PrimiFunc(callConv: PrimiFunc::CONV_CALLARGS)]
    public static function __op_eq__(
        CallArgs $args
    ): AbstractValue {

        [$self, $other] = $args->extractPositional(2);

        if ($other->getType() !== $self->getType()) {
            return Interned::constNotImplemented();
        }

        $equal = $self->attrGet(self::ATTR_TOTSEC)
            ->isEqualTo($other->attrGet(self::ATTR_TOTSEC));

        return Interned::bool($equal);

    }

    #[PrimiFunc(callConv: PrimiFunc::CONV_CALLARGS)]
    public static function __op_add__(
        CallArgs $args,
        Context $ctx
    ): AbstractValue {

        [$self, $other] = $args->extractPositional(2);

        if ($other->getType() !== $self->getType()) {
            return Interned::constNotImplemented();
        }

        $totalSeconds = $self->attrGet(self::ATTR_TOTSEC)
            ->doAddition($other->attrGet(self::ATTR_TOTSEC));

        $new = new InstanceValue($self->getType(), $ctx);
        $new->attrSet(self::ATTR_TOTSEC, $totalSeconds);

        return $new;

    }

    #[PrimiFunc(callConv: PrimiFunc::CONV_CALLARGS)]
    public static function __op_sub__(
        CallArgs $args,
        Context $ctx
    ): AbstractValue {

        [$self, $other] = $args->extractPositional(2);

        if ($other->getType() !== $self->getType()) {
            return Interned::constNotImplemented();
        }

        $totalSeconds = $self->attrGet(self::ATTR_TOTSEC)
            ->doSubtraction($other->attrGet(self::ATTR_TOTSEC));

        $new = new InstanceValue($self->getType(), $ctx);
        $new->attrSet(self::ATTR_TOTSEC, $totalSeconds);

        return $new;

    }

}