<commit_before><?php

namespace app\models\db;

use app\components\MotionSorter;
use app\components\UrlHelper;
use app\models\amendmentNumbering\IAmendmentNumbering;
use app\models\exceptions\Internal;
use app\models\exceptions\NotFound;
use app\models\SearchResult;
use app\models\settings\AntragsgruenApp;
use yii\db\ActiveRecord;

/**
 * @package app\models\db
 *
 * @property int $id
 * @property int $siteId
 * @property int $amendmentNumbering
 *
 * @property string $urlPath
 * @property string $title
 * @property string $titleShort
 * @property string $wordingBase
 * @property string $eventDateFrom
 * @property string $eventDateTo
 * @property string $adminEmail
 * @property string $dateCreation
 * @property string $dateDeletion
 * @property string $settings
 *
 * @property Site $site
 * @property Motion[] $motions
 * @property ConsultationText[] $texts
 * @property ConsultationOdtTemplate[] $odtTemplates
 * @property ConsultationSettingsTag[] $tags
 * @property ConsultationMotionType[] $motionTypes
 * @property ConsultationAgendaItem[] $agendaItems
 * @property ConsultationUserPrivilege[] $userPrivileges
 * @property ConsultationFile[] $files
 * @property ConsultationLog[] $logEntries
 * @property UserNotification[] $userNotifications
 * @property VotingBlock[] $votingBlocks
 */
class Consultation extends ActiveRecord
{
    const TITLE_SHORT_MAX_LEN = 45;

    /** @var null|Consultation */
    private static $current = null;

    /**
     * @param Consultation $consultation
     * @throws Internal
     */
    public static function setCurrent(Consultation $consultation)
    {
        if (static::$current) {
            throw new Internal('Current consultation already set');
        }
        static::$current = $consultation;
    }

    /**
     * @return Consultation|null
     */
    public static function getCurrent()
    {
        return static::$current;
    }

    /**
     * @return string
     */
    public static function tableName()
    {
        /** @var \app\models\settings\AntragsgruenApp $app */
        $app = \Yii::$app->params;
        return $app->tablePrefix . 'consultation';
    }

    /**
     * @return array
     */
    public function rules()
    {
        return [
            [['title', 'dateCreation'], 'required'],
            [['title', 'titleShort', 'eventDateFrom', 'eventDateTo'], 'safe'],
            [['adminEmail', 'wordingBase', 'amendmentNumbering'], 'safe'],
            ['!urlPath', 'match', 'pattern' => '/^[\w_-]+$/i'],
        ];
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getSite()
    {
        return $this->hasOne(Site::class, ['id' => 'siteId']);
    }

    private $preloadedAllMotionData = false;
    private $preloadedAmendmentIds  = null;
    private $preloadedMotionIds     = null;

    /**
     * Loads Motions, amendments, initiators and tags
     */
    public function preloadAllMotionData()
    {
        $this->preloadedAllMotionData = true;
        foreach ($this->motions as $motion) {
            $this->preloadedMotionIds[] = $motion->id;
            foreach ($motion->amendments as $amendment) {
                $this->preloadedAmendmentIds[] = $amendment->id;
            }
        }
    }

    /**
     * @return bool
     */
    public function hasPreloadedMotionData()
    {
        return $this->preloadedAllMotionData;
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getMotions()
    {
        if ($this->preloadedAllMotionData) {
            return $this->hasMany(Motion::class, ['consultationId' => 'id'])
                ->with(
                    'amendments', 'motionSupporters', 'amendments.amendmentSupporters',
                    'tags', 'motionSupporters.user', 'amendments.amendmentSupporters.user'
                )
                ->andWhere(Motion::tableName() . '.status != ' . Motion::STATUS_DELETED);
        } else {
            return $this->hasMany(Motion::class, ['consultationId' => 'id'])
                ->andWhere(Motion::tableName() . '.status != ' . Motion::STATUS_DELETED);
        }
    }

    /**
     * @param string|null $motionSlug
     * @return Motion|null
     */
    public function getMotion($motionSlug)
    {
        if (is_null($motionSlug)) {
            return null;
        }
        foreach ($this->motions as $motion) {
            if (is_numeric($motionSlug) && $motion->id == $motionSlug && $motion->status != Motion::STATUS_DELETED) {
                return $motion;
            }
            if (!is_numeric($motionSlug) && $motion->slug == $motionSlug && $motion->status != Motion::STATUS_DELETED) {
                return $motion;
            }
        }
        return null;
    }

    /**
     * @return Motion|null
     */
    public function getForcedMotion()
    {
        if ($this->getSettings()->forceMotion === null) {
            return null;
        }
        return $this->getMotion($this->getSettings()->forceMotion);<commit_msg>Performance improvements by additional caching<commit_after><?php

namespace app\models\db;

use app\components\MotionSorter;
use app\components\UrlHelper;
use app\models\amendmentNumbering\IAmendmentNumbering;
use app\models\exceptions\Internal;
use app\models\exceptions\NotFound;
use app\models\SearchResult;
use app\models\settings\AntragsgruenApp;
use yii\db\ActiveRecord;

/**
 * @package app\models\db
 *
 * @property int $id
 * @property int $siteId
 * @property int $amendmentNumbering
 *
 * @property string $urlPath
 * @property string $title
 * @property string $titleShort
 * @property string $wordingBase
 * @property string $eventDateFrom
 * @property string $eventDateTo
 * @property string $adminEmail
 * @property string $dateCreation
 * @property string $dateDeletion
 * @property string $settings
 *
 * @property Site $site
 * @property Motion[] $motions
 * @property ConsultationText[] $texts
 * @property ConsultationOdtTemplate[] $odtTemplates
 * @property ConsultationSettingsTag[] $tags
 * @property ConsultationMotionType[] $motionTypes
 * @property ConsultationAgendaItem[] $agendaItems
 * @property ConsultationUserPrivilege[] $userPrivileges
 * @property ConsultationFile[] $files
 * @property ConsultationLog[] $logEntries
 * @property UserNotification[] $userNotifications
 * @property VotingBlock[] $votingBlocks
 */
class Consultation extends ActiveRecord
{
    const TITLE_SHORT_MAX_LEN = 45;

    /** @var null|Consultation */
    private static $current = null;

    /**
     * @param Consultation $consultation
     * @throws Internal
     */
    public static function setCurrent(Consultation $consultation)
    {
        if (static::$current) {
            throw new Internal('Current consultation already set');
        }
        static::$current = $consultation;
    }

    /**
     * @return Consultation|null
     */
    public static function getCurrent()
    {
        return static::$current;
    }

    /**
     * @return string
     */
    public static function tableName()
    {
        /** @var \app\models\settings\AntragsgruenApp $app */
        $app = \Yii::$app->params;
        return $app->tablePrefix . 'consultation';
    }

    /**
     * @return array
     */
    public function rules()
    {
        return [
            [['title', 'dateCreation'], 'required'],
            [['title', 'titleShort', 'eventDateFrom', 'eventDateTo'], 'safe'],
            [['adminEmail', 'wordingBase', 'amendmentNumbering'], 'safe'],
            ['!urlPath', 'match', 'pattern' => '/^[\w_-]+$/i'],
        ];
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getSite()
    {
        return $this->hasOne(Site::class, ['id' => 'siteId']);
    }

    private $preloadedAllMotionData = false;
    private $preloadedAmendmentIds  = null;
    private $preloadedMotionIds     = null;

    /**
     * Loads Motions, amendments, initiators and tags
     */
    public function preloadAllMotionData()
    {
        $this->preloadedAllMotionData = true;
        foreach ($this->motions as $motion) {
            $this->preloadedMotionIds[] = $motion->id;
            foreach ($motion->amendments as $amendment) {
                $this->preloadedAmendmentIds[] = $amendment->id;
            }
        }
    }

    /**
     * @return bool
     */
    public function hasPreloadedMotionData()
    {
        return $this->preloadedAllMotionData;
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getMotions()
    {
        if ($this->preloadedAllMotionData) {
            return $this->hasMany(Motion::class, ['consultationId' => 'id'])
                ->with(
                    'amendments', 'motionSupporters', 'amendments.amendmentSupporters',
                    'tags', 'motionSupporters.user', 'amendments.amendmentSupporters.user'
                )
                ->andWhere(Motion::tableName() . '.status != ' . Motion::STATUS_DELETED);
        } else {
            return $this->hasMany(Motion::class, ['consultationId' => 'id'])
                ->andWhere(Motion::tableName() . '.status != ' . Motion::STATUS_DELETED);
        }
    }

    /** @var Motion[] */
    private $motionCache = [];

    /**
     * @param string|null $motionSlug
     * @return Motion|null
     */
    public function getMotion($motionSlug)
    {
        if (is_null($motionSlug)) {
            return null;
        }
        if (isset($this->motionCache[$motionSlug])) {
            return $this->motionCache[$motionSlug];
        }
        foreach ($this->motions as $motion) {
            $this->motionCache[$motion->id] = $motion;
            if ($motion->slug) {
                $this->motionCache[$motion->slug] = $motion;
            }
            if (is_numeric($motionSlug) && $motion->id == $motionSlug && $motion->status != Motion::STATUS_DELETED) {
                return $motion;
            }
            if (!is_numeric($motionSlug) && $motion->slug == $motionSlug && $motion->status != Motion::STATUS_DELETED) {
                return $motion;
            }
        }
        $this->motionCache[$motionSlug] = null;
        return null;
    }

    /**
     * @return Motion|null
     */
    public function getForcedMotion()
    {
        if ($this->getSettings()->forceMotion === null) {
            return null;
        }
        return $this->getMotion($this->getSettings()->forceMotion);
{'fraction_non_alphanumeric': 0.13846748478113827, 'fraction_numerical': 0.0003865107739878249, 'mean_word_length': 2.4650150652828926, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 73, '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': '2820662', 'n_tokens_mistral': 3111, 'n_tokens_neox': 2971, 'n_words': 611}