<commit_before><?php namespace App\Validation;

use App\Api\RolesApi;
use App\Api\UsersApi;
use App\Json\Schemas\RoleSchema;
use App\Json\Schemas\UserSchema;
use Limoncello\Flute\Types\DateTime;
use Limoncello\Flute\Validation\Rules\ApiRulesTrait;
use Limoncello\Flute\Validation\Rules\DatabaseRulesTrait;
use Limoncello\Flute\Validation\Rules\RelationshipRulesTrait;
use Limoncello\Validation\Contracts\Errors\ErrorCodes;
use Limoncello\Validation\Contracts\Rules\RuleInterface;
use Limoncello\Validation\Rules;

/**
 * @package App
 */
class BaseRules extends Rules
{
    use RelationshipRulesTrait, DatabaseRulesTrait, ApiRulesTrait;

    /**
     * @return RuleInterface
     */
    public static function roleId(): RuleInterface
    {
        return self::asSanitizedString(self::readable(RolesApi::class));
    }

    /**
     * @return RuleInterface
     */
    public static function roleRelationship(): RuleInterface
    {
        return self::toOneRelationship(RoleSchema::TYPE, static::roleId());
    }

    /**
     * @return RuleInterface
     */
    public static function userId(): RuleInterface
    {
        return self::stringToInt(self::readable(UsersApi::class));
    }

    /**
     * @return RuleInterface
     */
    public static function userRelationship(): RuleInterface
    {
        return self::toOneRelationship(UserSchema::TYPE, static::userId());
    }

    /**
     * @return RuleInterface
     */
    public static function usersRelationship(): RuleInterface
    {
        $readableAll = static::stringArrayToIntArray(static::readableAll(UsersApi::class));

        return self::toManyRelationship(UserSchema::TYPE, $readableAll);
    }

    /**
     * @param RuleInterface|null $next
     *
     * @return RuleInterface
     */
    public static function asSanitizedUrl(RuleInterface $next = null): RuleInterface
    {
        return self::isString(self::filter(FILTER_SANITIZE_URL, null, ErrorCodes::INVALID_VALUE, $next));
    }

    /**
     * @param RuleInterface|null $next
     *
     * @return RuleInterface
     */
    public static function asSanitizedString(RuleInterface $next = null): RuleInterface
    {
        return self::isString(
            self::filter(FILTER_SANITIZE_FULL_SPECIAL_CHARS, null, ErrorCodes::INVALID_VALUE, $next)
        );
    }

    /**
     * @param RuleInterface|null $next
     *
     * @return RuleInterface
     */
    public static function asJsonApiDateTime(RuleInterface $next = null): RuleInterface
    {
        return self::stringToDateTime(DateTime::JSON_API_FORMAT, $next);
    }
}
<commit_msg>Add support for validation rules chaining.<commit_after><?php namespace App\Validation;

use App\Api\RolesApi;
use App\Api\UsersApi;
use App\Json\Schemas\RoleSchema;
use App\Json\Schemas\UserSchema;
use Limoncello\Flute\Types\DateTime;
use Limoncello\Flute\Validation\Rules\ApiRulesTrait;
use Limoncello\Flute\Validation\Rules\DatabaseRulesTrait;
use Limoncello\Flute\Validation\Rules\RelationshipRulesTrait;
use Limoncello\Validation\Contracts\Errors\ErrorCodes;
use Limoncello\Validation\Contracts\Rules\RuleInterface;
use Limoncello\Validation\Rules;

/**
 * @package App
 */
class BaseRules extends Rules
{
    use RelationshipRulesTrait, DatabaseRulesTrait, ApiRulesTrait;

    /**
     * @param RuleInterface|null $next
     *
     * @return RuleInterface
     */
    public static function roleId(RuleInterface $next = null): RuleInterface
    {
        return self::asSanitizedString(self::readable(RolesApi::class, $next));
    }

    /**
     * @param RuleInterface|null $next
     *
     * @return RuleInterface
     */
    public static function roleRelationship(RuleInterface $next = null): RuleInterface
    {
        return self::toOneRelationship(RoleSchema::TYPE, static::roleId($next));
    }

    /**
     * @param RuleInterface|null $next
     *
     * @return RuleInterface
     */
    public static function userId(RuleInterface $next = null): RuleInterface
    {
        return self::stringToInt(self::readable(UsersApi::class, $next));
    }

    /**
     * @param RuleInterface|null $next
     *
     * @return RuleInterface
     */
    public static function userRelationship(RuleInterface $next = null): RuleInterface
    {
        return self::toOneRelationship(UserSchema::TYPE, static::userId($next));
    }

    /**
     * @param RuleInterface|null $next
     *
     * @return RuleInterface
     */
    public static function usersRelationship(RuleInterface $next = null): RuleInterface
    {
        $readableAll = static::stringArrayToIntArray(static::readableAll(UsersApi::class, $next));

        return self::toManyRelationship(UserSchema::TYPE, $readableAll);
    }

    /**
     * @param RuleInterface|null $next
     *
     * @return RuleInterface
     */
    public static function asSanitizedUrl(RuleInterface $next = null): RuleInterface
    {
        return self::isString(self::filter(FILTER_SANITIZE_URL, null, ErrorCodes::INVALID_VALUE, $next));
    }

    /**
     * @param RuleInterface|null $next
     *
     * @return RuleInterface
     */
    public static function asSanitizedString(RuleInterface $next = null): RuleInterface
    {
        return self::isString(
            self::filter(FILTER_SANITIZE_FULL_SPECIAL_CHARS, null, ErrorCodes::INVALID_VALUE, $next)
        );
    }

    /**
     * @param RuleInterface|null $next
     *
     * @return RuleInterface
     */
    public static function asJsonApiDateTime(RuleInterface $next = null): RuleInterface
    {
        return self::stringToDateTime(DateTime::JSON_API_FORMAT, $next);
    }
}

{'fraction_non_alphanumeric': 0.11146953405017922, 'fraction_numerical': 0.0, 'mean_word_length': 3.3465732087227416, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5610997', 'n_tokens_mistral': 1633, 'n_tokens_neox': 1612, 'n_words': 303}