View file src/addons/ThemeHouse/Reactions/Entity/Reaction.php

File size: 10.12Kb
<?php

namespace ThemeHouse\Reactions\Entity;

use ThemeHouse\Reactions\React\AbstractHandler;
use XF\Mvc\Entity\Entity;
use XF\Mvc\Entity\Structure;

/**
 * Class Reaction
 * @package ThemeHouse\Reactions\Entity
 *
 *
 * @property integer reaction_id
 * @property string title
 * @property string reaction_type_id
 * @property string styling_type
 * @property string reaction_text
 * @property string image_url
 * @property string image_url_2x
 * @property string image_type
 * @property string|array styling
 * @property AbstractHandler|array|string react_handler
 * @property string|array user_criteria
 * @property string|array $options
 * @property integer display_order
 * @property boolean like_wrapper
 * @property boolean random
 * @property boolean enabled
 * @property boolean is_default
 */
class Reaction extends Entity
{
    /**
     * @return array|mixed|null
     * @throws \Exception
     */
    public function getReactHandler()
    {
        if (isset($this->react_handler)) {
            if (in_array('all', $this->react_handler_)) {
                return array_keys($this->getReactHandlerRepo()->getReactHandlersList());
            }

            return $this->react_handler_;
        }
    }

    /**
     * @param $options
     * @param $key
     * @return bool
     * @throws \Exception
     */
    protected function verifyOptions(&$options, $key)
    {
        foreach ($this->getReactHandler() as $reactHandler) {
            $reactHandler = $this->getReactHandlerRepo()->getReactHandlerByType($reactHandler);
            if ($reactHandler) {
                $reactHandler->verifyOptions($this, $options, $error);
                if ($error) {
                    $this->error($error, $key);
                    return false;
                }
            }
        }

        return true;
    }

    /**
     * @param $reactionParams
     * @return bool
     */
    protected function verifyReactionParams(&$reactionParams)
    {
        array_walk($reactionParams, function ($value, $key) {
            if ($key != 'bs') {
                $value = intval($value);
            }

            return $value;
        });

        return true;
    }

    /**
     * @param $criteria
     * @return bool
     */
    protected function verifyUserCriteria(&$criteria)
    {
        $userCriteria = $this->app()->criteria('XF:User', $criteria);
        $criteria = $userCriteria->getCriteria();
        return true;
    }

    /**
     * @param $value
     * @param $key
     * @return bool
     */
    protected function verifyLikeWrapper($value, $key)
    {
        if ($value && \XF::finder('ThemeHouse\Reactions:Reaction')->where([
                'like_wrapper' => 1,
                ['reaction_id', '!=', $this->reaction_id]
            ])->fetch()->count()) {
            $this->error(\XF::phrase('th_only_one_reaction_can_like_wrapper_reactions'), $key);
            return false;
        }

        return true;
    }

    /**
     * @param $value
     * @param $key
     * @return bool
     */
    protected function verifyIsDefault($value, $key)
    {
        if ($value && \XF::Finder('ThemeHouse\Reactions:Reaction')->where([
                'is_default' => 1,
                ['reaction_id', '!=', $this->reaction_id]
            ])->fetch()->count()) {
            $this->error(\XF::phrase('threact_only_one_reaction_can_be_selected_as_the_default'), $key);
            return false;
        }

        return true;
    }

    /**
     * @param $value
     * @param $key
     * @return bool
     */
    protected function verifyRandom($value, $key)
    {
        if ($value && \XF::finder('ThemeHouse\Reactions:Reaction')->limit(5)->fetch()->count() < 3) {
            $this->error(\XF::phrase('th_at_least_x_reactions_needed_for_random_reactions', ['amount' => 3]), $key);
            return false;
        }

        return true;
    }

    protected function _preSave()
    {
        if (!$this->random && empty($this->reaction_type_id)) {
            $this->error(\XF::phrase('th_please_choose_valid_reaction_type_reactions'), 'reaction_type_id');
            return false;
        }

        if ($this->image_type == 'sprite') {
            $this->image_url_2x = '';
        }

        if ($this->styling_type == 'image') {
            if (empty($this->image_url)) {
                $this->error(\XF::phrase('please_enter_valid_url'), 'image_url');
                return false;
            }
        }

        if ($this->styling_type == 'text') {
            if (empty($this->reaction_text)) {
                $this->error(\XF::phrase('th_please_enter_text_for_reaction_reactions'), 'reaction_text');
                return false;
            }
        }

        if ($this->styling_type == 'css_class') {
            if (empty($this->reaction_text)) {
                $this->error(\XF::phrase('th_please_enter_css_class_for_reaction_reactions'), 'reaction_text');
                return false;
            }
        }

        return parent::_preSave();
    }

    protected function _postSave()
    {
        $this->rebuildReactionCache();

        return parent::_postSave();
    }

    protected function _postDelete()
    {
        $this->rebuildReactionCache();

        $this->db()->delete(
            'xf_th_reacted_content',
            'reaction_id = ?',
            [$this->reaction_id]
        );

        $this->db()->delete(
            'xf_th_reaction_user_count',
            'reaction_id = ?',
            [$this->reaction_id]
        );

        $this->db()->delete(
            'xf_th_reaction_content_count',
            'reaction_id = ?',
            [$this->reaction_id]
        );
    }

    protected function rebuildReactionCache()
    {
        $repo = $this->getThReactionRepo();

        \XF::runOnce('reactionCache', function () use ($repo) {
            $repo->rebuildReactionCache();
        });
    }

    protected function _setupDefaults()
    {
        $this->like_wrapper = false;

        $this->styling = [
            'text' => ['s' => '22px'],
            'image_normal' => ['w' => 22, 'h' => 22, 'u' => 'px'],
            'image_sprite' => ['w' => 22, 'h' => 22, 'x' => 0, 'y' => 0, 'bs' => '', 'u' => 'px'],
            'css_class' => 'fa fa-fw fa-thumbs-up',
            'html_css' => [
                'css' => '',
                'html' => ''
            ]
        ];

        $this->options = [
            'alerts' => true,
            'newsfeed' => true,
            'prevent_unreact' => false,
            'user_max_per_day' => 0
        ];
    }

    /**
     * @param Structure $structure
     * @return Structure
     */
    public static function getStructure(Structure $structure)
    {
        $structure->table = 'xf_th_reaction';
        $structure->shortName = 'ThemeHouse\Reactions:Reaction';
        $structure->primaryKey = 'reaction_id';
        $structure->columns = [
            'reaction_id' => ['type' => self::UINT, 'autoIncrement' => true],
            'title' => [
                'type' => self::STR,
                'maxLength' => 50,
                'required' => 'please_enter_valid_title'
            ],
            'reaction_type_id' => ['type' => self::STR, 'maxLength' => 25, 'match' => 'alphanumeric'],
            'styling_type' => [
                'type' => self::STR,
                'default' => 'image',
                'allowedValues' => [
                    'image',
                    'text',
                    'css_class',
                    'html_css'
                ]
            ],
            'reaction_text' => ['type' => self::STR, 'maxLength' => 10, 'default' => ''],
            'image_url' => ['type' => self::STR, 'maxLength' => 200],
            'image_url_2x' => ['type' => self::STR, 'maxLength' => 200, 'default' => ''],
            'image_type' => ['type' => self::STR, 'maxLength' => 25, 'default' => 'normal'],
            'styling' => ['type' => self::SERIALIZED_ARRAY, 'default' => []],
            'user_criteria' => [
                'type' => self::SERIALIZED_ARRAY,
                'default' => [],
                'verify' => 'verifyUserCriteria'
            ],
            'react_handler' => [
                'type' => self::LIST_COMMA,
                'default' => ['all'],
                'list' => ['type' => 'str', 'unique' => true, 'sort' => SORT_STRING],
            ],
            'options' => [
                'type' => self::SERIALIZED_ARRAY,
                'default' => [],
                'verify' => 'verifyOptions',
            ],
            'display_order' => ['type' => self::UINT, 'default' => 10],
            'like_wrapper' => [
                'type' => self::BOOL,
                'default' => false,
                'verify' => 'verifyLikeWrapper',
            ],
            'random' => [
                'type' => self::BOOL,
                'default' => false,
                'verify' => 'verifyRandom',
            ],
            'enabled' => ['type' => self::BOOL, 'default' => true],
            'is_default' => [
                'type' => self::BOOL,
                'default' => false,
                'verify' => 'verifyIsDefault',
            ],
        ];
        $structure->getters = [
            'react_handler' => true
        ];
        $structure->relations = [
            'ReactionType' => [
                'entity' => 'ThemeHouse\Reactions:ReactionType',
                'type' => self::TO_ONE,
                'conditions' => 'reaction_type_id',
                'primary' => true
            ],
        ];

        return $structure;
    }

    /**
     * @return \ThemeHouse\Reactions\Repository\Reaction
     */
    protected function getThReactionRepo()
    {
        /** @noinspection PhpIncompatibleReturnTypeInspection */
        return $this->repository('ThemeHouse\Reactions:Reaction');
    }

    /**
     * @return \ThemeHouse\Reactions\Repository\ReactionType
     */
    protected function getReactionTypeRepo()
    {
        /** @noinspection PhpIncompatibleReturnTypeInspection */
        return $this->repository('ThemeHouse\Reactions:ReactionType');
    }

    /**
     * @return \ThemeHouse\Reactions\Repository\ReactHandler
     */
    protected function getReactHandlerRepo()
    {
        /** @noinspection PhpIncompatibleReturnTypeInspection */
        return $this->repository('ThemeHouse\Reactions:ReactHandler');
    }
}