<?php

namespace App\Http\Traits;

use Illuminate\Support\Facades\Crypt;
use Illuminate\Contracts\Encryption\DecryptException;

/**
 * Trait Encryptable
 * This trait encrypts all your fields (defined in $this->encryptable) before saving it to the database.
 */
trait Encryptable
{
    /**
     * Checks if the attribute is encryptable.
     * @param $key
     * @return bool
     */
    private function isEncryptable($key)
    {
        return in_array($key, $this->encryptable);
    }

    /**
     * Decrypts a value.
     * @param $value
     *
     * @return string|void decrypted value
     */
    private function decrypt($value)
    {
        try {
            return Crypt::decryptString($value);
        } catch (DecryptException $e) {
            if (isset($this->dontThrowDecryptException) && $this->dontThrowDecryptException === true) {
                return $value;
            }

            throw $e;
        }
    }

    /**
     * Encrypts a value.
     * @param $value
     *
     * @return string
     */
    private function encrypt($value)
    {
        return Crypt::encryptString($value);
    }

    /**
     * Get an attribute from the model.
     *
     * @param  string  $key
     *
     * @return mixed
     */
    public function getAttribute($key)
    {

        $value = parent::getAttribute($key);

        if (!$value) {
            return '';
        }

        if ($this->isEncryptable($key) && (!is_null($value))) {
            return $this->decrypt($value);
        }

        return $value;
    }

    /**
     * Set a given attribute on the model.
     *
     * @param  string  $key
     * @param  mixed  $value
     *
     * @return $this
     */
    public function setAttribute($key, $value)
    {
        if (!$value) {
            return parent::setAttribute($key, $value);
        }

        if ($this->isEncryptable($key)) {
            $value = Crypt::encryptString($value);
        }

        return parent::setAttribute($key, $value);
    }
}
