<commit_before><?php

namespace Railken\Lem;

use Exception;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Railken\Bag;
use Railken\Lem\Contracts\AgentContract;
use Railken\Lem\Contracts\EntityContract;
use Railken\Lem\Contracts\ManagerContract;
use Railken\Lem\Contracts\ResultContract;

/**
 * Abstract Manager class.
 */
abstract class Manager implements ManagerContract
{
    use Concerns\HasExceptions;
    use Concerns\HasRepository;
    use Concerns\HasAuthorizer;
    use Concerns\HasSerializer;
    use Concerns\HasValidator;
    use Concerns\HasSchema;
    use Concerns\CallMethods;

    /**
     * @var string
     */
    protected $entity;

    /**
     * @var Collection
     */
    protected $attributes;

    /**
     * @var string
     */
    protected $comment;

    /**
     * @var array
     */
    protected $unique = [];

    /**
     * @var AgentContract
     */
    protected $agent;

    /**
     * @var array
     */
    protected $exceptions = [
        Tokens::NOT_AUTHORIZED => Exceptions\ModelNotAuthorizedException::class,
    ];

    /**
     * Construct.
     *
     * @param AgentContract $agent
     */
    public function __construct(AgentContract $agent = null)
    {
        $this->setAgent($agent);
        $this->boot();
    }

    /**
     * @param string $method
     * @param array  $args
     *
     * @return mixed
     */
    public function __call($method, $args)
    {
        if (preg_match('/OrFail$/', $method)) {
            $method = preg_replace('/OrFail$/', '', $method);

            if (method_exists($this, $method)) {
                $return = $this->$method(...$args);

                if ($return instanceof Result) {
                    if (!$return->ok()) {
                        throw new Exceptions\Exception(sprintf('Something went wrong while interacting with %s, errors: %s', $this->getEntity(), (string) json_encode($return->getSimpleErrors())));
                    } else {
                        return $return;
                    }
                }
            }
        }

        trigger_error('Call to undefined method '.__CLASS__.'::'.$method.'()', E_USER_ERROR);
    }

    /**
     * Get name.
     *
     * @return string
     */
    public function getName()
    {
        return preg_replace('/Manager$/', '', (new \ReflectionClass($this))->getShortName());
    }

    /**
     * Get Comment.
     *
     * @return string
     */
    public function getComment()
    {
        return $this->comment;
    }

    /**
     * Get base namespace.
     */
    public function getNamespaceBase()
    {
        return preg_replace('/\\\Managers$/', '', (new \ReflectionClass($this))->getNamespaceName());
    }

    /**
     * Register Components.
     */
    public function registerClasses()
    {
        $namespace = $this->getNamespaceBase();
        $name = $this->getName();

        return [
            'model'      => "{$namespace}\\Models\\{$name}",
            'serializer' => "{$namespace}\\Serializers\\{$name}Serializer",
            'repository' => "{$namespace}\\Repositories\\{$name}Repository",
            'validator'  => "{$namespace}\\Validators\\{$name}Validator",
            'authorizer' => "{$namespace}\\Authorizers\\{$name}Authorizer",
            'faker'      => "{$namespace}\\Fakers\\{$name}Faker",
            'schema'     => "{$namespace}\\Schemas\\{$name}Schema",
        ];
    }

    /**
     * Boot components.
     */
    public function boot()
    {
        $this->callMethods('boot', [$this->registerClasses()]);
    }

    /**
     * Boot entity.
     *
     * @param array $classes
     */
    public function bootEntity(array $classes)
    {
        $this->entity = $classes['model'];
    }

    /**
     * Create a new instance of exception.
     *
     * @param string $code
     * @param mixed  $value
     *
     * @return \Exception
     */
    public function newException(string $code, $value): Exception
    {
        $exception = $this->getException($code);

        return new $exception(
            strtoupper(Str::kebab($this->getName())),
            $value<commit_msg>registerClasses now have default values<commit_after><?php

namespace Railken\Lem;

use Exception;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Railken\Bag;
use Railken\Lem\Contracts\AgentContract;
use Railken\Lem\Contracts\EntityContract;
use Railken\Lem\Contracts\ManagerContract;
use Railken\Lem\Contracts\ResultContract;

/**
 * Abstract Manager class.
 */
abstract class Manager implements ManagerContract
{
    use Concerns\HasExceptions;
    use Concerns\HasRepository;
    use Concerns\HasAuthorizer;
    use Concerns\HasSerializer;
    use Concerns\HasValidator;
    use Concerns\HasSchema;
    use Concerns\CallMethods;

    /**
     * @var string
     */
    protected $entity;

    /**
     * @var Collection
     */
    protected $attributes;

    /**
     * @var string
     */
    protected $comment;

    /**
     * @var array
     */
    protected $unique = [];

    /**
     * @var AgentContract
     */
    protected $agent;

    /**
     * @var array
     */
    protected $exceptions = [
        Tokens::NOT_AUTHORIZED => Exceptions\ModelNotAuthorizedException::class,
    ];

    /**
     * Construct.
     *
     * @param AgentContract $agent
     */
    public function __construct(AgentContract $agent = null)
    {
        $this->setAgent($agent);
        $this->boot();
    }

    /**
     * @param string $method
     * @param array  $args
     *
     * @return mixed
     */
    public function __call($method, $args)
    {
        if (preg_match('/OrFail$/', $method)) {
            $method = preg_replace('/OrFail$/', '', $method);

            if (method_exists($this, $method)) {
                $return = $this->$method(...$args);

                if ($return instanceof Result) {
                    if (!$return->ok()) {
                        throw new Exceptions\Exception(sprintf('Something went wrong while interacting with %s, errors: %s', $this->getEntity(), (string) json_encode($return->getSimpleErrors())));
                    } else {
                        return $return;
                    }
                }
            }
        }

        trigger_error('Call to undefined method '.__CLASS__.'::'.$method.'()', E_USER_ERROR);
    }

    /**
     * Get name.
     *
     * @return string
     */
    public function getName()
    {
        return preg_replace('/Manager$/', '', (new \ReflectionClass($this))->getShortName());
    }

    /**
     * Get Comment.
     *
     * @return string
     */
    public function getComment()
    {
        return $this->comment;
    }

    /**
     * Get base namespace.
     */
    public function getNamespaceBase()
    {
        return preg_replace('/\\\Managers$/', '', (new \ReflectionClass($this))->getNamespaceName());
    }

    /**
     * Register Components.
     */
    public function retrieveClasses()
    {
        $namespace = $this->getNamespaceBase();
        $name = $this->getName();

        return array_merge([
            'model'      => "{$namespace}\\Models\\{$name}",
            'serializer' => "{$namespace}\\Serializers\\{$name}Serializer",
            'repository' => "{$namespace}\\Repositories\\{$name}Repository",
            'validator'  => "{$namespace}\\Validators\\{$name}Validator",
            'authorizer' => "{$namespace}\\Authorizers\\{$name}Authorizer",
            'faker'      => "{$namespace}\\Fakers\\{$name}Faker",
            'schema'     => "{$namespace}\\Schemas\\{$name}Schema",
        ], $this->registerClasses());
    }

    /**
     * Register Components.
     */
    public function registerClasses()
    {
        return [
            // ...
        ];
    }

    /**
     * Boot components.
     */
    public function boot()
    {
        $this->callMethods('boot', [$this->retrieveClasses()]);
    }

    /**
     * Boot entity.
     *
     * @param array $classes
     */
    public function bootEntity(array $classes)
    {
        $this->entity = $classes['model'];
    }

    /**
     * Create a new instance of exception.
     *
     * @param string $code
     * @param mixed  $value
     *
     * @return \Exception
     */
    public function newException(string $code, $value): Exception
    {
        $exception = $this->getException($code);

        return new $exception(
            strtoupper(Str::kebab($this->getName())),
            $value
{'fraction_non_alphanumeric': 0.15187052890817404, 'fraction_numerical': 0.0, 'mean_word_length': 1.933608531131751, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 52, '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': '2830470', 'n_tokens_mistral': 2476, 'n_tokens_neox': 2404, 'n_words': 473}