Skip to content
Extraits de code Groupes Projets
API.php 12,8 ko
Newer Older
  • Learn to ignore specific revisions
  • mattab's avatar
    mattab a validé
    <?php
    /**
    
     * Piwik - free/libre analytics platform
    
    mattab's avatar
    mattab a validé
     *
     * @link http://piwik.org
     * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
     *
     */
    
    namespace Piwik\Plugins\SegmentEditor;
    
    use Exception;
    
    mattab's avatar
    mattab a validé
    use Piwik\Common;
    
    mattab's avatar
    mattab a validé
    
    /**
    
     * The SegmentEditor API lets you add, update, delete custom Segments, and list saved segments.a
    
    mattab's avatar
    mattab a validé
     *
    
     * @method static \Piwik\Plugins\SegmentEditor\API getInstance()
    
    mattab's avatar
    mattab a validé
     */
    
    mattab's avatar
    mattab a validé
    {
    
        public function __construct(Model $model)
    
    mattab's avatar
    mattab a validé
        protected function checkSegmentValue($definition, $idSite)
        {
    
    mattab's avatar
    mattab a validé
            // unsanitize so we don't record the HTML entitied segment
    
            $definition = Common::unsanitizeInputValue($definition);
    
    mattab's avatar
    mattab a validé
            $definition = str_replace("#", '%23', $definition); // hash delimiter
            $definition = str_replace("'", '%27', $definition); // not encoded in JS
            $definition = str_replace("&", '%26', $definition);
    
    
    mattab's avatar
    mattab a validé
            try {
    
                $segment = new Segment($definition, $idSite);
    
    mattab's avatar
    mattab a validé
                $segment->getHash();
            } catch (Exception $e) {
                throw new Exception("The specified segment is invalid: " . $e->getMessage());
            }
    
    mattab's avatar
    mattab a validé
            return $definition;
    
    mattab's avatar
    mattab a validé
        }
    
        protected function checkSegmentName($name)
        {
            if (empty($name)) {
                throw new Exception("Invalid name for this custom segment.");
            }
        }
    
        protected function checkEnabledAllUsers($enabledAllUsers)
        {
            $enabledAllUsers = (int)$enabledAllUsers;
            if ($enabledAllUsers
    
    mattab's avatar
    mattab a validé
            ) {
    
                throw new Exception("enabledAllUsers=1 requires Super User access");
    
    mattab's avatar
    mattab a validé
            }
            return $enabledAllUsers;
        }
    
        protected function checkIdSite($idSite)
        {
            if (empty($idSite)) {
    
                if (!Piwik::hasUserSuperUserAccess()) {
    
                    throw new Exception($this->getMessageCannotEditSegmentCreatedBySuperUser());
    
    mattab's avatar
    mattab a validé
                }
            } else {
                if (!is_numeric($idSite)) {
                    throw new Exception("idSite should be a numeric value");
                }
                Piwik::checkUserHasViewAccess($idSite);
            }
    
    mattab's avatar
    mattab a validé
            $idSite = (int)$idSite;
            return $idSite;
    
    mattab's avatar
    mattab a validé
        }
    
        protected function checkAutoArchive($autoArchive, $idSite)
        {
            $autoArchive = (int)$autoArchive;
    
            if (!$autoArchive) {
                return $autoArchive;
            }
    
            $exception = new Exception(
                "Please contact Support to make these changes on your behalf. ".
                " To modify a pre-processed segment, a user must have admin access or super user access. "
            );
    
            // Segment 'All websites' and pre-processed requires Super User
            if (empty($idSite)) {
                if (!Piwik::hasUserSuperUserAccess()) {
                    throw $exception;
                }
                return $autoArchive;
            }
    
            // if real-time segments are disabled, then allow user to create pre-processed report
            $realTimeSegmentsDisabled = !Config::getInstance()->General['enable_create_realtime_segments'];
            if($realTimeSegmentsDisabled) {
                // User is at least view
                if(!Piwik::isUserHasViewAccess($idSite)) {
                    throw $exception;
    
    mattab's avatar
    mattab a validé
                }
    
    mattab's avatar
    mattab a validé
            }
    
    
            // pre-processed segment for a given website requires admin access
            if(!Piwik::isUserHasAdminAccess($idSite)) {
                throw $exception;
            }
    
    
    mattab's avatar
    mattab a validé
            return $autoArchive;
        }
    
    
        protected function getSegmentOrFail($idSegment)
        {
            $segment = $this->get($idSegment);
    
            if (empty($segment)) {
                throw new Exception("Requested segment not found");
            }
    
    mattab's avatar
    mattab a validé
        protected function checkUserIsNotAnonymous()
        {
    
    mattab's avatar
    mattab a validé
                throw new Exception("To create, edit or delete Custom Segments, please sign in first.");
            }
        }
    
    
        protected function checkUserCanAddNewSegment($idSite)
    
            if (empty($idSite)
                && !SegmentEditor::isAddingSegmentsForAllWebsitesEnabled()
            ) {
                throw new Exception(Piwik::translate('SegmentEditor_AddingSegmentForAllWebsitesDisabled'));
            }
    
            if (!$this->isUserCanAddNewSegment($idSite)) {
    
    d-skora's avatar
    d-skora a validé
                throw new Exception(Piwik::translate('SegmentEditor_YouDontHaveAccessToCreateSegments'));
    
        public function isUserCanAddNewSegment($idSite)
    
            $requiredAccess = Config::getInstance()->General['adding_segment_requires_access'];
    
            $authorized =
                ($requiredAccess == 'view' && Piwik::isUserHasViewAccess($idSite)) ||
                ($requiredAccess == 'admin' && Piwik::isUserHasAdminAccess($idSite)) ||
                ($requiredAccess == 'superuser' && Piwik::hasUserSuperUserAccess())
            ;
    
        protected function checkUserCanEditOrDeleteSegment($segment)
    
            if (Piwik::hasUserSuperUserAccess()) {
    
            $this->checkUserIsNotAnonymous();
    
    
            if ($segment['login'] != Piwik::getCurrentUserLogin()) {
    
                throw new Exception($this->getMessageCannotEditSegmentCreatedBySuperUser());
            }
        }
    
    
        /**
         * Deletes a stored segment.
         *
         * @param $idSegment
    
    sgiehl's avatar
    sgiehl a validé
         * @return bool
    
    mattab's avatar
    mattab a validé
        public function delete($idSegment)
        {
    
            $segment = $this->getSegmentOrFail($idSegment);
    
            $this->checkUserCanEditOrDeleteSegment($segment);
    
    Julien Moumné's avatar
    Julien Moumné a validé
    
    
            /**
             * Triggered before a segment is deleted or made invisible.
             *
             * This event can be used by plugins to throw an exception
             * or do something else.
             *
             * @param int $idSegment The ID of the segment being deleted.
             */
            Piwik::postEvent('SegmentEditor.deactivate', array($idSegment));
    
            $this->getModel()->deleteSegment($idSegment);
    
    
    mattab's avatar
    mattab a validé
            return true;
        }
    
    
        /**
         * Modifies an existing stored segment.
         *
    
         * @param int $idSegment The ID of the stored segment to modify.
    
         * @param string $name The new name of the segment.
         * @param string $definition The new definition of the segment.
         * @param bool $idSite If supplied, associates the stored segment with as single site.
    
         * @param bool $autoArchive Whether to automatically archive data with the segment or not.
         * @param bool $enabledAllUsers Whether the stored segment is viewable by all users or just the one that created it.
         *
    
    sgiehl's avatar
    sgiehl a validé
         * @return bool
    
    mattab's avatar
    mattab a validé
        public function update($idSegment, $name, $definition, $idSite = false, $autoArchive = false, $enabledAllUsers = false)
        {
    
            $segment = $this->getSegmentOrFail($idSegment);
    
            $this->checkUserCanEditOrDeleteSegment($segment);
    
    mattab's avatar
    mattab a validé
            $idSite = $this->checkIdSite($idSite);
    
    mattab's avatar
    mattab a validé
            $this->checkSegmentName($name);
    
            $definition      = $this->checkSegmentValue($definition, $idSite);
    
    mattab's avatar
    mattab a validé
            $enabledAllUsers = $this->checkEnabledAllUsers($enabledAllUsers);
    
            $autoArchive     = $this->checkAutoArchive($autoArchive, $idSite);
    
    mattab's avatar
    mattab a validé
    
            $bind = array(
                'name'               => $name,
                'definition'         => $definition,
                'enable_all_users'   => $enabledAllUsers,
                'enable_only_idsite' => $idSite,
                'auto_archive'       => $autoArchive,
    
                'ts_last_edit'       => Date::now()->getDatetime(),
    
    mattab's avatar
    mattab a validé
            );
    
    
            /**
             * Triggered before a segment is modified.
             *
             * This event can be used by plugins to throw an exception
             * or do something else.
             *
             * @param int $idSegment The ID of the segment which visibility is reduced.
             */
            Piwik::postEvent('SegmentEditor.update', array($idSegment, $bind));
    
    
            $this->getModel()->updateSegment($idSegment, $bind);
    
    
    mattab's avatar
    mattab a validé
            return true;
        }
    
    
        /**
         * Adds a new stored segment.
         *
    
         * @param string $name The new name of the segment.
         * @param string $definition The new definition of the segment.
         * @param bool $idSite If supplied, associates the stored segment with as single site.
    
         * @param bool $autoArchive Whether to automatically archive data with the segment or not.
         * @param bool $enabledAllUsers Whether the stored segment is viewable by all users or just the one that created it.
         *
         * @return int The newly created segment Id
         */
    
    mattab's avatar
    mattab a validé
        public function add($name, $definition, $idSite = false, $autoArchive = false, $enabledAllUsers = false)
        {
    
            $this->checkUserCanAddNewSegment($idSite);
    
    mattab's avatar
    mattab a validé
            $idSite = $this->checkIdSite($idSite);
    
    mattab's avatar
    mattab a validé
            $this->checkSegmentName($name);
    
    mattab's avatar
    mattab a validé
            $definition = $this->checkSegmentValue($definition, $idSite);
    
    mattab's avatar
    mattab a validé
            $enabledAllUsers = $this->checkEnabledAllUsers($enabledAllUsers);
            $autoArchive = $this->checkAutoArchive($autoArchive, $idSite);
    
            $bind = array(
                'name'               => $name,
                'definition'         => $definition,
                'login'              => Piwik::getCurrentUserLogin(),
                'enable_all_users'   => $enabledAllUsers,
                'enable_only_idsite' => $idSite,
                'auto_archive'       => $autoArchive,
    
                'ts_created'         => Date::now()->getDatetime(),
    
    mattab's avatar
    mattab a validé
                'deleted'            => 0,
            );
    
    
            $id = $this->getModel()->createSegment($bind);
    
            return $id;
    
    mattab's avatar
    mattab a validé
        }
    
    
        /**
         * Returns a stored segment by ID
         *
         * @param $idSegment
    
    sgiehl's avatar
    sgiehl a validé
         * @throws Exception
         * @return bool
    
    mattab's avatar
    mattab a validé
        public function get($idSegment)
        {
            Piwik::checkUserHasSomeViewAccess();
    
    mattab's avatar
    mattab a validé
            if (!is_numeric($idSegment)) {
                throw new Exception("idSegment should be numeric.");
            }
    
    
            $segment = $this->getModel()->getSegment($idSegment);
    
    mattab's avatar
    mattab a validé
    
            if (empty($segment)) {
                return false;
            }
            try {
    
    Julien Moumné's avatar
    Julien Moumné a validé
    
    
                if (!$segment['enable_all_users']) {
    
                    Piwik::checkUserHasSuperUserAccessOrIsTheUser($segment['login']);
    
    Julien Moumné's avatar
    Julien Moumné a validé
                }
    
    
    mattab's avatar
    mattab a validé
            } catch (Exception $e) {
    
                throw new Exception($this->getMessageCannotEditSegmentCreatedBySuperUser());
    
    mattab's avatar
    mattab a validé
            }
    
            if ($segment['deleted']) {
    
                throw new Exception("This segment is marked as deleted. ");
    
    mattab's avatar
    mattab a validé
            }
    
    mattab's avatar
    mattab a validé
            return $segment;
        }
    
    
        /**
         * Returns all stored segments.
         *
    
         * @param bool|int $idSite Whether to return stored segments for a specific idSite, or all of them. If supplied, must be a valid site ID.
    
    mattab's avatar
    mattab a validé
        {
    
    mattab's avatar
    mattab a validé
                Piwik::checkUserHasViewAccess($idSite);
            } else {
                Piwik::checkUserHasSomeViewAccess();
            }
    
            $userLogin = Piwik::getCurrentUserLogin();
    
    mattab's avatar
    mattab a validé
    
    
            if(Piwik::hasUserSuperUserAccess()) {
                $segments = $model->getAllSegmentsForAllUsers($idSite);
    
                if (empty($idSite)) {
                    $segments = $model->getAllSegments($userLogin);
                } else {
                    $segments = $model->getAllSegmentsForSite($idSite, $userLogin);
                }
    
    mattab's avatar
    mattab a validé
            }
    
    mattab's avatar
    mattab a validé
    
    
            $segments = $this->sortSegmentsCreatedByUserFirst($segments);
    
    
    mattab's avatar
    mattab a validé
            return $segments;
        }
    
    Julien Moumné's avatar
    Julien Moumné a validé
    
    
        /**
         * Sorts segment in a particular order:
         *
         *  1) my segments
         *  2) segments created by the super user that were shared with all users
         *  3) segments created by other users (which are visible to all super users)
         *
         * @param $segments
         * @return array
         */
        private function sortSegmentsCreatedByUserFirst($segments)
        {
            $orderedSegments = array();
            foreach($segments as $id => &$segment) {
                if($segment['login'] == Piwik::getCurrentUserLogin()) {
                    $orderedSegments[] = $segment;
                    unset($segments[$id]);
                }
            }
            foreach($segments as $id => &$segment) {
                if($segment['enable_all_users'] == 1) {
                    $orderedSegments[] = $segment;
                    unset($segments[$id]);
                }
            }
            foreach($segments as $id => &$segment) {
                $orderedSegments[] = $segment;
            }
            return $orderedSegments;
        }
    
    
        /**
         * @return string
         */
        private function getMessageCannotEditSegmentCreatedBySuperUser()
        {
    
            $message = "You can only edit and delete custom segments that you have created yourself. This segment was created and 'shared with you' by the Super User. " .
                "To modify this segment, you can first create a new one by clicking on 'Add new segment'. Then you can customize the segment's definition.";
    
            return $message;
    
    mattab's avatar
    mattab a validé
    }